diff --git a/services-turf/src/main/java/com/mapbox/turf/TurfMisc.java b/services-turf/src/main/java/com/mapbox/turf/TurfMisc.java index e109bb31d..8dac9c34d 100644 --- a/services-turf/src/main/java/com/mapbox/turf/TurfMisc.java +++ b/services-turf/src/main/java/com/mapbox/turf/TurfMisc.java @@ -2,6 +2,8 @@ import android.support.annotation.FloatRange; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + import com.mapbox.geojson.Feature; import com.mapbox.geojson.LineString; import com.mapbox.geojson.Point; @@ -207,7 +209,6 @@ public static LineString lineSliceAlong(@NonNull LineString line, return LineString.fromLngLats(slice); } - /** * Takes a {@link Point} and a {@link LineString} and calculates the closest Point on the * LineString. @@ -219,14 +220,35 @@ public static LineString lineSliceAlong(@NonNull LineString line, */ @NonNull public static Feature nearestPointOnLine(@NonNull Point pt, @NonNull List coords) { + return nearestPointOnLine(pt, coords, null); + } + + /** + * Takes a {@link Point} and a {@link LineString} and calculates the closest Point on the + * LineString. + * + * @param pt point to snap from + * @param coords line to snap to + * @param units one of the units found inside {@link TurfConstants.TurfUnitCriteria} + * can be degrees, radians, miles, or kilometers + * @return closest point on the line to point + * @since 4.9.0 + */ + @NonNull + public static Feature nearestPointOnLine(@NonNull Point pt, @NonNull List coords, + @Nullable @TurfConstants.TurfUnitCriteria String units) { if (coords.size() < 2) { throw new TurfException("Turf nearestPointOnLine requires a List of Points " - + "made up of at least 2 coordinates."); + + "made up of at least 2 coordinates."); + } + + if (units == null) { + units = TurfConstants.UNIT_KILOMETERS; } Feature closestPt = Feature.fromGeometry( - Point.fromLngLat(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)); + Point.fromLngLat(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)); closestPt.addNumberProperty("dist", Double.POSITIVE_INFINITY); for (int i = 0; i < coords.size() - 1; i++) { @@ -234,10 +256,10 @@ public static Feature nearestPointOnLine(@NonNull Point pt, @NonNull List Feature stop = Feature.fromGeometry(coords.get(i + 1)); //start start.addNumberProperty("dist", TurfMeasurement.distance( - pt, (Point) start.geometry(), TurfConstants.UNIT_MILES)); + pt, (Point) start.geometry(), units)); //stop stop.addNumberProperty("dist", TurfMeasurement.distance( - pt, (Point) stop.geometry(), TurfConstants.UNIT_MILES)); + pt, (Point) stop.geometry(), units)); //perpendicular double heightDistance = Math.max( start.properties().get("dist").getAsDouble(), @@ -246,11 +268,9 @@ public static Feature nearestPointOnLine(@NonNull Point pt, @NonNull List double direction = TurfMeasurement.bearing((Point) start.geometry(), (Point) stop.geometry()); Feature perpendicularPt1 = Feature.fromGeometry( - TurfMeasurement.destination(pt, heightDistance, direction + 90, - TurfConstants.UNIT_MILES)); + TurfMeasurement.destination(pt, heightDistance, direction + 90, units)); Feature perpendicularPt2 = Feature.fromGeometry( - TurfMeasurement.destination(pt, heightDistance, direction - 90, - TurfConstants.UNIT_MILES)); + TurfMeasurement.destination(pt, heightDistance, direction - 90, units)); LineIntersectsResult intersect = lineIntersects( ((Point) perpendicularPt1.geometry()).longitude(), ((Point) perpendicularPt1.geometry()).latitude(), @@ -267,7 +287,7 @@ public static Feature nearestPointOnLine(@NonNull Point pt, @NonNull List intersectPt = Feature.fromGeometry( Point.fromLngLat(intersect.horizontalIntersection(), intersect.verticalIntersection())); intersectPt.addNumberProperty("dist", TurfMeasurement.distance(pt, - (Point) intersectPt.geometry(), TurfConstants.UNIT_MILES)); + (Point) intersectPt.geometry(), units)); } if ((double) start.getNumberProperty("dist") diff --git a/services-turf/src/test/java/com/mapbox/turf/TurfMiscTest.java b/services-turf/src/test/java/com/mapbox/turf/TurfMiscTest.java index 913b6ee8a..f2b4a1055 100644 --- a/services-turf/src/test/java/com/mapbox/turf/TurfMiscTest.java +++ b/services-turf/src/test/java/com/mapbox/turf/TurfMiscTest.java @@ -345,6 +345,30 @@ public void testTurfPointOnLinePointsOnSidesOfLines() throws TurfException { } } + @Test + public void testTurfPointOnLinePointsOnSidesOfLinesCustomUnit() throws TurfException { + List line = new ArrayList<>(); + line.add(Point.fromLngLat(-122.45616137981413, 37.72125936929241)); + line.add(Point.fromLngLat(-122.45717525482178, 37.718242366859215)); + Point first = line.get(0); + Point last = line.get(1); + + List pts = new ArrayList<>(); + pts.add(Point.fromLngLat(-122.45702505111694, 37.71881098149625)); + pts.add(Point.fromLngLat(-122.45733618736267, 37.719235317933844)); + pts.add(Point.fromLngLat(-122.45686411857605, 37.72027068864082)); + pts.add(Point.fromLngLat(-122.45652079582213, 37.72063561093274)); + + for (Point pt : pts) { + Feature snappedFeature = TurfMisc.nearestPointOnLine(pt, line, TurfConstants.UNIT_MILES); + Point snapped = (Point) snappedFeature.geometry(); + // pt did not snap to first vertex + assertNotEquals(snapped, first); + // pt did not snap to last vertex + assertNotEquals(snapped, last); + } + } + @Test public void testLineSliceAlongLine1() throws IOException, TurfException { Feature line1 = Feature.fromJson(loadJsonFixture(LINE_SLICE_ALONG_LINE_ONE));