带粗细绘制算法的圆

标签 c algorithm geometry bresenham

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

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 我不想使用任何外部库,拜托!

最佳答案

如果您按照 Midpoint circle algorithm 的说明沿着八分圆扫描,您的主坐标 y 将始终增加 1。然后您可以一次绘制两个圆,因为它们的主坐标是同步的。

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

你为两个圆圈保持状态为 xerr,内圈 i 和外圈 o。内圆到达对角线后,内点位于该对角线上。这意味着您正在绘制八个相邻的八分圆扇区。

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

下面的代码将绘制一个具有给定内半径和外半径的空心圆。线宽为 ro - ri + 1,因此即使半径相等也会打印一个像素宽的圆。如果内半径小于外半径,则不会打印任何内容。

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);
            }
        }
    }
}

关于带粗细绘制算法的圆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27755514/

相关文章:

html - 裁剪大圆的顶部和底部

algorithm - 给定点位于多边形内部或外部

c - 生产者/消费者实现: Stuck in consumer loop

android - 使用 Cygwin 创建 .SO 文件时出错

c - 使用 bsearch() 搜索 char 数组时有没有找到元素位置的方法

javascript - 如何计算预计时间精度

algorithm - 构建或查找 "relevant terms"建议功能

c++ - 如何计算二维对数色度?

c - C Linux 编程中的信号量

autocomplete - 如何使用 ZStack & Geometry 定位列表?