Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added new nearestPointOnLine default and custom distance unit #1058

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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