2009-07-12 55 views
4

我正試圖建立一個矩形網格,可以在邊緣環繞。任何玩視頻遊戲的人都可能會熟悉這個概念:在世界地圖上朝一個方向走得足夠遠,並且最終會返回到開始的位置。但是,這會在設置視口時造成一些困難,因爲邊緣可以滾動到負座標區域。是否有一個簡單的「點矩陣」算法的環繞地圖?

這是很容易採取負座標和確定其實際價值:

function GetRealCoords(value: TPoint): TPoint; 
begin 
    result := ModPoints(AddPoints(value, MAP_SIZE), MAP_SIZE); 
end; 

其中AddPoints和ModPoints簡單地套用+mod運營商,分別給每個的兩個輸入座標以產生輸出值。

問題在於顛倒這一操作。給定一個點,其中兩個座標都是正數,並且一個TRect中的頂部和左側值可以是正數或負數(並且底部或右側可能超出地圖的邊界),並且在全局範圍內聲明MAP_SIZE,是有什麼辦法可以確定點是否落在矩形所在的區域內,而不必在四個不同的時間運行相同的計算?

回答

3

有了這個,你可以測試你的點是否在矩形內。

function PointInRect(aPoint:TPoint;aRect:TRect):boolean; 
begin 
    Result:=(aPoint.X >= aRect.Left ) and 
      (aPoint.X < aRect.Right) and 
      (aPoint.Y >= aRect.Top ) and 
      (aPoint.Y < aRect.Bottom); 
end; 

但是,如果我正確地理解你的描述,你想是這樣的:

function NormalisePoint(aPoint:TPoint;aRect:TRect):TPoint; 
var Width,Height:integer; 
begin 
    Width := aRect.Right-aRect.Left; 
    Height := aRect.Bottom-aRect.Top; 

    if (Width=0) then 
    aPoint.X := aRect.Left 
    else 
    begin 
    while (aPoint.X< aRect.Left ) do inc(aPoint.X,Width); 
    while (aPoint.X>=aRect.Right) do dec(aPoint.X,Width); 
    end; 

    if (Height=0) then 
    aPoint.Y := aRect.Top 
    else 
    begin 
    while (aPoint.Y< aRect.Top ) do inc(aPoint.Y,Height); 
    while (aPoint.Y>=aRect.Bottom) do dec(aPoint.Y,Height); 
    end; 
    Result := aPoint; 
end; 
+0

哎喲!我試圖在總體原則上低估這一點,只是對**和**聲明加倍。使閱讀變得更加困難。 :( – 2009-07-12 03:31:52

4

我相信如此。

最壞可能情況下,我能想到的(網格= [0,1)×[0,1))是這樣的: 頂= -0.25,左= -0.25,底= 0.25,右= 0.25

這看起來像(包裝時):

______ 
|_| |_| 
|  | 
|_ _| 
|_|__|_| 

現在,你必須測試的四個角落,看看如果點在他們裏面。但是,我相信通過在空間[1,2] x [1,2)中執行測試,您可以避免 問題,因爲它再次成爲一個矩形。

______ 
|  | 
|  | 
|  _|_ 
|____| | 
    |___| 

通過計算矩形的寬度和高度來簡化問題。

Width=Mod(Right-Left+MAP_SIZE,MAP_SIZE) 
Height=Mod(Bottom-Top+MAP_SIZE,MAP_SIZE) 

現在,左上

計算新的底部和右側計算包裹的位置:

RightNew=LeftNew+Width 
BottomNew=TopNew+Height 

現在,您希望測試的每一個點,加MAP_SIZE,並測試它是否在新的矩形內!

TestNew=AddPoints(Test,MAP_SIZE) 

If (TestNew.X>=LeftNew && TestNew.X<=RightNew && TestNew.Y>=TopNew && TestNew.T<=BottomNew) 
{ 
    We have a point inside! 
} 

我沒有詳盡地測試過,但我現在認爲它是正確的。

0

想想在一維您在兩個維度上做到這一點了。你想弄清楚一個數字是否在可能環繞的範圍內,例如。在時鐘的7到2範圍內是3。一旦你有了,你可以對X和Y座標進行測試。

我對簡單的題解:

//assumes start and end are both in [0, divisor). (Because .net and most other languages do modulus WRONG.) 
double ClockDistance(double start, double end, double clockSize) { 
    return (end - start + clockSize) % clockSize; 
} 
//assumes inclusive bounds 
bool ClockBetween(int n, double start, double end, double clockSize) { 
    return ClockDistance(start, n, clockSize) 
      <= ClockDistance(start, end, clockSize); 
} 

從而推廣到:

//assumes rects oriented so bottom < top, not the other way around like in UI 
bool RectContains(double x, double y, double left, double bottom, double right, double top, double worldWidth, double wordlHeight) { 
    return ClockBetween(x, left, right, worldWidth) 
      && ClockBetween(y, bottom, top, worldHeight); 
} 
相關問題