index.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. 'use strict';
  2. var explode = require('@turf/explode');
  3. var centroid = require('@turf/center');
  4. var nearestPoint = require('@turf/nearest-point');
  5. var booleanPointInPolygon = require('@turf/boolean-point-in-polygon');
  6. var helpers = require('@turf/helpers');
  7. function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
  8. var explode__default = /*#__PURE__*/_interopDefaultLegacy(explode);
  9. var centroid__default = /*#__PURE__*/_interopDefaultLegacy(centroid);
  10. var nearestPoint__default = /*#__PURE__*/_interopDefaultLegacy(nearestPoint);
  11. var booleanPointInPolygon__default = /*#__PURE__*/_interopDefaultLegacy(booleanPointInPolygon);
  12. /**
  13. * Takes a Feature or FeatureCollection and returns a {@link Point} guaranteed to be on the surface of the feature.
  14. *
  15. * * Given a {@link Polygon}, the point will be in the area of the polygon
  16. * * Given a {@link LineString}, the point will be along the string
  17. * * Given a {@link Point}, the point will the same as the input
  18. *
  19. * @name pointOnFeature
  20. * @param {GeoJSON} geojson any Feature or FeatureCollection
  21. * @returns {Feature<Point>} a point on the surface of `input`
  22. * @example
  23. * var polygon = turf.polygon([[
  24. * [116, -36],
  25. * [131, -32],
  26. * [146, -43],
  27. * [155, -25],
  28. * [133, -9],
  29. * [111, -22],
  30. * [116, -36]
  31. * ]]);
  32. *
  33. * var pointOnPolygon = turf.pointOnFeature(polygon);
  34. *
  35. * //addToMap
  36. * var addToMap = [polygon, pointOnPolygon];
  37. */
  38. function pointOnFeature(geojson) {
  39. // normalize
  40. var fc = normalize(geojson);
  41. // get centroid
  42. var cent = centroid__default['default'](fc);
  43. // check to see if centroid is on surface
  44. var onSurface = false;
  45. var i = 0;
  46. while (!onSurface && i < fc.features.length) {
  47. var geom = fc.features[i].geometry;
  48. var x, y, x1, y1, x2, y2, k;
  49. var onLine = false;
  50. if (geom.type === "Point") {
  51. if (
  52. cent.geometry.coordinates[0] === geom.coordinates[0] &&
  53. cent.geometry.coordinates[1] === geom.coordinates[1]
  54. ) {
  55. onSurface = true;
  56. }
  57. } else if (geom.type === "MultiPoint") {
  58. var onMultiPoint = false;
  59. k = 0;
  60. while (!onMultiPoint && k < geom.coordinates.length) {
  61. if (
  62. cent.geometry.coordinates[0] === geom.coordinates[k][0] &&
  63. cent.geometry.coordinates[1] === geom.coordinates[k][1]
  64. ) {
  65. onSurface = true;
  66. onMultiPoint = true;
  67. }
  68. k++;
  69. }
  70. } else if (geom.type === "LineString") {
  71. k = 0;
  72. while (!onLine && k < geom.coordinates.length - 1) {
  73. x = cent.geometry.coordinates[0];
  74. y = cent.geometry.coordinates[1];
  75. x1 = geom.coordinates[k][0];
  76. y1 = geom.coordinates[k][1];
  77. x2 = geom.coordinates[k + 1][0];
  78. y2 = geom.coordinates[k + 1][1];
  79. if (pointOnSegment(x, y, x1, y1, x2, y2)) {
  80. onLine = true;
  81. onSurface = true;
  82. }
  83. k++;
  84. }
  85. } else if (geom.type === "MultiLineString") {
  86. var j = 0;
  87. while (j < geom.coordinates.length) {
  88. onLine = false;
  89. k = 0;
  90. var line = geom.coordinates[j];
  91. while (!onLine && k < line.length - 1) {
  92. x = cent.geometry.coordinates[0];
  93. y = cent.geometry.coordinates[1];
  94. x1 = line[k][0];
  95. y1 = line[k][1];
  96. x2 = line[k + 1][0];
  97. y2 = line[k + 1][1];
  98. if (pointOnSegment(x, y, x1, y1, x2, y2)) {
  99. onLine = true;
  100. onSurface = true;
  101. }
  102. k++;
  103. }
  104. j++;
  105. }
  106. } else if (geom.type === "Polygon" || geom.type === "MultiPolygon") {
  107. if (booleanPointInPolygon__default['default'](cent, geom)) {
  108. onSurface = true;
  109. }
  110. }
  111. i++;
  112. }
  113. if (onSurface) {
  114. return cent;
  115. } else {
  116. var vertices = helpers.featureCollection([]);
  117. for (i = 0; i < fc.features.length; i++) {
  118. vertices.features = vertices.features.concat(
  119. explode__default['default'](fc.features[i]).features
  120. );
  121. }
  122. // Remove distanceToPoint properties from nearestPoint()
  123. return helpers.point(nearestPoint__default['default'](cent, vertices).geometry.coordinates);
  124. }
  125. }
  126. /**
  127. * Normalizes any GeoJSON to a FeatureCollection
  128. *
  129. * @private
  130. * @name normalize
  131. * @param {GeoJSON} geojson Any GeoJSON
  132. * @returns {FeatureCollection} FeatureCollection
  133. */
  134. function normalize(geojson) {
  135. if (geojson.type !== "FeatureCollection") {
  136. if (geojson.type !== "Feature") {
  137. return helpers.featureCollection([helpers.feature(geojson)]);
  138. }
  139. return helpers.featureCollection([geojson]);
  140. }
  141. return geojson;
  142. }
  143. function pointOnSegment(x, y, x1, y1, x2, y2) {
  144. var ab = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
  145. var ap = Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
  146. var pb = Math.sqrt((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y));
  147. return ab === ap + pb;
  148. }
  149. module.exports = pointOnFeature;
  150. module.exports.default = pointOnFeature;