Shi*_*ryu 11 php algorithm bezier gd
我正在玩GD库一段时间,特别是Bezier曲线atm.
我使用了一些我修改过的类(严重的eval()
......).我发现它是GD中使用的通用算法并转换为GD.
现在我想把它带到另一个层面:我想要一些颜色.
线条颜色没有问题,但填充颜色更难.
我的问题是:
那有没有适合的算法?我的意思是数学算法或任何已经这样做的语言,以便我可以将它转移到PHP + GD?
EDIT2 所以,我尝试使用更加曲线的@MizardX解决方案:
哪个应该显示:
并给出这个:
编辑
我已经阅读了@MizardX解决方案.用imagefilledpolygon
它来使它工作.
但它没有按预期工作.请参阅下图以查看问题.顶部图形是我所期望的(现在没有黑线,只有红色部分).
使用的坐标:
底部是我得到的那种算法......
将贝塞尔曲线转换为折线/多边形,并填充它.如果以足够近的间隔(~1像素)评估贝塞尔多项式,它将与理想的贝塞尔曲线相同.
我不知道你对Bezier曲线有多熟悉,但这是一个速成课程:
<?php
// Calculate the coordinate of the Bezier curve at $t = 0..1
function Bezier_eval($p1,$p2,$p3,$p4,$t) {
// lines between successive pairs of points (degree 1)
$q1 = array((1-$t) * $p1[0] + $t * $p2[0],(1-$t) * $p1[1] + $t * $p2[1]);
$q2 = array((1-$t) * $p2[0] + $t * $p3[0],(1-$t) * $p2[1] + $t * $p3[1]);
$q3 = array((1-$t) * $p3[0] + $t * $p4[0],(1-$t) * $p3[1] + $t * $p4[1]);
// curves between successive pairs of lines. (degree 2)
$r1 = array((1-$t) * $q1[0] + $t * $q2[0],(1-$t) * $q1[1] + $t * $q2[1]);
$r2 = array((1-$t) * $q2[0] + $t * $q3[0],(1-$t) * $q2[1] + $t * $q3[1]);
// final curve between the two 2-degree curves. (degree 3)
return array((1-$t) * $r1[0] + $t * $r2[0],(1-$t) * $r1[1] + $t * $r2[1]);
}
// Calculate the squared distance between two points
function Point_distance2($p1,$p2) {
$dx = $p2[0] - $p1[0];
$dy = $p2[1] - $p1[1];
return $dx * $dx + $dy * $dy;
}
// Convert the curve to a polyline
function Bezier_convert($p1,$p2,$p3,$p4,$tolerance) {
$t1 = 0.0;
$prev = $p1;
$t2 = 0.1;
$tol2 = $tolerance * $tolerance;
$result []= $prev[0];
$result []= $prev[1];
while ($t1 < 1.0) {
if ($t2 > 1.0) {
$t2 = 1.0;
}
$next = Bezier_eval($p1,$p2,$p3,$p4,$t2);
$dist = Point_distance2($prev,$next);
while ($dist > $tol2) {
// Halve the distance until small enough
$t2 = $t1 + ($t2 - $t1) * 0.5;
$next = Bezier_eval($p1,$p2,$p3,$p4,$t2);
$dist = Point_distance2($prev,$next);
}
// the image*polygon functions expect a flattened array of coordiantes
$result []= $next[0];
$result []= $next[1];
$t1 = $t2;
$prev = $next;
$t2 = $t1 + 0.1;
}
return $result;
}
// Draw a Bezier curve on an image
function Bezier_drawfilled($image,$p1,$p2,$p3,$p4,$color) {
$polygon = Bezier_convert($p1,$p2,$p3,$p4,1.0);
imagefilledpolygon($image,$polygon,count($polygon)/2,$color);
}
?>
Run Code Online (Sandbox Code Playgroud)
编辑:
我忘了测试这个例程.确实如你所说; 它没有给出正确的结果.现在我修复了两个错误:
$p1
和$p2
.我给他们改名$prev
和$next
.while
-loop.现在它循环直到距离足够小,而不是足够大.