沿路径绘制平行线 - PHP GD

时间:2010-09-29 18:17:44

标签: php path drawing

我需要使用PHP的图像库绘制类似地铁地图(沿同一路径的多条路线)的内容。这是一个例子:

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

在此路径上绘制一条线很容易。我不知道如何绘制多条沿着路径行的行,但它们之间有相等的空间。

2 个答案:

答案 0 :(得分:2)

对于给定的A点,以及通过它的更多行,对于第一点,您必须确定点是在“内部”(B)轨道还是“外部”(C):

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

现在,您可以计算点B到点A的偏移量,作为一个路径,其中长度=偏移量(例如5px)沿着角度,即AE和AE之间的顺时针角度的一半。 AD用于'内部'B(或者从AD到AE的顺时针角度用于'外部'C,或者稍后使用负偏移)。你需要B点与A之间的距离为5px,通过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 rad)的角度,通过AD = 180°(PI rad)
  • 然后通过AB的角度为(45 + ((180-45)/2)) =&gt; 112.5°(5/8 PI rad)
  • 从A =(10,10)到角度112.5°的5px偏移为您提供B的这个位置:
    • Bx = Ax + (cos(angle) * 5) = +/- 8.1
    • By = Ay + (sin(angle) * 5) = +/- 14.6
  • 在起始点D旁边的'兄弟'点Q,您没有先前的路径来参考/计算角度,所以我采取垂直:角度DQ =角度DA + 90°(PI / 2 rad)(在示例中你可以做Dy + 5,但也许你并不总是与2轴中的一个并行)
  • 冲洗并重复所有其他点,在计算的坐标之间画线。

答案 1 :(得分:0)

为了补充Wrikken的答案,这里是使用Objective-C的实际代码示例和从该线程和其他人重建的cocos2d-iphone引擎。不需要atan,而是使用交叉产品,请参阅代码示例末尾的C函数和this link

我还简单地将偏移矢量的符号从A切换到B,以便从A到C得到矢量。这避免了两次调用cosf / sinf。

PS:此代码在从i = 0i < numVertices的for循环中运行。

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