AreaOfInterest extends GraphicalContext<BorderPane> { static Double[] calculateConvexHull(final Point2D[] points) { final int numberOfPoints = points.length; final ArrayList<Double> convexHullPoints = new ArrayList<>(); final Vector<Point2D> hull = new Vector<>(); int lowestValueIndex = 0; for (int i = 1; i < numberOfPoints; i++) { if (points[i].getX() < points[lowestValueIndex].getX()) { lowestValueIndex = i; } } int point = lowestValueIndex, q; do { hull.add(points[point]); q = (point + 1) % numberOfPoints; for (int i = 0; i < numberOfPoints; i++) { if (orientation(points[point], points[i], points[q]) < 0) { q = i; } } point = q; } while (point != lowestValueIndex); for (final Point2D temp : hull) { convexHullPoints.add(temp.getX()); convexHullPoints.add(temp.getY()); } Double[] hullPointsArray = new Double[convexHullPoints.size()]; convexHullPoints.toArray(hullPointsArray); return hullPointsArray; } AreaOfInterest(final GazePlay gazePlay, final Stats stats); @Override ObservableList<Node> getChildren();  }
@Test void shouldCalculateConvexHull() { Point2D[] input = new Point2D[]{ new Point2D(2, 2), new Point2D(2, 3), new Point2D(3, 5), new Point2D(1, 2), new Point2D(1.25, 3), new Point2D(2, 1), new Point2D(4, 2) }; Double[] expected = new Double[]{ 1d, 2d, 2d, 1d, 4d, 2d, 3d, 5d, 1.25, 3d }; Double[] actual = AreaOfInterest.calculateConvexHull(input); assertArrayEquals(expected, actual); }