Skip to content

Commit

Permalink
Implement rhumbBearing function and test (#109)
Browse files Browse the repository at this point in the history
* initial commit, stolen from @armantorkzaban

* fix formatting

* cleanup comments
  • Loading branch information
lukas-h authored Jul 4, 2022
1 parent 1e83297 commit ea56d89
Show file tree
Hide file tree
Showing 7 changed files with 218 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Any new benchmarks must be named `*_benchmark.dart` and reside in the
- [ ] pointOnFeature
- [ ] polygonTangents
- [ ] pointToLineDistance
- [ ] rhumbBearing
- [x] [rhumbBearing](https://github.com/dartclub/turf_dart/blob/main/lib/src/rhumb_bearing.dart)
- [ ] rhumbDestination
- [ ] rhumbDistance
- [ ] square
Expand Down
1 change: 1 addition & 0 deletions lib/bearing.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
library turf_bearing;

export 'src/bearing.dart';
export 'src/rhumb_bearing.dart';
64 changes: 64 additions & 0 deletions lib/src/rhumb_bearing.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// https://en.wikipedia.org/wiki/Rhumb_line
import 'package:turf/src/invariant.dart';
import 'dart:math' as math;
import '../helpers.dart';

/// Takes two [Point] and finds the bearing angle between them along a Rhumb line
/// i.e. the angle measured in degrees start the north line (0 degrees)
/// [kFinal] calculates the final bearing if true.
/// Returns bearing from north in decimal degrees, between -180 and 180 degrees (positive clockwise)
/// example:
/// ```dart
/// var point1 = Feature(geometry: Point(coordinates: Position.of([-75.343, 39.984])), properties: {"marker-color": "#F00"});
/// var point2 = Feature(geometry: Point(coordinates: Position.of([-75.534, 39.123])), properties: {"marker-color": "#00F"});
/// var bearing = rhumbBearing(point1.geometry, point2.geometry);
/// //addToMap
/// var addToMap = [point1, point2];
/// point1.properties['bearing'] = bearing;
/// point2.properties['bearing'] = bearing;
/// ```
num rhumbBearing(Point start, Point end, {bool kFinal = false}) {
num bear360;
if (kFinal) {
bear360 = calculateRhumbBearing(getCoord(end), getCoord(start));
} else {
bear360 = calculateRhumbBearing(getCoord(start), getCoord(end));
}

var bear180 = bear360 > 180 ? -(360 - bear360) : bear360;

return bear180;
}

/// Returns the bearing from ‘this’ [Point] to destination [Point] along a rhumb line.
/// Adapted from Geodesy: https://github.com/chrisveness/geodesy/blob/master/latlon-spherical.js
/// Returns Bearing in degrees from north.
/// example
/// ```dart
/// var p1 = Position.named(lng: 51.127, lat: 1.338);
/// var p2 = Position.named(lng: 50.964, lat: 1.853);
/// var d = p1.rhumbBearingTo(p2); // 116.7 m
/// ```
num calculateRhumbBearing(Position from, Position to) {
// φ => phi
// Δλ => deltaLambda
// Δψ => deltaPsi
// θ => theta
num phi1 = degreesToRadians(from.lat);
num phi2 = degreesToRadians(to.lat);
num deltaLambda = degreesToRadians(to.lng - from.lng);
// if deltaLambda over 180° take shorter rhumb line across the anti-meridian:
if (deltaLambda > math.pi) {
deltaLambda -= 2 * math.pi;
}
if (deltaLambda < -math.pi) {
deltaLambda += 2 * math.pi;
}

double deltaPsi = math
.log(math.tan(phi2 / 2 + math.pi / 4) / math.tan(phi1 / 2 + math.pi / 4));

double theta = math.atan2(deltaLambda, deltaPsi);

return (radiansToDegrees(theta) + 360) % 360;
}
46 changes: 46 additions & 0 deletions test/components/rhumb_bearing_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import 'dart:convert';
import 'dart:io';

import 'package:test/test.dart';
import 'package:turf/helpers.dart';
import 'package:turf/src/rhumb_bearing.dart';

main() {
group(
'',
() {
Directory inDir = Directory('./test/examples/rhumb_bearing/in');
for (var file in inDir.listSync(recursive: true)) {
if (file is File && file.path.endsWith('.geojson')) {
test(
file.path,
() {
var inSource = file.readAsStringSync();
var inGeom = GeoJSONObject.fromJson(jsonDecode(inSource));

var start = (inGeom as FeatureCollection).features[0];
var end = inGeom.features[1];
var initialBearing =
rhumbBearing(start.geometry as Point, end.geometry as Point);
var finalBearing = rhumbBearing(
start.geometry as Point, end.geometry as Point,
kFinal: true);
var result = {
'initialBearing': initialBearing,
'finalBearing': finalBearing,
};

Directory outDir = Directory('./test/examples/rhumb_bearing/out');
for (var file in outDir.listSync(recursive: true)) {
if (file is File && file.path.endsWith('.json')) {
var outSource = jsonDecode(file.readAsStringSync());
expect(result, outSource);
}
}
},
);
}
}
},
);
}
31 changes: 31 additions & 0 deletions test/examples/rhumb_bearing/in/pair1.geojson
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"marker-color": "#F00"
},
"geometry": {
"type": "Point",
"coordinates": [
-75,
45
]
}
},
{
"type": "Feature",
"properties": {
"marker-color": "#00F"
},
"geometry": {
"type": "Point",
"coordinates": [
20,
60
]
}
}
]
}
71 changes: 71 additions & 0 deletions test/examples/rhumb_bearing/out/pair1.geojson
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"marker-color": "#F00"
},
"geometry": {
"type": "Point",
"coordinates": [
-75,
45
]
}
},
{
"type": "Feature",
"properties": {
"marker-color": "#00F"
},
"geometry": {
"type": "Point",
"coordinates": [
20,
60
]
}
},
{
"type": "Feature",
"properties": {
"stroke": "#F00",
"stroke-width": 6
},
"geometry": {
"type": "LineString",
"coordinates": [
[
-75,
45
],
[
-66.10068737769872,
51.79325008492101
]
]
}
},
{
"type": "Feature",
"properties": {
"stroke": "#00F",
"stroke-width": 6
},
"geometry": {
"type": "LineString",
"coordinates": [
[
20,
60
],
[
2.3844816279733956,
63.440396381483744
]
]
}
}
]
}
4 changes: 4 additions & 0 deletions test/examples/rhumb_bearing/out/pair1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"initialBearing": 75.28061364784332,
"finalBearing": -104.7193863521567
}

0 comments on commit ea56d89

Please sign in to comment.