Exemple #1
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);
  }
  /**
   * Causes the View attached to the specified WorldWindow to animate to the specified sector. The
   * View starts animating at its current location and stops when the sector fills the window.
   *
   * @param wwd the WorldWindow who's View animates.
   * @param sector the sector to go to.
   * @throws IllegalArgumentException if either the <code>wwd</code> or the <code>sector</code> are
   *     <code>null</code>.
   */
  public static void goTo(WorldWindow wwd, Sector sector) {
    if (wwd == null) {
      String message = Logging.getMessage("nullValue.WorldWindow");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    if (sector == null) {
      String message = Logging.getMessage("nullValue.SectorIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    // Create a bounding box for the specified sector in order to estimate its size in model
    // coordinates.
    Box extent =
        Sector.computeBoundingBox(
            wwd.getModel().getGlobe(), wwd.getSceneController().getVerticalExaggeration(), sector);

    // Estimate the distance between the center position and the eye position that is necessary to
    // cause the sector to
    // fill a viewport with the specified field of view. Note that we change the distance between
    // the center and eye
    // position here, and leave the field of view constant.
    Angle fov = wwd.getView().getFieldOfView();
    double zoom = extent.getRadius() / fov.cosHalfAngle() / fov.tanHalfAngle();

    // Configure OrbitView to look at the center of the sector from our estimated distance. This
    // causes OrbitView to
    // animate to the specified position over several seconds. To affect this change immediately use
    // the following:
    // ((OrbitView) wwd.getView()).setCenterPosition(new Position(sector.getCentroid(), 0d));
    // ((OrbitView) wwd.getView()).setZoom(zoom);
    wwd.getView().goTo(new Position(sector.getCentroid(), 0d), zoom);
  }
  /**
   * Creates a <code>Frustum</code> from a horizontal field-of-view, viewport aspect ratio and
   * distance to near and far depth clipping planes. The near plane must be closer than the far
   * plane, and both near and far values must be positive.
   *
   * @param horizontalFieldOfView horizontal field-of-view angle in the range (0, 180)
   * @param viewportWidth the width of the viewport in screen pixels
   * @param viewportHeight the height of the viewport in screen pixels
   * @param near distance to the near depth clipping plane
   * @param far distance to far depth clipping plane
   * @return Frustum configured from the specified perspective parameters.
   * @throws IllegalArgumentException if fov is not in the range (0, 180), if either near or far are
   *     negative, or near is greater than or equal to far
   */
  public Frustum setPerspective(
      Angle horizontalFieldOfView,
      double viewportWidth,
      double viewportHeight,
      double near,
      double far) {
    if (horizontalFieldOfView == null) {
      String msg = Logging.getMessage("nullValue.FieldOfViewIsNull");
      Logging.error(msg);
      throw new IllegalArgumentException(msg);
    }

    if (horizontalFieldOfView.degrees <= 0 || horizontalFieldOfView.degrees > 180) {
      String msg = Logging.getMessage("generic.FieldOfViewIsInvalid", horizontalFieldOfView);
      Logging.error(msg);
      throw new IllegalArgumentException(msg);
    }

    if (viewportWidth < 0) {
      String msg = Logging.getMessage("generic.WidthIsInvalid", viewportWidth);
      Logging.error(msg);
      throw new IllegalArgumentException(msg);
    }

    if (viewportHeight < 0) {
      String msg = Logging.getMessage("generic.HeightIsInvalid", viewportHeight);
      Logging.error(msg);
      throw new IllegalArgumentException(msg);
    }

    if (near <= 0 || near > far) {
      String msg = Logging.getMessage("generic.ClipDistancesAreInvalid", near, far);
      Logging.error(msg);
      throw new IllegalArgumentException(msg);
    }

    if (viewportWidth == 0) viewportWidth = 1;

    if (viewportHeight == 0) viewportHeight = 1;

    if (near == far) far = near + 1;

    double focalLength = 1d / horizontalFieldOfView.tanHalfAngle();
    double aspect = viewportHeight / viewportWidth;
    double lrLen = Math.sqrt(focalLength * focalLength + 1);
    double btLen = Math.sqrt(focalLength * focalLength + aspect * aspect);

    this.left.set(focalLength / lrLen, 0, -1d / lrLen, 0);
    this.right.set(-focalLength / lrLen, 0, -1d / lrLen, 0);
    this.bottom.set(0, focalLength / btLen, -aspect / btLen, 0);
    this.top.set(0, -focalLength / btLen, -aspect / btLen, 0);
    this.near.set(0, 0, -1, -near);
    this.far.set(0, 0, 1, far);

    return this;
  }