index.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. var line_intersect_1 = __importDefault(require("@turf/line-intersect"));
  7. var polygon_to_line_1 = require("@turf/polygon-to-line");
  8. var boolean_point_in_polygon_1 = __importDefault(require("@turf/boolean-point-in-polygon"));
  9. var invariant_1 = require("@turf/invariant");
  10. var helpers_1 = require("@turf/helpers");
  11. /**
  12. * Boolean-Crosses returns True if the intersection results in a geometry whose dimension is one less than
  13. * the maximum dimension of the two source geometries and the intersection set is interior to
  14. * both source geometries.
  15. *
  16. * Boolean-Crosses returns t (TRUE) for only multipoint/polygon, multipoint/linestring, linestring/linestring, linestring/polygon, and linestring/multipolygon comparisons.
  17. *
  18. * @name booleanCrosses
  19. * @param {Geometry|Feature<any>} feature1 GeoJSON Feature or Geometry
  20. * @param {Geometry|Feature<any>} feature2 GeoJSON Feature or Geometry
  21. * @returns {boolean} true/false
  22. * @example
  23. * var line1 = turf.lineString([[-2, 2], [4, 2]]);
  24. * var line2 = turf.lineString([[1, 1], [1, 2], [1, 3], [1, 4]]);
  25. *
  26. * var cross = turf.booleanCrosses(line1, line2);
  27. * //=true
  28. */
  29. function booleanCrosses(feature1, feature2) {
  30. var geom1 = invariant_1.getGeom(feature1);
  31. var geom2 = invariant_1.getGeom(feature2);
  32. var type1 = geom1.type;
  33. var type2 = geom2.type;
  34. switch (type1) {
  35. case "MultiPoint":
  36. switch (type2) {
  37. case "LineString":
  38. return doMultiPointAndLineStringCross(geom1, geom2);
  39. case "Polygon":
  40. return doesMultiPointCrossPoly(geom1, geom2);
  41. default:
  42. throw new Error("feature2 " + type2 + " geometry not supported");
  43. }
  44. case "LineString":
  45. switch (type2) {
  46. case "MultiPoint": // An inverse operation
  47. return doMultiPointAndLineStringCross(geom2, geom1);
  48. case "LineString":
  49. return doLineStringsCross(geom1, geom2);
  50. case "Polygon":
  51. return doLineStringAndPolygonCross(geom1, geom2);
  52. default:
  53. throw new Error("feature2 " + type2 + " geometry not supported");
  54. }
  55. case "Polygon":
  56. switch (type2) {
  57. case "MultiPoint": // An inverse operation
  58. return doesMultiPointCrossPoly(geom2, geom1);
  59. case "LineString": // An inverse operation
  60. return doLineStringAndPolygonCross(geom2, geom1);
  61. default:
  62. throw new Error("feature2 " + type2 + " geometry not supported");
  63. }
  64. default:
  65. throw new Error("feature1 " + type1 + " geometry not supported");
  66. }
  67. }
  68. function doMultiPointAndLineStringCross(multiPoint, lineString) {
  69. var foundIntPoint = false;
  70. var foundExtPoint = false;
  71. var pointLength = multiPoint.coordinates.length;
  72. var i = 0;
  73. while (i < pointLength && !foundIntPoint && !foundExtPoint) {
  74. for (var i2 = 0; i2 < lineString.coordinates.length - 1; i2++) {
  75. var incEndVertices = true;
  76. if (i2 === 0 || i2 === lineString.coordinates.length - 2) {
  77. incEndVertices = false;
  78. }
  79. if (isPointOnLineSegment(lineString.coordinates[i2], lineString.coordinates[i2 + 1], multiPoint.coordinates[i], incEndVertices)) {
  80. foundIntPoint = true;
  81. }
  82. else {
  83. foundExtPoint = true;
  84. }
  85. }
  86. i++;
  87. }
  88. return foundIntPoint && foundExtPoint;
  89. }
  90. function doLineStringsCross(lineString1, lineString2) {
  91. var doLinesIntersect = line_intersect_1.default(lineString1, lineString2);
  92. if (doLinesIntersect.features.length > 0) {
  93. for (var i = 0; i < lineString1.coordinates.length - 1; i++) {
  94. for (var i2 = 0; i2 < lineString2.coordinates.length - 1; i2++) {
  95. var incEndVertices = true;
  96. if (i2 === 0 || i2 === lineString2.coordinates.length - 2) {
  97. incEndVertices = false;
  98. }
  99. if (isPointOnLineSegment(lineString1.coordinates[i], lineString1.coordinates[i + 1], lineString2.coordinates[i2], incEndVertices)) {
  100. return true;
  101. }
  102. }
  103. }
  104. }
  105. return false;
  106. }
  107. function doLineStringAndPolygonCross(lineString, polygon) {
  108. var line = polygon_to_line_1.polygonToLine(polygon);
  109. var doLinesIntersect = line_intersect_1.default(lineString, line);
  110. if (doLinesIntersect.features.length > 0) {
  111. return true;
  112. }
  113. return false;
  114. }
  115. function doesMultiPointCrossPoly(multiPoint, polygon) {
  116. var foundIntPoint = false;
  117. var foundExtPoint = false;
  118. var pointLength = multiPoint.coordinates.length;
  119. for (var i = 0; i < pointLength && (!foundIntPoint || !foundExtPoint); i++) {
  120. if (boolean_point_in_polygon_1.default(helpers_1.point(multiPoint.coordinates[i]), polygon)) {
  121. foundIntPoint = true;
  122. }
  123. else {
  124. foundExtPoint = true;
  125. }
  126. }
  127. return foundExtPoint && foundIntPoint;
  128. }
  129. /**
  130. * Is a point on a line segment
  131. * Only takes into account outer rings
  132. * See http://stackoverflow.com/a/4833823/1979085
  133. *
  134. * @private
  135. * @param {number[]} lineSegmentStart coord pair of start of line
  136. * @param {number[]} lineSegmentEnd coord pair of end of line
  137. * @param {number[]} pt coord pair of point to check
  138. * @param {boolean} incEnd whether the point is allowed to fall on the line ends
  139. * @returns {boolean} true/false
  140. */
  141. function isPointOnLineSegment(lineSegmentStart, lineSegmentEnd, pt, incEnd) {
  142. var dxc = pt[0] - lineSegmentStart[0];
  143. var dyc = pt[1] - lineSegmentStart[1];
  144. var dxl = lineSegmentEnd[0] - lineSegmentStart[0];
  145. var dyl = lineSegmentEnd[1] - lineSegmentStart[1];
  146. var cross = dxc * dyl - dyc * dxl;
  147. if (cross !== 0) {
  148. return false;
  149. }
  150. if (incEnd) {
  151. if (Math.abs(dxl) >= Math.abs(dyl)) {
  152. return dxl > 0
  153. ? lineSegmentStart[0] <= pt[0] && pt[0] <= lineSegmentEnd[0]
  154. : lineSegmentEnd[0] <= pt[0] && pt[0] <= lineSegmentStart[0];
  155. }
  156. return dyl > 0
  157. ? lineSegmentStart[1] <= pt[1] && pt[1] <= lineSegmentEnd[1]
  158. : lineSegmentEnd[1] <= pt[1] && pt[1] <= lineSegmentStart[1];
  159. }
  160. else {
  161. if (Math.abs(dxl) >= Math.abs(dyl)) {
  162. return dxl > 0
  163. ? lineSegmentStart[0] < pt[0] && pt[0] < lineSegmentEnd[0]
  164. : lineSegmentEnd[0] < pt[0] && pt[0] < lineSegmentStart[0];
  165. }
  166. return dyl > 0
  167. ? lineSegmentStart[1] < pt[1] && pt[1] < lineSegmentEnd[1]
  168. : lineSegmentEnd[1] < pt[1] && pt[1] < lineSegmentStart[1];
  169. }
  170. }
  171. exports.default = booleanCrosses;