在计算机图形学中,平滑曲线的生成是一个常见且重要的任务。传统的平滑曲线方法包括使用插值或逼近技术,如NURBS、样条曲线、Cattmull-Rom、Chaikin或贝塞尔曲线,以及一些过滤技术。本文介绍的HotPoints方法是一种基于不同逻辑的近似方法,其输出结果与Chaikin方法非常相似。
HotPoints方法的核心逻辑可以通过逐步插图来解释。如果重复执行这些步骤至少3次迭代循环,将得到一个平滑的曲线。这种方法的算法质量非常满意。
如所见,主要问题或有趣的点在于如何找到绿色点的坐标。如何计算它们?现在,让回到大学时代,回忆一些几何主题,如直线、圆、椭圆等。
实际上,Q点可以沿着对角线移动,但当F点和Q点垂直时,可以得到最佳结果。
经过一些数学运算和消除后,最终可以使用以下公式计算Q点的笛卡尔坐标:
F := 1.0; // F: 0.0 .. 2.0
dx := p2.X - p1.X;
dy := p2.Y - p1.Y;
// a: 主轴,b: 副轴
a := dx / 2.82843; // 2*2^0.5 = 2.82843
b := dy / 2.82843;
// O: 中/中心点
Ox := (P1.X + P2.X) / 2.0;
Oy := (P1.Y + P2.Y) / 2.0;
Q1.X := Ox - F * a / 1.41421; // sqrt(2) = 1.41421
Q1.y := Oy - F * b / 1.41421;
Q2.X := Ox + F * a / 1.41421;
Q2.y := Oy + F * b / 1.41421;
让用代码来引导!
//////////////////////////////////////////
// HotPoints近似
////////////////////////////////////////////
// 计算热点
for i:=0 to nItera-1 do
begin
k := 0;
for j:=0 to nPoints-1 do
begin
j0 := (j+0 + nPoints) mod nPoints; // 循环形式
j1 := (j+1 + nPoints) mod nPoints;
p1.X := trunc(pinn[j0].X + 0.5);
p1.Y := trunc(pinn[j0].Y + 0.5);
p2.X := trunc(pinn[j1].X + 0.5);
p2.Y := trunc(pinn[j1].Y + 0.5);
dx := p2.X - p1.X;
dy := p2.Y - p1.Y;
radiX := dx / 2.82843; // 2 * 2^0.5 = 2.82843
radiY := dy / 2.82843; //
Ox := (P1.X + P2.X) / 2.0;
Oy := (P1.Y + P2.Y) / 2.0;
Q1.X := Ox - F * radiX / 1.41421; // sqrt(2) = 1.41421
Q1.y := Oy - F * radiY / 1.41421;
pout[k] := Q1; k := k + 1;
Q2.X := Ox + F * radiX / 1.41421;
Q2.y := Oy + F * radiY / 1.41421;
pout[k] := Q2; k := k + 1;
end; // j
nPoints := k;
for k:=0 to nPoints-1 do pinn[k] := pout[k]; // !!!
end; // 迭代,i
// 绘制曲线
for k:=0 to nPoints-1 do
begin
X := trunc(pout[k].X + 0.5);
Y := trunc(pout[k].Y + 0.5);
if (k = 0) then
imgDraw.Canvas.MoveTo(X, Y)
else
imgDraw.Canvas.LineTo(X, Y);
end;
这是描述步骤的中间运行状态:
为了比较,请参阅下面的Chaikin和HotPoints的结果。它们看起来几乎相同。
注:原始测试点是从上述(*)文章中借用的。