首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >带厚度绘图算法的圆

带厚度绘图算法的圆
EN

Stack Overflow用户
提问于 2015-01-03 13:44:55
回答 2查看 5.1K关注 0票数 5

目前,我使用的是Bresenham的圆绘制算法,该算法可以很好地绘制圆圈,但是我想要一种相对快速有效的方法来绘制一个指定厚度的圆(因为Bresenham的方法只绘制一个像素的厚度)。我意识到我可以简单地用不同的半径绘制多个圆圈,但我相信这将是非常低效率的(而且效率很重要,因为这将运行在Arduino上,在那里每微秒都是宝贵的)。我目前正在使用以下代码:

代码语言:javascript
运行
复制
void circle(byte xc, byte yc, int radius, Colour colour) {
  int x = -radius, y = 0, err = 2 - 2 * radius;
  while(x < 0) {
    setPixel(xc - x, yc + y, colour);
    setPixel(xc - y, yc - x, colour);
    setPixel(xc + x, yc - y, colour);
    setPixel(xc + y, yc + x, colour);
    radius = err;
    if(radius <= y) {
      err += ++y * 2 + 1;
    }
    if(radius > x || err > y) {
      err += ++x * 2 + 1;
    }
  }
}

我如何修改它以允许指定圆圈的厚度?PS我不想使用任何外部库,请!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-01-03 16:03:02

如果你沿着中点圆算法解释的八进制扫描,你的主要坐标y总是会增加一个。然后您可以同时绘制两个圆圈,因为它们的主要坐标是同步的。

不是放置像素,而是在具有相同y (或x)坐标的内圆和外圆的点之间绘制水平(和垂直)线。你这样做,直到外圆到达对角线。

将状态与xerr保持为两个圆圈,一个是内圈i,另一个是外圆o。内圆到达对角线后,内点就在对角线上。这意味着你画的是八个相邻的重要扇区。

这个想法与@oakad在评论中提出的想法非常相似,但不需要保留一个列表。中点圆算法可能比Bresenham算法慢,因此可能还有改进的余地,但内存占用量低是一个优势。

下面的代码将画一个空心圆与给定的内外半径。线宽是ro - ri + 1,所以即使是相同的半径也会打印出一个一个像素宽的圆。如果内部半径小于外部半径,它就不会打印任何东西。

代码语言:javascript
运行
复制
void xLine(int x1, int x2, int y, int colour)
{
    while (x1 <= x2) setPixel(x1++, y, colour);
}

void yLine(int x, int y1, int y2, int colour)
{
    while (y1 <= y2) setPixel(x, y1++, colour);
}

void circle2(int xc, int yc, int inner, int outer, int colour)
{
    int xo = outer;
    int xi = inner;
    int y = 0;
    int erro = 1 - xo;
    int erri = 1 - xi;

    while(xo >= y) {
        xLine(xc + xi, xc + xo, yc + y,  colour);
        yLine(xc + y,  yc + xi, yc + xo, colour);
        xLine(xc - xo, xc - xi, yc + y,  colour);
        yLine(xc - y,  yc + xi, yc + xo, colour);
        xLine(xc - xo, xc - xi, yc - y,  colour);
        yLine(xc - y,  yc - xo, yc - xi, colour);
        xLine(xc + xi, xc + xo, yc - y,  colour);
        yLine(xc + y,  yc - xo, yc - xi, colour);

        y++;

        if (erro < 0) {
            erro += 2 * y + 1;
        } else {
            xo--;
            erro += 2 * (y - xo + 1);
        }

        if (y > inner) {
            xi = y;
        } else {
            if (erri < 0) {
                erri += 2 * y + 1;
            } else {
                xi--;
                erri += 2 * (y - xi + 1);
            }
        }
    }
}
票数 4
EN

Stack Overflow用户

发布于 2017-07-04 18:58:45

下面的解决方案可能很慢,但是非常简单。

首先,使用Bresenham算法绘制内圆和外圆。然后,检查条件:

代码语言:javascript
运行
复制
if (pow(i - centre, 2) + pow(j - centre, 2) <= pow(outern_radius,2) &&
            pow(i - centre, 2) + pow(j - centre, 2) >= pow(inner_radius,2))

如果满足,setPixel(i,j)。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27755514

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档