private void adjustDateLineCrossingPoints() {
      ArrayList<LatLon> corners = new ArrayList<LatLon>(Arrays.asList(sw, se, nw, ne));
      if (!LatLon.locationsCrossDateLine(corners)) return;

      double lonSign = 0;
      for (LatLon corner : corners) {
        if (Math.abs(corner.getLongitude().degrees) != 180)
          lonSign = Math.signum(corner.getLongitude().degrees);
      }

      if (lonSign == 0) return;

      if (Math.abs(sw.getLongitude().degrees) == 180
          && Math.signum(sw.getLongitude().degrees) != lonSign)
        sw = new Position(sw.getLatitude(), sw.getLongitude().multiply(-1), sw.getElevation());
      if (Math.abs(se.getLongitude().degrees) == 180
          && Math.signum(se.getLongitude().degrees) != lonSign)
        se = new Position(se.getLatitude(), se.getLongitude().multiply(-1), se.getElevation());
      if (Math.abs(nw.getLongitude().degrees) == 180
          && Math.signum(nw.getLongitude().degrees) != lonSign)
        nw = new Position(nw.getLatitude(), nw.getLongitude().multiply(-1), nw.getElevation());
      if (Math.abs(ne.getLongitude().degrees) == 180
          && Math.signum(ne.getLongitude().degrees) != lonSign)
        ne = new Position(ne.getLatitude(), ne.getLongitude().multiply(-1), ne.getElevation());
    }
  protected static boolean isTileVisible(
      DrawContext dc, Tile tile, double minDistanceSquared, double maxDistanceSquared) {
    if (!tile.getSector().intersects(dc.getVisibleSector())) return false;

    View view = dc.getView();
    Position eyePos = view.getEyePosition();
    if (eyePos == null) return false;

    Angle lat =
        clampAngle(
            eyePos.getLatitude(),
            tile.getSector().getMinLatitude(),
            tile.getSector().getMaxLatitude());
    Angle lon =
        clampAngle(
            eyePos.getLongitude(),
            tile.getSector().getMinLongitude(),
            tile.getSector().getMaxLongitude());
    Vec4 p = dc.getGlobe().computePointFromPosition(lat, lon, 0d);
    double distSquared = dc.getView().getEyePoint().distanceToSquared3(p);
    //noinspection RedundantIfStatement
    if (minDistanceSquared > distSquared || maxDistanceSquared < distSquared) return false;

    return true;
  }
  protected int determineAdjustmentSide(Movable dragObject, double factor) {
    if (dragObject instanceof SurfaceSector) {
      SurfaceSector quad = (SurfaceSector) dragObject;
      Sector s = quad.getSector(); // TODO: go over all sectors
      Position p = this.getWwd().getCurrentPosition();

      if (p == null) {
        return NONE;
      }

      double dN = abs(s.getMaxLatitude().subtract(p.getLatitude()).degrees);
      double dS = abs(s.getMinLatitude().subtract(p.getLatitude()).degrees);
      double dW = abs(s.getMinLongitude().subtract(p.getLongitude()).degrees);
      double dE = abs(s.getMaxLongitude().subtract(p.getLongitude()).degrees);

      double sLat = factor * s.getDeltaLatDegrees();
      double sLon = factor * s.getDeltaLonDegrees();

      if (dN < sLat && dW < sLon) return NORTHWEST;
      if (dN < sLat && dE < sLon) return NORTHEAST;
      if (dS < sLat && dW < sLon) return SOUTHWEST;
      if (dS < sLat && dE < sLon) return SOUTHEAST;
      if (dN < sLat) return NORTH;
      if (dS < sLat) return SOUTH;
      if (dW < sLon) return WEST;
      if (dE < sLon) return EAST;
    }

    return NONE;
  }
  protected void movePolygon(Point previousMousePoint, Point mousePoint) {
    // Intersect a ray through each mouse point, with a geoid passing through the reference
    // elevation.
    // If either ray fails to intersect the geoid, then ignore this event. Use the difference
    // between the two
    // intersected positions to move the control point's location.

    View view = this.wwd.getView();
    Globe globe = this.wwd.getModel().getGlobe();

    Position refPos = this.polygon.getReferencePosition();
    if (refPos == null) return;

    Line ray = view.computeRayFromScreenPoint(mousePoint.getX(), mousePoint.getY());
    Line previousRay =
        view.computeRayFromScreenPoint(previousMousePoint.getX(), previousMousePoint.getY());

    Vec4 vec = AirspaceEditorUtil.intersectGlobeAt(this.wwd, refPos.getElevation(), ray);
    Vec4 previousVec =
        AirspaceEditorUtil.intersectGlobeAt(this.wwd, refPos.getElevation(), previousRay);

    if (vec == null || previousVec == null) {
      return;
    }

    Position pos = globe.computePositionFromPoint(vec);
    Position previousPos = globe.computePositionFromPoint(previousVec);
    LatLon change = pos.subtract(previousPos);

    this.polygon.move(new Position(change.getLatitude(), change.getLongitude(), 0.0));
  }
  protected void dragWholeShape(DragSelectEvent dragEvent, Movable dragObject) {
    View view = getWwd().getView();
    EllipsoidalGlobe globe = (EllipsoidalGlobe) getWwd().getModel().getGlobe();

    // Compute ref-point position in screen coordinates.
    Position refPos = dragObject.getReferencePosition();
    if (refPos == null) return;

    Vec4 refPoint = globe.computePointFromPosition(refPos);
    Vec4 screenRefPoint = view.project(refPoint);

    // Compute screen-coord delta since last event.
    int dx = dragEvent.getPickPoint().x - dragEvent.getPreviousPickPoint().x;
    int dy = dragEvent.getPickPoint().y - dragEvent.getPreviousPickPoint().y;

    // Find intersection of screen coord ref-point with globe.
    double x = screenRefPoint.x + dx;
    double y =
        dragEvent.getMouseEvent().getComponent().getSize().height - screenRefPoint.y + dy - 1;
    Line ray = view.computeRayFromScreenPoint(x, y);
    Intersection inters[] = globe.intersect(ray, refPos.getElevation());

    if (inters != null) {
      // Intersection with globe. Move reference point to the intersection point.
      Position p = globe.computePositionFromPoint(inters[0].getIntersectionPoint());
      dragObject.moveTo(p);
    }
  }
    /**
     * 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();
    }
  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++;
    }
  }
    private void fillPointsPanel() {
      int i = 0;
      for (Position pos : lineBuilder.getLine().getPositions()) {
        if (i == this.pointLabels.length) break;

        String las = String.format("Lat %7.4f\u00B0", pos.getLatitude().getDegrees());
        String los = String.format("Lon %7.4f\u00B0", pos.getLongitude().getDegrees());
        pointLabels[i++].setText(las + "  " + los);
      }
      for (; i < this.pointLabels.length; i++) pointLabels[i++].setText("");
    }
  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();
  }
  /** {@inheritDoc} */
  @Override
  public void moveTo(Position position) {
    Position delta;
    Position ref1 = this.path.getReferencePosition();
    Position ref2 = this.path2.getReferencePosition();
    if (ref1 != null && ref2 != null) delta = ref2.subtract(ref1);
    else delta = Position.ZERO;

    // Move the first path
    super.moveTo(position);

    // Move the second path
    this.path2.moveTo(position.add(delta));
  }
  protected Vec4 computeReferencePoint(DrawContext dc) {
    if (dc.getViewportCenterPosition() != null)
      return dc.getGlobe().computePointFromPosition(dc.getViewportCenterPosition());

    java.awt.geom.Rectangle2D viewport = dc.getView().getViewport();
    int x = (int) viewport.getWidth() / 2;
    for (int y = (int) (0.5 * viewport.getHeight()); y >= 0; y--) {
      Position pos = dc.getView().computePositionFromScreenPoint(x, y);
      if (pos == null) continue;

      return dc.getGlobe().computePointFromPosition(pos.getLatitude(), pos.getLongitude(), 0d);
    }

    return null;
  }
Beispiel #12
0
  /**
   * Compute the lat/lon position of the view center
   *
   * @param dc the current DrawContext
   * @param view the current View
   * @return the ground position of the view center or null
   */
  protected Position computeGroundPosition(DrawContext dc, View view) {
    if (view == null) return null;

    Position groundPos =
        view.computePositionFromScreenPoint(
            view.getViewport().getWidth() / 2, view.getViewport().getHeight() / 2);
    if (groundPos == null) return null;

    double elevation =
        dc.getGlobe().getElevation(groundPos.getLatitude(), groundPos.getLongitude());
    return new Position(
        groundPos.getLatitude(),
        groundPos.getLongitude(),
        elevation * dc.getVerticalExaggeration());
  }
 public void computeZone(DrawContext dc) {
   try {
     Position centerPos = ((OrbitView) dc.getView()).getCenterPosition();
     if (centerPos != null) {
       if (centerPos.latitude.degrees <= UTM_MAX_LATITUDE
           && centerPos.latitude.degrees >= UTM_MIN_LATITUDE) {
         UTMCoord UTM =
             UTMCoord.fromLatLon(
                 centerPos.getLatitude(), centerPos.getLongitude(), dc.getGlobe());
         this.zone = UTM.getZone();
       } else this.zone = 0;
     }
   } catch (Exception ex) {
     this.zone = 0;
   }
 }
Beispiel #14
0
  protected Sector resizeShape(Movable dragObject, int side) {
    if (dragObject instanceof SurfaceSector) {
      SurfaceSector quad = (SurfaceSector) dragObject;
      Sector s = quad.getSector(); // TODO: go over all sectors
      Position p = this.getWwd().getCurrentPosition();

      if (p == null || this.getPreviousPosition() == null) {
        return null;
      }

      Angle dLat = p.getLatitude().subtract(this.getPreviousPosition().getLatitude());
      Angle dLon = p.getLongitude().subtract(this.getPreviousPosition().getLongitude());

      Angle newMinLat = s.getMinLatitude();
      Angle newMinLon = s.getMinLongitude();
      Angle newMaxLat = s.getMaxLatitude();
      Angle newMaxLon = s.getMaxLongitude();

      if (side == NORTH) {
        newMaxLat = s.getMaxLatitude().add(dLat);
      } else if (side == SOUTH) {
        newMinLat = s.getMinLatitude().add(dLat);
      } else if (side == EAST) {
        newMaxLon = s.getMaxLongitude().add(dLon);
      } else if (side == WEST) {
        newMinLon = s.getMinLongitude().add(dLon);
      } else if (side == NORTHWEST) {
        newMaxLat = s.getMaxLatitude().add(dLat);
        newMinLon = s.getMinLongitude().add(dLon);
      } else if (side == NORTHEAST) {
        newMaxLat = s.getMaxLatitude().add(dLat);
        newMaxLon = s.getMaxLongitude().add(dLon);
      } else if (side == SOUTHWEST) {
        newMinLat = s.getMinLatitude().add(dLat);
        newMinLon = s.getMinLongitude().add(dLon);
      } else if (side == SOUTHEAST) {
        newMinLat = s.getMinLatitude().add(dLat);
        newMaxLon = s.getMaxLongitude().add(dLon);
      }

      return new Sector(newMinLat, newMaxLat, newMinLon, newMaxLon);
    }

    return null;
  }
    protected void showIntersections(List<Position> intersections) {
      this.intersectionsLayer.removeAllRenderables();

      // Display the intersections as CYAN points.
      PointPlacemarkAttributes intersectionPointAttributes;
      intersectionPointAttributes = new PointPlacemarkAttributes();
      intersectionPointAttributes.setLineMaterial(Material.CYAN);
      intersectionPointAttributes.setScale(6d);
      intersectionPointAttributes.setUsePointAsDefaultImage(true);

      for (Position p : intersections) {
        PointPlacemark pm = new PointPlacemark(p);
        pm.setAltitudeMode(WorldWind.CLAMP_TO_GROUND);
        pm.setAttributes(intersectionPointAttributes);
        pm.setValue(AVKey.DISPLAY_NAME, p.toString());
        this.intersectionsLayer.addRenderable(pm);
      }
    }
Beispiel #16
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;
 }
    protected void performIntersectionTests(final Position curPos) throws InterruptedException {
      // Clear the results lists when the user selects a new location.
      this.firstIntersectionPositions.clear();
      this.sightLines.clear();

      // Raise the selected location and the grid points a little above ground just to show we can.
      final double height = 5; // meters

      // Form the grid.
      double gridRadius = GRID_RADIUS.degrees;
      Sector sector =
          Sector.fromDegrees(
              curPos.getLatitude().degrees - gridRadius, curPos.getLatitude().degrees + gridRadius,
              curPos.getLongitude().degrees - gridRadius,
                  curPos.getLongitude().degrees + gridRadius);

      this.grid = buildGrid(sector, height, GRID_DIMENSION, GRID_DIMENSION);
      this.numGridPoints = grid.size();

      // Compute the position of the selected location (incorporate its height).
      this.referencePosition = new Position(curPos.getLatitude(), curPos.getLongitude(), height);
      this.referencePoint =
          terrain.getSurfacePoint(curPos.getLatitude(), curPos.getLongitude(), height);

      //            // Pre-caching is unnecessary and is useful only when it occurs before the
      // intersection
      //            // calculations. It will incur extra overhead otherwise. The normal intersection
      // calculations
      //            // cause the same caching, making subsequent calculations on the same area
      // faster.
      //            this.preCache(grid, this.referencePosition);

      // On the EDT, show the grid.
      SwingUtilities.invokeLater(
          new Runnable() {
            public void run() {
              progressBar.setValue(0);
              progressBar.setString(null);
              clearLayers();
              showGrid(grid, referencePosition);
              getWwd().redraw();
            }
          });

      // Perform the intersection calculations.
      this.startTime = System.currentTimeMillis();
      for (Position gridPos : this.grid) // for each grid point.
      {
        //noinspection ConstantConditions
        if (NUM_THREADS > 0) this.threadPool.execute(new Intersector(gridPos));
        else performIntersection(gridPos);
      }
    }
  protected String formatMeasurements(Position pos) {
    StringBuilder sb = new StringBuilder();

    /*
     //sb.append(this.unitsFormat.areaNL(this.getLabel(AREA_LABEL), this.getArea()));
     sb.append(this.unitsFormat.lengthNL(this.getLabel(PERIMETER_LABEL), this.getLength()));
    */

    // sb.append(this.unitsFormat.lengthNL(this.getLabel(WIDTH_LABEL),
    // this.shape.getEastWestRadius() * 2));
    // sb.append(this.unitsFormat.lengthNL(this.getLabel(LENGTH_LABEL),
    // this.shape.getNorthSouthRadius() * 2));
    // sb.append(this.unitsFormat.lengthNL(this.getLabel(HEIGHT_LABEL),
    // this.shape.getVerticalRadius() * 2));

    // sb.append(this.unitsFormat.angleNL(this.getLabel(HEADING_LABEL), this.shape.getHeading()));

    // if "activeControlPoint" is in fact one of the control points
    if (!this.arePositionsRedundant(pos, this.polygon.getReferencePosition())) {
      sb.append(this.unitsFormat.angleNL(this.getLabel(LATITUDE_LABEL), pos.getLatitude()));
      sb.append(this.unitsFormat.angleNL(this.getLabel(LONGITUDE_LABEL), pos.getLongitude()));
      sb.append(this.unitsFormat.lengthNL(this.getLabel(ALTITUDE_LABEL), pos.getAltitude()));
    }

    // if "activeControlPoint" is the shape itself
    if (this.polygon.getReferencePosition() != null) {
      sb.append(
          this.unitsFormat.angleNL(
              this.getLabel(CENTER_LATITUDE_LABEL),
              this.polygon.getReferencePosition().getLatitude()));
      sb.append(
          this.unitsFormat.angleNL(
              this.getLabel(CENTER_LONGITUDE_LABEL),
              this.polygon.getReferencePosition().getLongitude()));
      sb.append(
          this.unitsFormat.lengthNL(
              this.getLabel(CENTER_ALTITUDE_LABEL),
              this.polygon.getReferencePosition().getAltitude()));
    }

    return sb.toString();
  }
    protected void showGrid(List<Position> grid, Position cPos) {
      this.gridLayer.removeAllRenderables();

      // Display the grid points in yellow.
      PointPlacemarkAttributes gridPointAttributes;
      gridPointAttributes = new PointPlacemarkAttributes();
      gridPointAttributes.setLineMaterial(Material.YELLOW);
      gridPointAttributes.setScale(6d);
      gridPointAttributes.setUsePointAsDefaultImage(true);

      for (Position p : grid) {
        PointPlacemark pm = new PointPlacemark(p);
        pm.setAltitudeMode(WorldWind.RELATIVE_TO_GROUND);
        pm.setAttributes(gridPointAttributes);
        pm.setLineEnabled(true);
        pm.setValue(AVKey.DISPLAY_NAME, p.toString());
        this.gridLayer.addRenderable(pm);
      }

      showCenterPoint(cPos);
    }
    protected void showGridSightLines(List<Position> grid, Position cPos) {
      this.sightLinesLayer.removeAllRenderables();

      // Display lines from the center to each grid point.
      ShapeAttributes lineAttributes;
      lineAttributes = new BasicShapeAttributes();
      lineAttributes.setDrawOutline(true);
      lineAttributes.setDrawInterior(false);
      lineAttributes.setOutlineMaterial(Material.GREEN);
      lineAttributes.setOutlineOpacity(0.6);

      for (Position p : grid) {
        List<Position> endPoints = new ArrayList<Position>();
        endPoints.add(cPos);
        endPoints.add(new Position(p.getLatitude(), p.getLongitude(), 0));

        Path path = new Path(endPoints);
        path.setAltitudeMode(WorldWind.RELATIVE_TO_GROUND);
        path.setAttributes(lineAttributes);
        this.sightLinesLayer.addRenderable(path);
      }
    }
    protected boolean isNavSectorVisible(
        DrawContext dc, double minDistanceSquared, double maxDistanceSquared) {
      if (!navSector.intersects(dc.getVisibleSector())) return false;

      View view = dc.getView();
      Position eyePos = view.getEyePosition();
      if (eyePos == null) return false;

      // check for eyePos over globe
      if (Double.isNaN(eyePos.getLatitude().getDegrees())
          || Double.isNaN(eyePos.getLongitude().getDegrees())) return false;

      Angle lat =
          clampAngle(eyePos.getLatitude(), navSector.getMinLatitude(), navSector.getMaxLatitude());
      Angle lon =
          clampAngle(
              eyePos.getLongitude(), navSector.getMinLongitude(), navSector.getMaxLongitude());
      Vec4 p = dc.getGlobe().computePointFromPosition(lat, lon, 0d);
      double distSquared = dc.getView().getEyePoint().distanceToSquared3(p);
      //noinspection RedundantIfStatement
      if (minDistanceSquared > distSquared || maxDistanceSquared < distSquared) return false;

      return true;
    }
    protected void showCenterPoint(Position cPos) {
      // Display the center point in red.
      PointPlacemarkAttributes selectedLocationAttributes;
      selectedLocationAttributes = new PointPlacemarkAttributes();
      selectedLocationAttributes.setLineMaterial(Material.RED);
      selectedLocationAttributes.setScale(8d);
      selectedLocationAttributes.setUsePointAsDefaultImage(true);

      PointPlacemark pm = new PointPlacemark(cPos);
      pm.setAltitudeMode(WorldWind.RELATIVE_TO_GROUND);
      pm.setAttributes(selectedLocationAttributes);
      pm.setValue(AVKey.DISPLAY_NAME, cPos.toString());
      pm.setLineEnabled(true);
      this.gridLayer.addRenderable(pm);
    }
Beispiel #23
0
    private Info[] buildFreeShapes() {
      double elevation = 10e3;
      ArrayList<Position> positions = new ArrayList<Position>();
      positions.add(
          new Position(Angle.fromDegrees(37.8484), Angle.fromDegrees(-119.9754), elevation));
      positions.add(
          new Position(Angle.fromDegrees(39.3540), Angle.fromDegrees(-110.1526), elevation));
      positions.add(
          new Position(Angle.fromDegrees(38.3540), Angle.fromDegrees(-100.1526), elevation));

      ArrayList<Position> positions2 = new ArrayList<Position>();
      positions2.add(new Position(Angle.fromDegrees(0), Angle.fromDegrees(-150), elevation));
      positions2.add(new Position(Angle.fromDegrees(25), Angle.fromDegrees(-75), elevation));
      positions2.add(new Position(Angle.fromDegrees(50), Angle.fromDegrees(0), elevation));

      ArrayList<Position> positions3 = new ArrayList<Position>();
      for (double lat = 42, lon = -100; lat <= 45; lat += .1, lon += .1) {
        positions3.add(new Position(Angle.fromDegrees(lat), Angle.fromDegrees(lon), elevation));
      }

      ArrayList<Position> positions4 = new ArrayList<Position>();
      positions4.add(new Position(Angle.fromDegrees(90), Angle.fromDegrees(-110), elevation));
      positions4.add(new Position(Angle.fromDegrees(-90), Angle.fromDegrees(-110), elevation));

      ArrayList<Position> positions5 = new ArrayList<Position>();
      for (int i = 0; i < 100; i++) {
        positions5.add(
            Position.fromDegrees(38.0 + i * 0.0001, 30.0 + i * 0.0001, 1000.0 + i * 5.0));
      }

      @SuppressWarnings({"UnnecessaryLocalVariable"})
      Info[] infos =
          new Info[] {
            new Info("Short Path", new Polyline(positions)),
            new Info("Long Path", new Polyline(positions2)),
            new Info("Incremental Path", new Polyline(positions3)),
            new Info("Vertical Path", new Polyline(positions4)),
            new Info("Small-segment Path", new Polyline(positions5)),
            new Info("Quad", new Quadrilateral(Sector.fromDegrees(38, 40, -104, -105), elevation)),
            new Info("None", null)
          };

      return infos;
    }
  protected void setPolygonHeight(Point previousMousePoint, Point mousePoint) {
    // Find the closest points between the rays through each screen point, and the ray from the
    // control point
    // and in the direction of the globe's surface normal. Compute the elevation difference between
    // these two
    // points, and use that as the change in polygon height.

    Position referencePos = this.polygon.getReferencePosition();
    if (referencePos == null) return;

    Vec4 referencePoint = this.wwd.getModel().getGlobe().computePointFromPosition(referencePos);

    Vec4 surfaceNormal =
        this.wwd
            .getModel()
            .getGlobe()
            .computeSurfaceNormalAtLocation(
                referencePos.getLatitude(), referencePos.getLongitude());
    Line verticalRay = new Line(referencePoint, surfaceNormal);
    Line screenRay =
        this.wwd.getView().computeRayFromScreenPoint(mousePoint.getX(), mousePoint.getY());
    Line previousScreenRay =
        this.wwd
            .getView()
            .computeRayFromScreenPoint(previousMousePoint.getX(), previousMousePoint.getY());

    Vec4 pointOnLine = AirspaceEditorUtil.nearestPointOnLine(verticalRay, screenRay);
    Vec4 previousPointOnLine =
        AirspaceEditorUtil.nearestPointOnLine(verticalRay, previousScreenRay);

    Position pos = this.wwd.getModel().getGlobe().computePositionFromPoint(pointOnLine);
    Position previousPos =
        this.wwd.getModel().getGlobe().computePositionFromPoint(previousPointOnLine);
    double elevationChange = pos.getElevation() - previousPos.getElevation();

    java.util.List<Position> boundary = new ArrayList<Position>();
    for (LatLon ll : this.polygon.getOuterBoundary()) {
      boundary.add(new Position(ll, ((Position) ll).getElevation() + elevationChange));
    }

    this.polygon.setOuterBoundary(boundary);
  }
  protected Vec4 computeAnnotationPosition(Position pos) {
    Vec4 surfacePoint =
        this.wwd
            .getSceneController()
            .getTerrain()
            .getSurfacePoint(pos.getLatitude(), pos.getLongitude());
    if (surfacePoint == null) {
      Globe globe = this.wwd.getModel().getGlobe();
      surfacePoint =
          globe.computePointFromPosition(
              pos.getLatitude(),
              pos.getLongitude(),
              globe.getElevation(pos.getLatitude(), pos.getLongitude()));
    }

    return this.wwd.getView().project(surfacePoint);
  }
    protected List<Position> buildGrid(Sector sector, double height, int nLatCells, int nLonCells) {
      List<Position> grid = new ArrayList<Position>((nLatCells + 1) * (nLonCells + 1));

      double dLat = sector.getDeltaLatDegrees() / nLatCells;
      double dLon = sector.getDeltaLonDegrees() / nLonCells;

      for (int j = 0; j <= nLatCells; j++) {
        double lat =
            j == nLatCells
                ? sector.getMaxLatitude().degrees
                : sector.getMinLatitude().degrees + j * dLat;

        for (int i = 0; i <= nLonCells; i++) {
          double lon =
              i == nLonCells
                  ? sector.getMaxLongitude().degrees
                  : sector.getMinLongitude().degrees + i * dLon;

          grid.add(Position.fromDegrees(lat, lon, height));
        }
      }

      return grid;
    }
  protected void moveControlPoint(
      ControlPointMarker controlPoint, Point lastMousePoint, Point moveToPoint) {
    View view = this.wwd.getView();
    Globe globe = this.wwd.getModel().getGlobe();

    Position refPos = controlPoint.getPosition();
    if (refPos == null) return;

    Line ray = view.computeRayFromScreenPoint(moveToPoint.getX(), moveToPoint.getY());
    Line previousRay = view.computeRayFromScreenPoint(lastMousePoint.getX(), lastMousePoint.getY());

    Vec4 vec = AirspaceEditorUtil.intersectGlobeAt(this.wwd, refPos.getElevation(), ray);
    Vec4 previousVec =
        AirspaceEditorUtil.intersectGlobeAt(this.wwd, refPos.getElevation(), previousRay);

    if (vec == null || previousVec == null) {
      return;
    }

    Position pos = globe.computePositionFromPoint(vec);
    Position previousPos = globe.computePositionFromPoint(previousVec);
    LatLon change = pos.subtract(previousPos);

    java.util.List<LatLon> boundary = new ArrayList<LatLon>();
    for (LatLon ll : this.polygon.getOuterBoundary()) {
      boundary.add(ll);
    }

    boundary.set(controlPoint.getIndex(), new Position(pos.add(change), refPos.getAltitude()));

    // ExtrudedPolygon ensures that the last boundary position is the same as the first. Remove the
    // last point
    // before setting the boundary.
    boundary.remove(boundary.size() - 1);

    this.polygon.setOuterBoundary(boundary);
  }
    public void selectRenderables(DrawContext dc) {
      try {
        OrbitView view = (OrbitView) dc.getView();
        // Compute easting and northing label offsets
        Double pixelSize = view.computePixelSizeAtDistance(view.getZoom());
        Double eastingOffset = view.getViewport().width * pixelSize * offsetFactorX / 2;
        Double northingOffset = view.getViewport().height * pixelSize * offsetFactorY / 2;
        // Derive labels center pos from the view center
        Position centerPos = view.getCenterPosition();
        double labelEasting;
        double labelNorthing;
        String labelHemisphere;
        if (this.zone > 0) {
          UTMCoord UTM =
              UTMCoord.fromLatLon(centerPos.getLatitude(), centerPos.getLongitude(), dc.getGlobe());
          labelEasting = UTM.getEasting() + eastingOffset;
          labelNorthing = UTM.getNorthing() + northingOffset;
          labelHemisphere = UTM.getHemisphere();
          if (labelNorthing < 0) {
            labelNorthing = 10e6 + labelNorthing;
            labelHemisphere = AVKey.SOUTH;
          }
        } else {
          UPSCoord UPS =
              UPSCoord.fromLatLon(centerPos.getLatitude(), centerPos.getLongitude(), dc.getGlobe());
          labelEasting = UPS.getEasting() + eastingOffset;
          labelNorthing = UPS.getNorthing() + northingOffset;
          labelHemisphere = UPS.getHemisphere();
        }

        Position labelPos;
        for (int i = 0; i < this.extremes.length; i++) {
          UTMExtremes levelExtremes = this.extremes[i];
          double gridStep = Math.pow(10, i);
          double gridStepTimesTen = gridStep * 10;
          String graticuleType = getTypeFor((int) gridStep);
          if (levelExtremes.minX <= levelExtremes.maxX) {
            // Process easting scale labels for this level
            for (double easting = levelExtremes.minX;
                easting <= levelExtremes.maxX;
                easting += gridStep) {
              // Skip multiples of ten grid steps except for last (higher) level
              if (i == this.extremes.length - 1 || easting % gridStepTimesTen != 0) {
                try {
                  labelPos = computePosition(this.zone, labelHemisphere, easting, labelNorthing);
                  if (labelPos == null) continue;
                  Angle lat = labelPos.getLatitude();
                  Angle lon = labelPos.getLongitude();
                  Vec4 surfacePoint = getSurfacePoint(dc, lat, lon);
                  if (viewFrustum.contains(surfacePoint) && isPointInRange(dc, surfacePoint)) {
                    String text = String.valueOf((int) (easting % this.scaleModulo));
                    GeographicText gt = new UserFacingText(text, new Position(lat, lon, 0));
                    gt.setPriority(gridStepTimesTen);
                    addRenderable(gt, graticuleType);
                  }
                } catch (IllegalArgumentException ignore) {
                }
              }
            }
          }
          if (!(levelExtremes.maxYHemisphere.equals(AVKey.SOUTH) && levelExtremes.maxY == 0)) {
            // Process northing scale labels for this level
            String currentHemisphere = levelExtremes.minYHemisphere;
            for (double northing = levelExtremes.minY;
                (northing <= levelExtremes.maxY)
                    || !currentHemisphere.equals(levelExtremes.maxYHemisphere);
                northing += gridStep) {
              // Skip multiples of ten grid steps except for last (higher) level
              if (i == this.extremes.length - 1 || northing % gridStepTimesTen != 0) {
                try {
                  labelPos = computePosition(this.zone, currentHemisphere, labelEasting, northing);
                  if (labelPos == null) continue;
                  Angle lat = labelPos.getLatitude();
                  Angle lon = labelPos.getLongitude();
                  Vec4 surfacePoint = getSurfacePoint(dc, lat, lon);
                  if (viewFrustum.contains(surfacePoint) && isPointInRange(dc, surfacePoint)) {
                    String text = String.valueOf((int) (northing % this.scaleModulo));
                    GeographicText gt = new UserFacingText(text, new Position(lat, lon, 0));
                    gt.setPriority(gridStepTimesTen);
                    addRenderable(gt, graticuleType);
                  }
                } catch (IllegalArgumentException ignore) {
                }

                if (!currentHemisphere.equals(levelExtremes.maxYHemisphere)
                    && northing >= 10e6 - gridStep) {
                  // Switch hemisphere
                  currentHemisphere = levelExtremes.maxYHemisphere;
                  northing = -gridStep;
                }
              }
            }
          } // end northing
        } // for levels
      } catch (IllegalArgumentException ignore) {
      }
    }
  /** Create the graticule grid elements */
  private void createUTMRenderables() {
    this.gridElements = new ArrayList<GridElement>();

    ArrayList<Position> positions = new ArrayList<Position>();

    // Generate meridians and zone labels
    int lon = -180;
    int zoneNumber = 1;
    int maxLat;
    for (int i = 0; i < 60; i++) {
      Angle longitude = Angle.fromDegrees(lon);
      // Meridian
      positions.clear();
      positions.add(new Position(Angle.fromDegrees(-80), longitude, 10e3));
      positions.add(new Position(Angle.fromDegrees(-60), longitude, 10e3));
      positions.add(new Position(Angle.fromDegrees(-30), longitude, 10e3));
      positions.add(new Position(Angle.ZERO, longitude, 10e3));
      positions.add(new Position(Angle.fromDegrees(30), longitude, 10e3));
      if (lon < 6 || lon > 36) {
        // 'regular' UTM meridians
        maxLat = 84;
        positions.add(new Position(Angle.fromDegrees(60), longitude, 10e3));
        positions.add(new Position(Angle.fromDegrees(maxLat), longitude, 10e3));
      } else {
        // Exceptions: shorter meridians around and north-east of Norway
        if (lon == 6) {
          maxLat = 56;
          positions.add(new Position(Angle.fromDegrees(maxLat), longitude, 10e3));
        } else {
          maxLat = 72;
          positions.add(new Position(Angle.fromDegrees(60), longitude, 10e3));
          positions.add(new Position(Angle.fromDegrees(maxLat), longitude, 10e3));
        }
      }
      Object polyline = createLineRenderable(positions, Polyline.GREAT_CIRCLE);
      Sector sector = Sector.fromDegrees(-80, maxLat, lon, lon);
      this.gridElements.add(new GridElement(sector, polyline, GridElement.TYPE_LINE));

      // Zone label
      GeographicText text =
          new UserFacingText(zoneNumber + "", Position.fromDegrees(0, lon + 3, 0));
      sector = Sector.fromDegrees(-90, 90, lon + 3, lon + 3);
      this.gridElements.add(new GridElement(sector, text, GridElement.TYPE_LONGITUDE_LABEL));

      // Increase longitude and zone number
      lon += 6;
      zoneNumber++;
    }

    // Generate special meridian segments for exceptions around and north-east of Norway
    for (int i = 0; i < 5; i++) {
      positions.clear();
      lon = specialMeridians[i][0];
      positions.add(
          new Position(Angle.fromDegrees(specialMeridians[i][1]), Angle.fromDegrees(lon), 10e3));
      positions.add(
          new Position(Angle.fromDegrees(specialMeridians[i][2]), Angle.fromDegrees(lon), 10e3));
      Object polyline = createLineRenderable(positions, Polyline.GREAT_CIRCLE);
      Sector sector = Sector.fromDegrees(specialMeridians[i][1], specialMeridians[i][2], lon, lon);
      this.gridElements.add(new GridElement(sector, polyline, GridElement.TYPE_LINE));
    }

    // Generate parallels - no exceptions
    int lat = -80;
    for (int i = 0; i < 21; i++) {
      Angle latitude = Angle.fromDegrees(lat);
      for (int j = 0; j < 4; j++) {
        // Each prallel is divided into four 90 degrees segments
        positions.clear();
        lon = -180 + j * 90;
        positions.add(new Position(latitude, Angle.fromDegrees(lon), 10e3));
        positions.add(new Position(latitude, Angle.fromDegrees(lon + 30), 10e3));
        positions.add(new Position(latitude, Angle.fromDegrees(lon + 60), 10e3));
        positions.add(new Position(latitude, Angle.fromDegrees(lon + 90), 10e3));
        Object polyline = createLineRenderable(positions, Polyline.LINEAR);
        Sector sector = Sector.fromDegrees(lat, lat, lon, lon + 90);
        this.gridElements.add(new GridElement(sector, polyline, GridElement.TYPE_LINE));
      }
      // Latitude band label
      if (i < 20) {
        GeographicText text =
            new UserFacingText(latBands.charAt(i) + "", Position.fromDegrees(lat + 4, 0, 0));
        Sector sector = Sector.fromDegrees(lat + 4, lat + 4, -180, 180);
        this.gridElements.add(new GridElement(sector, text, GridElement.TYPE_LATITUDE_LABEL));
      }

      // Increase latitude
      lat += lat < 72 ? 8 : 12;
    }
  }
  /**
   * Select the visible grid elements
   *
   * @param dc the current <code>DrawContext</code>.
   */
  protected void selectRenderables(DrawContext dc) {
    if (dc == null) {
      String message = Logging.getMessage("nullValue.DrawContextIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }
    Sector vs = dc.getVisibleSector();
    OrbitView view = (OrbitView) dc.getView();
    // Compute labels offset from view center
    Position centerPos = view.getCenterPosition();
    Double pixelSizeDegrees =
        Angle.fromRadians(
                view.computePixelSizeAtDistance(view.getZoom())
                    / dc.getGlobe().getEquatorialRadius())
            .degrees;
    Double labelOffsetDegrees = pixelSizeDegrees * view.getViewport().getWidth() / 4;
    Position labelPos =
        Position.fromDegrees(
            centerPos.getLatitude().degrees - labelOffsetDegrees,
            centerPos.getLongitude().degrees - labelOffsetDegrees,
            0);
    Double labelLatDegrees = labelPos.getLatitude().normalizedLatitude().degrees;
    labelLatDegrees = Math.min(Math.max(labelLatDegrees, -76), 78);
    labelPos =
        new Position(
            Angle.fromDegrees(labelLatDegrees), labelPos.getLongitude().normalizedLongitude(), 0);

    if (vs != null) {
      for (GridElement ge : this.gridElements) {
        if (ge.isInView(dc)) {
          if (ge.renderable instanceof GeographicText) {
            GeographicText gt = (GeographicText) ge.renderable;
            if (labelPos.getLatitude().degrees < 72
                || "*32*34*36*".indexOf("*" + gt.getText() + "*") == -1) {
              // Adjust label position according to eye position
              Position pos = gt.getPosition();
              if (ge.type.equals(GridElement.TYPE_LATITUDE_LABEL))
                pos =
                    Position.fromDegrees(
                        pos.getLatitude().degrees,
                        labelPos.getLongitude().degrees,
                        pos.getElevation());
              else if (ge.type.equals(GridElement.TYPE_LONGITUDE_LABEL))
                pos =
                    Position.fromDegrees(
                        labelPos.getLatitude().degrees,
                        pos.getLongitude().degrees,
                        pos.getElevation());

              gt.setPosition(pos);
            }
          }

          this.graticuleSupport.addRenderable(ge.renderable, GRATICULE_UTM);
        }
      }
      // System.out.println("Total elements: " + count + " visible sector: " + vs);
    }
  }