www.51voa.com
www.cnn.com
為什么會出現select模型?
先看一下下面的這句代碼:
int iResult = recv(s, buffer,1024);
這是用來接收數據的,在默認的阻塞模式下的套接字里,recv會阻塞在那里,直到套接字連接上有數據可讀,把數據讀到buffer里后recv函數才會返
回,不然就會一直阻塞在那里。在單線程的程序里出現這種情況會導致主線程(單線程程序里只有一個默認的主線程)被阻塞,這樣整個程序被鎖死在這里,如果永
遠沒數據發送過來,那么程序就會被永遠鎖死。這個問題可以用多線程解決,但是在有多個套接字連接的情況下,這不是一個好的選擇,擴展性很差。
再看代碼:
int iResult = ioctlsocket(s, FIOBIO, (unsigned long *)&ul);
iResult = recv(s, buffer,1024);
這一次recv的調用不管套接字連接上有沒有數據可以接收都會馬上返回。原因就在于我們用ioctlsocket把套接字設置為非阻塞模式了。不過 你跟蹤 一下就會發現,在沒有數據的情況下,recv確實是馬上返回了,但是也返回了一個錯誤:WSAEWOULDBLOCK,意思就是請求的操作沒有成功完成。 看到這里很多人可能會說,那么就重復調用recv并檢查返回值,直到成功為止,但是這樣做效率很成問題,開銷太大。
select模型的出現就是為了解決上述問題。
select模型的關鍵是使用一種有序的方式,對多個套接字進行統一管理與調度。
看核心代碼:(這里只給出服務端的)
while ( 1 )
{
// 初始化fdset
FD_ZERO( &fdsRead );
// 將server套接字添加到可讀集合中
FD_SET( sockServer, &fdsRead );
// 調用select
select( 0, &fdsRead, NULL, NULL, &tv );
sudo apt-get install mysql-server-5.0 mysql-client-5.0
sudo apt-get install apache2 php5 libapache2-mod-php5
php5-mysql libapache2-mod-auth-mysql
測試一下:
sudo vi /var/www/test.php
Ubuntu 在安裝時,如同大部分 Linux 發行版一樣,都會同時安裝 GNU 版本的 Java。這個 Java 的實用程度太低,尤其對于開發人員來說,是沒有太多用處的。在 Ubuntu 下,安裝 SUN Java 是一件很容易的事情。第一步:
sudo apt-get install sun-java5-jdk
安裝完畢之后,選擇默認 java:
sudo update-alternatives --config java
然后配置環境變量:
sudo vim /etc/environment
在其中添加如下兩行:
CLASSPATH=/usr/lib/jvm/java-1.5.0-sun/lib
JAVA_HOME=/usr/lib/jvm/java-1.5.0-sun
保存退出。
之后安裝配置 Eclipse。安裝很簡單:
sudo apt-get install eclipse
雖然已經這時新安裝的 java 已經成為系統默認的 jvm,但是 Eclipse 并不會用 update-alternative 設置的 jvm 來啟動自身,而使用的是以前的 GNU Java。GNU Java 是 1.4.2 的實現,而且在性能上遠不如 SUN 的實現。為了讓 Eclipse 利用 SUN Java 啟動,我們還需要繼續配置。首先將 SUN Java 完完全全的設置為系統的默認 JDK:
sudo update-java-alternatives -s java-1.5.0-sun
然后編輯 JVM 配置文件:
sudo vim /etc/jvm
將文件中的
/usr/lib/jvm/java-1.5.0-sun
這一行移動到配置塊的頂部。由于 Eclipse 會忽略 Ubuntu 的通用 Java 設置(貌似一個 bug),我們需要繼續編輯 Eclipse 的 java_home 文件:
sudo vim /etc/eclipse/java_home
如同上面一樣,將
/usr/lib/jvm/java-1.5.0-sun
這一行移動到文件的頂部。所有的安裝配置完成之后,Ubuntu 的 Java 開發平臺就基本完備了。
1、要知道,眼睛一閉一睜,一天就過去了。
時間不停流,總是在不停的前行,所以,要懂得只爭朝夕,真正從內心里明白眼睛一閉一睜的概念,好好的度過每一天,而不是碌碌無為的不知道為誰而活,也不知道自己想要干些什么。
2、要明白,最愛的人是誰,要好好的去愛。
一定要明白,誰是你最愛的人,誰是最愛你的人,要好好的理解愛,用心的去愛,讓愛充滿陽光,同樣溫暖你生活的每個瞬間,只有這樣,你的幸福指數才會最高,最令人羨慕。
3、要知道,最重要的責任,要用心去生活。
要記得,人生最重要的不是掙錢,而是有責任,對身邊的人要負責,對生活要負責,對工作要負責,責任意識讓自己學著慢慢成熟,同樣也可以改變一個人的理想和信念,讓大家得到肯定。
4、要明白,不斷的學習,讓自己逐步提高。
活到老,學到老。總理說的沒有錯。人生苦短,但一定不要忘記學習,畢竟,在學習中不斷的提高自己,才可以獲得更大的成功。相信這一點,比什么都重要。
5、要知道,思考非常重要,學會改變自己。
要不斷的去思考,發現問題及時解決問題,并在發現問題和解決問題的時候學會改變自己,讓自己去適應社會和團隊的發展,當然,適應并不是放棄自己主觀能動性。
6、要明白,錢不是第一位,愛才是第一位。
有錢可以提高生活質量,但并不是提高愛的質量,愛是第一位的,錢不是第一位,只有充滿愛的生活,錢才更有價值,沒有了愛,有再多的錢一點用都沒有,全是自私和永不滿足的欲望而已。
7、要知道,逆境不可怕,可怕的是失去信心。
順境中發揮出自己應有的能力當然重要,但更重要的是在逆境中學會堅強的面對現實,只有這樣,才會更有信心的去堅持自己的理想,相信自己,什么都不可怕。
8、要明白,有份事業,為自己的所愛而奮斗。
要知道自己最需要什么,什么最適合自己,也許,在很多次艱難的決擇中,會發現自己最需要的是什么,朝著自己的目標去奮斗,相信會有成功的那一天。
9、要明白,健康是第一位,要學會多運動。
多多的運動,保持一個好的身體狀態,身體是革命的本錢,只有保證在健康的前提下,一切理想才可以去談,所以不要總是自以為是,科學合理的運動,健康第一位。
10、要知道,眼睛一閉不睜,一輩子就過去了。
理解這句話的真正用意,就是不要太去計較得與失,要勇敢的面對現實,要學會理解和寬容,要學會放棄,要懂得舍得的意思,活的開開心心的最重要,有個好的心態,一輩子才活的有意義。
雖然金錢不是萬能的,但沒有錢是萬萬不能的,雖然這句話很俗,但絕對有道理,所以30歲之前,請把你大部分精力放在你的事業上。
2,別把錢看得太重
不要抱怨自己現在工資低,銀行存款4位數以下,看不到前途,現在要做的就是努力學習,即使你文憑再高,怎么把理論運用到實踐還是需要一個很長的鍛煉過程,社會永遠是一所最博大的大學,它讓你學到的知識遠比你在學校學到的重要得多,所以同樣,你也別太介意學歷低.30歲之前靠自己能力買車買房的人還是極少。
3,學會體諒父母
別嫌他們嘮叨,等你為人父了你就知道可憐天下父母心,在他們眼里你還是個孩子,但他們真的老了,現在得你哄他們開心了,也許只要你的一個電話,一點小禮物,就可以讓他們安心,很容易做到。
4,交上好朋友
朋友對你一生都影響重大,不要去結識太多酒肉朋友,至少得有一個能在關鍵時刻幫助你的朋友,如果遇到這么一個人,就好好把握,日后必定有用,不管他現在是富還是窮。
5,別太相信愛情心中要有愛,但請別說也別相信那些瓊瑤阿姨小說里面的山盟海誓,世上本無永恒,重要的是責任,但女人心海底針,心變了,一切都成枉然,你要做的就是該出手時就出手,該放手時別猶豫.30歲之前的愛情不是假的,但只是大多數人都沒有能真正把握好的能力,所以學會量力而行。
6,別擔心至今還保留初吻
愛情不在多而在精,別以為自己20多歲還沒碰過女孩子就害怕自己永遠找不到老婆.以后你會有很多機會認識女孩子,要知道這個社會雖然男人多于女人,但現實是女人其實比男人更擔心這個問題.男人30一枝花,你在升值而不是貶值,成熟的愛情往往更美麗更長久,所以不要像瘋狗一樣看到女孩就想追,學會品味寂寞。
7,不要沉迷于任何東西
所謂玩物而喪志,網絡游戲是你在出校門之前玩的,你現在沒有多余的時間和精力花費到這上面,否則你透支的東西以后都得償還.一個人要有興趣,愛好,但請分清楚輕重。
8,年輕沒有失敗
不要遇到挫折就灰心,年輕人要時刻保持積極向上的態度.失敗了,重來過;失去了,再爭取別的。錯過了,要分析,下次來,要把握;幼稚了,下次,成熟點。不要緊,會好的,哪怕到了極點,也不要放棄,相信一定可以挺過去。不要消極,會好的。曾經的錯,過去了,總不能回味在過去。現在的,很好,累完了,很舒服。不要傷,總會有人在支撐你。
9,不要輕易崇拜或者鄙視一個人人都有偶像,但請擁有你自己的個性.不要刻意去模仿一個人,因為你就是你,是唯一的,獨一無二的,要有自信.也不要全盤否定一個人,每個人是有價值的,如果你不能理解他,也請學會接受。
10,要有責任心.
不管你曾經怎樣,但請從現在開始做一個正直的人.男人要有責任心,無論是工作還是生活上,一個有責任心的人才能讓別人有安全感,才能讓別人覺得你是一個值得信賴的人.我們不要懦弱,但請不要傷害愛你的人和你愛的人,尤其是善良的女孩,因為這個世界善良的女孩不多了,即使不想擁有,但也請讓她保持她美麗的心。
11,男人的外貌并不重要.
不要為自己的長相身高而過分擔心,一個心地善良,為人正直的男人遠比那些空有英俊相貌,挺拔身材但內心齷齪的男人要帥得多.如果有人以貌取人,請不要太在意,因為你不用去為一個低級趣味的人而難過。
12,學會保護身體
不要以為現在抽煙喝酒,熬夜通宵也沒什么事.那是因為你的身體正處于你一生的黃金時段.30歲以后你就能明白力不從心這個詞的意義了,身體是革命的本錢,沒有好的身體什么也做不了,所以要盡量讓自己過有規律的健康生活。
13,別覺得一事無成.你現在還沒有資格談成功,當然如果你有千萬資產的除外.一開始太固定的職業并不一定是好事,或許在不斷的改行當中,你會學到更豐富的知識,而且可以挖掘出自己的潛能,找到最適合你的工作。
14,請認真工作
即使你現在的工作再怎么無聊再怎么低級,也請你認真去對待,要知道任何成功人士都是從最小的事做起,或許你現在學不到多么了不起的知識,但起碼你要學會良好的工作態度和工作方法,這對以后很重要。
15,請認真對待感情.
不要羨慕那些換女人像換鞋一樣的花花公子,逢場作戲的愛情只是讓你浪費時間浪費精力,一個人最痛苦的不是找不到愛人,而是心中沒有了愛,當你把我愛你3 個字變成你最容易說的一句話時,那么你在愛情的世界里已經很難找到真正的幸福了.愛情沒有公平,總有一個人比對方付出得多,即使沒有結果,也別覺得不值, 因為你的付出不光是為了她,也是為了你自己的愛,為愛付出是很可貴的,贊自己一下。
16.請留一點童心
在內心深處,哪怕只是一個很小的角落里,請保持一份童心,不是幼稚,但有的時候單純一點會讓你很快樂.所以不要太計較得失,生活本無完美。
一、引言
計算機的出現使得很多原本十分繁瑣的工作得以大幅度簡化,但是也有一些在人們直觀看來很容易的問題卻需要拿出一套并不簡單的通用解決方案,比如幾何問題。作為計算機科學的一個分支,計算幾何主要研究解決幾何問題的算法。在現代工程和數學領域,計算幾何在圖形學、機器人技術、超大規模集成電路設計和統計等諸多領域有著十分重要的應用。在本文中,我們將對計算幾何常用的基本算法做一個全面的介紹,希望對您了解并應用計算幾何的知識解決問題起到幫助。
二、目錄
本文整理的計算幾何基本概念和常用算法包括如下內容:
三、算法介紹
如果一條線段的端點是有次序之分的,我們把這種線段成為有向線段(directed segment)。如果有向線段p1p2的起點p1在坐標原點,我們可以把它稱為矢量(vector)p2。
設二維矢量P = ( x1, y1 ),Q = ( x2 , y2 ),則矢量加法定義為: P + Q = ( x1 + x2 , y1 + y2 ),同樣的,矢量減法定義為: P - Q = ( x1 - x2 , y1 - y2 )。顯然有性質 P + Q = Q + P,P - Q = - ( Q - P )。
矢量叉積:
計算矢量叉積是與直線和線段相關算法的核心部分。設矢量P = ( x1, y1 ),Q = ( x2, y2 ),則矢量叉積定義為由(0,0)、p1、p2和p1+p2所組成的平行四邊形的帶符號的面積,即:P × Q = x1*y2 - x2*y1,其結果是一個標量。顯然有性質 P × Q = - ( Q × P ) 和 P × ( - Q ) = - ( P × Q )。一般在不加說明的情況下,本文下述算法中所有的點都看作矢量,兩點的加減法就是矢量相加減,而點的乘法則看作矢量叉積。
叉積的一個非常重要性質是可以通過它的符號判斷兩矢量相互之間的順逆時針關系:
若 P × Q > 0 , 則P在Q的順時針方向。
若 P × Q < 0 , 則P在Q的逆時針方向。
若 P × Q = 0 , 則P與Q共線,但可能同向也可能反向。
折線段的拐向判斷方法可以直接由矢量叉積的性質推出。對于有公共端點的線段p0p1和p1p2,通過計算(p2 - p0) × (p1 - p0)的符號便可以確定折線段的拐向:
若(p2 - p0) × (p1 - p0) > 0,則p0p1在p1點拐向右側后得到p1p2。
若(p2 - p0) × (p1 - p0) < 0,則p0p1在p1點拐向左側后得到p1p2。
若(p2 - p0) × (p1 - p0) = 0,則p0、p1、p2三點共線。
具體情況可參照下圖:
設點為Q,線段為P1P2 ,判斷點Q在該線段上的依據是:( Q - P1 ) × ( P2 - P1 ) = 0 且 Q 在以 P1,P2為對角頂點的矩形內。前者保證Q點在直線P1P2上,后者是保證Q點不在線段P1P2的延長線或反向延長線上,對于這一步驟的判斷可以用以下過程實現:
ON-SEGMENT(pi,pj,pk)
if min(xi,xj) <= xk <= max(xi,xj) and min(yi,yj) <= yk <= max(yi,yj)
then return true;
else return false;
特別要注意的是,由于需要考慮水平線段和垂直線段兩種特殊情況,min(xi,xj)<=xk<=max(xi,xj)和min(yi,yj)<=yk<=max(yi,yj)兩個條件必須同時滿足才能返回真值。
我們分兩步確定兩條線段是否相交:
(1)快速排斥試驗
設以線段 P1P2 為對角線的矩形為R, 設以線段 Q1Q2 為對角線的矩形為T,如果R和T不相交,顯然兩線段不會相交。
(2)跨立試驗
如果兩線段相交,則兩線段必然相互跨立對方。若P1P2跨立Q1Q2 ,則矢量 ( P1 - Q1 ) 和( P2 - Q1 )位于矢量( Q2 - Q1 ) 的兩側,即( P1 - Q1 ) × ( Q2 - Q1 ) * ( P2 - Q1 ) × ( Q2 - Q1 ) < 0。上式可改寫成( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) > 0。當 ( P1 - Q1 ) × ( Q2 - Q1 ) = 0 時,說明 ( P1 - Q1 ) 和 ( Q2 - Q1 )共線,但是因為已經通過快速排斥試驗,所以 P1 一定在線段 Q1Q2上;同理,( Q2 - Q1 ) ×(P2 - Q1 ) = 0 說明 P2 一定在線段 Q1Q2上。所以判斷P1P2跨立Q1Q2的依據是:( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) >= 0。同理判斷Q1Q2跨立P1P2的依據是:( Q1 - P1 ) × ( P2 - P1 ) * ( P2 - P1 ) × ( Q2 - P1 ) >= 0。具體情況如下圖所示:
在相同的原理下,對此算法的具體的實現細節可能會與此有所不同,除了這種過程外,大家也可以參考《算法導論》上的實現。
有了上面的基礎,這個算法就很容易了。如果線段P1P2和直線Q1Q2相交,則P1P2跨立Q1Q2,即:( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) >= 0。
只要判斷該點的橫坐標和縱坐標是否夾在矩形的左右邊和上下邊之間。
因為矩形是個凸集,所以只要判斷所有端點是否都在矩形中就可以了。
只要比較左右邊界和上下邊界就可以了。
很容易證明,圓在矩形中的充要條件是:圓心在矩形中且圓的半徑小于等于圓心到矩形四邊的距離的最小值。
判斷點P是否在多邊形中是計算幾何中一個非常基本但是十分重要的算法。以點P為端點,向左方作射線L,由于多邊形是有界的,所以射線L的左端一定在多邊形外,考慮沿著L從無窮遠處開始自左向右移動,遇到和多邊形的第一個交點的時候,進入到了多邊形的內部,遇到第二個交點的時候,離開了多邊形,……所以很容易看出當L和多邊形的交點數目C是奇數的時候,P在多邊形內,是偶數的話P在多邊形外。
但是有些特殊情況要加以考慮。如圖下圖(a)(b)(c)(d)所示。在圖(a)中,L和多邊形的頂點相交,這時候交點只能計算一個;在圖(b)中,L和多邊形頂點的交點不應被計算;在圖(c)和(d) 中,L和多邊形的一條邊重合,這條邊應該被忽略不計。如果L和多邊形的一條邊重合,這條邊應該被忽略不計。
為了統一起見,我們在計算射線L和多邊形的交點的時候,1。對于多邊形的水平邊不作考慮;2。對于多邊形的頂點和L相交的情況,如果該頂點是其所屬的邊上縱坐標較大的頂點,則計數,否則忽略;3。對于P在多邊形邊上的情形,直接可判斷P屬于多邊行。由此得出算法的偽代碼如下:
count ← 0;
以P為端點,作從右向左的射線L;
for 多邊形的每條邊s
do if P在邊s上
then return true;
if s不是水平的
then if s的一個端點在L上
if 該端點是s兩端點中縱坐標較大的端點
then count ← count+1
else if s和L相交
then count ← count+1;
if count mod 2 = 1
then return true;
else return false;
其中做射線L的方法是:設P'的縱坐標和P相同,橫坐標為正無窮大(很大的一個正數),則P和P'就確定了射線L。
判斷點是否在多邊形中的這個算法的時間復雜度為O(n)。
另外還有一種算法是用帶符號的三角形面積之和與多邊形面積進行比較,這種算法由于使用浮點數運算所以會帶來一定誤差,不推薦大家使用。
線段在多邊形內的一個必要條件是線段的兩個端點都在多邊形內,但由于多邊形可能為凹,所以這不能成為判斷的充分條件。如果線段和多邊形的某條邊內交(兩線段內交是指兩線段相交且交點不在兩線段的端點),因為多邊形的邊的左右兩側分屬多邊形內外不同部分,所以線段一定會有一部分在多邊形外(見圖a)。于是我們得到線段在多邊形內的第二個必要條件:線段和多邊形的所有邊都不內交。
線段和多邊形交于線段的兩端點并不會影響線段是否在多邊形內;但是如果多邊形的某個頂點和線段相交,還必須判斷兩相鄰交點之間的線段是否包含于多邊形內部(反例見圖b)。
因此我們可以先求出所有和線段相交的多邊形的頂點,然后按照X-Y坐標排序(X坐標小的排在前面,對于X坐標相同的點,Y坐標小的排在前面,這種排序準則也是為了保證水平和垂直情況的判斷正確),這樣相鄰的兩個點就是在線段上相鄰的兩交點,如果任意相鄰兩點的中點也在多邊形內,則該線段一定在多邊形內。
證明如下:
命題1:
如果線段和多邊形的兩相鄰交點P1 ,P2的中點P' 也在多邊形內,則P1, P2之間的所有點都在多邊形內。
證明:
假設P1,P2之間含有不在多邊形內的點,不妨設該點為Q,在P1, P'之間,因為多邊形是閉合曲線,所以其內外部之間有界,而P1屬于多邊行內部,Q屬于多邊性外部,P'屬于多邊性內部,P1-Q-P'完全連續,所以P1Q和QP'一定跨越多邊形的邊界,因此在P1,P'之間至少還有兩個該線段和多邊形的交點,這和P1P2是相鄰兩交點矛盾,故命題成立。證畢。
由命題1直接可得出推論:
推論2:
設多邊形和線段PQ的交點依次為P1,P2,……Pn,其中Pi和Pi+1是相鄰兩交點,線段PQ在多邊形內的充要條件是:P,Q在多邊形內且對于i =1, 2,……, n-1,Pi ,Pi+1的中點也在多邊形內。
在實際編程中,沒有必要計算所有的交點,首先應判斷線段和多邊形的邊是否內交,倘若線段和多邊形的某條邊內交則線段一定在多邊形外;如果線段和多邊形的每一條邊都不內交,則線段和多邊形的交點一定是線段的端點或者多邊形的頂點,只要判斷點是否在線段上就可以了。
至此我們得出算法如下:
if 線端PQ的端點不都在多邊形內
then return false;
點集pointSet初始化為空;
for 多邊形的每條邊s
do if 線段的某個端點在s上
then 將該端點加入pointSet;
else if s的某個端點在線段PQ上
then 將該端點加入pointSet;
else if s和線段PQ相交 // 這時候已經可以肯定是內交了
then return false;
將pointSet中的點按照X-Y坐標排序;
for pointSet中每兩個相鄰點 pointSet[i] , pointSet[ i+1]
do if pointSet[i] , pointSet[ i+1] 的中點不在多邊形中
then return false;
return true;
這個過程中的排序因為交點數目肯定遠小于多邊形的頂點數目n,所以最多是常數級的復雜度,幾乎可以忽略不計。因此算法的時間復雜度也是O(n)。
只要判斷折線的每條線段是否都在多邊形內即可。設折線有m條線段,多邊形有n個頂點,則該算法的時間復雜度為O(m*n)。
只要判斷多邊形的每條邊是否都在多邊形內即可。判斷一個有m個頂點的多邊形是否在一個有n個頂點的多邊形內復雜度為O(m*n)。
將矩形轉化為多邊形,然后再判斷是否在多邊形內。
只要計算圓心到多邊形的每條邊的最短距離,如果該距離大于等于圓半徑則該圓在多邊形內。計算圓心到多邊形每條邊最短距離的算法在后文闡述。
計算圓心到該點的距離,如果小于等于半徑則該點在圓內。
因為圓是凸集,所以只要判斷是否每個頂點都在圓內即可。
設兩圓為O1,O2,半徑分別為r1, r2,要判斷O2是否在O1內。先比較r1,r2的大小,如果r1<r2則O2不可能在O1內;否則如果兩圓心的距離大于r1 - r2 ,則O2不在O1內;否則O2在O1內。
如果該線段平行于X軸(Y軸),則過點point作該線段所在直線的垂線,垂足很容易求得,然后計算出垂足,如果垂足在線段上則返回垂足,否則返回離垂足近的端點;如果該線段不平行于X軸也不平行于Y軸,則斜率存在且不為0。設線段的兩端點為pt1和pt2,斜率為:k = ( pt2.y - pt1. y ) / (pt2.x - pt1.x );該直線方程為:y = k* ( x - pt1.x) + pt1.y。其垂線的斜率為 - 1 / k,垂線方程為:y = (-1/k) * (x - point.x) + point.y 。
聯立兩直線方程解得:x = ( k^2 * pt1.x + k * (point.y - pt1.y ) + point.x ) / ( k^2 + 1) ,y = k * ( x - pt1.x) + pt1.y;然后再判斷垂足是否在線段上,如果在線段上則返回垂足;如果不在則計算兩端點到垂足的距離,選擇距離垂足較近的端點返回。
只要分別計算點到每條線段的最近點,記錄最近距離,取其中最近距離最小的點即可。
如果該點在圓心,因為圓心到圓周任一點的距離相等,返回UNDEFINED。
連接點P和圓心O,如果PO平行于X軸,則根據P在O的左邊還是右邊計算出最近點的橫坐標為centerPoint.x - radius 或 centerPoint.x + radius。如果PO平行于Y軸,則根據P在O的上邊還是下邊計算出最近點的縱坐標為 centerPoint.y -+radius或 centerPoint.y - radius。如果PO不平行于X軸和Y軸,則PO的斜率存在且不為0,這時直線PO斜率為k = ( P.y - O.y )/ ( P.x - O.x )。直線PO的方程為:y = k * ( x - P.x) + P.y。設圓方程為:(x - O.x ) ^2 + ( y - O.y ) ^2 = r ^2,聯立兩方程組可以解出直線PO和圓的交點,取其中離P點較近的交點即可。
對于兩條共線的線段,它們之間的位置關系有下圖所示的幾種情況。圖(a)中兩條線段沒有交點;圖 (b) 和 (d) 中兩條線段有無窮焦點;圖 (c) 中兩條線段有一個交點。設line1是兩條線段中較長的一條,line2是較短的一條,如果line1包含了line2的兩個端點,則是圖(d)的情況,兩線段有無窮交點;如果line1只包含line2的一個端點,那么如果line1的某個端點等于被line1包含的line2的那個端點,則是圖(c)的情況,這時兩線段只有一個交點,否則就是圖(b)的情況,兩線段也是有無窮的交點;如果line1不包含line2的任何端點,則是圖(a)的情況,這時兩線段沒有交點。
設一條線段為L0 = P1P2,另一條線段或直線為L1 = Q1Q2 ,要計算的就是L0和L1的交點。
1. 首先判斷L0和L1是否相交(方法已在前文討論過),如果不相交則沒有交點,否則說明L0和L1一定有交點,下面就將L0和L1都看作直線來考慮。
2. 如果P1和P2橫坐標相同,即L0平行于Y軸
a) 若L1也平行于Y軸,
i. 若P1的縱坐標和Q1的縱坐標相同,說明L0和L1共線,假如L1是直線的話他們有無窮的交點,假如L1是線段的話可用"計算兩條共線線段的交點"的算法求他們的交點(該方法在前文已討論過);
ii. 否則說明L0和L1平行,他們沒有交點;
b) 若L1不平行于Y軸,則交點橫坐標為P1的橫坐標,代入到L1的直線方程中可以計算出交點縱坐標;
3. 如果P1和P2橫坐標不同,但是Q1和Q2橫坐標相同,即L1平行于Y軸,則交點橫坐標為Q1的橫坐標,代入到L0的直線方程中可以計算出交點縱坐標;
4. 如果P1和P2縱坐標相同,即L0平行于X軸
a) 若L1也平行于X軸,
i. 若P1的橫坐標和Q1的橫坐標相同,說明L0和L1共線,假如L1是直線的話他們有無窮的交點,假如L1是線段的話可用"計算兩條共線線段的交點"的算法求他們的交點(該方法在前文已討論過);
ii. 否則說明L0和L1平行,他們沒有交點;
b) 若L1不平行于X軸,則交點縱坐標為P1的縱坐標,代入到L1的直線方程中可以計算出交點橫坐標;
5. 如果P1和P2縱坐標不同,但是Q1和Q2縱坐標相同,即L1平行于X軸,則交點縱坐標為Q1的縱坐標,代入到L0的直線方程中可以計算出交點橫坐標;
6. 剩下的情況就是L1和L0的斜率均存在且不為0的情況
a) 計算出L0的斜率K0,L1的斜率K1 ;
b) 如果K1 = K2
i. 如果Q1在L0上,則說明L0和L1共線,假如L1是直線的話有無窮交點,假如L1是線段的話可用"計算兩條共線線段的交點"的算法求他們的交點(該方法在前文已討論過);
ii. 如果Q1不在L0上,則說明L0和L1平行,他們沒有交點。
c) 聯立兩直線的方程組可以解出交點來
這個算法并不復雜,但是要分情況討論清楚,尤其是當兩條線段共線的情況需要單獨考慮,所以在前文將求兩條共線線段的算法單獨寫出來。另外,一開始就先利用矢量叉乘判斷線段與線段(或直線)是否相交,如果結果是相交,那么在后面就可以將線段全部看作直線來考慮。需要注意的是,我們可以將直線或線段方程改寫為ax+by+c=0的形式,這樣一來上述過程的部分步驟可以合并,縮短了代碼長度,但是由于先要求出參數,這種算法將花費更多的時間。
分別求與每條邊的交點即可。
設圓心為O,圓半徑為r,直線(或線段)L上的兩點為P1,P2。
1. 如果L是線段且P1,P2都包含在圓O內,則沒有交點;否則進行下一步。
2. 如果L平行于Y軸,
a) 計算圓心到L的距離dis;
b) 如果dis > r 則L和圓沒有交點;
c) 利用勾股定理,可以求出兩交點坐標,但要注意考慮L和圓的相切情況。
3. 如果L平行于X軸,做法與L平行于Y軸的情況類似;
4. 如果L既不平行X軸也不平行Y軸,可以求出L的斜率K,然后列出L的點斜式方程,和圓方程聯立即可求解出L和圓的兩個交點;
5. 如果L是線段,對于2,3,4中求出的交點還要分別判斷是否屬于該線段的范圍內。
點集Q的凸包(convex hull)是指一個最小凸多邊形,滿足Q中的點或者在多邊形邊上或者在其內。下圖中由紅色線段表示的多邊形就是點集Q={p0,p1,...p12}的凸包。
現在已經證明了凸包算法的時間復雜度下界是O(n*logn),但是當凸包的頂點數h也被考慮進去的話,Krikpatrick和Seidel的剪枝搜索算法可以達到O(n*logh),在漸進意義下達到最優。最常用的凸包算法是Graham掃描法和Jarvis步進法。本文只簡單介紹一下Graham掃描法,其正確性的證明和Jarvis步進法的過程大家可以參考《算法導論》。
對于一個有三個或以上點的點集Q,Graham掃描法的過程如下:
令p0為Q中Y-X坐標排序下最小的點
設<p1,p2,...pm>為對其余點按以p0為中心的極角逆時針排序所得的點集(如果有多個點有相同的極角,除了距p0最遠的點外全部移除
壓p0進棧S
壓p1進棧S
壓p2進棧S
for i ← 3 to m
do while 由S的棧頂元素的下一個元素、S的棧頂元素以及pi構成的折線段不拐向左側
對S彈棧
壓pi進棧S
return S;
此過程執行后,棧S由底至頂的元素就是Q的凸包頂點按逆時針排列的點序列。需要注意的是,我們對點按極角逆時針排序時,并不需要真正求出極角,只需要求出任意兩點的次序就可以了。而這個步驟可以用前述的矢量叉積性質實現。
四、結語
盡管人類對幾何學的研究從古代起便沒有中斷過,但是具體到借助計算機來解決幾何問題的研究,還只是停留在一個初級階段,無論從應用領域還是發展前景來看,計算幾何學都值得我們認真學習、加以運用,希望這篇文章能帶你走進這個豐富多彩的世界。
當讀者有一定c/c++基礎
推薦的閱讀順序:
level 1
從<<essential c++>>開始,短小精悍,可以對c++能進一步了解其特性
以<<c++ primer>>作字典和課外讀物,因為太厚不可能一口氣看完
level 2
然后從<<effective c++>>開始轉職,這是圣經,請遵守10誡,要經常看,沒事就拿來翻翻
接著是<<exceptional c++>>,個人認為Herb Sutter主席大人的語言表達能力不及Scott Meyers總是在教育第一線的好
順下來就是<<more effective c++>>和<<more exceptional c++>>,請熟讀并牢記各條款
當你讀到這里,應該會有一股升級的沖動了
level 3
<<insied the c++ object model>>看過后如一縷清風掃去一直以來你對語言的疑惑,你終于能明白compiler到底都背著你做了些什么了,這本書要細細回味,比較難啃,最好反復看幾遍,加深印象
看完上一本之后,這本<<The design and evolution of c++>>會重演一次當年C++他爹在設計整個語言過程中的歷程
level 4
<<the c++ standard library>>是stl的字典,要什么都可以查得到
學c++不能不學stl,那么首先是<<effective stl>>,它和圣經一樣是你日常行為的規范
<<generic programming and the stl>>讓你從oo向gp轉變
光用不行,我們還有必要了解stl的工作原理,那么<<stl源碼剖析>>會解決你所有的困惑
level 5
對于c++無非是oo和gp,想進一步提升oo,<<exeptional c++ style>>是一本主席這么多年的經驗之談,是很長esp的
一位stl高手是不能不去了解template的,<<c++ template>>是一本百科全書,足夠你看完后對于gp游刃有余
<<modern c++ design>>是太過聰明的人寫給明眼人看的
好書有很多,不能一一列舉
以上我的讀書經歷,供各位參考。接下來的無非就是打怪練級,多聽多寫多看;boost、stl、loki這些都是利器,斬妖除魔,奉勸各位別再土法練鋼了。
at last,無他,唯手熟爾。
忘了一本《thinking in C++》
也是經典系列之一
<<effective c++>>這本圣經的作者Scott Meyesr在給<<modern c++ design>>序言的時候高度的贊賞了Andrei同志的工作:C++社群對template的理解即將經歷一次巨大的變化,我對它所說的任何事情,也許很快就會被認為是陳舊的、膚淺的、甚至是完全錯的。
就我所知,template的世界還在變化,速度之快就像我1995年回避寫它的時候一樣。從發展的速度來看,我可能永遠不會寫有關template的技術書籍。幸運的是一些人比我勇敢,Andrei就是這樣一位先鋒。我想你會從此書得到很多收獲。我自己就得到了很多——Scott Meyers September2000。
并且,Scott Meyers 在最近的Top5系列文章中,評價C++歷史里面最重要5本書中、把Modern C++ Design列入其中,另外四本是它自己的effective c++、以及C++ Programming Language、甚至包括《設計模式》和《C++標準文檔》。
顯然,Scott Meyers已經作為一個頂尖大師的角度承認了<<modern c++ design>>的價值。
并且調侃地說,可以把是否使用其中模板方法定義為,現代C++使用者和非現代C++使用者,并且檢討了自己在早期版本Effective對模板的忽視,最后重申在新版本Effective第七章節加入大量對模板程序設計的段落,作為對這次失誤的補償。
并且,在這里要明確的是<<modern c++ design>>并不是一本泛型編成的書,也不是一本模板手冊。其中提出了基于策略的設計方法,有計劃和目的的使用了模板、面向對象和設計模式。雖然Andrei本人對模板的研究世界無人能敵,但對其他領域的作為也令人贊嘆。
任何做游戲的人都不能忽視OpenAL把,你在開發者的名單里能看到Loki的名字:)
最近很忙,無時間寫文章,小奉獻一下書籍下載地址。雖然經過驗證,但是不感肯定各位一定能下:
<effective C++> 中文
http://www.itepub.net/html/ebookcn/2006/0523/40146.html
英文
http://dl.njfiw.gov.cn/books/C/Essential%20C++.chm
<c++ primer> 英文
http://www.vipbook.net/soft/2114.htm
<<effective c++>>英文
http://soft.studa.com/downinfo/19350.html
<exceptional c++> 英文
http://soft.studa.com/downinfo/19380.html
<more exceptional c++> 英文
http://soft.studa.com/downinfo/19377.html
<inside the C++ object Model>
http://dl.njfiw.gov.cn/books/C/Inside%20the%20C++%20Object%20Model.chm
< the design and evolution of c++ >
http://ebook.manboo.info/2006/11/19/the-design-and-evolution-of-c.html
< effective STL>
http://dl.njfiw.gov.cn/books/C/Effective%20STL.pdf
< the standard STL>
http://dl.njfiw.gov.cn/books/C/The%20C++%20Standard%20Library.chm
< moden C++ design>
http://dl.njfiw.gov.cn/books/C/Modern%20C++%20Design.chm
<exceptional c++ style>
http://cpp.ga-la.com/html/8/10/0510/71.htm
< c++ template >
http://www.itepub.net/html/ebookcn/2006/0429/7320.html
< generic programming and the STL >
http://www.jjhou.com/jjtbooks-generic-programming-and-the-stl.htm
真正的愛情,只有在平等的條件下產生。
去追一個對你沒感覺的女人,只會讓她很煩,如果她碰巧很漂亮,有很多像你一樣或者比你優秀的男人去追,那你一定不會有機會;即便上天給你了一個千載難逢的機會,并且還讓你抓住了,那么最終,你還是會失去的。因為你的愛,當她不再需要的時候,或者遇到更好的男人的時候,就是負擔。
最慘的是碰到玩弄感情的女人,你一定死得很慘。
女人拒絕男人,或者拋棄男人,根本理由只有一個,就是你達不到她的水平。
在感情上,男人要主動,但是,主動之前先看看你自己夠不夠斤兩,如果你不夠她的水平,那就放棄吧!
如果你觀察過一個有一個以上男朋友的女人,你一定會發現,她最喜歡的一定是那個對她最冷淡的男人。
所以說,愛人不如愛自己!
你要是愛自己勝過別的任何人,你會專注于自己的事業,你就會開始有錢;你會注意自己的外表,你就會變的帥氣;你會對自己充滿信心,你會充滿魅力。只要你懂得欣賞女人的心理,就會有很多的女人都來愛你。
她們并不是愛你的錢,相信我。除非你是那種除了錢什么都沒有的人,她們愛的確實是你這個人。你因此而取得了愛情中的優勢。
如果你取得了優勢,你就有了選擇的權力;你可以選擇一個和你一樣優秀的女人,自己做一個忠實的丈夫,所有人都會羨慕你們這對神仙眷屬;你也可以選擇一個自己心愛的但是并不如你的女人,這時你就不用那么辛苦地去追求她;你甚至可以去選擇擁有無數的女人,社會不會譴責你,因為她們是心甘情愿的。
知道為什么男人在二十歲的時候相信愛情,在三十歲的時候相信事業了吧。
愛情是脆弱的,在現實面前根本不堪一擊。世界上的確有很多的天荒地老,絕大多數是因為主人公都平凡得根本不會遭遇任何誘惑,幸運到能始終在一起。
虛榮是愛情最大的敵人,第二就是長久的分離。小別勝新婚,長久的別離則是愛情的毒藥。
沉迷在愛情中的戀人指著月亮發誓天長地久,難道他們不知道,月亮本身都是會不斷的在變么?月有陰晴圓缺,人有悲歡離合!
想一想,十年之前,我們在哪里做什么?我們今天在做什么?十年之前,我們能想象到今天么?不能,所以我們也無法預料到十年以后。人,只有中年之后才能穩定下來,所以想承諾的話,到那時侯再承諾吧!