本文整理匯總了TypeScript中@turf/meta.featureEach函數的典型用法代碼示例。如果您正苦於以下問題:TypeScript featureEach函數的具體用法?TypeScript featureEach怎麽用?TypeScript featureEach使用的例子?那麽, 這裏精選的函數代碼示例或許可以為您提供幫助。
在下文中一共展示了featureEach函數的15個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的TypeScript代碼示例。
示例1: findMedian
/**
* Recursive function to find new candidate medians.
*
* @private
* @param {Position} candidateMedian current candidate median
* @param {Position} previousCandidate the previous candidate median
* @param {FeatureCollection<Point>} centroids the collection of centroids whose median we are determining
* @param {number} counter how many attempts to try before quitting.
* @returns {Feature<Point>} the median center of the dataset.
*/
function findMedian(candidateMedian, previousCandidate, centroids, counter) {
var tolerance = centroids.properties.tolerance || 0.001;
var candidateXsum = 0;
var candidateYsum = 0;
var kSum = 0;
var centroidCount = 0;
featureEach(centroids, function (theCentroid: any) {
var weightValue = theCentroid.properties.weight;
var weight = (weightValue === undefined || weightValue === null) ? 1 : weightValue;
weight = Number(weight);
if (!isNumber(weight)) throw new Error('weight value must be a number');
if (weight > 0) {
centroidCount += 1;
var distanceFromCandidate = weight * distance(theCentroid, candidateMedian);
if (distanceFromCandidate === 0) distanceFromCandidate = 1;
var k = weight / distanceFromCandidate;
candidateXsum += theCentroid.geometry.coordinates[0] * k;
candidateYsum += theCentroid.geometry.coordinates[1] * k;
kSum += k;
}
});
if (centroidCount < 1) throw new Error('no features to measure');
var candidateX = candidateXsum / kSum;
var candidateY = candidateYsum / kSum;
if (centroidCount === 1 || counter === 0 || (Math.abs(candidateX - previousCandidate[0]) < tolerance && Math.abs(candidateY - previousCandidate[1]) < tolerance)) {
return point([candidateX, candidateY], {medianCandidates: centroids.properties.medianCandidates});
} else {
centroids.properties.medianCandidates.push([candidateX, candidateY]);
return findMedian([candidateX, candidateY], candidateMedian, centroids, counter - 1);
}
}
示例2: centerMedian
/**
* Takes a {@link FeatureCollection} of points and calculates the median center,
* algorithimically. The median center is understood as the point that is
* requires the least total travel from all other points.
*
* Turfjs has four different functions for calculating the center of a set of
* data. Each is useful depending on circumstance.
*
* `@turf/center` finds the simple center of a dataset, by finding the
* midpoint between the extents of the data. That is, it divides in half the
* farthest east and farthest west point as well as the farthest north and
* farthest south.
*
* `@turf/center-of-mass` imagines that the dataset is a sheet of paper.
* The center of mass is where the sheet would balance on a fingertip.
*
* `@turf/center-mean` takes the averages of all the coordinates and
* produces a value that respects that. Unlike `@turf/center`, it is
* sensitive to clusters and outliers. It lands in the statistical middle of a
* dataset, not the geographical. It can also be weighted, meaning certain
* points are more important than others.
*
* `@turf/center-median` takes the mean center and tries to find, iteratively,
* a new point that requires the least amount of travel from all the points in
* the dataset. It is not as sensitive to outliers as `@turf/center-mean`, but it is
* attracted to clustered data. It, too, can be weighted.
*
* **Bibliography**
*
* Harold W. Kuhn and Robert E. Kuenne, “An Efficient Algorithm for the
* Numerical Solution of the Generalized Weber Problem in Spatial
* Economics,” _Journal of Regional Science_ 4, no. 2 (1962): 21–33,
* doi:{@link https://doi.org/10.1111/j.1467-9787.1962.tb00902.x}.
*
* James E. Burt, Gerald M. Barber, and David L. Rigby, _Elementary
* Statistics for Geographers_, 3rd ed., New York: The Guilford
* Press, 2009, 150–151.
*
* @name centerMedian
* @param {FeatureCollection<any>} features Any GeoJSON Feature Collection
* @param {Object} [options={}] Optional parameters
* @param {string} [options.weight] the property name used to weight the center
* @param {number} [options.tolerance=0.001] the difference in distance between candidate medians at which point the algorighim stops iterating.
* @param {number} [options.counter=10] how many attempts to find the median, should the tolerance be insufficient.
* @returns {Feature<Point>} The median center of the collection
* @example
* var points = turf.points([[0, 0], [1, 0], [0, 1], [5, 8]]);
* var medianCenter = turf.centerMedian(points);
*
* //addToMap
* var addToMap = [points, medianCenter]
*/
function centerMedian(
features: FeatureCollection<any>,
options: { weight?: string, tolerance?: number, counter?: number} = {}
): Feature<Point, {
medianCandidates: Array<Position>,
[key: string]: any
}> {
// Optional params
options = options || {};
if (!isObject(options)) throw new Error('options is invalid');
var counter = options.counter || 10;
if (!isNumber(counter)) throw new Error('counter must be a number');
var weightTerm = options.weight;
// Calculate mean center:
var meanCenter = centerMean(features, {weight: options.weight});
// Calculate center of every feature:
var centroids: any = featureCollection([]);
featureEach(features, function (feature) {
centroids.features.push(centroid(feature, {properties: {weight: feature.properties[weightTerm]}}));
});
centroids.properties = {
tolerance: options.tolerance,
medianCandidates: []
};
return findMedian(meanCenter.geometry.coordinates, [0, 0], centroids, counter);
}
示例3: createBins
export function createBins(geojson: FeatureCollection<any>, property: string | number) {
var bins = {};
featureEach(geojson, function (feature, i) {
var properties = feature.properties || {};
if (properties.hasOwnProperty(String(property))) {
var value = properties[property];
if (bins.hasOwnProperty(value)) bins[value].push(i);
else bins[value] = [i];
}
});
return bins;
}
示例4: featureEach
featureEach(lineSegment(line1), (segment) => {
featureEach(tree.search(segment), (match) => {
const intersect = intersects(segment, match);
if (intersect) {
// prevent duplicate points https://github.com/Turfjs/turf/issues/688
const key = getCoords(intersect).join(",");
if (!unique[key]) {
unique[key] = true;
results.push(intersect);
}
}
});
});
示例5: featureEach
featureEach(lineSegment(line1), function (segment) {
featureEach(tree.search(segment), function (match) {
var intersect = intersects(segment, match);
if (intersect) {
// prevent duplicate points https://github.com/Turfjs/turf/issues/688
var key = getCoords(intersect).join(',');
if (!unique[key]) {
unique[key] = true;
results.push(intersect);
}
}
});
});
示例6: removeDuplicates
/**
* Removes duplicated points in a collection returning a new collection
*
* @private
* @param {FeatureCollection<Point>} points to be cleaned
* @returns {FeatureCollection<Point>} cleaned set of points
*/
function removeDuplicates(points: FeatureCollection<Point>): FeatureCollection<Point> {
const cleaned: Array<Feature<Point>> = [];
const existing: {[key: string]: boolean} = {};
featureEach(points, (pt) => {
if (!pt.geometry) { return; }
const key = pt.geometry.coordinates.join("-");
if (!existing.hasOwnProperty(key)) {
cleaned.push(pt);
existing[key] = true;
}
});
return featureCollection(cleaned);
}
示例7: function
export function getCluster<G extends any, P = any>(
geojson: FeatureCollection<G, P>,
filter: any
): FeatureCollection<G, P> {
// Validation
if (!geojson) throw new Error('geojson is required');
if (geojson.type !== 'FeatureCollection') throw new Error('geojson must be a FeatureCollection');
if (filter === undefined || filter === null) throw new Error('filter is required');
// Filter Features
var features: Feature<G, P>[] = [];
featureEach<G, P>(geojson, function (feature) {
if (applyFilter(feature.properties, filter)) features.push(feature);
});
return featureCollection(features);
}
示例8: intersects
/**
* Takes any LineString or Polygon GeoJSON and returns the intersecting point(s).
*
* @name lineIntersect
* @param {GeoJSON} line1 any LineString or Polygon
* @param {GeoJSON} line2 any LineString or Polygon
* @returns {FeatureCollection<Point>} point(s) that intersect both
* @example
* var line1 = turf.lineString([[126, -11], [129, -21]]);
* var line2 = turf.lineString([[123, -18], [131, -14]]);
* var intersects = turf.lineIntersect(line1, line2);
*
* //addToMap
* var addToMap = [line1, line2, intersects]
*/
function lineIntersect<
G1 extends LineString|MultiLineString|Polygon|MultiPolygon,
G2 extends LineString|MultiLineString|Polygon|MultiPolygon
>(
line1: FeatureCollection<G1> | Feature<G1> | G1,
line2: FeatureCollection<G2> | Feature<G2> | G2,
): FeatureCollection<Point> {
const unique: any = {};
const results: any[] = [];
// First, normalize geometries to features
// Then, handle simple 2-vertex segments
if (line1.type === "LineString") { line1 = feature(line1); }
if (line2.type === "LineString") { line2 = feature(line2); }
if (line1.type === "Feature" &&
line2.type === "Feature" &&
line1.geometry !== null &&
line2.geometry !== null &&
line1.geometry.type === "LineString" &&
line2.geometry.type === "LineString" &&
line1.geometry.coordinates.length === 2 &&
line2.geometry.coordinates.length === 2) {
const intersect = intersects(line1, line2);
if (intersect) { results.push(intersect); }
return featureCollection(results);
}
// Handles complex GeoJSON Geometries
const tree = rbush();
tree.load(lineSegment(line2));
featureEach(lineSegment(line1), (segment) => {
featureEach(tree.search(segment), (match) => {
const intersect = intersects(segment, match);
if (intersect) {
// prevent duplicate points https://github.com/Turfjs/turf/issues/688
const key = getCoords(intersect).join(",");
if (!unique[key]) {
unique[key] = true;
results.push(intersect);
}
}
});
});
return featureCollection(results);
}
示例9: segmentEach
segmentEach(line2, function (segment) {
var doesOverlaps = false;
// 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: any = 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;
}
});
示例10: nearestPoint
/**
* Takes a reference {@link Point|point} and a FeatureCollection of Features
* with Point geometries and returns the
* point from the FeatureCollection closest to the reference. This calculation
* is geodesic.
*
* @name nearestPoint
* @param {Coord} targetPoint the reference point
* @param {FeatureCollection<Point>} points against input point set
* @returns {Feature<Point>} the closest point in the set to the reference point
* @example
* var targetPoint = turf.point([28.965797, 41.010086], {"marker-color": "#0F0"});
* var points = turf.featureCollection([
* turf.point([28.973865, 41.011122]),
* turf.point([28.948459, 41.024204]),
* turf.point([28.938674, 41.013324])
* ]);
*
* var nearest = turf.nearestPoint(targetPoint, points);
*
* //addToMap
* var addToMap = [targetPoint, points, nearest];
* nearest.properties['marker-color'] = '#F00';
*/
function nearestPoint(targetPoint: Coord, points: FeatureCollection<Point>): NearestPoint {
// Input validation
if (!targetPoint) throw new Error('targetPoint is required');
if (!points) throw new Error('points is required');
let nearest: NearestPoint;
let minDist: number = Infinity;
let bestFeatureIndex: number = 0;
featureEach(points, (pt, featureIndex) => {
const distanceToPoint = distance(targetPoint, pt);
if (distanceToPoint < minDist) {
bestFeatureIndex = featureIndex;
minDist = distanceToPoint;
}
});
nearest = clone(points.features[bestFeatureIndex]);
nearest.properties.featureIndex = bestFeatureIndex;
nearest.properties.distanceToPoint = minDist;
return nearest;
}
示例11: combine
/**
* Combines a {@link FeatureCollection} of {@link Point}, {@link LineString}, or {@link Polygon} features
* into {@link MultiPoint}, {@link MultiLineString}, or {@link MultiPolygon} features.
*
* @name combine
* @param {FeatureCollection<Point|LineString|Polygon>} fc a FeatureCollection of any type
* @returns {FeatureCollection<MultiPoint|MultiLineString|MultiPolygon>} a FeatureCollection of corresponding type to input
* @example
* var fc = turf.featureCollection([
* turf.point([19.026432, 47.49134]),
* turf.point([19.074497, 47.509548])
* ]);
*
* var combined = turf.combine(fc);
*
* //addToMap
* var addToMap = [combined]
*/
function combine(fc: FeatureCollection<Point|LineString|Polygon>) {
var groups = {
MultiPoint: {coordinates: [], properties: []},
MultiLineString: {coordinates: [], properties: []},
MultiPolygon: {coordinates: [], properties: []}
};
var multiMapping = Object.keys(groups).reduce(function (memo, item) {
memo[item.replace('Multi', '')] = item;
return memo;
}, {});
function addToGroup(feature, key, multi) {
if (!multi) {
groups[key].coordinates.push(feature.geometry.coordinates);
} else {
groups[key].coordinates = groups[key].coordinates.concat(feature.geometry.coordinates);
}
groups[key].properties.push(feature.properties);
}
featureEach(fc, function (feature) {
if (!feature.geometry) return;
if (groups[feature.geometry.type]) {
addToGroup(feature, feature.geometry.type, true);
} else if (multiMapping[feature.geometry.type]) {
addToGroup(feature, multiMapping[feature.geometry.type], false);
}
});
return featureCollection(Object.keys(groups)
.filter(function (key) {
return groups[key].coordinates.length;
})
.sort()
.map(function (key) {
var geometry = { type: key, coordinates: groups[key].coordinates };
var properties = { collectedProperties: groups[key].properties };
return feature(geometry, properties);
}));
}
示例12: nearestNeighborAnalysis
/**
* Nearest Neighbor Analysis calculates an index based the average distances
* between points in the dataset, thereby providing inference as to whether the
* data is clustered, dispersed, or randomly distributed within the study area.
*
* It returns a {@link Feature<Polygon>} of the study area, with the results of
* the analysis attached as part of of the `nearestNeighborAnalysis` property
* of the study area's `properties`. The attached
* [_z_-score](https://en.wikipedia.org/wiki/Standard_score) indicates how many
* standard deviations above or below the expected mean distance the data's
* observed mean distance is. The more negative, the more clustered. The more
* positive, the more evenly dispersed. A _z_-score between -2 and 2 indicates
* a seemingly random distribution. That is, within _p_ of less than 0.05, the
* distribution appears statistically significantly neither clustered nor
* dispersed.
*
* **Remarks**
*
* - Though the analysis will work on any {@link FeatureCollection} type, it
* works best with {@link Point} collections.
*
* - This analysis is _very_ sensitive to the study area provided.
* If no {@link Feature<Polygon>} is passed as the study area, the function draws a box
* around the data, which may distort the findings. This analysis works best
* with a bounded area of interest within with the data is either clustered,
* dispersed, or randomly distributed. For example, a city's subway stops may
* look extremely clustered if the study area is an entire state. On the other
* hand, they may look rather evenly dispersed if the study area is limited to
* the city's downtown.
*
* **Bibliography**
*
* Philip J. Clark and Francis C. Evans, “Distance to Nearest Neighbor as a
* Measure of Spatial Relationships in Populations,” _Ecology_ 35, no. 4
* (1954): 445–453, doi:[10.2307/1931034](http://doi.org/10.2307/1931034).
*
* @name nearestNeighborAnalysis
* @param {FeatureCollection<any>} dataset FeatureCollection (pref. of points) to study
* @param {Object} [options={}] Optional parameters
* @param {Feature<Polygon>} [options.studyArea] polygon representing the study area
* @param {string} [options.units='kilometers'] unit of measurement for distances and, squared, area.
* @param {Object} [options.properties={}] properties
* @returns {Feature<Polygon>} A polygon of the study area or an approximation of one.
* @example
* var bbox = [-65, 40, -63, 42];
* var dataset = turf.randomPoint(100, { bbox: bbox });
* var nearestNeighborStudyArea = turf.nearestNeighborAnalysis(dataset);
*
* //addToMap
* var addToMap = [dataset, nearestNeighborStudyArea];
*/
function nearestNeighborAnalysis(dataset: FeatureCollection<any>, options?: {
studyArea?: Feature<Polygon>;
units?: Units;
properties?: Properties;
}): NearestNeighborStudyArea {
// Optional params
options = options || {};
const studyArea = options.studyArea || bboxPolygon(bbox(dataset));
const properties = options.properties || {};
const units = options.units || 'kilometers';
const features: Array<Feature<Point>> = [];
featureEach(dataset, (feature) => {
features.push(centroid(feature));
});
const n = features.length;
const observedMeanDistance = features.map((feature, index) => {
const otherFeatures = featureCollection<Point>(features.filter((f, i) => {
return i !== index;
}));
// Have to add the ! to make typescript validation pass
// see https://stackoverflow.com/a/40350534/1979085
return distance(feature, nearestPoint(feature, otherFeatures).geometry!.coordinates, {units});
}).reduce((sum, value) => { return sum + value; }, 0) / n;
const populationDensity = n / convertArea(area(studyArea), 'meters', units);
const expectedMeanDistance = 1 / (2 * Math.sqrt(populationDensity));
const variance = 0.26136 / (Math.sqrt(n * populationDensity));
properties.nearestNeighborAnalysis = {
units: units,
arealUnits: units + '²',
observedMeanDistance: observedMeanDistance,
expectedMeanDistance: expectedMeanDistance,
nearestNeighborIndex: observedMeanDistance / expectedMeanDistance,
numberOfPoints: n,
zScore: (observedMeanDistance - expectedMeanDistance) / variance,
};
studyArea.properties = properties;
return studyArea as NearestNeighborStudyArea;
}
示例13: intersects
/**
* Takes any LineString or Polygon GeoJSON and returns the intersecting point(s).
*
* @name lineIntersect
* @param {Geometry|FeatureCollection|Feature<LineString|MultiLineString|Polygon|MultiPolygon>} line1 any LineString or Polygon
* @param {Geometry|FeatureCollection|Feature<LineString|MultiLineString|Polygon|MultiPolygon>} line2 any LineString or Polygon
* @returns {FeatureCollection<Point>} point(s) that intersect both
* @example
* var line1 = turf.lineString([[126, -11], [129, -21]]);
* var line2 = turf.lineString([[123, -18], [131, -14]]);
* var intersects = turf.lineIntersect(line1, line2);
*
* //addToMap
* var addToMap = [line1, line2, intersects]
*/
function lineIntersect<G1 extends LineString|MultiLineString|Polygon|MultiPolygon, G2 extends LineString|MultiLineString|Polygon|MultiPolygon>(
line1: FeatureCollection<G1> | Feature<G1> | G1,
line2: FeatureCollection<G2> | Feature<G2> | G2,
): FeatureCollection<Point> {
var unique = {};
var results = [];
// First, normalize geometries to features
// Then, handle simple 2-vertex segments
if (line1.type === 'LineString') line1 = feature(line1);
if (line2.type === 'LineString') line2 = feature(line2);
if (line1.type === 'Feature' &&
line2.type === 'Feature' &&
line1.geometry.type === 'LineString' &&
line2.geometry.type === 'LineString' &&
line1.geometry.coordinates.length === 2 &&
line2.geometry.coordinates.length === 2) {
var intersect = intersects(line1, line2);
if (intersect) results.push(intersect);
return featureCollection(results);
}
// Handles complex GeoJSON Geometries
var tree = rbush();
tree.load(lineSegment(line2));
featureEach(lineSegment(line1), function (segment) {
featureEach(tree.search(segment), function (match) {
var intersect = intersects(segment, match);
if (intersect) {
// prevent duplicate points https://github.com/Turfjs/turf/issues/688
var key = getCoords(intersect).join(',');
if (!unique[key]) {
unique[key] = true;
results.push(intersect);
}
}
});
});
return featureCollection(results);
}
示例14: clustersKmeans
/**
* Takes a set of {@link Point|points} and partition them into clusters using the k-mean .
* It uses the [k-means algorithm](https://en.wikipedia.org/wiki/K-means_clustering)
*
* @name clustersKmeans
* @param {FeatureCollection<Point>} points to be clustered
* @param {Object} [options={}] Optional parameters
* @param {number} [options.numberOfClusters=Math.sqrt(numberOfPoints/2)] numberOfClusters that will be generated
* @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated (significant performance increase if true)
* @returns {FeatureCollection<Point>} Clustered Points with an additional two properties associated to each Feature:
* - {number} cluster - the associated clusterId
* - {[number, number]} centroid - Centroid of the cluster [Longitude, Latitude]
* @example
* // create random points with random z-values in their properties
* var points = turf.randomPoint(100, {bbox: [0, 30, 20, 50]});
* var options = {numberOfClusters: 7};
* var clustered = turf.clustersKmeans(points, options);
*
* //addToMap
* var addToMap = [clustered];
*/
function clustersKmeans(points: FeatureCollection<Point>, options: {
numberOfClusters?: number,
mutate?: boolean
} = {}): FeatureCollection<Point, KmeansProps> {
// Default Params
var count = points.features.length;
options.numberOfClusters = options.numberOfClusters || Math.round(Math.sqrt(count / 2));
// numberOfClusters can't be greater than the number of points
// fallbacks to count
if (options.numberOfClusters > count) options.numberOfClusters = count;
// Clone points to prevent any mutations (enabled by default)
if (options.mutate !== true) points = clone(points);
// collect points coordinates
var data = coordAll(points);
// create seed to avoid skmeans to drift
var initialCentroids = data.slice(0, options.numberOfClusters);
// create skmeans clusters
var skmeansResult = skmeans(data, options.numberOfClusters, initialCentroids);
// store centroids {clusterId: [number, number]}
var centroids = {};
skmeansResult.centroids.forEach(function (coord, idx) {
centroids[idx] = coord;
});
// add associated cluster number
featureEach(points, function (point, index) {
var clusterId = skmeansResult.idxs[index];
point.properties.cluster = clusterId;
point.properties.centroid = centroids[clusterId];
});
return points;
}
示例15: normalize
/**
* Returns the closest {@link Point|point}, of a {@link FeatureCollection|collection} of points,
* to a {@link LineString|line}. The returned point has a `dist` property indicating its distance to the line.
*
* @name nearestPointToLine
* @param {FeatureCollection|GeometryCollection<Point>} points Point Collection
* @param {Feature|Geometry<LineString>} line Line Feature
* @param {Object} [options] Optional parameters
* @param {string} [options.units='kilometers'] unit of the output distance property
* (eg: degrees, radians, miles, or kilometers)
* @param {Object} [options.properties={}] Translate Properties to Point
* @returns {Feature<Point>} the closest point
* @example
* var pt1 = turf.point([0, 0]);
* var pt2 = turf.point([0.5, 0.5]);
* var points = turf.featureCollection([pt1, pt2]);
* var line = turf.lineString([[1,1], [-1,1]]);
*
* var nearest = turf.nearestPointToLine(points, line);
*
* //addToMap
* var addToMap = [nearest, line];
*/
function nearestPointToLine<P = {dist: number, [key: string]: any}>(
points: FeatureCollection<Point> | Feature<GeometryCollection> | GeometryCollection,
line: Feature<LineString> | LineString,
options: {
units?: Units,
properties?: Properties,
} = {},
): Feature<Point, P> {
const units = options.units;
const properties = options.properties || {};
// validation
const pts = normalize(points);
if (!pts.features.length) { throw new Error("points must contain features"); }
if (!line) { throw new Error("line is required"); }
if (getType(line) !== "LineString") { throw new Error("line must be a LineString"); }
let dist = Infinity;
let pt: any = null;
featureEach(pts, (point) => {
const d = pointToLineDistance(point, line, { units });
if (d < dist) {
dist = d;
pt = point;
}
});
/**
* Translate Properties to final Point, priorities:
* 1. options.properties
* 2. inherent Point properties
* 3. dist custom properties created by NearestPointToLine
*/
if (pt) { pt.properties = objectAssign({dist}, pt.properties, properties); }
// if (pt) { pt.properties = objectAssign({dist}, pt.properties, properties); }
return pt;
}