index.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. 'use strict';
  2. var clone = require('@turf/clone');
  3. var booleanClockwise = require('@turf/boolean-clockwise');
  4. var meta = require('@turf/meta');
  5. var invariant = require('@turf/invariant');
  6. var helpers = require('@turf/helpers');
  7. function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
  8. var clone__default = /*#__PURE__*/_interopDefaultLegacy(clone);
  9. var booleanClockwise__default = /*#__PURE__*/_interopDefaultLegacy(booleanClockwise);
  10. /**
  11. * Rewind {@link LineString|(Multi)LineString} or {@link Polygon|(Multi)Polygon} outer ring counterclockwise and inner rings clockwise (Uses {@link http://en.wikipedia.org/wiki/Shoelace_formula|Shoelace Formula}).
  12. *
  13. * @name rewind
  14. * @param {GeoJSON} geojson input GeoJSON Polygon
  15. * @param {Object} [options={}] Optional parameters
  16. * @param {boolean} [options.reverse=false] enable reverse winding
  17. * @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated (significant performance increase if true)
  18. * @returns {GeoJSON} rewind Polygon
  19. * @example
  20. * var polygon = turf.polygon([[[121, -29], [138, -29], [138, -18], [121, -18], [121, -29]]]);
  21. *
  22. * var rewind = turf.rewind(polygon);
  23. *
  24. * //addToMap
  25. * var addToMap = [rewind];
  26. */
  27. function rewind(geojson, options) {
  28. // Optional parameters
  29. options = options || {};
  30. if (!helpers.isObject(options)) throw new Error("options is invalid");
  31. var reverse = options.reverse || false;
  32. var mutate = options.mutate || false;
  33. // validation
  34. if (!geojson) throw new Error("<geojson> is required");
  35. if (typeof reverse !== "boolean")
  36. throw new Error("<reverse> must be a boolean");
  37. if (typeof mutate !== "boolean")
  38. throw new Error("<mutate> must be a boolean");
  39. // prevent input mutation
  40. if (mutate === false) geojson = clone__default['default'](geojson);
  41. // Support Feature Collection or Geometry Collection
  42. var results = [];
  43. switch (geojson.type) {
  44. case "GeometryCollection":
  45. meta.geomEach(geojson, function (geometry) {
  46. rewindFeature(geometry, reverse);
  47. });
  48. return geojson;
  49. case "FeatureCollection":
  50. meta.featureEach(geojson, function (feature) {
  51. meta.featureEach(rewindFeature(feature, reverse), function (result) {
  52. results.push(result);
  53. });
  54. });
  55. return helpers.featureCollection(results);
  56. }
  57. // Support Feature or Geometry Objects
  58. return rewindFeature(geojson, reverse);
  59. }
  60. /**
  61. * Rewind
  62. *
  63. * @private
  64. * @param {Geometry|Feature<any>} geojson Geometry or Feature
  65. * @param {Boolean} [reverse=false] enable reverse winding
  66. * @returns {Geometry|Feature<any>} rewind Geometry or Feature
  67. */
  68. function rewindFeature(geojson, reverse) {
  69. var type = geojson.type === "Feature" ? geojson.geometry.type : geojson.type;
  70. // Support all GeoJSON Geometry Objects
  71. switch (type) {
  72. case "GeometryCollection":
  73. meta.geomEach(geojson, function (geometry) {
  74. rewindFeature(geometry, reverse);
  75. });
  76. return geojson;
  77. case "LineString":
  78. rewindLineString(invariant.getCoords(geojson), reverse);
  79. return geojson;
  80. case "Polygon":
  81. rewindPolygon(invariant.getCoords(geojson), reverse);
  82. return geojson;
  83. case "MultiLineString":
  84. invariant.getCoords(geojson).forEach(function (lineCoords) {
  85. rewindLineString(lineCoords, reverse);
  86. });
  87. return geojson;
  88. case "MultiPolygon":
  89. invariant.getCoords(geojson).forEach(function (lineCoords) {
  90. rewindPolygon(lineCoords, reverse);
  91. });
  92. return geojson;
  93. case "Point":
  94. case "MultiPoint":
  95. return geojson;
  96. }
  97. }
  98. /**
  99. * Rewind LineString - outer ring clockwise
  100. *
  101. * @private
  102. * @param {Array<Array<number>>} coords GeoJSON LineString geometry coordinates
  103. * @param {Boolean} [reverse=false] enable reverse winding
  104. * @returns {void} mutates coordinates
  105. */
  106. function rewindLineString(coords, reverse) {
  107. if (booleanClockwise__default['default'](coords) === reverse) coords.reverse();
  108. }
  109. /**
  110. * Rewind Polygon - outer ring counterclockwise and inner rings clockwise.
  111. *
  112. * @private
  113. * @param {Array<Array<Array<number>>>} coords GeoJSON Polygon geometry coordinates
  114. * @param {Boolean} [reverse=false] enable reverse winding
  115. * @returns {void} mutates coordinates
  116. */
  117. function rewindPolygon(coords, reverse) {
  118. // outer ring
  119. if (booleanClockwise__default['default'](coords[0]) !== reverse) {
  120. coords[0].reverse();
  121. }
  122. // inner rings
  123. for (var i = 1; i < coords.length; i++) {
  124. if (booleanClockwise__default['default'](coords[i]) === reverse) {
  125. coords[i].reverse();
  126. }
  127. }
  128. }
  129. module.exports = rewind;
  130. module.exports.default = rewind;