2010-09-29 87 views
3

我需要使用PHP的圖像庫來繪製類似地鐵地圖(沿相同路徑的多條路線)。下面是一個示例:沿路徑繪製平行線 - PHP GD

 
    ********* 
    ******** * 
    ******* * * 
     * * * 
      * * * 
      * * * 
      * * * 
      * * *      
      * * *      
      * * *      
      * * *      
      * * *      
      * * *     
       * * ******************** 
       * ********************* 
       ********************** 

沿着這條路徑繪製一條線很容易。我不知道如何繪製沿着路徑的多條線,但它們之間有相等的空間。

回答

2

對於給定的A點,多線通過它,對於第一點,你必須決定點是否去「裏面」(B)的軌道,或「外部」(C):

********C 
    D******A * 
    Q*****B * * 
     * * * 
      * E * 

現在,您可以計算B點到A點的偏移量,作爲距離長度=偏移量(例如5px)的路徑,沿角度爲AE'& AD之間的順時針角度的一半(或者'外部'C的AD到AE的順時針角度,或者稍後使用負的偏移量)。你會希望B點距離A沿着A線沿A線穿過角度angle AE + ((angle AD - angle AE)/2)

我絕不是一個數學問題,而且我唯一需要計算的角度就是在javascript中,我會把它作爲一個例子,重寫PHP,請你(任何人誰不知道數學,隨意笑&正確需要時):

var dx = b.x - a.x; 
var dy = b.y - a.y; 
if(dx == 0 && dy == 0){ 
    answer = 0; 
} else if(dx > 0 && dy >= 0){ 
    answer = Math.atan(dy/dx); 
} else if(dx <= 0 && dy > 0){ 
    answer = Math.atan(dx/dy) + (Math.PI * 0.5); 
} else if(dx <= 0 && dy <= 0){ 
    answer = Math.atan(dy/dx) + Math.PI; 
} else if(dx >= 0 && dy <= 0){ 
    answer = Math.atan(dy/dx) + (Math.PI * 1.5); 
} 

所以,在一個方格,d = (0,10),A =(10,10),E =(20,20):

  • 通過AE的角度= 45°(PI/4弧度),通過AD = 180°(PI弧度)
  • 通過AB的角度然後(45 + ((180-45)/2)) => 112.5°(5/8 PI弧度)
  • 5像素=(10,10)通過角度112.5°從A偏移給你乙這個位置:
    • Bx = Ax + (cos(angle) * 5) = +/- 8.1
    • By = Ay + (sin(angle) * 5) = +/- 14.6
  • 在起點D旁邊的'兄弟'點Q處,您沒有先前的參考/計算角度的路徑,所以我將採用垂線:角度DQ =角度DA + 90°(PI/2弧度) (在這個例子中,你可以做Dy + 5,但也許你並不總是開始平行於2軸中的一個)
  • 沖洗並重復所有其他點,在計算出的座標之間畫線。
+0

確定點位於哪一方更容易積完成。這裏是和示例:http://stackoverflow.com/questions/3461453/determine-which-side-of-a-line-a-point-lies – LearnCocos2D 2012-07-15 13:39:00

+0

@ LearnCocos2D:呃..這是一段時間以前(近2年)但是:在這個問題中,你認爲我們需要「確定一個點在哪一邊」? (1)相對於上一行,但更重要的是(2)一開始就做出選擇/用戶決定,以及使用正值('+')或負值('-')偏移量(在本例中爲5px或-5px)的區別。或者我完全錯過了什麼? – Wrikken 2012-07-15 15:00:19

+0

我的確很欣賞與BTW交叉產品的鏈接,現在閱讀它,但我真的很難看到它與手頭問題的相關性,這是如何幫助計算B點的座標? – Wrikken 2012-07-15 15:03:15

0

爲了補充Wrikken的回答,下面是一個使用Objective-C和從該線程和其他線程重建的cocos2d-iphone引擎的實際代碼示例。 atan不是必需的,而是使用交叉產品,請參閱代碼示例末尾的C函數和this link

我也簡單地將偏移矢量的符號從A切換到B,以便從A到C獲得矢量。這樣可以避免兩次調用cosf/sinf。

PS:此代碼在for循環中運行,從i = 0i < numVertices

CGPoint splinePoint = splinePoints[i]; 

CGPoint prevPoint = (i == 0) ? splinePoint : splinePoints[i - 1]; 
CGPoint railPoint = splinePoint; 
CGPoint nextPoint = (i == (numVertices-1)) ? splinePoint : splinePoints[i + 1]; 

CGPoint toPrevPoint = ccpSub(railPoint, prevPoint); 
CGPoint toNextPoint = ccpSub(railPoint, nextPoint); 
float angleToPrevPoint = ccpAngleSigned(kAngleOriginVector, toPrevPoint); 
float angleToNextPoint = ccpAngleSigned(kAngleOriginVector, toNextPoint); 
float offsetAngle = 0.0f; 

if (i > 0 && i < (numVertices - 1)) 
{ 
    offsetAngle = angleToNextPoint + ((angleToPrevPoint-angleToNextPoint)/2); 
} 
else if (i == 0) 
{ 
    offsetAngle = angleToNextPoint + M_PI_2; 
} 
else 
{ 
    offsetAngle = angleToPrevPoint + M_PI_2; 
} 

CGPoint offsetLeftRail, offsetRightRail, offsetRail; 
offsetRail.x = cosf(offsetAngle) * railOffsetFromCenter; 
offsetRail.y = sinf(offsetAngle) * railOffsetFromCenter; 
offsetLeftRail = ccpAdd(railPoint, offsetRail); 
offsetRightRail = ccpAdd(railPoint, ccpMult(offsetRail, -1.0f)); 

if (isPointToTheLeftOfLine(prevPoint, railPoint, offsetLeftRail)) 
{ 
    leftRailSplinePoints[i] = offsetLeftRail; 
    rightRailSplinePoints[i] = offsetRightRail; 
} 
else 
{ 
    leftRailSplinePoints[i] = offsetRightRail; 
    rightRailSplinePoints[i] = offsetLeftRail; 
} 

BOOL isPointToTheLeftOfLine(CGPoint start, CGPoint end, CGPoint test) 
{ 
    return ((end.x - start.x) * (test.y - start.y) - 
      (end.y - start.y) * (test.x - start.x)) > 0; 
} 

幫我畫上了鐵路軌道導軌:

enter image description here

+0

什麼是railOffsetFromCenter? – programmer 2013-02-23 12:46:19