Пример #1
0
  protected List<Position> computePathPositions(
      Position startPosition, Position endPosition, Angle delta) {
    Angle dist = LatLon.greatCircleDistance(startPosition, endPosition);
    dist = dist.multiply(0.6);

    Angle azimuth = LatLon.greatCircleAzimuth(startPosition, endPosition);

    LatLon locA = LatLon.greatCircleEndPosition(startPosition, azimuth.add(delta), dist);

    dist = dist.multiply(0.9);
    LatLon locB = LatLon.greatCircleEndPosition(startPosition, azimuth.subtract(delta), dist);

    return Arrays.asList(startPosition, new Position(locA, 0), new Position(locB, 0), endPosition);
  }
  protected void doMoveTo(Position oldReferencePosition, Position newReferencePosition) {
    java.util.ArrayList<LatLon> newLocations = new java.util.ArrayList<LatLon>();

    for (LatLon ll : this.locations) {
      Angle heading = LatLon.greatCircleAzimuth(oldReferencePosition, ll);
      Angle pathLength = LatLon.greatCircleDistance(oldReferencePosition, ll);
      newLocations.add(LatLon.greatCircleEndPosition(newReferencePosition, heading, pathLength));
    }

    this.setLocations(newLocations);
  }
Пример #3
0
 /**
  * Compute the view range footprint on the globe.
  *
  * @param dc the current <code>DrawContext</code>
  * @param steps the number of steps.
  * @return an array list of <code>LatLon</code> forming a closed shape.
  */
 protected ArrayList<LatLon> computeViewFootPrint(DrawContext dc, int steps) {
   ArrayList<LatLon> positions = new ArrayList<LatLon>();
   Position eyePos = dc.getView().getEyePosition();
   Angle distance =
       Angle.fromRadians(
           Math.asin(
               dc.getView().getFarClipDistance()
                   / (dc.getGlobe().getRadius() + eyePos.getElevation())));
   if (distance.degrees > 10) {
     double headStep = 360d / steps;
     Angle heading = Angle.ZERO;
     for (int i = 0; i <= steps; i++) {
       LatLon p = LatLon.greatCircleEndPosition(eyePos, heading, distance);
       positions.add(p);
       heading = heading.addDegrees(headStep);
     }
     return positions;
   } else return null;
 }
  @Override
  protected void doMoveTo(Position oldReferencePosition, Position newReferencePosition) {
    if (this.boundaries.getContourCount() == 0) return;

    for (int i = 0; i < this.boundaries.getContourCount(); i++) {
      ArrayList<LatLon> newLocations = new ArrayList<LatLon>();

      for (LatLon ll : this.boundaries.getContour(i)) {
        Angle heading = LatLon.greatCircleAzimuth(oldReferencePosition, ll);
        Angle pathLength = LatLon.greatCircleDistance(oldReferencePosition, ll);
        newLocations.add(LatLon.greatCircleEndPosition(newReferencePosition, heading, pathLength));
      }

      this.boundaries.setContour(i, newLocations);
    }

    // We've changed the multi-polygon's list of boundaries; flag the shape as changed.
    this.onShapeChanged();
  }
  /** {@inheritDoc} */
  @Override
  protected void determineLabelPositions(DrawContext dc) {
    Position center = this.getReferencePosition();
    if (center == null) return;

    // Position the labels along a line radiating out from the center of the circle. The angle (60
    // degrees) is
    // chosen to match the graphic template defined by MIL-STD-2525C, pg. 613.
    double globeRadius = dc.getGlobe().getRadius();

    Angle labelAngle = this.getLabelAngle();

    int i = 0;
    for (SurfaceCircle ring : this.rings) {
      double radius = ring.getRadius();

      LatLon ll = LatLon.greatCircleEndPosition(center, labelAngle.radians, radius / globeRadius);

      this.labels.get(i).setPosition(new Position(ll, 0));
      i += 1;
    }
  }
Пример #6
0
  protected void doMoveTo(Position oldRef, Position newRef) {
    if (oldRef == null) {
      String message = "nullValue.OldRefIsNull";
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }
    if (newRef == null) {
      String message = "nullValue.NewRefIsNull";
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    super.doMoveTo(oldRef, newRef);

    int count = this.locations.size();
    LatLon[] newLocations = new LatLon[count];
    for (int i = 0; i < count; i++) {
      LatLon ll = this.locations.get(i);
      double distance = LatLon.greatCircleDistance(oldRef, ll).radians;
      double azimuth = LatLon.greatCircleAzimuth(oldRef, ll).radians;
      newLocations[i] = LatLon.greatCircleEndPosition(newRef, azimuth, distance);
    }
    this.setLocations(Arrays.asList(newLocations));
  }
Пример #7
0
  /**
   * Subdivide a list of positions so that no segment is longer then the provided maxLength. Only
   * the positions between start and start + count - 1 will be processed.
   *
   * <p>If needed, new intermediate positions will be created along lines that follow the given
   * pathType - one of Polyline.LINEAR, Polyline.RHUMB_LINE or Polyline.GREAT_CIRCLE. All position
   * elevations will be either at the terrain surface if followTerrain is true, or interpolated
   * according to the original elevations.
   *
   * @param globe the globe to draw elevations and points from.
   * @param positions the original position list
   * @param maxLength the maximum length for one segment.
   * @param followTerrain true if the positions should be on the terrain surface.
   * @param pathType the type of path to use in between two positions.
   * @param start the first position indice in the original list.
   * @param count how many positions from the original list have to be processed and returned.
   * @return a list of positions with no segment longer then maxLength and elevations following
   *     terrain or not.
   */
  protected static ArrayList<? extends Position> subdividePositions(
      Globe globe,
      ArrayList<? extends Position> positions,
      double maxLength,
      boolean followTerrain,
      String pathType,
      int start,
      int count) {
    if (positions == null || positions.size() < start + count) return positions;

    ArrayList<Position> newPositions = new ArrayList<Position>();
    // Add first position
    Position pos1 = positions.get(start);
    if (followTerrain)
      newPositions.add(
          new Position(pos1, globe.getElevation(pos1.getLatitude(), pos1.getLongitude())));
    else newPositions.add(pos1);
    for (int i = 1; i < count; i++) {
      Position pos2 = positions.get(start + i);
      double arcLengthRadians = LatLon.greatCircleDistance(pos1, pos2).radians;
      double arcLength = arcLengthRadians * globe.getRadiusAt(LatLon.interpolate(.5, pos1, pos2));
      if (arcLength > maxLength) {
        // if necessary subdivide segment at regular intervals smaller then maxLength
        Angle segmentAzimuth = null;
        Angle segmentDistance = null;
        int steps = (int) Math.ceil(arcLength / maxLength); // number of intervals - at least two
        for (int j = 1; j < steps; j++) {
          float s = (float) j / steps;
          LatLon destLatLon;
          if (pathType.equals(AVKey.LINEAR)) {
            destLatLon = LatLon.interpolate(s, pos1, pos2);
          } else if (pathType.equals(AVKey.RHUMB_LINE)) {
            if (segmentAzimuth == null) {
              segmentAzimuth = LatLon.rhumbAzimuth(pos1, pos2);
              segmentDistance = LatLon.rhumbDistance(pos1, pos2);
            }
            destLatLon =
                LatLon.rhumbEndPosition(pos1, segmentAzimuth.radians, s * segmentDistance.radians);
          } else // GREAT_CIRCLE
          {
            if (segmentAzimuth == null) {
              segmentAzimuth = LatLon.greatCircleAzimuth(pos1, pos2);
              segmentDistance = LatLon.greatCircleDistance(pos1, pos2);
            }
            destLatLon =
                LatLon.greatCircleEndPosition(
                    pos1, segmentAzimuth.radians, s * segmentDistance.radians);
          }
          // Set elevation
          double elevation;
          if (followTerrain)
            elevation = globe.getElevation(destLatLon.getLatitude(), destLatLon.getLongitude());
          else elevation = pos1.elevation * (1 - s) + pos2.elevation * s;
          // Add new position
          newPositions.add(new Position(destLatLon, elevation));
        }
      }
      // Finally add the segment end position
      if (followTerrain)
        newPositions.add(
            new Position(pos2, globe.getElevation(pos2.getLatitude(), pos2.getLongitude())));
      else newPositions.add(pos2);
      // Prepare for next segment
      pos1 = pos2;
    }
    return newPositions;
  }
  protected void updateView(ScreenAnnotation control, String controlType) {
    if (this.wwd == null) return;
    if (!(this.wwd.getView() instanceof OrbitView)) return;

    OrbitView view = (OrbitView) this.wwd.getView();
    view.stopAnimations();
    view.stopMovement();

    if (controlType.equals(AVKey.VIEW_PAN)) {
      resetOrbitView(view);
      // Go some distance in the control mouse direction
      Angle heading = computePanHeading(view, control);
      Angle distance = computePanAmount(this.wwd.getModel().getGlobe(), view, control, panStep);
      LatLon newViewCenter =
          LatLon.greatCircleEndPosition(view.getCenterPosition(), heading, distance);
      // Turn around if passing by a pole - TODO: better handling of the pole crossing situation
      if (this.isPathCrossingAPole(newViewCenter, view.getCenterPosition()))
        view.setHeading(Angle.POS180.subtract(view.getHeading()));
      // Set new center pos
      view.setCenterPosition(new Position(newViewCenter, view.getCenterPosition().getElevation()));
    } else if (controlType.equals(AVKey.VIEW_LOOK)) {
      setupFirstPersonView(view);
      Angle heading = computeLookHeading(view, control, headingStep);
      Angle pitch = computeLookPitch(view, control, pitchStep);
      // Check whether the view will still point at terrain
      Vec4 surfacePoint = computeSurfacePoint(view, heading, pitch);
      if (surfacePoint != null) {
        // Change view state
        final Position eyePos = view.getEyePosition(); // Save current eye position
        view.setHeading(heading);
        view.setPitch(pitch);
        view.setZoom(0);
        view.setCenterPosition(eyePos); // Set center at the eye position
      }
    } else if (controlType.equals(AVKey.VIEW_ZOOM_IN)) {
      resetOrbitView(view);
      view.setZoom(computeNewZoom(view, -zoomStep));
    } else if (controlType.equals(AVKey.VIEW_ZOOM_OUT)) {
      resetOrbitView(view);
      view.setZoom(computeNewZoom(view, zoomStep));
    } else if (controlType.equals(AVKey.VIEW_HEADING_LEFT)) {
      resetOrbitView(view);
      view.setHeading(view.getHeading().addDegrees(headingStep));
    } else if (controlType.equals(AVKey.VIEW_HEADING_RIGHT)) {
      resetOrbitView(view);
      view.setHeading(view.getHeading().addDegrees(-headingStep));
    } else if (controlType.equals(AVKey.VIEW_PITCH_UP)) {
      resetOrbitView(view);
      if (view.getPitch().degrees >= pitchStep)
        view.setPitch(view.getPitch().addDegrees(-pitchStep));
    } else if (controlType.equals(AVKey.VIEW_PITCH_DOWN)) {
      resetOrbitView(view);
      if (view.getPitch().degrees <= 90 - pitchStep)
        view.setPitch(view.getPitch().addDegrees(pitchStep));
    } else if (controlType.equals(AVKey.VIEW_FOV_NARROW)) {
      if (view.getFieldOfView().degrees / fovStep >= 4)
        view.setFieldOfView(view.getFieldOfView().divide(fovStep));
    } else if (controlType.equals(AVKey.VIEW_FOV_WIDE)) {
      if (view.getFieldOfView().degrees * fovStep < 120)
        view.setFieldOfView(view.getFieldOfView().multiply(fovStep));
    } else if (controlType.equals(AVKey.VERTICAL_EXAGGERATION_UP)) {
      SceneController sc = this.wwd.getSceneController();
      sc.setVerticalExaggeration(sc.getVerticalExaggeration() + this.veStep);
    } else if (controlType.equals(AVKey.VERTICAL_EXAGGERATION_DOWN)) {
      SceneController sc = this.wwd.getSceneController();
      sc.setVerticalExaggeration(Math.max(1d, sc.getVerticalExaggeration() - this.veStep));
    }

    view.firePropertyChange(AVKey.VIEW, null, view);
  }