Skip to content

Commit

Permalink
[meta] add coordeach implementation (#50)
Browse files Browse the repository at this point in the history
* [meta] add coordeach implementation

* [benchmark] add coordeach benchmark using test fixtures
  • Loading branch information
tobrun authored Feb 20, 2022
1 parent fde7642 commit 2aff26e
Show file tree
Hide file tree
Showing 4 changed files with 571 additions and 4 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,19 +129,19 @@ Any new benchmarks must be named `*_benchmark.dart` and reside in the

### META
- [ ] coordAll
- [ ] coordEach
- [x] coordEach
- [ ] coordReduce
- [ ] featureEach
- [x] featureEach
- [ ] featureReduce
- [ ] flattenEach
- [ ] flattenReduce
- [ ] getCoord
- [ ] getCoords
- [ ] getGeom
- [ ] getType
- [ ] geomEach
- [x] geomEach
- [ ] geomReduce
- [ ] propEach
- [x] propEach
- [ ] propReduce
- [ ] segmentEach
- [ ] segmentReduce
Expand Down
40 changes: 40 additions & 0 deletions benchmark/meta_benchmark.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import 'package:benchmark/benchmark.dart';
import 'package:turf/helpers.dart';
import 'package:turf/meta.dart';

import 'dart:convert';
import 'dart:io';

void main() {
Point pt = Point.fromJson({
'coordinates': [0, 0]
Expand All @@ -25,6 +28,43 @@ void main() {
features: pointFeatures,
);

group('coordEach', () {
void coordEachNoopCB(
CoordinateType? currentCoord,
int? coordIndex,
int? featureIndex,
int? multiFeatureIndex,
int? geometryIndex,
) {}

benchmark('geometry', () {
coordEach(pt, coordEachNoopCB);
});

benchmark('feature', () {
coordEach(featurePt, coordEachNoopCB);
});

benchmark('geometry collection', () {
coordEach(geomCollection, coordEachNoopCB);
});

benchmark('feature collection', () {
coordEach(featureCollection, coordEachNoopCB);
});

var dir = Directory('./test/examples');
for (var file in dir.listSync(recursive: true)) {
if (file is File && file.path.endsWith('.geojson')) {
var source = (file).readAsStringSync();
var geoJSON = GeoJSONObject.fromJson(jsonDecode(source));
benchmark(file.path, () {
coordEach(geoJSON, coordEachNoopCB);
});
}
}
});

group('geomEach', () {
void geomEachNoopCB(
GeometryObject? currentGeometry,
Expand Down
144 changes: 144 additions & 0 deletions lib/src/meta.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,149 @@
import 'geojson.dart';

typedef CoordEachCallback = dynamic Function(
CoordinateType? currentCoord,
int? coordIndex,
int? featureIndex,
int? multiFeatureIndex,
int? geometryIndex,
);

///
/// Iterate over coordinates in any [geoJSON] object, similar to Array.forEach()
///
/// For example:
///
/// ```dart
/// // TODO add example
/// ```
void coordEach(GeoJSONObject geoJSON, CoordEachCallback callback,
[bool excludeWrapCoord = false]) {
dynamic coords;
dynamic geometry;
int stopG;
GeoJSONObject? geometryMaybeCollection;
int wrapShrink = 0;
int coordIndex = 0;
bool isGeometryCollection;
bool isFeatureCollection = geoJSON is FeatureCollection;
bool isFeature = geoJSON is Feature;
int stop = isFeatureCollection ? geoJSON.features.length : 1;

try {
for (var featureIndex = 0; featureIndex < stop; featureIndex++) {
geometryMaybeCollection = isFeatureCollection
? geoJSON.features[featureIndex].geometry
: isFeature
? geoJSON.geometry
: geoJSON;

isGeometryCollection = geometryMaybeCollection != null
? geometryMaybeCollection is GeometryCollection
: false;

stopG =
isGeometryCollection ? geometryMaybeCollection.geometries.length : 1;

for (int geomIndex = 0; geomIndex < stopG; geomIndex++) {
int multiFeatureIndex = 0;
int geometryIndex = 0;
geometry = isGeometryCollection
? geometryMaybeCollection.geometries[geomIndex]
: geometryMaybeCollection;

// Handles null Geometry -- Skips this geometry
if (geometry == null) {
continue;
}
coords = geometry.coordinates as Iterable;
GeoJSONObjectType geomType = geometry.type;

wrapShrink = excludeWrapCoord &&
(geomType == GeoJSONObjectType.polygon ||
geomType == GeoJSONObjectType.multiLineString)
? 1
: 0;

if (geomType == GeoJSONObjectType.point) {
if (callback(coords as CoordinateType, coordIndex, featureIndex,
multiFeatureIndex, geometryIndex) ==
false) {
throw _ShortCircuit();
}
coordIndex++;
multiFeatureIndex++;
break;
} else if (geomType == GeoJSONObjectType.lineString ||
geomType == GeoJSONObjectType.multiPoint) {
for (var j = 0; j < coords.length; j++) {
if (callback(coords[j], coordIndex, featureIndex, multiFeatureIndex,
geometryIndex) ==
false) {
throw _ShortCircuit();
}
coordIndex++;
if (geomType == GeoJSONObjectType.multiPoint) {
multiFeatureIndex++;
}
}
if (geomType == GeoJSONObjectType.lineString) {
multiFeatureIndex++;
}
} else if (geomType == GeoJSONObjectType.polygon ||
geomType == GeoJSONObjectType.multiLineString) {
for (var j = 0; j < coords.length; j++) {
for (var k = 0; k < coords[j].length - wrapShrink; k++) {
if (callback(coords[j][k], coordIndex, featureIndex,
multiFeatureIndex, geometryIndex) ==
false) {
throw _ShortCircuit();
}
coordIndex++;
}
if (geomType == GeoJSONObjectType.multiLineString) {
multiFeatureIndex++;
}
if (geomType == GeoJSONObjectType.polygon) {
geometryIndex++;
}
}
if (geomType == GeoJSONObjectType.polygon) {
multiFeatureIndex++;
}
} else if (geomType == GeoJSONObjectType.multiPolygon) {
for (var j = 0; j < coords.length; j++) {
geometryIndex = 0;
for (var k = 0; k < coords[j].length; k++) {
for (var l = 0; l < coords[j][k].length - wrapShrink; l++) {
if (callback(coords[j][k][l], coordIndex, featureIndex,
multiFeatureIndex, geometryIndex) ==
false) {
throw _ShortCircuit();
}
coordIndex++;
}
geometryIndex++;
}
multiFeatureIndex++;
}
} else if (geomType == GeoJSONObjectType.geometryCollection) {
for (var j = 0; j < geometry.geometries.length; j++) {
try {
coordEach(geometry.geometries[j], callback, excludeWrapCoord);
} on _ShortCircuit {
rethrow;
}
}
} else {
throw Exception('Unknown Geometry Type');
}
}
}
} on _ShortCircuit {
return;
}
}

typedef GeomEachCallback = dynamic Function(
GeometryObject? currentGeometry,
int? featureIndex,
Expand Down
Loading

0 comments on commit 2aff26e

Please sign in to comment.