How to discretize an Ellipse or Circle to a Polygon using C++ Graphics?
Last Updated :
17 Jan, 2020
In this article, we'll see how to discretize an Ellipse (or a circle) into a polygon. Since a circle is just a specific case of an ellipse we'll not discuss separately how to discretize a circle to a polygon!
Why discretize an ellipse to a polygon?
Discretization has several applications, the two most important being:
- Rendering Curves: Curves cannot be rendered directly on the screen. They first need to be approximated to polygons (in case of Circles and ellipses) or chained-line-segments (in case of Bezier curves and splines) and discretization serves that purpose! *
- Collision-Detection: While checking intersection for curves like Circle and Bezier curve is simple, some curves like Ellipses are way too complicated and checking intersection for them precisely is very inefficient! Hence they are first discretized to simple shapes like rectangle, polygon, etc for which collision can be detected efficiently!
* While one can render curves pixel by pixel with Bresengham's algorithm, it is often not the best practice! Since modern GPUs have become much more powerful they can render a series of the pixel without any bloat! Also drawing any curve pixel by pixel strips any possibility of batching and GPU "memorization"! And because of the way modern CPUs work trigonometric functions are no longer "computationally expensive" (atleast most of the time)!
Proof-of-concept: So the main idea of discretizing an ellipse is to break the ellipse into vertices representing polygon whereby the number of segments of the polygon would either be calculated automatically or given by the client user! For this example, we'll not calculate the number of segments automatically!
We'll use C Borland Graphics API but the same principles can be applied to any graphics library! Linux Users may want to use
SDL libgraph as a replacement for Borland Graphics Library! Also we'll use C++ instead of C to use the built-in
pair
data-structure that STL provides (and also for function-overloading that will come handy later)!
Rendering Polygons:
As it turns out, the Borland Graphics API doesn't actually have a multi-format polygon rendering function like modern graphics libraries have! There's
drawPoly and
fillPoly but the representation of the polygon might not make sense to some people and also it might lead us to some pointer problems. So we'll implement our own polygon rendering function! We'll represent a polygon as a vector of pairs of integers representing the vertices of the polygon! The main benefit of this is that a vector always knows it's size, unlike arrays which under the hood is just a pointer unknown of its bounds.
In any case, here's our code for rendering a polygon in Borland Graphics Library:-
CPP
#include <algorithm>
#include <graphics.h>
using namespace std;
typedef pair<int, int> vertex;
void polygon(vector<vertex>& vertices)
{
for (int i = 0, n = vertices.size(); i < n; i++) {
vertex current = vertices[i], next;
next = vertices[(i == n - 1) ? 0 : i + 1];
int x1 = current.first, y1 = current.second;
int x2 = next.first, y2 = next.second;
line(x1, y1, x2, y2);
}
}
// Driver code
int main()
{
int gd = DETECT, gm;
// initialize graphics library
initgraph(&gd, &gm, "");
vector<vertex> vertices;
vertices.push_back(vertex(340, 150));
vertices.push_back(vertex(220, 250));
vertices.push_back(vertex(340, 350));
polygon(vertices);
delay(5000);
}
Output:
Discretizing Ellipse to Polygon:
Now that we can render polygons we are ready to discretize an ellipse to a polygon!
So the key to discretizing an ellipse is to have a moving point that moves across the ellipse in equal intervals and creating a vertex on every such point (every point where the moving point passes over)! For this one must know the parametric form of an ellipse which is:-
x=acos(\theta )
y=bsin(\theta )
Based on the above formula, here's the code-snippet that discretizes our ellipse to a polygon:-
CPP
#define TWO_PI 44 / 7.0f
vector<vertex> discretizeEllipse(
int x, int y,
int a, int b,
int seg)
{
float angle_shift = TWO_PI / seg, phi = 0;
vector<vertex> vertices;
for (int i = 0; i < seg; ++i) {
phi += angle_shift;
vertices
.push_back(
vertex(
x + a * cos(phi),
y + b * sin(phi)));
}
return vertices;
}
One last thing that's left to do is
overload the function such that the last parameter is not needed! We can set
segments
to some default value but we'd like it to be calculated based on the dimensions of the ellipse! So here's the second overload:-
CPP
vector<vertex> discretizeEllipse(
int x, int y,
int a, int b)
{
int segments
= max((int)floor(
sqrt(((a + b) / 2) * 20)),
8);
return discretizeEllipse(
x, y,
a, b,
segments);
}
To end this article, here's the complete source-code:
CPP
#include <algorithm>
#include <graphics.h>
#define TWO_PI 44 / 7.0f
typedef pair<int, int> vertex;
void polygon(vector<vertex> vertices)
{
for (int i = 0, n = vertices.size(); i < n; i++) {
vertex current = vertices[i], next;
next = vertices[(i == n - 1) ? 0 : i + 1];
int x1 = current.first, y1 = current.second;
int x2 = next.first, y2 = next.second;
line(x1, y1, x2, y2);
}
}
vector<vertex> discretizeEllipse(
int x, int y, int a,
int b, int seg)
{
float angle_shift = TWO_PI / seg, phi = 0;
vector<vertex> vertices;
for (int i = 0; i < seg; ++i) {
phi += angle_shift;
vertices.push_back(
vertex(
x + a * cos(phi),
y + b * sin(phi)));
}
return vertices;
}
vector<vertex> discretizeEllipse(
int x, int y, int a, int b)
{
int segments
= max((int)floor(
sqrt(((a + b) / 2) * 20)),
8);
return discretizeEllipse(
x, y, a, b, segments);
}
int main()
{
int gd = DETECT, gm;
// initialize graphics library
initgraph(&gd, &gm, "");
polygon(discretizeEllipse(320, 240, 200, 100));
polygon(discretizeEllipse(320, 240, 200, 100, 8));
delay(5000);
}
Output:
Similar Reads
Draw an ellipse divided by straight line into two colored part in C++ Graphics
Prerequisite: How to include graphics.h?, graphics.hThe task is to draw an ellipse that is intersected by a straight line passing through the center of the ellipse diagonally. And then color both segments with different colors. Approach: To run the program we need to include the following header fil
3 min read
C++ program to draw a traffic light simulation using computer graphics
In computers, graphics.h can be used to provide direct functions to draw different coordinates, like circles, rectangles, etc. Using these shapes, different objects can be drawn. This article focuses on how to make a traffic light simulation in Turbo C++. Functions Used: delay(n): It is used to hold
3 min read
Draw a moving cycle using computer graphics programming in C/C++
In C graphics, the graphics.h functions are used to draw different shapes like circles, rectangles, etc, display text(any message) in a different format (different fonts and colors). By using the functions in the header graphics.h, programs, animations, and different games can also be made. In this
3 min read
Draw an ellipse using OpenCV in C++
In this article, the task is to draw an ellipse using OpenCV in C++. The ellipse() function from OpenCV C++ library will be used. Syntax: ellipse(image, centerCoordinates, axesLength, angle, startAngle, endAngle, color, thickness, lineType, shift) Parameters: image: It is the image on which ellipse
3 min read
Number of cycles in a Polygon with lines from Centroid to Vertices
Given a number N which denotes the number of sides of the polygon where the centroid of the polygon is connected with all the vertices, the task is to find the number of cycles in the polygon.Examples: Input: N = 4 Output: 13Input: N = 8 Output: 57 Approach: This problem follows a simplistic approac
3 min read
Represent Tree using graphics in C/C++
Prerequisite: graphics.h, How to include graphics.h? In C/C++ there is graphics.h header file which is used to create the object like line, circle, etc. Given an array arr[] of N integers, the task is to write C++ program to create the Tree using graphics.h. Approach: To run the program we have the
3 min read
Program to draw circles using mouse moves in OpenGL
In this article, the task is to draw circles using a single mouse click in OpenGL. OpenGL: OpenGL is a cross-language, cross-platform API for rendering 2D and 3D Vector Graphics. It will make a lot of design as well as animations using this. Create a circle anywhere on the console using a single lef
3 min read
Creating Butterfly themed Fractal in C++ Using Graphics
In Layman's terms, Fractals are beautiful patterns brought into existence upon the intertwining of computation and mathematics. To get a bit technical they are recursive in nature such that when looked upon a certain subset of a given fractal a similar pattern appears to emerge out of it. In this ar
3 min read
Area of the circle that has a square and a circle inscribed in it
Given the side of a square that is kept inside a circle. It keeps expanding until all four of its vertices touch the circumference of the circle. Another smaller circle is kept inside the square now and it keeps expanding until its circumference touches all four sides of the square. The outer and th
3 min read
Area of a n-sided regular polygon with given side length
Given a regular polygon of N sides with side length a. The task is to find the area of the polygon. Examples: Input : N = 6, a = 9 Output : 210.444 Input : N = 7, a = 8 Output : 232.571 Approach: In the figure above, we see the polygon can be divided into N equal triangles. Looking into one of the t
4 min read