private void makeRadialWallTerrainConformant(
      DrawContext dc,
      int pillars,
      int stacks,
      float[] verts,
      double[] altitudes,
      boolean[] terrainConformant,
      Vec4 referenceCenter) {
    Globe globe = dc.getGlobe();
    Matrix transform = this.computeTransform(dc.getGlobe(), dc.getVerticalExaggeration());

    for (int p = 0; p <= pillars; p++) {
      int index = p;
      index = 3 * index;
      Vec4 vec = new Vec4(verts[index], verts[index + 1], verts[index + 2]);
      vec = vec.transformBy4(transform);
      Position pos = globe.computePositionFromPoint(vec);

      for (int s = 0; s <= stacks; s++) {
        double elevation = altitudes[s];
        if (terrainConformant[s])
          elevation += this.computeElevationAt(dc, pos.getLatitude(), pos.getLongitude());
        vec = globe.computePointFromPosition(pos.getLatitude(), pos.getLongitude(), elevation);

        index = p + s * (pillars + 1);
        index = 3 * index;
        verts[index] = (float) (vec.x - referenceCenter.x);
        verts[index + 1] = (float) (vec.y - referenceCenter.y);
        verts[index + 2] = (float) (vec.z - referenceCenter.z);
      }
    }
  }
    /**
     * 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();
    }
  private void makePartialCylinderTerrainConformant(
      DrawContext dc,
      int slices,
      int stacks,
      float[] verts,
      double[] altitudes,
      boolean[] terrainConformant,
      Vec4 referenceCenter) {
    Globe globe = dc.getGlobe();
    Matrix transform = this.computeTransform(dc.getGlobe(), dc.getVerticalExaggeration());

    for (int i = 0; i <= slices; i++) {
      int index = i * (stacks + 1);
      index = 3 * index;
      Vec4 vec = new Vec4(verts[index], verts[index + 1], verts[index + 2]);
      vec = vec.transformBy4(transform);
      Position p = globe.computePositionFromPoint(vec);

      for (int j = 0; j <= stacks; j++) {
        double elevation = altitudes[j];
        if (terrainConformant[j])
          elevation += this.computeElevationAt(dc, p.getLatitude(), p.getLongitude());
        vec = globe.computePointFromPosition(p.getLatitude(), p.getLongitude(), elevation);

        index = j + i * (stacks + 1);
        index = 3 * index;
        verts[index] = (float) (vec.x - referenceCenter.x);
        verts[index + 1] = (float) (vec.y - referenceCenter.y);
        verts[index + 2] = (float) (vec.z - referenceCenter.z);
      }
    }
  }
  /**
   * 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);
  }
  @Override
  protected List<Vec4> computeMinimalGeometry(Globe globe, double verticalExaggeration) {
    double[] angles = this.computeAngles();
    // Angles are equal, fall back to building a closed cylinder.
    if (angles == null) return super.computeMinimalGeometry(globe, verticalExaggeration);

    double[] radii = this.getRadii();
    Matrix transform = this.computeTransform(globe, verticalExaggeration);

    GeometryBuilder gb = this.getGeometryBuilder();
    int count = gb.getPartialDiskVertexCount(MINIMAL_GEOMETRY_SLICES, MINIMAL_GEOMETRY_LOOPS);
    int numCoords = 3 * count;
    float[] verts = new float[numCoords];
    gb.makePartialDiskVertices(
        (float) radii[0],
        (float) radii[1], // Inner radius, outer radius.
        MINIMAL_GEOMETRY_SLICES,
        MINIMAL_GEOMETRY_LOOPS, // Slices, loops,
        (float) angles[0],
        (float) angles[2], // Start angle, sweep angle.
        verts);

    List<LatLon> locations = new ArrayList<LatLon>();
    for (int i = 0; i < numCoords; i += 3) {
      Vec4 v = new Vec4(verts[i], verts[i + 1], verts[i + 2]);
      v = v.transformBy4(transform);
      locations.add(globe.computePositionFromPoint(v));
    }

    ArrayList<Vec4> points = new ArrayList<Vec4>();
    this.makeExtremePoints(globe, verticalExaggeration, locations, points);

    return points;
  }
  private void makePartialDiskTerrainConformant(
      DrawContext dc,
      int numCoords,
      float[] verts,
      double altitude,
      boolean terrainConformant,
      Vec4 referenceCenter) {
    Globe globe = dc.getGlobe();
    Matrix transform = this.computeTransform(dc.getGlobe(), dc.getVerticalExaggeration());

    for (int i = 0; i < numCoords; i += 3) {
      Vec4 vec = new Vec4(verts[i], verts[i + 1], verts[i + 2]);
      vec = vec.transformBy4(transform);
      Position p = globe.computePositionFromPoint(vec);

      double elevation = altitude;
      if (terrainConformant)
        elevation += this.computeElevationAt(dc, p.getLatitude(), p.getLongitude());

      vec = globe.computePointFromPosition(p.getLatitude(), p.getLongitude(), elevation);
      verts[i] = (float) (vec.x - referenceCenter.x);
      verts[i + 1] = (float) (vec.y - referenceCenter.y);
      verts[i + 2] = (float) (vec.z - referenceCenter.z);
    }
  }
Beispiel #7
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;
  }
  protected void assembleHeightControlPoints() {
    if (this.controlPoints.size() < 2) return;

    // Add one control point for the height between the first and second vertices.
    // TODO: ensure that this control point is visible
    Position firstVertex = this.controlPoints.get(0).getPosition();
    Position secondVertex = this.controlPoints.get(1).getPosition();

    Globe globe = this.wwd.getModel().getGlobe();

    // Get cartesian points for the vertices
    Vec4 firstPoint = globe.computePointFromPosition(firstVertex);
    Vec4 secondPoint = globe.computePointFromPosition(secondVertex);

    // Find the midpoint of the line segment that connects the vertices
    Vec4 halfwayPoint = firstPoint.add3(secondPoint).divide3(2.0);

    Position halfwayPosition = globe.computePositionFromPoint(halfwayPoint);

    this.controlPoints.add(
        new ControlPointMarker(
            CHANGE_HEIGHT_ACTION,
            halfwayPosition,
            halfwayPoint,
            this.heightControlAttributes,
            this.controlPoints.size()));
  }
    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;
    }
  protected void makeTessellatedLocations(
      Globe globe, int subdivisions, List<LatLon> locations, List<LatLon> tessellatedLocations) {
    ArrayList<Vec4> points = new ArrayList<Vec4>();
    for (LatLon ll : locations) {
      points.add(globe.computePointFromLocation(ll));
    }

    //noinspection StringEquality
    if (WWMath.computeWindingOrderOfLocations(locations) != AVKey.COUNTER_CLOCKWISE)
      Collections.reverse(locations);

    Vec4 centerPoint = Vec4.computeAveragePoint(points);
    Vec4 surfaceNormal = globe.computeSurfaceNormalAtPoint(centerPoint);

    int numPoints = points.size();
    float[] coords = new float[3 * numPoints];
    for (int i = 0; i < numPoints; i++) {
      points.get(i).toFloatArray(coords, 3 * i, 3);
    }

    GeometryBuilder gb = new GeometryBuilder();
    GeometryBuilder.IndexedTriangleArray tessellatedPoints =
        gb.tessellatePolygon(0, numPoints, coords, surfaceNormal);

    for (int i = 0; i < subdivisions; i++) {
      gb.subdivideIndexedTriangleArray(tessellatedPoints);
    }

    for (int i = 0; i < tessellatedPoints.getVertexCount(); i++) {
      Vec4 v = Vec4.fromFloatArray(tessellatedPoints.getVertices(), 3 * i, 3);
      tessellatedLocations.add(globe.computePositionFromPoint(v));
    }
  }
  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 void assembleVertexControlPoints(DrawContext dc) {
    Terrain terrain = dc.getTerrain();
    ExtrudedPolygon polygon = this.getPolygon();

    Position refPos = polygon.getReferencePosition();
    Vec4 refPoint = terrain.getSurfacePoint(refPos.getLatitude(), refPos.getLongitude(), 0);

    int altitudeMode = polygon.getAltitudeMode();
    double height = polygon.getHeight();

    Vec4 vaa = null;
    double vaaLength = 0; // used to compute independent length of each cap vertex
    double vaLength = 0;

    int i = 0;
    for (LatLon location : polygon.getOuterBoundary()) {
      Vec4 vert;

      // Compute the top/cap point.
      if (altitudeMode == WorldWind.CONSTANT || !(location instanceof Position)) {
        if (vaa == null) {
          // Compute the vector lengths of the top and bottom points at the reference position.
          vaa = refPoint.multiply3(height / refPoint.getLength3());
          vaaLength = vaa.getLength3();
          vaLength = refPoint.getLength3();
        }

        // Compute the bottom point, which is on the terrain.
        vert = terrain.getSurfacePoint(location.getLatitude(), location.getLongitude(), 0);

        double delta = vaLength - vert.dot3(refPoint) / vaLength;
        vert = vert.add3(vaa.multiply3(1d + delta / vaaLength));
      } else if (altitudeMode == WorldWind.RELATIVE_TO_GROUND) {
        vert =
            terrain.getSurfacePoint(
                location.getLatitude(),
                location.getLongitude(),
                ((Position) location).getAltitude());
      } else // WorldWind.ABSOLUTE
      {
        vert =
            terrain
                .getGlobe()
                .computePointFromPosition(
                    location.getLatitude(),
                    location.getLongitude(),
                    ((Position) location).getAltitude() * terrain.getVerticalExaggeration());
      }

      Position vertexPosition = this.wwd.getModel().getGlobe().computePositionFromPoint(vert);

      this.controlPoints.add(
          new ControlPointMarker(
              MOVE_VERTEX_ACTION, vertexPosition, vert, this.vertexControlAttributes, i));
      i++;
    }
  }
  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();
  }
  protected void onHorizontalTranslateRel(
      Angle forwardChange, Angle sideChange, ViewInputAttributes.ActionAttributes actionAttribs) {
    View view = this.getView();
    if (view == null) // include this test to ensure any derived implementation performs it
    {
      return;
    }

    if (forwardChange.equals(Angle.ZERO) && sideChange.equals(Angle.ZERO)) {
      return;
    }

    if (view instanceof BasicFlyView) {

      Vec4 forward = view.getForwardVector();
      Vec4 up = view.getUpVector();
      Vec4 side = forward.transformBy3(Matrix.fromAxisAngle(Angle.fromDegrees(90), up));

      forward = forward.multiply3(forwardChange.getDegrees());
      side = side.multiply3(sideChange.getDegrees());
      Vec4 eyePoint = view.getEyePoint();
      eyePoint = eyePoint.add3(forward.add3(side));
      Position newPosition = view.getGlobe().computePositionFromPoint(eyePoint);

      this.setEyePosition(this.uiAnimControl, view, newPosition, actionAttribs);
      view.firePropertyChange(AVKey.VIEW, null, view);
    }
  }
  protected Matrix transformModelView(Matrix modelView, IDelegateView view) {
    if (disableHeadTransform) {
      return modelView;
    }

    Vec4 translation = RiftUtils.toVec4(eyePoses[eye].Position);
    double translationScale = getHeadTranslationScale(view);
    Quaternion rotation = RiftUtils.toQuaternion(eyePoses[eye].Orientation);

    Matrix translationM = Matrix.fromTranslation(translation.multiply3(-translationScale));
    Matrix rotationM = Matrix.fromQuaternion(rotation.getInverse());

    return rotationM.multiply(translationM.multiply(modelView));
  }
Beispiel #16
0
    private float[] vectorToArray(Vec4... vectors) {
      double[] temp = new double[4];

      int counter = 0;
      float[] vf = new float[vectors.length * 4];
      for (Vec4 v : vectors) {
        temp = v.toArray4(temp, 0);

        for (int i = 0; i < temp.length; i++) {
          vf[counter] = (float) temp[i];
          counter++;
        }
      }
      return vf;
    }
  private void makeCap(
      DrawContext dc,
      GeometryBuilder.IndexedTriangleArray ita,
      double altitude,
      boolean terrainConformant,
      int orientation,
      Matrix locationTransform,
      Vec4 referenceCenter,
      int indexPos,
      int[] indices,
      int vertexPos,
      float[] vertices,
      float[] normals) {
    GeometryBuilder gb = this.getGeometryBuilder();
    Globe globe = dc.getGlobe();

    int indexCount = ita.getIndexCount();
    int vertexCount = ita.getVertexCount();
    int[] locationIndices = ita.getIndices();
    float[] locationVerts = ita.getVertices();

    this.copyIndexArray(
        indexCount,
        (orientation == GeometryBuilder.INSIDE),
        locationIndices,
        vertexPos,
        indexPos,
        indices);

    for (int i = 0; i < vertexCount; i++) {
      int index = 3 * i;
      Vec4 vec = new Vec4(locationVerts[index], locationVerts[index + 1], locationVerts[index + 2]);
      vec = vec.transformBy4(locationTransform);

      Position pos = globe.computePositionFromPoint(vec);
      vec =
          this.computePointFromPosition(
              dc, pos.getLatitude(), pos.getLongitude(), altitude, terrainConformant);

      index = 3 * (vertexPos + i);
      vertices[index] = (float) (vec.x - referenceCenter.x);
      vertices[index + 1] = (float) (vec.y - referenceCenter.y);
      vertices[index + 2] = (float) (vec.z - referenceCenter.z);
    }

    gb.makeIndexedTriangleArrayNormals(
        indexPos, indexCount, indices, vertexPos, vertexCount, vertices, normals);
  }
  private void makeSectionVertices(
      DrawContext dc,
      int locationPos,
      float[] locations,
      double[] altitude,
      boolean[] terrainConformant,
      int subdivisions,
      Matrix locationTransform,
      Vec4 referenceCenter,
      int vertexPos,
      float[] vertices) {
    GeometryBuilder gb = this.getGeometryBuilder();
    int numPoints = gb.getSubdivisionPointsVertexCount(subdivisions);

    Globe globe = dc.getGlobe();
    int index1 = 3 * locationPos;
    int index2 = 3 * (locationPos + 1);

    float[] locationVerts = new float[3 * numPoints];
    gb.makeSubdivisionPoints(
        locations[index1],
        locations[index1 + 1],
        locations[index1 + 2],
        locations[index2],
        locations[index2 + 1],
        locations[index2 + 2],
        subdivisions,
        locationVerts);

    for (int i = 0; i < numPoints; i++) {
      int index = 3 * i;
      Vec4 vec = new Vec4(locationVerts[index], locationVerts[index + 1], locationVerts[index + 2]);
      vec = vec.transformBy4(locationTransform);
      Position pos = globe.computePositionFromPoint(vec);

      for (int j = 0; j < 2; j++) {
        vec =
            this.computePointFromPosition(
                dc, pos.getLatitude(), pos.getLongitude(), altitude[j], terrainConformant[j]);

        index = 2 * i + j;
        index = 3 * (vertexPos + index);
        vertices[index] = (float) (vec.x - referenceCenter.x);
        vertices[index + 1] = (float) (vec.y - referenceCenter.y);
        vertices[index + 2] = (float) (vec.z - referenceCenter.z);
      }
    }
  }
Beispiel #19
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);
    }
Beispiel #20
0
  // Draw the scale label
  private void drawLabel(DrawContext dc, String text, Vec4 screenPoint) {
    TextRenderer textRenderer =
        OGLTextRenderer.getOrCreateTextRenderer(dc.getTextRendererCache(), this.defaultFont);

    Rectangle2D nameBound = textRenderer.getBounds(text);
    int x = (int) (screenPoint.x() - nameBound.getWidth() / 2d);
    int y = (int) screenPoint.y();

    textRenderer.begin3DRendering();

    textRenderer.setColor(this.getBackgroundColor(this.color));
    textRenderer.draw(text, x + 1, y - 1);
    textRenderer.setColor(this.color);
    textRenderer.draw(text, x, y);

    textRenderer.end3DRendering();
  }
Beispiel #21
0
  protected void addToolTip(DrawContext dc, WWIcon icon, Vec4 iconPoint) {
    if (icon.getToolTipFont() == null && icon.getToolTipText() == null) return;

    Vec4 screenPoint = dc.getView().project(iconPoint);
    if (screenPoint == null) return;

    if (icon.getToolTipOffset() != null) screenPoint = screenPoint.add3(icon.getToolTipOffset());

    OrderedText tip =
        new OrderedText(
            icon.getToolTipText(),
            icon.getToolTipFont(),
            screenPoint,
            icon.getToolTipTextColor(),
            0d);
    dc.addOrderedRenderable(tip);
  }
  /**
   * 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);
  }
  protected Extent computeExtent(Globe globe, double verticalExaggeration) {
    List<Vec4> points = this.computeMinimalGeometry(globe, verticalExaggeration);
    if (points == null || points.isEmpty()) return null;

    // Add a point at the center of this polygon to the points used to compute its extent. The
    // center point captures
    // the curvature of the globe when the polygon's minimal geometry only contain any points near
    // the polygon's
    // edges.
    Vec4 centerPoint = Vec4.computeAveragePoint(points);
    LatLon centerLocation = globe.computePositionFromPoint(centerPoint);
    this.makeExtremePoints(globe, verticalExaggeration, Arrays.asList(centerLocation), points);

    return Box.computeBoundingBox(points);
  }
  /**
   * Returns the vector element at the specified position, as a {@link Vec4}. This buffer's logical
   * vector size must be either 2, 3 or 4.
   *
   * @param position the logical vector position.
   * @return the vector at the specified vector position.
   * @throws IllegalArgumentException if the position is out of range, or if this buffer cannot
   *     store a Vec4.
   */
  public Vec4 getVector(int position) {
    if (position < 0 || position >= this.getSize()) {
      String message =
          Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    if (this.coordsPerVec != 2 && this.coordsPerVec != 3 && this.coordsPerVec != 4) {
      String message = Logging.getMessage("generic.BufferIncompatible", this);
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    double[] compArray = new double[this.coordsPerVec];
    this.get(position, compArray);
    return Vec4.fromDoubleArray(compArray, 0, this.coordsPerVec);
  }
  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);
  }
  /**
   * Sets the vector element at the specified position, as a Vec4. This buffer's logical vector size
   * must be either 2, 3 or 4.
   *
   * @param position the logical vector position.
   * @param vec the vector to set.
   * @throws IllegalArgumentException if the position is out of range, if the vector is null, or if
   *     this buffer cannot store a Vec4.
   */
  public void putVector(int position, Vec4 vec) {
    if (position < 0 || position >= this.getSize()) {
      String message =
          Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

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

    if (this.coordsPerVec != 2 && this.coordsPerVec != 3 && this.coordsPerVec != 4) {
      String message = Logging.getMessage("generic.BufferIncompatible", this);
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    double[] compArray = new double[this.coordsPerVec];
    vec.toDoubleArray(compArray, 0, this.coordsPerVec);
    this.put(position, compArray);
  }
Beispiel #27
0
 /**
  * Computes the lat/lon of the pickPoint over the world map
  *
  * @param dc the current <code>DrawContext</code>
  * @param locationSW the screen location of the bottom left corner of the map
  * @param mapSize the world map screen dimension in pixels
  * @return the picked Position
  */
 protected Position computePickPosition(DrawContext dc, Vec4 locationSW, Dimension mapSize) {
   Position pickPosition = null;
   Point pickPoint = dc.getPickPoint();
   if (pickPoint != null) {
     Rectangle viewport = dc.getView().getViewport();
     // Check if pickpoint is inside the map
     if (pickPoint.getX() >= locationSW.getX()
         && pickPoint.getX() < locationSW.getX() + mapSize.width
         && viewport.height - pickPoint.getY() >= locationSW.getY()
         && viewport.height - pickPoint.getY() < locationSW.getY() + mapSize.height) {
       double lon = (pickPoint.getX() - locationSW.getX()) / mapSize.width * 360 - 180;
       double lat =
           (viewport.height - pickPoint.getY() - locationSW.getY()) / mapSize.height * 180 - 90;
       double pickAltitude = 1000e3;
       pickPosition = new Position(Angle.fromDegrees(lat), Angle.fromDegrees(lon), pickAltitude);
     }
   }
   return pickPosition;
 }
 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;
 }
  /**
   * 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);
  }