123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- import rbush from "geojson-rbush";
- import lineSegment from "@turf/line-segment";
- import nearestPointOnLine from "@turf/nearest-point-on-line";
- import booleanPointOnLine from "@turf/boolean-point-on-line";
- import { getCoords } from "@turf/invariant";
- import { featureEach, segmentEach } from "@turf/meta";
- import { featureCollection, isObject, } from "@turf/helpers";
- import equal from "deep-equal";
- /**
- * Takes any LineString or Polygon and returns the overlapping lines between both features.
- *
- * @name lineOverlap
- * @param {Geometry|Feature<LineString|MultiLineString|Polygon|MultiPolygon>} line1 any LineString or Polygon
- * @param {Geometry|Feature<LineString|MultiLineString|Polygon|MultiPolygon>} line2 any LineString or Polygon
- * @param {Object} [options={}] Optional parameters
- * @param {number} [options.tolerance=0] Tolerance distance to match overlapping line segments (in kilometers)
- * @returns {FeatureCollection<LineString>} lines(s) that are overlapping between both features
- * @example
- * var line1 = turf.lineString([[115, -35], [125, -30], [135, -30], [145, -35]]);
- * var line2 = turf.lineString([[115, -25], [125, -30], [135, -30], [145, -25]]);
- *
- * var overlapping = turf.lineOverlap(line1, line2);
- *
- * //addToMap
- * var addToMap = [line1, line2, overlapping]
- */
- function lineOverlap(line1, line2, options) {
- if (options === void 0) { options = {}; }
- // Optional parameters
- options = options || {};
- if (!isObject(options))
- throw new Error("options is invalid");
- var tolerance = options.tolerance || 0;
- // Containers
- var features = [];
- // Create Spatial Index
- var tree = rbush();
- // To-Do -- HACK way to support typescript
- var line = lineSegment(line1);
- tree.load(line);
- var overlapSegment;
- // Line Intersection
- // Iterate over line segments
- segmentEach(line2, function (segment) {
- var doesOverlaps = false;
- if (!segment) {
- return;
- }
- // Iterate over each segments which falls within the same bounds
- featureEach(tree.search(segment), function (match) {
- if (doesOverlaps === false) {
- var coordsSegment = getCoords(segment).sort();
- var coordsMatch = getCoords(match).sort();
- // Segment overlaps feature
- if (equal(coordsSegment, coordsMatch)) {
- doesOverlaps = true;
- // Overlaps already exists - only append last coordinate of segment
- if (overlapSegment)
- overlapSegment = concatSegment(overlapSegment, segment);
- else
- overlapSegment = segment;
- // Match segments which don't share nodes (Issue #901)
- }
- else if (tolerance === 0
- ? booleanPointOnLine(coordsSegment[0], match) &&
- booleanPointOnLine(coordsSegment[1], match)
- : nearestPointOnLine(match, coordsSegment[0]).properties.dist <=
- tolerance &&
- nearestPointOnLine(match, coordsSegment[1]).properties.dist <=
- tolerance) {
- doesOverlaps = true;
- if (overlapSegment)
- overlapSegment = concatSegment(overlapSegment, segment);
- else
- overlapSegment = segment;
- }
- else if (tolerance === 0
- ? booleanPointOnLine(coordsMatch[0], segment) &&
- booleanPointOnLine(coordsMatch[1], segment)
- : nearestPointOnLine(segment, coordsMatch[0]).properties.dist <=
- tolerance &&
- nearestPointOnLine(segment, coordsMatch[1]).properties.dist <=
- tolerance) {
- // Do not define (doesOverlap = true) since more matches can occur within the same segment
- // doesOverlaps = true;
- if (overlapSegment)
- overlapSegment = concatSegment(overlapSegment, match);
- else
- overlapSegment = match;
- }
- }
- });
- // Segment doesn't overlap - add overlaps to results & reset
- if (doesOverlaps === false && overlapSegment) {
- features.push(overlapSegment);
- overlapSegment = undefined;
- }
- });
- // Add last segment if exists
- if (overlapSegment)
- features.push(overlapSegment);
- return featureCollection(features);
- }
- /**
- * Concat Segment
- *
- * @private
- * @param {Feature<LineString>} line LineString
- * @param {Feature<LineString>} segment 2-vertex LineString
- * @returns {Feature<LineString>} concat linestring
- */
- function concatSegment(line, segment) {
- var coords = getCoords(segment);
- var lineCoords = getCoords(line);
- var start = lineCoords[0];
- var end = lineCoords[lineCoords.length - 1];
- var geom = line.geometry.coordinates;
- if (equal(coords[0], start))
- geom.unshift(coords[1]);
- else if (equal(coords[0], end))
- geom.push(coords[1]);
- else if (equal(coords[1], start))
- geom.unshift(coords[0]);
- else if (equal(coords[1], end))
- geom.push(coords[0]);
- return line;
- }
- export default lineOverlap;
|