index.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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 geojson_rbush_1 = __importDefault(require("geojson-rbush"));
  7. var line_segment_1 = __importDefault(require("@turf/line-segment"));
  8. var nearest_point_on_line_1 = __importDefault(require("@turf/nearest-point-on-line"));
  9. var boolean_point_on_line_1 = __importDefault(require("@turf/boolean-point-on-line"));
  10. var invariant_1 = require("@turf/invariant");
  11. var meta_1 = require("@turf/meta");
  12. var helpers_1 = require("@turf/helpers");
  13. var deep_equal_1 = __importDefault(require("deep-equal"));
  14. /**
  15. * Takes any LineString or Polygon and returns the overlapping lines between both features.
  16. *
  17. * @name lineOverlap
  18. * @param {Geometry|Feature<LineString|MultiLineString|Polygon|MultiPolygon>} line1 any LineString or Polygon
  19. * @param {Geometry|Feature<LineString|MultiLineString|Polygon|MultiPolygon>} line2 any LineString or Polygon
  20. * @param {Object} [options={}] Optional parameters
  21. * @param {number} [options.tolerance=0] Tolerance distance to match overlapping line segments (in kilometers)
  22. * @returns {FeatureCollection<LineString>} lines(s) that are overlapping between both features
  23. * @example
  24. * var line1 = turf.lineString([[115, -35], [125, -30], [135, -30], [145, -35]]);
  25. * var line2 = turf.lineString([[115, -25], [125, -30], [135, -30], [145, -25]]);
  26. *
  27. * var overlapping = turf.lineOverlap(line1, line2);
  28. *
  29. * //addToMap
  30. * var addToMap = [line1, line2, overlapping]
  31. */
  32. function lineOverlap(line1, line2, options) {
  33. if (options === void 0) { options = {}; }
  34. // Optional parameters
  35. options = options || {};
  36. if (!helpers_1.isObject(options))
  37. throw new Error("options is invalid");
  38. var tolerance = options.tolerance || 0;
  39. // Containers
  40. var features = [];
  41. // Create Spatial Index
  42. var tree = geojson_rbush_1.default();
  43. // To-Do -- HACK way to support typescript
  44. var line = line_segment_1.default(line1);
  45. tree.load(line);
  46. var overlapSegment;
  47. // Line Intersection
  48. // Iterate over line segments
  49. meta_1.segmentEach(line2, function (segment) {
  50. var doesOverlaps = false;
  51. if (!segment) {
  52. return;
  53. }
  54. // Iterate over each segments which falls within the same bounds
  55. meta_1.featureEach(tree.search(segment), function (match) {
  56. if (doesOverlaps === false) {
  57. var coordsSegment = invariant_1.getCoords(segment).sort();
  58. var coordsMatch = invariant_1.getCoords(match).sort();
  59. // Segment overlaps feature
  60. if (deep_equal_1.default(coordsSegment, coordsMatch)) {
  61. doesOverlaps = true;
  62. // Overlaps already exists - only append last coordinate of segment
  63. if (overlapSegment)
  64. overlapSegment = concatSegment(overlapSegment, segment);
  65. else
  66. overlapSegment = segment;
  67. // Match segments which don't share nodes (Issue #901)
  68. }
  69. else if (tolerance === 0
  70. ? boolean_point_on_line_1.default(coordsSegment[0], match) &&
  71. boolean_point_on_line_1.default(coordsSegment[1], match)
  72. : nearest_point_on_line_1.default(match, coordsSegment[0]).properties.dist <=
  73. tolerance &&
  74. nearest_point_on_line_1.default(match, coordsSegment[1]).properties.dist <=
  75. tolerance) {
  76. doesOverlaps = true;
  77. if (overlapSegment)
  78. overlapSegment = concatSegment(overlapSegment, segment);
  79. else
  80. overlapSegment = segment;
  81. }
  82. else if (tolerance === 0
  83. ? boolean_point_on_line_1.default(coordsMatch[0], segment) &&
  84. boolean_point_on_line_1.default(coordsMatch[1], segment)
  85. : nearest_point_on_line_1.default(segment, coordsMatch[0]).properties.dist <=
  86. tolerance &&
  87. nearest_point_on_line_1.default(segment, coordsMatch[1]).properties.dist <=
  88. tolerance) {
  89. // Do not define (doesOverlap = true) since more matches can occur within the same segment
  90. // doesOverlaps = true;
  91. if (overlapSegment)
  92. overlapSegment = concatSegment(overlapSegment, match);
  93. else
  94. overlapSegment = match;
  95. }
  96. }
  97. });
  98. // Segment doesn't overlap - add overlaps to results & reset
  99. if (doesOverlaps === false && overlapSegment) {
  100. features.push(overlapSegment);
  101. overlapSegment = undefined;
  102. }
  103. });
  104. // Add last segment if exists
  105. if (overlapSegment)
  106. features.push(overlapSegment);
  107. return helpers_1.featureCollection(features);
  108. }
  109. /**
  110. * Concat Segment
  111. *
  112. * @private
  113. * @param {Feature<LineString>} line LineString
  114. * @param {Feature<LineString>} segment 2-vertex LineString
  115. * @returns {Feature<LineString>} concat linestring
  116. */
  117. function concatSegment(line, segment) {
  118. var coords = invariant_1.getCoords(segment);
  119. var lineCoords = invariant_1.getCoords(line);
  120. var start = lineCoords[0];
  121. var end = lineCoords[lineCoords.length - 1];
  122. var geom = line.geometry.coordinates;
  123. if (deep_equal_1.default(coords[0], start))
  124. geom.unshift(coords[1]);
  125. else if (deep_equal_1.default(coords[0], end))
  126. geom.push(coords[1]);
  127. else if (deep_equal_1.default(coords[1], start))
  128. geom.unshift(coords[0]);
  129. else if (deep_equal_1.default(coords[1], end))
  130. geom.push(coords[0]);
  131. return line;
  132. }
  133. exports.default = lineOverlap;