Spaghetti Source logo

可視グラフ

説明

注目頂点のリストと障害物のリストが与えられたとき,次のグラフを作成する.

このように,見える頂点対に辺を張ったグラフのことを可視グラフという.二次元平面上の二点間最短経路は,可視グラフ上の最短経路と一致する.

計算量

O(n^3).

TODO

ソースコード

#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]
bool block_off(const point &a, const point &b, const polygon &obj) {
  point m = (a+b)/2.0;
  bool on = false, in = false;
  for (int j = 0; j < obj.size(); ++j) {
    point c = curr(obj,j), d = next(obj,j);
    if (imag(d) < imag(c)) swap(c, d);
    if (cross(a-c,b-c) * cross(a-d,b-d) < 0 &&    // strictly intersect.
        cross(c-a,d-a) * cross(c-b,d-b) < 0) return true;
    if (cross(a-c,b-c) == 0 && dot(a-c,b-c) < 0) return true;
    if (imag(c) <= imag(m) && imag(m) < imag(d))  // strictly contain.
      if (cross(c-m,d-m) < 0) in = !in;
    if (cross(c-m,d-m) == 0 && dot(c-m,d-m) <= 0) on = true;
  }
  return !on && in;
}
graph visibility_graph(const vector<point> &pt,
    const vector<polygon> &objs) {
  graph g(pt.size());
  for (int i = 0; i < pt.size(); ++i) {
    for (int j = i+1; j < pt.size(); ++j) {
      for (int k = 0; k < objs.size(); ++k)
        if (block_off(pt[i], pt[j], objs[k])) goto SKIP;
      g[i].push_back( edge(i, j, abs(pt[i]-pt[j])) );
      g[j].push_back( edge(j, i, abs(pt[i]-pt[j])) );
SKIP:;
    }
  }
  return g;
}

Verified

前原 貴憲(maehara@prefield.com).

Last Modified: 2006.12.11 08:46:28.