@Test
 public void testKnownAzimuthE() {
   LatLon begin = LatLon.fromDegrees(-12.0, 87.0);
   LatLon end = LatLon.fromDegrees(53.0902505, -67.1064558);
   double azimuth = LatLon.rhumbAzimuth(begin, end).degrees;
   assertEquals("Known Azimuth E", -64.05846977747626, azimuth, THRESHOLD);
 }
 @Test
 public void testKnownAzimuthC() {
   LatLon begin = LatLon.fromDegrees(-12.0, 87.0);
   LatLon end = LatLon.fromDegrees(-12.0000001, 86.9999999);
   double azimuth = LatLon.rhumbAzimuth(begin, end).degrees;
   assertEquals("Known Azimuth C", -135.63291443992495, azimuth, THRESHOLD);
 }
 @Test
 public void testKnownAzimuthD() {
   LatLon begin = LatLon.fromDegrees(-12.0, 87.0);
   LatLon end = LatLon.fromDegrees(11.9999999, -93.0000001);
   double azimuth = LatLon.rhumbAzimuth(begin, end).degrees;
   assertEquals("Known Azimuth D", 82.34987931207793, azimuth, THRESHOLD);
 }
 @Test
 public void testKnownAzimuthB() {
   LatLon begin = LatLon.fromDegrees(53.0902505, 112.8935442);
   LatLon end = LatLon.fromDegrees(-53.0902505, -67.1064558);
   double azimuth = LatLon.rhumbAzimuth(begin, end).degrees;
   assertEquals("Known Azimuth B", -124.94048502315054, azimuth, THRESHOLD);
 }
 @Test
 public void testKnownAzimuthA() {
   LatLon begin = LatLon.fromDegrees(-90.0, -180.0);
   LatLon end = LatLon.fromDegrees(90.0, 180.0);
   double azimuth = LatLon.rhumbAzimuth(begin, end).degrees;
   assertEquals("Known Azimuth A", 0.0, azimuth, THRESHOLD);
 }
 @Test
 public void testEquivalentPoints() {
   LatLon begin = LatLon.fromDegrees(53.0902505, 112.8935442);
   LatLon end = LatLon.fromDegrees(53.0902505, 112.8935442);
   double azimuth = LatLon.rhumbAzimuth(begin, end).degrees;
   assertEquals("Equivalent points", 0.0, azimuth, THRESHOLD);
 }
 @Test
 public void testTrivialEquivalentPointsC() {
   LatLon begin = LatLon.fromDegrees(90.0, 0.0);
   LatLon end = LatLon.fromDegrees(90.0, 0.0);
   double azimuth = LatLon.rhumbAzimuth(begin, end).degrees;
   assertEquals("Trivial equivalent points C", 0.0, azimuth, THRESHOLD);
 }
 @Test
 public void testTrivialWest() {
   LatLon begin = LatLon.fromDegrees(0.0, 0.0);
   LatLon end = LatLon.fromDegrees(0.0, -90.0);
   double azimuth = LatLon.rhumbAzimuth(begin, end).degrees;
   assertEquals("Trivial West rhumbAzimuth", -90.0, azimuth, THRESHOLD);
 }
Example #9
0
  /**
   * Subdivide a list of positions so that no segment is longer then the provided maxLength. Only
   * the positions between start and start + count - 1 will be processed.
   *
   * <p>If needed, new intermediate positions will be created along lines that follow the given
   * pathType - one of Polyline.LINEAR, Polyline.RHUMB_LINE or Polyline.GREAT_CIRCLE. All position
   * elevations will be either at the terrain surface if followTerrain is true, or interpolated
   * according to the original elevations.
   *
   * @param globe the globe to draw elevations and points from.
   * @param positions the original position list
   * @param maxLength the maximum length for one segment.
   * @param followTerrain true if the positions should be on the terrain surface.
   * @param pathType the type of path to use in between two positions.
   * @param start the first position indice in the original list.
   * @param count how many positions from the original list have to be processed and returned.
   * @return a list of positions with no segment longer then maxLength and elevations following
   *     terrain or not.
   */
  protected static ArrayList<? extends Position> subdividePositions(
      Globe globe,
      ArrayList<? extends Position> positions,
      double maxLength,
      boolean followTerrain,
      String pathType,
      int start,
      int count) {
    if (positions == null || positions.size() < start + count) return positions;

    ArrayList<Position> newPositions = new ArrayList<Position>();
    // Add first position
    Position pos1 = positions.get(start);
    if (followTerrain)
      newPositions.add(
          new Position(pos1, globe.getElevation(pos1.getLatitude(), pos1.getLongitude())));
    else newPositions.add(pos1);
    for (int i = 1; i < count; i++) {
      Position pos2 = positions.get(start + i);
      double arcLengthRadians = LatLon.greatCircleDistance(pos1, pos2).radians;
      double arcLength = arcLengthRadians * globe.getRadiusAt(LatLon.interpolate(.5, pos1, pos2));
      if (arcLength > maxLength) {
        // if necessary subdivide segment at regular intervals smaller then maxLength
        Angle segmentAzimuth = null;
        Angle segmentDistance = null;
        int steps = (int) Math.ceil(arcLength / maxLength); // number of intervals - at least two
        for (int j = 1; j < steps; j++) {
          float s = (float) j / steps;
          LatLon destLatLon;
          if (pathType.equals(AVKey.LINEAR)) {
            destLatLon = LatLon.interpolate(s, pos1, pos2);
          } else if (pathType.equals(AVKey.RHUMB_LINE)) {
            if (segmentAzimuth == null) {
              segmentAzimuth = LatLon.rhumbAzimuth(pos1, pos2);
              segmentDistance = LatLon.rhumbDistance(pos1, pos2);
            }
            destLatLon =
                LatLon.rhumbEndPosition(pos1, segmentAzimuth.radians, s * segmentDistance.radians);
          } else // GREAT_CIRCLE
          {
            if (segmentAzimuth == null) {
              segmentAzimuth = LatLon.greatCircleAzimuth(pos1, pos2);
              segmentDistance = LatLon.greatCircleDistance(pos1, pos2);
            }
            destLatLon =
                LatLon.greatCircleEndPosition(
                    pos1, segmentAzimuth.radians, s * segmentDistance.radians);
          }
          // Set elevation
          double elevation;
          if (followTerrain)
            elevation = globe.getElevation(destLatLon.getLatitude(), destLatLon.getLongitude());
          else elevation = pos1.elevation * (1 - s) + pos2.elevation * s;
          // Add new position
          newPositions.add(new Position(destLatLon, elevation));
        }
      }
      // Finally add the segment end position
      if (followTerrain)
        newPositions.add(
            new Position(pos2, globe.getElevation(pos2.getLatitude(), pos2.getLongitude())));
      else newPositions.add(pos2);
      // Prepare for next segment
      pos1 = pos2;
    }
    return newPositions;
  }