Open In App

Neighbors of a point on a circle using Bresenham’s algorithm

Last Updated : 31 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given a center of a circle and its radius. our task is to find the neighbors of any point on the discrete circle. 
Examples: 

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)


The neighbours of any point on the discrete circle are those points which are having one less or one more x coordinate from its original x coordinate. 
 


We use bresenham’s circle generation algorithm to extract out integer points required to draw a circle on computer screen of pixels.
 

Breshanham


Circle have the property of being highly symmetrical which is needed when it comes to drawing them on the computer screen of pixels. Bresenham’s circle algorithm calculates the locations of the pixels in the first 45 degrees and remaining pixels on the periphery of a circle which is centered at origin are computed by using 8-way symmetry property of the circle.
 

Breshanham2


Derivation: Consider an infinitesimally small continuous arc of a circle as shown in the figure below, Let’s suppose that we want to move along a clockwise circular arc with center at the origin, with radius r and our motion lies in the first octant lies in first octant, so our limits are from (0, r) to (r/\sqrt{2}        , r/\sqrt{2}        ) where x = y. as we know that, In this particular octant, the decrease in the y coordinate is less than increase in the x coordinate or you can say that the movement along x axis is more than the movement along y axis so, the x coordinate always increases in first octant. now, we want to know whether the y will change with x or not. In order to know the variation of y with x, bresenham’s introduced a variable named as decision parameter which will update their value as the loop runs.
Now, we need to understand that how we will choose the next pixel, In the figure, f(N) and f(S) are errors involved in calculating the distances from origin to pixel N and S respectively and whichever is comes out to be less we’ll choose that pixel. decision parameter is defined as d = f(N)+f(S), if d <= 0 then N will be the next pixel otherwise S will be the next pixel. we will keep doing this procedure until x<y condition holds and by taking all symmetric points we will end up with all the integer points required to show a circle on computer screen of pixels.
This article is not predominantly focused on bresenham’s algorithm therefore, I’ll skip the derivation of decision parameter but if you want to understand of derivation of decision parameter then go to the reference links.
Note: neighbors of a point can be of any number and y-coordinate of the neighbors should have same sign as of its input pixel and for those pixels which have y coordinate zero we will print out all the neighbors irrespective of its signs.
A discrete geometric object consists of a finite set of integer points. This set is usually very sparse. Therefore, an array representation is not at all space efficient to store. we will use hash map having data value is a linked list of y-coordinate and key value as x- coordinate. we can easily access them using the key value and its also a space efficient.
Below is C++ stl program for determining Neighbors of a given point.
 

CPP

// C++ program to find neighbors of a given point on circle
#include <bits/stdc++.h>
using namespace std;
 
// map to store all the pixels of circle
map<int, list<int> > mymap;
map<int, list<int> >::iterator it;
 
// This program will print all the stored pixels.
void showallpoints(map<int, list<int> >& 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<int> 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<int, list<int> >& mymap)
{
    // check if the given pixel is present already in the
    // map then discard that pixel and return the function.
    map<int, list<int> >::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<int> temp = it->second;
        list<int>::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 circle 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<int, list<int> >& 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<int> temp1 = it->second;
            list<int>::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;
}

                    

Java

import java.util.*;
 
public class CircleAlgorithm {
 
    static TreeMap<Integer, TreeSet<Integer>> mymap = new TreeMap<>();
    static Iterator<Map.Entry<Integer, TreeSet<Integer>>> it;
 
    public static void main(String[] args) {
        int center_x = 0, center_y = 0;
        float r = 3.0f;
        circle(center_x, center_y, r);
        showAllPoints(mymap);
        int nx = 3, ny = 0;
        neighbors(mymap, nx, ny);
        System.out.println();
    }
 
    static void showAllPoints(TreeMap<Integer, TreeSet<Integer>> mymap) {
        for (Map.Entry<Integer, TreeSet<Integer>> entry : mymap.entrySet()) {
            int key = entry.getKey();
            TreeSet<Integer> temp = entry.getValue();
 
            for (int p : temp) {
                System.out.println("(" + key + ", " + p + ")");
            }
        }
    }
 
    static void putPixelOne(int m, int n, TreeMap<Integer, TreeSet<Integer>> mymap) {
        if (mymap.containsKey(m)) {
            TreeSet<Integer> temp = mymap.get(m);
 
            if (!temp.contains(n)) {
                temp.add(n);
            }
        } else {
            TreeSet<Integer> temp = new TreeSet<>();
            temp.add(n);
            mymap.put(m, temp);
        }
    }
 
    static 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);
    }
 
    static void circle(int centerx, int centery, float r) {
        int x = 0;
        int y = (int) r;
        float decision_para = 3 - 2 * r;
        putPixelAll(x, y, centerx, centery);
 
        while (x < y) {
            x = x + 1;
            if (decision_para <= 0) {
                decision_para = decision_para + 4 * x + 6;
            } else {
                y = y - 1;
                decision_para = decision_para + 4 * (x - y) + 10;
            }
            putPixelAll(x, y, centerx, centery);
        }
    }
 
    static void neighbors(TreeMap<Integer, TreeSet<Integer>> mymap, int given_pointx, int given_pointy) {
        for (Map.Entry<Integer, TreeSet<Integer>> entry : mymap.entrySet()) {
            if (entry.getKey() == given_pointx + 1 || entry.getKey() == given_pointx - 1) {
                TreeSet<Integer> temp1 = entry.getValue();
 
                for (int itr1 : temp1) {
                    if ((given_pointy >= 0 && itr1 >= 0) || (given_pointy <= 0 && itr1 <= 0)) {
                        System.out.println("(" + entry.getKey() + ", " + itr1 + ")");
                    }
                }
            }
        }
    }
}

                    

Python3

# Python program to find neighbors of a given point on circle
from typing import List, Tuple
from collections import defaultdict
 
# defaultdict to store all the pixels of circle
mymap = defaultdict(list)
 
 
# This program will print all the stored pixels.
def showallpoints(mymap: defaultdict) -> None:
    # To print out all the stored pixels,
    # we will traverse the defaultdict using items
    for key, values in mymap.items():
        # List contains all the y-coordinate.
        for value in values:
            print(f"({key}, {value})")
 
 
# This function will store the pixels.
def put_pixel_one(m: int, n: int, mymap: defaultdict) -> None:
    # check if the given pixel is present already in the defaultdict
    # then discard that pixel and return the function.
    if n in mymap[m]:
        return
    else:
        # if map doesn't contain pixels having same y-coordinate
        # then pixel are different and store the pixel
        mymap[m].append(n)
 
 
# generate all the pixels using 8 way-symmetry of circle
def put_pixel_all(p: int, q: int, x1: int, y1: int) -> None:
    put_pixel_one(p + x1, q + y1, mymap)
    put_pixel_one(q + x1, p + y1, mymap)
    put_pixel_one(q + x1, -p + y1, mymap)
    put_pixel_one(p + x1, -q + y1, mymap)
    put_pixel_one(-p + x1, -q + y1, mymap)
    put_pixel_one(-q + x1, -p + y1, mymap)
    put_pixel_one(-q + x1, p + y1, mymap)
    put_pixel_one(-p + x1, q + y1, mymap)
 
 
# Brensenham's circle algorithm
def circle(centerx: int, centery: int, r: float) -> None:
    # initial coordinate will be (0, radius) and we
    # will move counter-clockwise from this coordinate
    x = 0
    y = int(r)
 
    # decision parameter for initial coordinate
    decision_para = 3 - 2 * r
    put_pixel_all(x, y, centerx, centery)
 
    while x < y:
        # x will always increase by 1 unit
        x += 1
        if decision_para <= 0:
            # if decision parameter is negative then N
            # will be next pixel N(x+1, y)
            decision_para += 4 * x + 6
        else:
            # if decision parameter is positive then N
            # will be next pixel S(x+1, y-1)
            y -= 1
            decision_para += 4 * (x - y) + 10
        # Function call to generate all the pixels by symmetry
        put_pixel_all(x, y, centerx, centery)
 
 
# this program will find the neighbors of a given point
def neighbours(mymap: defaultdict, given_pointx: int, given_pointy: int) -> None:
    for key, values in mymap.items():
        if key == given_pointx + 1 or key == given_pointx - 1:
            for value in values:
                # Checking for same-sign.
                if given_pointy >= 0 and value >= 0:
                    print(f"({key}, {value})")
                elif given_pointy <= 0 and value <= 0:
                    print(f"({key}, {value})")
                else:
                    continue
 
# Driver code             
center_x = 0
center_y = 0
r = 3.0
circle(center_x, center_y, r)
showallpoints(mymap)
nx = 3
ny = 0
neighbours(mymap, nx, ny);
 
# This code is contributed by Utkarsh Kumar.

                    

C#

// C# program to find neighbors of a given point on circle
using System;
using System.Collections.Generic;
 
class Program
{
    // defaultdict to store all the pixels of circle
    static Dictionary<int, List<int>> mymap = new Dictionary<int, List<int>>();
     
    // This program will print all the stored pixels.
    static void ShowAllPoints(Dictionary<int, List<int>> mymap) {
         
        // To print out all the stored pixels,
        // we will traverse the defaultdict using items
        foreach (KeyValuePair<int, List<int>> entry in mymap) {
             
            // List contains all the y-coordinate.
            foreach (int value in entry.Value) {
                Console.WriteLine($"({entry.Key}, {value})");
            }
        }
    }
     
    // This function will store the pixels.
    static void PutPixelOne(int m, int n, Dictionary<int, List<int>> mymap) {
         
        // check if the given pixel is present already in the defaultdict
        // then discard that pixel and return the function.
        if (mymap.ContainsKey(m) && mymap[m].Contains(n)) {
            return;
        }
        else {
             
            // if map doesn't contain pixels having same y-coordinate
            // then pixel are different and store the pixel
            if (!mymap.ContainsKey(m)) {
                mymap.Add(m, new List<int>());
            }
            mymap[m].Add(n);
        }
    }
    // generate all the pixels using 8 way-symmetry of circle
    static 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);
    }
     
    // Brensenham's circle algorithm
    static void Circle(int centerx, int centery, double r) {
         
        // initial coordinate will be (0, radius) and we
        // will move counter-clockwise from this coordinate
        int x = 0;
        int y = (int)r;
     
        // decision parameter for initial coordinate
        double decision_para = 3 - 2 * r;
        PutPixelAll(x, y, centerx, centery);
     
        while (x < y) {
             
            // x will always increase by 1 unit
            x++;
            if (decision_para <= 0) {
                 
                // if decision parameter is negative then N
                // will be next pixel N(x+1, y)
                decision_para += 4 * x + 6;
            }
            else {
                 
                // if decision parameter is positive then N
                // will be next pixel S(x+1, y-1)
                y--;
                decision_para += 4 * (x - y) + 10;
            }
             
            // Function call to generate all the pixels by symmetry
            PutPixelAll(x, y, centerx, centery);
        }
    }
     
    // this program will find the neighbors of a given point
    static void Neighbours(Dictionary<int, List<int>> mymap, int given_pointx, int given_pointy) {
        foreach (KeyValuePair<int, List<int>> entry in mymap) {
            if (entry.Key == given_pointx + 1 || entry.Key == given_pointx - 1) {
                foreach (int value in entry.Value) {
                     
                    // Checking for same-sign.
                    if ((given_pointy >= 0 && value >= 0) || (given_pointy <= 0 && value <= 0)) {
                        Console.WriteLine($"({entry.Key}, {value})");
                    }
                }
            }
        }
    }
     
    // Driver code
    static void Main(string[] args) {
        int center_x = 0;
        int center_y = 0;
        double r = 3.0;
        Circle(center_x, center_y, r);
        ShowAllPoints(mymap);
        int nx = 3;
        int ny = 0;
        Neighbours(mymap, nx, ny);
    }
}
 
// This code is contributed by shivhack999

                    

Javascript

class CircleAlgorithm {
    // Data structure to store points in the circle
    static mymap = new Map();
 
    // Function to display all points in the map
    static showAllPoints(mymap) {
        for (const [key, temp] of mymap.entries()) {
            for (const p of temp) {
                console.log(`(${key}, ${p})`);
            }
        }
    }
 
    // Function to add a point to the map
    static putPixelOne(m, n, mymap) {
        if (mymap.has(m)) {
            const temp = mymap.get(m);
            if (!temp.has(n)) {
                temp.add(n);
            }
        } else {
            const temp = new Set();
            temp.add(n);
            mymap.set(m, temp);
        }
    }
 
    // Function to add all symmetric points of a given pixel
    static putPixelAll(p, q, x1, y1) {
        CircleAlgorithm.putPixelOne(p + x1, q + y1, CircleAlgorithm.mymap);
        CircleAlgorithm.putPixelOne(q + x1, p + y1, CircleAlgorithm.mymap);
        CircleAlgorithm.putPixelOne(q + x1, -p + y1, CircleAlgorithm.mymap);
        CircleAlgorithm.putPixelOne(p + x1, -q + y1, CircleAlgorithm.mymap);
        CircleAlgorithm.putPixelOne(-p + x1, -q + y1, CircleAlgorithm.mymap);
        CircleAlgorithm.putPixelOne(-q + x1, -p + y1, CircleAlgorithm.mymap);
        CircleAlgorithm.putPixelOne(-q + x1, p + y1, CircleAlgorithm.mymap);
        CircleAlgorithm.putPixelOne(-p + x1, q + y1, CircleAlgorithm.mymap);
    }
 
    // Function to draw a circle using Bresenham's algorithm
    static circle(centerx, centery, r) {
        let x = 0;
        let y = r;
        let decision_para = 3 - 2 * r;
 
        // Plot the initial points
        CircleAlgorithm.putPixelAll(x, y, centerx, centery);
 
        while (x < y) {
            x = x + 1;
            if (decision_para <= 0) {
                decision_para = decision_para + 4 * x + 6;
            } else {
                y = y - 1;
                decision_para = decision_para + 4 * (x - y) + 10;
            }
            // Plot symmetric points in all octants
            CircleAlgorithm.putPixelAll(x, y, centerx, centery);
        }
    }
 
    // Function to find neighbors of a given point
    static neighbors(mymap, given_pointx, given_pointy) {
        for (const [key, temp] of mymap.entries()) {
            if (key === given_pointx + 1 || key === given_pointx - 1) {
                for (const itr1 of temp) {
                    if ((given_pointy >= 0 && itr1 >= 0) || (given_pointy <= 0 && itr1 <= 0)) {
                        console.log(`(${key}, ${itr1})`);
                    }
                }
            }
        }
    }
}
 
// Example Usage
const center_x = 0, center_y = 0;
const r = 3.0;
// Call the circle function to draw a circle
CircleAlgorithm.circle(center_x, center_y, r);
// Display all points in the circle
CircleAlgorithm.showAllPoints(CircleAlgorithm.mymap);
// Find and display neighbors of a given point
const nx = 3, ny = 0;
CircleAlgorithm.neighbors(CircleAlgorithm.mymap, nx, ny);

                    

Output
(-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)
(2, 2)
(2, -2)


References : 
https://www.slideshare.net/tahersb/bresenham-circle


 



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads