Drawing a circle without using a function for it - graphics

So I was wondering how does a circle() function work, and how can I draw to circle without using it (wanted to do something related to it). Does anyone know this stuff?

A classic way of rasterizing a circle is using the Midpoint Circle Algorithm.
It works by tracking the pixels which are as close to the x2 + y2 = r2 isoline as possible. This can even be done with purely integer calculations, which is particularly suitable for low-computation power devices.

A circle is the set of points located at a constant distance from another point, called the center.
If you can draw lines defined by two points, you can draw the representation of a circle on a canvas, knowing its center, and its radius.
The approach is to determine a set of consecutive points located on the circumference, then join them with lines.
for instance, in python (which reads like pseudocode):
import math
def make_circle(center, radius, num_points=40):
"""returns a sequence of points on the circumference
"""
points = [center]
d_theta = 2 * math.pi / num_points
cx, cy = center
for idx in range(num_points + 1):
theta = idx * d_theta
points.append((cx + math.cos(theta) * radius, cy + math.sin(theta) * radius))
return points
And if you want to try it, here it is: circles codeskulptor.
You will see that for display purposes, 40 points on the circumference is enough to give an acceptable rendition.

Related

Is it accurate to conclude the radius of a circle given 4 bazier curves in svg?

I have used svg2paths2, and wanted to figure out what is the position and radius of a circle, I have noticed the circle is consructed by 4 CubicBezier, as follow:
Path(CubicBezier(start=(127.773+90.5469j), control1=(127.773+85.7656j), control2=(123.898+81.8906j), end=(119.121+81.8906j)),
CubicBezier(start=(119.121+81.8906j), control1=(114.34+81.8906j), control2=(110.465+85.7656j), end=(110.465+90.5469j)),
CubicBezier(start=(110.465+90.5469j), control1=(110.465+95.3281j), control2=(114.34+99.1992j), end=(119.121+99.1992j)),
CubicBezier(start=(119.121+99.1992j), control1=(123.898+99.1992j), control2=(127.773+95.3281j), end=(127.773+90.5469j)))
I have read the standard approach is to divide the circle into four equal sections, and fit each section to a cubic Bézier curve.
So I was wondering is it accurate to say the Radius of the circle is
(q1.start.real - q3.start.real)/2
or
(q2.start.imag - q4.start.imag)/2
And the center of the circle is:
c_x = (q1.start.real + q1.end.real) / 2
c_y = (q1.start.imag + q1.end.imag) / 2
Thank you!
I'm assuming you are using svg.path library in python, or svg2paths2 is related.
from svg.path import Path, Line, Arc, CubicBezier, QuadraticBezier, Close
path = Path(CubicBezier(start=(127.773+90.5469j), control1=(127.773+85.7656j), control2=(123.898+81.8906j), end=(119.121+81.8906j)),
CubicBezier(start=(119.121+81.8906j), control1=(114.34+81.8906j), control2=(110.465+85.7656j), end=(110.465+90.5469j)),
CubicBezier(start=(110.465+90.5469j), control1=(110.465+95.3281j), control2=(114.34+99.1992j), end=(119.121+99.1992j)),
CubicBezier(start=(119.121+99.1992j), control1=(123.898+99.1992j), control2=(127.773+95.3281j), end=(127.773+90.5469j)))
q1 = path[0]
q2 = path[1]
q3 = path[2]
q4 = path[3]
.real is the X coordinate
.imag is the Y coordinate
There's a very slight error in accuracy in the drawing program you are using and it's not at all an issue unless you want extreme accuracy.
(q1.start.real - q3.start.real) / 2 # 8.6539 is the radius in this case.
(q4.start.imag - q2.start.imag)/2 # 8.6543 is also the radius.
(q1.start.real - q1.end.real) # 8.6539 is again also the radius.
This accesses the same property, q1 of path and I' prefer it to the two above ways because it's accessing one property not two.
Below shown by green circle in diagram
c_x = (q1.start.real + q1.end.real) / 2 # 123.447 not center x
c_y = (q1.start.imag + q1.end.imag) / 2 # 86.21875 not center y
Below shown by red circle in diagram
c_x = q1.end.imag # 119.121 this is center x
c_y = q1.start.real # 90.5469 this is center y
To explain how serious the error in accuracy, the pink circle uses 8.6543 radius, below it is 8.6539 in green, perhaps viewable with an extreme zoom. But this does illustrate how important or not the decimal points can be.
Consider using numbers under 100 and as few decimal points as possible, especially understanding a new idea. Shorter text-length numbers vastly improves readability, understanding no end.
I often use just numbers below ten.
Note: you are drawing the circle counter-clockwise. Clockwise is the usual way.

Having the coordinates of the two triangles of a twisted triangle prism, how can I know if a point is inside it?

Here some examples of twisted triangle prisms.
I want to know if a moving triangle will hit a certain point. That's why I need to solve this problem.
The idea is that a triangle with random coordinates becomes the other random triangle whose vertices all move between then
related: How to determine point/time of intersection for ray hitting a moving triangle?
One of my students made this little animation in Mathematica.
It shows the twisting of a prism to the Schönhardt polyhedron.
See the Wikipedia page for its significance.
It would be easy to determine if a particular point is inside the polyhedron.
But whether it is inside a particular smooth twisting, as in your image, depends on the details (the rate) of the twisting.
Let's bottom triangle lies in plane z=0, it has rotation angle 0, top triangle has rotation angle Fi. Height of twisted prism is Hgt.
Rotation angle linearly depends on height, so layer at height h has rotation angle
a(h) = Fi * h / Hgt
If point coordinates are (x,y,z), then shift point to z=0 and rotate (x,y) coordinates about rotation axis (rx, ry) by -a(z) angle
t = -a(z) = - Fi * z / Hgt
xn = rx + (x-rx) * Cos(t) - (y-ry) * Sin(t)
yn = ry + (x-rx) * Sin(t) - (y-ry) * Cos(t)
Then check whether (xn, yn) lies inside bottom triangle

How to get a point on an ellipse's outline given an angle?

So, I have ellipses given - they are defined by their midpoint, an horizontal radius(rh) and an vertical radius(rv). I'm drawing them using sin/cos and the result looks fairly good to me(just making sure this isn't an error source).
Now say I have an angle(or a direction vector) given and I want to have the point on the ellipse's outline with that angle/direction. My intuitive approach was to simply use the direction vector, normalise it and multiply its x-component with rh, its y-component with rv. Now both my written program AND all the calculations I did on a paper give me not the point I want but another one, though it's still on the ellipse's outline. However, this method works just fine if the direction is one of (1,0), (0, 1), (-1, 0), (0, -1), (so it works for 0°, 90°, 180°, 270°).
Although there is a farily big amount of data about ellipses themselves on the internet, I couldn't find any information about my particular problem - and I couldn't come up with any better solution than the above one.
So, any idea how to achieve this?
If I understand what you are asking then I think that what you need is polar form of an ellipse where the angle is measured from the ellipse centre. Using this form of the ellipse, you will be able to evaulate your elliptic radius value for a given choice of theta and then plot your point.
If you take a look at this gif image you will see why using the parametric angle give you the correct result only at theta = 90, 180, 270 and 360 degrees http://en.wikipedia.org/wiki/File:Parametric_ellipse.gif . Use the polar form for an ellipse and you should get the points that you want.
You are correct - the parametric angle is not the same as the angle between the desired point and the X axis. However, their tangents are proportional (with a factor of rh/rv) so you can use this approach:
Get the tangent of the desired angle
Multiply this tangent by rh/rv
Use trigonometric identities to compute the sine and cosine from the tangent
Scale/position the point according to the parameters (midpoint, rh, rv)
In Python:
from math import copysign, cos, sin, sqrt
class Ellipse:
def __init__(self, mx, my, rh, rv):
self.mx = mx
self.my = my
self.rh = rh
self.rv = rv
def pointFromAngle(self, a):
c = cos(a)
s = sin(a)
ta = s / c ## tan(a)
tt = ta * self.rh / self.rv ## tan(t)
d = 1. / sqrt(1. + tt * tt)
x = self.mx + copysign(self.rh * d, c)
y = self.my + copysign(self.rv * tt * d, s)
return x, y

how to draw circular arc with give two points and radius and clockwise direction

The problem is draw arc with two pints on bitmap with radius and clockwise direction.
From your one-sentence question, I'm gonna assume you're ok with drawing Bezier curves. If not, there is plenty of information about them out there.
Anyway, you cannot create a perfect circular arc with Bezier curves (or splines). What you can do is approximating a circle to a level where the eye won't be able to see the difference. This is usually done with 8 quadratic Bezier curve segments, each covering 1/8th of the circle. This is i.e. how Adobe Flash creates circles.
If you're after a plain parametrization using sin and cos, it's way easier:
for (float t = 0; t < 2 * Math.PI; t+=0.05) {
float x = radius * sin(t);
float y = radius * cos(t);
}

Ray Generation Inconsistency

I have written code that generates a ray from the "eye" of the camera to the viewing plane some distance away from the camera's eye:
R3Ray ConstructRayThroughPixel(...)
{
R3Point p;
double increments_x = (lr.X() - ul.X())/(double)width;
double increments_y = (ul.Y() - lr.Y())/(double)height;
p.SetX( ul.X() + ((double)i_pos+0.5)*increments_x );
p.SetY( lr.Y() + ((double)j_pos+0.5)*increments_y );
p.SetZ( lr.Z() );
R3Vector v = p-camera_pos;
R3Ray new_ray(camera_pos,v);
return new_ray;
}
ul is the upper left corner of the viewing plane and lr is the lower left corner of the viewing plane. They are defined as follows:
R3Point org = scene->camera.eye + scene->camera.towards * radius;
R3Vector dx = scene->camera.right * radius * tan(scene->camera.xfov);
R3Vector dy = scene->camera.up * radius * tan(scene->camera.yfov);
R3Point lr = org + dx - dy;
R3Point ul = org - dx + dy;
Here, org is the center of the viewing plane with radius being the distance between the viewing plane and the camera eye, dx and dy are the displacements in the x and y directions from the center of the viewing plane.
The ConstructRayThroughPixel(...) function works perfectly for a camera whose eye is at (0,0,0). However, when the camera is at some different position, not all needed rays are produced for the image.
Any suggestions what could be going wrong? Maybe something wrong with my equations?
Thanks for the help.
Here's a quibble that may have nothing to do with you problem:
When you do this:
R3Vector dx = scene->camera.right * radius * tan(scene->camera.xfov);
R3Vector dy = scene->camera.up * radius * tan(scene->camera.yfov);
I assume that the right and up vectors are normalized, right? In that case you want sin not tan. Of course, if the fov angles are small it won't make much difference.
The reason why my code wasn't working was because I was treating x,y,z values separately. This is wrong, since the camera can be facing in any direction and thus if it was facing down the x-axis, the x coordinates would be the same, producing increments of 0 (which is incorrect). Instead, what should be done is an interpolation of corner points (where points have x,y,z coordinates). Please see answer in related post: 3D coordinate of 2D point given camera and view plane

Resources