public GeoPoint[] interpolate(final GeoPoint start,final GeoPoint end,final double[] proportions){
  double A=x;
  double B=y;
  double C=z;
  final double transX=-D * A;
  final double transY=-D * B;
  final double transZ=-D * C;
  double cosRA;
  double sinRA;
  double cosHA;
  double sinHA;
  double magnitude=magnitude();
  if (magnitude >= MINIMUM_RESOLUTION) {
    final double denom=1.0 / magnitude;
    A*=denom;
    B*=denom;
    C*=denom;
    final double xyMagnitude=Math.sqrt(A * A + B * B);
    if (xyMagnitude >= MINIMUM_RESOLUTION) {
      final double xyDenom=1.0 / xyMagnitude;
      cosRA=A * xyDenom;
      sinRA=-B * xyDenom;
    }
 else {
      cosRA=1.0;
      sinRA=0.0;
    }
    sinHA=xyMagnitude;
    cosHA=C;
  }
 else {
    cosRA=1.0;
    sinRA=0.0;
    cosHA=1.0;
    sinHA=0.0;
  }
  final Vector modifiedStart=modify(start,transX,transY,transZ,sinRA,cosRA,sinHA,cosHA);
  final Vector modifiedEnd=modify(end,transX,transY,transZ,sinRA,cosRA,sinHA,cosHA);
  if (Math.abs(modifiedStart.z) >= MINIMUM_RESOLUTION)   throw new IllegalArgumentException("Start point was not on plane: " + modifiedStart.z);
  if (Math.abs(modifiedEnd.z) >= MINIMUM_RESOLUTION)   throw new IllegalArgumentException("End point was not on plane: " + modifiedEnd.z);
  final double startAngle=Math.atan2(modifiedStart.y,modifiedStart.x);
  final double endAngle=Math.atan2(modifiedEnd.y,modifiedEnd.x);
  final double startMagnitude=Math.sqrt(modifiedStart.x * modifiedStart.x + modifiedStart.y * modifiedStart.y);
  double delta;
  double newEndAngle=endAngle;
  while (newEndAngle < startAngle) {
    newEndAngle+=Math.PI * 2.0;
  }
  if (newEndAngle - startAngle <= Math.PI) {
    delta=newEndAngle - startAngle;
  }
 else {
    double newStartAngle=startAngle;
    while (newStartAngle < endAngle) {
      newStartAngle+=Math.PI * 2.0;
    }
    delta=newStartAngle - endAngle;
  }
  final GeoPoint[] returnValues=new GeoPoint[proportions.length];
  for (int i=0; i < returnValues.length; i++) {
    final double newAngle=startAngle + proportions[i] * delta;
    final double sinNewAngle=Math.sin(newAngle);
    final double cosNewAngle=Math.cos(newAngle);
    final Vector newVector=new Vector(cosNewAngle * startMagnitude,sinNewAngle * startMagnitude,0.0);
    returnValues[i]=reverseModify(newVector,transX,transY,transZ,sinRA,cosRA,sinHA,cosHA);
  }
  return returnValues;
}

public GeoPoint [ ] interpolate ( final GeoPoint start , final GeoPoint end , final double [ ] proportions ) { double A = x ; double B = y ; double C = z ; final double transX = - D * A ; final double transY = - D * B ; final double transZ = - D * C ; double cosRA ; double sinRA ; double cosHA ; double sinHA ; double magnitude = magnitude ( ) ; if ( magnitude >= MINIMUM_RESOLUTION ) { final double denom = 1.0 / magnitude ; A *= denom ; B *= denom ; C *= denom ; final double xyMagnitude = Math . sqrt ( A * A + B * B ) ; if ( xyMagnitude >= MINIMUM_RESOLUTION ) { final double xyDenom = 1.0 / xyMagnitude ; cosRA = A * xyDenom ; sinRA = - B * xyDenom ; } else { cosRA = 1.0 ; sinRA = 0.0 ; } sinHA = xyMagnitude ; cosHA = C ; } else { cosRA = 1.0 ; sinRA = 0.0 ; cosHA = 1.0 ; sinHA = 0.0 ; } final Vector modifiedStart = modify ( start , transX , transY , transZ , sinRA , cosRA , sinHA , cosHA ) ; final Vector modifiedEnd = modify ( end , transX , transY , transZ , sinRA , cosRA , sinHA , cosHA ) ; if ( Math . abs ( modifiedStart . z ) >= MINIMUM_RESOLUTION ) throw new IllegalArgumentException ( "Start point was not on plane: " + modifiedStart . z ) ; if ( Math . abs ( modifiedEnd . z ) >= MINIMUM_RESOLUTION ) throw new IllegalArgumentException ( "End point was not on plane: " + modifiedEnd . z ) ; final double startAngle = Math . atan2 ( modifiedStart . y , modifiedStart . x ) ; final double endAngle = Math . atan2 ( modifiedEnd . y , modifiedEnd . x ) ; final double startMagnitude = Math . sqrt ( modifiedStart . x * modifiedStart . x + modifiedStart . y * modifiedStart . y ) ; double delta ; double newEndAngle = endAngle ; while ( newEndAngle < startAngle ) { newEndAngle += Math . PI * 2.0 ; } if ( newEndAngle - startAngle <= Math . PI ) { delta = newEndAngle - startAngle ; } else { double newStartAngle = startAngle ; while ( newStartAngle < endAngle ) { newStartAngle += Math . PI * 2.0 ; } delta = newStartAngle - endAngle ; } final GeoPoint [ ] returnValues = new GeoPoint [ proportions . length ] ; for ( int i = 0 ; i < returnValues . length ; i ++ ) { final double newAngle = startAngle + proportions [ i ] * delta ; final double sinNewAngle = Math . sin ( newAngle ) ; final double cosNewAngle = Math . cos ( newAngle ) ; final Vector newVector = new Vector ( cosNewAngle * startMagnitude , sinNewAngle * startMagnitude , 0.0 ) ; returnValues [ i ] = reverseModify ( newVector , transX , transY , transZ , sinRA , cosRA , sinHA , cosHA ) ; } return returnValues ; }
find points on the boundary of the intersection of a plane and the unit sphere , given a starting point , and ending point , and a list of proportions of the arc ( e . g . 0 . 25 , 0 . 5 , 0 . 75 ) . the angle between the starting point and ending point is assumed to be less than pi .
