| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 | "use strict";Object.defineProperty(exports, "__esModule", { value: true });var helpers_1 = require("@turf/helpers");var invariant_1 = require("@turf/invariant");// To-Do => Improve Typescript GeoJSON handling/** * Removes redundant coordinates from any GeoJSON Geometry. * * @name cleanCoords * @param {Geometry|Feature} geojson Feature or Geometry * @param {Object} [options={}] Optional parameters * @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated * @returns {Geometry|Feature} the cleaned input Feature/Geometry * @example * var line = turf.lineString([[0, 0], [0, 2], [0, 5], [0, 8], [0, 8], [0, 10]]); * var multiPoint = turf.multiPoint([[0, 0], [0, 0], [2, 2]]); * * turf.cleanCoords(line).geometry.coordinates; * //= [[0, 0], [0, 10]] * * turf.cleanCoords(multiPoint).geometry.coordinates; * //= [[0, 0], [2, 2]] */function cleanCoords(geojson, options) {    if (options === void 0) { options = {}; }    // Backwards compatible with v4.0    var mutate = typeof options === "object" ? options.mutate : options;    if (!geojson)        throw new Error("geojson is required");    var type = invariant_1.getType(geojson);    // Store new "clean" points in this Array    var newCoords = [];    switch (type) {        case "LineString":            newCoords = cleanLine(geojson);            break;        case "MultiLineString":        case "Polygon":            invariant_1.getCoords(geojson).forEach(function (line) {                newCoords.push(cleanLine(line));            });            break;        case "MultiPolygon":            invariant_1.getCoords(geojson).forEach(function (polygons) {                var polyPoints = [];                polygons.forEach(function (ring) {                    polyPoints.push(cleanLine(ring));                });                newCoords.push(polyPoints);            });            break;        case "Point":            return geojson;        case "MultiPoint":            var existing = {};            invariant_1.getCoords(geojson).forEach(function (coord) {                var key = coord.join("-");                if (!Object.prototype.hasOwnProperty.call(existing, key)) {                    newCoords.push(coord);                    existing[key] = true;                }            });            break;        default:            throw new Error(type + " geometry not supported");    }    // Support input mutation    if (geojson.coordinates) {        if (mutate === true) {            geojson.coordinates = newCoords;            return geojson;        }        return { type: type, coordinates: newCoords };    }    else {        if (mutate === true) {            geojson.geometry.coordinates = newCoords;            return geojson;        }        return helpers_1.feature({ type: type, coordinates: newCoords }, geojson.properties, {            bbox: geojson.bbox,            id: geojson.id,        });    }}/** * Clean Coords * * @private * @param {Array<number>|LineString} line Line * @returns {Array<number>} Cleaned coordinates */function cleanLine(line) {    var points = invariant_1.getCoords(line);    // handle "clean" segment    if (points.length === 2 && !equals(points[0], points[1]))        return points;    var newPoints = [];    var secondToLast = points.length - 1;    var newPointsLength = newPoints.length;    newPoints.push(points[0]);    for (var i = 1; i < secondToLast; i++) {        var prevAddedPoint = newPoints[newPoints.length - 1];        if (points[i][0] === prevAddedPoint[0] &&            points[i][1] === prevAddedPoint[1])            continue;        else {            newPoints.push(points[i]);            newPointsLength = newPoints.length;            if (newPointsLength > 2) {                if (isPointOnLineSegment(newPoints[newPointsLength - 3], newPoints[newPointsLength - 1], newPoints[newPointsLength - 2]))                    newPoints.splice(newPoints.length - 2, 1);            }        }    }    newPoints.push(points[points.length - 1]);    newPointsLength = newPoints.length;    if (equals(points[0], points[points.length - 1]) && newPointsLength < 4)        throw new Error("invalid polygon");    if (isPointOnLineSegment(newPoints[newPointsLength - 3], newPoints[newPointsLength - 1], newPoints[newPointsLength - 2]))        newPoints.splice(newPoints.length - 2, 1);    return newPoints;}/** * Compares two points and returns if they are equals * * @private * @param {Position} pt1 point * @param {Position} pt2 point * @returns {boolean} true if they are equals */function equals(pt1, pt2) {    return pt1[0] === pt2[0] && pt1[1] === pt2[1];}/** * Returns if `point` is on the segment between `start` and `end`. * Borrowed from `@turf/boolean-point-on-line` to speed up the evaluation (instead of using the module as dependency) * * @private * @param {Position} start coord pair of start of line * @param {Position} end coord pair of end of line * @param {Position} point coord pair of point to check * @returns {boolean} true/false */function isPointOnLineSegment(start, end, point) {    var x = point[0], y = point[1];    var startX = start[0], startY = start[1];    var endX = end[0], endY = end[1];    var dxc = x - startX;    var dyc = y - startY;    var dxl = endX - startX;    var dyl = endY - startY;    var cross = dxc * dyl - dyc * dxl;    if (cross !== 0)        return false;    else if (Math.abs(dxl) >= Math.abs(dyl))        return dxl > 0 ? startX <= x && x <= endX : endX <= x && x <= startX;    else        return dyl > 0 ? startY <= y && y <= endY : endY <= y && y <= startY;}exports.default = cleanCoords;
 |