Skip to content

Commit

Permalink
Added new nearestPointOnLine default and custom distance unit (#1058)
Browse files Browse the repository at this point in the history
  • Loading branch information
Langston Smith authored Jun 25, 2019
1 parent a4b4f05 commit faa62bf
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 10 deletions.
40 changes: 30 additions & 10 deletions services-turf/src/main/java/com/mapbox/turf/TurfMisc.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand All @@ -219,25 +220,46 @@ public static LineString lineSliceAlong(@NonNull LineString line,
*/
@NonNull
public static Feature nearestPointOnLine(@NonNull Point pt, @NonNull List<Point> 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<Point> 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++) {
Feature start = Feature.fromGeometry(coords.get(i));
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(),
Expand All @@ -246,11 +268,9 @@ public static Feature nearestPointOnLine(@NonNull Point pt, @NonNull List<Point>
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(),
Expand All @@ -267,7 +287,7 @@ public static Feature nearestPointOnLine(@NonNull Point pt, @NonNull List<Point>
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")
Expand Down
24 changes: 24 additions & 0 deletions services-turf/src/test/java/com/mapbox/turf/TurfMiscTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,30 @@ public void testTurfPointOnLinePointsOnSidesOfLines() throws TurfException {
}
}

@Test
public void testTurfPointOnLinePointsOnSidesOfLinesCustomUnit() throws TurfException {
List<Point> 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<Point> 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));
Expand Down

0 comments on commit faa62bf

Please sign in to comment.