📜  使用布雷森汉姆算法的圆上的点的邻居

📅  最后修改于: 2021-04-29 01:17:53             🧑  作者: Mango

给定圆心及其半径。我们的任务是找到离散圆上任意点的邻居。

例子:

Input :  Center = (0, 0), 
         Radius = 3 
         Point for determining neighbors = (2, 2)
Output : Neighbors of given point are : (1, 3), (3, 1)

Input : Center = (2, 2) 
        Radius 2
        Point of determining neighbors = (0, 2)
Output : Neighbors of given point are : (1, 4), (3, 4)

离散圆上任何点的邻居都是那些比其原始x坐标少一个或多于一个x坐标的点。

我们使用布雷森汉姆的圆生成算法来提取在像素计算机屏幕上绘制圆所需的整数点。

布雷申汉姆

圆具有高度对称的特性,这是在像素的计算机屏幕上绘制圆时所需要的。 Bresenham的圆算法计算像素的前45度位置,并使用圆的8向对称特性计算以原点为中心的圆外围的其余像素。

布雷申汉姆2

推导:考虑一个无限小的连续圆弧,如下图所示,假设我们要沿着以原点为中心,半径为r的顺时针圆弧移动,并且运动位于第一个八分圆中八分圆,所以我们的限制是从(0,r)到(r / \sqrt{2} ,/ \sqrt{2} ),其中x = y。我们知道,在这个特定的八分圆中,y坐标的减小小于x坐标的增大,或者可以说沿x轴的运动大于沿y轴的运动,因此,x坐标在第一个八分圆。现在,我们想知道y是否会随x改变。为了知道y随x的变化,bresenham’s引入了一个名为决策参数的变量,该变量将在循环运行时更新其值。

现在,我们需要了解如何选择下一个像素,在图中,f(N)和f(S)分别是计算从原点到像素N和S的距离时涉及的误差,无论哪个是更少,我们将选择该像素。决策参数定义为d = f(N)+ f(S),如果d <= 0,则N将是下一个像素,否则S将是下一个像素。我们将继续执行此过程,直到x

因此,本文主要不是针对布雷森汉姆算法,因此,我将跳过决策参数的推导,但是如果您想了解决策参数的推导,请转到参考链接。

注意:点的邻居可以是任意数量,并且邻居的y坐标应与其输入像素具有相同的符号,对于y坐标为零的那些像素,我们将打印出所有邻居,而不考虑其符号。

离散的几何对象由一组有限的整数点组成。这个集合通常非常稀疏。因此,数组表示完全没有空间来存储。我们将使用具有数据值是y坐标和键值作为x坐标的链表的哈希图。我们可以使用键值轻松访问它们,并且还可以节省空间。

下面是C++ stl程序,用于确定给定点的邻居。

// C++ program to find neighbors of a given point on circle
#include 
using namespace std;
  
// map to store all the pixels of circle
map > mymap;
map >::iterator it;
  
// This program will print all the stored pixels.
void showallpoints(map >& mymap)
{
    // To print out all the stored pixels,
    // we will traverse the map using iterator
    for (it = mymap.begin(); it != mymap.end(); it++) {
  
        // List contains all the y-coordinate.
        list temp = it->second;
  
        for (auto p = temp.begin(); p != temp.end(); p++) {
            cout << "(" << it->first << ", " << *p << ")\n";
        }
    }
}
  
// This function will stored the pixels.
void putpixelone(int m, int n, map >& mymap)
{
    // check if the given pixel is present already in the
    // map then discard that pixel and return the function.
    map >::iterator it;
  
    // if x-coordinate of the pixel is present in the map then
    // it will give iterator pointing to list of those pixels 
    // which are having same x-coordinate as the input pixel
    if (mymap.find(m) != mymap.end()) {
  
        it = mymap.find(m);
        list temp = it->second;
        list::iterator p;
  
        // Checking for y coordinate
        for (p = temp.begin(); p != temp.end(); p++) 
            if (*p == n)
                return;
  
        // if map doesn't contain pixels having same y-
        // coordinate then pixel are different and store
        // the pixel
        mymap[m].push_back(n);
    } else
  
        // Neither x nor y coordinate are same.
        // put the pixel into the map
        mymap[m].push_back(n);
  
    return;
}
  
// generate all the pixels using 8 way-symmetry of circle
void putpixelall(int p, int q, int x1, int y1)
{
    putpixelone(p + x1, q + y1, mymap);
    putpixelone(q + x1, p + y1, mymap);
    putpixelone(q + x1, -p + y1, mymap);
    putpixelone(p + x1, -q + y1, mymap);
    putpixelone(-p + x1, -q + y1, mymap);
    putpixelone(-q + x1, -p + y1, mymap);
    putpixelone(-q + x1, p + y1, mymap);
    putpixelone(-p + x1, q + y1, mymap);
    return;
}
  
// Brensenham's cirle algorithm
void circle(int centerx, int centery, int r)
{
    // initial coordinate will be (0, radius) and we 
    // will move counter-clockwise from this coordinate
    int x = 0;
    int y = r;
  
    // decision parameter for initial coordinate
    float decision_para = 3 - 2 * (r);
    putpixelall(x, y, centerx, centery);
  
    while (x < y) {
  
        // x will always increase by 1 unit
        x = x + 1;
        if (decision_para <= 0) {
  
            // if decision parameter is negative then N 
            // will be next pixel N(x+1, y)
            decision_para = decision_para + 4 * x + 6;
        } else {
  
            // if decision parameter is positive then N 
            // will be next pixel S(x+1, y-1)
            y = y - 1;
            decision_para = decision_para + 4 * (x - y) + 10;
        }
  
        // Function call to generate all the pixels by symmetry
        putpixelall(x, y, centerx, centery);
    }
    return;
}
// this program will find the neighbors of a given point`
void neighbours(map >& mymap, int given_pointx, 
                                             int given_pointy)
{
    for (it = mymap.begin(); it != mymap.end(); ++it) {
        if (it->first == given_pointx + 1 || 
            it->first == given_pointx - 1) {
            list temp1 = it->second;
            list::iterator itr1;
            for (itr1 = temp1.begin(); itr1 != temp1.end(); ++itr1) {
  
                // Checking for same-sign.
                if (given_pointy >= 0 && *itr1 >= 0)
                    cout << "(" << it->first << ", " << *itr1 << ")\n";
                else if (given_pointy <= 0 && *itr1 <= 0)
                    cout << "(" << it->first << ", " << *itr1 << ")\n";
                else
                    continue;
            }
        }
    }
}
  
// Driver code
int main()
{
    int center_x = 0, center_y = 0;
    float r = 3.0;
    circle(center_x, center_y, r);
    showallpoints(mymap);
    int nx = 3, ny = 0;
    neighbours(mymap, nx, ny);
    cout << endl;
    return 0;
}

输出:

(-3, 0), (-3, -1), (-3, 1), (-2, -2), (-2, 2), (-1, -3), (-1, 3), (0, 3)
(0, -3), (1, 3), (1, -3), (2, 2), (2, -2), (3, 0), (3, 1), (3, -1)
 Neighbours of given point are : (2, 2), (2, -2)

参考 :
https://www.slideshare.net/tahersb/bresenham-circle