if (firstHeading.isPresent() && secondHeading.isPresent()) final Angle candidate = firstHeading.get().difference(secondHeading.get()); if (candidate.isGreaterThan(maximum))
@Override public String toString() { return String.valueOf(this.asDegrees()); } }
/** * @param dm7 * A heading value in degree of magnitude 7 (dm7) * @return The built {@link Heading} object using the dm7 value */ public static Heading dm7(final long dm7) { // Roll dm7 value from 0->360 to the -180->180 that the angle expects. // Heading's circle is 180 degree ahead of Angle's long rollingDm7 = (dm7 - DELTA_DM7) % REVOLUTION_DM7; // After the roll operation, dm7 value could fall into (-180, -360) degrees. // This addition of 360 degrees will shift that degree back into (0, 180) if (rollingDm7 < MINIMUM_DM7) { rollingDm7 += REVOLUTION_DM7; } // After the roll operation, dm7 value could fall into [180, 360) degrees. // This subtraction of 360 degrees will shift that degree back into [-180, 0) if (rollingDm7 >= MAXIMUM_DM7) { rollingDm7 -= REVOLUTION_DM7; } return new Heading((int) rollingDm7); }
Assert.assertEquals(Angle.MAXIMUM, Heading.degrees(-180).difference(Heading.degrees(0))); Assert.assertEquals(Heading.degrees(-180).difference(Heading.degrees(20)), Angle.degrees(160)); Assert.assertEquals(Heading.degrees(-180).difference(Heading.degrees(70)), Angle.degrees(110)); Assert.assertEquals(Heading.degrees(-180).difference(Heading.degrees(90)), Angle.degrees(90)); Assert.assertEquals(Heading.degrees(-180).difference(Heading.degrees(160)), Angle.degrees(20)); Assert.assertEquals(Heading.degrees(-180).difference(Heading.degrees(180)), Angle.degrees(0)); Assert.assertEquals(Heading.degrees(-180).difference(Heading.degrees(200)), Angle.degrees(20)); Assert.assertEquals(Heading.degrees(-180).difference(Heading.degrees(250)), Angle.degrees(70)); Assert.assertEquals(Heading.degrees(-180).difference(Heading.degrees(270)), Angle.degrees(90)); Assert.assertEquals(Heading.degrees(-180).difference(Heading.degrees(290)), Angle.degrees(110)); Assert.assertEquals(Heading.degrees(-180).difference(Heading.degrees(340)), Angle.degrees(160)); Assert.assertEquals(Angle.MAXIMUM, Heading.degrees(-180).difference(Heading.degrees(360))); Assert.assertEquals(Heading.degrees(-180).difference(Heading.degrees(380)), Angle.degrees(160)); Assert.assertEquals(Angle.degrees(90), Heading.degrees(-90).difference(Heading.degrees(0))); Assert.assertEquals(Heading.degrees(-90).difference(Heading.degrees(20)), Angle.degrees(110)); Assert.assertEquals(Heading.degrees(-90).difference(Heading.degrees(70)),
Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(315), Distance.meters(3)), Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(310), Distance.meters(6)), Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(305), Distance.meters(9)), Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(300), Distance.meters(12)), Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(295), Distance.meters(15)), Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(290), Distance.meters(18)), Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(285), Distance.meters(21)), Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(280), Distance.meters(24)), Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(275), Distance.meters(27)), Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(270), Distance.meters(30))); Assert.assertFalse(halfCircleLike.isApproximatelyNSided(1, Angle.MINIMUM));
public boolean isSameDirection(final Heading headingA, final Heading headingB) { final Angle headingDifference = headingB.subtract(headingA); final boolean sameDirection = headingDifference .isGreaterThanOrEqualTo(this.sameDirectionLowerLimit) && headingDifference.isLessThan(this.sameDirectionUpperLimit); return sameDirection; }
/** * @param radians * A heading value in Radians * @return The built {@link Heading} object using the Radians value */ public static Heading radians(final double radians) { return dm7(Math.round(radians * DM7_PER_RADIAN)); }
/** * This computes the initial heading (heading at the start point) of the segment on the surface * of earth between two locations * * @see "http://www.movable-type.co.uk/scripts/latlong.html" * @param that * The other point to compute the heading to * @return The heading between two points */ public Heading headingTo(final Location that) { if (this.equals(that)) { throw new CoreException("Cannot compute some heading when two points are the same."); } // convert to radians final double lat1 = this.getLatitude().asRadians(); final double lon1 = this.getLongitude().asRadians(); final double lat2 = that.getLatitude().asRadians(); final double lon2 = that.getLongitude().asRadians(); final double deltaLon = lon2 - lon1; final double yAxis = Math.sin(deltaLon) * Math.cos(lat2); final double xAxis = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(deltaLon); return Heading.radians(Math.atan2(yAxis, xAxis)); }
final double bearing = initialHeading.asRadians();
Assert.assertEquals(Angle.NONE, Heading.degrees(-180).difference(Angle.degrees(0))); Assert.assertEquals(Angle.degrees(20), Heading.degrees(-180).difference(Angle.degrees(20))); Assert.assertEquals(Angle.degrees(70), Heading.degrees(-180).difference(Angle.degrees(70))); Assert.assertEquals(Angle.degrees(90), Heading.degrees(-180).difference(Angle.degrees(90))); Assert.assertEquals(Heading.degrees(-180).difference(Angle.degrees(160)), Angle.degrees(160)); Assert.assertEquals(Angle.MAXIMUM, Heading.degrees(-180).difference(Angle.degrees(180))); Assert.assertEquals(Heading.degrees(-180).difference(Angle.degrees(200)), Angle.degrees(160)); Assert.assertEquals(Heading.degrees(-180).difference(Angle.degrees(250)), Angle.degrees(110)); Assert.assertEquals(Heading.degrees(-180).difference(Angle.degrees(270)), Angle.degrees(90)); Assert.assertEquals(Heading.degrees(-180).difference(Angle.degrees(290)), Angle.degrees(70)); Assert.assertEquals(Heading.degrees(-180).difference(Angle.degrees(340)), Angle.degrees(20)); Assert.assertEquals(Angle.NONE, Heading.degrees(-180).difference(Angle.degrees(360))); Assert.assertEquals(Heading.degrees(-180).difference(Angle.degrees(380)), Angle.degrees(20)); Assert.assertEquals(Angle.degrees(90), Heading.degrees(-90).difference(Angle.degrees(0))); Assert.assertEquals(Angle.degrees(70), Heading.degrees(-90).difference(Angle.degrees(20))); Assert.assertEquals(Angle.degrees(20), Heading.degrees(-90).difference(Angle.degrees(70))); Assert.assertEquals(Angle.NONE, Heading.degrees(-90).difference(Angle.degrees(90))); Assert.assertEquals(Angle.degrees(70), Heading.degrees(-90).difference(Angle.degrees(160))); Assert.assertEquals(Angle.degrees(90), Heading.degrees(-90).difference(Angle.degrees(180))); Assert.assertEquals(Heading.degrees(-90).difference(Angle.degrees(200)), Angle.degrees(110));
@Test public void testIsApproximatelyNSidedTriangleLike3() { // Test another triangular like shape with several additional inner points // POLYGON ((-122.003467 37.324233, -122.0034571 37.3242374, -122.0033991 37.3242654, // -122.0033691 37.324278, -122.0035536 37.3242908, -122.0034922 37.3242511, -122.003467 // 37.324233)) final Polygon polygon = new Polygon(Location.STEVENS_CREEK, Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(61), Distance.meters(1)), Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(59), Distance.meters(7)), Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(60), Distance.meters(10)), Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(310), Distance.meters(10)), Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(312), Distance.meters(3))); Assert.assertFalse(polygon.isApproximatelyNSided(1, Angle.MINIMUM)); Assert.assertFalse(polygon.isApproximatelyNSided(1, Angle.MAXIMUM)); Assert.assertFalse(polygon.isApproximatelyNSided(2, Angle.MINIMUM)); Assert.assertFalse(polygon.isApproximatelyNSided(2, Angle.MAXIMUM)); Assert.assertFalse(polygon.isApproximatelyNSided(3, Angle.MINIMUM)); Assert.assertFalse(polygon.isApproximatelyNSided(3, Angle.degrees(0.1))); Assert.assertFalse(polygon.isApproximatelyNSided(3, Angle.degrees(0.5))); Assert.assertFalse(polygon.isApproximatelyNSided(3, Angle.degrees(1))); Assert.assertFalse(polygon.isApproximatelyNSided(3, Angle.degrees(2))); Assert.assertTrue(polygon.isApproximatelyNSided(3, Angle.degrees(3))); Assert.assertTrue(polygon.isApproximatelyNSided(3, Angle.degrees(30))); }
public boolean isOppositeDirection(final Heading incomingEdgeHeading, final Heading outgoingEdgeHeading) { final Angle headingDifference = incomingEdgeHeading.subtract(outgoingEdgeHeading); return headingDifference.isGreaterThanOrEqualTo(this.oppositeDirectionLowerLimit) || headingDifference.isLessThan(this.oppositeDirectionUpperLimit); }
/** * @param degrees * A heading value in degrees * @return The built {@link Heading} object using the degrees value */ public static Heading degrees(final double degrees) { return dm7(Math.round(degrees * DM7_PER_DEGREE)); }
/** * @return The location of the biggest Angle in this {@link PolyLine} */ public Optional<Location> maximumAngleLocation() { final List<Segment> segments = segments(); if (segments.isEmpty() || segments.size() == 1) { return Optional.empty(); } Angle maximum = Angle.NONE; Location maximumAngleLocation = null; for (int i = 1; i < segments.size(); i++) { final Segment first = segments.get(i - 1); final Segment second = segments.get(i); final Optional<Heading> firstHeading = first.heading(); final Optional<Heading> secondHeading = second.heading(); if (firstHeading.isPresent() && secondHeading.isPresent()) { final Angle candidate = firstHeading.get().difference(secondHeading.get()); if (candidate.isGreaterThan(maximum) || maximumAngleLocation == null) { maximum = candidate; maximumAngleLocation = first.end(); } } } return Optional.ofNullable(maximumAngleLocation); }
@Test public void testHeadingTo() { final Location location1 = new Location(Latitude.degrees(37.336900), Longitude.degrees(-122.005414)); final Location location2 = new Location(Latitude.degrees(37.332758), Longitude.degrees(-122.005409)); Assert.assertTrue(Heading.degrees(180).difference(location1.headingTo(location2)) .isLessThan(Angle.degrees(1))); }
@Test public void testCrossingAntimeridian() { final Location one = new Location(Latitude.degrees(37), Longitude.degrees(179.998)); final Location two = new Location(Latitude.degrees(37), Longitude.degrees(179.999)); // This one is actually -180.0 final Location thr = new Location(Latitude.degrees(37), Longitude.degrees(180.0)); final Location fur = new Location(Latitude.degrees(37), Longitude.degrees(-179.999)); logger.info("one equirectangular two: {}", one.equirectangularDistanceTo(two)); logger.info("two equirectangular thr: {}", two.equirectangularDistanceTo(thr)); logger.info("thr equirectangular fur: {}", thr.equirectangularDistanceTo(fur)); logger.info("one haversine two: {}", one.haversineDistanceTo(two)); logger.info("two haversine thr: {}", two.haversineDistanceTo(thr)); logger.info("thr haversine fur: {}", thr.haversineDistanceTo(fur)); logger.info("one mixed two: {}", one.distanceTo(two)); logger.info("two mixed thr: {}", two.distanceTo(thr)); logger.info("thr mixed fur: {}", thr.distanceTo(fur)); logger.info("one heading two: {}", one.headingTo(two)); logger.info("two heading thr: {}", two.headingTo(thr)); logger.info("thr heading fur: {}", thr.headingTo(fur)); Assert.assertEquals(one.distanceTo(two).asMeters(), two.distanceTo(thr).asMeters(), 3); Assert.assertEquals(two.distanceTo(thr).asMeters(), thr.distanceTo(fur).asMeters(), 3); Assert.assertEquals(one.headingTo(two).asDegrees(), two.headingTo(thr).asDegrees(), 3); Assert.assertEquals(two.headingTo(thr).asDegrees(), thr.headingTo(fur).asDegrees(), 3); }
@Test public void testIsApproximatelyNSidedTriangleLike1() { // Test triangular like shape with one additional inner point // POLYGON ((-122.003467 37.324233, -122.003418 37.3242555, -122.0033691 37.324278, // -122.0035536 37.3242908, -122.003467 37.324233)) final Polygon polygon = new Polygon(Location.STEVENS_CREEK, Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(60), Distance.meters(5)), Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(60), Distance.meters(10)), Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(310), Distance.meters(10))); Assert.assertFalse(polygon.isApproximatelyNSided(1, Angle.MINIMUM)); Assert.assertFalse(polygon.isApproximatelyNSided(1, Angle.MAXIMUM)); Assert.assertFalse(polygon.isApproximatelyNSided(2, Angle.MINIMUM)); Assert.assertFalse(polygon.isApproximatelyNSided(2, Angle.MAXIMUM)); Assert.assertFalse(polygon.isApproximatelyNSided(3, Angle.MINIMUM)); Assert.assertTrue(polygon.isApproximatelyNSided(3, Angle.degrees(0.1))); Assert.assertTrue(polygon.isApproximatelyNSided(3, Angle.degrees(1))); Assert.assertTrue(polygon.isApproximatelyNSided(3, Angle.degrees(30))); }
return Optional.of(heading2.get().subtract(heading1.get()));
if (firstHeading.isPresent() && secondHeading.isPresent()) final Angle candidate = firstHeading.get().difference(secondHeading.get()); if (candidate.isLessThanOrEqualTo(target))
@Test public void testIsApproximatelyNSidedTriangleLike2() { // Test another triangular like shape with one additional inner point // POLYGON ((-122.05576 37.332439, -122.055711 37.3324615, -122.055662 37.332484, // -122.0558466 37.3324968, -122.05576 37.332439)) final Polygon polygon = new Polygon(Location.STEVENS_CREEK, Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(59), Distance.meters(5)), Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(60), Distance.meters(10)), Location.STEVENS_CREEK.shiftAlongGreatCircle(Heading.degrees(310), Distance.meters(10))); Assert.assertFalse(polygon.isApproximatelyNSided(1, Angle.MINIMUM)); Assert.assertFalse(polygon.isApproximatelyNSided(1, Angle.MAXIMUM)); Assert.assertFalse(polygon.isApproximatelyNSided(2, Angle.MINIMUM)); Assert.assertFalse(polygon.isApproximatelyNSided(2, Angle.MAXIMUM)); Assert.assertFalse(polygon.isApproximatelyNSided(3, Angle.MINIMUM)); Assert.assertFalse(polygon.isApproximatelyNSided(3, Angle.degrees(0.1))); Assert.assertFalse(polygon.isApproximatelyNSided(3, Angle.degrees(0.5))); Assert.assertFalse(polygon.isApproximatelyNSided(3, Angle.degrees(1))); Assert.assertFalse(polygon.isApproximatelyNSided(3, Angle.degrees(2))); Assert.assertTrue(polygon.isApproximatelyNSided(3, Angle.degrees(3))); Assert.assertTrue(polygon.isApproximatelyNSided(3, Angle.degrees(30))); }