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