js實現凸包問題

背景:

地圖上給出若干個點,求出這些點圍繞的最大面積,並按順序排列。

原理:
暴力枚舉,由反證法得x軸最小的值一定是圍繞的邊界點,將其作爲起點,在尋找下一個點符合其餘的點均在這兩個點構成直線的一側。最後回到初始點時返回。

向量和點關係算法:

S(P1,P2,P3)=|y1 y2 y3|= (x1-x3)*(y2-y3)-(y1-y3)*(x2-x3)

當P1P2P3逆時針時S爲正的,當P1P2P3順時針時S爲負的。

因爲座標經度需求大,爲了精確計算使用了函數實現四則運算。

function mul(a, b) {
  var c = 0,
    d = a.toString(),
    e = b.toString();
  try {
    c += d.split(".")[1].length;
  } catch (f) {}
  try {
    c += e.split(".")[1].length;
  } catch (f) {}
  return (
    (Number(d.replace(".", "")) * Number(e.replace(".", ""))) / Math.pow(10, c)
  );
}
function sub(a, b) {
  var c, d, e;
  try {
    c = a.toString().split(".")[1].length;
  } catch (f) {
    c = 0;
  }
  try {
    d = b.toString().split(".")[1].length;
  } catch (f) {
    d = 0;
  }
  return (e = Math.pow(10, Math.max(c, d))), (mul(a, e) - mul(b, e)) / e;
}

輸入數據結構示例:
lines[{x:"123",y:"456"},{x:"123",y:"456"}]

具體實現:

 //範圍算法
    ConvexHull(lines) {
      //排序去重
      for (let i = 0; i < lines.length; i++) {
        for (let j = 0; j < lines.length - i - 1; j++) {
          if (lines[j].x > lines[j + 1].x) {
            let tamp = lines[j];
            lines[j] = lines[j + 1];
            lines[j + 1] = tamp;
          }
          if (lines[j].x == lines[j + 1].x && lines[j].y == lines[j + 1].y) {
            lines.splice(j + 1, 1);
            j--;
          }
        }
      }
      let result = [];
      let index = 1;
      result.push(lines[0]);
      while (true) {
        let point = this.findNext(lines, result[index - 2], result[index - 1]);
        if (point == null) break;
        result.push(point);
        if (point.x == lines[0].x && point.y == lines[0].y) {
          break;
        }
        if (index > lines.length + 2) {
          break;
        }
        index++;
      }
      return result;
    },
   findNext(lines, start, node) {
      for (let i = 0; i < lines.length; i++) {
        if (start != null && start.x == lines[i].x && start.y == lines[i].y) {
          continue;
        }
        if (node != null && node.x == lines[i].x && node.y == lines[i].y) {
          continue;
        }
        let search = true;
        let target = -9999;
        for (let j = 0; j < lines.length; j++) {
          if (i == j) continue;
          if (node != null && node.x == lines[j].x && node.y == lines[j].y) {
            continue;
          }
          let left =
            sub(node.x, lines[j].x) * sub(lines[i].y, lines[j].y) -
              sub(node.y, lines[j].y) * sub(lines[i].x, lines[j].x) >
            0
              ? true
              : false;
          if (target == -9999) {
            target = left;
          }
          if (left != target) {
            search = false;
            break;
          }
        }
        if (search == true) {
          return lines[i];
        }
      }
    },

 

發佈了15 篇原創文章 · 獲贊 0 · 訪問量 2451
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章