線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:11994
推到 Plurk!
推到 Facebook!

請問如何計算不規則面積?

尚未結案
enu
中階會員


發表:36
回覆:93
積分:55
註冊:2003-10-22

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-09-19 04:32:12 IP:220.142.xxx.xxx 未訂閱
各位先進,請教一個問題,通過一條直線的A、B兩座標,其所構成的不規則形狀面積應如何計算呢(如下圖所示)? 懇請賜教,感謝!
richtop
資深會員


發表:122
回覆:646
積分:468
註冊:2003-06-10

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-09-19 17:51:41 IP:211.76.xxx.xxx 未訂閱
enu 您好: 一個簡單的看法供您參考一下: 如果圖形誠如您所畫的樣子,那麼算出所有藍色的pixel數,再乘上一個適當比例,也就是實際圖形與電腦上圖型的大小比值;或者利用填圖的演算法,填滿封閉區域並同時計算填入的pixel數,亦可估計面積的近似大小。 RichTop 敬上 =====***** 把數學當工具,可以解決問題;將數學變能力,能夠發現並解決問題! =====#####
andychang1690
資深會員


發表:20
回覆:694
積分:442
註冊:2003-03-14

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-09-19 21:52:16 IP:221.169.xxx.xxx 未訂閱
enu:你這是數學! 我不記得那裡見過一篇文章,是有關醫學的文章好像講免役系統及病變 的文章其中計算(以肝癌例)病變百分之多少,是以像素計算。相對我覺得 你可以以點計算,先算包括於此不規則形狀面積的三角形或梯形面積 (這個好算),掃瞄這塊區域的點可以得到兩個值(一個是不規則形狀面積) 按百分比應該就可以了! 關於掃瞄圖形上的點說明本園地很多。 請參考! Andy Chang
------
Andy Chang
enu
中階會員


發表:36
回覆:93
積分:55
註冊:2003-10-22

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-09-19 23:23:40 IP:220.142.xxx.xxx 未訂閱
先謝謝richtop和andychang1690先生。我想我再將問題描述仔細一點,看各位先進可否再給予其它建議。    小弟的作業環境就是一般的form最大化,只是可能有一條直線,而當滑鼠由這條直線的A點通過,再由B點通過,則可能會形成一塊不規則的形狀,小弟想要計算這塊不規則形狀的面積,不知道有沒有演算法可以使用?    查了一下網路的資訊,是不是可以用微積分的方式去求得不規則形狀的面積?只是對它不瞭解,不知道有沒有那位先進可以指導一下。感恩!
richtop
資深會員


發表:122
回覆:646
積分:468
註冊:2003-06-10

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-09-20 22:15:59 IP:140.129.xxx.xxx 未訂閱
enu 您好:    理論上用Pixel來判斷是比較簡單且適合離散式的螢幕顯示,但如果您"堅持用數學"來解決,應該也沒問題,不過我尚無實際的實作經驗,僅能提供想法,您參考看看。 理論的根據如下所描述,詳細的內容請翻閱微積分或工程數學書籍,在此難完整呈現。 這個算法是比較適合您的需求,但是在計算時,必須要知道封閉曲線的座標,這可以由滑鼠走過的位置得知,再設定一個參考原點,當然就用Form的左上角當原點亦可,雖然圖形會上下相反,不過面積應該還是一樣。 還有計算時必須一個封閉區域單獨計算後取絕對值,最後再將所有的封閉區域相加,才能得到總共的面積,否則有可能面積會抵消掉,除非可以精確的使用相同的封閉廻圈積分方向。所以如何判斷出每一個單獨的封閉迴圈,可能是您要特別思考的問題,比方說,兩次通過直線就會產生封閉區域,諸如此類的判斷。
m8815010
版主


發表:99
回覆:372
積分:289
註冊:2003-11-13

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-09-27 13:15:01 IP:218.173.xxx.xxx 未訂閱
引言: 各位先進,請教一個問題,通過一條直線的A、B兩座標,其所構成的不規則形狀面積應如何計算呢(如下圖所示)? 懇請賜教,感謝!
enu你好: 我之前剛好做電子地圖在求全省面積,可以提供提供意見! 首先我想只要是用電腦繪出圖形,都一定是由描點描完再一點一點連起來的。所以 即使是再圓滑的一條>範例: 如下圖範例,先劃一條<>(>到<>(>的直線當>(注意因為 >!) 接著會做一步座標的調整動作,就是把座標都 >! < src="http://delphi.ktop.com.tw/loadfile.php?TOPICID=17815034&CC=398426">

~~
TForm1 *Form1;    int Get_Trace=false;
int x_coor=50;
int y_coor=200;    //---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{    }
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
 this->Canvas->MoveTo(50,200);
 this->Canvas->LineTo(600,200);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
      int X, int Y)
{
 if (!Get_Trace)
     return;     if (Y<200)
     return;     this->Canvas->MoveTo(x_coor,y_coor);
 this->Canvas->LineTo(X,Y);     x_coor=X;
 y_coor=Y;     Memo1->Lines->Add(IntToStr(X)+"  "+IntToStr(Y));
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClick(TObject *Sender)
{
 Get_Trace=!Get_Trace;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
 TStringList* coor1=new TStringList;
 TStringList* coor2=new TStringList;
 double area=0.;     for (int i=1;iLines->Count;i++) {
      coor1->CommaText=Memo2->Lines->Strings[i-1];
      coor2->CommaText=Memo2->Lines->Strings[i];          double dx=StrToFloat(coor2->Strings[0])-StrToFloat(coor1->Strings[0]);
      area+=dx*(StrToFloat(coor2->Strings[1])+StrToFloat(coor1->Strings[1]));
 }     area/=2;
 delete coor1;
 delete coor2;
 ShowMessage(area);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
 TStringList* sl=new TStringList;     for (int i=0;iLines->Count;i++) {
      sl->CommaText=Memo1->Lines->Strings[i];
      int x=StrToInt(sl->Strings[0]);
      int y=StrToInt(sl->Strings[1]);          Memo2->Lines->Add(IntToStr(x-50)+" "+IntToStr(y-200));
 }
}
//---------------------------------------------------------------------------
注意事項(重要重要) 1. 計算面積的精神就是把不規則region切分成一塊一塊梯形面積各別計算 2. 上述這種計算方式並沒有任何誤差,因為如同一開始解釋的,所以的電腦圖形都是由 有限的點組成,並不是由無限點組成的! 3. 這種求法已concern了converx、concave邊形的問題,user不用擔心! 4. 每個每個點座標是有順序性的,任意改變是不行的。因為任意改變後的座標其實是表 示另一個不規則圖形 5. y軸以下的面積如果有的話,照樣是會被自動計算的,只是會被當成負值而已!如果enu 兄也要計算的話,就多加一條判斷式,把負面積加絕對值即可! 6. enu兄劃的例子其y軸是一條有斜率的斜線,以本範例不同。這個問題同樣只要做座標的 調整即可! 7. 本範例求法最終原點一定要shift到(0,0)哦! 8. capture軟體沒註冊,嘿嘿嘿! 發表人 - m8815010 於 2004/09/27 13:20:15
enu
中階會員


發表:36
回覆:93
積分:55
註冊:2003-10-22

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-09-28 09:30:20 IP:220.142.xxx.xxx 未訂閱
感恩感恩! 先研究研究!
enu
中階會員


發表:36
回覆:93
積分:55
註冊:2003-10-22

發送簡訊給我
#8 引用回覆 回覆 發表時間:2004-10-11 19:06:03 IP:163.27.xxx.xxx 未訂閱
謝謝m8815010 先生,可否請教幾個問題? 您所提供的範例經測試,好像不需要封閉曲線也能計算面積因為只要在基準線下方
m8815010
版主


發表:99
回覆:372
積分:289
註冊:2003-11-13

發送簡訊給我
#9 引用回覆 回覆 發表時間:2004-10-12 15:27:05 IP:61.63.xxx.xxx 未訂閱
引言: 謝謝m8815010 先生,可否請教幾個問題? 您所提供的範例經測試,好像不需要封閉曲線也能計算面積因為只要在基準線下方>< face="Verdana, Arial, Helvetica"> enu你好< >: 是的,不是封閉的曲線也是可計算面積的,讓我用精美的插圖說明< >!
圖一:是電腦繪出的一條曲線,承之前解釋,因為都是有限點,所以其實都是直線組成的!
      現在假設組成點為紅圈圈處!
      
      
圖二:圖一面積的計算方式是把它切成若干小region,藍色的線即是切法!圖一的例子共可
      切成6個小region,每一個小region都是一個梯形(當有一個底邊為0時,則變成三角
      形),所以只要求完6個小梯形面積再相加後即是全部region的總面積了!
      
圖三:舉例說明那一個小region面積的算法,上下底就直接是Y1,Y2的值,而高是X2、X1
      的差(注意是有方向性的)!
      
圖四:如果今天曲線不是封閉的話!    圖五:依造本程式算面積的方法會計算這樣一個region的面積!所以假想第一點是和(5,200)
      連接是不對的!也就是頭、尾這兩點就是不和什麼點連。但即使這條開放的曲線頭、
      尾兩點都沒有和誰連,本程式還是可以求出一個region的面積。不是程式厲害,而是
      定義是這樣罷了!
      
圖六:圖五這個region的面積求法,依例先切成小region,然後就可以求面積了!    重要重要      
1.注意圖三中,梯形的上底、下底我們是直接等於Y1、Y2,這是因為我們假設〝Y軸〞是y=0
  這一條線!那前一篇例子中的Y軸其實是y=200,所以當然要做一下每個點的Y座標調整了!
2.承上,其實X座標並不需調整,因為圖三中梯形的高我們是取X2-X1,也就是取其差值,
  所以其實X座標並不需調整也行!
3.為什麼基準線(Y軸)以下的面積會被當成負的,還有為什麼凸、凹邊形的問題已自動concern
  進去了,就請自行比照方式研究吧,實在無法再細述了!           <>
最後,是的,本例的算法其面積剛好等於>     >!    
        
enu
中階會員


發表:36
回覆:93
積分:55
註冊:2003-10-22

發送簡訊給我
#10 引用回覆 回覆 發表時間:2004-10-13 10:37:09 IP:163.27.xxx.xxx 未訂閱
再次感謝m8815010先生,給您用力的賀彩!讓小弟收穫良多。 可否再提一個小問題,不知道我這樣的想法對不對?既然該法是算出
m8815010
版主


發表:99
回覆:372
積分:289
註冊:2003-11-13

發送簡訊給我
#11 引用回覆 回覆 發表時間:2004-10-13 20:21:05 IP:210.64.xxx.xxx 未訂閱
引言: 再次感謝m8815010先生,給您用力的賀彩!讓小弟收穫良多。 可否再提一個小問題,不知道我這樣的想法對不對?既然該法是算出>< face="Verdana, Arial, Helvetica"> enu兄你好: 初聽這個想法有點 >! 另外實際營幕長、寬應該是這樣求的: < class="code"> HWND hwnd=GetDesktopWindow(); HDC dc=GetDC(hwnd); ShowMessage(GetDeviceCaps(dc,HORZRES)); ShowMessage(GetDeviceCaps(dc,HORZSIZE)); 大概就這樣了,肚子沒墨水了! 啊,忘了我上面的回應中 〝 >! 發表人 -
enu
中階會員


發表:36
回覆:93
積分:55
註冊:2003-10-22

發送簡訊給我
#12 引用回覆 回覆 發表時間:2004-10-14 09:46:19 IP:163.27.xxx.xxx 未訂閱
感恩!感恩! 查了一下GetDeviceCaps,實際螢幕長、寬應是HORZSIZE和VERTSIZE才對,Anyway,再請教一個小問題,以
m8815010
版主


發表:99
回覆:372
積分:289
註冊:2003-11-13

發送簡訊給我
#13 引用回覆 回覆 發表時間:2004-10-14 10:19:13 IP:61.63.xxx.xxx 未訂閱
引言: 感恩!感恩! 查了一下GetDeviceCaps,實際螢幕長、寬應是HORZSIZE和VERTSIZE才對,Anyway,再請教一個小問題,以>< face="Verdana, Arial, Helvetica"> enu你好< >: 嗯,嗯,你講的沒錯,我這邊誤寫了< >:

              ShowMessage(GetDeviceCaps(dc,HORZRES));   <--Error parameter in secode position
              ShowMessage(GetDeviceCaps(dc,HORZSIZE));
     
另外求營幕的實際長、寬我也是昨天臨時查Help的< >,並且我也跟 >! 技窮,技窮< >!
enu
中階會員


發表:36
回覆:93
積分:55
註冊:2003-10-22

發送簡訊給我
#14 引用回覆 回覆 發表時間:2004-10-18 11:24:49 IP:163.27.xxx.xxx 未訂閱
謝謝m8815010 先生,與您討論真是獲益良多。目前只好先用這些來解決問題,感謝各位先進的指導!
系統時間:2024-11-25 16:22:48
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!