DistanceFromEllipsoidSurfaceOp extends
	AbstractBinaryFunctionOp<Ellipsoid, Vector3dc, DoubleType> { @Override public DoubleType calculate(final Ellipsoid ellipsoid, final Vector3dc point) throws IllegalArgumentException { if (tolerance < 0.0) { throw new IllegalArgumentException("Tolerance cannot be negative"); } if (maxIterations < 1) { throw new IllegalArgumentException("Max iterations must be positive"); } final double a = ellipsoid.getA(); final double b = ellipsoid.getB(); final double c = ellipsoid.getC(); final Vector3dc pointInEllipsoidCoordinates = toEllipsoidCoordinates(point, ellipsoid); final double rootTerm = Math.sqrt(pointInEllipsoidCoordinates.x() * pointInEllipsoidCoordinates.x() / (a * a) + pointInEllipsoidCoordinates.y() * pointInEllipsoidCoordinates.y() / (b * b)); Vector2dc anglesK = new Vector2d(Math.atan2(a * pointInEllipsoidCoordinates.y(), b * pointInEllipsoidCoordinates.x()), Math .atan2(pointInEllipsoidCoordinates.z(), c * rootTerm)); Vector2d anglesKPlus1 = new Vector2d(0.0, 0.0); long iterations = 0; while (iterations < maxIterations) { anglesKPlus1 = new Vector2d(anglesK.x(), anglesK.y()); anglesKPlus1.add(inverseJacobian(anglesK, ellipsoid, pointInEllipsoidCoordinates)); if (getDifference(anglesK, anglesKPlus1) <= tolerance) { break; } anglesK = new Vector2d(anglesKPlus1.x, anglesKPlus1.y); iterations++; } final Vector3d closestPointOnEllipsoidSurface = getCartesianCoordinatesFromAngleParametrization(anglesKPlus1, ellipsoid); final Vector3d v = new Vector3d(closestPointOnEllipsoidSurface); v.negate(); v.add(pointInEllipsoidCoordinates); return new DoubleType(v.length()); }  @Override DoubleType calculate(final Ellipsoid ellipsoid, final Vector3dc point);  }
@Test(expected = ArithmeticException.class) public void testArithmeticExceptionForZeroDeterminant() { final Ellipsoid ellipsoid = new Ellipsoid(2.0, 2.0, 2.0); final Vector3dc origin = new Vector3d(); distanceFromEllipsoidSurfaceOp.calculate(ellipsoid, origin).get(); }
@Test public void testInsidePointForArbitraryEllipsoid() { final Vector3dc insidePoint = new Vector3d(1.0, 1.0 + Math.sqrt(3.0) / 2.0, 1 - 0.5); final double distanceToInsidePoint = distanceFromEllipsoidSurfaceOp .calculate(transformedEllipsoid, insidePoint).get(); assertEquals("Distance to inside point failed", 1.0, distanceToInsidePoint, 1.0e-12); }
@Test public void testInsidePointForAxisAlignedEllipsoid() { final Vector3dc insidePoint = new Vector3d(0.0, 1.0, 0.0); final double distanceToInsidePoint = distanceFromEllipsoidSurfaceOp .calculate(axisAlignedEllipsoid, insidePoint).get(); assertEquals("Distance to inside point failed", 1.0, distanceToInsidePoint, 1.0e-12); }
@Test public void testInsidePointForSphere() { final Vector3d sphereVector = new Vector3d(spherePointSupplier.get()); final Vector3dc insidePoint = new Vector3d(sphereVector); final double distanceToInsidePoint = distanceFromEllipsoidSurfaceOp .calculate(sphere, insidePoint).get(); assertEquals("Distance to inside point failed", 1.0, distanceToInsidePoint, 1.0e-12); }
@Test public void testOutsidePointForArbitraryEllipsoid() { final Vector3dc outsidePoint = new Vector3d(1.0 + 2.0, 1.0, 1.0); final double distanceToOutsidePoint = distanceFromEllipsoidSurfaceOp .calculate(transformedEllipsoid, outsidePoint).get(); assertEquals("Distance to outside point failed", 1.0, distanceToOutsidePoint, 1.0e-12); }
@Test public void testOutsidePointForAxisAlignedEllipsoid() { final Vector3dc outsidePoint = new Vector3d(2.0, 0.0, 0.0); final double distanceToOutsidePoint = distanceFromEllipsoidSurfaceOp .calculate(axisAlignedEllipsoid, outsidePoint).get(); assertEquals("Distance to outside point failed", 1.0, distanceToOutsidePoint, 1.0e-12); }
@Test public void testOutsidePointForSphere() { final Vector3d sphereVector = new Vector3d(spherePointSupplier.get()); sphereVector.mul(3.0); final Vector3dc outsidePoint = new Vector3d(sphereVector); final double distanceToOutsidePoint = distanceFromEllipsoidSurfaceOp .calculate(sphere, outsidePoint).get(); assertEquals("Distance to outside point failed", 1.0, distanceToOutsidePoint, 1.0e-12); }
@Test public void testSurfacePointForArbitraryEllipsoid() { final Vector3dc surfacePoint = new Vector3d(1.0, 1.0 + 1.5, 1.0 + 3.0 * Math .sqrt(3.0) / 2.0); final double distanceToSurfacePoint = distanceFromEllipsoidSurfaceOp .calculate(transformedEllipsoid, surfacePoint).get(); assertEquals("Distance to surface point failed", 0.0, distanceToSurfacePoint, 1.0e-12); }
@Test public void testSurfacePointForAxisAlignedEllipsoid() { final Vector3dc surfacePoint = new Vector3d(0.0, 0.0, 3.0); final double distanceToSurfacePoint = distanceFromEllipsoidSurfaceOp .calculate(axisAlignedEllipsoid, surfacePoint).get(); assertEquals("Distance to surface point failed", 0.0, distanceToSurfacePoint, 1.0e-12); }
@Test public void testSurfacePointForSphere() { final Vector3d sphereVector = new Vector3d(spherePointSupplier.get()); sphereVector.mul(2.0); final Vector3dc surfacePoint = new Vector3d(sphereVector); final double distanceToSurfacePoint = distanceFromEllipsoidSurfaceOp .calculate(sphere, surfacePoint).get(); assertEquals("Distance to surface point failed", 0.0, distanceToSurfacePoint, 1.0e-12); }