如果这个过于简单,我道歉,但我是数学专业最可能的事情,而且我无法将抽象公式简化为可行的代码。我知道一条线的公式,但把它变成代码让我头晕目眩。并强调我的代码调试器。
给定一个2D网格坐标系,我需要能够指定一个起点X1,Y1和一个终点X2,Y2,并直接在这两个点之间的一条直线上计算所有网格单元的列表。
所以如果......
X1,Y1 = 3,3
X2,Y2 = 0,5
我想计算一个点数组
3,3
2,4
1,4
0,5
或类似的东西。能够按顺序列出这些点也很重要 - 如上所述,我从原点X,Y开始,然后朝目的地X,Y方向移动。
(不,这不是作业 - 我已经看到了这里要求了很多其他的数学问题,所以我会先把它弄出去。也许如果我把它作为家庭作业25年前我现在不需要问!)
我确实发现PHP Find Coordinates between two points似乎在讨论解决方案,但评论表明“已接受”的答案并不完整。
非常感谢。
答案 0 :(得分:4)
听起来你最好的选择可能是Bresenham's algorithm for drawing a line,除了不是绘制你将捕获x,y值的点。
答案 1 :(得分:1)
我假设您需要整数坐标,因为这是您在示例中列出的内容。但请注意,对于任何一组(x1,y1)和(x2,y2),情况不一定如此。我的答案只给你全数x坐标。
我会使用线性方程的两点形式。 yi =(y2-y1)/(x2-x1)*(xi-x1)+ y1 其中(xi,yi)是您要寻找的点。
for ($xi=$x1; $xi<$x2; $xi++) {
$yi = ($y2-$y1)/($x2-$x1)*($xi-$x1) + $y1
echo $xi + "," + $yi
}
在运行上述代码之前,请确保您拥有$x1 < $x2
。
当您在两个任意点(x1,y1)和(x2,y2)之间绘制一条直线并且想要输出与该直线相交的正方形(网格单元格)列时,会出现更复杂的情况。
答案 2 :(得分:1)
因此,对于更多细节,这里是一个PHP函数,它将始终返回以第一个数组元素作为原点而最后一个作为目标的点。这是经过测试和运作的,是http://alex.moutonking.com/wordpress/?p=44的改编版。
function bresenham($x1, $y1, $x2, $y2, $guaranteeEndPoint=true) {
$xBegin = $x1;
$yBegin = $y1;
$xEnd = $x2;
$yEnd = $y2;
$dots = array();
$steep = abs($y2 - $y1) > abs($x2 - $x1);
if ($steep) {
$tmp = $x1;
$x1 = $y1;
$y1 = $tmp;
$tmp = $x2;
$x2 = $y2;
$y2 = $tmp;
}
if ($x1 > $x2) {
$tmp = $x1;
$x1 = $x2;
$x2 = $tmp;
$tmp = $y1;
$y1 = $y2;
$y2 = $tmp;
}
$deltax = floor($x2 - $x1);
$deltay = floor(abs($y2 - $y1));
$error = 0;
$deltaerr = $deltay / $deltax;
$y = $y1;
$ystep = ($y1 < $y2) ? 1 : -1;
for ($x = $x1; $x < $x2; $x++) {
$dots[] = $steep ? array($y, $x) : array($x, $y);
$error += $deltaerr;
if ($error >= 0.5) {
$y += $ystep;
$error -= 1;
}
}
if ($guaranteeEndPoint) {
if ((($xEnd - $x) * ($xEnd - $x) + ($yEnd - $y) * ($yEnd - $y)) < (($xBegin - $x) * ($xBegin - $x) + ($yBegin - $y) * ($yBegin - $y))) {
$dots[] = array($xEnd, $yEnd);
} else
$dots[] = array($xBegin, $yBegin);
}
if ($dots[0][0] != $xBegin and $dots[0][1] != $yBegin) {
return array_reverse($dots);
} else {
return $dots;
}
}
答案 3 :(得分:0)
我不知道这是特别优雅的,但是我会这样做:
function getLinePoints( $startPoint, $endPoint ){
$totalSteps = max( abs( $startPoint[0] - $endPoint[0] ), abs( $startPoint[1] - $endPoint[1] ) );
if ( $totalSteps == 0 ){
return $startPoint;
}
$xStep = ( $endPoint[0] - $startPoint[0] ) / $totalSteps;
$yStep = ( $endPoint[1] - $startPoint[1] ) / $totalSteps;
$points[] = $currentPoint = $startPoint;
for( $step = 0; $step < $totalSteps; $step++ ){
$currentPoint[0] += $xStep;
$currentPoint[1] += $yStep;
$points[] = array( round( $currentPoint[0], 0 ), round( $currentPoint[1], 0 ) );
}
return $points;
}
$pointA = array( 3, 3 );
$pointB = array( 0, 5 );
$points = getLinePoints( $pointA, $pointB );
这需要执行以下步骤:
返回值应为:
Array(
Array( 3, 3 ),
Array( 2, 4 ),
Array( 1, 4 ),
Array( 0, 5 )
)
答案 4 :(得分:0)
看起来你正在寻找插值方法,检查一下:http://paulbourke.net/miscellaneous/interpolation/(你需要的是线性插值)