-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement
pointToLineDistance
(#189)
- Loading branch information
Showing
26 changed files
with
726 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
library turf_point_to_line_distance; | ||
|
||
export 'package:geotypes/geotypes.dart'; | ||
export 'src/point_to_line_distance.dart'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import 'package:turf/distance.dart'; | ||
import 'package:turf/line_segment.dart'; | ||
import 'helpers.dart'; | ||
|
||
// Sourced from https://turfjs.org (MIT license) and from | ||
// http://geomalgorithms.com/a02-_lines.html | ||
|
||
/// Returns the minimum distance between a [point] and a [line], being the | ||
/// distance from a line the minimum distance between the point and any | ||
/// segment of the [LineString]. | ||
/// | ||
/// Example: | ||
/// ```dart | ||
/// final point = Point(coordinates: Position(0, 0)); | ||
/// final line = LineString(coordinates: [Position(1, 1), Position(-1, 1)]); | ||
/// | ||
/// final distance = pointToLineDistance(point, line, unit: Unit.miles); | ||
/// // distance == 69.11854715938406 | ||
/// ``` | ||
num pointToLineDistance( | ||
Point point, | ||
LineString line, { | ||
Unit unit = Unit.kilometers, | ||
DistanceGeometry method = DistanceGeometry.geodesic, | ||
}) { | ||
var distance = double.infinity; | ||
final position = point.coordinates; | ||
|
||
segmentEach(line, (segment, _, __, ___, ____) { | ||
final a = segment.geometry!.coordinates[0]; | ||
final b = segment.geometry!.coordinates[1]; | ||
final d = _distanceToSegment(position, a, b, method: method); | ||
|
||
if (d < distance) { | ||
distance = d.toDouble(); | ||
} | ||
}); | ||
|
||
return convertLength(distance, Unit.degrees, unit); | ||
} | ||
|
||
/// Returns the distance between a point P on a segment AB. | ||
num _distanceToSegment( | ||
Position p, | ||
Position a, | ||
Position b, { | ||
required DistanceGeometry method, | ||
}) { | ||
final v = b - a; | ||
final w = p - a; | ||
|
||
final c1 = w.dotProduct(v); | ||
if (c1 <= 0) { | ||
return _calcDistance(p, a, method: method, unit: Unit.degrees); | ||
} | ||
|
||
final c2 = v.dotProduct(v); | ||
if (c2 <= c1) { | ||
return _calcDistance(p, b, method: method, unit: Unit.degrees); | ||
} | ||
|
||
final b2 = c1 / c2; | ||
final pb = a + Position(v[0]! * b2, v[1]! * b2); | ||
return _calcDistance(p, pb, method: method, unit: Unit.degrees); | ||
} | ||
|
||
num _calcDistance( | ||
Position a, | ||
Position b, { | ||
required Unit unit, | ||
required DistanceGeometry method, | ||
}) { | ||
if (method == DistanceGeometry.planar) { | ||
return rhumbDistance(Point(coordinates: a), Point(coordinates: b), unit); | ||
} | ||
|
||
// Otherwise DistanceGeometry.geodesic | ||
return distanceRaw(a, b, unit); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import 'dart:convert'; | ||
import 'dart:io'; | ||
|
||
import 'package:test/test.dart'; | ||
import 'package:turf/helpers.dart'; | ||
import 'package:turf/src/point_to_line_distance.dart'; | ||
|
||
final distances = { | ||
"city-line1.geojson": 1.0299686758, | ||
"city-line2.geojson": 3.6186172981, | ||
"city-segment-inside1.geojson": 1.1489389115, | ||
"city-segment-inside2.geojson": 1.0280898152, | ||
"city-segment-inside3.geojson": 3.5335695907, | ||
"city-segment-obtuse1.geojson": 2.8573246363, | ||
"city-segment-obtuse2.geojson": 3.3538913334, | ||
"city-segment-projected1.geojson": 3.5886611693, | ||
"city-segment-projected2.geojson": 4.163469898, | ||
"issue-1156.geojson": 189.6618028794, | ||
"line-fiji.geojson": 27.1266612008, | ||
"line-resolute-bay.geojson": 425.0745081528, | ||
"line1.geojson": 23.4224834672, | ||
"line2.geojson": 188.015686924, | ||
"segment-fiji.geojson": 27.6668301762, | ||
"segment1.geojson": 69.0934195756, | ||
"segment1a.geojson": 69.0934195756, | ||
"segment2.geojson": 69.0934195756, | ||
"segment3.geojson": 69.0828960461, | ||
"segment4.geojson": 332.8803863574 | ||
}; | ||
|
||
void main() { | ||
group('pointToLineDistance', () { | ||
group('in == out', () { | ||
final inDir = Directory('./test/examples/point_to_line_distance/in'); | ||
|
||
for (final file in inDir.listSync(recursive: true)) { | ||
if (file is File && file.path.endsWith('.geojson')) { | ||
testFile(file); | ||
} | ||
} | ||
}); | ||
|
||
group('unit tests', () { | ||
testPlanarGeodesic(); | ||
}); | ||
}); | ||
} | ||
|
||
void testFile(File file) { | ||
test(file.path, () { | ||
final inSource = file.readAsStringSync(); | ||
final collection = FeatureCollection.fromJson(jsonDecode(inSource)); | ||
|
||
final rawPoint = collection.features[0]; | ||
final rawLine = collection.features[1]; | ||
|
||
final point = Feature<Point>.fromJson(rawPoint.toJson()); | ||
final line = Feature<LineString>.fromJson(rawLine.toJson()); | ||
|
||
final properties = rawPoint.properties ?? {}; | ||
final unitRaw = properties["units"] as String?; | ||
|
||
var unit = Unit.kilometers; | ||
if (unitRaw == 'meters') { | ||
unit = Unit.meters; | ||
} else if (unitRaw == 'miles') { | ||
unit = Unit.miles; | ||
} else { | ||
expect(unitRaw, null, reason: '"units" was given but not handled.'); | ||
} | ||
|
||
final distance = | ||
pointToLineDistance(point.geometry!, line.geometry!, unit: unit); | ||
|
||
final name = file.path.substring(file.path.lastIndexOf('/') + 1); | ||
|
||
expect(distance, closeTo(distances[name]!, 0.01)); | ||
}); | ||
} | ||
|
||
void testPlanarGeodesic() { | ||
test('Check planar and geodesic results are different', () { | ||
final pt = Point(coordinates: Position(0, 0)); | ||
final line = LineString(coordinates: [ | ||
Position(10, 10), | ||
Position(-1, 1), | ||
]); | ||
|
||
final geoOut = | ||
pointToLineDistance(pt, line, method: DistanceGeometry.geodesic); | ||
final planarOut = | ||
pointToLineDistance(pt, line, method: DistanceGeometry.planar); | ||
|
||
expect(geoOut, isNot(equals(planarOut))); | ||
}); | ||
} |
30 changes: 30 additions & 0 deletions
30
test/examples/point_to_line_distance/in/city-line1.geojson
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{ | ||
"type": "FeatureCollection", | ||
"features": [ | ||
{ | ||
"type": "Feature", | ||
"properties": {}, | ||
"geometry": { | ||
"type": "Point", | ||
"coordinates": [-0.3767967224121093, 39.4689324766527] | ||
} | ||
}, | ||
{ | ||
"type": "Feature", | ||
"properties": {}, | ||
"geometry": { | ||
"type": "LineString", | ||
"coordinates": [ | ||
[-0.40567874908447266, 39.47386857192064], | ||
[-0.3963661193847656, 39.47578991028725], | ||
[-0.38035869598388666, 39.482216070269594], | ||
[-0.3776121139526367, 39.48195108571802], | ||
[-0.3689002990722656, 39.47641930269614], | ||
[-0.35945892333984375, 39.46349905420083], | ||
[-0.35782814025878906, 39.45982131412374], | ||
[-0.3458118438720703, 39.453890134716616] | ||
] | ||
} | ||
} | ||
] | ||
} |
27 changes: 27 additions & 0 deletions
27
test/examples/point_to_line_distance/in/city-line2.geojson
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"type": "FeatureCollection", | ||
"features": [ | ||
{ | ||
"type": "Feature", | ||
"properties": {}, | ||
"geometry": { | ||
"type": "Point", | ||
"coordinates": [-3.592529296875, 40.573804799488194] | ||
} | ||
}, | ||
{ | ||
"type": "Feature", | ||
"properties": {}, | ||
"geometry": { | ||
"type": "LineString", | ||
"coordinates": [ | ||
[-3.8884735107421875, 40.420292132688964], | ||
[-3.736724853515625, 40.276906410822825], | ||
[-3.5025787353515625, 40.422383097039905], | ||
[-3.5018920898437496, 40.516409213865586], | ||
[-3.668060302734375, 40.559199680578075] | ||
] | ||
} | ||
} | ||
] | ||
} |
26 changes: 26 additions & 0 deletions
26
test/examples/point_to_line_distance/in/city-segment-inside1.geojson
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
{ | ||
"type": "FeatureCollection", | ||
"features": [ | ||
{ | ||
"type": "Feature", | ||
"properties": { | ||
"units": "miles" | ||
}, | ||
"geometry": { | ||
"type": "Point", | ||
"coordinates": [-6.0047149658203125, 37.365109304227246] | ||
} | ||
}, | ||
{ | ||
"type": "Feature", | ||
"properties": {}, | ||
"geometry": { | ||
"type": "LineString", | ||
"coordinates": [ | ||
[-6.0150146484375, 37.38011551844836], | ||
[-5.931415557861328, 37.39702801486944] | ||
] | ||
} | ||
} | ||
] | ||
} |
24 changes: 24 additions & 0 deletions
24
test/examples/point_to_line_distance/in/city-segment-inside2.geojson
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"type": "FeatureCollection", | ||
"features": [ | ||
{ | ||
"type": "Feature", | ||
"properties": {}, | ||
"geometry": { | ||
"type": "Point", | ||
"coordinates": [-0.3767967224121093, 39.4689324766527] | ||
} | ||
}, | ||
{ | ||
"type": "Feature", | ||
"properties": {}, | ||
"geometry": { | ||
"type": "LineString", | ||
"coordinates": [ | ||
[-0.3689861297607422, 39.47648555419739], | ||
[-0.3595447540283203, 39.46363158174706] | ||
] | ||
} | ||
} | ||
] | ||
} |
24 changes: 24 additions & 0 deletions
24
test/examples/point_to_line_distance/in/city-segment-inside3.geojson
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"type": "FeatureCollection", | ||
"features": [ | ||
{ | ||
"type": "Feature", | ||
"properties": {}, | ||
"geometry": { | ||
"type": "Point", | ||
"coordinates": [-3.592529296875, 40.573804799488194] | ||
} | ||
}, | ||
{ | ||
"type": "Feature", | ||
"properties": {}, | ||
"geometry": { | ||
"type": "LineString", | ||
"coordinates": [ | ||
[-3.503265380859375, 40.51693121343741], | ||
[-3.6694335937500004, 40.560764667193595] | ||
] | ||
} | ||
} | ||
] | ||
} |
24 changes: 24 additions & 0 deletions
24
test/examples/point_to_line_distance/in/city-segment-obtuse1.geojson
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"type": "FeatureCollection", | ||
"features": [ | ||
{ | ||
"type": "Feature", | ||
"properties": {}, | ||
"geometry": { | ||
"type": "Point", | ||
"coordinates": [-6.030292510986328, 37.35746862390723] | ||
} | ||
}, | ||
{ | ||
"type": "Feature", | ||
"properties": {}, | ||
"geometry": { | ||
"type": "LineString", | ||
"coordinates": [ | ||
[-6.0150146484375, 37.38011551844836], | ||
[-5.931415557861328, 37.39702801486944] | ||
] | ||
} | ||
} | ||
] | ||
} |
Oops, something went wrong.