StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics
https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1132 lines
46 KiB
1132 lines
46 KiB
'use strict';
|
|
|
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
|
var helpers = require('@turf/helpers');
|
|
|
|
/**
|
|
* Callback for coordEach
|
|
*
|
|
* @callback coordEachCallback
|
|
* @param {Array<number>} currentCoord The current coordinate being processed.
|
|
* @param {number} coordIndex The current index of the coordinate being processed.
|
|
* @param {number} featureIndex The current index of the Feature being processed.
|
|
* @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.
|
|
* @param {number} geometryIndex The current index of the Geometry being processed.
|
|
*/
|
|
|
|
/**
|
|
* Iterate over coordinates in any GeoJSON object, similar to Array.forEach()
|
|
*
|
|
* @name coordEach
|
|
* @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object
|
|
* @param {Function} callback a method that takes (currentCoord, coordIndex, featureIndex, multiFeatureIndex)
|
|
* @param {boolean} [excludeWrapCoord=false] whether or not to include the final coordinate of LinearRings that wraps the ring in its iteration.
|
|
* @returns {void}
|
|
* @example
|
|
* var features = turf.featureCollection([
|
|
* turf.point([26, 37], {"foo": "bar"}),
|
|
* turf.point([36, 53], {"hello": "world"})
|
|
* ]);
|
|
*
|
|
* turf.coordEach(features, function (currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) {
|
|
* //=currentCoord
|
|
* //=coordIndex
|
|
* //=featureIndex
|
|
* //=multiFeatureIndex
|
|
* //=geometryIndex
|
|
* });
|
|
*/
|
|
function coordEach(geojson, callback, excludeWrapCoord) {
|
|
// Handles null Geometry -- Skips this GeoJSON
|
|
if (geojson === null) return;
|
|
var j, k, l, geometry, stopG, coords,
|
|
geometryMaybeCollection,
|
|
wrapShrink = 0,
|
|
coordIndex = 0,
|
|
isGeometryCollection,
|
|
type = geojson.type,
|
|
isFeatureCollection = type === 'FeatureCollection',
|
|
isFeature = type === 'Feature',
|
|
stop = isFeatureCollection ? geojson.features.length : 1;
|
|
|
|
// This logic may look a little weird. The reason why it is that way
|
|
// is because it's trying to be fast. GeoJSON supports multiple kinds
|
|
// of objects at its root: FeatureCollection, Features, Geometries.
|
|
// This function has the responsibility of handling all of them, and that
|
|
// means that some of the `for` loops you see below actually just don't apply
|
|
// to certain inputs. For instance, if you give this just a
|
|
// Point geometry, then both loops are short-circuited and all we do
|
|
// is gradually rename the input until it's called 'geometry'.
|
|
//
|
|
// This also aims to allocate as few resources as possible: just a
|
|
// few numbers and booleans, rather than any temporary arrays as would
|
|
// be required with the normalization approach.
|
|
for (var featureIndex = 0; featureIndex < stop; featureIndex++) {
|
|
geometryMaybeCollection = (isFeatureCollection ? geojson.features[featureIndex].geometry :
|
|
(isFeature ? geojson.geometry : geojson));
|
|
isGeometryCollection = (geometryMaybeCollection) ? geometryMaybeCollection.type === 'GeometryCollection' : false;
|
|
stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1;
|
|
|
|
for (var geomIndex = 0; geomIndex < stopG; geomIndex++) {
|
|
var multiFeatureIndex = 0;
|
|
var geometryIndex = 0;
|
|
geometry = isGeometryCollection ?
|
|
geometryMaybeCollection.geometries[geomIndex] : geometryMaybeCollection;
|
|
|
|
// Handles null Geometry -- Skips this geometry
|
|
if (geometry === null) continue;
|
|
coords = geometry.coordinates;
|
|
var geomType = geometry.type;
|
|
|
|
wrapShrink = (excludeWrapCoord && (geomType === 'Polygon' || geomType === 'MultiPolygon')) ? 1 : 0;
|
|
|
|
switch (geomType) {
|
|
case null:
|
|
break;
|
|
case 'Point':
|
|
if (callback(coords, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) === false) return false;
|
|
coordIndex++;
|
|
multiFeatureIndex++;
|
|
break;
|
|
case 'LineString':
|
|
case 'MultiPoint':
|
|
for (j = 0; j < coords.length; j++) {
|
|
if (callback(coords[j], coordIndex, featureIndex, multiFeatureIndex, geometryIndex) === false) return false;
|
|
coordIndex++;
|
|
if (geomType === 'MultiPoint') multiFeatureIndex++;
|
|
}
|
|
if (geomType === 'LineString') multiFeatureIndex++;
|
|
break;
|
|
case 'Polygon':
|
|
case 'MultiLineString':
|
|
for (j = 0; j < coords.length; j++) {
|
|
for (k = 0; k < coords[j].length - wrapShrink; k++) {
|
|
if (callback(coords[j][k], coordIndex, featureIndex, multiFeatureIndex, geometryIndex) === false) return false;
|
|
coordIndex++;
|
|
}
|
|
if (geomType === 'MultiLineString') multiFeatureIndex++;
|
|
if (geomType === 'Polygon') geometryIndex++;
|
|
}
|
|
if (geomType === 'Polygon') multiFeatureIndex++;
|
|
break;
|
|
case 'MultiPolygon':
|
|
for (j = 0; j < coords.length; j++) {
|
|
geometryIndex = 0;
|
|
for (k = 0; k < coords[j].length; k++) {
|
|
for (l = 0; l < coords[j][k].length - wrapShrink; l++) {
|
|
if (callback(coords[j][k][l], coordIndex, featureIndex, multiFeatureIndex, geometryIndex) === false) return false;
|
|
coordIndex++;
|
|
}
|
|
geometryIndex++;
|
|
}
|
|
multiFeatureIndex++;
|
|
}
|
|
break;
|
|
case 'GeometryCollection':
|
|
for (j = 0; j < geometry.geometries.length; j++)
|
|
if (coordEach(geometry.geometries[j], callback, excludeWrapCoord) === false) return false;
|
|
break;
|
|
default:
|
|
throw new Error('Unknown Geometry Type');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Callback for coordReduce
|
|
*
|
|
* The first time the callback function is called, the values provided as arguments depend
|
|
* on whether the reduce method has an initialValue argument.
|
|
*
|
|
* If an initialValue is provided to the reduce method:
|
|
* - The previousValue argument is initialValue.
|
|
* - The currentValue argument is the value of the first element present in the array.
|
|
*
|
|
* If an initialValue is not provided:
|
|
* - The previousValue argument is the value of the first element present in the array.
|
|
* - The currentValue argument is the value of the second element present in the array.
|
|
*
|
|
* @callback coordReduceCallback
|
|
* @param {*} previousValue The accumulated value previously returned in the last invocation
|
|
* of the callback, or initialValue, if supplied.
|
|
* @param {Array<number>} currentCoord The current coordinate being processed.
|
|
* @param {number} coordIndex The current index of the coordinate being processed.
|
|
* Starts at index 0, if an initialValue is provided, and at index 1 otherwise.
|
|
* @param {number} featureIndex The current index of the Feature being processed.
|
|
* @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.
|
|
* @param {number} geometryIndex The current index of the Geometry being processed.
|
|
*/
|
|
|
|
/**
|
|
* Reduce coordinates in any GeoJSON object, similar to Array.reduce()
|
|
*
|
|
* @name coordReduce
|
|
* @param {FeatureCollection|Geometry|Feature} geojson any GeoJSON object
|
|
* @param {Function} callback a method that takes (previousValue, currentCoord, coordIndex)
|
|
* @param {*} [initialValue] Value to use as the first argument to the first call of the callback.
|
|
* @param {boolean} [excludeWrapCoord=false] whether or not to include the final coordinate of LinearRings that wraps the ring in its iteration.
|
|
* @returns {*} The value that results from the reduction.
|
|
* @example
|
|
* var features = turf.featureCollection([
|
|
* turf.point([26, 37], {"foo": "bar"}),
|
|
* turf.point([36, 53], {"hello": "world"})
|
|
* ]);
|
|
*
|
|
* turf.coordReduce(features, function (previousValue, currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) {
|
|
* //=previousValue
|
|
* //=currentCoord
|
|
* //=coordIndex
|
|
* //=featureIndex
|
|
* //=multiFeatureIndex
|
|
* //=geometryIndex
|
|
* return currentCoord;
|
|
* });
|
|
*/
|
|
function coordReduce(geojson, callback, initialValue, excludeWrapCoord) {
|
|
var previousValue = initialValue;
|
|
coordEach(geojson, function (currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) {
|
|
if (coordIndex === 0 && initialValue === undefined) previousValue = currentCoord;
|
|
else previousValue = callback(previousValue, currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex);
|
|
}, excludeWrapCoord);
|
|
return previousValue;
|
|
}
|
|
|
|
/**
|
|
* Callback for propEach
|
|
*
|
|
* @callback propEachCallback
|
|
* @param {Object} currentProperties The current Properties being processed.
|
|
* @param {number} featureIndex The current index of the Feature being processed.
|
|
*/
|
|
|
|
/**
|
|
* Iterate over properties in any GeoJSON object, similar to Array.forEach()
|
|
*
|
|
* @name propEach
|
|
* @param {FeatureCollection|Feature} geojson any GeoJSON object
|
|
* @param {Function} callback a method that takes (currentProperties, featureIndex)
|
|
* @returns {void}
|
|
* @example
|
|
* var features = turf.featureCollection([
|
|
* turf.point([26, 37], {foo: 'bar'}),
|
|
* turf.point([36, 53], {hello: 'world'})
|
|
* ]);
|
|
*
|
|
* turf.propEach(features, function (currentProperties, featureIndex) {
|
|
* //=currentProperties
|
|
* //=featureIndex
|
|
* });
|
|
*/
|
|
function propEach(geojson, callback) {
|
|
var i;
|
|
switch (geojson.type) {
|
|
case 'FeatureCollection':
|
|
for (i = 0; i < geojson.features.length; i++) {
|
|
if (callback(geojson.features[i].properties, i) === false) break;
|
|
}
|
|
break;
|
|
case 'Feature':
|
|
callback(geojson.properties, 0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Callback for propReduce
|
|
*
|
|
* The first time the callback function is called, the values provided as arguments depend
|
|
* on whether the reduce method has an initialValue argument.
|
|
*
|
|
* If an initialValue is provided to the reduce method:
|
|
* - The previousValue argument is initialValue.
|
|
* - The currentValue argument is the value of the first element present in the array.
|
|
*
|
|
* If an initialValue is not provided:
|
|
* - The previousValue argument is the value of the first element present in the array.
|
|
* - The currentValue argument is the value of the second element present in the array.
|
|
*
|
|
* @callback propReduceCallback
|
|
* @param {*} previousValue The accumulated value previously returned in the last invocation
|
|
* of the callback, or initialValue, if supplied.
|
|
* @param {*} currentProperties The current Properties being processed.
|
|
* @param {number} featureIndex The current index of the Feature being processed.
|
|
*/
|
|
|
|
/**
|
|
* Reduce properties in any GeoJSON object into a single value,
|
|
* similar to how Array.reduce works. However, in this case we lazily run
|
|
* the reduction, so an array of all properties is unnecessary.
|
|
*
|
|
* @name propReduce
|
|
* @param {FeatureCollection|Feature} geojson any GeoJSON object
|
|
* @param {Function} callback a method that takes (previousValue, currentProperties, featureIndex)
|
|
* @param {*} [initialValue] Value to use as the first argument to the first call of the callback.
|
|
* @returns {*} The value that results from the reduction.
|
|
* @example
|
|
* var features = turf.featureCollection([
|
|
* turf.point([26, 37], {foo: 'bar'}),
|
|
* turf.point([36, 53], {hello: 'world'})
|
|
* ]);
|
|
*
|
|
* turf.propReduce(features, function (previousValue, currentProperties, featureIndex) {
|
|
* //=previousValue
|
|
* //=currentProperties
|
|
* //=featureIndex
|
|
* return currentProperties
|
|
* });
|
|
*/
|
|
function propReduce(geojson, callback, initialValue) {
|
|
var previousValue = initialValue;
|
|
propEach(geojson, function (currentProperties, featureIndex) {
|
|
if (featureIndex === 0 && initialValue === undefined) previousValue = currentProperties;
|
|
else previousValue = callback(previousValue, currentProperties, featureIndex);
|
|
});
|
|
return previousValue;
|
|
}
|
|
|
|
/**
|
|
* Callback for featureEach
|
|
*
|
|
* @callback featureEachCallback
|
|
* @param {Feature<any>} currentFeature The current Feature being processed.
|
|
* @param {number} featureIndex The current index of the Feature being processed.
|
|
*/
|
|
|
|
/**
|
|
* Iterate over features in any GeoJSON object, similar to
|
|
* Array.forEach.
|
|
*
|
|
* @name featureEach
|
|
* @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object
|
|
* @param {Function} callback a method that takes (currentFeature, featureIndex)
|
|
* @returns {void}
|
|
* @example
|
|
* var features = turf.featureCollection([
|
|
* turf.point([26, 37], {foo: 'bar'}),
|
|
* turf.point([36, 53], {hello: 'world'})
|
|
* ]);
|
|
*
|
|
* turf.featureEach(features, function (currentFeature, featureIndex) {
|
|
* //=currentFeature
|
|
* //=featureIndex
|
|
* });
|
|
*/
|
|
function featureEach(geojson, callback) {
|
|
if (geojson.type === 'Feature') {
|
|
callback(geojson, 0);
|
|
} else if (geojson.type === 'FeatureCollection') {
|
|
for (var i = 0; i < geojson.features.length; i++) {
|
|
if (callback(geojson.features[i], i) === false) break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Callback for featureReduce
|
|
*
|
|
* The first time the callback function is called, the values provided as arguments depend
|
|
* on whether the reduce method has an initialValue argument.
|
|
*
|
|
* If an initialValue is provided to the reduce method:
|
|
* - The previousValue argument is initialValue.
|
|
* - The currentValue argument is the value of the first element present in the array.
|
|
*
|
|
* If an initialValue is not provided:
|
|
* - The previousValue argument is the value of the first element present in the array.
|
|
* - The currentValue argument is the value of the second element present in the array.
|
|
*
|
|
* @callback featureReduceCallback
|
|
* @param {*} previousValue The accumulated value previously returned in the last invocation
|
|
* of the callback, or initialValue, if supplied.
|
|
* @param {Feature} currentFeature The current Feature being processed.
|
|
* @param {number} featureIndex The current index of the Feature being processed.
|
|
*/
|
|
|
|
/**
|
|
* Reduce features in any GeoJSON object, similar to Array.reduce().
|
|
*
|
|
* @name featureReduce
|
|
* @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object
|
|
* @param {Function} callback a method that takes (previousValue, currentFeature, featureIndex)
|
|
* @param {*} [initialValue] Value to use as the first argument to the first call of the callback.
|
|
* @returns {*} The value that results from the reduction.
|
|
* @example
|
|
* var features = turf.featureCollection([
|
|
* turf.point([26, 37], {"foo": "bar"}),
|
|
* turf.point([36, 53], {"hello": "world"})
|
|
* ]);
|
|
*
|
|
* turf.featureReduce(features, function (previousValue, currentFeature, featureIndex) {
|
|
* //=previousValue
|
|
* //=currentFeature
|
|
* //=featureIndex
|
|
* return currentFeature
|
|
* });
|
|
*/
|
|
function featureReduce(geojson, callback, initialValue) {
|
|
var previousValue = initialValue;
|
|
featureEach(geojson, function (currentFeature, featureIndex) {
|
|
if (featureIndex === 0 && initialValue === undefined) previousValue = currentFeature;
|
|
else previousValue = callback(previousValue, currentFeature, featureIndex);
|
|
});
|
|
return previousValue;
|
|
}
|
|
|
|
/**
|
|
* Get all coordinates from any GeoJSON object.
|
|
*
|
|
* @name coordAll
|
|
* @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object
|
|
* @returns {Array<Array<number>>} coordinate position array
|
|
* @example
|
|
* var features = turf.featureCollection([
|
|
* turf.point([26, 37], {foo: 'bar'}),
|
|
* turf.point([36, 53], {hello: 'world'})
|
|
* ]);
|
|
*
|
|
* var coords = turf.coordAll(features);
|
|
* //= [[26, 37], [36, 53]]
|
|
*/
|
|
function coordAll(geojson) {
|
|
var coords = [];
|
|
coordEach(geojson, function (coord) {
|
|
coords.push(coord);
|
|
});
|
|
return coords;
|
|
}
|
|
|
|
/**
|
|
* Callback for geomEach
|
|
*
|
|
* @callback geomEachCallback
|
|
* @param {Geometry} currentGeometry The current Geometry being processed.
|
|
* @param {number} featureIndex The current index of the Feature being processed.
|
|
* @param {Object} featureProperties The current Feature Properties being processed.
|
|
* @param {Array<number>} featureBBox The current Feature BBox being processed.
|
|
* @param {number|string} featureId The current Feature Id being processed.
|
|
*/
|
|
|
|
/**
|
|
* Iterate over each geometry in any GeoJSON object, similar to Array.forEach()
|
|
*
|
|
* @name geomEach
|
|
* @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object
|
|
* @param {Function} callback a method that takes (currentGeometry, featureIndex, featureProperties, featureBBox, featureId)
|
|
* @returns {void}
|
|
* @example
|
|
* var features = turf.featureCollection([
|
|
* turf.point([26, 37], {foo: 'bar'}),
|
|
* turf.point([36, 53], {hello: 'world'})
|
|
* ]);
|
|
*
|
|
* turf.geomEach(features, function (currentGeometry, featureIndex, featureProperties, featureBBox, featureId) {
|
|
* //=currentGeometry
|
|
* //=featureIndex
|
|
* //=featureProperties
|
|
* //=featureBBox
|
|
* //=featureId
|
|
* });
|
|
*/
|
|
function geomEach(geojson, callback) {
|
|
var i, j, g, geometry, stopG,
|
|
geometryMaybeCollection,
|
|
isGeometryCollection,
|
|
featureProperties,
|
|
featureBBox,
|
|
featureId,
|
|
featureIndex = 0,
|
|
isFeatureCollection = geojson.type === 'FeatureCollection',
|
|
isFeature = geojson.type === 'Feature',
|
|
stop = isFeatureCollection ? geojson.features.length : 1;
|
|
|
|
// This logic may look a little weird. The reason why it is that way
|
|
// is because it's trying to be fast. GeoJSON supports multiple kinds
|
|
// of objects at its root: FeatureCollection, Features, Geometries.
|
|
// This function has the responsibility of handling all of them, and that
|
|
// means that some of the `for` loops you see below actually just don't apply
|
|
// to certain inputs. For instance, if you give this just a
|
|
// Point geometry, then both loops are short-circuited and all we do
|
|
// is gradually rename the input until it's called 'geometry'.
|
|
//
|
|
// This also aims to allocate as few resources as possible: just a
|
|
// few numbers and booleans, rather than any temporary arrays as would
|
|
// be required with the normalization approach.
|
|
for (i = 0; i < stop; i++) {
|
|
|
|
geometryMaybeCollection = (isFeatureCollection ? geojson.features[i].geometry :
|
|
(isFeature ? geojson.geometry : geojson));
|
|
featureProperties = (isFeatureCollection ? geojson.features[i].properties :
|
|
(isFeature ? geojson.properties : {}));
|
|
featureBBox = (isFeatureCollection ? geojson.features[i].bbox :
|
|
(isFeature ? geojson.bbox : undefined));
|
|
featureId = (isFeatureCollection ? geojson.features[i].id :
|
|
(isFeature ? geojson.id : undefined));
|
|
isGeometryCollection = (geometryMaybeCollection) ? geometryMaybeCollection.type === 'GeometryCollection' : false;
|
|
stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1;
|
|
|
|
for (g = 0; g < stopG; g++) {
|
|
geometry = isGeometryCollection ?
|
|
geometryMaybeCollection.geometries[g] : geometryMaybeCollection;
|
|
|
|
// Handle null Geometry
|
|
if (geometry === null) {
|
|
if (callback(null, featureIndex, featureProperties, featureBBox, featureId) === false) return false;
|
|
continue;
|
|
}
|
|
switch (geometry.type) {
|
|
case 'Point':
|
|
case 'LineString':
|
|
case 'MultiPoint':
|
|
case 'Polygon':
|
|
case 'MultiLineString':
|
|
case 'MultiPolygon': {
|
|
if (callback(geometry, featureIndex, featureProperties, featureBBox, featureId) === false) return false;
|
|
break;
|
|
}
|
|
case 'GeometryCollection': {
|
|
for (j = 0; j < geometry.geometries.length; j++) {
|
|
if (callback(geometry.geometries[j], featureIndex, featureProperties, featureBBox, featureId) === false) return false;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
throw new Error('Unknown Geometry Type');
|
|
}
|
|
}
|
|
// Only increase `featureIndex` per each feature
|
|
featureIndex++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Callback for geomReduce
|
|
*
|
|
* The first time the callback function is called, the values provided as arguments depend
|
|
* on whether the reduce method has an initialValue argument.
|
|
*
|
|
* If an initialValue is provided to the reduce method:
|
|
* - The previousValue argument is initialValue.
|
|
* - The currentValue argument is the value of the first element present in the array.
|
|
*
|
|
* If an initialValue is not provided:
|
|
* - The previousValue argument is the value of the first element present in the array.
|
|
* - The currentValue argument is the value of the second element present in the array.
|
|
*
|
|
* @callback geomReduceCallback
|
|
* @param {*} previousValue The accumulated value previously returned in the last invocation
|
|
* of the callback, or initialValue, if supplied.
|
|
* @param {Geometry} currentGeometry The current Geometry being processed.
|
|
* @param {number} featureIndex The current index of the Feature being processed.
|
|
* @param {Object} featureProperties The current Feature Properties being processed.
|
|
* @param {Array<number>} featureBBox The current Feature BBox being processed.
|
|
* @param {number|string} featureId The current Feature Id being processed.
|
|
*/
|
|
|
|
/**
|
|
* Reduce geometry in any GeoJSON object, similar to Array.reduce().
|
|
*
|
|
* @name geomReduce
|
|
* @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object
|
|
* @param {Function} callback a method that takes (previousValue, currentGeometry, featureIndex, featureProperties, featureBBox, featureId)
|
|
* @param {*} [initialValue] Value to use as the first argument to the first call of the callback.
|
|
* @returns {*} The value that results from the reduction.
|
|
* @example
|
|
* var features = turf.featureCollection([
|
|
* turf.point([26, 37], {foo: 'bar'}),
|
|
* turf.point([36, 53], {hello: 'world'})
|
|
* ]);
|
|
*
|
|
* turf.geomReduce(features, function (previousValue, currentGeometry, featureIndex, featureProperties, featureBBox, featureId) {
|
|
* //=previousValue
|
|
* //=currentGeometry
|
|
* //=featureIndex
|
|
* //=featureProperties
|
|
* //=featureBBox
|
|
* //=featureId
|
|
* return currentGeometry
|
|
* });
|
|
*/
|
|
function geomReduce(geojson, callback, initialValue) {
|
|
var previousValue = initialValue;
|
|
geomEach(geojson, function (currentGeometry, featureIndex, featureProperties, featureBBox, featureId) {
|
|
if (featureIndex === 0 && initialValue === undefined) previousValue = currentGeometry;
|
|
else previousValue = callback(previousValue, currentGeometry, featureIndex, featureProperties, featureBBox, featureId);
|
|
});
|
|
return previousValue;
|
|
}
|
|
|
|
/**
|
|
* Callback for flattenEach
|
|
*
|
|
* @callback flattenEachCallback
|
|
* @param {Feature} currentFeature The current flattened feature being processed.
|
|
* @param {number} featureIndex The current index of the Feature being processed.
|
|
* @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.
|
|
*/
|
|
|
|
/**
|
|
* Iterate over flattened features in any GeoJSON object, similar to
|
|
* Array.forEach.
|
|
*
|
|
* @name flattenEach
|
|
* @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object
|
|
* @param {Function} callback a method that takes (currentFeature, featureIndex, multiFeatureIndex)
|
|
* @example
|
|
* var features = turf.featureCollection([
|
|
* turf.point([26, 37], {foo: 'bar'}),
|
|
* turf.multiPoint([[40, 30], [36, 53]], {hello: 'world'})
|
|
* ]);
|
|
*
|
|
* turf.flattenEach(features, function (currentFeature, featureIndex, multiFeatureIndex) {
|
|
* //=currentFeature
|
|
* //=featureIndex
|
|
* //=multiFeatureIndex
|
|
* });
|
|
*/
|
|
function flattenEach(geojson, callback) {
|
|
geomEach(geojson, function (geometry, featureIndex, properties, bbox, id) {
|
|
// Callback for single geometry
|
|
var type = (geometry === null) ? null : geometry.type;
|
|
switch (type) {
|
|
case null:
|
|
case 'Point':
|
|
case 'LineString':
|
|
case 'Polygon':
|
|
if (callback(helpers.feature(geometry, properties, {bbox: bbox, id: id}), featureIndex, 0) === false) return false;
|
|
return;
|
|
}
|
|
|
|
var geomType;
|
|
|
|
// Callback for multi-geometry
|
|
switch (type) {
|
|
case 'MultiPoint':
|
|
geomType = 'Point';
|
|
break;
|
|
case 'MultiLineString':
|
|
geomType = 'LineString';
|
|
break;
|
|
case 'MultiPolygon':
|
|
geomType = 'Polygon';
|
|
break;
|
|
}
|
|
|
|
for (var multiFeatureIndex = 0; multiFeatureIndex < geometry.coordinates.length; multiFeatureIndex++) {
|
|
var coordinate = geometry.coordinates[multiFeatureIndex];
|
|
var geom = {
|
|
type: geomType,
|
|
coordinates: coordinate
|
|
};
|
|
if (callback(helpers.feature(geom, properties), featureIndex, multiFeatureIndex) === false) return false;
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Callback for flattenReduce
|
|
*
|
|
* The first time the callback function is called, the values provided as arguments depend
|
|
* on whether the reduce method has an initialValue argument.
|
|
*
|
|
* If an initialValue is provided to the reduce method:
|
|
* - The previousValue argument is initialValue.
|
|
* - The currentValue argument is the value of the first element present in the array.
|
|
*
|
|
* If an initialValue is not provided:
|
|
* - The previousValue argument is the value of the first element present in the array.
|
|
* - The currentValue argument is the value of the second element present in the array.
|
|
*
|
|
* @callback flattenReduceCallback
|
|
* @param {*} previousValue The accumulated value previously returned in the last invocation
|
|
* of the callback, or initialValue, if supplied.
|
|
* @param {Feature} currentFeature The current Feature being processed.
|
|
* @param {number} featureIndex The current index of the Feature being processed.
|
|
* @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.
|
|
*/
|
|
|
|
/**
|
|
* Reduce flattened features in any GeoJSON object, similar to Array.reduce().
|
|
*
|
|
* @name flattenReduce
|
|
* @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object
|
|
* @param {Function} callback a method that takes (previousValue, currentFeature, featureIndex, multiFeatureIndex)
|
|
* @param {*} [initialValue] Value to use as the first argument to the first call of the callback.
|
|
* @returns {*} The value that results from the reduction.
|
|
* @example
|
|
* var features = turf.featureCollection([
|
|
* turf.point([26, 37], {foo: 'bar'}),
|
|
* turf.multiPoint([[40, 30], [36, 53]], {hello: 'world'})
|
|
* ]);
|
|
*
|
|
* turf.flattenReduce(features, function (previousValue, currentFeature, featureIndex, multiFeatureIndex) {
|
|
* //=previousValue
|
|
* //=currentFeature
|
|
* //=featureIndex
|
|
* //=multiFeatureIndex
|
|
* return currentFeature
|
|
* });
|
|
*/
|
|
function flattenReduce(geojson, callback, initialValue) {
|
|
var previousValue = initialValue;
|
|
flattenEach(geojson, function (currentFeature, featureIndex, multiFeatureIndex) {
|
|
if (featureIndex === 0 && multiFeatureIndex === 0 && initialValue === undefined) previousValue = currentFeature;
|
|
else previousValue = callback(previousValue, currentFeature, featureIndex, multiFeatureIndex);
|
|
});
|
|
return previousValue;
|
|
}
|
|
|
|
/**
|
|
* Callback for segmentEach
|
|
*
|
|
* @callback segmentEachCallback
|
|
* @param {Feature<LineString>} currentSegment The current Segment being processed.
|
|
* @param {number} featureIndex The current index of the Feature being processed.
|
|
* @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.
|
|
* @param {number} geometryIndex The current index of the Geometry being processed.
|
|
* @param {number} segmentIndex The current index of the Segment being processed.
|
|
* @returns {void}
|
|
*/
|
|
|
|
/**
|
|
* Iterate over 2-vertex line segment in any GeoJSON object, similar to Array.forEach()
|
|
* (Multi)Point geometries do not contain segments therefore they are ignored during this operation.
|
|
*
|
|
* @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON
|
|
* @param {Function} callback a method that takes (currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex)
|
|
* @returns {void}
|
|
* @example
|
|
* var polygon = turf.polygon([[[-50, 5], [-40, -10], [-50, -10], [-40, 5], [-50, 5]]]);
|
|
*
|
|
* // Iterate over GeoJSON by 2-vertex segments
|
|
* turf.segmentEach(polygon, function (currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) {
|
|
* //=currentSegment
|
|
* //=featureIndex
|
|
* //=multiFeatureIndex
|
|
* //=geometryIndex
|
|
* //=segmentIndex
|
|
* });
|
|
*
|
|
* // Calculate the total number of segments
|
|
* var total = 0;
|
|
* turf.segmentEach(polygon, function () {
|
|
* total++;
|
|
* });
|
|
*/
|
|
function segmentEach(geojson, callback) {
|
|
flattenEach(geojson, function (feature, featureIndex, multiFeatureIndex) {
|
|
var segmentIndex = 0;
|
|
|
|
// Exclude null Geometries
|
|
if (!feature.geometry) return;
|
|
// (Multi)Point geometries do not contain segments therefore they are ignored during this operation.
|
|
var type = feature.geometry.type;
|
|
if (type === 'Point' || type === 'MultiPoint') return;
|
|
|
|
// Generate 2-vertex line segments
|
|
var previousCoords;
|
|
var previousFeatureIndex = 0;
|
|
var previousMultiIndex = 0;
|
|
var prevGeomIndex = 0;
|
|
if (coordEach(feature, function (currentCoord, coordIndex, featureIndexCoord, multiPartIndexCoord, geometryIndex) {
|
|
// Simulating a meta.coordReduce() since `reduce` operations cannot be stopped by returning `false`
|
|
if (previousCoords === undefined || featureIndex > previousFeatureIndex || multiPartIndexCoord > previousMultiIndex || geometryIndex > prevGeomIndex) {
|
|
previousCoords = currentCoord;
|
|
previousFeatureIndex = featureIndex;
|
|
previousMultiIndex = multiPartIndexCoord;
|
|
prevGeomIndex = geometryIndex;
|
|
segmentIndex = 0;
|
|
return;
|
|
}
|
|
var currentSegment = helpers.lineString([previousCoords, currentCoord], feature.properties);
|
|
if (callback(currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) === false) return false;
|
|
segmentIndex++;
|
|
previousCoords = currentCoord;
|
|
}) === false) return false;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Callback for segmentReduce
|
|
*
|
|
* The first time the callback function is called, the values provided as arguments depend
|
|
* on whether the reduce method has an initialValue argument.
|
|
*
|
|
* If an initialValue is provided to the reduce method:
|
|
* - The previousValue argument is initialValue.
|
|
* - The currentValue argument is the value of the first element present in the array.
|
|
*
|
|
* If an initialValue is not provided:
|
|
* - The previousValue argument is the value of the first element present in the array.
|
|
* - The currentValue argument is the value of the second element present in the array.
|
|
*
|
|
* @callback segmentReduceCallback
|
|
* @param {*} previousValue The accumulated value previously returned in the last invocation
|
|
* of the callback, or initialValue, if supplied.
|
|
* @param {Feature<LineString>} currentSegment The current Segment being processed.
|
|
* @param {number} featureIndex The current index of the Feature being processed.
|
|
* @param {number} multiFeatureIndex The current index of the Multi-Feature being processed.
|
|
* @param {number} geometryIndex The current index of the Geometry being processed.
|
|
* @param {number} segmentIndex The current index of the Segment being processed.
|
|
*/
|
|
|
|
/**
|
|
* Reduce 2-vertex line segment in any GeoJSON object, similar to Array.reduce()
|
|
* (Multi)Point geometries do not contain segments therefore they are ignored during this operation.
|
|
*
|
|
* @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON
|
|
* @param {Function} callback a method that takes (previousValue, currentSegment, currentIndex)
|
|
* @param {*} [initialValue] Value to use as the first argument to the first call of the callback.
|
|
* @returns {void}
|
|
* @example
|
|
* var polygon = turf.polygon([[[-50, 5], [-40, -10], [-50, -10], [-40, 5], [-50, 5]]]);
|
|
*
|
|
* // Iterate over GeoJSON by 2-vertex segments
|
|
* turf.segmentReduce(polygon, function (previousSegment, currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) {
|
|
* //= previousSegment
|
|
* //= currentSegment
|
|
* //= featureIndex
|
|
* //= multiFeatureIndex
|
|
* //= geometryIndex
|
|
* //= segmentInex
|
|
* return currentSegment
|
|
* });
|
|
*
|
|
* // Calculate the total number of segments
|
|
* var initialValue = 0
|
|
* var total = turf.segmentReduce(polygon, function (previousValue) {
|
|
* previousValue++;
|
|
* return previousValue;
|
|
* }, initialValue);
|
|
*/
|
|
function segmentReduce(geojson, callback, initialValue) {
|
|
var previousValue = initialValue;
|
|
var started = false;
|
|
segmentEach(geojson, function (currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) {
|
|
if (started === false && initialValue === undefined) previousValue = currentSegment;
|
|
else previousValue = callback(previousValue, currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex);
|
|
started = true;
|
|
});
|
|
return previousValue;
|
|
}
|
|
|
|
/**
|
|
* Callback for lineEach
|
|
*
|
|
* @callback lineEachCallback
|
|
* @param {Feature<LineString>} currentLine The current LineString|LinearRing being processed
|
|
* @param {number} featureIndex The current index of the Feature being processed
|
|
* @param {number} multiFeatureIndex The current index of the Multi-Feature being processed
|
|
* @param {number} geometryIndex The current index of the Geometry being processed
|
|
*/
|
|
|
|
/**
|
|
* Iterate over line or ring coordinates in LineString, Polygon, MultiLineString, MultiPolygon Features or Geometries,
|
|
* similar to Array.forEach.
|
|
*
|
|
* @name lineEach
|
|
* @param {Geometry|Feature<LineString|Polygon|MultiLineString|MultiPolygon>} geojson object
|
|
* @param {Function} callback a method that takes (currentLine, featureIndex, multiFeatureIndex, geometryIndex)
|
|
* @example
|
|
* var multiLine = turf.multiLineString([
|
|
* [[26, 37], [35, 45]],
|
|
* [[36, 53], [38, 50], [41, 55]]
|
|
* ]);
|
|
*
|
|
* turf.lineEach(multiLine, function (currentLine, featureIndex, multiFeatureIndex, geometryIndex) {
|
|
* //=currentLine
|
|
* //=featureIndex
|
|
* //=multiFeatureIndex
|
|
* //=geometryIndex
|
|
* });
|
|
*/
|
|
function lineEach(geojson, callback) {
|
|
// validation
|
|
if (!geojson) throw new Error('geojson is required');
|
|
|
|
flattenEach(geojson, function (feature, featureIndex, multiFeatureIndex) {
|
|
if (feature.geometry === null) return;
|
|
var type = feature.geometry.type;
|
|
var coords = feature.geometry.coordinates;
|
|
switch (type) {
|
|
case 'LineString':
|
|
if (callback(feature, featureIndex, multiFeatureIndex, 0, 0) === false) return false;
|
|
break;
|
|
case 'Polygon':
|
|
for (var geometryIndex = 0; geometryIndex < coords.length; geometryIndex++) {
|
|
if (callback(helpers.lineString(coords[geometryIndex], feature.properties), featureIndex, multiFeatureIndex, geometryIndex) === false) return false;
|
|
}
|
|
break;
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Callback for lineReduce
|
|
*
|
|
* The first time the callback function is called, the values provided as arguments depend
|
|
* on whether the reduce method has an initialValue argument.
|
|
*
|
|
* If an initialValue is provided to the reduce method:
|
|
* - The previousValue argument is initialValue.
|
|
* - The currentValue argument is the value of the first element present in the array.
|
|
*
|
|
* If an initialValue is not provided:
|
|
* - The previousValue argument is the value of the first element present in the array.
|
|
* - The currentValue argument is the value of the second element present in the array.
|
|
*
|
|
* @callback lineReduceCallback
|
|
* @param {*} previousValue The accumulated value previously returned in the last invocation
|
|
* of the callback, or initialValue, if supplied.
|
|
* @param {Feature<LineString>} currentLine The current LineString|LinearRing being processed.
|
|
* @param {number} featureIndex The current index of the Feature being processed
|
|
* @param {number} multiFeatureIndex The current index of the Multi-Feature being processed
|
|
* @param {number} geometryIndex The current index of the Geometry being processed
|
|
*/
|
|
|
|
/**
|
|
* Reduce features in any GeoJSON object, similar to Array.reduce().
|
|
*
|
|
* @name lineReduce
|
|
* @param {Geometry|Feature<LineString|Polygon|MultiLineString|MultiPolygon>} geojson object
|
|
* @param {Function} callback a method that takes (previousValue, currentLine, featureIndex, multiFeatureIndex, geometryIndex)
|
|
* @param {*} [initialValue] Value to use as the first argument to the first call of the callback.
|
|
* @returns {*} The value that results from the reduction.
|
|
* @example
|
|
* var multiPoly = turf.multiPolygon([
|
|
* turf.polygon([[[12,48],[2,41],[24,38],[12,48]], [[9,44],[13,41],[13,45],[9,44]]]),
|
|
* turf.polygon([[[5, 5], [0, 0], [2, 2], [4, 4], [5, 5]]])
|
|
* ]);
|
|
*
|
|
* turf.lineReduce(multiPoly, function (previousValue, currentLine, featureIndex, multiFeatureIndex, geometryIndex) {
|
|
* //=previousValue
|
|
* //=currentLine
|
|
* //=featureIndex
|
|
* //=multiFeatureIndex
|
|
* //=geometryIndex
|
|
* return currentLine
|
|
* });
|
|
*/
|
|
function lineReduce(geojson, callback, initialValue) {
|
|
var previousValue = initialValue;
|
|
lineEach(geojson, function (currentLine, featureIndex, multiFeatureIndex, geometryIndex) {
|
|
if (featureIndex === 0 && initialValue === undefined) previousValue = currentLine;
|
|
else previousValue = callback(previousValue, currentLine, featureIndex, multiFeatureIndex, geometryIndex);
|
|
});
|
|
return previousValue;
|
|
}
|
|
|
|
/**
|
|
* Finds a particular 2-vertex LineString Segment from a GeoJSON using `@turf/meta` indexes.
|
|
*
|
|
* Negative indexes are permitted.
|
|
* Point & MultiPoint will always return null.
|
|
*
|
|
* @param {FeatureCollection|Feature|Geometry} geojson Any GeoJSON Feature or Geometry
|
|
* @param {Object} [options={}] Optional parameters
|
|
* @param {number} [options.featureIndex=0] Feature Index
|
|
* @param {number} [options.multiFeatureIndex=0] Multi-Feature Index
|
|
* @param {number} [options.geometryIndex=0] Geometry Index
|
|
* @param {number} [options.segmentIndex=0] Segment Index
|
|
* @param {Object} [options.properties={}] Translate Properties to output LineString
|
|
* @param {BBox} [options.bbox={}] Translate BBox to output LineString
|
|
* @param {number|string} [options.id={}] Translate Id to output LineString
|
|
* @returns {Feature<LineString>} 2-vertex GeoJSON Feature LineString
|
|
* @example
|
|
* var multiLine = turf.multiLineString([
|
|
* [[10, 10], [50, 30], [30, 40]],
|
|
* [[-10, -10], [-50, -30], [-30, -40]]
|
|
* ]);
|
|
*
|
|
* // First Segment (defaults are 0)
|
|
* turf.findSegment(multiLine);
|
|
* // => Feature<LineString<[[10, 10], [50, 30]]>>
|
|
*
|
|
* // First Segment of 2nd Multi Feature
|
|
* turf.findSegment(multiLine, {multiFeatureIndex: 1});
|
|
* // => Feature<LineString<[[-10, -10], [-50, -30]]>>
|
|
*
|
|
* // Last Segment of Last Multi Feature
|
|
* turf.findSegment(multiLine, {multiFeatureIndex: -1, segmentIndex: -1});
|
|
* // => Feature<LineString<[[-50, -30], [-30, -40]]>>
|
|
*/
|
|
function findSegment(geojson, options) {
|
|
// Optional Parameters
|
|
options = options || {};
|
|
if (!helpers.isObject(options)) throw new Error('options is invalid');
|
|
var featureIndex = options.featureIndex || 0;
|
|
var multiFeatureIndex = options.multiFeatureIndex || 0;
|
|
var geometryIndex = options.geometryIndex || 0;
|
|
var segmentIndex = options.segmentIndex || 0;
|
|
|
|
// Find FeatureIndex
|
|
var properties = options.properties;
|
|
var geometry;
|
|
|
|
switch (geojson.type) {
|
|
case 'FeatureCollection':
|
|
if (featureIndex < 0) featureIndex = geojson.features.length + featureIndex;
|
|
properties = properties || geojson.features[featureIndex].properties;
|
|
geometry = geojson.features[featureIndex].geometry;
|
|
break;
|
|
case 'Feature':
|
|
properties = properties || geojson.properties;
|
|
geometry = geojson.geometry;
|
|
break;
|
|
case 'Point':
|
|
case 'MultiPoint':
|
|
return null;
|
|
case 'LineString':
|
|
case 'Polygon':
|
|
case 'MultiLineString':
|
|
case 'MultiPolygon':
|
|
geometry = geojson;
|
|
break;
|
|
default:
|
|
throw new Error('geojson is invalid');
|
|
}
|
|
|
|
// Find SegmentIndex
|
|
if (geometry === null) return null;
|
|
var coords = geometry.coordinates;
|
|
switch (geometry.type) {
|
|
case 'Point':
|
|
case 'MultiPoint':
|
|
return null;
|
|
case 'LineString':
|
|
if (segmentIndex < 0) segmentIndex = coords.length + segmentIndex - 1;
|
|
return helpers.lineString([coords[segmentIndex], coords[segmentIndex + 1]], properties, options);
|
|
case 'Polygon':
|
|
if (geometryIndex < 0) geometryIndex = coords.length + geometryIndex;
|
|
if (segmentIndex < 0) segmentIndex = coords[geometryIndex].length + segmentIndex - 1;
|
|
return helpers.lineString([coords[geometryIndex][segmentIndex], coords[geometryIndex][segmentIndex + 1]], properties, options);
|
|
case 'MultiLineString':
|
|
if (multiFeatureIndex < 0) multiFeatureIndex = coords.length + multiFeatureIndex;
|
|
if (segmentIndex < 0) segmentIndex = coords[multiFeatureIndex].length + segmentIndex - 1;
|
|
return helpers.lineString([coords[multiFeatureIndex][segmentIndex], coords[multiFeatureIndex][segmentIndex + 1]], properties, options);
|
|
case 'MultiPolygon':
|
|
if (multiFeatureIndex < 0) multiFeatureIndex = coords.length + multiFeatureIndex;
|
|
if (geometryIndex < 0) geometryIndex = coords[multiFeatureIndex].length + geometryIndex;
|
|
if (segmentIndex < 0) segmentIndex = coords[multiFeatureIndex][geometryIndex].length - segmentIndex - 1;
|
|
return helpers.lineString([coords[multiFeatureIndex][geometryIndex][segmentIndex], coords[multiFeatureIndex][geometryIndex][segmentIndex + 1]], properties, options);
|
|
}
|
|
throw new Error('geojson is invalid');
|
|
}
|
|
|
|
/**
|
|
* Finds a particular Point from a GeoJSON using `@turf/meta` indexes.
|
|
*
|
|
* Negative indexes are permitted.
|
|
*
|
|
* @param {FeatureCollection|Feature|Geometry} geojson Any GeoJSON Feature or Geometry
|
|
* @param {Object} [options={}] Optional parameters
|
|
* @param {number} [options.featureIndex=0] Feature Index
|
|
* @param {number} [options.multiFeatureIndex=0] Multi-Feature Index
|
|
* @param {number} [options.geometryIndex=0] Geometry Index
|
|
* @param {number} [options.coordIndex=0] Coord Index
|
|
* @param {Object} [options.properties={}] Translate Properties to output Point
|
|
* @param {BBox} [options.bbox={}] Translate BBox to output Point
|
|
* @param {number|string} [options.id={}] Translate Id to output Point
|
|
* @returns {Feature<Point>} 2-vertex GeoJSON Feature Point
|
|
* @example
|
|
* var multiLine = turf.multiLineString([
|
|
* [[10, 10], [50, 30], [30, 40]],
|
|
* [[-10, -10], [-50, -30], [-30, -40]]
|
|
* ]);
|
|
*
|
|
* // First Segment (defaults are 0)
|
|
* turf.findPoint(multiLine);
|
|
* // => Feature<Point<[10, 10]>>
|
|
*
|
|
* // First Segment of the 2nd Multi-Feature
|
|
* turf.findPoint(multiLine, {multiFeatureIndex: 1});
|
|
* // => Feature<Point<[-10, -10]>>
|
|
*
|
|
* // Last Segment of last Multi-Feature
|
|
* turf.findPoint(multiLine, {multiFeatureIndex: -1, coordIndex: -1});
|
|
* // => Feature<Point<[-30, -40]>>
|
|
*/
|
|
function findPoint(geojson, options) {
|
|
// Optional Parameters
|
|
options = options || {};
|
|
if (!helpers.isObject(options)) throw new Error('options is invalid');
|
|
var featureIndex = options.featureIndex || 0;
|
|
var multiFeatureIndex = options.multiFeatureIndex || 0;
|
|
var geometryIndex = options.geometryIndex || 0;
|
|
var coordIndex = options.coordIndex || 0;
|
|
|
|
// Find FeatureIndex
|
|
var properties = options.properties;
|
|
var geometry;
|
|
|
|
switch (geojson.type) {
|
|
case 'FeatureCollection':
|
|
if (featureIndex < 0) featureIndex = geojson.features.length + featureIndex;
|
|
properties = properties || geojson.features[featureIndex].properties;
|
|
geometry = geojson.features[featureIndex].geometry;
|
|
break;
|
|
case 'Feature':
|
|
properties = properties || geojson.properties;
|
|
geometry = geojson.geometry;
|
|
break;
|
|
case 'Point':
|
|
case 'MultiPoint':
|
|
return null;
|
|
case 'LineString':
|
|
case 'Polygon':
|
|
case 'MultiLineString':
|
|
case 'MultiPolygon':
|
|
geometry = geojson;
|
|
break;
|
|
default:
|
|
throw new Error('geojson is invalid');
|
|
}
|
|
|
|
// Find Coord Index
|
|
if (geometry === null) return null;
|
|
var coords = geometry.coordinates;
|
|
switch (geometry.type) {
|
|
case 'Point':
|
|
return helpers.point(coords, properties, options);
|
|
case 'MultiPoint':
|
|
if (multiFeatureIndex < 0) multiFeatureIndex = coords.length + multiFeatureIndex;
|
|
return helpers.point(coords[multiFeatureIndex], properties, options);
|
|
case 'LineString':
|
|
if (coordIndex < 0) coordIndex = coords.length + coordIndex;
|
|
return helpers.point(coords[coordIndex], properties, options);
|
|
case 'Polygon':
|
|
if (geometryIndex < 0) geometryIndex = coords.length + geometryIndex;
|
|
if (coordIndex < 0) coordIndex = coords[geometryIndex].length + coordIndex;
|
|
return helpers.point(coords[geometryIndex][coordIndex], properties, options);
|
|
case 'MultiLineString':
|
|
if (multiFeatureIndex < 0) multiFeatureIndex = coords.length + multiFeatureIndex;
|
|
if (coordIndex < 0) coordIndex = coords[multiFeatureIndex].length + coordIndex;
|
|
return helpers.point(coords[multiFeatureIndex][coordIndex], properties, options);
|
|
case 'MultiPolygon':
|
|
if (multiFeatureIndex < 0) multiFeatureIndex = coords.length + multiFeatureIndex;
|
|
if (geometryIndex < 0) geometryIndex = coords[multiFeatureIndex].length + geometryIndex;
|
|
if (coordIndex < 0) coordIndex = coords[multiFeatureIndex][geometryIndex].length - coordIndex;
|
|
return helpers.point(coords[multiFeatureIndex][geometryIndex][coordIndex], properties, options);
|
|
}
|
|
throw new Error('geojson is invalid');
|
|
}
|
|
|
|
exports.coordEach = coordEach;
|
|
exports.coordReduce = coordReduce;
|
|
exports.propEach = propEach;
|
|
exports.propReduce = propReduce;
|
|
exports.featureEach = featureEach;
|
|
exports.featureReduce = featureReduce;
|
|
exports.coordAll = coordAll;
|
|
exports.geomEach = geomEach;
|
|
exports.geomReduce = geomReduce;
|
|
exports.flattenEach = flattenEach;
|
|
exports.flattenReduce = flattenReduce;
|
|
exports.segmentEach = segmentEach;
|
|
exports.segmentReduce = segmentReduce;
|
|
exports.lineEach = lineEach;
|
|
exports.lineReduce = lineReduce;
|
|
exports.findSegment = findSegment;
|
|
exports.findPoint = findPoint;
|
|
|