アルゴリズムが正しくなかったため、アルゴリズムを変更しました。今回はすべてのケースをカバーすることを願っています!。
反射aから始めて、次の頂点をa'とし、辺a 'でa --a'と交差するエッジが見つかるまでポリゴンをたどり、bをこのエッジと線a--aとの交点とします。 'およびcエッジの終点(a--cの右側の終点)。
次に、ポリゴンのエッジを通過し続けます。エッジがセグメントa--bと左から右に交差する場合は、 bを新しい交点に設定し、 cを終了頂点に設定します。終了すると、三角形a--b--cができます。ここで、 cからやり直して、すべての頂点を調べて、三角形a--b--cの内側にあるかどうかを確認します。その場合は、cを新しい頂点に設定します。最後に、a--cはポリゴンの対角線です。
これは、反射点aが次の場所にあることを前提としたCでの実装ですP[0]
。
struct pt {
double x,y;
friend pt operator+(pt a, pt b){a.x+=b.x; a.y+=b.y; return a;}
friend pt operator-(pt a, pt b){a.x-=b.x; a.y-=b.y; return a;}
friend pt operator*(pt a, double k){a.x*=k; a.y*=k; return a;}
bool leftof(pt a, pt b) const{
// returns true if the *this point is left of the segment a--b.
return (b.x-a.x)*(y-a.y) - (x-a.x)*(b.y-a.y) > 0;
}
};
pt intersect(pt a, pt b, pt c, pt d){// (see O'rourke p.222)
double s,t, denom;
denom = (a.x-b.x)*(d.y-c.y)+ (d.x-c.x)*(b.y-a.y);
s = ( a.x*(d.y-c.y)+c.x*(a.y-d.y)+d.x*(c.y-a.y) )/denom;
return a + (b-a)*s;
}
/**
P is a polygon, P[0] is a reflex (the inside angle at P[0] is > pi).
finds a vertex t such that P[0]--P[t] is a diagonal of the polygon.
**/
int diagonal( vector<pt> P ){
pt a = P[0], b = P[1]; //alias
int j=2;
if( !b.leftof(a,P[j]) ){
// find first edge cutting a--b to the right of b
for(int k = j+1; k+1 < int(P.size()); ++k)
if( P[k].leftof(a,b) && P[k+1].leftof(b,a) && b.leftof(P[k+1],P[k]) )
j = k,
b = intersect( a,b,P[k],P[k+1] );
// find nearest edge cutting the segment a--b
for(int k = j+1; k+1 < int(P.size()); ++k)
if( P[k].leftof(a,b) && P[k+1].leftof(b,a) &&
a.leftof(P[k+1],P[k]) && b.leftof(P[k],P[k+1]) ){
b = intersect( a,b,P[k],P[k+1] );
j = k+1;
}
}
for(int k = j+1; k+1 < int(P.size()); ++k)
if( P[k].leftof(a,b) && P[k].leftof(b,P[j]) && P[k].leftof(P[j],a) )
j = k;
return j;
}