preface

Need: Judge whether the fence drawn by the user is legal in Amap.

Core solution point: judge in reverse order if it is two adjacent line segments, judge whether there is an intersection, non-adjacent line segments do not intersect.

The installation

npm install  @turf/helpers  @turf/line-intersect
Copy the code

code

/** * geometric *@author maybe
 * @license https://gitee.com/null_639_5368
 */
import * as  turf from "@turf/helpers"
import lineIntersect from "@turf/line-intersect"
/** * coordinate rotation segment *@param {*} path 
 * @returns {arr}* /
export function pathToLines(path) {
    const lines = [];

    path.forEach((p, pi) = > {
        let line;
        if (pi == path.length - 1) {
            line = turf.lineString([path[pi], path[0]]);
            lines.push(line)
            return;
        }
        line = turf.lineString([path[pi], path[pi + 1]]);
        lines.push(line)
    })
    // console.log(JSON.stringify(lines))
    return lines;
}
/** * Determine if a single polygon consisting of coordinates is valid *@param {*} path 
 * @description Please pass in a two-dimensional array like [[1,2],[2,2],[3,3]] *@returns {boolean}* /
export function isTruePolygon(path) {
    // Determine the array and the length of the array is less than 3 does not constitute a necessary termination of a face
    if (!Array.isArray(path) || path.length < 3) return false;
    // The coordinates should also be a one-dimensional array with a length equal to 2
    if(! path.every(item= > Array.isArray(item) && item.length == 2)) return false;

    // Convert coordinates to line segments
    const lines = pathToLines(path);
    // Whether the flag is valid
    let isTrue = true;
    // Validate the function
    function check() {
        // reverse loop
        for (let i = lines.length - 1; i >= 0; i--) {
            // Set the base line
            const line = lines[i];
            const lineNextIndex = i == 0 ? lines.length - 1 : i - 1;
            const lineLastIndex = i == lines.length - 1 ? 0 : i + 1;
            const lineNext = lines[lineNextIndex];
            const lineLast = lines[lineLastIndex];
            // Two adjacent lines must intersect
            if(! isIntersect(line, lineNext) || ! isIntersect(line, lineLast) ) {console.log('Two adjacent line segments must intersect.', line, lineNext, lineLast, isIntersect(line, lineNext), isIntersect(line, lineLast))
                isTrue = false;
                return;
            }
            // Non-adjacent line segments must have no intersection
            const noNearLines = lines.filter((item, i) = >i ! == lineNextIndex && i ! == lineLastIndex); noNearLines.forEach(le= > {
                if (isIntersect(line, le)) {
                    console.log('Non-adjacent line segments must have no intersection')
                    isTrue = false;
                    return;
                }
            })
        }
    }
    check();
    isTrue ? console.info('Polygon legal') : console.log("Polygons are illegal")
    return isTrue;

}

function isIntersect(line1, line2) {
    return lineIntersect(line1, line2).features.length > 0;
}
export default {
    pathToLines,
    isTruePolygon,
}
Copy the code

test

import { isTruePolygon } from './geometric'
const path_false = [
    [116.403322.39.920255],
    [116.385726.39.909893],
    [116.410703.39.897555],
    [116.402292.39.892353],
    [116.389846.39.891365]]const path_true = [
    [116.403322.39.920255],
    [116.410703.39.897555],
    [116.402292.39.892353],
    [116.389846.39.891365]]console.log(isTruePolygon(path_true)); // true
console.log(isTruePolygon(path_false)); // false
Copy the code