1. 程式人生 > 其它 >js根據座標判斷構成單個多邊形是否合法

js根據座標判斷構成單個多邊形是否合法

安裝

npm install  @turf/helpers  @turf/line-intersect

程式碼


/**
 * 幾何工具庫
 * @author maybe
 * @license https://gitee.com/null_639_5368
 */
import * as  turf from "@turf/helpers"
import lineIntersect from "@turf/line-intersect"
/**
 * 座標轉線段
 * @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;
}
/**
 * 判斷座標組成的單個多邊形是否合法
 * @param {*} path 
 * @description 請傳入[[1,2],[2,2],[3,3]] 類似的二維陣列 
 * @returns {boolean}
 */
export function isTruePolygon (path) {
  //  判斷陣列且陣列的長度小於3不構成滿足一個面的必要條件終止
  if (!Array.isArray(path) || path.length < 3) return false;
  //  具體座標也需是一個一維陣列,並且陣列的長度等於2
  if (!path.every(item => Array.isArray(item) && item.length == 2)) return false;

  // 將座標轉成線段
  const lines = pathToLines(path);
  // 是否合法標誌
  let isTrue = true;
  // 驗證函式
  function check () {
    // 倒序迴圈
    for (let i = lines.length - 1; i >= 0; i--) {
      // 基準線段
      const line1 = lines[i];
      // 依次判斷
      for (let j = i - 1; j >= 0; j--) {
        const line2 = lines[j];
        // 判斷是否相交
        const lt = lineIntersect(line1, line2)
        // console.log(JSON.stringify(lt.features.length > 0 ? '相交' : '不相交'))
        // 如果是相鄰的一根線段,判斷是否有交點且交點是否在端點上,如果是最後一根線段為基準線段那麼和第一根線段也將相鄰在端點才合法
        if (j == i - 1 || (i == lines.length - 1 && j == 0)) {
          // 判斷交點是否在端點上
          const coordinates = line1.geometry.coordinates;
          const ltCoordinates = lt.features.length > 0 && lt.features[0].geometry.coordinates
          const isEndpoint = coordinates.find(p => p[0] == ltCoordinates[0] && p[1] == ltCoordinates[1]);
          // console.log(lt.features[0].geometry.coordinates);
          if (!isEndpoint) {
            isTrue = false;
            // console.log('相鄰線段非端點不合法')
            return;
          } else {
            // console.log('相鄰線段合法')
          }
        } else {
          if (lt.features.length > 0) {
            isTrue = false;
            // console.log('非相鄰線段相交不合法')
            return;
          } else {
            // console.log('非相鄰線段合法')
          }
        }
      }
    }
  }
  check();
  isTrue ? console.info('多邊形合法') : console.log("多邊形不合法")
  return isTrue;

}
export default {
  pathToLines,
  isTruePolygon,
}

測試

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