/**
   * Setup the view to a first person mode (zoom = 0)
   *
   * @param view the orbit view to set into a first person view.
   */
  protected void setupFirstPersonView(OrbitView view) {
    if (view.getZoom() == 0) // already in first person mode
    return;

    Vec4 eyePoint = view.getEyePoint();
    // Center pos at eye pos
    Position centerPosition = wwd.getModel().getGlobe().computePositionFromPoint(eyePoint);
    // Compute pitch and heading relative to center position
    Vec4 normal =
        wwd.getModel()
            .getGlobe()
            .computeSurfaceNormalAtLocation(
                centerPosition.getLatitude(), centerPosition.getLongitude());
    Vec4 north =
        wwd.getModel()
            .getGlobe()
            .computeNorthPointingTangentAtLocation(
                centerPosition.getLatitude(), centerPosition.getLongitude());
    // Pitch
    view.setPitch(Angle.POS180.subtract(view.getForwardVector().angleBetween3(normal)));
    // Heading
    Vec4 perpendicular = view.getForwardVector().perpendicularTo3(normal);
    Angle heading = perpendicular.angleBetween3(north);
    double direction = Math.signum(-normal.cross3(north).dot3(perpendicular));
    view.setHeading(heading.multiply(direction));
    // Zoom
    view.setZoom(0);
    // Center pos
    view.setCenterPosition(centerPosition);
  }
Пример #2
0
  /**
   * Compute the positions of the arrow head of the graphic's legs.
   *
   * @param dc Current draw context
   * @param base Position of the arrow's starting point.
   * @param tip Position of the arrow head tip.
   * @param arrowLength Length of the arrowhead as a fraction of the total line length.
   * @param arrowAngle Angle of the arrow head.
   * @return Positions required to draw the arrow head.
   */
  protected List<Position> computeArrowheadPositions(
      DrawContext dc, Position base, Position tip, double arrowLength, Angle arrowAngle) {
    // Build a triangle to represent the arrowhead. The triangle is built from two vectors, one
    // parallel to the
    // segment, and one perpendicular to it.

    Globe globe = dc.getGlobe();

    Vec4 ptA = globe.computePointFromPosition(base);
    Vec4 ptB = globe.computePointFromPosition(tip);

    // Compute parallel component
    Vec4 parallel = ptA.subtract3(ptB);

    Vec4 surfaceNormal = globe.computeSurfaceNormalAtPoint(ptB);

    // Compute perpendicular component
    Vec4 perpendicular = surfaceNormal.cross3(parallel);

    double finalArrowLength = arrowLength * parallel.getLength3();
    double arrowHalfWidth = finalArrowLength * arrowAngle.tanHalfAngle();

    perpendicular = perpendicular.normalize3().multiply3(arrowHalfWidth);
    parallel = parallel.normalize3().multiply3(finalArrowLength);

    // Compute geometry of direction arrow
    Vec4 vertex1 = ptB.add3(parallel).add3(perpendicular);
    Vec4 vertex2 = ptB.add3(parallel).subtract3(perpendicular);

    return TacticalGraphicUtil.asPositionList(globe, vertex1, vertex2, ptB);
  }
Пример #3
0
  /**
   * Determine the positions that make up the arrowhead.
   *
   * @param dc Current draw context.
   * @param startPosition Position of the arrow's base.
   * @param endPosition Position of the arrow head tip.
   * @return Positions that define the arrowhead.
   */
  protected List<Position> computeArrowheadPositions(
      DrawContext dc, Position startPosition, Position endPosition) {
    Globe globe = dc.getGlobe();

    // Arrowhead looks like this:
    //                  _
    //        A\         | 1/2 width
    // ________B\       _|
    // Pt. 1    /
    //        C/
    //         | |
    //      Length

    Vec4 p1 = globe.computePointFromPosition(startPosition);
    Vec4 pB = globe.computePointFromPosition(endPosition);

    // Find vector in the direction of the arrow
    Vec4 vB1 = p1.subtract3(pB);

    double arrowLengthFraction = this.getArrowLength();

    // Find the point at the base of the arrowhead
    Vec4 arrowBase = pB.add3(vB1.multiply3(arrowLengthFraction));

    Vec4 normal = globe.computeSurfaceNormalAtPoint(arrowBase);

    // Compute the length of the arrowhead
    double arrowLength = vB1.getLength3() * arrowLengthFraction;
    double arrowHalfWidth = arrowLength * this.getArrowAngle().tanHalfAngle();

    // Compute a vector perpendicular to the segment and the normal vector
    Vec4 perpendicular = vB1.cross3(normal);
    perpendicular = perpendicular.normalize3().multiply3(arrowHalfWidth);

    // Find points A and C
    Vec4 pA = arrowBase.add3(perpendicular);
    Vec4 pC = arrowBase.subtract3(perpendicular);

    return TacticalGraphicUtil.asPositionList(globe, pA, pB, pC);
  }
  /**
   * Reset the view to an orbit view state if in first person mode (zoom = 0)
   *
   * @param view the orbit view to reset
   */
  protected void resetOrbitView(OrbitView view) {
    if (view.getZoom() > 0) // already in orbit view mode
    return;

    // Find out where on the terrain the eye is looking at in the viewport center
    // TODO: if no terrain is found in the viewport center, iterate toward viewport bottom until it
    // is found
    Vec4 centerPoint = computeSurfacePoint(view, view.getHeading(), view.getPitch());
    // Reset the orbit view center point heading, pitch and zoom
    if (centerPoint != null) {
      Vec4 eyePoint = view.getEyePoint();
      // Center pos on terrain surface
      Position centerPosition = wwd.getModel().getGlobe().computePositionFromPoint(centerPoint);
      // Compute pitch and heading relative to center position
      Vec4 normal =
          wwd.getModel()
              .getGlobe()
              .computeSurfaceNormalAtLocation(
                  centerPosition.getLatitude(), centerPosition.getLongitude());
      Vec4 north =
          wwd.getModel()
              .getGlobe()
              .computeNorthPointingTangentAtLocation(
                  centerPosition.getLatitude(), centerPosition.getLongitude());
      // Pitch
      view.setPitch(Angle.POS180.subtract(view.getForwardVector().angleBetween3(normal)));
      // Heading
      Vec4 perpendicular = view.getForwardVector().perpendicularTo3(normal);
      Angle heading = perpendicular.angleBetween3(north);
      double direction = Math.signum(-normal.cross3(north).dot3(perpendicular));
      view.setHeading(heading.multiply(direction));
      // Zoom
      view.setZoom(eyePoint.distanceTo3(centerPoint));
      // Center pos
      view.setCenterPosition(centerPosition);
    }
  }
  /**
   * Compute points on either side of a line segment. This method requires a point on the line, and
   * either a next point, previous point, or both.
   *
   * @param point Center point about which to compute side points.
   * @param prev Previous point on the line. May be null if {@code next} is non-null.
   * @param next Next point on the line. May be null if {@code prev} is non-null.
   * @param leftPositions Left position will be added to this list.
   * @param rightPositions Right position will be added to this list.
   * @param halfWidth Distance from the center line to the left or right lines.
   * @param globe Current globe.
   */
  protected void generateParallelPoints(
      Vec4 point,
      Vec4 prev,
      Vec4 next,
      List<Position> leftPositions,
      List<Position> rightPositions,
      double halfWidth,
      Globe globe) {
    if ((point == null) || (prev == null && next == null)) {
      String message = Logging.getMessage("nullValue.PointIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }
    if (leftPositions == null || rightPositions == null) {
      String message = Logging.getMessage("nullValue.PositionListIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }
    if (globe == null) {
      String message = Logging.getMessage("nullValue.GlobeIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    Vec4 offset;
    Vec4 normal = globe.computeSurfaceNormalAtPoint(point);

    // Compute vector in the direction backward along the line.
    Vec4 backward = (prev != null) ? prev.subtract3(point) : point.subtract3(next);

    // Compute a vector perpendicular to segment BC, and the globe normal vector.
    Vec4 perpendicular = backward.cross3(normal);

    double length;
    // If both next and previous points are supplied then calculate the angle that bisects the angle
    // current, next, prev.
    if (next != null && prev != null && !Vec4.areColinear(prev, point, next)) {
      // Compute vector in the forward direction.
      Vec4 forward = next.subtract3(point);

      // Calculate the vector that bisects angle ABC.
      offset = forward.normalize3().add3(backward.normalize3());
      offset = offset.normalize3();

      // Compute the scalar triple product of the vector BC, the normal vector, and the offset
      // vector to
      // determine if the offset points to the left or the right of the control line.
      double tripleProduct = perpendicular.dot3(offset);
      if (tripleProduct < 0) {
        offset = offset.multiply3(-1);
      }

      // Determine the length of the offset vector that will keep the left and right lines parallel
      // to the control
      // line.
      Angle theta = backward.angleBetween3(offset);
      if (!Angle.ZERO.equals(theta)) length = halfWidth / theta.sin();
      else length = halfWidth;
    } else {
      offset = perpendicular.normalize3();
      length = halfWidth;
    }
    offset = offset.multiply3(length);

    // Determine the left and right points by applying the offset.
    Vec4 ptRight = point.add3(offset);
    Vec4 ptLeft = point.subtract3(offset);

    // Convert cartesian points to geographic.
    Position posLeft = globe.computePositionFromPoint(ptLeft);
    Position posRight = globe.computePositionFromPoint(ptRight);

    leftPositions.add(posLeft);
    rightPositions.add(posRight);
  }