From 914043e75356b88a52932f4bcd2a319f76b2b482 Mon Sep 17 00:00:00 2001 From: armantorkzaban Date: Mon, 20 Jun 2022 11:12:23 +0200 Subject: [PATCH 01/12] line_to_polygon ported --- lib/src/line_to_polygon.dart | 277 +++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 lib/src/line_to_polygon.dart diff --git a/lib/src/line_to_polygon.dart b/lib/src/line_to_polygon.dart new file mode 100644 index 0000000..9e9bdde --- /dev/null +++ b/lib/src/line_to_polygon.dart @@ -0,0 +1,277 @@ +import 'package:turf/bbox.dart'; +import 'package:turf/helpers.dart'; +import 'package:turf/src/invariant.dart'; +import 'package:turf/src/meta/feature.dart'; + +/// Converts [MultiLineString](s) to [Polygon](s). +/// Takes an optional bool autoComplete=true that auto complete [Linestring]s (matches first & last coordinates) +/// Takes an optional orderCoords=true that sorts [Linestring]s to place outer ring at the first position of the coordinates +/// Takes an optional mutate=false that mutates the original [Linestring] using autoComplete (matches first & last coordinates) +/// Returns [Feature] or [Feature] converted to Polygons. +/// example: +/// ```dart +/// var line = LineString(coordinates: [[125, -30], [145, -30], [145, -20], [125, -20], [125, -30]]); +/// var polygon = lineToPolygon(line); +/// //addToMap +/// var addToMap = [polygon]; +/// ``` +lineToPolygon( + GeoJSONObject lines, { + Map? properties, + bool autoComplete = true, + bool orderCoords = true, + bool mutate = false, +}) { + if (!mutate) { + lines = lines.clone(); + } + + if (lines is FeatureCollection) { + List>> coords = []; + featureEach( + lines, + ((line, featureIndex) => coords.add(getCoords(lineStringToPolygon( + line, autoComplete, orderCoords, properties: {})) + as List>))); + return Feature( + geometry: MultiPolygon(coordinates: coords), properties: properties); + } else { + return lineStringToPolygon(lines, autoComplete, orderCoords, + properties: properties); + } +} + +/// Converts LineString to Polygon +/// Takes a optional bool autoComplete=true that auto completes linestrings +/// Takes an optional orderCoords=true that sorts linestrings to place outer ring at the first position of the coordinates +Feature lineStringToPolygon( + GeoJSONObject line, bool autoComplete, bool orderCoords, + {Map? properties}) { + properties = properties ?? (line is Feature ? line.properties ?? {} : {}); + var geom = line is LineString ? line : (line as Feature).geometry; + List coords = geom is LineString + ? geom.coordinates + : ((geom as Feature).geometry as GeometryType).coordinates; + + if (coords.isEmpty) throw Exception("line must contain coordinates"); + + if (geom is LineString) { + if (autoComplete) { + coords = _autoCompleteCoords(coords as List); + } + return Feature( + geometry: Polygon(coordinates: [coords as List]), + properties: properties); + } else if (geom is MultiLineString) { + List> multiCoords = []; + num largestArea = 0; + + (coords as List>).forEach((coord) { + if (autoComplete) { + coord = _autoCompleteCoords(coord); + } + + // Largest LineString to be placed in the first position of the coordinates array + if (orderCoords) { + var area = _calculateArea(bbox(LineString(coordinates: coord))); + if (area > largestArea) { + multiCoords.insert(0, coord); + largestArea = area; + } else { + multiCoords.add(coord); + } + } else { + multiCoords.add(coord); + } + }); + return Feature( + geometry: Polygon(coordinates: multiCoords), properties: properties); + } else { + throw Exception( + "geometry type ${(geom as GeoJSONObject).type} is not supported"); + } +} + +/// Auto Completes Coords - matches first & last coordinates +List _autoCompleteCoords(List coords) { + var first = coords[0]; + var x1 = first[0]; + var y1 = first[1]; + var last = coords[coords.length - 1]; + var x2 = last[0]; + var y2 = last[1]; + if (x1 != x2 || y1 != y2) { + coords.add(first); + } + return coords; +} + +/// Quick calculates approximate area (used to sort) +num _calculateArea(BBox bbox) { + var west = bbox[0]; + var south = bbox[1]; + var east = bbox[2]; + var north = bbox[3]; + return (west! - east!).abs() * (south! - north!).abs(); +} + + +/** + * import { + Feature, + FeatureCollection, + MultiLineString, + LineString, + GeoJsonProperties, + BBox, + Position, +} from "geojson"; +import turfBBox from "@turf/bbox"; +import { getCoords, getGeom } from "@turf/invariant"; +import { polygon, multiPolygon, lineString } from "@turf/helpers"; +import clone from "@turf/clone"; + +/** + * Converts (Multi)LineString(s) to Polygon(s). + * + * @name lineToPolygon + * @param {FeatureCollection|Feature} lines Features to convert + * @param {Object} [options={}] Optional parameters + * @param {Object} [options.properties={}] translates GeoJSON properties to Feature + * @param {boolean} [options.autoComplete=true] auto complete linestrings (matches first & last coordinates) + * @param {boolean} [options.orderCoords=true] sorts linestrings to place outer ring at the first position of the coordinates + * @param {boolean} [options.mutate=false] mutate the original linestring using autoComplete (matches first & last coordinates) + * @returns {Feature} converted to Polygons + * @example + * var line = turf.lineString([[125, -30], [145, -30], [145, -20], [125, -20], [125, -30]]); + * + * var polygon = turf.lineToPolygon(line); + * + * //addToMap + * var addToMap = [polygon]; + */ +function lineToPolygon( + lines: Feature | FeatureCollection | G, + options: { + properties?: GeoJsonProperties; + autoComplete?: boolean; + orderCoords?: boolean; + mutate?: boolean; + } = {} +) { + // Optional parameters + var properties = options.properties; + var autoComplete = options.autoComplete ?? true; + var orderCoords = options.orderCoords ?? true; + var mutate = options.mutate ?? false; + + if (!mutate) { + lines = clone(lines); + } + + switch (lines.type) { + case "FeatureCollection": + var coords: number[][][][] = []; + lines.features.forEach(function (line) { + coords.push( + getCoords(lineStringToPolygon(line, {}, autoComplete, orderCoords)) + ); + }); + return multiPolygon(coords, properties); + default: + return lineStringToPolygon(lines, properties, autoComplete, orderCoords); + } +} + +/** + * LineString to Polygon + * + * @private + * @param {Feature} line line + * @param {Object} [properties] translates GeoJSON properties to Feature + * @param {boolean} [autoComplete=true] auto complete linestrings + * @param {boolean} [orderCoords=true] sorts linestrings to place outer ring at the first position of the coordinates + * @returns {Feature} line converted to Polygon + */ +function lineStringToPolygon( + line: Feature | G, + properties: GeoJsonProperties | undefined, + autoComplete: boolean, + orderCoords: boolean +) { + properties = properties + ? properties + : line.type === "Feature" + ? line.properties + : {}; + var geom = getGeom(line); + var coords: Position[] | Position[][] = geom.coordinates; + var type = geom.type; + + if (!coords.length) throw new Error("line must contain coordinates"); + + switch (type) { + case "LineString": + if (autoComplete) coords = autoCompleteCoords(coords as Position[]); + return polygon([coords as Position[]], properties); + case "MultiLineString": + var multiCoords: number[][][] = []; + var largestArea = 0; + + (coords as Position[][]).forEach(function (coord) { + if (autoComplete) coord = autoCompleteCoords(coord); + + // Largest LineString to be placed in the first position of the coordinates array + if (orderCoords) { + var area = calculateArea(turfBBox(lineString(coord))); + if (area > largestArea) { + multiCoords.unshift(coord); + largestArea = area; + } else multiCoords.push(coord); + } else { + multiCoords.push(coord); + } + }); + return polygon(multiCoords, properties); + default: + throw new Error("geometry type " + type + " is not supported"); + } +} + +/** + * Auto Complete Coords - matches first & last coordinates + * + * @private + * @param {Array>} coords Coordinates + * @returns {Array>} auto completed coordinates + */ +function autoCompleteCoords(coords: Position[]) { + var first = coords[0]; + var x1 = first[0]; + var y1 = first[1]; + var last = coords[coords.length - 1]; + var x2 = last[0]; + var y2 = last[1]; + if (x1 !== x2 || y1 !== y2) { + coords.push(first); + } + return coords; +} + +/** + * area - quick approximate area calculation (used to sort) + * + * @private + * @param {Array} bbox BBox [west, south, east, north] + * @returns {number} very quick area calculation + */ +function calculateArea(bbox: BBox) { + var west = bbox[0]; + var south = bbox[1]; + var east = bbox[2]; + var north = bbox[3]; + return Math.abs(west - east) * Math.abs(south - north); +} + +export default lineToPolygon; + */ \ No newline at end of file From 238ccf90319cfd4c481f884f4c6083ac979a4942 Mon Sep 17 00:00:00 2001 From: armantorkzaban Date: Mon, 20 Jun 2022 12:17:57 +0200 Subject: [PATCH 02/12] test init of lineToPolygon --- test/components/line_to_polygon_test.dart | 108 +++++++++++++++++ .../in/collection-linestring.geojson | 39 ++++++ .../in/geometry-linestring.geojson | 10 ++ .../in/linestring-incomplete.geojson | 20 ++++ .../lineToPolygon/in/linestring.geojson | 17 +++ .../in/linestrings-to-multipolygons.geojson | 113 ++++++++++++++++++ .../in/multi-linestring-incomplete.geojson | 29 +++++ .../in/multi-linestring-nested.geojson | 49 ++++++++ .../in/multi-linestring-nested2.geojson | 71 +++++++++++ ...estring-outer-ring-middle-position.geojson | 34 ++++++ .../in/multi-linestring-with-hole.geojson | 26 ++++ .../in/multi-linestrings-nested.geojson | 71 +++++++++++ .../multi-linestrings-outer-doughnut.geojson | 57 +++++++++ .../in/multi-linestrings-with-holes.geojson | 74 ++++++++++++ .../out/collection-linestring.geojson | 30 +++++ .../out/geometry-linestring.geojson | 19 +++ .../out/linestring-incomplete.geojson | 23 ++++ .../lineToPolygon/out/linestring.geojson | 19 +++ .../out/linestrings-to-multipolygons.geojson | 80 +++++++++++++ .../out/multi-linestring-incomplete.geojson | 31 +++++ .../out/multi-linestring-nested.geojson | 49 ++++++++ .../out/multi-linestring-nested2.geojson | 58 +++++++++ ...estring-outer-ring-middle-position.geojson | 37 ++++++ .../out/multi-linestring-with-hole.geojson | 26 ++++ .../out/multi-linestrings-nested.geojson | 58 +++++++++ .../multi-linestrings-outer-doughnut.geojson | 44 +++++++ .../out/multi-linestrings-with-holes.geojson | 53 ++++++++ 27 files changed, 1245 insertions(+) create mode 100644 test/components/line_to_polygon_test.dart create mode 100644 test/examples/lineToPolygon/in/collection-linestring.geojson create mode 100644 test/examples/lineToPolygon/in/geometry-linestring.geojson create mode 100644 test/examples/lineToPolygon/in/linestring-incomplete.geojson create mode 100644 test/examples/lineToPolygon/in/linestring.geojson create mode 100644 test/examples/lineToPolygon/in/linestrings-to-multipolygons.geojson create mode 100644 test/examples/lineToPolygon/in/multi-linestring-incomplete.geojson create mode 100644 test/examples/lineToPolygon/in/multi-linestring-nested.geojson create mode 100644 test/examples/lineToPolygon/in/multi-linestring-nested2.geojson create mode 100644 test/examples/lineToPolygon/in/multi-linestring-outer-ring-middle-position.geojson create mode 100644 test/examples/lineToPolygon/in/multi-linestring-with-hole.geojson create mode 100644 test/examples/lineToPolygon/in/multi-linestrings-nested.geojson create mode 100644 test/examples/lineToPolygon/in/multi-linestrings-outer-doughnut.geojson create mode 100644 test/examples/lineToPolygon/in/multi-linestrings-with-holes.geojson create mode 100644 test/examples/lineToPolygon/out/collection-linestring.geojson create mode 100644 test/examples/lineToPolygon/out/geometry-linestring.geojson create mode 100644 test/examples/lineToPolygon/out/linestring-incomplete.geojson create mode 100644 test/examples/lineToPolygon/out/linestring.geojson create mode 100644 test/examples/lineToPolygon/out/linestrings-to-multipolygons.geojson create mode 100644 test/examples/lineToPolygon/out/multi-linestring-incomplete.geojson create mode 100644 test/examples/lineToPolygon/out/multi-linestring-nested.geojson create mode 100644 test/examples/lineToPolygon/out/multi-linestring-nested2.geojson create mode 100644 test/examples/lineToPolygon/out/multi-linestring-outer-ring-middle-position.geojson create mode 100644 test/examples/lineToPolygon/out/multi-linestring-with-hole.geojson create mode 100644 test/examples/lineToPolygon/out/multi-linestrings-nested.geojson create mode 100644 test/examples/lineToPolygon/out/multi-linestrings-outer-doughnut.geojson create mode 100644 test/examples/lineToPolygon/out/multi-linestrings-with-holes.geojson diff --git a/test/components/line_to_polygon_test.dart b/test/components/line_to_polygon_test.dart new file mode 100644 index 0000000..a4e76d7 --- /dev/null +++ b/test/components/line_to_polygon_test.dart @@ -0,0 +1,108 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:test/test.dart'; +import 'package:turf/helpers.dart'; +import 'package:turf/src/line_to_polygon.dart'; + +void main() { + var inDir = Directory('./test/examples/lineToPolygon/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 properties = (inGeom is Feature)? inGeom.properties ?? { "stroke": "#F0F", "stroke-width": 6 }:{ "stroke": "#F0F", "stroke-width": 6 }; + var results = lineToPolygon(inGeom, + properties: properties, + ); + + var outPath = './' + + file.uri.pathSegments + .sublist(0, file.uri.pathSegments.length - 2) + .join('/') + + '/out/${file.uri.pathSegments.last}'; + + var outSource = File(outPath).readAsStringSync(); + + expect(inGeom, equals(outSource)); + } + // Handle Errors +test('Handles Errors', (){ + + + expect(() => lineToPolygon(point([10, 5])),); + t.throws(() => lineToPolygon(lineString([])), "throws - empty coordinates"); + t.assert( + lineToPolygon( + lineString([ + [10, 5], + [20, 10], + [30, 20], + ]), + { autocomplete: false } + ), + "is valid - autoComplete=false" + ); + }); + + t.end(); +}) +;} + +/* +const fs = require("fs"); +const test = require("tape"); +const path = require("path"); +const load = require("load-json-file"); +const write = require("write-json-file"); +const { point, lineString } = require("@turf/helpers"); +const clone = require("@turf/clone").default; +const lineToPolygon = require("./index").default; + +const directories = { + in: path.join(__dirname, "test", "in") + path.sep, + out: path.join(__dirname, "test", "out") + path.sep, +}; + +let fixtures = fs.readdirSync(directories.in).map((filename) => { + return { + filename, + name: path.parse(filename).name, + geojson: load.sync(directories.in + filename), + }; +}); +// fixtures = fixtures.filter(fixture => fixture.name === 'multi-linestrings-with-holes'); + +test("turf-linestring-to-polygon", (t) => { + for (const { name, filename, geojson } of fixtures) { + const originalInput = clone(geojson); + let { autoComplete, properties, orderCoords } = geojson.properties || {}; + properties = properties || { stroke: "#F0F", "stroke-width": 6 }; + const results = lineToPolygon(geojson, { + properties: properties, + autoComplete: autoComplete, + orderCoords: orderCoords, + }); + + if (process.env.REGEN) write.sync(directories.out + filename, results); + t.deepEqual(load.sync(directories.out + filename), results, name); + t.deepEqual(originalInput, geojson); + } + // Handle Errors + t.throws(() => lineToPolygon(point([10, 5])), "throws - invalid geometry"); + t.throws(() => lineToPolygon(lineString([])), "throws - empty coordinates"); + t.assert( + lineToPolygon( + lineString([ + [10, 5], + [20, 10], + [30, 20], + ]), + { autocomplete: false } + ), + "is valid - autoComplete=false" + ); + t.end(); +}); +*/ \ No newline at end of file diff --git a/test/examples/lineToPolygon/in/collection-linestring.geojson b/test/examples/lineToPolygon/in/collection-linestring.geojson new file mode 100644 index 0000000..40586ab --- /dev/null +++ b/test/examples/lineToPolygon/in/collection-linestring.geojson @@ -0,0 +1,39 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "stroke": "#F00", + "stroke-width": 6 + }, + "geometry": { + "type": "LineString", + "coordinates": [ + [102, 2], + [103, 2], + [103, 3], + [102, 3], + [102, 2] + ] + } + }, + { + "type": "Feature", + "properties": { + "stroke": "#00F", + "stroke-width": 6 + }, + "geometry": { + "type": "LineString", + "coordinates": [ + [100, 0], + [101, 0], + [101, 1], + [100, 1], + [100, 0] + ] + } + } + ] +} diff --git a/test/examples/lineToPolygon/in/geometry-linestring.geojson b/test/examples/lineToPolygon/in/geometry-linestring.geojson new file mode 100644 index 0000000..61e6ffa --- /dev/null +++ b/test/examples/lineToPolygon/in/geometry-linestring.geojson @@ -0,0 +1,10 @@ +{ + "type": "LineString", + "coordinates": [ + [-2.275543, 53.464547], + [-2.275543, 53.489271], + [-2.215118, 53.489271], + [-2.215118, 53.464547], + [-2.275543, 53.464547] + ] +} diff --git a/test/examples/lineToPolygon/in/linestring-incomplete.geojson b/test/examples/lineToPolygon/in/linestring-incomplete.geojson new file mode 100644 index 0000000..4f045fb --- /dev/null +++ b/test/examples/lineToPolygon/in/linestring-incomplete.geojson @@ -0,0 +1,20 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F00", + "stroke-width": 6 + }, + "geometry": { + "type": "LineString", + "coordinates": [ + [131.0009765625, -30.939924331023455], + [125.46386718749999, -29.878755346037963], + [121.77246093750001, -26.07652055985696], + [121.5087890625, -21.902277966668624], + [127.79296875, -16.1724728083975], + [133.154296875, -14.944784875088372], + [137.4169921875, -20.097206227083888], + [138.515625, -26.82407078047018] + ] + } +} diff --git a/test/examples/lineToPolygon/in/linestring.geojson b/test/examples/lineToPolygon/in/linestring.geojson new file mode 100644 index 0000000..b453fed --- /dev/null +++ b/test/examples/lineToPolygon/in/linestring.geojson @@ -0,0 +1,17 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F00", + "stroke-width": 6 + }, + "geometry": { + "type": "LineString", + "coordinates": [ + [-2.275543, 53.464547], + [-2.275543, 53.489271], + [-2.215118, 53.489271], + [-2.215118, 53.464547], + [-2.275543, 53.464547] + ] + } +} diff --git a/test/examples/lineToPolygon/in/linestrings-to-multipolygons.geojson b/test/examples/lineToPolygon/in/linestrings-to-multipolygons.geojson new file mode 100644 index 0000000..82df227 --- /dev/null +++ b/test/examples/lineToPolygon/in/linestrings-to-multipolygons.geojson @@ -0,0 +1,113 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "stroke": "#008000", + "stroke-width": 6, + "stroke-opacity": 1 + }, + "geometry": { + "type": "LineString", + "coordinates": [ + [33.4149169921875, 48.28684818710906], + [32.816162109375, 48.42191010942875], + [32.783203125, 48.09642606004488], + [33.3270263671875, 47.931066347509784], + [33.4149169921875, 48.28684818710906] + ] + } + }, + { + "type": "Feature", + "properties": { + "stroke": "#ff8000", + "stroke-width": 6, + "stroke-opacity": 1 + }, + "geometry": { + "type": "LineString", + "coordinates": [ + [35.244140625, 47.15984001304432], + [35.17822265625, 46.37725420510028], + [36.40869140625, 46.240651955001695], + [37.02392578125, 46.9502622421856], + [35.244140625, 47.15984001304432] + ] + } + }, + { + "type": "Feature", + "properties": { + "stroke": "#ff0000", + "stroke-width": 6, + "stroke-opacity": 1 + }, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [33.398, 46.867], + [34.057, 46.867], + [34.057, 47.197], + [33.398, 47.197], + [33.398, 46.867] + ], + [ + [33.42041015625, 46.164614496897094], + [34.12353515625, 46.58906908309182], + [34.73876953125, 46.73233101286786], + [35.013427734375, 47.34626718205302], + [34.07958984374999, 47.73193447949174], + [32.947998046875, 47.338822694822], + [32.354736328125, 46.73986059969267], + [32.54150390625, 46.240651955001695], + [33.42041015625, 46.164614496897094] + ], + [ + [32.969, 46.46], + [33.321, 46.46], + [33.321, 46.672], + [32.969, 46.672], + [32.969, 46.46] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "stroke": "#0080ff", + "stroke-width": 6, + "stroke-opacity": 1 + }, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [34.178466796875, 48.436489955944154], + [35.101318359375, 47.57652571374621], + [37.3974609375, 47.48008846346322], + [38.133544921875, 48.777912755501845], + [35.92529296875, 49.930008124606886], + [34.178466796875, 48.436489955944154] + ], + [ + [34.80468749999999, 48.29050321714062], + [35.04638671874999, 47.938426929481054], + [35.760498046875, 47.95314495015594], + [35.343017578125, 48.32703913063476], + [34.80468749999999, 48.29050321714062] + ], + [ + [35.99395751953125, 47.83528342275264], + [35.93902587890624, 47.73193447949174], + [36.15325927734375, 47.65428791076272], + [35.99395751953125, 47.83528342275264] + ] + ] + } + } + ] +} diff --git a/test/examples/lineToPolygon/in/multi-linestring-incomplete.geojson b/test/examples/lineToPolygon/in/multi-linestring-incomplete.geojson new file mode 100644 index 0000000..30b9ea4 --- /dev/null +++ b/test/examples/lineToPolygon/in/multi-linestring-incomplete.geojson @@ -0,0 +1,29 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F00", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [129.28710937499997, -31.57853542647337], + [120.05859375, -26.35249785815401], + [120.05859375, -19.72534224805787], + [124.62890625, -17.056784609942543], + [131.572265625, -17.224758206624628], + [133.330078125, -23.644524198573677] + ], + [ + [126.2548828125, -20.427012814257385], + [123.662109375, -22.512556954051437], + [124.1455078125, -25.36388227274024], + [126.9580078125, -25.799891182088306], + [128.5400390625, -24.166802085303225], + [127.83691406249999, -21.207458730482642], + [127.265625, -20.756113874762068] + ] + ] + } +} diff --git a/test/examples/lineToPolygon/in/multi-linestring-nested.geojson b/test/examples/lineToPolygon/in/multi-linestring-nested.geojson new file mode 100644 index 0000000..3bc2751 --- /dev/null +++ b/test/examples/lineToPolygon/in/multi-linestring-nested.geojson @@ -0,0 +1,49 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [102.359619140625, 33.916013113401696], + [103.65600585937499, 33.916013113401696], + [103.65600585937499, 34.97600151317588], + [102.359619140625, 34.97600151317588], + [102.359619140625, 33.916013113401696] + ], + [ + [101.18408203124999, 32.95336814579932], + [101.18408203124999, 35.93354064249312], + [104.952392578125, 35.93354064249312], + [104.952392578125, 32.95336814579932], + [101.18408203124999, 32.95336814579932] + ], + [ + [101.612548828125, 33.330528249028085], + [104.556884765625, 33.330528249028085], + [104.556884765625, 35.46961797120201], + [101.612548828125, 35.46961797120201], + [101.612548828125, 33.330528249028085] + ], + [ + [106.4794921875, 32.7872745269555], + [110.687255859375, 32.7872745269555], + [110.687255859375, 36.83566824724438], + [106.4794921875, 36.83566824724438], + [106.4794921875, 32.7872745269555] + ], + [ + [106.06201171875, 32.47269502206151], + [111.86279296875, 32.47269502206151], + [111.86279296875, 37.33522435930639], + [106.06201171875, 37.33522435930639], + [106.06201171875, 32.47269502206151] + ] + ] + } + } + ] +} diff --git a/test/examples/lineToPolygon/in/multi-linestring-nested2.geojson b/test/examples/lineToPolygon/in/multi-linestring-nested2.geojson new file mode 100644 index 0000000..1958996 --- /dev/null +++ b/test/examples/lineToPolygon/in/multi-linestring-nested2.geojson @@ -0,0 +1,71 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [115.927734375, -34.016241889667015], + [134.560546875, -34.016241889667015], + [134.560546875, -16.8886597873816], + [115.927734375, -16.8886597873816], + [115.927734375, -34.016241889667015] + ], + [ + [118.65234374999999, -30.90222470517144], + [131.484375, -30.90222470517144], + [131.484375, -19.808054128088575], + [118.65234374999999, -19.808054128088575], + [118.65234374999999, -30.90222470517144] + ], + [ + [120.9375, -28.998531814051795], + [129.7265625, -28.998531814051795], + [129.7265625, -22.105998799750566], + [120.9375, -22.105998799750566], + [120.9375, -28.998531814051795] + ], + [ + [123.48632812499999, -27.137368359795584], + [127.44140625, -27.137368359795584], + [127.44140625, -24.126701958681668], + [123.48632812499999, -24.126701958681668], + [123.48632812499999, -27.137368359795584] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [139.21874999999997, -36.10237644873643], + [158.73046875, -36.10237644873643], + [158.73046875, -17.476432197195518], + [139.21874999999997, -17.476432197195518], + [139.21874999999997, -36.10237644873643] + ], + [ + [142.3828125, -34.016241889667015], + [155.91796874999997, -34.016241889667015], + [155.91796874999997, -20.13847031245114], + [142.3828125, -20.13847031245114], + [142.3828125, -34.016241889667015] + ] + ] + } + } + ] +} diff --git a/test/examples/lineToPolygon/in/multi-linestring-outer-ring-middle-position.geojson b/test/examples/lineToPolygon/in/multi-linestring-outer-ring-middle-position.geojson new file mode 100644 index 0000000..a6f77a8 --- /dev/null +++ b/test/examples/lineToPolygon/in/multi-linestring-outer-ring-middle-position.geojson @@ -0,0 +1,34 @@ +{ + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [33.398, 46.867], + [34.057, 46.867], + [34.057, 47.197], + [33.398, 47.197], + [33.398, 46.867] + ], + [ + [33.42041015625, 46.164614496897094], + [34.12353515625, 46.58906908309182], + [34.73876953125, 46.73233101286786], + [35.013427734375, 47.34626718205302], + [34.07958984374999, 47.73193447949174], + [32.947998046875, 47.338822694822], + [32.354736328125, 46.73986059969267], + [32.54150390625, 46.240651955001695], + [33.42041015625, 46.164614496897094] + ], + [ + [32.969, 46.46], + [33.321, 46.46], + [33.321, 46.672], + [32.969, 46.672], + [32.969, 46.46] + ] + ] + } +} diff --git a/test/examples/lineToPolygon/in/multi-linestring-with-hole.geojson b/test/examples/lineToPolygon/in/multi-linestring-with-hole.geojson new file mode 100644 index 0000000..660dcbd --- /dev/null +++ b/test/examples/lineToPolygon/in/multi-linestring-with-hole.geojson @@ -0,0 +1,26 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F00", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [100, 0], + [101, 0], + [101, 1], + [100, 1], + [100, 0] + ], + [ + [100.2, 0.2], + [100.8, 0.2], + [100.8, 0.8], + [100.2, 0.8], + [100.2, 0.2] + ] + ] + } +} diff --git a/test/examples/lineToPolygon/in/multi-linestrings-nested.geojson b/test/examples/lineToPolygon/in/multi-linestrings-nested.geojson new file mode 100644 index 0000000..1958996 --- /dev/null +++ b/test/examples/lineToPolygon/in/multi-linestrings-nested.geojson @@ -0,0 +1,71 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [115.927734375, -34.016241889667015], + [134.560546875, -34.016241889667015], + [134.560546875, -16.8886597873816], + [115.927734375, -16.8886597873816], + [115.927734375, -34.016241889667015] + ], + [ + [118.65234374999999, -30.90222470517144], + [131.484375, -30.90222470517144], + [131.484375, -19.808054128088575], + [118.65234374999999, -19.808054128088575], + [118.65234374999999, -30.90222470517144] + ], + [ + [120.9375, -28.998531814051795], + [129.7265625, -28.998531814051795], + [129.7265625, -22.105998799750566], + [120.9375, -22.105998799750566], + [120.9375, -28.998531814051795] + ], + [ + [123.48632812499999, -27.137368359795584], + [127.44140625, -27.137368359795584], + [127.44140625, -24.126701958681668], + [123.48632812499999, -24.126701958681668], + [123.48632812499999, -27.137368359795584] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [139.21874999999997, -36.10237644873643], + [158.73046875, -36.10237644873643], + [158.73046875, -17.476432197195518], + [139.21874999999997, -17.476432197195518], + [139.21874999999997, -36.10237644873643] + ], + [ + [142.3828125, -34.016241889667015], + [155.91796874999997, -34.016241889667015], + [155.91796874999997, -20.13847031245114], + [142.3828125, -20.13847031245114], + [142.3828125, -34.016241889667015] + ] + ] + } + } + ] +} diff --git a/test/examples/lineToPolygon/in/multi-linestrings-outer-doughnut.geojson b/test/examples/lineToPolygon/in/multi-linestrings-outer-doughnut.geojson new file mode 100644 index 0000000..3d3d994 --- /dev/null +++ b/test/examples/lineToPolygon/in/multi-linestrings-outer-doughnut.geojson @@ -0,0 +1,57 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [115.927734375, -34.016241889667015], + [134.560546875, -34.016241889667015], + [134.560546875, -16.8886597873816], + [115.927734375, -16.8886597873816], + [115.927734375, -34.016241889667015] + ], + [ + [118.65234374999999, -30.90222470517144], + [131.484375, -30.90222470517144], + [131.484375, -19.808054128088575], + [118.65234374999999, -19.808054128088575], + [118.65234374999999, -30.90222470517144] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [120.9375, -28.998531814051795], + [129.7265625, -28.998531814051795], + [129.7265625, -22.105998799750566], + [120.9375, -22.105998799750566], + [120.9375, -28.998531814051795] + ], + [ + [123.48632812499999, -27.137368359795584], + [127.44140625, -27.137368359795584], + [127.44140625, -24.126701958681668], + [123.48632812499999, -24.126701958681668], + [123.48632812499999, -27.137368359795584] + ] + ] + } + } + ] +} diff --git a/test/examples/lineToPolygon/in/multi-linestrings-with-holes.geojson b/test/examples/lineToPolygon/in/multi-linestrings-with-holes.geojson new file mode 100644 index 0000000..804a27c --- /dev/null +++ b/test/examples/lineToPolygon/in/multi-linestrings-with-holes.geojson @@ -0,0 +1,74 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "stroke": "#00F", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [102, 2], + [103, 2], + [103, 3], + [102, 3], + [102, 2] + ], + [ + [102.227783203125, 2.191238104506552], + [102.227783203125, 2.8223442468940902], + [102.843017578125, 2.8223442468940902], + [102.843017578125, 2.191238104506552], + [102.227783203125, 2.191238104506552] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "stroke": "#F80", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [100, 0], + [101, 0], + [101, 1], + [100, 1], + [100, 0] + ], + [ + [100.206298828125, 0.2526847277643438], + [100.206298828125, 0.7909904981540058], + [100.8050537109375, 0.7909904981540058], + [100.8050537109375, 0.2526847277643438], + [100.206298828125, 0.2526847277643438] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "stroke": "#080", + "stroke-width": 6 + }, + "geometry": { + "type": "LineString", + "coordinates": [ + [101.700439453125, 0.5273363048115169], + [102.645263671875, 0.5273363048115169], + [102.645263671875, 1.3511930983018892], + [101.700439453125, 1.3511930983018892], + [101.700439453125, 0.5273363048115169] + ] + } + } + ] +} diff --git a/test/examples/lineToPolygon/out/collection-linestring.geojson b/test/examples/lineToPolygon/out/collection-linestring.geojson new file mode 100644 index 0000000..bc0a389 --- /dev/null +++ b/test/examples/lineToPolygon/out/collection-linestring.geojson @@ -0,0 +1,30 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [102, 2], + [103, 2], + [103, 3], + [102, 3], + [102, 2] + ] + ], + [ + [ + [100, 0], + [101, 0], + [101, 1], + [100, 1], + [100, 0] + ] + ] + ] + } +} diff --git a/test/examples/lineToPolygon/out/geometry-linestring.geojson b/test/examples/lineToPolygon/out/geometry-linestring.geojson new file mode 100644 index 0000000..5043748 --- /dev/null +++ b/test/examples/lineToPolygon/out/geometry-linestring.geojson @@ -0,0 +1,19 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [-2.275543, 53.464547], + [-2.275543, 53.489271], + [-2.215118, 53.489271], + [-2.215118, 53.464547], + [-2.275543, 53.464547] + ] + ] + } +} diff --git a/test/examples/lineToPolygon/out/linestring-incomplete.geojson b/test/examples/lineToPolygon/out/linestring-incomplete.geojson new file mode 100644 index 0000000..19d6558 --- /dev/null +++ b/test/examples/lineToPolygon/out/linestring-incomplete.geojson @@ -0,0 +1,23 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [131.0009765625, -30.939924331023455], + [125.46386718749999, -29.878755346037963], + [121.77246093750001, -26.07652055985696], + [121.5087890625, -21.902277966668624], + [127.79296875, -16.1724728083975], + [133.154296875, -14.944784875088372], + [137.4169921875, -20.097206227083888], + [138.515625, -26.82407078047018], + [131.0009765625, -30.939924331023455] + ] + ] + } +} diff --git a/test/examples/lineToPolygon/out/linestring.geojson b/test/examples/lineToPolygon/out/linestring.geojson new file mode 100644 index 0000000..5043748 --- /dev/null +++ b/test/examples/lineToPolygon/out/linestring.geojson @@ -0,0 +1,19 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [-2.275543, 53.464547], + [-2.275543, 53.489271], + [-2.215118, 53.489271], + [-2.215118, 53.464547], + [-2.275543, 53.464547] + ] + ] + } +} diff --git a/test/examples/lineToPolygon/out/linestrings-to-multipolygons.geojson b/test/examples/lineToPolygon/out/linestrings-to-multipolygons.geojson new file mode 100644 index 0000000..3c8f176 --- /dev/null +++ b/test/examples/lineToPolygon/out/linestrings-to-multipolygons.geojson @@ -0,0 +1,80 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [33.4149169921875, 48.28684818710906], + [32.816162109375, 48.42191010942875], + [32.783203125, 48.09642606004488], + [33.3270263671875, 47.931066347509784], + [33.4149169921875, 48.28684818710906] + ] + ], + [ + [ + [35.244140625, 47.15984001304432], + [35.17822265625, 46.37725420510028], + [36.40869140625, 46.240651955001695], + [37.02392578125, 46.9502622421856], + [35.244140625, 47.15984001304432] + ] + ], + [ + [ + [33.42041015625, 46.164614496897094], + [34.12353515625, 46.58906908309182], + [34.73876953125, 46.73233101286786], + [35.013427734375, 47.34626718205302], + [34.07958984374999, 47.73193447949174], + [32.947998046875, 47.338822694822], + [32.354736328125, 46.73986059969267], + [32.54150390625, 46.240651955001695], + [33.42041015625, 46.164614496897094] + ], + [ + [33.398, 46.867], + [34.057, 46.867], + [34.057, 47.197], + [33.398, 47.197], + [33.398, 46.867] + ], + [ + [32.969, 46.46], + [33.321, 46.46], + [33.321, 46.672], + [32.969, 46.672], + [32.969, 46.46] + ] + ], + [ + [ + [34.178466796875, 48.436489955944154], + [35.101318359375, 47.57652571374621], + [37.3974609375, 47.48008846346322], + [38.133544921875, 48.777912755501845], + [35.92529296875, 49.930008124606886], + [34.178466796875, 48.436489955944154] + ], + [ + [34.80468749999999, 48.29050321714062], + [35.04638671874999, 47.938426929481054], + [35.760498046875, 47.95314495015594], + [35.343017578125, 48.32703913063476], + [34.80468749999999, 48.29050321714062] + ], + [ + [35.99395751953125, 47.83528342275264], + [35.93902587890624, 47.73193447949174], + [36.15325927734375, 47.65428791076272], + [35.99395751953125, 47.83528342275264] + ] + ] + ] + } +} diff --git a/test/examples/lineToPolygon/out/multi-linestring-incomplete.geojson b/test/examples/lineToPolygon/out/multi-linestring-incomplete.geojson new file mode 100644 index 0000000..16dfc89 --- /dev/null +++ b/test/examples/lineToPolygon/out/multi-linestring-incomplete.geojson @@ -0,0 +1,31 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [129.28710937499997, -31.57853542647337], + [120.05859375, -26.35249785815401], + [120.05859375, -19.72534224805787], + [124.62890625, -17.056784609942543], + [131.572265625, -17.224758206624628], + [133.330078125, -23.644524198573677], + [129.28710937499997, -31.57853542647337] + ], + [ + [126.2548828125, -20.427012814257385], + [123.662109375, -22.512556954051437], + [124.1455078125, -25.36388227274024], + [126.9580078125, -25.799891182088306], + [128.5400390625, -24.166802085303225], + [127.83691406249999, -21.207458730482642], + [127.265625, -20.756113874762068], + [126.2548828125, -20.427012814257385] + ] + ] + } +} diff --git a/test/examples/lineToPolygon/out/multi-linestring-nested.geojson b/test/examples/lineToPolygon/out/multi-linestring-nested.geojson new file mode 100644 index 0000000..fce548b --- /dev/null +++ b/test/examples/lineToPolygon/out/multi-linestring-nested.geojson @@ -0,0 +1,49 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [106.06201171875, 32.47269502206151], + [111.86279296875, 32.47269502206151], + [111.86279296875, 37.33522435930639], + [106.06201171875, 37.33522435930639], + [106.06201171875, 32.47269502206151] + ], + [ + [106.4794921875, 32.7872745269555], + [110.687255859375, 32.7872745269555], + [110.687255859375, 36.83566824724438], + [106.4794921875, 36.83566824724438], + [106.4794921875, 32.7872745269555] + ], + [ + [101.18408203124999, 32.95336814579932], + [101.18408203124999, 35.93354064249312], + [104.952392578125, 35.93354064249312], + [104.952392578125, 32.95336814579932], + [101.18408203124999, 32.95336814579932] + ], + [ + [102.359619140625, 33.916013113401696], + [103.65600585937499, 33.916013113401696], + [103.65600585937499, 34.97600151317588], + [102.359619140625, 34.97600151317588], + [102.359619140625, 33.916013113401696] + ], + [ + [101.612548828125, 33.330528249028085], + [104.556884765625, 33.330528249028085], + [104.556884765625, 35.46961797120201], + [101.612548828125, 35.46961797120201], + [101.612548828125, 33.330528249028085] + ] + ] + ] + } +} diff --git a/test/examples/lineToPolygon/out/multi-linestring-nested2.geojson b/test/examples/lineToPolygon/out/multi-linestring-nested2.geojson new file mode 100644 index 0000000..4a3384c --- /dev/null +++ b/test/examples/lineToPolygon/out/multi-linestring-nested2.geojson @@ -0,0 +1,58 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [115.927734375, -34.016241889667015], + [134.560546875, -34.016241889667015], + [134.560546875, -16.8886597873816], + [115.927734375, -16.8886597873816], + [115.927734375, -34.016241889667015] + ], + [ + [118.65234374999999, -30.90222470517144], + [131.484375, -30.90222470517144], + [131.484375, -19.808054128088575], + [118.65234374999999, -19.808054128088575], + [118.65234374999999, -30.90222470517144] + ], + [ + [120.9375, -28.998531814051795], + [129.7265625, -28.998531814051795], + [129.7265625, -22.105998799750566], + [120.9375, -22.105998799750566], + [120.9375, -28.998531814051795] + ], + [ + [123.48632812499999, -27.137368359795584], + [127.44140625, -27.137368359795584], + [127.44140625, -24.126701958681668], + [123.48632812499999, -24.126701958681668], + [123.48632812499999, -27.137368359795584] + ] + ], + [ + [ + [139.21874999999997, -36.10237644873643], + [158.73046875, -36.10237644873643], + [158.73046875, -17.476432197195518], + [139.21874999999997, -17.476432197195518], + [139.21874999999997, -36.10237644873643] + ], + [ + [142.3828125, -34.016241889667015], + [155.91796874999997, -34.016241889667015], + [155.91796874999997, -20.13847031245114], + [142.3828125, -20.13847031245114], + [142.3828125, -34.016241889667015] + ] + ] + ] + } +} diff --git a/test/examples/lineToPolygon/out/multi-linestring-outer-ring-middle-position.geojson b/test/examples/lineToPolygon/out/multi-linestring-outer-ring-middle-position.geojson new file mode 100644 index 0000000..98e5458 --- /dev/null +++ b/test/examples/lineToPolygon/out/multi-linestring-outer-ring-middle-position.geojson @@ -0,0 +1,37 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [33.42041015625, 46.164614496897094], + [34.12353515625, 46.58906908309182], + [34.73876953125, 46.73233101286786], + [35.013427734375, 47.34626718205302], + [34.07958984374999, 47.73193447949174], + [32.947998046875, 47.338822694822], + [32.354736328125, 46.73986059969267], + [32.54150390625, 46.240651955001695], + [33.42041015625, 46.164614496897094] + ], + [ + [33.398, 46.867], + [34.057, 46.867], + [34.057, 47.197], + [33.398, 47.197], + [33.398, 46.867] + ], + [ + [32.969, 46.46], + [33.321, 46.46], + [33.321, 46.672], + [32.969, 46.672], + [32.969, 46.46] + ] + ] + } +} diff --git a/test/examples/lineToPolygon/out/multi-linestring-with-hole.geojson b/test/examples/lineToPolygon/out/multi-linestring-with-hole.geojson new file mode 100644 index 0000000..342f08f --- /dev/null +++ b/test/examples/lineToPolygon/out/multi-linestring-with-hole.geojson @@ -0,0 +1,26 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [100, 0], + [101, 0], + [101, 1], + [100, 1], + [100, 0] + ], + [ + [100.2, 0.2], + [100.8, 0.2], + [100.8, 0.8], + [100.2, 0.8], + [100.2, 0.2] + ] + ] + } +} diff --git a/test/examples/lineToPolygon/out/multi-linestrings-nested.geojson b/test/examples/lineToPolygon/out/multi-linestrings-nested.geojson new file mode 100644 index 0000000..4a3384c --- /dev/null +++ b/test/examples/lineToPolygon/out/multi-linestrings-nested.geojson @@ -0,0 +1,58 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [115.927734375, -34.016241889667015], + [134.560546875, -34.016241889667015], + [134.560546875, -16.8886597873816], + [115.927734375, -16.8886597873816], + [115.927734375, -34.016241889667015] + ], + [ + [118.65234374999999, -30.90222470517144], + [131.484375, -30.90222470517144], + [131.484375, -19.808054128088575], + [118.65234374999999, -19.808054128088575], + [118.65234374999999, -30.90222470517144] + ], + [ + [120.9375, -28.998531814051795], + [129.7265625, -28.998531814051795], + [129.7265625, -22.105998799750566], + [120.9375, -22.105998799750566], + [120.9375, -28.998531814051795] + ], + [ + [123.48632812499999, -27.137368359795584], + [127.44140625, -27.137368359795584], + [127.44140625, -24.126701958681668], + [123.48632812499999, -24.126701958681668], + [123.48632812499999, -27.137368359795584] + ] + ], + [ + [ + [139.21874999999997, -36.10237644873643], + [158.73046875, -36.10237644873643], + [158.73046875, -17.476432197195518], + [139.21874999999997, -17.476432197195518], + [139.21874999999997, -36.10237644873643] + ], + [ + [142.3828125, -34.016241889667015], + [155.91796874999997, -34.016241889667015], + [155.91796874999997, -20.13847031245114], + [142.3828125, -20.13847031245114], + [142.3828125, -34.016241889667015] + ] + ] + ] + } +} diff --git a/test/examples/lineToPolygon/out/multi-linestrings-outer-doughnut.geojson b/test/examples/lineToPolygon/out/multi-linestrings-outer-doughnut.geojson new file mode 100644 index 0000000..037a064 --- /dev/null +++ b/test/examples/lineToPolygon/out/multi-linestrings-outer-doughnut.geojson @@ -0,0 +1,44 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [115.927734375, -34.016241889667015], + [134.560546875, -34.016241889667015], + [134.560546875, -16.8886597873816], + [115.927734375, -16.8886597873816], + [115.927734375, -34.016241889667015] + ], + [ + [118.65234374999999, -30.90222470517144], + [131.484375, -30.90222470517144], + [131.484375, -19.808054128088575], + [118.65234374999999, -19.808054128088575], + [118.65234374999999, -30.90222470517144] + ] + ], + [ + [ + [120.9375, -28.998531814051795], + [129.7265625, -28.998531814051795], + [129.7265625, -22.105998799750566], + [120.9375, -22.105998799750566], + [120.9375, -28.998531814051795] + ], + [ + [123.48632812499999, -27.137368359795584], + [127.44140625, -27.137368359795584], + [127.44140625, -24.126701958681668], + [123.48632812499999, -24.126701958681668], + [123.48632812499999, -27.137368359795584] + ] + ] + ] + } +} diff --git a/test/examples/lineToPolygon/out/multi-linestrings-with-holes.geojson b/test/examples/lineToPolygon/out/multi-linestrings-with-holes.geojson new file mode 100644 index 0000000..11bc7f7 --- /dev/null +++ b/test/examples/lineToPolygon/out/multi-linestrings-with-holes.geojson @@ -0,0 +1,53 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [102, 2], + [103, 2], + [103, 3], + [102, 3], + [102, 2] + ], + [ + [102.227783203125, 2.191238104506552], + [102.227783203125, 2.8223442468940902], + [102.843017578125, 2.8223442468940902], + [102.843017578125, 2.191238104506552], + [102.227783203125, 2.191238104506552] + ] + ], + [ + [ + [100, 0], + [101, 0], + [101, 1], + [100, 1], + [100, 0] + ], + [ + [100.206298828125, 0.2526847277643438], + [100.206298828125, 0.7909904981540058], + [100.8050537109375, 0.7909904981540058], + [100.8050537109375, 0.2526847277643438], + [100.206298828125, 0.2526847277643438] + ] + ], + [ + [ + [101.700439453125, 0.5273363048115169], + [102.645263671875, 0.5273363048115169], + [102.645263671875, 1.3511930983018892], + [101.700439453125, 1.3511930983018892], + [101.700439453125, 0.5273363048115169] + ] + ] + ] + } +} From a5aa35acee5443055f4638b7a4717afea8940b33 Mon Sep 17 00:00:00 2001 From: armantorkzaban Date: Mon, 20 Jun 2022 18:10:52 +0200 Subject: [PATCH 03/12] debugging the test on line to polygon --- lib/src/line_to_polygon.dart | 35 +++++++- test/components/line_to_polygon_test.dart | 101 ++++++++++++++-------- 2 files changed, 94 insertions(+), 42 deletions(-) diff --git a/lib/src/line_to_polygon.dart b/lib/src/line_to_polygon.dart index 9e9bdde..64b74e2 100644 --- a/lib/src/line_to_polygon.dart +++ b/lib/src/line_to_polygon.dart @@ -1,5 +1,6 @@ import 'package:turf/bbox.dart'; import 'package:turf/helpers.dart'; +import 'package:turf/meta.dart'; import 'package:turf/src/invariant.dart'; import 'package:turf/src/meta/feature.dart'; @@ -22,6 +23,31 @@ lineToPolygon( bool orderCoords = true, bool mutate = false, }) { + print(lines); + if (lines is FeatureCollection) { + bool onlyLineString = true; + featureEach(lines, (currentFeature, index) { + return onlyLineString = currentFeature is LineString; + }); + if (onlyLineString) { + lines = lines as FeatureCollection; + } else { + throw Exception( + "allowed types are Feature, LineString, FeatureCollection"); + } + } + if (lines is Feature) { + if (lines.geometry is LineString) { + lines = lines as Feature; + } + } + if (lines is! Feature || + lines is! LineString || + lines is! FeatureCollection) { + throw Exception( + "allowed types are Feature, LineString, FeatureCollection"); + } + if (!mutate) { lines = lines.clone(); } @@ -29,10 +55,11 @@ lineToPolygon( if (lines is FeatureCollection) { List>> coords = []; featureEach( - lines, - ((line, featureIndex) => coords.add(getCoords(lineStringToPolygon( - line, autoComplete, orderCoords, properties: {})) - as List>))); + lines, + ((line, featureIndex) => coords.add(getCoords(lineStringToPolygon( + line, autoComplete, orderCoords, properties: {})) + as List>)), + ); return Feature( geometry: MultiPolygon(coordinates: coords), properties: properties); } else { diff --git a/test/components/line_to_polygon_test.dart b/test/components/line_to_polygon_test.dart index a4e76d7..7beb951 100644 --- a/test/components/line_to_polygon_test.dart +++ b/test/components/line_to_polygon_test.dart @@ -4,51 +4,76 @@ import 'dart:io'; import 'package:test/test.dart'; import 'package:turf/helpers.dart'; import 'package:turf/src/line_to_polygon.dart'; +import 'package:turf/src/meta/feature.dart'; void main() { - var inDir = Directory('./test/examples/lineToPolygon/in'); + group( + 'line_to_polygon:', + () { + var inDir = Directory('./test/examples/lineToPolygon/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 properties = (inGeom is Feature)? inGeom.properties ?? { "stroke": "#F0F", "stroke-width": 6 }:{ "stroke": "#F0F", "stroke-width": 6 }; - var results = lineToPolygon(inGeom, - properties: properties, - ); - - var outPath = './' + - file.uri.pathSegments - .sublist(0, file.uri.pathSegments.length - 2) - .join('/') + - '/out/${file.uri.pathSegments.last}'; + test(file.path, () { + var inSource = file.readAsStringSync(); + var inGeom = GeoJSONObject.fromJson(jsonDecode(inSource)); + var properties = (inGeom is Feature) + ? inGeom.properties ?? {"stroke": "#F0F", "stroke-width": 6} + : {"stroke": "#F0F", "stroke-width": 6}; + if (inGeom is FeatureCollection) { + bool onlyLineString = true; + featureEach(inGeom, (currentFeature, index) { + return onlyLineString = currentFeature is LineString; + }); + if (onlyLineString) { + inGeom = inGeom as FeatureCollection; + } else { + throw Exception( + "allowed types are Feature, LineString, FeatureCollection"); + } + } + //print(inGeom); + var results = lineToPolygon( + inGeom, + properties: properties, + ); - var outSource = File(outPath).readAsStringSync(); + var outPath = './' + + file.uri.pathSegments + .sublist(0, file.uri.pathSegments.length - 2) + .join('/') + + '/out/${file.uri.pathSegments.last}'; - expect(inGeom, equals(outSource)); - } - // Handle Errors -test('Handles Errors', (){ + var outSource = File(outPath).readAsStringSync(); - - expect(() => lineToPolygon(point([10, 5])),); - t.throws(() => lineToPolygon(lineString([])), "throws - empty coordinates"); - t.assert( - lineToPolygon( - lineString([ - [10, 5], - [20, 10], - [30, 20], - ]), - { autocomplete: false } - ), - "is valid - autoComplete=false" + expect(results, equals(outSource)); + }); + } + test( + 'Handles Errors', + () { + // expect( + // () => lineToPolygon(Point(coordinates: Position.of([10, 5]))), + // throwsA(isA())); + // expect(() => lineToPolygon(LineString(coordinates: [])), + // throwsA(isA())); + // TODO: what is the outcome? + // expect( + // lineToPolygon( + // LineString(coordinates:[ + // Position.of([10, 5]), + // Position.of([20, 10]), + // Position.of([30, 20]), + // ]), + // autoComplete: false + // ), + // "is valid - autoComplete=false" + // ); + }, + ); + } + }, ); - }); - - t.end(); -}) -;} +} /* const fs = require("fs"); @@ -105,4 +130,4 @@ test("turf-linestring-to-polygon", (t) => { ); t.end(); }); -*/ \ No newline at end of file +*/ From ab5fda57902e8fff3422794a3fbc22c08f888aea Mon Sep 17 00:00:00 2001 From: armantorkzaban Date: Tue, 21 Jun 2022 20:29:49 +0200 Subject: [PATCH 04/12] line_to_polygon_test done --- lib/src/line_to_polygon.dart | 73 ++++++++++++++--------- test/components/line_to_polygon_test.dart | 60 +++++++++---------- 2 files changed, 73 insertions(+), 60 deletions(-) diff --git a/lib/src/line_to_polygon.dart b/lib/src/line_to_polygon.dart index 64b74e2..555cd6d 100644 --- a/lib/src/line_to_polygon.dart +++ b/lib/src/line_to_polygon.dart @@ -2,9 +2,8 @@ import 'package:turf/bbox.dart'; import 'package:turf/helpers.dart'; import 'package:turf/meta.dart'; import 'package:turf/src/invariant.dart'; -import 'package:turf/src/meta/feature.dart'; -/// Converts [MultiLineString](s) to [Polygon](s). +/// Converts [LineString]s & [MultiLineString](s) to [Polygon](s). /// Takes an optional bool autoComplete=true that auto complete [Linestring]s (matches first & last coordinates) /// Takes an optional orderCoords=true that sorts [Linestring]s to place outer ring at the first position of the coordinates /// Takes an optional mutate=false that mutates the original [Linestring] using autoComplete (matches first & last coordinates) @@ -16,38 +15,57 @@ import 'package:turf/src/meta/feature.dart'; /// //addToMap /// var addToMap = [polygon]; /// ``` -lineToPolygon( +Feature lineToPolygon( GeoJSONObject lines, { Map? properties, bool autoComplete = true, bool orderCoords = true, bool mutate = false, }) { - print(lines); + Exception exc = Exception( + """allowed types are Feature, LineString, + MultiLineString, FeatureCollection"""); if (lines is FeatureCollection) { - bool onlyLineString = true; - featureEach(lines, (currentFeature, index) { - return onlyLineString = currentFeature is LineString; - }); - if (onlyLineString) { - lines = lines as FeatureCollection; - } else { - throw Exception( - "allowed types are Feature, LineString, FeatureCollection"); + bool isEitherMultiLineStringOrLineString = true; + + if (isEitherMultiLineStringOrLineString) { + List> list = []; + geomEach( + lines, + ( + GeometryType? currentGeometry, + int? featureIndex, + Map? featureProperties, + BBox? featureBBox, + dynamic featureId, + ) { + if (currentGeometry is LineString) { + list.add(currentGeometry.coordinates); + } else { + list = [...list, ...currentGeometry?.coordinates]; + } + }, + ); + + lines = FeatureCollection(features: []) + ..features.add(Feature(geometry: MultiLineString(coordinates: list))); } - } - if (lines is Feature) { + } else if (lines is Feature) { if (lines.geometry is LineString) { - lines = lines as Feature; + lines = Feature(geometry: lines.geometry as LineString); + } else if (lines.geometry is MultiLineString) { + lines = + Feature(geometry: lines.geometry as MultiLineString); + } else { + throw exc; } + } else if (lines is LineString) { + lines = Feature(geometry: lines); + } else if (lines is MultiLineString) { + lines = Feature(geometry: lines); + } else { + throw exc; } - if (lines is! Feature || - lines is! LineString || - lines is! FeatureCollection) { - throw Exception( - "allowed types are Feature, LineString, FeatureCollection"); - } - if (!mutate) { lines = lines.clone(); } @@ -76,8 +94,10 @@ Feature lineStringToPolygon( {Map? properties}) { properties = properties ?? (line is Feature ? line.properties ?? {} : {}); var geom = line is LineString ? line : (line as Feature).geometry; - List coords = geom is LineString - ? geom.coordinates + List coords = (geom is LineString || geom is MultiLineString) + ? (geom is LineString) + ? geom.coordinates + : (geom as MultiLineString).coordinates : ((geom as Feature).geometry as GeometryType).coordinates; if (coords.isEmpty) throw Exception("line must contain coordinates"); @@ -142,7 +162,6 @@ num _calculateArea(BBox bbox) { return (west! - east!).abs() * (south! - north!).abs(); } - /** * import { Feature, @@ -301,4 +320,4 @@ function calculateArea(bbox: BBox) { } export default lineToPolygon; - */ \ No newline at end of file + */ diff --git a/test/components/line_to_polygon_test.dart b/test/components/line_to_polygon_test.dart index 7beb951..8220ef9 100644 --- a/test/components/line_to_polygon_test.dart +++ b/test/components/line_to_polygon_test.dart @@ -4,7 +4,6 @@ import 'dart:io'; import 'package:test/test.dart'; import 'package:turf/helpers.dart'; import 'package:turf/src/line_to_polygon.dart'; -import 'package:turf/src/meta/feature.dart'; void main() { group( @@ -19,18 +18,6 @@ void main() { var properties = (inGeom is Feature) ? inGeom.properties ?? {"stroke": "#F0F", "stroke-width": 6} : {"stroke": "#F0F", "stroke-width": 6}; - if (inGeom is FeatureCollection) { - bool onlyLineString = true; - featureEach(inGeom, (currentFeature, index) { - return onlyLineString = currentFeature is LineString; - }); - if (onlyLineString) { - inGeom = inGeom as FeatureCollection; - } else { - throw Exception( - "allowed types are Feature, LineString, FeatureCollection"); - } - } //print(inGeom); var results = lineToPolygon( inGeom, @@ -44,30 +31,37 @@ void main() { '/out/${file.uri.pathSegments.last}'; var outSource = File(outPath).readAsStringSync(); + var outGeom = GeoJSONObject.fromJson(jsonDecode(outSource)); - expect(results, equals(outSource)); + if (outGeom is Feature) { + if (outGeom.geometry is Polygon) { + outGeom = + Feature(geometry: outGeom.geometry as Polygon); + } else { + outGeom = Feature( + geometry: outGeom.geometry as MultiPolygon); + } + } + expect(results, equals(outGeom)); }); } test( 'Handles Errors', () { - // expect( - // () => lineToPolygon(Point(coordinates: Position.of([10, 5]))), - // throwsA(isA())); - // expect(() => lineToPolygon(LineString(coordinates: [])), - // throwsA(isA())); - // TODO: what is the outcome? - // expect( - // lineToPolygon( - // LineString(coordinates:[ - // Position.of([10, 5]), - // Position.of([20, 10]), - // Position.of([30, 20]), - // ]), - // autoComplete: false - // ), - // "is valid - autoComplete=false" - // ); + expect( + () => lineToPolygon(Point(coordinates: Position.of([10, 5]))), + throwsA(isA())); + expect(() => lineToPolygon(LineString(coordinates: [])), + throwsA(isA())); + expect( + lineToPolygon( + LineString(coordinates: [ + Position.of([10, 5]), + Position.of([20, 10]), + Position.of([30, 20]), + ]), + autoComplete: false) is Feature, + true); }, ); } @@ -97,9 +91,9 @@ let fixtures = fs.readdirSync(directories.in).map((filename) => { geojson: load.sync(directories.in + filename), }; }); -// fixtures = fixtures.filter(fixture => fixture.name === 'multi-linestrings-with-holes'); +// fixtures = fixtures.filter(fixture => fixture.name === 'multi-outGeomtrings-with-holes'); -test("turf-linestring-to-polygon", (t) => { +test("turf-outGeomtring-to-polygon", (t) => { for (const { name, filename, geojson } of fixtures) { const originalInput = clone(geojson); let { autoComplete, properties, orderCoords } = geojson.properties || {}; From 98f7b14dd19c68cf4a66cdc8b6e2933ef2b08ab6 Mon Sep 17 00:00:00 2001 From: armantorkzaban Date: Tue, 21 Jun 2022 20:48:18 +0200 Subject: [PATCH 05/12] polygonToLine init --- lib/line_to_polygon.dart | 3 + lib/polygon_to_line.dart | 3 + lib/src/polygon_to_line.dart | 218 ++++++++++++++++++ test/components/polygon_to_line_test.dart | 71 ++++++ .../polygonToLine/in/geometry-polygon.geojson | 12 + .../in/multi-polygon-outer-doughnut.geojson | 44 ++++ .../in/multi-polygon-with-holes.geojson | 53 +++++ .../polygonToLine/in/multi-polygon.geojson | 30 +++ .../in/polygon-with-hole.geojson | 26 +++ .../examples/polygonToLine/in/polygon.geojson | 19 ++ .../out/geometry-polygon.geojson | 14 ++ .../out/multi-polygon-outer-doughnut.geojson | 57 +++++ .../out/multi-polygon-with-holes.geojson | 74 ++++++ .../polygonToLine/out/multi-polygon.geojson | 39 ++++ .../out/polygon-with-hole.geojson | 26 +++ .../polygonToLine/out/polygon.geojson | 17 ++ 16 files changed, 706 insertions(+) create mode 100644 lib/line_to_polygon.dart create mode 100644 lib/polygon_to_line.dart create mode 100644 lib/src/polygon_to_line.dart create mode 100644 test/components/polygon_to_line_test.dart create mode 100644 test/examples/polygonToLine/in/geometry-polygon.geojson create mode 100644 test/examples/polygonToLine/in/multi-polygon-outer-doughnut.geojson create mode 100644 test/examples/polygonToLine/in/multi-polygon-with-holes.geojson create mode 100644 test/examples/polygonToLine/in/multi-polygon.geojson create mode 100644 test/examples/polygonToLine/in/polygon-with-hole.geojson create mode 100644 test/examples/polygonToLine/in/polygon.geojson create mode 100644 test/examples/polygonToLine/out/geometry-polygon.geojson create mode 100644 test/examples/polygonToLine/out/multi-polygon-outer-doughnut.geojson create mode 100644 test/examples/polygonToLine/out/multi-polygon-with-holes.geojson create mode 100644 test/examples/polygonToLine/out/multi-polygon.geojson create mode 100644 test/examples/polygonToLine/out/polygon-with-hole.geojson create mode 100644 test/examples/polygonToLine/out/polygon.geojson diff --git a/lib/line_to_polygon.dart b/lib/line_to_polygon.dart new file mode 100644 index 0000000..1dfc8be --- /dev/null +++ b/lib/line_to_polygon.dart @@ -0,0 +1,3 @@ +library turf_line_to_polygon.dart; + +export 'src/line_to_polygon.dart'; diff --git a/lib/polygon_to_line.dart b/lib/polygon_to_line.dart new file mode 100644 index 0000000..0b38e83 --- /dev/null +++ b/lib/polygon_to_line.dart @@ -0,0 +1,3 @@ +library turf_polygon_to_line; + +export 'src/polygon_to_line.dart'; diff --git a/lib/src/polygon_to_line.dart b/lib/src/polygon_to_line.dart new file mode 100644 index 0000000..91086c8 --- /dev/null +++ b/lib/src/polygon_to_line.dart @@ -0,0 +1,218 @@ + +import { featureCollection, lineString, multiLineString } from "@turf/helpers"; +import { + Feature, + FeatureCollection, + LineString, + MultiLineString, + MultiPolygon, + Polygon, + GeoJsonProperties, +} from "geojson"; +import { getGeom } from "@turf/invariant"; + +/** + * Converts a {@link Polygon} to {@link LineString|(Multi)LineString} or {@link MultiPolygon} to a + * {@link FeatureCollection} of {@link LineString|(Multi)LineString}. + * + * @name polygonToLine + * @param {Feature} poly Feature to convert + * @param {Object} [options={}] Optional parameters + * @param {Object} [options.properties={}] translates GeoJSON properties to Feature + * @returns {FeatureCollection|Feature} converted (Multi)Polygon to (Multi)LineString + * @example + * var poly = turf.polygon([[[125, -30], [145, -30], [145, -20], [125, -20], [125, -30]]]); + * + * var line = turf.polygonToLine(poly); + * + * //addToMap + * var addToMap = [line]; + */ +export default function < + G extends Polygon | MultiPolygon, + P = GeoJsonProperties +>( + poly: Feature | G, + options: { properties?: any } = {} +): + | Feature + | FeatureCollection { + const geom: any = getGeom(poly); + if (!options.properties && poly.type === "Feature") { + options.properties = poly.properties; + } + switch (geom.type) { + case "Polygon": + return polygonToLine(geom, options); + case "MultiPolygon": + return multiPolygonToLine(geom, options); + default: + throw new Error("invalid poly"); + } +} + +/** + * @private + */ +export function polygonToLine( + poly: Feature | G, + options: { properties?: any } = {} +): Feature { + const geom = getGeom(poly); + const coords: any[] = geom.coordinates; + const properties: any = options.properties + ? options.properties + : poly.type === "Feature" + ? poly.properties + : {}; + + return coordsToLine(coords, properties); +} + +/** + * @private + */ +export function multiPolygonToLine< + G extends MultiPolygon, + P = GeoJsonProperties +>( + multiPoly: Feature | G, + options: { properties?: P } = {} +): FeatureCollection { + const geom = getGeom(multiPoly); + const coords: any[] = geom.coordinates; + const properties: any = options.properties + ? options.properties + : multiPoly.type === "Feature" + ? multiPoly.properties + : {}; + + const lines: Array> = []; + coords.forEach((coord) => { + lines.push(coordsToLine(coord, properties)); + }); + return featureCollection(lines); +} + +/** + * @private + */ +export function coordsToLine

( + coords: number[][][], + properties: P +): Feature { + if (coords.length > 1) { + return multiLineString(coords, properties); + } + return lineString(coords[0], properties); +} +/** + * import { featureCollection, lineString, multiLineString } from "@turf/helpers"; +import { + Feature, + FeatureCollection, + LineString, + MultiLineString, + MultiPolygon, + Polygon, + GeoJsonProperties, +} from "geojson"; +import { getGeom } from "@turf/invariant"; + +/** + * Converts a {@link Polygon} to {@link LineString|(Multi)LineString} or {@link MultiPolygon} to a + * {@link FeatureCollection} of {@link LineString|(Multi)LineString}. + * + * @name polygonToLine + * @param {Feature} poly Feature to convert + * @param {Object} [options={}] Optional parameters + * @param {Object} [options.properties={}] translates GeoJSON properties to Feature + * @returns {FeatureCollection|Feature} converted (Multi)Polygon to (Multi)LineString + * @example + * var poly = turf.polygon([[[125, -30], [145, -30], [145, -20], [125, -20], [125, -30]]]); + * + * var line = turf.polygonToLine(poly); + * + * //addToMap + * var addToMap = [line]; + */ +export default function < + G extends Polygon | MultiPolygon, + P = GeoJsonProperties +>( + poly: Feature | G, + options: { properties?: any } = {} +): + | Feature + | FeatureCollection { + const geom: any = getGeom(poly); + if (!options.properties && poly.type === "Feature") { + options.properties = poly.properties; + } + switch (geom.type) { + case "Polygon": + return polygonToLine(geom, options); + case "MultiPolygon": + return multiPolygonToLine(geom, options); + default: + throw new Error("invalid poly"); + } +} + +/** + * @private + */ +export function polygonToLine( + poly: Feature | G, + options: { properties?: any } = {} +): Feature { + const geom = getGeom(poly); + const coords: any[] = geom.coordinates; + const properties: any = options.properties + ? options.properties + : poly.type === "Feature" + ? poly.properties + : {}; + + return coordsToLine(coords, properties); +} + +/** + * @private + */ +export function multiPolygonToLine< + G extends MultiPolygon, + P = GeoJsonProperties +>( + multiPoly: Feature | G, + options: { properties?: P } = {} +): FeatureCollection { + const geom = getGeom(multiPoly); + const coords: any[] = geom.coordinates; + const properties: any = options.properties + ? options.properties + : multiPoly.type === "Feature" + ? multiPoly.properties + : {}; + + const lines: Array> = []; + coords.forEach((coord) => { + lines.push(coordsToLine(coord, properties)); + }); + return featureCollection(lines); +} + +/** + * @private + */ +export function coordsToLine

( + coords: number[][][], + properties: P +): Feature { + if (coords.length > 1) { + return multiLineString(coords, properties); + } + return lineString(coords[0], properties); +} + + */ \ No newline at end of file diff --git a/test/components/polygon_to_line_test.dart b/test/components/polygon_to_line_test.dart new file mode 100644 index 0000000..eed77d3 --- /dev/null +++ b/test/components/polygon_to_line_test.dart @@ -0,0 +1,71 @@ +const fs = require("fs"); +const test = require("tape"); +const path = require("path"); +const load = require("load-json-file"); +const write = require("write-json-file"); +const { point } = require("@turf/helpers"); +const { polygon } = require("@turf/helpers"); +const polygonToLine = require("./index").default; + +const directories = { + in: path.join(__dirname, "test", "in") + path.sep, + out: path.join(__dirname, "test", "out") + path.sep, +}; + +const fixtures = fs.readdirSync(directories.in).map((filename) => { + return { + filename, + name: path.parse(filename).name, + geojson: load.sync(directories.in + filename), + }; +}); + +test("turf-polygon-to-linestring", (t) => { + for (const { name, filename, geojson } of fixtures) { + const results = polygonToLine(geojson); + + if (process.env.REGEN) write.sync(directories.out + filename, results); + t.deepEqual(load.sync(directories.out + filename), results, name); + } + // Handle Errors + t.throws(() => polygonToLine(point([10, 5])), "throws - invalid geometry"); + t.throws(() => polygonToLine(polygon([])), "throws - empty coordinates"); + t.end(); +}); + +/** + * const fs = require("fs"); +const test = require("tape"); +const path = require("path"); +const load = require("load-json-file"); +const write = require("write-json-file"); +const { point } = require("@turf/helpers"); +const { polygon } = require("@turf/helpers"); +const polygonToLine = require("./index").default; + +const directories = { + in: path.join(__dirname, "test", "in") + path.sep, + out: path.join(__dirname, "test", "out") + path.sep, +}; + +const fixtures = fs.readdirSync(directories.in).map((filename) => { + return { + filename, + name: path.parse(filename).name, + geojson: load.sync(directories.in + filename), + }; +}); + +test("turf-polygon-to-linestring", (t) => { + for (const { name, filename, geojson } of fixtures) { + const results = polygonToLine(geojson); + + if (process.env.REGEN) write.sync(directories.out + filename, results); + t.deepEqual(load.sync(directories.out + filename), results, name); + } + // Handle Errors + t.throws(() => polygonToLine(point([10, 5])), "throws - invalid geometry"); + t.throws(() => polygonToLine(polygon([])), "throws - empty coordinates"); + t.end(); +}); + */ \ No newline at end of file diff --git a/test/examples/polygonToLine/in/geometry-polygon.geojson b/test/examples/polygonToLine/in/geometry-polygon.geojson new file mode 100644 index 0000000..401ebe2 --- /dev/null +++ b/test/examples/polygonToLine/in/geometry-polygon.geojson @@ -0,0 +1,12 @@ +{ + "type": "Polygon", + "coordinates": [ + [ + [-2.275543, 53.464547], + [-2.275543, 53.489271], + [-2.215118, 53.489271], + [-2.215118, 53.464547], + [-2.275543, 53.464547] + ] + ] +} diff --git a/test/examples/polygonToLine/in/multi-polygon-outer-doughnut.geojson b/test/examples/polygonToLine/in/multi-polygon-outer-doughnut.geojson new file mode 100644 index 0000000..037a064 --- /dev/null +++ b/test/examples/polygonToLine/in/multi-polygon-outer-doughnut.geojson @@ -0,0 +1,44 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [115.927734375, -34.016241889667015], + [134.560546875, -34.016241889667015], + [134.560546875, -16.8886597873816], + [115.927734375, -16.8886597873816], + [115.927734375, -34.016241889667015] + ], + [ + [118.65234374999999, -30.90222470517144], + [131.484375, -30.90222470517144], + [131.484375, -19.808054128088575], + [118.65234374999999, -19.808054128088575], + [118.65234374999999, -30.90222470517144] + ] + ], + [ + [ + [120.9375, -28.998531814051795], + [129.7265625, -28.998531814051795], + [129.7265625, -22.105998799750566], + [120.9375, -22.105998799750566], + [120.9375, -28.998531814051795] + ], + [ + [123.48632812499999, -27.137368359795584], + [127.44140625, -27.137368359795584], + [127.44140625, -24.126701958681668], + [123.48632812499999, -24.126701958681668], + [123.48632812499999, -27.137368359795584] + ] + ] + ] + } +} diff --git a/test/examples/polygonToLine/in/multi-polygon-with-holes.geojson b/test/examples/polygonToLine/in/multi-polygon-with-holes.geojson new file mode 100644 index 0000000..dd14d7c --- /dev/null +++ b/test/examples/polygonToLine/in/multi-polygon-with-holes.geojson @@ -0,0 +1,53 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F00", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [102, 2], + [103, 2], + [103, 3], + [102, 3], + [102, 2] + ], + [ + [102.227783203125, 2.191238104506552], + [102.227783203125, 2.8223442468940902], + [102.843017578125, 2.8223442468940902], + [102.843017578125, 2.191238104506552], + [102.227783203125, 2.191238104506552] + ] + ], + [ + [ + [100, 0], + [101, 0], + [101, 1], + [100, 1], + [100, 0] + ], + [ + [100.206298828125, 0.2526847277643438], + [100.206298828125, 0.7909904981540058], + [100.8050537109375, 0.7909904981540058], + [100.8050537109375, 0.2526847277643438], + [100.206298828125, 0.2526847277643438] + ] + ], + [ + [ + [101.700439453125, 0.5273363048115169], + [102.645263671875, 0.5273363048115169], + [102.645263671875, 1.3511930983018892], + [101.700439453125, 1.3511930983018892], + [101.700439453125, 0.5273363048115169] + ] + ] + ] + } +} diff --git a/test/examples/polygonToLine/in/multi-polygon.geojson b/test/examples/polygonToLine/in/multi-polygon.geojson new file mode 100644 index 0000000..d8731f8 --- /dev/null +++ b/test/examples/polygonToLine/in/multi-polygon.geojson @@ -0,0 +1,30 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F00", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [102, 2], + [103, 2], + [103, 3], + [102, 3], + [102, 2] + ] + ], + [ + [ + [100, 0], + [101, 0], + [101, 1], + [100, 1], + [100, 0] + ] + ] + ] + } +} diff --git a/test/examples/polygonToLine/in/polygon-with-hole.geojson b/test/examples/polygonToLine/in/polygon-with-hole.geojson new file mode 100644 index 0000000..20bb898 --- /dev/null +++ b/test/examples/polygonToLine/in/polygon-with-hole.geojson @@ -0,0 +1,26 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F00", + "stroke-width": 6 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [-2.275543, 53.464547], + [-2.215118, 53.464547], + [-2.215118, 53.489271], + [-2.275543, 53.489271], + [-2.275543, 53.464547] + ], + [ + [-2.261037826538086, 53.47062762161877], + [-2.2293663024902344, 53.47062762161877], + [-2.2293663024902344, 53.48196795587917], + [-2.261037826538086, 53.48196795587917], + [-2.261037826538086, 53.47062762161877] + ] + ] + } +} diff --git a/test/examples/polygonToLine/in/polygon.geojson b/test/examples/polygonToLine/in/polygon.geojson new file mode 100644 index 0000000..a518e3d --- /dev/null +++ b/test/examples/polygonToLine/in/polygon.geojson @@ -0,0 +1,19 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F00", + "stroke-width": 6 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [-2.275543, 53.464547], + [-2.275543, 53.489271], + [-2.215118, 53.489271], + [-2.215118, 53.464547], + [-2.275543, 53.464547] + ] + ] + } +} diff --git a/test/examples/polygonToLine/out/geometry-polygon.geojson b/test/examples/polygonToLine/out/geometry-polygon.geojson new file mode 100644 index 0000000..c8c6b04 --- /dev/null +++ b/test/examples/polygonToLine/out/geometry-polygon.geojson @@ -0,0 +1,14 @@ +{ + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [-2.275543, 53.464547], + [-2.275543, 53.489271], + [-2.215118, 53.489271], + [-2.215118, 53.464547], + [-2.275543, 53.464547] + ] + } +} diff --git a/test/examples/polygonToLine/out/multi-polygon-outer-doughnut.geojson b/test/examples/polygonToLine/out/multi-polygon-outer-doughnut.geojson new file mode 100644 index 0000000..3d3d994 --- /dev/null +++ b/test/examples/polygonToLine/out/multi-polygon-outer-doughnut.geojson @@ -0,0 +1,57 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [115.927734375, -34.016241889667015], + [134.560546875, -34.016241889667015], + [134.560546875, -16.8886597873816], + [115.927734375, -16.8886597873816], + [115.927734375, -34.016241889667015] + ], + [ + [118.65234374999999, -30.90222470517144], + [131.484375, -30.90222470517144], + [131.484375, -19.808054128088575], + [118.65234374999999, -19.808054128088575], + [118.65234374999999, -30.90222470517144] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "stroke": "#F0F", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [120.9375, -28.998531814051795], + [129.7265625, -28.998531814051795], + [129.7265625, -22.105998799750566], + [120.9375, -22.105998799750566], + [120.9375, -28.998531814051795] + ], + [ + [123.48632812499999, -27.137368359795584], + [127.44140625, -27.137368359795584], + [127.44140625, -24.126701958681668], + [123.48632812499999, -24.126701958681668], + [123.48632812499999, -27.137368359795584] + ] + ] + } + } + ] +} diff --git a/test/examples/polygonToLine/out/multi-polygon-with-holes.geojson b/test/examples/polygonToLine/out/multi-polygon-with-holes.geojson new file mode 100644 index 0000000..4af234d --- /dev/null +++ b/test/examples/polygonToLine/out/multi-polygon-with-holes.geojson @@ -0,0 +1,74 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "stroke": "#F00", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [102, 2], + [103, 2], + [103, 3], + [102, 3], + [102, 2] + ], + [ + [102.227783203125, 2.191238104506552], + [102.227783203125, 2.8223442468940902], + [102.843017578125, 2.8223442468940902], + [102.843017578125, 2.191238104506552], + [102.227783203125, 2.191238104506552] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "stroke": "#F00", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [100, 0], + [101, 0], + [101, 1], + [100, 1], + [100, 0] + ], + [ + [100.206298828125, 0.2526847277643438], + [100.206298828125, 0.7909904981540058], + [100.8050537109375, 0.7909904981540058], + [100.8050537109375, 0.2526847277643438], + [100.206298828125, 0.2526847277643438] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "stroke": "#F00", + "stroke-width": 6 + }, + "geometry": { + "type": "LineString", + "coordinates": [ + [101.700439453125, 0.5273363048115169], + [102.645263671875, 0.5273363048115169], + [102.645263671875, 1.3511930983018892], + [101.700439453125, 1.3511930983018892], + [101.700439453125, 0.5273363048115169] + ] + } + } + ] +} diff --git a/test/examples/polygonToLine/out/multi-polygon.geojson b/test/examples/polygonToLine/out/multi-polygon.geojson new file mode 100644 index 0000000..fa82c4d --- /dev/null +++ b/test/examples/polygonToLine/out/multi-polygon.geojson @@ -0,0 +1,39 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "stroke": "#F00", + "stroke-width": 6 + }, + "geometry": { + "type": "LineString", + "coordinates": [ + [102, 2], + [103, 2], + [103, 3], + [102, 3], + [102, 2] + ] + } + }, + { + "type": "Feature", + "properties": { + "stroke": "#F00", + "stroke-width": 6 + }, + "geometry": { + "type": "LineString", + "coordinates": [ + [100, 0], + [101, 0], + [101, 1], + [100, 1], + [100, 0] + ] + } + } + ] +} diff --git a/test/examples/polygonToLine/out/polygon-with-hole.geojson b/test/examples/polygonToLine/out/polygon-with-hole.geojson new file mode 100644 index 0000000..a5dea97 --- /dev/null +++ b/test/examples/polygonToLine/out/polygon-with-hole.geojson @@ -0,0 +1,26 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F00", + "stroke-width": 6 + }, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [-2.275543, 53.464547], + [-2.215118, 53.464547], + [-2.215118, 53.489271], + [-2.275543, 53.489271], + [-2.275543, 53.464547] + ], + [ + [-2.261037826538086, 53.47062762161877], + [-2.2293663024902344, 53.47062762161877], + [-2.2293663024902344, 53.48196795587917], + [-2.261037826538086, 53.48196795587917], + [-2.261037826538086, 53.47062762161877] + ] + ] + } +} diff --git a/test/examples/polygonToLine/out/polygon.geojson b/test/examples/polygonToLine/out/polygon.geojson new file mode 100644 index 0000000..b453fed --- /dev/null +++ b/test/examples/polygonToLine/out/polygon.geojson @@ -0,0 +1,17 @@ +{ + "type": "Feature", + "properties": { + "stroke": "#F00", + "stroke-width": 6 + }, + "geometry": { + "type": "LineString", + "coordinates": [ + [-2.275543, 53.464547], + [-2.275543, 53.489271], + [-2.215118, 53.489271], + [-2.215118, 53.464547], + [-2.275543, 53.464547] + ] + } +} From 2f46a6366f78ee6ca38ec253d58dbe97132c5b29 Mon Sep 17 00:00:00 2001 From: armantorkzaban Date: Wed, 22 Jun 2022 09:55:10 +0200 Subject: [PATCH 06/12] check for features' tyope in FeatureCollections --- lib/src/line_to_polygon.dart | 234 +++++++---------------------------- 1 file changed, 46 insertions(+), 188 deletions(-) diff --git a/lib/src/line_to_polygon.dart b/lib/src/line_to_polygon.dart index 555cd6d..84008b7 100644 --- a/lib/src/line_to_polygon.dart +++ b/lib/src/line_to_polygon.dart @@ -10,7 +10,12 @@ import 'package:turf/src/invariant.dart'; /// Returns [Feature] or [Feature] converted to Polygons. /// example: /// ```dart -/// var line = LineString(coordinates: [[125, -30], [145, -30], [145, -20], [125, -20], [125, -30]]); +/// var line = LineString(coordinates: [ +/// Position.of([125, -30]), +/// Position.of([145, -30]), +/// Position.of([145, -20]), +/// Position.of([125, -20]), +/// Position.of([125, -30])]); /// var polygon = lineToPolygon(line); /// //addToMap /// var addToMap = [polygon]; @@ -26,36 +31,48 @@ Feature lineToPolygon( """allowed types are Feature, LineString, MultiLineString, FeatureCollection"""); if (lines is FeatureCollection) { - bool isEitherMultiLineStringOrLineString = true; - - if (isEitherMultiLineStringOrLineString) { - List> list = []; - geomEach( - lines, - ( - GeometryType? currentGeometry, - int? featureIndex, - Map? featureProperties, - BBox? featureBBox, - dynamic featureId, - ) { - if (currentGeometry is LineString) { - list.add(currentGeometry.coordinates); - } else { - list = [...list, ...currentGeometry?.coordinates]; - } - }, - ); + featureEach( + lines, + (currentFeature, index) { + if (currentFeature.geometry is! LineString && + currentFeature.geometry is! MultiLineString) { + throw exc; + } + }, + ); + List> list = []; + geomEach( + lines, + ( + GeometryType? currentGeometry, + int? featureIndex, + Map? featureProperties, + BBox? featureBBox, + dynamic featureId, + ) { + if (currentGeometry is LineString) { + list.add(currentGeometry.coordinates); + } else { + list = [...list, ...currentGeometry?.coordinates]; + } + }, + ); - lines = FeatureCollection(features: []) - ..features.add(Feature(geometry: MultiLineString(coordinates: list))); - } + lines = FeatureCollection(features: []) + ..features.add(Feature(geometry: MultiLineString(coordinates: list))); } else if (lines is Feature) { if (lines.geometry is LineString) { - lines = Feature(geometry: lines.geometry as LineString); + lines = Feature( + geometry: lines.geometry as LineString, + properties: lines.properties, + id: lines.id, + ); } else if (lines.geometry is MultiLineString) { - lines = - Feature(geometry: lines.geometry as MultiLineString); + lines = Feature( + geometry: lines.geometry as MultiLineString, + properties: lines.properties, + id: lines.id, + ); } else { throw exc; } @@ -88,7 +105,8 @@ Feature lineToPolygon( /// Converts LineString to Polygon /// Takes a optional bool autoComplete=true that auto completes linestrings -/// Takes an optional orderCoords=true that sorts linestrings to place outer ring at the first position of the coordinates +/// Takes an optional orderCoords=true that sorts linestrings to place outer +/// ring at the first position of the coordinates. Feature lineStringToPolygon( GeoJSONObject line, bool autoComplete, bool orderCoords, {Map? properties}) { @@ -161,163 +179,3 @@ num _calculateArea(BBox bbox) { var north = bbox[3]; return (west! - east!).abs() * (south! - north!).abs(); } - -/** - * import { - Feature, - FeatureCollection, - MultiLineString, - LineString, - GeoJsonProperties, - BBox, - Position, -} from "geojson"; -import turfBBox from "@turf/bbox"; -import { getCoords, getGeom } from "@turf/invariant"; -import { polygon, multiPolygon, lineString } from "@turf/helpers"; -import clone from "@turf/clone"; - -/** - * Converts (Multi)LineString(s) to Polygon(s). - * - * @name lineToPolygon - * @param {FeatureCollection|Feature} lines Features to convert - * @param {Object} [options={}] Optional parameters - * @param {Object} [options.properties={}] translates GeoJSON properties to Feature - * @param {boolean} [options.autoComplete=true] auto complete linestrings (matches first & last coordinates) - * @param {boolean} [options.orderCoords=true] sorts linestrings to place outer ring at the first position of the coordinates - * @param {boolean} [options.mutate=false] mutate the original linestring using autoComplete (matches first & last coordinates) - * @returns {Feature} converted to Polygons - * @example - * var line = turf.lineString([[125, -30], [145, -30], [145, -20], [125, -20], [125, -30]]); - * - * var polygon = turf.lineToPolygon(line); - * - * //addToMap - * var addToMap = [polygon]; - */ -function lineToPolygon( - lines: Feature | FeatureCollection | G, - options: { - properties?: GeoJsonProperties; - autoComplete?: boolean; - orderCoords?: boolean; - mutate?: boolean; - } = {} -) { - // Optional parameters - var properties = options.properties; - var autoComplete = options.autoComplete ?? true; - var orderCoords = options.orderCoords ?? true; - var mutate = options.mutate ?? false; - - if (!mutate) { - lines = clone(lines); - } - - switch (lines.type) { - case "FeatureCollection": - var coords: number[][][][] = []; - lines.features.forEach(function (line) { - coords.push( - getCoords(lineStringToPolygon(line, {}, autoComplete, orderCoords)) - ); - }); - return multiPolygon(coords, properties); - default: - return lineStringToPolygon(lines, properties, autoComplete, orderCoords); - } -} - -/** - * LineString to Polygon - * - * @private - * @param {Feature} line line - * @param {Object} [properties] translates GeoJSON properties to Feature - * @param {boolean} [autoComplete=true] auto complete linestrings - * @param {boolean} [orderCoords=true] sorts linestrings to place outer ring at the first position of the coordinates - * @returns {Feature} line converted to Polygon - */ -function lineStringToPolygon( - line: Feature | G, - properties: GeoJsonProperties | undefined, - autoComplete: boolean, - orderCoords: boolean -) { - properties = properties - ? properties - : line.type === "Feature" - ? line.properties - : {}; - var geom = getGeom(line); - var coords: Position[] | Position[][] = geom.coordinates; - var type = geom.type; - - if (!coords.length) throw new Error("line must contain coordinates"); - - switch (type) { - case "LineString": - if (autoComplete) coords = autoCompleteCoords(coords as Position[]); - return polygon([coords as Position[]], properties); - case "MultiLineString": - var multiCoords: number[][][] = []; - var largestArea = 0; - - (coords as Position[][]).forEach(function (coord) { - if (autoComplete) coord = autoCompleteCoords(coord); - - // Largest LineString to be placed in the first position of the coordinates array - if (orderCoords) { - var area = calculateArea(turfBBox(lineString(coord))); - if (area > largestArea) { - multiCoords.unshift(coord); - largestArea = area; - } else multiCoords.push(coord); - } else { - multiCoords.push(coord); - } - }); - return polygon(multiCoords, properties); - default: - throw new Error("geometry type " + type + " is not supported"); - } -} - -/** - * Auto Complete Coords - matches first & last coordinates - * - * @private - * @param {Array>} coords Coordinates - * @returns {Array>} auto completed coordinates - */ -function autoCompleteCoords(coords: Position[]) { - var first = coords[0]; - var x1 = first[0]; - var y1 = first[1]; - var last = coords[coords.length - 1]; - var x2 = last[0]; - var y2 = last[1]; - if (x1 !== x2 || y1 !== y2) { - coords.push(first); - } - return coords; -} - -/** - * area - quick approximate area calculation (used to sort) - * - * @private - * @param {Array} bbox BBox [west, south, east, north] - * @returns {number} very quick area calculation - */ -function calculateArea(bbox: BBox) { - var west = bbox[0]; - var south = bbox[1]; - var east = bbox[2]; - var north = bbox[3]; - return Math.abs(west - east) * Math.abs(south - north); -} - -export default lineToPolygon; - */ From 8edd96f28c278aa36327915122f25553474e7b70 Mon Sep 17 00:00:00 2001 From: armantorkzaban Date: Wed, 22 Jun 2022 09:59:43 +0200 Subject: [PATCH 07/12] file name change --- ...ollection-linestring.geojson => collection_linestring.geojson} | 0 .../{geometry-linestring.geojson => geometry_linestring.geojson} | 0 ...inestring-incomplete.geojson => linestring_incomplete.geojson} | 0 ...multipolygons.geojson => linestrings_to_multipolygons.geojson} | 0 ...ing-incomplete.geojson => multi_linestring_incomplete.geojson} | 0 ...-linestring-nested.geojson => multi_linestring_nested.geojson} | 0 ...inestring-nested2.geojson => multi_linestring_nested2.geojson} | 0 ...eojson => multi_linestring_outer_ring_middle_position.geojson} | 0 ...tring-with-hole.geojson => multi_linestring_with_hole.geojson} | 0 ...inestrings-nested.geojson => multi_linestrings_nested.geojson} | 0 ...-doughnut.geojson => multi_linestrings_outer_doughnut.geojson} | 0 ...gs-with-holes.geojson => multi_linestrings_with_holes.geojson} | 0 ...ollection-linestring.geojson => collection_linestring.geojson} | 0 .../{geometry-linestring.geojson => geometry_linestring.geojson} | 0 ...inestring-incomplete.geojson => linestring_incomplete.geojson} | 0 ...multipolygons.geojson => linestrings_to_multipolygons.geojson} | 0 ...ing-incomplete.geojson => multi_linestring_incomplete.geojson} | 0 ...-linestring-nested.geojson => multi_linestring_nested.geojson} | 0 ...inestring-nested2.geojson => multi_linestring_nested2.geojson} | 0 ...eojson => multi_linestring_outer_ring_middle_position.geojson} | 0 ...tring-with-hole.geojson => multi_linestring_with_hole.geojson} | 0 ...inestrings-nested.geojson => multi_linestrings_nested.geojson} | 0 ...-doughnut.geojson => multi_linestrings_outer_doughnut.geojson} | 0 ...gs-with-holes.geojson => multi_linestrings_with_holes.geojson} | 0 24 files changed, 0 insertions(+), 0 deletions(-) rename test/examples/lineToPolygon/in/{collection-linestring.geojson => collection_linestring.geojson} (100%) rename test/examples/lineToPolygon/in/{geometry-linestring.geojson => geometry_linestring.geojson} (100%) rename test/examples/lineToPolygon/in/{linestring-incomplete.geojson => linestring_incomplete.geojson} (100%) rename test/examples/lineToPolygon/in/{linestrings-to-multipolygons.geojson => linestrings_to_multipolygons.geojson} (100%) rename test/examples/lineToPolygon/in/{multi-linestring-incomplete.geojson => multi_linestring_incomplete.geojson} (100%) rename test/examples/lineToPolygon/in/{multi-linestring-nested.geojson => multi_linestring_nested.geojson} (100%) rename test/examples/lineToPolygon/in/{multi-linestring-nested2.geojson => multi_linestring_nested2.geojson} (100%) rename test/examples/lineToPolygon/in/{multi-linestring-outer-ring-middle-position.geojson => multi_linestring_outer_ring_middle_position.geojson} (100%) rename test/examples/lineToPolygon/in/{multi-linestring-with-hole.geojson => multi_linestring_with_hole.geojson} (100%) rename test/examples/lineToPolygon/in/{multi-linestrings-nested.geojson => multi_linestrings_nested.geojson} (100%) rename test/examples/lineToPolygon/in/{multi-linestrings-outer-doughnut.geojson => multi_linestrings_outer_doughnut.geojson} (100%) rename test/examples/lineToPolygon/in/{multi-linestrings-with-holes.geojson => multi_linestrings_with_holes.geojson} (100%) rename test/examples/lineToPolygon/out/{collection-linestring.geojson => collection_linestring.geojson} (100%) rename test/examples/lineToPolygon/out/{geometry-linestring.geojson => geometry_linestring.geojson} (100%) rename test/examples/lineToPolygon/out/{linestring-incomplete.geojson => linestring_incomplete.geojson} (100%) rename test/examples/lineToPolygon/out/{linestrings-to-multipolygons.geojson => linestrings_to_multipolygons.geojson} (100%) rename test/examples/lineToPolygon/out/{multi-linestring-incomplete.geojson => multi_linestring_incomplete.geojson} (100%) rename test/examples/lineToPolygon/out/{multi-linestring-nested.geojson => multi_linestring_nested.geojson} (100%) rename test/examples/lineToPolygon/out/{multi-linestring-nested2.geojson => multi_linestring_nested2.geojson} (100%) rename test/examples/lineToPolygon/out/{multi-linestring-outer-ring-middle-position.geojson => multi_linestring_outer_ring_middle_position.geojson} (100%) rename test/examples/lineToPolygon/out/{multi-linestring-with-hole.geojson => multi_linestring_with_hole.geojson} (100%) rename test/examples/lineToPolygon/out/{multi-linestrings-nested.geojson => multi_linestrings_nested.geojson} (100%) rename test/examples/lineToPolygon/out/{multi-linestrings-outer-doughnut.geojson => multi_linestrings_outer_doughnut.geojson} (100%) rename test/examples/lineToPolygon/out/{multi-linestrings-with-holes.geojson => multi_linestrings_with_holes.geojson} (100%) diff --git a/test/examples/lineToPolygon/in/collection-linestring.geojson b/test/examples/lineToPolygon/in/collection_linestring.geojson similarity index 100% rename from test/examples/lineToPolygon/in/collection-linestring.geojson rename to test/examples/lineToPolygon/in/collection_linestring.geojson diff --git a/test/examples/lineToPolygon/in/geometry-linestring.geojson b/test/examples/lineToPolygon/in/geometry_linestring.geojson similarity index 100% rename from test/examples/lineToPolygon/in/geometry-linestring.geojson rename to test/examples/lineToPolygon/in/geometry_linestring.geojson diff --git a/test/examples/lineToPolygon/in/linestring-incomplete.geojson b/test/examples/lineToPolygon/in/linestring_incomplete.geojson similarity index 100% rename from test/examples/lineToPolygon/in/linestring-incomplete.geojson rename to test/examples/lineToPolygon/in/linestring_incomplete.geojson diff --git a/test/examples/lineToPolygon/in/linestrings-to-multipolygons.geojson b/test/examples/lineToPolygon/in/linestrings_to_multipolygons.geojson similarity index 100% rename from test/examples/lineToPolygon/in/linestrings-to-multipolygons.geojson rename to test/examples/lineToPolygon/in/linestrings_to_multipolygons.geojson diff --git a/test/examples/lineToPolygon/in/multi-linestring-incomplete.geojson b/test/examples/lineToPolygon/in/multi_linestring_incomplete.geojson similarity index 100% rename from test/examples/lineToPolygon/in/multi-linestring-incomplete.geojson rename to test/examples/lineToPolygon/in/multi_linestring_incomplete.geojson diff --git a/test/examples/lineToPolygon/in/multi-linestring-nested.geojson b/test/examples/lineToPolygon/in/multi_linestring_nested.geojson similarity index 100% rename from test/examples/lineToPolygon/in/multi-linestring-nested.geojson rename to test/examples/lineToPolygon/in/multi_linestring_nested.geojson diff --git a/test/examples/lineToPolygon/in/multi-linestring-nested2.geojson b/test/examples/lineToPolygon/in/multi_linestring_nested2.geojson similarity index 100% rename from test/examples/lineToPolygon/in/multi-linestring-nested2.geojson rename to test/examples/lineToPolygon/in/multi_linestring_nested2.geojson diff --git a/test/examples/lineToPolygon/in/multi-linestring-outer-ring-middle-position.geojson b/test/examples/lineToPolygon/in/multi_linestring_outer_ring_middle_position.geojson similarity index 100% rename from test/examples/lineToPolygon/in/multi-linestring-outer-ring-middle-position.geojson rename to test/examples/lineToPolygon/in/multi_linestring_outer_ring_middle_position.geojson diff --git a/test/examples/lineToPolygon/in/multi-linestring-with-hole.geojson b/test/examples/lineToPolygon/in/multi_linestring_with_hole.geojson similarity index 100% rename from test/examples/lineToPolygon/in/multi-linestring-with-hole.geojson rename to test/examples/lineToPolygon/in/multi_linestring_with_hole.geojson diff --git a/test/examples/lineToPolygon/in/multi-linestrings-nested.geojson b/test/examples/lineToPolygon/in/multi_linestrings_nested.geojson similarity index 100% rename from test/examples/lineToPolygon/in/multi-linestrings-nested.geojson rename to test/examples/lineToPolygon/in/multi_linestrings_nested.geojson diff --git a/test/examples/lineToPolygon/in/multi-linestrings-outer-doughnut.geojson b/test/examples/lineToPolygon/in/multi_linestrings_outer_doughnut.geojson similarity index 100% rename from test/examples/lineToPolygon/in/multi-linestrings-outer-doughnut.geojson rename to test/examples/lineToPolygon/in/multi_linestrings_outer_doughnut.geojson diff --git a/test/examples/lineToPolygon/in/multi-linestrings-with-holes.geojson b/test/examples/lineToPolygon/in/multi_linestrings_with_holes.geojson similarity index 100% rename from test/examples/lineToPolygon/in/multi-linestrings-with-holes.geojson rename to test/examples/lineToPolygon/in/multi_linestrings_with_holes.geojson diff --git a/test/examples/lineToPolygon/out/collection-linestring.geojson b/test/examples/lineToPolygon/out/collection_linestring.geojson similarity index 100% rename from test/examples/lineToPolygon/out/collection-linestring.geojson rename to test/examples/lineToPolygon/out/collection_linestring.geojson diff --git a/test/examples/lineToPolygon/out/geometry-linestring.geojson b/test/examples/lineToPolygon/out/geometry_linestring.geojson similarity index 100% rename from test/examples/lineToPolygon/out/geometry-linestring.geojson rename to test/examples/lineToPolygon/out/geometry_linestring.geojson diff --git a/test/examples/lineToPolygon/out/linestring-incomplete.geojson b/test/examples/lineToPolygon/out/linestring_incomplete.geojson similarity index 100% rename from test/examples/lineToPolygon/out/linestring-incomplete.geojson rename to test/examples/lineToPolygon/out/linestring_incomplete.geojson diff --git a/test/examples/lineToPolygon/out/linestrings-to-multipolygons.geojson b/test/examples/lineToPolygon/out/linestrings_to_multipolygons.geojson similarity index 100% rename from test/examples/lineToPolygon/out/linestrings-to-multipolygons.geojson rename to test/examples/lineToPolygon/out/linestrings_to_multipolygons.geojson diff --git a/test/examples/lineToPolygon/out/multi-linestring-incomplete.geojson b/test/examples/lineToPolygon/out/multi_linestring_incomplete.geojson similarity index 100% rename from test/examples/lineToPolygon/out/multi-linestring-incomplete.geojson rename to test/examples/lineToPolygon/out/multi_linestring_incomplete.geojson diff --git a/test/examples/lineToPolygon/out/multi-linestring-nested.geojson b/test/examples/lineToPolygon/out/multi_linestring_nested.geojson similarity index 100% rename from test/examples/lineToPolygon/out/multi-linestring-nested.geojson rename to test/examples/lineToPolygon/out/multi_linestring_nested.geojson diff --git a/test/examples/lineToPolygon/out/multi-linestring-nested2.geojson b/test/examples/lineToPolygon/out/multi_linestring_nested2.geojson similarity index 100% rename from test/examples/lineToPolygon/out/multi-linestring-nested2.geojson rename to test/examples/lineToPolygon/out/multi_linestring_nested2.geojson diff --git a/test/examples/lineToPolygon/out/multi-linestring-outer-ring-middle-position.geojson b/test/examples/lineToPolygon/out/multi_linestring_outer_ring_middle_position.geojson similarity index 100% rename from test/examples/lineToPolygon/out/multi-linestring-outer-ring-middle-position.geojson rename to test/examples/lineToPolygon/out/multi_linestring_outer_ring_middle_position.geojson diff --git a/test/examples/lineToPolygon/out/multi-linestring-with-hole.geojson b/test/examples/lineToPolygon/out/multi_linestring_with_hole.geojson similarity index 100% rename from test/examples/lineToPolygon/out/multi-linestring-with-hole.geojson rename to test/examples/lineToPolygon/out/multi_linestring_with_hole.geojson diff --git a/test/examples/lineToPolygon/out/multi-linestrings-nested.geojson b/test/examples/lineToPolygon/out/multi_linestrings_nested.geojson similarity index 100% rename from test/examples/lineToPolygon/out/multi-linestrings-nested.geojson rename to test/examples/lineToPolygon/out/multi_linestrings_nested.geojson diff --git a/test/examples/lineToPolygon/out/multi-linestrings-outer-doughnut.geojson b/test/examples/lineToPolygon/out/multi_linestrings_outer_doughnut.geojson similarity index 100% rename from test/examples/lineToPolygon/out/multi-linestrings-outer-doughnut.geojson rename to test/examples/lineToPolygon/out/multi_linestrings_outer_doughnut.geojson diff --git a/test/examples/lineToPolygon/out/multi-linestrings-with-holes.geojson b/test/examples/lineToPolygon/out/multi_linestrings_with_holes.geojson similarity index 100% rename from test/examples/lineToPolygon/out/multi-linestrings-with-holes.geojson rename to test/examples/lineToPolygon/out/multi_linestrings_with_holes.geojson From f05529963b964acd1337de4e21c5efd34c013921 Mon Sep 17 00:00:00 2001 From: armantorkzaban Date: Thu, 23 Jun 2022 09:45:26 +0200 Subject: [PATCH 08/12] test and impl. done for polygonToLine --- lib/src/polygon_to_line.dart | 259 ++++-------------- test/components/polygon_to_line_test.dart | 135 ++++----- ...lygon.geojson => geometry_polygon.geojson} | 0 ...-polygon.geojson => multi_polygon.geojson} | 0 ...n => multi_polygon_outer_doughnut.geojson} | 0 ...ojson => multi_polygon_with_holes.geojson} | 0 ...hole.geojson => polygon_with_hole.geojson} | 0 ...lygon.geojson => geometry_polygon.geojson} | 0 ...-polygon.geojson => multi_polygon.geojson} | 0 ...n => multi_polygon_outer_doughnut.geojson} | 0 ...ojson => multi_polygon_with_holes.geojson} | 0 ...hole.geojson => polygon_with_hole.geojson} | 0 12 files changed, 123 insertions(+), 271 deletions(-) rename test/examples/polygonToLine/in/{geometry-polygon.geojson => geometry_polygon.geojson} (100%) rename test/examples/polygonToLine/in/{multi-polygon.geojson => multi_polygon.geojson} (100%) rename test/examples/polygonToLine/in/{multi-polygon-outer-doughnut.geojson => multi_polygon_outer_doughnut.geojson} (100%) rename test/examples/polygonToLine/in/{multi-polygon-with-holes.geojson => multi_polygon_with_holes.geojson} (100%) rename test/examples/polygonToLine/in/{polygon-with-hole.geojson => polygon_with_hole.geojson} (100%) rename test/examples/polygonToLine/out/{geometry-polygon.geojson => geometry_polygon.geojson} (100%) rename test/examples/polygonToLine/out/{multi-polygon.geojson => multi_polygon.geojson} (100%) rename test/examples/polygonToLine/out/{multi-polygon-outer-doughnut.geojson => multi_polygon_outer_doughnut.geojson} (100%) rename test/examples/polygonToLine/out/{multi-polygon-with-holes.geojson => multi_polygon_with_holes.geojson} (100%) rename test/examples/polygonToLine/out/{polygon-with-hole.geojson => polygon_with_hole.geojson} (100%) diff --git a/lib/src/polygon_to_line.dart b/lib/src/polygon_to_line.dart index 91086c8..06b49ac 100644 --- a/lib/src/polygon_to_line.dart +++ b/lib/src/polygon_to_line.dart @@ -1,218 +1,69 @@ +import '../helpers.dart'; -import { featureCollection, lineString, multiLineString } from "@turf/helpers"; -import { - Feature, - FeatureCollection, - LineString, - MultiLineString, - MultiPolygon, - Polygon, - GeoJsonProperties, -} from "geojson"; -import { getGeom } from "@turf/invariant"; +/// Converts a [Polygon] to [LineString] or [MultiLineString] or a [MultiPolygon] to a +/// [FeatureCollection] of [LineString] or [MultiLineString]. +/// Returns [FeatureCollection] or [Feature] or [Feature] +/// example: +/// ```dart +/// var poly = Polygon(coordinates: +/// [ +/// [ +/// Position.of([125, -30]), +/// Position.of([145, -30]), +/// Position.of([145, -20]), +/// Position.of([125, -20]), +/// Position.of([125, -30]) +/// ] +/// ]); +/// var line = polygonToLine(poly); +/// //addToMap +/// var addToMap = [line]; +/// ``` +polygonToLine(GeoJSONObject poly, {Map? properties}) { + var geom = poly is Feature ? poly.geometry : poly; -/** - * Converts a {@link Polygon} to {@link LineString|(Multi)LineString} or {@link MultiPolygon} to a - * {@link FeatureCollection} of {@link LineString|(Multi)LineString}. - * - * @name polygonToLine - * @param {Feature} poly Feature to convert - * @param {Object} [options={}] Optional parameters - * @param {Object} [options.properties={}] translates GeoJSON properties to Feature - * @returns {FeatureCollection|Feature} converted (Multi)Polygon to (Multi)LineString - * @example - * var poly = turf.polygon([[[125, -30], [145, -30], [145, -20], [125, -20], [125, -30]]]); - * - * var line = turf.polygonToLine(poly); - * - * //addToMap - * var addToMap = [line]; - */ -export default function < - G extends Polygon | MultiPolygon, - P = GeoJsonProperties ->( - poly: Feature | G, - options: { properties?: any } = {} -): - | Feature - | FeatureCollection { - const geom: any = getGeom(poly); - if (!options.properties && poly.type === "Feature") { - options.properties = poly.properties; - } - switch (geom.type) { - case "Polygon": - return polygonToLine(geom, options); - case "MultiPolygon": - return multiPolygonToLine(geom, options); - default: - throw new Error("invalid poly"); - } -} - -/** - * @private - */ -export function polygonToLine( - poly: Feature | G, - options: { properties?: any } = {} -): Feature { - const geom = getGeom(poly); - const coords: any[] = geom.coordinates; - const properties: any = options.properties - ? options.properties - : poly.type === "Feature" - ? poly.properties - : {}; - - return coordsToLine(coords, properties); -} - -/** - * @private - */ -export function multiPolygonToLine< - G extends MultiPolygon, - P = GeoJsonProperties ->( - multiPoly: Feature | G, - options: { properties?: P } = {} -): FeatureCollection { - const geom = getGeom(multiPoly); - const coords: any[] = geom.coordinates; - const properties: any = options.properties - ? options.properties - : multiPoly.type === "Feature" - ? multiPoly.properties - : {}; + (poly is Feature) + ? properties = poly.properties + : properties = {}; - const lines: Array> = []; - coords.forEach((coord) => { - lines.push(coordsToLine(coord, properties)); - }); - return featureCollection(lines); -} - -/** - * @private - */ -export function coordsToLine

( - coords: number[][][], - properties: P -): Feature { - if (coords.length > 1) { - return multiLineString(coords, properties); + if (geom is Polygon) { + return _polygonToLine(poly, properties: properties); + } else if (geom is MultiPolygon) { + return _multiPolygonToLine(poly, properties: properties); + } else { + throw Exception("invalid poly"); } - return lineString(coords[0], properties); } -/** - * import { featureCollection, lineString, multiLineString } from "@turf/helpers"; -import { - Feature, - FeatureCollection, - LineString, - MultiLineString, - MultiPolygon, - Polygon, - GeoJsonProperties, -} from "geojson"; -import { getGeom } from "@turf/invariant"; -/** - * Converts a {@link Polygon} to {@link LineString|(Multi)LineString} or {@link MultiPolygon} to a - * {@link FeatureCollection} of {@link LineString|(Multi)LineString}. - * - * @name polygonToLine - * @param {Feature} poly Feature to convert - * @param {Object} [options={}] Optional parameters - * @param {Object} [options.properties={}] translates GeoJSON properties to Feature - * @returns {FeatureCollection|Feature} converted (Multi)Polygon to (Multi)LineString - * @example - * var poly = turf.polygon([[[125, -30], [145, -30], [145, -20], [125, -20], [125, -30]]]); - * - * var line = turf.polygonToLine(poly); - * - * //addToMap - * var addToMap = [line]; - */ -export default function < - G extends Polygon | MultiPolygon, - P = GeoJsonProperties ->( - poly: Feature | G, - options: { properties?: any } = {} -): - | Feature - | FeatureCollection { - const geom: any = getGeom(poly); - if (!options.properties && poly.type === "Feature") { - options.properties = poly.properties; - } - switch (geom.type) { - case "Polygon": - return polygonToLine(geom, options); - case "MultiPolygon": - return multiPolygonToLine(geom, options); - default: - throw new Error("invalid poly"); - } -} - -/** - * @private - */ -export function polygonToLine( - poly: Feature | G, - options: { properties?: any } = {} -): Feature { - const geom = getGeom(poly); - const coords: any[] = geom.coordinates; - const properties: any = options.properties - ? options.properties - : poly.type === "Feature" - ? poly.properties - : {}; +Feature _polygonToLine(GeoJSONObject poly, {Map? properties}) { + var geom = poly is Feature ? poly.geometry : poly; + var coords = (geom as GeometryType).coordinates; + properties = + properties ?? (poly is Feature ? poly.properties : {}); - return coordsToLine(coords, properties); + return _coordsToLine(coords, properties); } -/** - * @private - */ -export function multiPolygonToLine< - G extends MultiPolygon, - P = GeoJsonProperties ->( - multiPoly: Feature | G, - options: { properties?: P } = {} -): FeatureCollection { - const geom = getGeom(multiPoly); - const coords: any[] = geom.coordinates; - const properties: any = options.properties - ? options.properties - : multiPoly.type === "Feature" - ? multiPoly.properties - : {}; +FeatureCollection _multiPolygonToLine(GeoJSONObject multiPoly, + {Map? properties}) { + var geom = multiPoly is Feature ? multiPoly.geometry : multiPoly; + var coords = (geom as GeometryType).coordinates; + properties = properties ?? + (multiPoly is Feature ? multiPoly.properties : {}); - const lines: Array> = []; - coords.forEach((coord) => { - lines.push(coordsToLine(coord, properties)); - }); - return featureCollection(lines); + var lines = []; + coords.forEach((coord) => {lines.add(_coordsToLine(coord, properties))}); + return FeatureCollection(features: lines); } -/** - * @private - */ -export function coordsToLine

( - coords: number[][][], - properties: P -): Feature { - if (coords.length > 1) { - return multiLineString(coords, properties); +Feature _coordsToLine( + List> coords, Map? properties) { + if (coords.isEmpty) { + throw RangeError("coordinates is empty"); + } else if (coords.length > 1) { + return Feature( + geometry: MultiLineString(coordinates: coords), properties: properties); } - return lineString(coords[0], properties); + return Feature( + geometry: LineString(coordinates: coords[0]), properties: properties); } - - */ \ No newline at end of file diff --git a/test/components/polygon_to_line_test.dart b/test/components/polygon_to_line_test.dart index eed77d3..8084653 100644 --- a/test/components/polygon_to_line_test.dart +++ b/test/components/polygon_to_line_test.dart @@ -1,71 +1,72 @@ -const fs = require("fs"); -const test = require("tape"); -const path = require("path"); -const load = require("load-json-file"); -const write = require("write-json-file"); -const { point } = require("@turf/helpers"); -const { polygon } = require("@turf/helpers"); -const polygonToLine = require("./index").default; +import 'dart:convert'; +import 'dart:io'; -const directories = { - in: path.join(__dirname, "test", "in") + path.sep, - out: path.join(__dirname, "test", "out") + path.sep, -}; +import 'package:test/expect.dart'; +import 'package:test/scaffolding.dart'; +import 'package:turf/polygon_to_line.dart'; +import 'package:turf/turf.dart'; -const fixtures = fs.readdirSync(directories.in).map((filename) => { - return { - filename, - name: path.parse(filename).name, - geojson: load.sync(directories.in + filename), - }; -}); +main() { + group( + 'polygonToLine', + () { + var inDir = Directory('./test/examples/polygonToLine/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 results = polygonToLine(inGeom); -test("turf-polygon-to-linestring", (t) => { - for (const { name, filename, geojson } of fixtures) { - const results = polygonToLine(geojson); + var outPath = './' + + file.uri.pathSegments + .sublist(0, file.uri.pathSegments.length - 2) + .join('/') + + '/out/${file.uri.pathSegments.last}'; - if (process.env.REGEN) write.sync(directories.out + filename, results); - t.deepEqual(load.sync(directories.out + filename), results, name); - } - // Handle Errors - t.throws(() => polygonToLine(point([10, 5])), "throws - invalid geometry"); - t.throws(() => polygonToLine(polygon([])), "throws - empty coordinates"); - t.end(); -}); - -/** - * const fs = require("fs"); -const test = require("tape"); -const path = require("path"); -const load = require("load-json-file"); -const write = require("write-json-file"); -const { point } = require("@turf/helpers"); -const { polygon } = require("@turf/helpers"); -const polygonToLine = require("./index").default; - -const directories = { - in: path.join(__dirname, "test", "in") + path.sep, - out: path.join(__dirname, "test", "out") + path.sep, -}; - -const fixtures = fs.readdirSync(directories.in).map((filename) => { - return { - filename, - name: path.parse(filename).name, - geojson: load.sync(directories.in + filename), - }; -}); - -test("turf-polygon-to-linestring", (t) => { - for (const { name, filename, geojson } of fixtures) { - const results = polygonToLine(geojson); - - if (process.env.REGEN) write.sync(directories.out + filename, results); - t.deepEqual(load.sync(directories.out + filename), results, name); - } - // Handle Errors - t.throws(() => polygonToLine(point([10, 5])), "throws - invalid geometry"); - t.throws(() => polygonToLine(polygon([])), "throws - empty coordinates"); - t.end(); -}); - */ \ No newline at end of file + var outSource = File(outPath).readAsStringSync(); + var outGeom = GeoJSONObject.fromJson(jsonDecode(outSource)); + if (results is FeatureCollection) { + expect(outGeom is FeatureCollection, true); + for (var i = 0; i < results.features.length; i++) { + expect(results.features[i], + equals((outGeom as FeatureCollection).features[i])); + expect( + (results.features[i].geometry as GeometryType).coordinates, + equals((outGeom.features[i].geometry as GeometryType) + .coordinates), + ); + expect( + results.features[i].properties, + equals(outGeom.features[i].properties), + ); + } + } else if (results is Feature) { + expect(outGeom is Feature, true); + expect((outGeom as Feature).properties, + equals(results.properties)); + expect((results.geometry as GeometryType).type, + equals((outGeom.geometry)?.type)); + expect((results.geometry as GeometryType).coordinates, + equals((outGeom.geometry as GeometryType).coordinates)); + } + }, + ); + test( + "handles error", + () { + // Handle Errors + expect( + () => polygonToLine(Point(coordinates: Position.of([10, 5]))), + throwsA(isA())); + expect(() => polygonToLine(Polygon(coordinates: [])), + throwsA(isA())); + }, + ); + } + } + }, + ); +} diff --git a/test/examples/polygonToLine/in/geometry-polygon.geojson b/test/examples/polygonToLine/in/geometry_polygon.geojson similarity index 100% rename from test/examples/polygonToLine/in/geometry-polygon.geojson rename to test/examples/polygonToLine/in/geometry_polygon.geojson diff --git a/test/examples/polygonToLine/in/multi-polygon.geojson b/test/examples/polygonToLine/in/multi_polygon.geojson similarity index 100% rename from test/examples/polygonToLine/in/multi-polygon.geojson rename to test/examples/polygonToLine/in/multi_polygon.geojson diff --git a/test/examples/polygonToLine/in/multi-polygon-outer-doughnut.geojson b/test/examples/polygonToLine/in/multi_polygon_outer_doughnut.geojson similarity index 100% rename from test/examples/polygonToLine/in/multi-polygon-outer-doughnut.geojson rename to test/examples/polygonToLine/in/multi_polygon_outer_doughnut.geojson diff --git a/test/examples/polygonToLine/in/multi-polygon-with-holes.geojson b/test/examples/polygonToLine/in/multi_polygon_with_holes.geojson similarity index 100% rename from test/examples/polygonToLine/in/multi-polygon-with-holes.geojson rename to test/examples/polygonToLine/in/multi_polygon_with_holes.geojson diff --git a/test/examples/polygonToLine/in/polygon-with-hole.geojson b/test/examples/polygonToLine/in/polygon_with_hole.geojson similarity index 100% rename from test/examples/polygonToLine/in/polygon-with-hole.geojson rename to test/examples/polygonToLine/in/polygon_with_hole.geojson diff --git a/test/examples/polygonToLine/out/geometry-polygon.geojson b/test/examples/polygonToLine/out/geometry_polygon.geojson similarity index 100% rename from test/examples/polygonToLine/out/geometry-polygon.geojson rename to test/examples/polygonToLine/out/geometry_polygon.geojson diff --git a/test/examples/polygonToLine/out/multi-polygon.geojson b/test/examples/polygonToLine/out/multi_polygon.geojson similarity index 100% rename from test/examples/polygonToLine/out/multi-polygon.geojson rename to test/examples/polygonToLine/out/multi_polygon.geojson diff --git a/test/examples/polygonToLine/out/multi-polygon-outer-doughnut.geojson b/test/examples/polygonToLine/out/multi_polygon_outer_doughnut.geojson similarity index 100% rename from test/examples/polygonToLine/out/multi-polygon-outer-doughnut.geojson rename to test/examples/polygonToLine/out/multi_polygon_outer_doughnut.geojson diff --git a/test/examples/polygonToLine/out/multi-polygon-with-holes.geojson b/test/examples/polygonToLine/out/multi_polygon_with_holes.geojson similarity index 100% rename from test/examples/polygonToLine/out/multi-polygon-with-holes.geojson rename to test/examples/polygonToLine/out/multi_polygon_with_holes.geojson diff --git a/test/examples/polygonToLine/out/polygon-with-hole.geojson b/test/examples/polygonToLine/out/polygon_with_hole.geojson similarity index 100% rename from test/examples/polygonToLine/out/polygon-with-hole.geojson rename to test/examples/polygonToLine/out/polygon_with_hole.geojson From c120ac7c4bd2153c1ae0eed90931e8cc50945bd4 Mon Sep 17 00:00:00 2001 From: Lukas Himsel Date: Mon, 4 Jul 2022 08:59:35 +0200 Subject: [PATCH 09/12] refactor autocomplete, lineStringToPolygon --- lib/src/line_to_polygon.dart | 52 +++++++++++++++++------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/lib/src/line_to_polygon.dart b/lib/src/line_to_polygon.dart index 84008b7..5757734 100644 --- a/lib/src/line_to_polygon.dart +++ b/lib/src/line_to_polygon.dart @@ -108,30 +108,32 @@ Feature lineToPolygon( /// Takes an optional orderCoords=true that sorts linestrings to place outer /// ring at the first position of the coordinates. Feature lineStringToPolygon( - GeoJSONObject line, bool autoComplete, bool orderCoords, - {Map? properties}) { + GeoJSONObject line, + bool autoComplete, + bool orderCoords, { + Map? properties, +}) { properties = properties ?? (line is Feature ? line.properties ?? {} : {}); - var geom = line is LineString ? line : (line as Feature).geometry; - List coords = (geom is LineString || geom is MultiLineString) - ? (geom is LineString) - ? geom.coordinates - : (geom as MultiLineString).coordinates - : ((geom as Feature).geometry as GeometryType).coordinates; - if (coords.isEmpty) throw Exception("line must contain coordinates"); + if (line is Feature && line.geometry != null) { + return lineStringToPolygon(line.geometry!, autoComplete, orderCoords); + } + + if (line is GeometryType && line.coordinates.isEmpty) { + throw Exception("line must contain coordinates"); + } + + if (line is LineString) { + var coords = + autoComplete ? _autoCompleteCoords(line.coordinates) : line.coordinates; - if (geom is LineString) { - if (autoComplete) { - coords = _autoCompleteCoords(coords as List); - } return Feature( - geometry: Polygon(coordinates: [coords as List]), - properties: properties); - } else if (geom is MultiLineString) { + geometry: Polygon(coordinates: [coords]), properties: properties); + } else if (line is MultiLineString) { List> multiCoords = []; num largestArea = 0; - (coords as List>).forEach((coord) { + line.coordinates.forEach((coord) { if (autoComplete) { coord = _autoCompleteCoords(coord); } @@ -152,23 +154,17 @@ Feature lineStringToPolygon( return Feature( geometry: Polygon(coordinates: multiCoords), properties: properties); } else { - throw Exception( - "geometry type ${(geom as GeoJSONObject).type} is not supported"); + throw Exception("Geometry type ${line.type} is not supported"); } } /// Auto Completes Coords - matches first & last coordinates List _autoCompleteCoords(List coords) { - var first = coords[0]; - var x1 = first[0]; - var y1 = first[1]; - var last = coords[coords.length - 1]; - var x2 = last[0]; - var y2 = last[1]; - if (x1 != x2 || y1 != y2) { - coords.add(first); + var newCoords = coords.map((c) => c.clone()).toList(); + if (newCoords.first != newCoords.last) { + newCoords.add(newCoords.first.clone()); } - return coords; + return newCoords; } /// Quick calculates approximate area (used to sort) From d6ae86cb398bbafbb7c8b3a3b261ecc3aef22dab Mon Sep 17 00:00:00 2001 From: armantorkzaban Date: Mon, 4 Jul 2022 10:04:09 +0200 Subject: [PATCH 10/12] comments resolved --- lib/src/line_to_polygon.dart | 32 +++++++++++++++++--------------- lib/src/polygon_to_line.dart | 27 +++++++++++---------------- 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/lib/src/line_to_polygon.dart b/lib/src/line_to_polygon.dart index 5757734..99578da 100644 --- a/lib/src/line_to_polygon.dart +++ b/lib/src/line_to_polygon.dart @@ -3,7 +3,7 @@ import 'package:turf/helpers.dart'; import 'package:turf/meta.dart'; import 'package:turf/src/invariant.dart'; -/// Converts [LineString]s & [MultiLineString](s) to [Polygon](s). +/// Converts [LineString]s & [MultiLineString](s) to [Polygon] or [MultiPolygon]. /// Takes an optional bool autoComplete=true that auto complete [Linestring]s (matches first & last coordinates) /// Takes an optional orderCoords=true that sorts [Linestring]s to place outer ring at the first position of the coordinates /// Takes an optional mutate=false that mutates the original [Linestring] using autoComplete (matches first & last coordinates) @@ -133,24 +133,26 @@ Feature lineStringToPolygon( List> multiCoords = []; num largestArea = 0; - line.coordinates.forEach((coord) { - if (autoComplete) { - coord = _autoCompleteCoords(coord); - } + line.coordinates.forEach( + (coord) { + if (autoComplete) { + coord = _autoCompleteCoords(coord); + } - // Largest LineString to be placed in the first position of the coordinates array - if (orderCoords) { - var area = _calculateArea(bbox(LineString(coordinates: coord))); - if (area > largestArea) { - multiCoords.insert(0, coord); - largestArea = area; + // Largest LineString to be placed in the first position of the coordinates array + if (orderCoords) { + var area = _calculateArea(bbox(LineString(coordinates: coord))); + if (area > largestArea) { + multiCoords.insert(0, coord); + largestArea = area; + } else { + multiCoords.add(coord); + } } else { multiCoords.add(coord); } - } else { - multiCoords.add(coord); - } - }); + }, + ); return Feature( geometry: Polygon(coordinates: multiCoords), properties: properties); } else { diff --git a/lib/src/polygon_to_line.dart b/lib/src/polygon_to_line.dart index 06b49ac..2f0a331 100644 --- a/lib/src/polygon_to_line.dart +++ b/lib/src/polygon_to_line.dart @@ -19,37 +19,32 @@ import '../helpers.dart'; /// //addToMap /// var addToMap = [line]; /// ``` -polygonToLine(GeoJSONObject poly, {Map? properties}) { +dynamic polygonToLine(GeoJSONObject poly, {Map? properties}) { var geom = poly is Feature ? poly.geometry : poly; - (poly is Feature) - ? properties = poly.properties - : properties = {}; + properties = + properties ?? ((poly is Feature) ? poly.properties : {}); if (geom is Polygon) { - return _polygonToLine(poly, properties: properties); + return _polygonToLine(geom, properties: properties); } else if (geom is MultiPolygon) { - return _multiPolygonToLine(poly, properties: properties); + return _multiPolygonToLine(geom, properties: properties); } else { throw Exception("invalid poly"); } } -Feature _polygonToLine(GeoJSONObject poly, {Map? properties}) { - var geom = poly is Feature ? poly.geometry : poly; - var coords = (geom as GeometryType).coordinates; - properties = - properties ?? (poly is Feature ? poly.properties : {}); +Feature _polygonToLine(Polygon geom, {Map? properties}) { + var coords = geom.coordinates; + properties = properties ?? {}; return _coordsToLine(coords, properties); } -FeatureCollection _multiPolygonToLine(GeoJSONObject multiPoly, +FeatureCollection _multiPolygonToLine(MultiPolygon geom, {Map? properties}) { - var geom = multiPoly is Feature ? multiPoly.geometry : multiPoly; - var coords = (geom as GeometryType).coordinates; - properties = properties ?? - (multiPoly is Feature ? multiPoly.properties : {}); + var coords = geom.coordinates; + properties = properties ?? {}; var lines = []; coords.forEach((coord) => {lines.add(_coordsToLine(coord, properties))}); From 2213cf8ac1978e280a9110c8186a3ead652252ba Mon Sep 17 00:00:00 2001 From: armantorkzaban Date: Mon, 4 Jul 2022 10:14:08 +0200 Subject: [PATCH 11/12] type added --- lib/src/polygon_to_line.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/polygon_to_line.dart b/lib/src/polygon_to_line.dart index 2f0a331..6f25a44 100644 --- a/lib/src/polygon_to_line.dart +++ b/lib/src/polygon_to_line.dart @@ -19,7 +19,8 @@ import '../helpers.dart'; /// //addToMap /// var addToMap = [line]; /// ``` -dynamic polygonToLine(GeoJSONObject poly, {Map? properties}) { +GeoJSONObject polygonToLine(GeoJSONObject poly, + {Map? properties}) { var geom = poly is Feature ? poly.geometry : poly; properties = From 92cee2ee6c726d4648350342b41410e063eac09d Mon Sep 17 00:00:00 2001 From: armantorkzaban Date: Mon, 4 Jul 2022 13:41:30 +0200 Subject: [PATCH 12/12] implementation and test and type setting --- lib/src/line_to_polygon.dart | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/src/line_to_polygon.dart b/lib/src/line_to_polygon.dart index 99578da..6870ba5 100644 --- a/lib/src/line_to_polygon.dart +++ b/lib/src/line_to_polygon.dart @@ -51,9 +51,16 @@ Feature lineToPolygon( dynamic featureId, ) { if (currentGeometry is LineString) { - list.add(currentGeometry.coordinates); + list.add(currentGeometry.coordinates.map((e) => e.clone()).toList()); + } else if (currentGeometry is MultiLineString) { + list = [ + ...list, + ...currentGeometry.coordinates + .map((e) => e.map((p) => p.clone()).toList()) + .toList() + ]; } else { - list = [...list, ...currentGeometry?.coordinates]; + throw Exception("$currentGeometry type is not supperted"); } }, );