88 lines
3.0 KiB
JavaScript
Executable File
88 lines
3.0 KiB
JavaScript
Executable File
import bearing from '@turf/bearing';
|
|
import distance from '@turf/distance';
|
|
import destination from '@turf/destination';
|
|
import { isObject, lineString } from '@turf/helpers';
|
|
|
|
/**
|
|
* Takes a {@link LineString|line}, a specified distance along the line to a start {@link Point},
|
|
* and a specified distance along the line to a stop point
|
|
* and returns a subsection of the line in-between those points.
|
|
*
|
|
* This can be useful for extracting only the part of a route between two distances.
|
|
*
|
|
* @name lineSliceAlong
|
|
* @param {Feature<LineString>|LineString} line input line
|
|
* @param {number} startDist distance along the line to starting point
|
|
* @param {number} stopDist distance along the line to ending point
|
|
* @param {Object} [options={}] Optional parameters
|
|
* @param {string} [options.units='kilometers'] can be degrees, radians, miles, or kilometers
|
|
* @returns {Feature<LineString>} sliced line
|
|
* @example
|
|
* var line = turf.lineString([[7, 45], [9, 45], [14, 40], [14, 41]]);
|
|
* var start = 12.5;
|
|
* var stop = 25;
|
|
* var sliced = turf.lineSliceAlong(line, start, stop, {units: 'miles'});
|
|
*
|
|
* //addToMap
|
|
* var addToMap = [line, start, stop, sliced]
|
|
*/
|
|
function lineSliceAlong(line, startDist, stopDist, options) {
|
|
// Optional parameters
|
|
options = options || {};
|
|
if (!isObject(options)) throw new Error("options is invalid");
|
|
|
|
var coords;
|
|
var slice = [];
|
|
|
|
// Validation
|
|
if (line.type === "Feature") coords = line.geometry.coordinates;
|
|
else if (line.type === "LineString") coords = line.coordinates;
|
|
else throw new Error("input must be a LineString Feature or Geometry");
|
|
var origCoordsLength = coords.length;
|
|
var travelled = 0;
|
|
var overshot, direction, interpolated;
|
|
for (var i = 0; i < coords.length; i++) {
|
|
if (startDist >= travelled && i === coords.length - 1) break;
|
|
else if (travelled > startDist && slice.length === 0) {
|
|
overshot = startDist - travelled;
|
|
if (!overshot) {
|
|
slice.push(coords[i]);
|
|
return lineString(slice);
|
|
}
|
|
direction = bearing(coords[i], coords[i - 1]) - 180;
|
|
interpolated = destination(coords[i], overshot, direction, options);
|
|
slice.push(interpolated.geometry.coordinates);
|
|
}
|
|
|
|
if (travelled >= stopDist) {
|
|
overshot = stopDist - travelled;
|
|
if (!overshot) {
|
|
slice.push(coords[i]);
|
|
return lineString(slice);
|
|
}
|
|
direction = bearing(coords[i], coords[i - 1]) - 180;
|
|
interpolated = destination(coords[i], overshot, direction, options);
|
|
slice.push(interpolated.geometry.coordinates);
|
|
return lineString(slice);
|
|
}
|
|
|
|
if (travelled >= startDist) {
|
|
slice.push(coords[i]);
|
|
}
|
|
|
|
if (i === coords.length - 1) {
|
|
return lineString(slice);
|
|
}
|
|
|
|
travelled += distance(coords[i], coords[i + 1], options);
|
|
}
|
|
|
|
if (travelled < startDist && coords.length === origCoordsLength)
|
|
throw new Error("Start position is beyond line");
|
|
|
|
var last = coords[coords.length - 1];
|
|
return lineString([last, last]);
|
|
}
|
|
|
|
export default lineSliceAlong;
|