MapProjection extends AbstractMathTransform implements MathTransform2D, Serializable { protected double orthodromicDistance(final Point2D source, final Point2D target) { if (source.distanceSq(target) > 1.0) { final double y1 = toRadians(source.getY()); final double y2 = toRadians(target.getY()); final double dx = toRadians(abs(target.getX() - source.getX()) % 360); double rho = sin(y1)*sin(y2) + cos(y1)*cos(y2)*cos(dx); if (rho > +1) {assert rho <= +(1+EPSILON) : rho; rho = +1;} if (rho < -1) {assert rho >= -(1+EPSILON) : rho; rho = -1;} return acos(rho) * semiMajor; } else { double lat1 = toRadians(source.getY()); double lat2 = toRadians(target.getY()); double lng1 = toRadians(source.getX()); double lng2 = toRadians(target.getX()); double dlat = Math.sin(0.5 * (lat2 - lat1)); double dlng = Math.sin(0.5 * (lng2 - lng1)); double x = dlat * dlat + dlng * dlng * Math.cos(lat1) * Math.cos(lat2); double arcRadians = 2 * Math.atan2(Math.sqrt(x), Math.sqrt(Math.max(0.0, 1.0 - x))); return arcRadians * semiMajor; } } protected  MapProjection(final ParameterValueGroup values);   MapProjection(final ParameterValueGroup values, Collection<GeneralParameterDescriptor> expected); @Override abstract ParameterDescriptorGroup getParameterDescriptors(); @Override ParameterValueGroup getParameterValues(); final int getSourceDimensions(); final int getTargetDimensions(); @Override final Point2D transform(final Point2D ptSrc, Point2D ptDst); final void transform(final double[] srcPts, int srcOff,
                                final double[] dstPts, int dstOff, int numPts); @Override final void transform(final float[] srcPts, int srcOff,
                                final float[] dstPts, int dstOff, int numPts); @Override final MathTransform2D inverse(); static synchronized void resetWarnings(); @Override int hashCode(); @Override boolean equals(final Object object); static boolean SKIP_SANITY_CHECKS; }
@Test public void testOrthodromicDistance() throws FactoryException { MapProjection mt = createGoogleMercator(); assertEquals(111319.49079, mt.orthodromicDistance(new Point2D.Double(0.0, 0.0), new Point2D.Double(0.0, 1.0)), 0.001); assertEquals(111319.49079, mt.orthodromicDistance(new Point2D.Double(0.0, 0.0), new Point2D.Double(1.0, 0.0)), 0.001); assertEquals(111319.49079, mt.orthodromicDistance(new Point2D.Double(0.0, 89.0), new Point2D.Double(0.0, 90.0)), 0.001); assertEquals(1942.76834, mt.orthodromicDistance(new Point2D.Double(0.0, 89.0), new Point2D.Double(1.0, 89.0)), 0.001); assertEquals(10018754.17139, mt.orthodromicDistance(new Point2D.Double(0.0, 0.0), new Point2D.Double(0.0, 90.0)), 0.001); Point2D src = new Point2D.Double(48.38824840214492, -14.967538330290973); assertEquals(0.0, mt.orthodromicDistance(src, src), 0.000000001); Point2D target = new Point2D.Double(src.getX(), src.getY()+0.0000001); assertEquals(0.011131948840096939, mt.orthodromicDistance(src, target), 1E-12); Point2D target2 = new Point2D.Double(src.getX(), src.getY()+0.000000000001); assertEquals(1.1117412E-7, mt.orthodromicDistance(src, target2), 1E-12); }