EllipsoidOptimisationStrategy extends AbstractBinaryFunctionOp<byte[][], Vector3d, QuickEllipsoid> { void bump(final QuickEllipsoid ellipsoid, final Collection<double[]> contactPoints, final double[] seedPoint) { final double displacement = algorithmParameters.vectorIncrement / 2; final double[] c = ellipsoid.getCentre(); final double[] vector = contactPointUnitVector(ellipsoid, contactPoints); final double x = c[0] + vector[0] * displacement; final double y = c[1] + vector[1] * displacement; final double z = c[2] + vector[2] * displacement; Vector3d distance = new Vector3d(seedPoint[0], seedPoint[1], seedPoint[2]); distance.sub(new Vector3d(x, y, z)); if (distance.length() < algorithmParameters.maxDrift) ellipsoid.setCentroid(x, y, z); }  @Override QuickEllipsoid calculate(byte[][] pixels, Vector3d seedPoint);  }
@Test public void testBumpSurfacePoint() { double[] radii = {1,2,3}; double[] centre = {0,0,0}; QuickEllipsoid e = new QuickEllipsoid(radii, centre, new double[][]{{1,0,0},{0,1,0},{0,0,1}}); final EllipsoidOptimisationStrategy optimisation = (EllipsoidOptimisationStrategy) Functions.binary(ops, EllipsoidOptimisationStrategy.class, QuickEllipsoid.class, new byte[10][10], new Vector3d(),new long[]{10,10,1}, new AnchorEllipsoidConstrain()); final ArrayList<double[]> contactPoints = new ArrayList<>(); contactPoints.add(new double[]{0,0,3}); final AnchorEllipsoidConstrain anchorConstrain = new AnchorEllipsoidConstrain(); anchorConstrain.preConstrain(e, new Vector3d(1,0,0)); optimisation.bump(e, contactPoints, new double[]{e.getCentre()[0], e.getCentre()[1], e.getCentre()[2]}); anchorConstrain.postConstrain(e); assertTrue("Bump does not preserve surface point.",onSurface(e, new double[]{1,0,0})); }