我想从ARC获取所有顶点。我有用于绘制弧的所有数据(例如:起点,终点,起始角,终止角,半径),但我需要从弧数据生成所有顶点。
我已尝试使用一个或两个算法,但我无法从弧数据中获取精确的顶点。
我使用了Bresenham的算法,但我失败了。
现在我正在使用下面的代码,但它不起作用..
double theta = 2 * 3.1415926 / 100;
double c = Math.cos(theta);
double s = Math.sin(theta);
double t;
double x = ((ArcTo) element).getRadius();//we start at angle = 0
double y = 0;
for(int ii = 0; ii < 100; ii++) {
coordinates.add(new Coordinate(x + element.getCenterPoint().getX(), y + element.getCenterPoint().getY()));//output vertex
//apply the rotation matrix
t = x;
x = c * x - s * y;
y = s * t + c * y;
}
请帮帮我。谢谢。
答案 0 :(得分:0)
首先澄清一些
我假设顶点表示像素, ARC 是标准 2D 圆弧(不是椭圆弧!!! ),您的输入数据是:
int (x0,y0),(x1,y1) // star/end points on curve !!!
float a0,a1 // start end angles [rad]
int (xc,yc) // center of circle
int r // radius
请勿使用Bresenham
因为您需要从零角度开始并计算所有像素,直到命中起点。然后翻转绘制标记,以便从该点开始填充像素并停止在终点点击。此外,您需要处理绕组以匹配 ARC 方向。
您可以使用圆参数方程
// just some arc data to test with
float r=25.0;
float a0= 45.0*M_PI/180.0;
float a1=270.0*M_PI/180.0;
int xc=100,x0=xc+floor(r*cos(a0)),x1=xc+floor(r*cos(a1));
int yc=100,y0=yc+floor(r*sin(a0)),y1=yc+floor(r*sin(a1));
// arc rasterize code
int x,y;
float a,da;
// here draw pixels x0,y0 and x1,y1 to avoid rounding holes ...
if (r) da=0.75/float(r); else da=0.1; // step slightly less then pixel to avoid holes
for (a=a0;;a+=da)
{
x=xc+int(floor(r*cos(a)));
y=yc+int(floor(r*sin(a)));
// here draw pixel x,y
if ((x==x1)&&(y==y1)) // stop if endpoint reach
if (fabs(a-a1)<da) // but ignore stop if not at end angle (full or empty circle arc)
break;
}
可能是round
而不是floor
会有更少的像素位置错误。如果您的端点不匹配,那么这将无限循环。如果你稍微调整一下结束条件,你甚至可以避免或者从我x1,y1
重新计算a1
......
您可以使用公式(x-xc)^2+(y-yc)^2=r^2
您需要将 ARC 划分为象限,并将每个处理为单独的弧循环遍历x
或y
并计算其他坐标。循环通过更改更多的坐标
所以在蓝色区域循环y
和红色循环x
。例如,红色区域代码可能如下所示:
int x,y;
for (x=_x0;;x++)
{
y=sqrt((r*r)-((x-xc)*(x-xc)));
// here draw pixel x,y
if (x==_x1) // stop if endpoint reach
break;
}
您需要在象限内计算{strong> ARC 的切割部分的(_x0,_y0),(_x1,_y1)
个起点,并制作_x0<=_x1
。
_x
循环起点/终点坐标的值为xc +/- sqrt(r)
或x0
或x1
_y
循环起点/终点坐标的值为yc +/- sqrt(r)
或y0
或y1
蓝色部分以类似方式完成(只需交换/替换x
和y
)。由于切割这种方法有点复杂,但可以仅对整数进行。 sqrt
可以加速 LUT (限制最大半径),^2
也可以进一步优化。
<强> [注释] 强>
所以,如果我重述参数方程是最简单的实现,但最慢。那么sqrt
方法可以像Bresenham一样快速完成( LUT 可能会更快)但是需要将 ARC 切割成象限的代码在渲染之前需要很少if
秒。
所有代码都在 C ++ 中,可以进一步改进,例如避免一些int/float
转换,在循环之前预先计算一些值等等。
最后一次是Bresenham,但你需要改变一些内部的东西,当你不知道自己在做什么时,你很容易迷失。它还需要削减到八分圆,所以变化的复杂性远远大于sqrt
方法