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

Documentation #75

Merged
merged 12 commits into from
Apr 15, 2022
94 changes: 94 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Contributiung to Turf.dart

Welcome and thank you for deciding to contribute to the project!

Here is how cooperation works perfectly at [Turf Dart](https://github.com/dartclub/turf_dart)
#### Table of Contents
- [Code of Conduct](#code-of-conduct)
- [Get started](#get-started)
- [Structure of modules](#structure-of-modules)
- [Implementation Process](#implementation-process)
- [Documentation](#documentation)
- [GeoJSON object model](#GeoJSON-object-model)

## Code of conduct
By participating, you are expected to uphold international human rights and fundamental freedoms!
To put it simply, be kind to each other.

## Get started
- Get the [Dart tools](https://dart.dev/tools)
- Clone the repository: ```git clone [email protected]:dartclub/turf_dart.git```
- Navigate to project's folder in terminal & get its dependencies: ```dart pub get```
- Go through [Implementation Process](#implementation-process)
- Import the library in your code and use it. For example:
```dart
import 'package:turf/helpers.dart';
import 'package:turf/src/line_segment.dart';

Feature<Polygon> poly = Feature<Polygon>(
geometry: Polygon(coordinates: [
[
Position(0, 0),
Position(2, 2),
Position(0, 1),
Position(0, 0),
],
[
Position(0, 0),
Position(1, 1),
Position(0, 1),
Position(0, 0),
],
]),
);

var total = segmentReduce<int>(poly, (previousValue,
currentSegment,
initialValue,
featureIndex,
multiFeatureIndex,
geometryIndex,
segmentIndex) {
if (previousValue != null) {
armantorkzaban marked this conversation as resolved.
Show resolved Hide resolved
previousValue++;
}
return previousValue;
}, 0, combineNestedGeometries: false);
// total.length == 6
```
## Structure of modules
```
TURF_DART/lib/<MODULE NAME>.dart // public facing API, exports the implementation
│ │
│ └───src/<MODULE NAME>.dart // the implementation
└───benchmark/<MODULE NAME>_benchmark.dart
└───test/components/<MODULE NAME>_test.dart // all the related tests
armantorkzaban marked this conversation as resolved.
Show resolved Hide resolved
```
## Implementation process
- Check the Backlog/Issues for similar issues
- Create a new branch _feature-_ from _main_
- Create a _draft Pull request_, mention in it the associated issues
- **Implement**
- Document everything [properly](#documentation)
- If you are importing tests, comments etc. from [Turfjs](https://github.com/Turfjs/turf), please make sure you refactor it so it conforms with Dart syntax.
- **Write [tests](https://dart.dev/guides/testing)**―Keep an eye on [Turfjs'](https://github.com/Turfjs/turf) implementation
- run the the test: ```dart test test/components/XXX.dart```
- **Write [benchmarks](https://pub.dev/packages/benchmark)**―have a look at our [implementation](https://github.com/dartclub/turf_dart/tree/main/benchmark)
- run the benchmark: ```dart pub run benchmark```
- Commit
- Convert to real Pull request _ready for review_
- Code review / mention a reviewer from [contributors list](https://github.com/dartclub/turf_dart/graphs/contributors)


## Documentation
We follow [Effective Dart](https://dart.dev/guides/language/effective-dart/documentation) guidelines for documentation.

After going through the [Implementation Process](#implementation-process), please mention the made changes in [README.md](https://github.com/dartclub/turf_dart/blob/main/README.md)

In order to add to this very documentation, please develop CONTRIBUTING.md in [documentation branch](https://github.com/dartclub/turf_dart/tree/documentation)

## GeoJSON Object Model
If you have not read our [README.md](https://github.com/dartclub/turf_dart/blob/main/README.md) this diagram will give you a lot of information. Please consider looking our [notable design decisions](https://github.com/dartclub/turf_dart/blob/main/README.md#notable-design-decisions).
![polymorphism](https://user-images.githubusercontent.com/10634693/159876354-f9da2f37-02b3-4546-b32a-c0f82c372272.png)
2 changes: 0 additions & 2 deletions benchmark/cluster_benchmark.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@ void main() {

benchmark('clusterEach', () {
List clusters = [];
int total = 0;
clusterEach(featureCollection, "cluster",
(cluster, clusterValue, currentIndex) {
total += cluster!.features.length;
clusters.add(cluster);
});
});
Expand Down
20 changes: 20 additions & 0 deletions lib/src/bearing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import 'dart:math';
import 'geojson.dart';
import 'helpers.dart';

// http://en.wikipedia.org/wiki/Haversine_formula
// http://www.movable-type.co.uk/scripts/latlong.html

num bearingRaw(Position start, Position end, {bool calcFinal = false}) {
// Reverse calculation
if (calcFinal == true) {
Expand All @@ -19,6 +22,22 @@ num bearingRaw(Position start, Position end, {bool calcFinal = false}) {
return radiansToDegrees(atan2(a, b));
}

/// Takes two [Point]s and finds the geographic bearing between them,
/// i.e. the angle measured in degrees from the north line (0 degrees)
/// For example:
///
/// ```dart
/// var point1 = Point(coordinates: Position(-75.343, 39.984));
/// var point2 = Point(coordinates: Position((-75.543, 39.123));
///
/// var bearing = bearing(point1, point2);
/// //addToMap
/// var addToMap = [point1, point2]
/// point1.properties['marker-color'] = '#f00'
/// point2.properties['marker-color'] = '#0f0'
/// point1.properties.bearing = bearing
/// ```

num bearing(Point start, Point end, {bool calcFinal = false}) =>
bearingRaw(start.coordinates, end.coordinates, calcFinal: calcFinal);

Expand All @@ -28,5 +47,6 @@ num calculateFinalBearingRaw(Position start, Position end) {
return reverseBearing.remainder(360);
}

/// Calculates Final Bearing
num calculateFinalBearing(Point start, Point end) =>
calculateFinalBearingRaw(start.coordinates, end.coordinates);
19 changes: 19 additions & 0 deletions lib/src/destination.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,25 @@ Position destinationRaw(Position origin, num distance, num bearing,
);
}

/// Takes a [Point] and calculates the location of a destination point given a distance in
/// degrees, radians, miles, or kilometers; and bearing in degrees.
/// This uses the [Haversine formula](http://en.wikipedia.org/wiki/Haversine_formula) to account for global curvature.
/// For example:
///
/// ```dart
/// var point = Point(coordinates: Position(-75.343, 39.984));
/// var distance = 50;
/// var bearing = 90;
/// var options = Unit.miles;
///
/// var destination = destination(point, distance, bearing, options);
///
/// //addToMap
/// var addToMap = [point, destination]
/// destination.properties['marker-color'] = '#f00';
/// point.properties['marker-color'] = '#0f0';
/// ```

Point destination(Point origin, num distance, num bearing,
[Unit unit = Unit.kilometers]) =>
Point(
Expand Down
14 changes: 14 additions & 0 deletions lib/src/distance.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import 'dart:math';
import 'geojson.dart';
import 'helpers.dart';

//http://en.wikipedia.org/wiki/Haversine_formula
//http://www.movable-type.co.uk/scripts/latlong.html

num distanceRaw(Position from, Position to, [Unit unit = Unit.kilometers]) {
var dLat = degreesToRadians((to.lat - from.lat));
var dLon = degreesToRadians((to.lng - from.lng));
Expand All @@ -14,5 +17,16 @@ num distanceRaw(Position from, Position to, [Unit unit = Unit.kilometers]) {
return radiansToLength(2 * atan2(sqrt(a), sqrt(1 - a)), unit);
}

/// Calculates the distance between two [Point]s in degrees, radians, miles, or kilometers.
/// This uses the [Haversine formula](http://en.wikipedia.org/wiki/Haversine_formula) to account for global curvature.
/// For example:
///
/// ```dart
/// var from = Point(coordinates: Position(-75.343, 39.984));
/// var to = Point(coordinates: Position(-75.443, 39.984));
/// var options = Unit.miles;
///
/// var distance = distance(from, to, options);
/// ```
num distance(Point from, Point to, [Unit unit = Unit.kilometers]) =>
distanceRaw(from.coordinates, to.coordinates, unit);
19 changes: 19 additions & 0 deletions lib/src/helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ enum Corner {
centroid,
}

/// Earth Radius used with the Harvesine formula and approximates using a spherical (non-ellipsoid) Earth.
const earthRadius = 6371008.8;

/// Unit of measurement factors using a spherical (non-ellipsoid) earth radius.
/// Keys are the name of the unit, values are the number of that unit in a single radian
const factors = <Unit, num>{
Unit.centimeters: earthRadius * 100,
Unit.degrees: earthRadius / 111325,
Expand Down Expand Up @@ -60,6 +63,7 @@ const unitsFactors = <Unit, num>{
Unit.yards: 1 / 1.0936,
};

/// Area of measurement factors based on 1 square meter.
const areaFactors = <Unit, num>{
Unit.acres: 0.000247105,
Unit.centimeters: 10000,
Expand All @@ -72,6 +76,7 @@ const areaFactors = <Unit, num>{
Unit.yards: 1.195990046,
};

/// Round number to precision
num round(num value, [num precision = 0]) {
if (!(precision >= 0)) {
throw Exception("precision must be a positive number");
Expand All @@ -81,6 +86,8 @@ num round(num value, [num precision = 0]) {
return result.round() / multiplier;
}

/// Convert a distance measurement (assuming a spherical Earth) from radians to a more friendly unit.
/// Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet
num radiansToLength(num radians, [Unit unit = Unit.kilometers]) {
var factor = factors[unit];
if (factor == null) {
Expand All @@ -89,6 +96,8 @@ num radiansToLength(num radians, [Unit unit = Unit.kilometers]) {
return radians * factor;
}

/// Convert a distance measurement (assuming a spherical Earth) from a real-world unit into radians
/// Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet
num lengthToRadians(num distance, [Unit unit = Unit.kilometers]) {
num? factor = factors[unit];
if (factor == null) {
Expand All @@ -97,10 +106,14 @@ num lengthToRadians(num distance, [Unit unit = Unit.kilometers]) {
return distance / factor;
}

/// Convert a distance measurement (assuming a spherical Earth) from a real-world unit into degrees
/// Valid units: miles, nauticalmiles, inches, yards, meters, metres, centimeters, kilometres, feet
num lengthToDegrees(num distance, [Unit unit = Unit.kilometers]) {
return radiansToDegrees(lengthToRadians(distance, unit));
}

/// Converts any bearing angle from the north line direction (positive clockwise)
/// and returns an angle between 0-360 degrees (positive clockwise), 0 being the north line
num bearingToAzimuth(num bearing) {
num angle = bearing.remainder(360);
if (angle < 0) {
Expand All @@ -109,16 +122,20 @@ num bearingToAzimuth(num bearing) {
return angle;
}

/// Converts an angle in radians to degrees
num radiansToDegrees(num radians) {
num degrees = radians.remainder(2 * pi);
return degrees * 180 / pi;
}

/// Converts an angle in degrees to radians
num degreesToRadians(num degrees) {
num radians = degrees.remainder(360);
return radians * pi / 180;
}

/// Converts a length to the requested unit.
/// Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet
num convertLength(
num length, [
Unit originalUnit = Unit.kilometers,
Expand All @@ -130,6 +147,8 @@ num convertLength(
return radiansToLength(lengthToRadians(length, originalUnit), finalUnit);
}

/// Converts a area to the requested unit.
/// Valid units: kilometers, kilometres, meters, metres, centimetres, millimeters, acres, miles, yards, feet, inches, hectares
num convertArea(num area,
[originalUnit = Unit.meters, finalUnit = Unit.kilometers]) {
if (area < 0) {
Expand Down
3 changes: 2 additions & 1 deletion lib/src/invariant.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ Position getCoord(dynamic coord) {
throw Exception("coord must be GeoJSON Point or Position");
}

/// Unwrap coordinates from a [Feature], [GeometryObject] or a [List]
/// Unwraps coordinates from a [Feature], [GeometryObject] or a [List]
///
/// Gets a [List<dynamic>], [GeometryObject] or a [Feature] or a [List<dynamic>] and
/// returns [List<dynamic>].
/// For example:
///
/// ```dart
/// var polygon = Polygon(coordinates: [
/// [
Expand Down
4 changes: 1 addition & 3 deletions lib/src/line_segment.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import 'package:turf/src/meta/flatten.dart';

import 'geojson.dart';

// export default lineSegment;

/// Creates a [FeatureCollection] of 2-vertex [LineString] segments from a
/// [LineString] or [MultiLineString] or [Polygon] and [MultiPolygon]
/// Returns [FeatureCollection<LineString>] 2-vertex line segments
Expand Down Expand Up @@ -210,7 +208,7 @@ typedef T? SegmentReduceCallback<T>(
int segmentIndex,
);

/// Reduce 2-vertex line segment in any GeoJSON object, similar to [Iterable.reduce]()
/// Reduces 2-vertex line segment in any GeoJSON object, similar to [Iterable.reduce]()
/// (Multi)Point geometries do not contain segments therefore they are ignored during this operation.
///
/// Takes [FeatureCollection], [Feature], [GeoJSONObject], a
Expand Down
14 changes: 7 additions & 7 deletions lib/src/meta/extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ extension GeoJSONObjectMetaExtension on GeoJSONObject {
}

T? geomReduce<T>(meta.GeomReduceCallback<T> callback, T? initialValue) {
meta.geomReduce<T>(
return meta.geomReduce<T>(
this,
callback,
initialValue,
Expand All @@ -22,7 +22,7 @@ extension GeoJSONObjectMetaExtension on GeoJSONObject {
meta.PropReduceCallback<T> callback,
T? initialValue,
) {
meta.propReduce<T>(
return meta.propReduce<T>(
this,
callback,
initialValue,
Expand All @@ -37,7 +37,7 @@ extension GeoJSONObjectMetaExtension on GeoJSONObject {
meta.FeatureReduceCallback<T> callback,
T? initialValue,
) {
meta.featureReduce<T>(
return meta.featureReduce<T>(
this,
callback,
initialValue,
Expand All @@ -53,7 +53,7 @@ extension GeoJSONObjectMetaExtension on GeoJSONObject {
T? initialValue, [
bool excludeWrapCoord = false,
]) {
meta.coordReduce<T>(
return meta.coordReduce<T>(
this,
callback,
initialValue,
Expand All @@ -73,7 +73,7 @@ extension GeoJSONObjectMetaExtension on GeoJSONObject {
meta.FlattenReduceCallback<T> callback,
T? initialValue,
) {
meta.flattenReduce<T>(
return meta.flattenReduce<T>(
this,
callback,
initialValue,
Expand All @@ -89,7 +89,7 @@ extension GeoJSONObjectMetaExtension on GeoJSONObject {
T? initialValue, {
bool combineNestedGeometries = true,
}) {
meta.segmentReduce<T>(
return meta.segmentReduce<T>(
this,
callback,
initialValue,
Expand All @@ -115,7 +115,7 @@ extension FeatureCollectionMetaExtension on FeatureCollection {
meta.ClusterReduceCallback<T> callback,
dynamic initialValue,
) {
meta.clusterReduce<T>(
return meta.clusterReduce<T>(
this,
property,
callback,
Expand Down
1 change: 0 additions & 1 deletion lib/src/meta/feature.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ typedef FeatureEachCallback = dynamic Function(

/// Iterates over features in any [geoJSONObject], calling [callback] on each
/// iteration. Similar to [Iterable.forEach].
///
/// For example:
///
/// ```dart
Expand Down
Loading