From 028e0222c76f24aa4cae3fec080194e15dab9594 Mon Sep 17 00:00:00 2001 From: Denis Date: Sun, 30 Apr 2017 23:35:13 -0400 Subject: [PATCH 1/5] Publish new module @turf/rewind --- packages/turf-rewind/LICENSE | 20 +++ packages/turf-rewind/README.md | 79 ++++++++++++ packages/turf-rewind/bench.js | 34 +++++ packages/turf-rewind/index.d.ts | 14 +++ packages/turf-rewind/index.js | 117 ++++++++++++++++++ packages/turf-rewind/package.json | 46 +++++++ packages/turf-rewind/test.js | 31 +++++ ...geometry-polygon-counter-clockwise.geojson | 27 ++++ .../test/in/line-clockwise.geojson | 49 ++++++++ .../test/in/line-counter-clockwise.geojson | 49 ++++++++ .../test/in/polygon-clockwise.geojson | 31 +++++ .../test/in/polygon-counter-clockwise.geojson | 31 +++++ ...geometry-polygon-counter-clockwise.geojson | 27 ++++ .../test/out/line-clockwise.geojson | 49 ++++++++ .../test/out/line-counter-clockwise.geojson | 49 ++++++++ .../test/out/polygon-clockwise.geojson | 31 +++++ .../out/polygon-counter-clockwise.geojson | 31 +++++ packages/turf-rewind/test/types.ts | 15 +++ 18 files changed, 730 insertions(+) create mode 100644 packages/turf-rewind/LICENSE create mode 100644 packages/turf-rewind/README.md create mode 100644 packages/turf-rewind/bench.js create mode 100644 packages/turf-rewind/index.d.ts create mode 100644 packages/turf-rewind/index.js create mode 100644 packages/turf-rewind/package.json create mode 100644 packages/turf-rewind/test.js create mode 100644 packages/turf-rewind/test/in/geometry-polygon-counter-clockwise.geojson create mode 100644 packages/turf-rewind/test/in/line-clockwise.geojson create mode 100644 packages/turf-rewind/test/in/line-counter-clockwise.geojson create mode 100644 packages/turf-rewind/test/in/polygon-clockwise.geojson create mode 100644 packages/turf-rewind/test/in/polygon-counter-clockwise.geojson create mode 100644 packages/turf-rewind/test/out/geometry-polygon-counter-clockwise.geojson create mode 100644 packages/turf-rewind/test/out/line-clockwise.geojson create mode 100644 packages/turf-rewind/test/out/line-counter-clockwise.geojson create mode 100644 packages/turf-rewind/test/out/polygon-clockwise.geojson create mode 100644 packages/turf-rewind/test/out/polygon-counter-clockwise.geojson create mode 100644 packages/turf-rewind/test/types.ts diff --git a/packages/turf-rewind/LICENSE b/packages/turf-rewind/LICENSE new file mode 100644 index 0000000000..96ce51b76f --- /dev/null +++ b/packages/turf-rewind/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2017 TurfJS + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/turf-rewind/README.md b/packages/turf-rewind/README.md new file mode 100644 index 0000000000..d4109f6a8b --- /dev/null +++ b/packages/turf-rewind/README.md @@ -0,0 +1,79 @@ +# @turf/rewind + +# rewind + +Rewind [LineString](http://geojson.org/geojson-spec.html#linestring) or [Polygon](http://geojson.org/geojson-spec.html#polygon) outer ring clockwise and inner rings counterclockwise (Uses [Shoelace Formula](http://en.wikipedia.org/wiki/Shoelace_formula)). + +**Parameters** + +- `geojson` **[Feature](http://geojson.org/geojson-spec.html#feature-objects)<([Polygon](http://geojson.org/geojson-spec.html#polygon) \| [LineString](http://geojson.org/geojson-spec.html#linestring))>** input GeoJSON Polygon +- `reverse` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** enable reverse winding (optional, default `false`) +- `mutate` **\[[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** allows GeoJSON input to be mutated (significant performance increase if true) (optional, default `false`) + +**Examples** + +```javascript +var polygon = { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [[121, -29], [138, -29], [138, -18], [121, -18], [121, -29]] + ] + } +}; +var rewind = turf.rewind(polygon); + +//addToMap +var addToMap = [rewind]; +``` + +Returns **[Feature](http://geojson.org/geojson-spec.html#feature-objects)<([Polygon](http://geojson.org/geojson-spec.html#polygon) \| [LineString](http://geojson.org/geojson-spec.html#linestring))>** rewind Polygon + +# rewindLineString + +Rewind LineString - outer ring clockwise + +**Parameters** + +- `coords` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>>** GeoJSON LineString geometry coordinates +- `reverse` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** enable reverse winding (optional, default `false`) + +Returns **void** mutates coordinates + +# rewindPolygon + +Rewind Polygon - outer ring clockwise and inner rings counterclockwise. + +**Parameters** + +- `coords` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>>>** GeoJSON Polygon geometry coordinates +- `reverse` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** enable reverse winding (optional, default `false`) + +Returns **void** mutates coordinates + + + +--- + +This module is part of the [Turfjs project](http://turfjs.org/), an open source +module collection dedicated to geographic algorithms. It is maintained in the +[Turfjs/turf](https://github.com/Turfjs/turf) repository, where you can create +PRs and issues. + +### Installation + +Install this module individually: + +```sh +$ npm install @turf/rewind +``` + +Or install the Turf module that includes it as a function: + +```sh +$ npm install @turf/turf +``` diff --git a/packages/turf-rewind/bench.js b/packages/turf-rewind/bench.js new file mode 100644 index 0000000000..1021db23ea --- /dev/null +++ b/packages/turf-rewind/bench.js @@ -0,0 +1,34 @@ +const fs = require('fs'); +const path = require('path'); +const load = require('load-json-file'); +const Benchmark = require('benchmark'); +const rewind = require('./'); + +const directory = path.join(__dirname, 'test', 'in') + path.sep; +let fixtures = fs.readdirSync(directory).map(filename => { + return { + filename, + name: path.parse(filename).name, + geojson: load.sync(directory + filename) + }; +}); +// fixtures = fixtures.filter(fixture => fixture.name === 'polygons'); + +/** + * Benchmark Results + * + * geometry-polygon-counter-clockwise x 3,217,454 ops/sec ±4.31% (83 runs sampled) + * line-clockwise x 2,249,133 ops/sec ±0.97% (90 runs sampled) + * line-counter-clockwise x 2,224,334 ops/sec ±1.40% (87 runs sampled) + * polygon-clockwise x 3,429,437 ops/sec ±1.49% (86 runs sampled) + * polygon-counter-clockwise x 3,464,880 ops/sec ±1.05% (88 runs sampled) + */ +const suite = new Benchmark.Suite('turf-rewind'); +for (const {name, geojson} of fixtures) { + suite.add(name, () => rewind(geojson, false, true)); +} + +suite + .on('cycle', e => console.log(String(e.target))) + .on('complete', () => {}) + .run(); diff --git a/packages/turf-rewind/index.d.ts b/packages/turf-rewind/index.d.ts new file mode 100644 index 0000000000..41b670855a --- /dev/null +++ b/packages/turf-rewind/index.d.ts @@ -0,0 +1,14 @@ +/// + +type Polygon = GeoJSON.Feature | GeoJSON.Polygon; +type LineString = GeoJSON.Feature | GeoJSON.LineString; +type MultiLineString = GeoJSON.Feature | GeoJSON.MultiLineString; +type MultiPolygon = GeoJSON.Feature | GeoJSON.MultiPolygon; +type Rewind = Polygon | LineString | MultiLineString | MultiPolygon; + +/** + * http://turfjs.org/docs/#rewind + */ +declare function rewind(geojson: Input, reversed?: boolean, mutate?: boolean): Input; +declare namespace rewind { } +export = rewind; diff --git a/packages/turf-rewind/index.js b/packages/turf-rewind/index.js new file mode 100644 index 0000000000..d6dcdd57e9 --- /dev/null +++ b/packages/turf-rewind/index.js @@ -0,0 +1,117 @@ +var getCoords = require('@turf/invariant').getCoords; + +/** + * Rewind {@link LineString} or {@link Polygon} outer ring clockwise and inner rings counterclockwise (Uses {@link http://en.wikipedia.org/wiki/Shoelace_formula|Shoelace Formula}). + * + * @name rewind + * @param {Feature} geojson input GeoJSON Polygon + * @param {Boolean} [reverse=false] enable reverse winding + * @param {boolean} [mutate=false] allows GeoJSON input to be mutated (significant performance increase if true) + * @returns {Feature} rewind Polygon + * @example + * var polygon = { + * "type": "Feature", + * "properties": {}, + * "geometry": { + * "type": "Polygon", + * "coordinates": [ + * [[121, -29], [138, -29], [138, -18], [121, -18], [121, -29]] + * ] + * } + * }; + * var rewind = turf.rewind(polygon); + * + * //addToMap + * var addToMap = [rewind]; + */ +module.exports = function (geojson, reverse, mutate) { + // default params + reverse = (reverse !== undefined) ? reverse : false; + mutate = (mutate !== undefined) ? mutate : false; + + // validation + if (!geojson) throw new Error(' is required'); + if (typeof reverse !== 'boolean') throw new Error(' must be a boolean'); + if (typeof mutate !== 'boolean') throw new Error(' must be a boolean'); + + // prevent input mutation + if (mutate === false || mutate === undefined) geojson = JSON.parse(JSON.stringify(geojson)); + + var coords = getCoords(geojson); + var type = getGeomType(geojson); + + switch (type) { + case 'LineString': + rewindLineString(coords, reverse); + return geojson; + case 'Polygon': + rewindPolygon(coords, reverse); + return geojson; + case 'MultiLineString': + coords.forEach(function (lineCoords) { + rewindLineString(lineCoords, reverse); + }); + return geojson; + case 'MultiPolygon': + coords.forEach(function (lineCoords) { + rewindPolygon(lineCoords, reverse); + }); + return geojson; + default: + throw new Error('geometry ' + type + ' type not supported'); + } +}; + +/** + * Rewind LineString - outer ring clockwise + * + * @param {Array>} coords GeoJSON LineString geometry coordinates + * @param {Boolean} [reverse=false] enable reverse winding + * @returns {void} mutates coordinates + */ +function rewindLineString(coords, reverse) { + if (isClockWise(coords) === reverse) coords.reverse(); +} + +/** + * Rewind Polygon - outer ring clockwise and inner rings counterclockwise. + * + * @param {Array>>} coords GeoJSON Polygon geometry coordinates + * @param {Boolean} [reverse=false] enable reverse winding + * @returns {void} mutates coordinates + */ +function rewindPolygon(coords, reverse) { + // outer ring + if (isClockWise(coords[0]) === reverse) { + coords[0].reverse(); + } + // inner rings + for (var i = 1; i < coords.length; i++) { + if (isClockWise(coords[i]) !== reverse) { + coords[i].reverse(); + } + } +} + +/** + * is Clockwise + * + * @private + * @param {Array>} coords LineString geometry coordinates + * @returns {boolean} is LineString clockwise or not + */ +function isClockWise(coords) { + var initialValue = 0; + var reduced = coords.reduce(function (previous, current, index) { + var a = previous; + var b = current; + var c = index; + var d = coords; + return a + ((c < d.length - 1) ? (d[c + 1][0] - b[0]) * (d[c + 1][1] + b[1]) : 0); + }, initialValue); + return reduced > 0; +} + +function getGeomType(feature) { + return (feature.geometry) ? feature.geometry.type : feature.type; +} diff --git a/packages/turf-rewind/package.json b/packages/turf-rewind/package.json new file mode 100644 index 0000000000..eca50a57af --- /dev/null +++ b/packages/turf-rewind/package.json @@ -0,0 +1,46 @@ +{ + "name": "@turf/rewind", + "version": "4.0.0", + "description": "turf rewind module", + "main": "index.js", + "types": "index.d.ts", + "files": [ + "index.js", + "index.d.ts" + ], + "scripts": { + "test": "node test.js", + "bench": "node bench.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/Turfjs/turf.git" + }, + "keywords": [ + "turf", + "geojson", + "polygon", + "rewind" + ], + "author": "Turf Authors", + "contributors": [ + "Abel Vázquez Montoro <@AbelVM>", + "Tom MacWright <@tmcw>", + "Denis Carriere <@DenisCarriere>" + ], + "license": "MIT", + "bugs": { + "url": "https://github.com/Turfjs/turf/issues" + }, + "homepage": "https://github.com/Turfjs/turf", + "devDependencies": { + "@turf/helpers": "^4.2.0", + "benchmark": "^2.1.4", + "load-json-file": "^2.0.0", + "tape": "^4.6.3", + "write-json-file": "^2.0.0" + }, + "dependencies": { + "@turf/invariant": "^4.2.0" + } +} diff --git a/packages/turf-rewind/test.js b/packages/turf-rewind/test.js new file mode 100644 index 0000000000..3c477e5574 --- /dev/null +++ b/packages/turf-rewind/test.js @@ -0,0 +1,31 @@ +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 rewind = require('./'); + +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 === 'line-counter-clockwise'); + +test('turf-rewind', t => { + for (const {filename, name, geojson} of fixtures) { + const {reverse} = geojson.properties || {}; + const results = rewind(geojson, reverse); + + if (process.env.REGEN) write.sync(directories.out + filename, results); + t.deepEqual(results, load.sync(directories.out + filename), name); + } + t.end(); +}); diff --git a/packages/turf-rewind/test/in/geometry-polygon-counter-clockwise.geojson b/packages/turf-rewind/test/in/geometry-polygon-counter-clockwise.geojson new file mode 100644 index 0000000000..0142d8bdf4 --- /dev/null +++ b/packages/turf-rewind/test/in/geometry-polygon-counter-clockwise.geojson @@ -0,0 +1,27 @@ +{ + "type": "Polygon", + "coordinates": [ + [ + [ + 121.9921875, + -29.22889003019423 + ], + [ + 138.515625, + -29.22889003019423 + ], + [ + 138.515625, + -18.312810846425442 + ], + [ + 121.9921875, + -18.312810846425442 + ], + [ + 121.9921875, + -29.22889003019423 + ] + ] + ] +} \ No newline at end of file diff --git a/packages/turf-rewind/test/in/line-clockwise.geojson b/packages/turf-rewind/test/in/line-clockwise.geojson new file mode 100644 index 0000000000..4e44ddb26c --- /dev/null +++ b/packages/turf-rewind/test/in/line-clockwise.geojson @@ -0,0 +1,49 @@ +{ + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + 122.87109375, + -20.13847031245114 + ], + [ + 126.21093749999999, + -15.792253570362446 + ], + [ + 129.5947265625, + -14.604847155053898 + ], + [ + 134.560546875, + -15.834535741221552 + ], + [ + 138.73535156249997, + -20.014645445341355 + ], + [ + 139.833984375, + -25.799891182088306 + ], + [ + 134.12109375, + -30.183121842195504 + ], + [ + 131.8798828125, + -30.221101852485987 + ], + [ + 128.49609375, + -29.878755346037963 + ], + [ + 124.4091796875, + -27.839076094777802 + ] + ] + } +} \ No newline at end of file diff --git a/packages/turf-rewind/test/in/line-counter-clockwise.geojson b/packages/turf-rewind/test/in/line-counter-clockwise.geojson new file mode 100644 index 0000000000..17dafd3b27 --- /dev/null +++ b/packages/turf-rewind/test/in/line-counter-clockwise.geojson @@ -0,0 +1,49 @@ +{ + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + 124.4091796875, + -27.839076094777802 + ], + [ + 128.49609375, + -29.878755346037963 + ], + [ + 131.8798828125, + -30.221101852485987 + ], + [ + 134.12109375, + -30.183121842195504 + ], + [ + 139.833984375, + -25.799891182088306 + ], + [ + 138.73535156249997, + -20.014645445341355 + ], + [ + 134.560546875, + -15.834535741221552 + ], + [ + 129.5947265625, + -14.604847155053898 + ], + [ + 126.21093749999999, + -15.792253570362446 + ], + [ + 122.87109375, + -20.13847031245114 + ] + ] + } +} diff --git a/packages/turf-rewind/test/in/polygon-clockwise.geojson b/packages/turf-rewind/test/in/polygon-clockwise.geojson new file mode 100644 index 0000000000..b823d23879 --- /dev/null +++ b/packages/turf-rewind/test/in/polygon-clockwise.geojson @@ -0,0 +1,31 @@ +{ + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 121.9921875, + -29.22889003019423 + ], + [ + 121.9921875, + -18.312810846425442 + ], + [ + 138.515625, + -18.312810846425442 + ], + [ + 138.515625, + -29.22889003019423 + ], + [ + 121.9921875, + -29.22889003019423 + ] + ] + ] + } +} diff --git a/packages/turf-rewind/test/in/polygon-counter-clockwise.geojson b/packages/turf-rewind/test/in/polygon-counter-clockwise.geojson new file mode 100644 index 0000000000..79fec8dac7 --- /dev/null +++ b/packages/turf-rewind/test/in/polygon-counter-clockwise.geojson @@ -0,0 +1,31 @@ +{ + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 121.9921875, + -29.22889003019423 + ], + [ + 138.515625, + -29.22889003019423 + ], + [ + 138.515625, + -18.312810846425442 + ], + [ + 121.9921875, + -18.312810846425442 + ], + [ + 121.9921875, + -29.22889003019423 + ] + ] + ] + } +} \ No newline at end of file diff --git a/packages/turf-rewind/test/out/geometry-polygon-counter-clockwise.geojson b/packages/turf-rewind/test/out/geometry-polygon-counter-clockwise.geojson new file mode 100644 index 0000000000..749cf998ce --- /dev/null +++ b/packages/turf-rewind/test/out/geometry-polygon-counter-clockwise.geojson @@ -0,0 +1,27 @@ +{ + "type": "Polygon", + "coordinates": [ + [ + [ + 121.9921875, + -29.22889003019423 + ], + [ + 121.9921875, + -18.312810846425442 + ], + [ + 138.515625, + -18.312810846425442 + ], + [ + 138.515625, + -29.22889003019423 + ], + [ + 121.9921875, + -29.22889003019423 + ] + ] + ] +} diff --git a/packages/turf-rewind/test/out/line-clockwise.geojson b/packages/turf-rewind/test/out/line-clockwise.geojson new file mode 100644 index 0000000000..61a7433741 --- /dev/null +++ b/packages/turf-rewind/test/out/line-clockwise.geojson @@ -0,0 +1,49 @@ +{ + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + 122.87109375, + -20.13847031245114 + ], + [ + 126.21093749999999, + -15.792253570362446 + ], + [ + 129.5947265625, + -14.604847155053898 + ], + [ + 134.560546875, + -15.834535741221552 + ], + [ + 138.73535156249997, + -20.014645445341355 + ], + [ + 139.833984375, + -25.799891182088306 + ], + [ + 134.12109375, + -30.183121842195504 + ], + [ + 131.8798828125, + -30.221101852485987 + ], + [ + 128.49609375, + -29.878755346037963 + ], + [ + 124.4091796875, + -27.839076094777802 + ] + ] + } +} diff --git a/packages/turf-rewind/test/out/line-counter-clockwise.geojson b/packages/turf-rewind/test/out/line-counter-clockwise.geojson new file mode 100644 index 0000000000..61a7433741 --- /dev/null +++ b/packages/turf-rewind/test/out/line-counter-clockwise.geojson @@ -0,0 +1,49 @@ +{ + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + 122.87109375, + -20.13847031245114 + ], + [ + 126.21093749999999, + -15.792253570362446 + ], + [ + 129.5947265625, + -14.604847155053898 + ], + [ + 134.560546875, + -15.834535741221552 + ], + [ + 138.73535156249997, + -20.014645445341355 + ], + [ + 139.833984375, + -25.799891182088306 + ], + [ + 134.12109375, + -30.183121842195504 + ], + [ + 131.8798828125, + -30.221101852485987 + ], + [ + 128.49609375, + -29.878755346037963 + ], + [ + 124.4091796875, + -27.839076094777802 + ] + ] + } +} diff --git a/packages/turf-rewind/test/out/polygon-clockwise.geojson b/packages/turf-rewind/test/out/polygon-clockwise.geojson new file mode 100644 index 0000000000..2a1dc4e0bb --- /dev/null +++ b/packages/turf-rewind/test/out/polygon-clockwise.geojson @@ -0,0 +1,31 @@ +{ + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 121, + -29 + ], + [ + 121, + -18 + ], + [ + 138, + -18 + ], + [ + 138, + -29 + ], + [ + 121, + -29 + ] + ] + ] + } +} diff --git a/packages/turf-rewind/test/out/polygon-counter-clockwise.geojson b/packages/turf-rewind/test/out/polygon-counter-clockwise.geojson new file mode 100644 index 0000000000..b823d23879 --- /dev/null +++ b/packages/turf-rewind/test/out/polygon-counter-clockwise.geojson @@ -0,0 +1,31 @@ +{ + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 121.9921875, + -29.22889003019423 + ], + [ + 121.9921875, + -18.312810846425442 + ], + [ + 138.515625, + -18.312810846425442 + ], + [ + 138.515625, + -29.22889003019423 + ], + [ + 121.9921875, + -29.22889003019423 + ] + ] + ] + } +} diff --git a/packages/turf-rewind/test/types.ts b/packages/turf-rewind/test/types.ts new file mode 100644 index 0000000000..bb9d6709f0 --- /dev/null +++ b/packages/turf-rewind/test/types.ts @@ -0,0 +1,15 @@ +import {polygon, lineString, multiLineString, multiPolygon} from '@turf/helpers' +import * as rewind from '../' + +const coords = [[121, -29], [138, -29], [138, -18], [121, -18], [121, -29]] +const poly = polygon([coords]) +const line = lineString(coords) +const multiPoly = multiPolygon([[coords], [coords]]) +const multiLine = multiLineString([coords, coords]) + +rewind(line) +rewind(poly) +rewind(multiPoly) +rewind(multiLine) +rewind(poly, true) +rewind(poly, true, true) From b5bbefb36f86970e227832c8daed1f7eb5d96892 Mon Sep 17 00:00:00 2001 From: Denis Date: Sun, 30 Apr 2017 23:42:55 -0400 Subject: [PATCH 2/5] Update out fixture --- .../test/out/polygon-clockwise.geojson | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/turf-rewind/test/out/polygon-clockwise.geojson b/packages/turf-rewind/test/out/polygon-clockwise.geojson index 2a1dc4e0bb..b823d23879 100644 --- a/packages/turf-rewind/test/out/polygon-clockwise.geojson +++ b/packages/turf-rewind/test/out/polygon-clockwise.geojson @@ -6,24 +6,24 @@ "coordinates": [ [ [ - 121, - -29 + 121.9921875, + -29.22889003019423 ], [ - 121, - -18 + 121.9921875, + -18.312810846425442 ], [ - 138, - -18 + 138.515625, + -18.312810846425442 ], [ - 138, - -29 + 138.515625, + -29.22889003019423 ], [ - 121, - -29 + 121.9921875, + -29.22889003019423 ] ] ] From e668205171786d73674b995fd0395643e212991f Mon Sep 17 00:00:00 2001 From: Denis Date: Sun, 30 Apr 2017 23:46:36 -0400 Subject: [PATCH 3/5] Add Mutli Polygon/LineString to JSDocs --- packages/turf-rewind/README.md | 6 +++--- packages/turf-rewind/index.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/turf-rewind/README.md b/packages/turf-rewind/README.md index d4109f6a8b..03b82fcc28 100644 --- a/packages/turf-rewind/README.md +++ b/packages/turf-rewind/README.md @@ -2,11 +2,11 @@ # rewind -Rewind [LineString](http://geojson.org/geojson-spec.html#linestring) or [Polygon](http://geojson.org/geojson-spec.html#polygon) outer ring clockwise and inner rings counterclockwise (Uses [Shoelace Formula](http://en.wikipedia.org/wiki/Shoelace_formula)). +Rewind [(Mutli)LineString](http://geojson.org/geojson-spec.html#linestring) or [(Multi)Polygon](http://geojson.org/geojson-spec.html#polygon) outer ring clockwise and inner rings counterclockwise (Uses [Shoelace Formula](http://en.wikipedia.org/wiki/Shoelace_formula)). **Parameters** -- `geojson` **[Feature](http://geojson.org/geojson-spec.html#feature-objects)<([Polygon](http://geojson.org/geojson-spec.html#polygon) \| [LineString](http://geojson.org/geojson-spec.html#linestring))>** input GeoJSON Polygon +- `geojson` **[Feature](http://geojson.org/geojson-spec.html#feature-objects)<([Polygon](http://geojson.org/geojson-spec.html#polygon) \| [MultiPolygon](http://geojson.org/geojson-spec.html#multipolygon) \| [LineString](http://geojson.org/geojson-spec.html#linestring) \| [MultiLineString](http://geojson.org/geojson-spec.html#multilinestring))>** input GeoJSON Polygon - `reverse` **\[[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** enable reverse winding (optional, default `false`) - `mutate` **\[[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)]** allows GeoJSON input to be mutated (significant performance increase if true) (optional, default `false`) @@ -29,7 +29,7 @@ var rewind = turf.rewind(polygon); var addToMap = [rewind]; ``` -Returns **[Feature](http://geojson.org/geojson-spec.html#feature-objects)<([Polygon](http://geojson.org/geojson-spec.html#polygon) \| [LineString](http://geojson.org/geojson-spec.html#linestring))>** rewind Polygon +Returns **[Feature](http://geojson.org/geojson-spec.html#feature-objects)<([Polygon](http://geojson.org/geojson-spec.html#polygon) \| [MultiPolygon](http://geojson.org/geojson-spec.html#multipolygon) \| [LineString](http://geojson.org/geojson-spec.html#linestring) \| [MultiLineString](http://geojson.org/geojson-spec.html#multilinestring))>** rewind Polygon # rewindLineString diff --git a/packages/turf-rewind/index.js b/packages/turf-rewind/index.js index d6dcdd57e9..c4b38abcb9 100644 --- a/packages/turf-rewind/index.js +++ b/packages/turf-rewind/index.js @@ -1,13 +1,13 @@ var getCoords = require('@turf/invariant').getCoords; /** - * Rewind {@link LineString} or {@link Polygon} outer ring clockwise and inner rings counterclockwise (Uses {@link http://en.wikipedia.org/wiki/Shoelace_formula|Shoelace Formula}). + * Rewind {@link LineString|(Mutli)LineString} or {@link Polygon|(Multi)Polygon} outer ring clockwise and inner rings counterclockwise (Uses {@link http://en.wikipedia.org/wiki/Shoelace_formula|Shoelace Formula}). * * @name rewind - * @param {Feature} geojson input GeoJSON Polygon + * @param {Feature} geojson input GeoJSON Polygon * @param {Boolean} [reverse=false] enable reverse winding * @param {boolean} [mutate=false] allows GeoJSON input to be mutated (significant performance increase if true) - * @returns {Feature} rewind Polygon + * @returns {Feature} rewind Polygon * @example * var polygon = { * "type": "Feature", From 3eaab8014dd64ba500830f7538d9b1682e3f374e Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 1 May 2017 00:02:00 -0400 Subject: [PATCH 4/5] Add Morgan to contributors --- packages/turf-rewind/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/turf-rewind/package.json b/packages/turf-rewind/package.json index eca50a57af..0fb01ad27f 100644 --- a/packages/turf-rewind/package.json +++ b/packages/turf-rewind/package.json @@ -26,7 +26,8 @@ "contributors": [ "Abel Vázquez Montoro <@AbelVM>", "Tom MacWright <@tmcw>", - "Denis Carriere <@DenisCarriere>" + "Denis Carriere <@DenisCarriere>", + "Morgan Herlocker <@morganherlocker>" ], "license": "MIT", "bugs": { From f981e903390079ed17bd9e73adf51eb17e6948e6 Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 1 May 2017 00:13:39 -0400 Subject: [PATCH 5/5] 3x performance increase using turf-is-clockwise @morganherlocker <3 love it! --- packages/turf-rewind/bench.js | 10 +++++----- packages/turf-rewind/index.js | 20 +------------------- packages/turf-rewind/package.json | 3 ++- 3 files changed, 8 insertions(+), 25 deletions(-) diff --git a/packages/turf-rewind/bench.js b/packages/turf-rewind/bench.js index 1021db23ea..a5182ff65b 100644 --- a/packages/turf-rewind/bench.js +++ b/packages/turf-rewind/bench.js @@ -17,11 +17,11 @@ let fixtures = fs.readdirSync(directory).map(filename => { /** * Benchmark Results * - * geometry-polygon-counter-clockwise x 3,217,454 ops/sec ±4.31% (83 runs sampled) - * line-clockwise x 2,249,133 ops/sec ±0.97% (90 runs sampled) - * line-counter-clockwise x 2,224,334 ops/sec ±1.40% (87 runs sampled) - * polygon-clockwise x 3,429,437 ops/sec ±1.49% (86 runs sampled) - * polygon-counter-clockwise x 3,464,880 ops/sec ±1.05% (88 runs sampled) + * geometry-polygon-counter-clockwise x 10,379,811 ops/sec ±0.84% (89 runs sampled) + * line-clockwise x 7,937,098 ops/sec ±1.13% (90 runs sampled) + * line-counter-clockwise x 6,324,221 ops/sec ±5.40% (74 runs sampled) + * polygon-clockwise x 8,941,337 ops/sec ±2.95% (81 runs sampled) + * polygon-counter-clockwise x 7,625,375 ops/sec ±12.27% (72 runs sampled) */ const suite = new Benchmark.Suite('turf-rewind'); for (const {name, geojson} of fixtures) { diff --git a/packages/turf-rewind/index.js b/packages/turf-rewind/index.js index c4b38abcb9..0a4fa4c629 100644 --- a/packages/turf-rewind/index.js +++ b/packages/turf-rewind/index.js @@ -1,4 +1,5 @@ var getCoords = require('@turf/invariant').getCoords; +var isClockWise = require('turf-is-clockwise'); /** * Rewind {@link LineString|(Mutli)LineString} or {@link Polygon|(Multi)Polygon} outer ring clockwise and inner rings counterclockwise (Uses {@link http://en.wikipedia.org/wiki/Shoelace_formula|Shoelace Formula}). @@ -93,25 +94,6 @@ function rewindPolygon(coords, reverse) { } } -/** - * is Clockwise - * - * @private - * @param {Array>} coords LineString geometry coordinates - * @returns {boolean} is LineString clockwise or not - */ -function isClockWise(coords) { - var initialValue = 0; - var reduced = coords.reduce(function (previous, current, index) { - var a = previous; - var b = current; - var c = index; - var d = coords; - return a + ((c < d.length - 1) ? (d[c + 1][0] - b[0]) * (d[c + 1][1] + b[1]) : 0); - }, initialValue); - return reduced > 0; -} - function getGeomType(feature) { return (feature.geometry) ? feature.geometry.type : feature.type; } diff --git a/packages/turf-rewind/package.json b/packages/turf-rewind/package.json index 0fb01ad27f..bfeb5bbadf 100644 --- a/packages/turf-rewind/package.json +++ b/packages/turf-rewind/package.json @@ -42,6 +42,7 @@ "write-json-file": "^2.0.0" }, "dependencies": { - "@turf/invariant": "^4.2.0" + "@turf/invariant": "^4.2.0", + "turf-is-clockwise": "^1.0.0" } }