| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 | import { point } from "@turf/helpers";/** * Takes a {@link LineString|linestring}, {@link MultiLineString|multi-linestring}, * {@link MultiPolygon|multi-polygon} or {@link Polygon|polygon} and * returns {@link Point|points} at all self-intersections. * * @name kinks * @param {Feature<LineString|MultiLineString|MultiPolygon|Polygon>} featureIn input feature * @returns {FeatureCollection<Point>} self-intersections * @example * var poly = turf.polygon([[ *   [-12.034835, 8.901183], *   [-12.060413, 8.899826], *   [-12.03638, 8.873199], *   [-12.059383, 8.871418], *   [-12.034835, 8.901183] * ]]); * * var kinks = turf.kinks(poly); * * //addToMap * var addToMap = [poly, kinks] */export default function kinks(featureIn) {    var coordinates;    var feature;    var results = {        type: "FeatureCollection",        features: [],    };    if (featureIn.type === "Feature") {        feature = featureIn.geometry;    }    else {        feature = featureIn;    }    if (feature.type === "LineString") {        coordinates = [feature.coordinates];    }    else if (feature.type === "MultiLineString") {        coordinates = feature.coordinates;    }    else if (feature.type === "MultiPolygon") {        coordinates = [].concat.apply([], feature.coordinates);    }    else if (feature.type === "Polygon") {        coordinates = feature.coordinates;    }    else {        throw new Error("Input must be a LineString, MultiLineString, " +            "Polygon, or MultiPolygon Feature or Geometry");    }    coordinates.forEach(function (line1) {        coordinates.forEach(function (line2) {            for (var i = 0; i < line1.length - 1; i++) {                // start iteration at i, intersections for k < i have already                // been checked in previous outer loop iterations                for (var k = i; k < line2.length - 1; k++) {                    if (line1 === line2) {                        // segments are adjacent and always share a vertex, not a kink                        if (Math.abs(i - k) === 1) {                            continue;                        }                        // first and last segment in a closed lineString or ring always share a vertex, not a kink                        if (                        // segments are first and last segment of lineString                        i === 0 &&                            k === line1.length - 2 &&                            // lineString is closed                            line1[i][0] === line1[line1.length - 1][0] &&                            line1[i][1] === line1[line1.length - 1][1]) {                            continue;                        }                    }                    var intersection = lineIntersects(line1[i][0], line1[i][1], line1[i + 1][0], line1[i + 1][1], line2[k][0], line2[k][1], line2[k + 1][0], line2[k + 1][1]);                    if (intersection) {                        results.features.push(point([intersection[0], intersection[1]]));                    }                }            }        });    });    return results;}// modified from http://jsfiddle.net/justin_c_rounds/Gd2S2/light/function lineIntersects(line1StartX, line1StartY, line1EndX, line1EndY, line2StartX, line2StartY, line2EndX, line2EndY) {    // if the lines intersect, the result contains the x and y of the    // intersection (treating the lines as infinite) and booleans for whether    // line segment 1 or line segment 2 contain the point    var denominator;    var a;    var b;    var numerator1;    var numerator2;    var result = {        x: null,        y: null,        onLine1: false,        onLine2: false,    };    denominator =        (line2EndY - line2StartY) * (line1EndX - line1StartX) -            (line2EndX - line2StartX) * (line1EndY - line1StartY);    if (denominator === 0) {        if (result.x !== null && result.y !== null) {            return result;        }        else {            return false;        }    }    a = line1StartY - line2StartY;    b = line1StartX - line2StartX;    numerator1 = (line2EndX - line2StartX) * a - (line2EndY - line2StartY) * b;    numerator2 = (line1EndX - line1StartX) * a - (line1EndY - line1StartY) * b;    a = numerator1 / denominator;    b = numerator2 / denominator;    // if we cast these lines infinitely in both directions, they intersect here:    result.x = line1StartX + a * (line1EndX - line1StartX);    result.y = line1StartY + a * (line1EndY - line1StartY);    // if line1 is a segment and line2 is infinite, they intersect if:    if (a >= 0 && a <= 1) {        result.onLine1 = true;    }    // if line2 is a segment and line1 is infinite, they intersect if:    if (b >= 0 && b <= 1) {        result.onLine2 = true;    }    // if line1 and line2 are segments, they intersect if both of the above are true    if (result.onLine1 && result.onLine2) {        return [result.x, result.y];    }    else {        return false;    }}
 |