# Voronoi泰森多边形的实现

### 凸包算法

    graham() {
let vs = this.children.filter(e=>e.getClass() == "Vertex");
// find p0-y vectex
let p0 = vs[0];

for (let v of vs) {
if ( (v.y < p0.y) || (v.y==p0.y && v.x<p0.x))
p0 = v;
}

vs.sort(function(a,b) {
let d1 = Math.atan2( a.y-p0.y , a.x-p0.x ) * (180 / Math.PI);
if (d1 < 0) d1 += 180;

let d2 = Math.atan2( b.y-p0.y , b.x-p0.x ) * (180 / Math.PI);
if (d2 < 0) d2 += 180;

if (d1 < d2)
return -1;
else if (d1 > d2)
return 1;
else {
p0.getDistance(a) - p0.getDistance(b) > 0 ? 1 : -1;
}
});

let ps = [].concat(vs);

let stack = new Array(ps.shift(), ps.shift());
for (let current of ps) {

let d;
do {
let top = stack.peek();
let sec = stack[stack.length-2];

let line = Line.TwoPoint(sec,top);
d = line.position(current);

if (d>0)
top = stack.pop();

} while (d > 0);

stack.push(current);
}
}

### 德洛内三角

    DelaunayBowyer() {
let indices = this.children
.filter(e=>e.getClass() == "Vertex")
.sort((a,b)=>{
return a.x == b.x ? 0 : (a.x < b.x ? -1 : 1);
});

let maxx = 0, maxy = 0, minx = Number.MAX_SAFE_INTEGER, miny = Number.MAX_SAFE_INTEGER;
indices.forEach(v=>{
if (v.x < minx) minx = v.x;
if (v.x > maxx) maxx = v.x;
if (v.y < miny) miny = v.y;
if (v.y > maxy) maxy = v.y;
});
let r = new Rectangle(new Point(minx, miny), new Point(maxx, maxy));
let supert = Triangle.ExternalTriangleFromRectangle(r);

let vs = indices.concat([ supert.p0, supert.p1, supert.p2 ]);
let ts =[ supert ];
for (let v of vs) {

let edge = new CountArray();
let i = ts.length - 1;
while (i>=0) {
let t = ts[i--];
let c = Circle.Circumcircle(t);

let position = c.test(v);
if (position == "out") {
continue ;
}
else {
edge.push(new Pair(t.p0, t.p1));
edge.push(new Pair(t.p1, t.p2));
edge.push(new Pair(t.p2, t.p0));
ts.remove(t);
}
}

let nedge = edge.getArray();
for (let i=0; i<nedge.length; i++) {
if (v.equals(nedge[i].v1) || v.equals(nedge[i].v2) || nedge[i].v1.equals(nedge[i].v2)) {
continue ;
}
let t = new Triangular(v, nedge[i].v1, nedge[i].v2);
ts.push(t);
}

}

for (let i=ts.length-1; i>=0; i--) {
let t = ts[i];

if (t.p0.getClass() == "Point" || t.p1.getClass() == "Point" || t.p2.getClass() == "Point") {
ts.remove(t);
continue ;
}

this.children.push(t);
}

return ts;
}

    Voronoi() {

let vs = this.children.filter(e=>e.getClass() == "Vertex");
let ts = this.children.filter(e=>e.getClass() == "Triangular");

let gl = [];

for (let v of vs) {

let bounds = [];
for (let t of ts)
if (t.p0 == v || t.p1 == v || t.p2 == v)
bounds.push(t);

let sort = [];
let e = bounds[0].exclude(v)[0];
let t;

while (bounds.length > 0) {

let bFound = false;
for (t of bounds) {
if (t.hasEdge(v, e)) {
e = t.exclude(v, e)[0];
bFound = true;
break;
}
}

if (bFound) {
bounds.remove(t);
sort.push(t);
}
else {
break ;
}

}

if (bounds.length == 0)
gl.push(sort);

}

for (let g of gl) {

let cps = [];
for (let s of g) {
let c = Circle.Circumcircle(s);
if (c.x <= 0 && c.y <= 0)
return ;
cps.push(c.p);
}

let p = new Path(cps);
this.children.push(p);

}

}

• 0
点赞
• 4
收藏
• 打赏
• 1
评论
03-15
12-14
05-08 2783
09-04 8万+
11-03 1万+
06-19 1万+
09-02 3万+
03-21
03-24
01-08 2540
04-30
11-11 2291

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

vcshcn

¥2 ¥4 ¥6 ¥10 ¥20

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、C币套餐、付费专栏及课程。