2012-11-06 57 views
1

我寫了一個基於win32 api的GUI應用程序,它使用GDI +功能,如DrawCurve()和DrawLine()。如何檢測多圖片邊緣的點擊?

這個應用程序繪製代表多圖的線條和曲線。

邊緣的數據結構只是一個5 int的結構。 (x1,y1,x2,y2和id)

如果兩個頂點之間只有一條邊,則使用DrawLine()繪製直線段。 如果存在多條邊,則使用DrawCurve()繪製曲線 - 這裏,I 傳播圍繞兩個頂點中點的直線邊緣,使它們成爲曲線。使用法線方程計算距離它一些單位像素的點。如果添加更多邊緣,則選擇距中點兩個單位像素的像素,然後選擇3個單位像素,依此類推。

現在我有兩個關於檢測邊緣點擊的問題。

  1. 在尋找直線邊緣時,爲了最小化搜索時間,我該怎麼辦?
    檢查點擊的像素是否在線段上很簡單,但如果邊緣的數量很大,比較所有邊緣效率會很低。看起來有可能在O(log n)中完成,其中n是邊的數量。
    編輯:在這一點上,邊緣(類邊緣)存儲在std :: map,將邊緣id(int)的 映射到Edge對象,我正在考慮聲明另一個將像素映射到邊緣id的容器。
    我正在考慮使用二叉搜索樹,但什麼可以是關鍵?或者我應該只使用一個2D像素陣列?

  2. 我可以得到DrawCurve()使用的點的數組嗎?如果這是不可能的,那麼我應該重新計算基數樣條線,得到點數組,並檢查用戶點擊的點是否與該數組中的任何點相匹配。

+0

僅用於檢測邊緣被單擊的目的,還是需要根據點擊邊緣的位置來檢索值? – K3N

+0

只要檢測到哪個邊緣被點擊是好的。然後將檢索邊緣的id,並查找std :: map 。 –

回答

0

如果你有複雜形狀的線,你可以做如下:

  • 創建內部位圖您的圖形的大小,用黑色填充。
  • 當您渲染圖形時,也會渲染此位圖的邊緣,使其具有可點擊的邊緣,但使用不同的顏色渲染它們。將這些顏色值與相應的ID一起存儲在一個表中。這裏重要的是顏色是不同的(獨特的)。
  • 單擊圖形時,將X和Y座標轉移到內部位圖並讀取像素。如果不是黑色,請查看錶格中的顏色值並獲取關聯的ID。

這種方式根本不需要擔心形狀,也不需要使用自己的曲線算法等等。成本是額外的內存,這是一個考慮因素,但除非它是一個巨大的圖表(在這種情況下,您可以緩衝繪圖),但在大多數情況下不是問題。您可以在第二遍渲染內部位圖以使主圖形顯得更快(如往常一樣)。

希望這會有所幫助!

(小貼士:您可以使用更寬的筆渲染「內部」線條,使其更敏感)。

+0

在1920 x 1080分辨率下,32 bpp(因此一次可以繪製的最大邊數爲2^32),需要大約8 MB的空間來檢測每個圖視圖的邊緣點擊(這裏我假定畫布大小是固定的,因爲頻繁的位圖緩衝區重新分配會大大降低性能)。我認爲這是最簡單和最快的(O(1))實現方式,但起初它似乎浪費太多空間(O(xy)〜= O(n^2))。但是,我可以降低bpp並減小位圖緩衝區的大小,因爲實際上曲線數量超過幾千個甚至在繪製在一起時不可見。 –

+0

當然,如果不可見=不可點擊,所以你可以消除重疊的情況。正如你所說,也可以通過減半位圖以及x/y座標來量化點擊點,或者甚至將位圖縮小到1/4,每個點擊點都可以在4x4像素區域中點,但是如果您在同一時間有很多邊緣可能不太方便。我只會使用24 bpp(2^24或16.8 mil。不同顏色 - 甚至是16位位圖),因爲在1920 x 1080的空間中,您將永遠無法使用所有顏色,因爲只有大約2 mil。屏幕上可用的像素。 – K3N