我当前的应用程序需要一种算法来绘制给定图像的直线,圆和旋转椭圆。我在互联网上搜索过,发现这篇文章Algorithm for Drawing Curves解释了如何实现它。我正在尝试实现C#中描述的方法,但是在第40行中有一个Int和Bool之间的操作。
有问题的操作是:
x1 = 2 * err > dy; // <- this
y1 = 2 * (err + yy) < -dy); // <- this
if (2 * err < dx || y1) // <- this
{
y0 += sy;
dy += xy;
err += dx += xx;
}
if (2 * err > dx || x1) // <- this
{
x0 += sx;
dx += xy;
err += dy += yy;
}
变量x1,y1是整数,err,yy和dy是double。我不知道作者使用了哪种编程语言,但显然似乎是在C语言中。
如何在C#中翻译此操作?
我尝试在C#中实现的完整方法:
private static Point[] plotQuadRationalBezierSeg(int x0, int y0, int x1, int y1, int x2, int y2, double w)
{
// plot a limited rational Bezier segment, squared weight
var points = new List<Point>();
int sx = x2 - x1, sy = y2 - y1; // relative values for checks
double dx = x0 - x2, dy = y0 - y2, xx = x0 - x1, yy = y0 - y1;
double xy = xx * sy + yy * sx, cur = xx * sy - yy * sx, err; // curvature
//assert(xx * sx <= 0.0 && yy * sy <= 0.0); // sign of gradient must not change
if (cur != 0.0 && w > 0.0)
{ /* no straight line */
if (sx * (long)sx + sy * (long)sy > xx * xx + yy * yy)
{ // begin with longer part
x2 = x0;
x0 -= (int)dx;
y2 = y0;
y0 -= (int)dy;
cur = -cur; //swap P0 P2
}
xx = 2.0 * (4.0 * w * sx * xx + dx * dx); //differences 2nd degree
yy = 2.0 * (4.0 * w * sy * yy + dy * dy);
sx = x0 < x2 ? 1 : -1; // x step direction
sy = y0 < y2 ? 1 : -1; // y step direction
xy = -2.0 * sx * sy * (2.0 * w * xy + dx * dy);
if (cur * sx * sy < 0.0)
{
// negated curvature?
xx = -xx;
yy = -yy;
xy = -xy;
cur = -cur;
}
dx = 4.0 * w * (x1 - x0) * sy * cur + xx / 2.0 + xy; //differences 1st degree
dy = 4.0 * w * (y0 - y1) * sx * cur + yy / 2.0 + xy;
if (w < 0.5 && (dy > xy || dx < xy))
{
// flat ellipse, algorithm fails
cur = (w + 1.0) / 2.0;
w = Math.Sqrt(w);
xy = 1.0 / (w + 1.0);
sx = (int)Math.Floor((x0 + 2.0 * w * x1 + x2) * xy / 2.0 + 0.5); //subdivide curve in half
sy = (int)Math.Floor((y0 + 2.0 * w * y1 + y2) * xy / 2.0 + 0.5);
dx = (int)Math.Floor((w * x1 + x0) * xy + 0.5);
dy = (int)Math.Floor((y1 * w + y0) * xy + 0.5);
points.AddRange(plotQuadRationalBezierSeg(x0, y0, (int)dx, (int)dy, sx, sy, cur)); //plot separately
dx = Math.Floor((w * x1 + x2) * xy + 0.5); dy = Math.Floor((y1 * w + y2) * xy + 0.5);
points.AddRange(plotQuadRationalBezierSeg(sx, sy, (int)dx, (int)dy, x2, y2, cur));
return points.ToArray();
}
//error 1.step
err = dx + dy - xy;
do
{
points.Add(new Point(x0, y0)); // plot curve
if (x0 == x2 && y0 == y2)
return points.ToArray(); // last pixel -> curve finished
x1 = 2 * err > dy;
y1 = 2 * (err + yy) < -dy); // save value for test of x step
if (2 * err < dx || y1)
{
y0 += sy;
dy += xy;
err += dx += xx;
}/* y step */
if (2 * err > dx || x1)
{
x0 += sx;
dx += xy;
err += dy += yy;
}/* x step */
} while (dy <= xy && dx >= xy); // gradient negates -> algorithm fails
}
// plot remaining needle to end
points.AddRange(
new Point[] {
new Point(x0, y0),
new Point(x2, y2),
});
return points.ToArray();
}