/**
     * Performs one line of sight calculation between the reference position and a specified grid
     * position.
     *
     * @param gridPosition the grid position.
     * @throws InterruptedException if the operation is interrupted.
     */
    protected void performIntersection(Position gridPosition) throws InterruptedException {
      // Intersect the line between this grid point and the selected position.
      Intersection[] intersections = this.terrain.intersect(this.referencePosition, gridPosition);
      if (intersections == null || intersections.length == 0) {
        // No intersection, so the line goes from the center to the grid point.
        this.sightLines.add(new Position[] {this.referencePosition, gridPosition});
        return;
      }

      // Only the first intersection is shown.
      Vec4 iPoint = intersections[0].getIntersectionPoint();
      Vec4 gPoint =
          terrain.getSurfacePoint(
              gridPosition.getLatitude(), gridPosition.getLongitude(), gridPosition.getAltitude());

      // Check to see whether the intersection is beyond the grid point.
      if (iPoint.distanceTo3(this.referencePoint) >= gPoint.distanceTo3(this.referencePoint)) {
        // Intersection is beyond the grid point; the line goes from the center to the grid point.
        this.addSightLine(this.referencePosition, gridPosition);
        return;
      }

      // Compute the position corresponding to the intersection.
      Position iPosition = this.terrain.getGlobe().computePositionFromPoint(iPoint);

      // The sight line goes from the user-selected position to the intersection position.
      this.addSightLine(this.referencePosition, new Position(iPosition, 0));

      // Keep track of the intersection positions.
      this.addIntersectionPosition(iPosition);

      this.updateProgress();
    }
예제 #2
0
  protected double computeLength(Globe globe, boolean followTerrain) {
    if (this.positions == null || this.positions.size() < 2) return -1;

    if (this.subdividedPositions == null) {
      // Subdivide path so as to have at least segments smaller then maxSegmentLenth. If follow
      // terrain,
      // subdivide so as to have at least lengthTerrainSamplingSteps segments, but no segments
      // shorter then
      // DEFAULT_MIN_SEGMENT_LENGTH either.
      double maxLength = this.maxSegmentLength;
      if (followTerrain) {
        // Recurse to compute overall path length not following terrain
        double pathLength = computeLength(globe, !followTerrain);
        // Determine segment length to have enough sampling points
        maxLength = pathLength / this.lengthTerrainSamplingSteps;
        maxLength =
            Math.min(Math.max(maxLength, DEFAULT_MIN_SEGMENT_LENGTH), getMaxSegmentLength());
      }
      this.subdividedPositions =
          subdividePositions(globe, this.positions, maxLength, followTerrain, this.pathType);
    }

    // Sum each segment length
    double length = 0;
    Vec4 p1 = globe.computePointFromPosition(this.subdividedPositions.get(0));
    for (int i = 1; i < subdividedPositions.size(); i++) {
      Vec4 p2 = globe.computePointFromPosition(this.subdividedPositions.get(i));
      length += p1.distanceTo3(p2);
      p1 = p2;
    }
    return length;
  }
예제 #3
0
    protected boolean areShapesIntersecting(Airspace a1, Airspace a2) {
      if ((a1 instanceof SphereAirspace) && (a2 instanceof SphereAirspace)) {
        SphereAirspace s1 = (SphereAirspace) a1;
        SphereAirspace s2 = (SphereAirspace) a2;

        LatLon location1 = s1.getLocation();
        LatLon location2 = s2.getLocation();
        double altitude1 = s1.getAltitudes()[0];
        double altitude2 = s2.getAltitudes()[0];
        boolean terrainConforming1 = s1.isTerrainConforming()[0];
        boolean terrainConforming2 = s2.isTerrainConforming()[0];

        // We have to compute the 3D coordinates of the sphere's center ourselves here.
        Vec4 p1 =
            terrainConforming1
                ? this.getSurfacePoint(location1, altitude1)
                : this.getPoint(location1, altitude1);
        Vec4 p2 =
            terrainConforming2
                ? this.getSurfacePoint(location2, altitude2)
                : this.getPoint(location2, altitude2);
        double r1 = s1.getRadius();
        double r2 = s2.getRadius();

        double d = p1.distanceTo3(p2);

        return d <= (r1 + r2);
      }

      return false;
    }
예제 #4
0
    protected void render(DrawContext dc, Vec4 p1, Vec4 p2, double radius) {
      // To compute the rotation of the cylinder axis to the orientation of the vector between the
      // two points,
      // this method performs the same operation as Vec4.axisAngle() but with a "v2" of <0, 0, 1>.

      // Compute rotation angle
      double length = p1.distanceTo3(p2);
      Vec4 u1 = new Vec4((p2.x - p1.x) / length, (p2.y - p1.y) / length, (p2.z - p1.z) / length);
      double angle = Math.acos(u1.z);

      // Compute the direction cosine factors that define the rotation axis
      double A = -u1.y;
      double B = u1.x;
      double L = Math.sqrt(A * A + B * B);

      GL gl = dc.getGL();

      // pushReferenceCenter performs the translation of the pipe's origin to point p1 and the
      // necessary
      // push/pop of the modelview stack. Otherwise we'd need to include a glPushMatrix and
      // gl.glTranslated(p1.x, p1.y, p1.z) above the rotation, and a corresponding glPopMatrix after
      // the
      // call to glCallIst.
      dc.getView().pushReferenceCenter(dc, p1);
      gl.glRotated(angle * TO_DEGREES, A / L, B / L, 0);
      gl.glScaled(
          radius, radius, length / 2); // length / 2 because cylinder is created with length 2
      dc.getGL().glCallList(this.glListId);
      dc.getView().popReferenceCenter(dc);
    }
  protected void requestTile(DrawContext dc, Tile tile) {
    Vec4 centroid = dc.getGlobe().computePointFromPosition(tile.getSector().getCentroid(), 0);
    if (this.getReferencePoint() != null)
      tile.setPriority(centroid.distanceTo3(this.getReferencePoint()));

    RequestTask task = new RequestTask(tile, this);
    this.getRequestQ().add(task);
  }
  protected static boolean isNameVisible(
      DrawContext dc, PlaceNameService service, Position namePosition) {
    double elevation = dc.getVerticalExaggeration() * namePosition.getElevation();
    Vec4 namePoint =
        dc.getGlobe()
            .computePointFromPosition(
                namePosition.getLatitude(), namePosition.getLongitude(), elevation);
    Vec4 eyeVec = dc.getView().getEyePoint();

    double dist = eyeVec.distanceTo3(namePoint);
    return dist >= service.getMinDisplayDistance() && dist <= service.getMaxDisplayDistance();
  }
  public void lookAt(Position lookAtPos, long timeToMove) {
    BasicFlyView view = (BasicFlyView) this.getView();
    Vec4 lookDirection;
    double distanceToSurface;
    Vec4 currentLookAtPt = view.getCenterPoint();
    Position newPosition;
    if (currentLookAtPt == null) {
      view.getGlobe().computePointFromPosition(lookAtPos);
      double elevAtLookAtPos =
          view.getGlobe().getElevation(lookAtPos.getLatitude(), lookAtPos.getLongitude());
      newPosition = new Position(lookAtPos, elevAtLookAtPos + 10000);
    } else {
      Vec4 currentEyePt = view.getEyePoint();
      distanceToSurface = currentEyePt.distanceTo3(currentLookAtPt);
      lookDirection = currentLookAtPt.subtract3(currentEyePt).normalize3();
      Vec4 newLookAtPt = view.getGlobe().computePointFromPosition(lookAtPos);
      Vec4 flyToPoint = newLookAtPt.add3(lookDirection.multiply3(-distanceToSurface));
      newPosition = view.getGlobe().computePositionFromPoint(flyToPoint);
    }

    ViewUtil.ViewState viewCoords = view.getViewState(newPosition, lookAtPos);

    FlyToFlyViewAnimator panAnimator =
        FlyToFlyViewAnimator.createFlyToFlyViewAnimator(
            view,
            view.getEyePosition(),
            newPosition,
            view.getHeading(),
            viewCoords.getHeading(),
            view.getPitch(),
            viewCoords.getPitch(),
            view.getEyePosition().getElevation(),
            viewCoords.getPosition().getElevation(),
            timeToMove,
            WorldWind.ABSOLUTE);

    this.gotoAnimControl.put(VIEW_ANIM_PAN, panAnimator);
    this.getView().firePropertyChange(AVKey.VIEW, null, this.getView());

    view.firePropertyChange(AVKey.VIEW, null, view);
  }
예제 #8
0
  /**
   * Add a vertex to the polygon's outer boundary.
   *
   * @param mousePoint the point at which the mouse was clicked. The new vertex will be placed as
   *     near as possible to this point, at the elevation of the polygon.
   */
  protected void addVertex(Point mousePoint) {
    // Try to find the edge that is closest to a ray passing through the screen point. We're trying
    // to determine
    // the user's intent as to which edge a new two control points should be added to.

    Line ray = this.wwd.getView().computeRayFromScreenPoint(mousePoint.getX(), mousePoint.getY());
    Vec4 pickPoint = this.intersectPolygonAltitudeAt(ray);

    double nearestDistance = Double.MAX_VALUE;
    int newVertexIndex = 0;

    // Loop through the control points and determine which edge is closest to the pick point
    for (int i = 0; i < this.controlPoints.size(); i++) {
      ControlPointMarker thisMarker = (ControlPointMarker) this.controlPoints.get(i);
      ControlPointMarker nextMarker =
          (ControlPointMarker) this.controlPoints.get((i + 1) % this.controlPoints.size());

      Vec4 pointOnEdge =
          AirspaceEditorUtil.nearestPointOnSegment(thisMarker.point, nextMarker.point, pickPoint);
      if (!AirspaceEditorUtil.isPointBehindLineOrigin(ray, pointOnEdge)) {
        double d = pointOnEdge.distanceTo3(pickPoint);
        if (d < nearestDistance) {
          newVertexIndex = i + 1;
          nearestDistance = d;
        }
      }
    }

    Position newPosition = this.wwd.getModel().getGlobe().computePositionFromPoint(pickPoint);

    // Copy the outer boundary list
    ArrayList<Position> positionList = new ArrayList<Position>(this.controlPoints.size());
    for (LatLon position : this.getPolygon().getOuterBoundary()) {
      positionList.add((Position) position);
    }

    // Add the new vertex
    positionList.add(newVertexIndex, newPosition);

    this.getPolygon().setOuterBoundary(positionList);
  }
  /**
   * 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);
    }
  }
 protected double computeHorizonDistance(Vec4 eyePoint) {
   double horizon = 0;
   // Compute largest distance to flat globe 'corners'.
   if (this.globe != null && eyePoint != null) {
     double dist = 0;
     Vec4 p;
     // Use max distance to six points around the map
     p = this.globe.computePointFromPosition(Angle.POS90, Angle.NEG180, 0); // NW
     dist = Math.max(dist, eyePoint.distanceTo3(p));
     p = this.globe.computePointFromPosition(Angle.POS90, Angle.POS180, 0); // NE
     dist = Math.max(dist, eyePoint.distanceTo3(p));
     p = this.globe.computePointFromPosition(Angle.NEG90, Angle.NEG180, 0); // SW
     dist = Math.max(dist, eyePoint.distanceTo3(p));
     p = this.globe.computePointFromPosition(Angle.NEG90, Angle.POS180, 0); // SE
     dist = Math.max(dist, eyePoint.distanceTo3(p));
     p = this.globe.computePointFromPosition(Angle.ZERO, Angle.POS180, 0); // E
     dist = Math.max(dist, eyePoint.distanceTo3(p));
     p = this.globe.computePointFromPosition(Angle.ZERO, Angle.NEG180, 0); // W
     dist = Math.max(dist, eyePoint.distanceTo3(p));
     horizon = dist;
   }
   return horizon;
 }
  protected void onMoveTo(
      Position focalPosition,
      ViewInputAttributes.DeviceAttributes deviceAttributes,
      ViewInputAttributes.ActionAttributes actionAttribs) {
    BasicFlyView view = (BasicFlyView) this.getView();
    if (view == null) // include this test to ensure any derived implementation performs it
    {
      return;
    }

    // We're treating a speed parameter as smoothing here. A greater speed results in greater
    // smoothing and
    // slower response. Therefore the min speed used at lower altitudes ought to be *greater* than
    // the max
    // speed used at higher altitudes.
    double smoothing = this.getScaleValueElevation(deviceAttributes, actionAttribs);
    if (!actionAttribs.isEnableSmoothing()) smoothing = 0.0;

    Vec4 currentLookAtPt = view.getCenterPoint();
    if (currentLookAtPt == null) {
      currentLookAtPt = view.getGlobe().computePointFromPosition(focalPosition);
    }

    Vec4 currentEyePt = view.getEyePoint();
    double distanceToSurface = currentEyePt.distanceTo3(currentLookAtPt);
    Vec4 lookDirection = currentEyePt.subtract3(currentLookAtPt).normalize3();
    Vec4 newLookAtPt = view.getGlobe().computePointFromPosition(focalPosition);
    Vec4 flyToPoint = newLookAtPt.add3(lookDirection.multiply3(distanceToSurface));

    Position newPosition = view.getGlobe().computePositionFromPoint(flyToPoint);

    ViewUtil.ViewState viewCoords = view.getViewState(newPosition, focalPosition);

    this.stopAnimators();
    this.gotoAnimControl.put(
        VIEW_ANIM_HEADING,
        new RotateToAngleAnimator(
            view.getHeading(),
            viewCoords.getHeading(),
            smoothing,
            ViewPropertyAccessor.createHeadingAccessor(view)));
    this.gotoAnimControl.put(
        VIEW_ANIM_PITCH,
        new RotateToAngleAnimator(
            view.getPitch(),
            viewCoords.getPitch(),
            smoothing,
            ViewPropertyAccessor.createPitchAccessor(view)));

    double elevation =
        ((FlyViewLimits) view.getViewPropertyLimits())
            .limitEyeElevation(newPosition, view.getGlobe());
    if (elevation != newPosition.getElevation()) {
      newPosition = new Position(newPosition, elevation);
    }
    this.gotoAnimControl.put(
        VIEW_ANIM_POSITION,
        new MoveToPositionAnimator(
            view.getEyePosition(),
            newPosition,
            smoothing,
            ViewPropertyAccessor.createEyePositionAccessor(view)));

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