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

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

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

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

    // Configure OrbitView to look at the center of the sector from our estimated distance. This
    // causes OrbitView to
    // animate to the specified position over several seconds. To affect this change immediately use
    // the following:
    // ((OrbitView) wwd.getView()).setCenterPosition(new Position(sector.getCentroid(), 0d));
    // ((OrbitView) wwd.getView()).setZoom(zoom);
    wwd.getView().goTo(new Position(sector.getCentroid(), 0d), zoom);
  }
  private void applyModify() {
    layer.setName(layerNameTextField.getText());
    Color choosenColor = colorBtn.getBackground();
    color = new Color(choosenColor.getRed(), choosenColor.getGreen(), choosenColor.getBlue());
    List<Position> positions = new ArrayList<Position>();
    for (int i = 0; i < latTexts.size(); i++) {
      Position p = layer.getPositions().get(i);
      double lat = Double.valueOf(latTexts.get(i).getText());
      double lng = Double.valueOf(lngTexts.get(i).getText());
      Position newP =
          new Position(Angle.fromDegrees(lat), Angle.fromDegrees(lng), p.getElevation());
      positions.add(newP);
    }
    layer.setPositions(positions);
    path.setPositions(positions);

    // Create and set an attribute bundle.
    ShapeAttributes attrs = new BasicShapeAttributes();
    Material material = new Material(color);
    attrs.setOutlineMaterial(material);
    attrs.setOutlineWidth(Double.valueOf(sizeTextField.getText()));
    attrs.setOutlineOpacity(Double.valueOf(opacityTextField.getText()));
    //		path.setColor(color);
    //		path.setLineWidth(Double.valueOf(sizeTextField.getText()));
    path.setAttributes(attrs);

    layer.refresh();
    frame.getLayerPanelDialog().getLayerPanel().update();
  }
  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);
    }
  }
  /**
   * 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);
  }
Beispiel #5
0
    private Info[] buildSurfaceShapes() {
      LatLon position = new LatLon(Angle.fromDegrees(38), Angle.fromDegrees(-105));

      ArrayList<LatLon> surfaceLinePositions = new ArrayList<LatLon>();
      //            surfaceLinePositions.add(LatLon.fromDegrees(37.8484, -119.9754));
      //            surfaceLinePositions.add(LatLon.fromDegrees(38.3540, -119.1526));

      //            surfaceLinePositions.add(new LatLon(Angle.fromDegrees(0),
      // Angle.fromDegrees(-150)));
      //            surfaceLinePositions.add(new LatLon(Angle.fromDegrees(60),
      // Angle.fromDegrees(0)));

      surfaceLinePositions.add(position);
      surfaceLinePositions.add(LatLon.fromDegrees(39, -104));
      surfaceLinePositions.add(LatLon.fromDegrees(39, -105));
      surfaceLinePositions.add(position);

      return new Info[] {
        new Info("Circle", new SurfaceCircle(position, 100e3)),
        new Info("Ellipse", new SurfaceEllipse(position, 100e3, 90e3, Angle.ZERO)),
        new Info("Square", new SurfaceSquare(position, 100e3)),
        new Info("Quad", new SurfaceQuad(position, 100e3, 60e3, Angle.ZERO)),
        new Info("Sector", new SurfaceSector(Sector.fromDegrees(38, 40, -105, -103))),
        new Info("Polygon", new SurfacePolygon(surfaceLinePositions)),
      };
    }
  /**
   * Apply the model's position, orientation, and scale to a COLLADA root.
   *
   * @param root COLLADA root to configure.
   */
  protected void configureColladaRoot(ColladaRoot root) {
    root.setResourceResolver(this);

    Position refPosition = this.model.getLocation().getPosition();
    root.setPosition(refPosition);
    root.setAltitudeMode(KMLUtil.convertAltitudeMode(this.model.getAltitudeMode()));

    KMLOrientation orientation = this.model.getOrientation();
    if (orientation != null) {
      Double d = orientation.getHeading();
      if (d != null) root.setHeading(Angle.fromDegrees(d));

      d = orientation.getTilt();
      if (d != null) root.setPitch(Angle.fromDegrees(-d));

      d = orientation.getRoll();
      if (d != null) root.setRoll(Angle.fromDegrees(-d));
    }

    KMLScale scale = this.model.getScale();
    if (scale != null) {
      Double x = scale.getX();
      Double y = scale.getY();
      Double z = scale.getZ();

      Vec4 modelScale = new Vec4(x != null ? x : 1.0, y != null ? y : 1.0, z != null ? z : 1.0);

      root.setModelScale(modelScale);
    }
  }
 /**
  * Returns the latitude and longitude of the sector's angular center: (minimum latitude + maximum
  * latitude) / 2, (minimum longitude + maximum longitude) / 2.
  *
  * @return The latitude and longitude of the sector's angular center
  */
 public LatLon getCentroid() {
   Angle la =
       Angle.fromDegrees(0.5 * (this.getMaxLatitude().degrees + this.getMinLatitude().degrees));
   Angle lo =
       Angle.fromDegrees(0.5 * (this.getMaxLongitude().degrees + this.getMinLongitude().degrees));
   return new LatLon(la, lo);
 }
  /**
   * {@inheritDoc}
   *
   * @param positions Control points. This graphic uses only two control point, which determine the
   *     midpoints of two opposite sides of the quad. See Fire Support Area (2.X.4.3.2.1.2) on pg.
   *     652 of MIL-STD-2525C for an example of how these points are interpreted.
   */
  public void setPositions(Iterable<? extends Position> positions) {
    if (positions == null) {
      String message = Logging.getMessage("nullValue.PositionsListIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    Iterator<? extends Position> iterator = positions.iterator();
    try {
      Position pos1 = iterator.next();
      Position pos2 = iterator.next();

      LatLon center = LatLon.interpolateGreatCircle(0.5, pos1, pos2);
      this.quad.setCenter(center);

      Angle heading = LatLon.greatCircleAzimuth(pos2, pos1);
      this.quad.setHeading(heading.subtract(Angle.POS90));

      this.positions = positions;
      this.shapeInvalid = true; // Need to recompute quad size
    } catch (NoSuchElementException e) {
      String message = Logging.getMessage("generic.InsufficientPositions");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }
  }
  /**
   * Tests the equality of the sectors' angles. Sectors are equal if all of their corresponding
   * angles are equal.
   *
   * @param o the sector to compareTo with <code>this</code>.
   * @return <code>true</code> if the four corresponding angles of each sector are equal, <code>
   *     false</code> otherwise.
   */
  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }

    final gov.nasa.worldwind.geom.Sector sector = (gov.nasa.worldwind.geom.Sector) o;

    if (!maxLatitude.equals(sector.maxLatitude)) {
      return false;
    }
    if (!maxLongitude.equals(sector.maxLongitude)) {
      return false;
    }
    if (!minLatitude.equals(sector.minLatitude)) {
      return false;
    }
    //noinspection RedundantIfStatement
    if (!minLongitude.equals(sector.minLongitude)) {
      return false;
    }

    return true;
  }
  protected Tile[] buildTiles(PlaceNameService placeNameService, NavigationTile navTile) {
    final Angle dLat = placeNameService.getTileDelta().getLatitude();
    final Angle dLon = placeNameService.getTileDelta().getLongitude();

    // Determine the row and column offset from the global tiling origin for the southwest tile
    // corner
    int firstRow = Tile.computeRow(dLat, navTile.navSector.getMinLatitude());
    int firstCol = Tile.computeColumn(dLon, navTile.navSector.getMinLongitude());
    int lastRow = Tile.computeRow(dLat, navTile.navSector.getMaxLatitude().subtract(dLat));
    int lastCol = Tile.computeColumn(dLon, navTile.navSector.getMaxLongitude().subtract(dLon));

    int nLatTiles = lastRow - firstRow + 1;
    int nLonTiles = lastCol - firstCol + 1;

    Tile[] tiles = new Tile[nLatTiles * nLonTiles];

    Angle p1 = Tile.computeRowLatitude(firstRow, dLat);
    for (int row = 0; row <= lastRow - firstRow; row++) {
      Angle p2;
      p2 = p1.add(dLat);

      Angle t1 = Tile.computeColumnLongitude(firstCol, dLon);
      for (int col = 0; col <= lastCol - firstCol; col++) {
        Angle t2;
        t2 = t1.add(dLon);
        // Need offset row and column to correspond to total ro/col numbering
        tiles[col + row * nLonTiles] =
            new Tile(placeNameService, new Sector(p1, p2, t1, t2), row + firstRow, col + firstCol);
        t1 = t2;
      }
      p1 = p2;
    }

    return tiles;
  }
  protected void onHorizontalTranslateRel(
      double forwardInput,
      double sideInput,
      double totalForwardInput,
      double totalSideInput,
      ViewInputAttributes.DeviceAttributes deviceAttributes,
      ViewInputAttributes.ActionAttributes actionAttributes) {
    Angle forwardChange;
    Angle sideChange;

    this.stopGoToAnimators();
    if (actionAttributes.getMouseActions() != null) {
      forwardChange =
          Angle.fromDegrees(
              -totalForwardInput * getScaleValueElevation(deviceAttributes, actionAttributes));
      sideChange =
          Angle.fromDegrees(
              totalSideInput * getScaleValueElevation(deviceAttributes, actionAttributes));
    } else {
      forwardChange =
          Angle.fromDegrees(
              forwardInput * speed * getScaleValueElevation(deviceAttributes, actionAttributes));
      sideChange =
          Angle.fromDegrees(
              sideInput * speed * getScaleValueElevation(deviceAttributes, actionAttributes));
    }
    onHorizontalTranslateRel(forwardChange, sideChange, actionAttributes);
  }
  /**
   * 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);
    }
  }
 static int computeColumn(Angle delta, Angle longitude) {
   if (delta == null || longitude == null) {
     String msg = Logging.getMessage("nullValue.AngleIsNull");
     Logging.logger().severe(msg);
     throw new IllegalArgumentException(msg);
   }
   return (int) ((longitude.getDegrees() + 180d) / delta.getDegrees());
 }
 static Angle computeColumnLongitude(int column, Angle delta) {
   if (delta == null) {
     String msg = Logging.getMessage("nullValue.AngleIsNull");
     Logging.logger().severe(msg);
     throw new IllegalArgumentException(msg);
   }
   return Angle.fromDegrees(-180 + delta.getDegrees() * column);
 }
 /**
  * Creates a new <code>Sector</code> and initializes it to the specified angles. The angles are
  * assumed to be normalized to +/- 90 degrees latitude and +/- 180 degrees longitude, but this
  * method does not verify that.
  *
  * @param minLatitude the sector's minimum latitude in degrees.
  * @param maxLatitude the sector's maximum latitude in degrees.
  * @param minLongitude the sector's minimum longitude in degrees.
  * @param maxLongitude the sector's maximum longitude in degrees.
  * @return the new <code>Sector</code>
  */
 public static Sector fromDegrees(
     double minLatitude, double maxLatitude, double minLongitude, double maxLongitude) {
   return new Sector(
       Angle.fromDegrees(minLatitude),
       Angle.fromDegrees(maxLatitude),
       Angle.fromDegrees(minLongitude),
       Angle.fromDegrees(maxLongitude));
 }
 static Angle computeRowLatitude(int row, Angle delta) {
   if (delta == null) {
     String msg = Logging.getMessage("nullValue.AngleIsNull");
     Logging.logger().severe(msg);
     throw new IllegalArgumentException(msg);
   }
   return Angle.fromDegrees(-90d + delta.getDegrees() * row);
 }
 /**
  * Computes a hash code from the sector's four angles.
  *
  * @return a hash code incorporating the sector's four angles.
  */
 @Override
 public int hashCode() {
   int result;
   result = minLatitude.hashCode();
   result = 29 * result + maxLatitude.hashCode();
   result = 29 * result + minLongitude.hashCode();
   result = 29 * result + maxLongitude.hashCode();
   return result;
 }
 protected Angle computePanHeading(OrbitView view, ScreenAnnotation control) {
   // Compute last pick point 'heading' relative to pan control center
   double size = control.getAttributes().getSize().width * control.getAttributes().getScale();
   Vec4 center = new Vec4(control.getScreenPoint().x, control.getScreenPoint().y + size / 2, 0);
   double px = lastPickPoint.x - center.x;
   double py = view.getViewport().getHeight() - lastPickPoint.y - center.y;
   Angle heading = view.getHeading().add(Angle.fromRadians(Math.atan2(px, py)));
   heading = heading.degrees >= 0 ? heading : heading.addDegrees(360);
   return heading;
 }
  public void rotate(Angle angle) {
    if (this.view == null) {
      return;
    }

    Angle heading = view.getHeading();
    Angle newHeading = heading.add(angle);
    this.view.setHeading(newHeading);
    this.view.firePropertyChange(AVKey.VIEW, null, this.view);
  }
 protected Angle computeLookHeading(OrbitView view, ScreenAnnotation control, double headingStep) {
   // Compute last pick point 'heading' relative to look control center on x
   double size = control.getAttributes().getSize().width * control.getAttributes().getScale();
   Vec4 center = new Vec4(control.getScreenPoint().x, control.getScreenPoint().y + size / 2, 0);
   double px = lastPickPoint.x - center.x;
   double pickDistanceFactor = Math.min(Math.abs(px) / 3000, 5) * Math.signum(px);
   // New heading
   Angle heading = view.getHeading().add(Angle.fromRadians(headingStep * pickDistanceFactor));
   heading = heading.degrees >= 0 ? heading : heading.addDegrees(360);
   return heading;
 }
 protected Angle computeLookPitch(OrbitView view, ScreenAnnotation control, double pitchStep) {
   // Compute last pick point 'pitch' relative to look control center on y
   double size = control.getAttributes().getSize().width * control.getAttributes().getScale();
   Vec4 center = new Vec4(control.getScreenPoint().x, control.getScreenPoint().y + size / 2, 0);
   double py = view.getViewport().getHeight() - lastPickPoint.y - center.y;
   double pickDistanceFactor = Math.min(Math.abs(py) / 3000, 5) * Math.signum(py);
   // New pitch
   Angle pitch = view.getPitch().add(Angle.fromRadians(pitchStep * pickDistanceFactor));
   pitch = pitch.degrees >= 0 ? (pitch.degrees <= 90 ? pitch : Angle.fromDegrees(90)) : Angle.ZERO;
   return pitch;
 }
 protected Position computePositionFromUPS(String hemisphere, double easting, double northing) {
   try {
     UPSCoord UPS = UPSCoord.fromUPS(hemisphere, easting, northing, globe);
     return new Position(
         Angle.fromRadiansLatitude(UPS.getLatitude().radians),
         Angle.fromRadiansLongitude(UPS.getLongitude().radians),
         10e3);
   } catch (IllegalArgumentException e) {
     return null;
   }
 }
  public Sector(Sector sector) {
    if (sector == null) {
      throw new IllegalArgumentException("Sector Is Null");
    }

    this.minLatitude = new Angle(sector.getMinLatitude());
    this.maxLatitude = new Angle(sector.getMaxLatitude());
    this.minLongitude = new Angle(sector.getMinLongitude());
    this.maxLongitude = new Angle(sector.getMaxLongitude());
    this.deltaLat = Angle.fromDegrees(this.maxLatitude.degrees - this.minLatitude.degrees);
    this.deltaLon = Angle.fromDegrees(this.maxLongitude.degrees - this.minLongitude.degrees);
  }
  public Sector[] subdivide() {
    Angle midLat = Angle.average(this.minLatitude, this.maxLatitude);
    Angle midLon = Angle.average(this.minLongitude, this.maxLongitude);

    Sector[] sectors = new Sector[4];
    sectors[0] = new Sector(this.minLatitude, midLat, this.minLongitude, midLon);
    sectors[1] = new Sector(this.minLatitude, midLat, midLon, this.maxLongitude);
    sectors[2] = new Sector(midLat, this.maxLatitude, this.minLongitude, midLon);
    sectors[3] = new Sector(midLat, this.maxLatitude, midLon, this.maxLongitude);

    return sectors;
  }
  @Override
  protected void doRestoreState(RestorableSupport rs, RestorableSupport.StateObject context) {
    super.doRestoreState(rs, context);

    Double la = rs.getStateValueAsDouble(context, "leftAzimuthDegrees");
    if (la == null) la = this.leftAzimuth.degrees;

    Double ra = rs.getStateValueAsDouble(context, "rightAzimuthDegrees");
    if (ra == null) ra = this.rightAzimuth.degrees;

    this.setAzimuths(Angle.fromDegrees(la), Angle.fromDegrees(ra));
  }
 @Test
 public void testKnownAzimuthD() {
   LatLon begin = LatLon.fromDegrees(51.5000, 0.0000);
   LatLon end = LatLon.fromDegrees(42.0000, -71.0000);
   Angle theta =
       LatLon.ellipsoidalForwardAzimuth(
           begin, end, globe.getEquatorialRadius(), globe.getPolarRadius());
   assertEquals(
       "Known ellipsoidal Azimuth D",
       Angle.normalizedLongitude(Angle.fromDegrees(287.95372)).degrees,
       theta.degrees,
       TOLERANCE);
 }
 @Test
 public void testKnownAzimuthB() {
   LatLon begin = LatLon.fromDegrees(9.0000, -79.0000);
   LatLon end = LatLon.fromDegrees(48.0000, -122.0000);
   Angle theta =
       LatLon.ellipsoidalForwardAzimuth(
           begin, end, globe.getEquatorialRadius(), globe.getPolarRadius());
   assertEquals(
       "Known ellipsoidal Azimuth B",
       Angle.normalizedLongitude(Angle.fromDegrees(325.10111)).degrees,
       theta.degrees,
       TOLERANCE);
 }
Beispiel #28
0
  /**
   * Computes the shortest distance between this and <code>angle</code>, as an <code>Angle</code>.
   *
   * @param angle the <code>Angle</code> to measure angular distance to.
   * @return the angular distance between this and <code>value</code>.
   */
  public Angle angularDistanceTo(Angle angle) {
    if (angle == null) {
      String message = Logging.getMessage("nullValue.AngleIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    double differenceDegrees = angle.subtract(this).degrees;
    if (differenceDegrees < -180) differenceDegrees += 360;
    else if (differenceDegrees > 180) differenceDegrees -= 360;

    double absAngle = Math.abs(differenceDegrees);
    return Angle.fromDegrees(absAngle);
  }
  /**
   * Creates a new <code>Sector</code> and initializes it to the specified angles. The angles are
   * assumed to be normalized to +/- 90 degrees latitude and +/- 180 degrees longitude, but this
   * method does not verify that.
   *
   * @param minLatitude the sector's minimum latitude.
   * @param maxLatitude the sector's maximum latitude.
   * @param minLongitude the sector's minimum longitude.
   * @param maxLongitude the sector's maximum longitude.
   * @throws IllegalArgumentException if any of the angles are null
   */
  public Sector(Angle minLatitude, Angle maxLatitude, Angle minLongitude, Angle maxLongitude) {
    if (minLatitude == null
        || maxLatitude == null
        || minLongitude == null
        || maxLongitude == null) {
      throw new IllegalArgumentException("Input Angles Null");
    }

    this.minLatitude = minLatitude;
    this.maxLatitude = maxLatitude;
    this.minLongitude = minLongitude;
    this.maxLongitude = maxLongitude;
    this.deltaLat = Angle.fromDegrees(this.maxLatitude.degrees - this.minLatitude.degrees);
    this.deltaLon = Angle.fromDegrees(this.maxLongitude.degrees - this.minLongitude.degrees);
  }
  public void tilt(Angle tilt) {
    if (this.view == null) {
      return;
    }

    Angle pitch = view.getPitch();
    Angle newPitch = pitch.add(tilt);

    if (newPitch.degrees < 0 || newPitch.degrees > 90) {
      return;
    }

    this.view.setPitch(newPitch);
    this.view.firePropertyChange(AVKey.VIEW, null, this.view);
  }