diff --git a/lib/circle.dart b/lib/circle.dart new file mode 100644 index 0000000..f6df875 --- /dev/null +++ b/lib/circle.dart @@ -0,0 +1,4 @@ +library turf_circle; + +export 'package:geotypes/geotypes.dart'; +export 'src/circle.dart'; diff --git a/lib/src/circle.dart b/lib/src/circle.dart new file mode 100644 index 0000000..f27f3f8 --- /dev/null +++ b/lib/src/circle.dart @@ -0,0 +1,48 @@ +import 'package:turf/helpers.dart'; +import 'package:turf/invariant.dart'; +import 'package:turf/src/booleans/boolean_helper.dart'; +import 'destination.dart'; + +/// Takes a [Point] or a [Feature] and calculates the circle polygon given a radius in degrees, radians, miles, or kilometers; and steps for precision. +/// +/// example: +/// ```dart +/// var properties = { 'foo': 'bar' }; +/// var point = Feature(geometry: Point(coordinates: Position.of([-75.343, 39.984]))); +/// final polygonCircle = circle( +/// feature.geometry!, +/// radius, +/// steps: 32, +/// unit: Unit.meters, +/// properties: feature.properties, +/// ); +/// ``` +Feature circle( + GeoJSONObject center, + num radius, { + num? steps, + Unit? unit, + Map? properties, +}) { + steps ??= 64; + unit ??= Unit.kilometers; + Point origin; + final geometry = getGeom(center); + if (geometry is Point) { + origin = geometry; + } else { + throw GeometryNotSupported(geometry); + } + properties ??= + center is Feature && center.properties != null ? center.properties : {}; + final List coordinates = []; + for (var i = 0; i < steps; i++) { + final c = destination(origin, radius, (i * -360) / steps, unit).coordinates; + coordinates.add(c); + } + coordinates.add(coordinates[0]); + return Feature( + properties: properties, + geometry: Polygon(coordinates: [coordinates]), + ); +} diff --git a/test/components/circle_test.dart b/test/components/circle_test.dart new file mode 100644 index 0000000..5dc1f10 --- /dev/null +++ b/test/components/circle_test.dart @@ -0,0 +1,59 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:test/test.dart'; +import 'package:turf/circle.dart'; +import 'package:turf/src/truncate.dart'; +import 'package:turf_equality/turf_equality.dart'; + +import '../context/helper.dart'; + +void main() { + group( + 'circle', + () { + test('circle -- add properties', () { + final point = Point(coordinates: Position(0, 0)); + final out = circle(point, 10, properties: {'foo': 'bar'}); + + final isEqual = out.properties?['foo'] == 'bar'; + expect(isEqual, true); + }); + + Directory inDir = Directory('./test/examples/circle/in'); + for (var file in inDir.listSync(recursive: true)) { + if (file is File && file.path.endsWith('.geojson')) { + test( + file.path, + () { + final inSource = file.readAsStringSync(); + final feature = Feature.fromJson(jsonDecode(inSource)); + final properties = feature.properties ?? {}; + final radius = properties['radius'] ?? 5; + final steps = properties['steps'] ?? 64; + final unit = properties['units']; + + final C = truncate(circle(feature, radius, + properties: {"marker-symbol": "circle"}, + steps: steps, + unit: unit)) as Feature; + + final results = featureCollection([feature, C]); + + Directory outDir = Directory('./test/examples/centroid/out'); + for (var file2 in outDir.listSync(recursive: true)) { + if (file2 is File && + file2.uri.pathSegments.last == file.uri.pathSegments.last) { + var outSource = file2.readAsStringSync(); + var outGeom = GeoJSONObject.fromJson(jsonDecode(outSource)); + Equality eq = Equality(); + expect(eq.compare(results, outGeom), true); + } + } + }, + ); + } + } + }, + ); +} diff --git a/test/examples/circle/in/circle1.geojson b/test/examples/circle/in/circle1.geojson new file mode 100644 index 0000000..119ffc0 --- /dev/null +++ b/test/examples/circle/in/circle1.geojson @@ -0,0 +1,10 @@ +{ + "type": "Feature", + "properties": { + "radius": 5 + }, + "geometry": { + "type": "Point", + "coordinates": [-75.343, 39.984] + } +} diff --git a/test/examples/circle/out/circle1.geojson b/test/examples/circle/out/circle1.geojson new file mode 100644 index 0000000..e01ab52 --- /dev/null +++ b/test/examples/circle/out/circle1.geojson @@ -0,0 +1,93 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "radius": 5 + }, + "geometry": { + "type": "Point", + "coordinates": [-75.343, 39.984] + } + }, + { + "type": "Feature", + "properties": { + "radius": 5 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [-75.343, 40.028966], + [-75.348756, 40.028749], + [-75.354456, 40.028101], + [-75.360046, 40.027029], + [-75.365472, 40.025541], + [-75.37068, 40.023653], + [-75.375622, 40.021383], + [-75.380248, 40.018753], + [-75.384516, 40.015788], + [-75.388383, 40.012517], + [-75.391813, 40.008972], + [-75.394772, 40.005185], + [-75.397232, 40.001195], + [-75.399169, 39.997039], + [-75.400565, 39.992758], + [-75.401406, 39.988393], + [-75.401685, 39.983985], + [-75.401399, 39.979578], + [-75.40055, 39.975213], + [-75.399148, 39.970934], + [-75.397204, 39.96678], + [-75.39474, 39.962792], + [-75.391777, 39.959008], + [-75.388345, 39.955465], + [-75.384477, 39.952197], + [-75.380211, 39.949235], + [-75.375586, 39.946608], + [-75.370648, 39.94434], + [-75.365444, 39.942455], + [-75.360025, 39.940969], + [-75.354442, 39.939897], + [-75.348748, 39.93925], + [-75.343, 39.939034], + [-75.337252, 39.93925], + [-75.331558, 39.939897], + [-75.325975, 39.940969], + [-75.320556, 39.942455], + [-75.315352, 39.94434], + [-75.310414, 39.946608], + [-75.305789, 39.949235], + [-75.301523, 39.952197], + [-75.297655, 39.955465], + [-75.294223, 39.959008], + [-75.29126, 39.962792], + [-75.288796, 39.96678], + [-75.286852, 39.970934], + [-75.28545, 39.975213], + [-75.284601, 39.979578], + [-75.284315, 39.983985], + [-75.284594, 39.988393], + [-75.285435, 39.992758], + [-75.286831, 39.997039], + [-75.288768, 40.001195], + [-75.291228, 40.005185], + [-75.294187, 40.008972], + [-75.297617, 40.012517], + [-75.301484, 40.015788], + [-75.305752, 40.018753], + [-75.310378, 40.021383], + [-75.31532, 40.023653], + [-75.320528, 40.025541], + [-75.325954, 40.027029], + [-75.331544, 40.028101], + [-75.337244, 40.028749], + [-75.343, 40.028966] + ] + ] + } + } + ] +}