c++ 布雷森汉姆的线算法绘制弧形和旋转
c++ Bresenham's line algorithm draw arc and rotate
我正在寻找用布雷斯纳姆的直线算法制作弧的方法。这个算法画完美的圆,但如果我需要画弧(从0到Pi),并旋转它30度(例如)?
void DrawCircle(HDC hdc,int x0, int y0, int radius)
{
int x = 0;
int y = radius;
int delta = 2 - 2 * radius;
int error = 0;
while(y >= 0) {
//SetPixel(hdc,x0 + x, y0 + y,pencol);
SetPixel(hdc,x0 + x, y0 - y,pencol);
//SetPixel(hdc,x0 - x, y0 + y,pencol);
SetPixel(hdc,x0 - x, y0 - y,pencol);
error = 2 * (delta + y) - 1;
if(delta < 0 && error <= 0) {
++x;
delta += 2 * x + 1;
continue;
}
error = 2 * (delta - x) - 1;
if(delta > 0 && error > 0) {
--y;
delta += 1 - 2 * y;
continue;
}
++x;
delta += 2 * (x - y);
--y;
}
}
要得到1/2个圆(到pi),只调用SetPixel例程之一。要使圆弧旋转30度需要用到一些三角函数。你可以让上面的循环运行,直到你的x/y比率等于tan(30度),然后开始实际绘图,直到你的比率达到你想要停止的值。不是最有效的方法,但它会起作用。为了得到更好的结果,您需要预先计算开始的4个变量值。您可以从上面的运行中获取值,并将它们作为起始值插入,这将非常有效。
你是从Michael Abrash的黑皮书里得到上面的算法的吗?如果没有,我将谷歌作为快速圆/弧绘制的第二个参考点。
好吧,唉,省略的章节没有包括在那里。这是我在网上发现的一些声称来自Abrash的东西:
/* One of Abrash's ellipse algorithms */
void draw_ellipse(int x, int y, int a, int b, int color)
{
int wx, wy;
int thresh;
int asq = a * a;
int bsq = b * b;
int xa, ya;
draw_pixel(x, y+b, color);
draw_pixel(x, y-b, color);
wx = 0;
wy = b;
xa = 0;
ya = asq * 2 * b;
thresh = asq / 4 - asq * b;
for (;;) {
thresh += xa + bsq;
if (thresh >= 0) {
ya -= asq * 2;
thresh -= ya;
wy--;
}
xa += bsq * 2;
wx++;
if (xa >= ya)
break;
draw_pixel(x+wx, y-wy, color);
draw_pixel(x-wx, y-wy, color);
draw_pixel(x+wx, y+wy, color);
draw_pixel(x-wx, y+wy, color);
}
draw_pixel(x+a, y, color);
draw_pixel(x-a, y, color);
wx = a;
wy = 0;
xa = bsq * 2 * a;
ya = 0;
thresh = bsq / 4 - bsq * a;
for (;;) {
thresh += ya + asq;
if (thresh >= 0) {
xa -= bsq * 2;
thresh = thresh - xa;
wx--;
}
ya += asq * 2;
wy++;
if (ya > xa)
break;
draw_pixel(x+wx, y-wy, color);
draw_pixel(x-wx, y-wy, color);
draw_pixel(x+wx, y+wy, color);
draw_pixel(x-wx, y+wy, color);
}
}
意思是每次画1/8的圆x4,然后翻出剩下的1/8。但还是没有直接回答你的问题。正在努力……
同样,上面的代码应该可以工作,您只需要仔细控制开始和结束条件。y>= 0需要成为完成"弧"长度时的y值,并且需要计算起始值作为弧的起始值。
这将不是一个直接的任务,因为事情是这样的。使用浮点例程可能更容易。数学运算要简单得多,处理器也倾向于比设计这些整数例程时更好地处理它们。
如果你不需要确定的Bresenham,有一个快速的步骤方法介绍在这篇文章,你可以设置中心点,起点和圆弧角。它不需要停止准则,因为它已经包含在算法中(按圆角)。使它快速的是切向和径向运动因子的预计算,实际的循环没有三角函数调用,只有乘法、加法和减法。
我想有三种方法:
A)渐进式像布里森汉姆
B)像这样细分方法
C)步骤(或段)方法
我将举一个缓慢的步进方法的例子(如果速度很重要,不要使用这个):
// I know the question is tagged c++, but the idea comes clear in javascript
var start_angle = 0.5, end_angle = 1.1, r = 30;
for(var i = start_angle; i < end_angle; i = i + 0.05)
{
drawpixel(x: 50 + Math.cos(i) * r, y: 100 + Math.sin(i) * r); // center point is (x = 50, y = 100)
}
缓慢来自于cos和sin,它们在循环中(不必要地)重复。这可以通过预先计算cos和sin来解决,正如上面提到的SO帖子所述。这意味着巨大的加速(在排名前5的javascript引擎中平均12倍)。
我对各种圆和弧绘制算法进行了非完全可比的速度测试。Bresenham算法速度很快,但需要添加启动和停止准则逻辑,这会使算法速度变慢。如果你真的需要Bresenham和arc,我没有现成的解决方案,也没有找到。这当然是可能的。顺便说一下,与Bresenham相比,使用预计算触发器的step方法在性能上并没有那么差(至少在javascript中)。请用c++测试并报告
- 与互斥锁相比,旋转锁可以保证上下文切换
- QuadTree只在窗口的右上角绘制
- 绘制旋转的三角形
- flutter:即使shouldRepaint()返回true,自定义画家也不会重新绘制
- 旋转模型矩阵时的形状失真
- 四边形的 2D 旋转
- 垂直方向的 Gtk3+ 旋转按钮 (c/c++)
- 如何在QT中的自定义视频小工具t上绘制矩形
- 发布旋转矩阵(openGL/glm)
- 如何在Visual Basic中使用矩形函数OpenGL绘制矩形
- 无法使用VAO和EBO(openGL)绘制多个对象
- 为什么我的点没有在 OpenGL 中绘制鼠标所在的位置?
- 绘制顺时针三角形,重新排序点
- 如何绘制具有随机顶点数量的多边形并旋转它们
- 在使用PI上的OpenGL ES绘制之前,如何旋转纹理
- 旋转使用OpenGL绘制的二维对象
- 在画布上绘制旋转图像
- 如何在opencvc++中绘制眼睛周围的旋转边界框
- c++ 布雷森汉姆的线算法绘制弧形和旋转
- c++旋转立方体坐标(非绘制)