index.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. /**
  4. * Returns a cloned copy of the passed GeoJSON Object, including possible 'Foreign Members'.
  5. * ~3-5x faster than the common JSON.parse + JSON.stringify combo method.
  6. *
  7. * @name clone
  8. * @param {GeoJSON} geojson GeoJSON Object
  9. * @returns {GeoJSON} cloned GeoJSON Object
  10. * @example
  11. * var line = turf.lineString([[-74, 40], [-78, 42], [-82, 35]], {color: 'red'});
  12. *
  13. * var lineCloned = turf.clone(line);
  14. */
  15. function clone(geojson) {
  16. if (!geojson) {
  17. throw new Error("geojson is required");
  18. }
  19. switch (geojson.type) {
  20. case "Feature":
  21. return cloneFeature(geojson);
  22. case "FeatureCollection":
  23. return cloneFeatureCollection(geojson);
  24. case "Point":
  25. case "LineString":
  26. case "Polygon":
  27. case "MultiPoint":
  28. case "MultiLineString":
  29. case "MultiPolygon":
  30. case "GeometryCollection":
  31. return cloneGeometry(geojson);
  32. default:
  33. throw new Error("unknown GeoJSON type");
  34. }
  35. }
  36. /**
  37. * Clone Feature
  38. *
  39. * @private
  40. * @param {Feature<any>} geojson GeoJSON Feature
  41. * @returns {Feature<any>} cloned Feature
  42. */
  43. function cloneFeature(geojson) {
  44. var cloned = { type: "Feature" };
  45. // Preserve Foreign Members
  46. Object.keys(geojson).forEach(function (key) {
  47. switch (key) {
  48. case "type":
  49. case "properties":
  50. case "geometry":
  51. return;
  52. default:
  53. cloned[key] = geojson[key];
  54. }
  55. });
  56. // Add properties & geometry last
  57. cloned.properties = cloneProperties(geojson.properties);
  58. cloned.geometry = cloneGeometry(geojson.geometry);
  59. return cloned;
  60. }
  61. /**
  62. * Clone Properties
  63. *
  64. * @private
  65. * @param {Object} properties GeoJSON Properties
  66. * @returns {Object} cloned Properties
  67. */
  68. function cloneProperties(properties) {
  69. var cloned = {};
  70. if (!properties) {
  71. return cloned;
  72. }
  73. Object.keys(properties).forEach(function (key) {
  74. var value = properties[key];
  75. if (typeof value === "object") {
  76. if (value === null) {
  77. // handle null
  78. cloned[key] = null;
  79. }
  80. else if (Array.isArray(value)) {
  81. // handle Array
  82. cloned[key] = value.map(function (item) {
  83. return item;
  84. });
  85. }
  86. else {
  87. // handle generic Object
  88. cloned[key] = cloneProperties(value);
  89. }
  90. }
  91. else {
  92. cloned[key] = value;
  93. }
  94. });
  95. return cloned;
  96. }
  97. /**
  98. * Clone Feature Collection
  99. *
  100. * @private
  101. * @param {FeatureCollection<any>} geojson GeoJSON Feature Collection
  102. * @returns {FeatureCollection<any>} cloned Feature Collection
  103. */
  104. function cloneFeatureCollection(geojson) {
  105. var cloned = { type: "FeatureCollection" };
  106. // Preserve Foreign Members
  107. Object.keys(geojson).forEach(function (key) {
  108. switch (key) {
  109. case "type":
  110. case "features":
  111. return;
  112. default:
  113. cloned[key] = geojson[key];
  114. }
  115. });
  116. // Add features
  117. cloned.features = geojson.features.map(function (feature) {
  118. return cloneFeature(feature);
  119. });
  120. return cloned;
  121. }
  122. /**
  123. * Clone Geometry
  124. *
  125. * @private
  126. * @param {Geometry<any>} geometry GeoJSON Geometry
  127. * @returns {Geometry<any>} cloned Geometry
  128. */
  129. function cloneGeometry(geometry) {
  130. var geom = { type: geometry.type };
  131. if (geometry.bbox) {
  132. geom.bbox = geometry.bbox;
  133. }
  134. if (geometry.type === "GeometryCollection") {
  135. geom.geometries = geometry.geometries.map(function (g) {
  136. return cloneGeometry(g);
  137. });
  138. return geom;
  139. }
  140. geom.coordinates = deepSlice(geometry.coordinates);
  141. return geom;
  142. }
  143. /**
  144. * Deep Slice coordinates
  145. *
  146. * @private
  147. * @param {Coordinates} coords Coordinates
  148. * @returns {Coordinates} all coordinates sliced
  149. */
  150. function deepSlice(coords) {
  151. var cloned = coords;
  152. if (typeof cloned[0] !== "object") {
  153. return cloned.slice();
  154. }
  155. return cloned.map(function (coord) {
  156. return deepSlice(coord);
  157. });
  158. }
  159. exports.default = clone;