http://www.cnblogs.com/carekee/articles/1877575.html
2.2.1下面開始程序的設計:
由於本部分需要判斷空間多邊形的拓撲關系,現在約定凸多邊形的邊界和內部,凸多邊形用頂點坐標的逆時針方向序列確定。凸多邊形P Q 的頂點序列為 p1 p2 ..pn 和q1 q2 …qn 。為了簡單,假設P邊界上不包含Q的頂點,Q的邊界上不包含P的頂點。這使得P 和Q或者完全分離,或者重疊而交出一個新的凸多邊形。(這是我對本部分的初步設計。)
程序部分:
struct point
{
double x,y;
bool operator !=(point& p){return ((x!=p.x)||(y!=p.y));}
};
定義點的存儲結構同時根據需要重載了operator !=。
然後是主類實現拓撲關系判斷。此外還有兩個輔助類dotline.h ,LineIntersect.h分別實現點線判斷,兩線段相交求交點,為主類提供相應的輔助功能。
Yolk.h(主類)
class ConvexPolyIntersection
{
private:
point R;
void output(double ,double);
void advance();頂點前進程序部分
point *p,*q;
int il,jl,i,j,onlyonce;
dot inst1;
Intersect inst2;
public:
ConvexPolyIntersection(int itmp,int jtmp);求交集函數部分。
int intersection(int tab);
void printRelate();
~ConvexPolyIntersection(){delete p;delete q;inst1.~dot();inst2.~Intersect();}
};
為了有次序地求出交點,可以在兩個多邊形上交替的前進,原則是在哪個多邊形的邊上可能有交點就等待,在另一個多邊形的邊上前進。如果兩個凸多邊形相交,本程序可以精確的輸出交得的新凸多邊形的坐標。並且已經具備了一定的拓撲關系判斷能力,可是由於程序在設計之前添加了很多苛刻限制,使得程序不能很好的判斷EQ 和相切關系。但是基本的分明蛋黃RCC5 程序已經完成。
難點問題解決
主要難點是判斷多邊形頂點前進的方法,規定P0=P1 Q0=Q1 ,接下來在哪個多邊形上前進,需要區分8種情況,其中前四種和後四種是P 和Q的地位對調。如圖
情形 |
(1) |
(2) |
(3) |
(4) |
(5) |
(6) |
(7) |
(8) |
Pi在Qi-1Qi |
左 |
左 |
右 |
右 |
右 |
左 |
右 |
左 |
Qi在Pi-1Pi |
左 |
左 |
右 |
左 |
左 |
左 |
右 |
右 |
安排在那個多邊形前進 |
Q |
P |
Q |
P |
P |
Q |
P |
Q |
這樣完成了理論部分。
本來我認為完成上面的程序就已經大功告成,可是我發現他不遵守RCC標准,即沒有求三原謂詞P, C和I,雖然程序在改進後可以完全實現RCC5拓撲判斷功能,但是已經無法直接求取三原謂詞P, C和I了。因為程序中關於三原謂詞P ,C 和I的理解發生了偏差,程序中是按照相交為P考慮的,即求出交集p=true。而當C=true 時 P並不為真,他僅僅關注邊和點,而理論中應該是關注邊所圍成的面積。P是C的一部分。所以將對程序進行改寫。
由於下面將繼續使用點線判斷類,所以對此類的實現進行詳細介紹:
dotline.h(注意這裡直線是有方向性的)
怎麼判斷坐標為(xp,yp)的點P是在直線的哪一側呢?設直線是由其上兩點(x1,y1)(x2,y2)確定的,直線方向是由(x1,y1)到(x2,y2)的方向。這時若直線方程記為Ax+By+C=0
則有:
A=y2-y1; B=x1-x2; C=x2*y1-x1*y2;
這時可以計算D:
D=A*xp+B*yp+C
若D<0,則點(xp,yp)在直線的左側;若D>0,則點在直線的右側;D=0點在直線上。
接下來將實現真正的RCC5程序。在原有程序的實踐基礎上,求三原謂詞P ,C 和I 關系實際上就是求凸多邊形的邊界頂點與另一個凸多邊形的位置關系。
即:
P(x,y)只要有凸多邊形x或y 的一個頂點在凸多邊形 y 或x 內,說明x,y 有相交部分(即,面積有重合部分),P=true 否則 P=false。
C (x,y) 凸多邊形y 的所有頂點都在凸多邊形x 中或上, c=true,否則 c=false。
I (x,y)與C (x,y)同理。
這樣就減少了設計的復雜性,同時相切問題也會得到解決,即主要注意「點線」關系,就可以很好的判斷各種關系。
難點問題解決:
這樣程序的焦點就都集中在一個功能齊全的點與線段關系判斷類上。此類首先能判斷點與線段所在直線的位置關系(點在直線左側;點在直線右側 ;點在直線上),當點在直線上時,進一步判斷點與線段的關系,在線段上(在線段端點上 或 不在),在線段外。
本程序將繼承 dotline.h
實現Superdotline.h
#include」dotline.h」/*頭文件*/
class SuperDot: public dot
{
public:
SuperDot(){}
SuperDot(double xp1,double yp1,double x11,double y11,double x22,double y22):dot(xp1, yp1,x11,y11,x22,y22){}
~SuperDot(){}
int judgeDeeply();/*此函數返回點線關系結果*/
};
/*
點線關系 :
1 在線段左側 -- 點在凸多邊形 內部 是點在直線的公共左側
0 在線段右側
2 點在線段外
3 點與線段端點重合
4 點在線段上
*/
其中 輸出結果為 3 4 時,是為RCC8 程序准備的。此程序由於是對dotline.h的擴展,所以函數數量較少。
完成點線關系判斷後,實現RCC5判斷
實現yolk1.h (在yolk.h 的基礎上對其進行標准RCC5 重寫 求三原謂詞P ,C和I)
本程序繼承了yolk.h的優點,使用指針存儲點結構(對頂點數沒有限制)。
class yolk :public SuperDot
{
proteced:
point *p,*q;
int il,jl,i,j;
bool P,C,I;
void relateRcc();/* 求P C I*/
yolk(){}
public:
yolk(int itmp,int jtmp);
~yolk(){delete p;delete q;}
void printRelate();
};
算法設計:
此類的焦點集中在relateRcc()函數上。他對矢量數據進行兩次掃描判斷三原謂詞P,C和I。以「點 、凸多邊形」拓撲關系為基礎。如當其中一個凸多邊形的端點在另一個的內部時,可以判斷P=true.