### Question:
Circle extends ACircle { public static Optional<ICircle> hullCircle(final List<IVector2> points) { return Streams .concat(StreamUtil.nonRepeatingPermutation2Fold(points), StreamUtil.nonRepeatingPermutation3Fold(points)) .map(Circle::fromNPoints) .filter(Optional::isPresent) .map(Optional::get) .filter(c -> points.stream().allMatch(p -> c.isPointInShape(p, 1e-10))) .min(Comparator.comparing(ICircle::radius)); } protected  Circle(); protected  Circle(final ICircle circle); protected  Circle(final IVector2 center, final double radius); static ICircle from2Points(final IVector2 p1, final IVector2 p2); static Optional<ICircle> from3Points(final IVector2 p1, final IVector2 p2, final IVector2 p3); static Optional<ICircle> fromNPoints(final List<IVector2> points); static Optional<ICircle> hullCircle(final List<IVector2> points); static ICircle createCircle(final IVector2 center, final double radius); @Override ICircle withMargin(final double margin); @Override ICircle mirror(); @Override double radius(); @Override IVector2 center(); @Override final boolean equals(final Object o); @Override final int hashCode(); @Override String toString();  }### Answer:
@Test public void testHullCircle() { List<IVector2> points = new ArrayList<>(); points.add(Vector2.fromXY(1, 0)); points.add(Vector2.fromXY(-1, 0)); points.add(Vector2.fromXY(0, 0.5)); points.add(Vector2.fromXY(0, -0.5)); ICircle circle = Circle.hullCircle(points).orElseThrow(AssertionError::new); Assert.assertEquals(1.0, circle.radius(), Double.MIN_VALUE); Assert.assertEquals(0.0, circle.center().x(), Double.MIN_VALUE); Assert.assertEquals(0.0, circle.center().y(), Double.MIN_VALUE); }
@Test public void testHullCircleRandomPoints() { Random rnd = new Random(42); long iterations = 1000; for (int i = 0; i < iterations; i++) { int n = 2 + rnd.nextInt(10); List<IVector2> points = new ArrayList<>(); for (int j = 0; j < n; j++) { points.add(Vector2.fromXY((rnd.nextDouble() * 2000) - 1000, (rnd.nextDouble() + 2000) - 1000)); } Optional<ICircle> hullCircleOpt = Circle.hullCircle(points); ICircle hullCircle = hullCircleOpt.orElseThrow(AssertionError::new); assertThat(points).allMatch(p -> hullCircle.isPointInShape(p, 1e-10)); } }