protected Angle computePanAmount(
      Globe globe, OrbitView view, ScreenAnnotation control, double panStep) {
    // Compute last pick point distance relative to pan control center
    double size = control.getAttributes().getSize().width * control.getAttributes().getScale();
    Vec4 center = new Vec4(control.getScreenPoint().x, control.getScreenPoint().y + size / 2, 0);
    double px = lastPickPoint.x - center.x;
    double py = view.getViewport().getHeight() - lastPickPoint.y - center.y;
    double pickDistance = Math.sqrt(px * px + py * py);
    double pickDistanceFactor = Math.min(pickDistance / 10, 5);

    // Compute globe angular distance depending on eye altitude
    Position eyePos = view.getEyePosition();
    double radius = globe.getRadiusAt(eyePos);
    double minValue = 0.5 * (180.0 / (Math.PI * radius)); // Minimum change ~0.5 meters
    double maxValue = 1.0; // Maximum change ~1 degree

    // Compute an interpolated value between minValue and maxValue, using (eye altitude)/(globe
    // radius) as
    // the interpolant. Interpolation is performed on an exponential curve, to keep the value from
    // increasing too quickly as eye altitude increases.
    double a = eyePos.getElevation() / radius;
    a = (a < 0 ? 0 : (a > 1 ? 1 : a));
    double expBase = 2.0; // Exponential curve parameter.
    double value =
        minValue + (maxValue - minValue) * ((Math.pow(expBase, a) - 1.0) / (expBase - 1.0));

    return Angle.fromDegrees(value * pickDistanceFactor * panStep);
  }
 protected Angle computePanHeading(OrbitView view, ScreenAnnotation control) {
   // Compute last pick point 'heading' relative to pan control center
   double size = control.getAttributes().getSize().width * control.getAttributes().getScale();
   Vec4 center = new Vec4(control.getScreenPoint().x, control.getScreenPoint().y + size / 2, 0);
   double px = lastPickPoint.x - center.x;
   double py = view.getViewport().getHeight() - lastPickPoint.y - center.y;
   Angle heading = view.getHeading().add(Angle.fromRadians(Math.atan2(px, py)));
   heading = heading.degrees >= 0 ? heading : heading.addDegrees(360);
   return heading;
 }
 protected Angle computeLookPitch(OrbitView view, ScreenAnnotation control, double pitchStep) {
   // Compute last pick point 'pitch' relative to look control center on y
   double size = control.getAttributes().getSize().width * control.getAttributes().getScale();
   Vec4 center = new Vec4(control.getScreenPoint().x, control.getScreenPoint().y + size / 2, 0);
   double py = view.getViewport().getHeight() - lastPickPoint.y - center.y;
   double pickDistanceFactor = Math.min(Math.abs(py) / 3000, 5) * Math.signum(py);
   // New pitch
   Angle pitch = view.getPitch().add(Angle.fromRadians(pitchStep * pickDistanceFactor));
   pitch = pitch.degrees >= 0 ? (pitch.degrees <= 90 ? pitch : Angle.fromDegrees(90)) : Angle.ZERO;
   return pitch;
 }
 protected Angle computeLookHeading(OrbitView view, ScreenAnnotation control, double headingStep) {
   // Compute last pick point 'heading' relative to look control center on x
   double size = control.getAttributes().getSize().width * control.getAttributes().getScale();
   Vec4 center = new Vec4(control.getScreenPoint().x, control.getScreenPoint().y + size / 2, 0);
   double px = lastPickPoint.x - center.x;
   double pickDistanceFactor = Math.min(Math.abs(px) / 3000, 5) * Math.signum(px);
   // New heading
   Angle heading = view.getHeading().add(Angle.fromRadians(headingStep * pickDistanceFactor));
   heading = heading.degrees >= 0 ? heading : heading.addDegrees(360);
   return heading;
 }