Correct use of cos() and sin() in Python - python-3.x

I'm trying to convert, just for fun, a code listing written in a language called Seed7 into Python. I've got it just about to beta phase, except for one part. This is the extract of the Seed7 listing:
x1 := flt(column) + 0.5;
y1 := flt(row) + 0.5;
angle := (course - 1.0) * 0.785398;
delta_x := cos(angle);
delta_y := -sin(angle);
inquad := TRUE;
blocked := FALSE;
number := 1;
while number <= distance do
y1 := y1 + delta_y;
x1 := x1 + delta_x;
row := trunc(y1);
column := trunc(x1);
if column < 1 or column > 8 or row < 1 or row > 8 then
inquad := FALSE;
number := distance;
else
if sect[row][column] <> 1 then (* Object blocking move *)
blocked := TRUE;
number := distance;
end if;
end if;
incr(number);
end while;
Which all makes sense, except for the fact that I don't understand how the functions cos() and sin() work in Seed7.
The manual says:
sin
const func float: sin (in float: x)
Compute the sine of x, where x is given in radians.
Returns:
the trigonometric sine of an angle.
but I can't make the equivalent in Python.
This problem is purely one caused by me not understanding Python properly (and not really being that great with maths either), so I come here to ask someone who does understand these things.
What code is required to make the above code work in Python? Help!!! :-)
Many thanks,
Joseph.
Edit: I think the problem is the incr() function. Basically, it is possible to warp in this game less than 1. From the help files:
writeln("Warp - One warp moves you the width of a quadrant. A warp of .5 will move you");
writeln("halfway through a quadrant. Moving diagonally across a quadrant to the next");
writeln("will require 1.414 warps. Warp 3 will move you 3 quadrants providing nothing");
writeln("in your present quadrant blocks your exit. Once you leave the quadrant that");
writeln("you were in, you will enter hyperspace; coming out of hyperspace will place you");
writeln("randomly in the new quadrant. Klingons in a given quadrant will fire at you");
writeln("whenever you leave, enter, or move within the quadrant. Entering a course or");
writeln("warp of zero can be used to return to the command mode.")
My code looks like this:
x1 = float(column) + 0.5
y1 = float(row) + 0.5
angle = (course - 1.0) * 0.785398
deltaX = math.cos(angle)
deltaY = -math.sin(angle)
inQuad = True
blocked = False
num = 1
while num <= distance:
y1 += deltaY
x1 += deltaX
row = int(round(y1))
column = int(round(x1))
if column < 0 or column > 7 or row < 0 or row > 7:
inQuad = False
num = distance
else:
if sect[row][column] != 1:
blocked = True
num = distance
num += 1
The thing is I'm using num+=1 at the end there, as opposed to incr, but I don't understand incr. As I have said, I've been a bit long out of the game, and certain things are really catching me out.
Any help in shining a light would be appreciated.
Joseph.

A guess:
If Seed7 expects radians, you may need to convert degrees to radians before applying sin or cos:
import math
math.sin(math.radians(1))

Related

How do you calculate the position of different radius circles when the arc should always intersect with each other on 2 specific points?

This is way above my level, in any matter, programming and math. I'm just trying to simplify setup in our CNC-machine.
To the problem ill attach a pic that show roughly what I mean.
Circle Image
So, the 2 small circles have always a known distance and size. 27.5 dia and 200 cc.
The bigger circles have always a known radius but will differ.
The goal is to know how to position the bigger circles, so it always lines up together with the smaller ones, arc to arc. Which will make them overlap with different radiuses.
I have tried googling. But have not been able to find any clear simple formula for me to calculate this value. Just a bunch of "advance" equations which doesn't make any sense to me :)
I found this post that describes the same problem, i think. But not sure how to calculate it myself...
Would be really impressed if someone has a solution to this, thanks in advance!!!
Let small roll radius is r, distance is d, large circle radius is R
Circle centers form isosceles triangle with side lengths d, R+r, R+r.
Large circle center y-coordinate (over triangle base) is (using Pythagoras theorem)
y = sqrt((R+r)^2-d^2/4)
Example of calculation:
Delphi code used to generate this image:
var
x1, y1, x2, y2, lx, ly: Integer;
r, Rrr, d: Integer;
begin
x1 := 200; y1 := 500; d := 200; r := 30; rrr := 150;
x2 := x1 + d;
y2 := y1;
lx := x1 + d div 2; //large circle center
ly := y1 - Round(Sqrt((Rrr+r)*(Rrr+r)-d*d/4));
canvas.Ellipse(x1 - r, y1 - r, x1 + r + 1, y1 + r + 1);
canvas.Ellipse(x2 - r, y2 - r, x2 + r + 1, y2 + r + 1);
canvas.Ellipse(lx - Rrr, ly - Rrr, lx + Rrr + 1, ly + Rrr + 1);

I want to make a Cornu spiral in blender using nodes

And I have no clue where to start. In case you don't know what a cornu spiral is: https://mathworld.wolfram.com/CornuSpiral.html
All that I see are intrincated maths whose terms I'm not familiar with and doesn't translate as far as I know directly to blender interface which also I don't know in depth.
I had some success setting the handle absolute positions given point position on the bezier but I have no idea how to relate them in order to achieve my goal. Can you lend me any formula to calculate the correct brezier handle positions relative to point position and also the positions of the points? I'm about a week on this and I'm still starting.
We can draw Cornu spiral using small line segments. Example in Delphi:
cx := 10;
cy := 700;
scale := 700;
step := 0.02;
Canvas.MoveTo(cx, cy);
for i := 1 to 250 do begin
t := i * step;
fresnelintegral(t, c, s);
x := cx + Round(scale * s);
y := cy - Round(scale * c);
Canvas.LineTo(x, y);
end;
here t is curve parameter (proportional to arc length), and we calculate coordinate of current point using Fresnel integrals and scaling (to make a picture of viewable size). This code generates black curve:
If we want to approximate Cornu spiral by Bezier curves, we have to get endpoints with the same equations, then get direction angles in previous point and in the current point (slope equation (2) in your link) to define intermediate control points. But we also need to calculate distances to control points - seems rather hard problem. I made quick code to demonstrate an approach.
Curvature of Cornu spiral rises along the curve. To approximate spiral better, I had to diminish steps, so Bezier segments become smaller and smaller. Small circles are Bezier endpoints, they become closer.
I tried to make coeff depending on t value, but have not found good equation. The code below generates blue curve. It is very close to black one (we can align them) in chosen t range.
Canvas.Pen.Color := clBlue;
cx := 500;
step := 0.2;
prevt := 0;
t := 0;
Canvas.MoveTo(cx, cy);
Pts[0] := Point(cx, cy);
for i := 1 to 70 do begin
t := t + step;
fresnelintegral(prevt, c, s);
prevx := cx + Round(scale * s);
prevy := cy - Round(scale * c);
prevfi := 0.5 * Pi * prevt * prevt;
fresnelintegral(t, c, s);
x := cx + Round(scale * s);
y := cy - Round(scale * c);
pts[i*3] := Point(x, y);
fi := 0.5 * Pi * t * t;
Canvas.Ellipse(x-2, y-2, x+3, y+3);
coeff := 1/3;
dist := Hypot(x - prevx, y - prevy) * coeff;
px := prevx + Round(dist * Sin(prevfi));
py := prevy - Round(dist * Cos(prevfi));
pts[i * 3 - 2] := Point(px, py);
px := x - Round(dist * Sin(fi));
py := y + Round(dist * Cos(fi));
pts[i * 3 - 1] := Point(px, py);
step := step * 0.96;
prevt := t;
end;
Canvas.PolyBezier(pts);

Open Scene Graph - Usage of DrawElementsUInt: Drawing a cloth without duplicating vertices

I am currently working on simulating a cloth like material and then displaying the results via Open Scene Graph.
I've gotten the setup to display something cloth like, by just dumping all the vertices into 1 Vec3Array and then displaying them with a standard Point based DrawArrays. However I am looking into adding the faces between the vertices so that a further part of my application can visually see the cloth.
This is currently what I am attempting as for the PrimitiveSet
// create and add a DrawArray Primitive (see include/osg/Primitive). The first
// parameter passed to the DrawArrays constructor is the Primitive::Mode which
// in this case is POINTS (which has the same value GL_POINTS), the second
// parameter is the index position into the vertex array of the first point
// to draw, and the third parameter is the number of points to draw.
unsigned int k = CLOTH_SIZE_X;
unsigned int n = CLOTH_SIZE_Y;
osg::ref_ptr<osg::DrawElementsUInt> indices = new osg::DrawElementsUInt(GL_QUADS, (k) * (n));
for (uint y_i = 0; y_i < n - 1; y_i++) {
for (uint x_i = 0; x_i < k - 1; x_i++) {
(*indices)[y_i * k + x_i] = y_i * k + x_i;
(*indices)[y_i * (k + 1) + x_i] = y_i * (k + 1) + x_i;
(*indices)[y_i * (k + 1) + x_i + 1] = y_i * (k + 1) + x_i + 1;
(*indices)[y_i * k + x_i] = y_i * k + x_i + 1;
}
}
geom->addPrimitiveSet(indices.get());
This does however cause memory corruption when running, and I am not fluent enough in Assembly code to decipher what it is trying to do wrong when CLion gives me the disassembled code.
My thought was that I would iterate over each of the faces of my cloth and then select the 4 indices of the vertices that belong to it. The vertices are inputted from top left to bottom right in order. So:
0 1 2 3 ... k-1
k k+1 k+2 k+3 ... 2k-1
2k 2k+1 2k+2 2k+3 ... 3k-1
...
Has anyone come across this specific use-case before and does he/she perhaps have a solution for my problem? Any help would be greatly appreciated.
You might want to look into using DrawArrays with QUAD_STRIP (or TRIANGLE_STRIP because quads are frowned upon these days). There's an example here:
http://openscenegraph.sourceforge.net/documentation/OpenSceneGraph/examples/osggeometry/osggeometry.cpp
It's slightly less efficient than Elements/indices, but it's also less complicated to manage the relationship between the two related containers (the vertices and the indices).
If you really want to do the Elements/indices route, we'd probably need to see more repro code to see what's going on.

Algorithm for drawing a 4-connected line

I'm looking for an algorithm (coded in Java would be nice, but anything clear enough to translate to Java is fine) to draw a 4-connected line. It seems that Bresenham's algorithm is the most widely used, but all the understandable implementations I've found are 8-connected. OpenCV's cvline function apparently has a 4-connected version, but the source code is, to me, as a mediocre and nearly C-illiterate programmer, impenetrable. Various other searches have turned up nothing.
Thanks for any help anyone can provide.
The following is a Bresenham-like algorithm that draws 4-connected lines. The code is in Python but I suppose can be understood easily even if you don't know the language.
def line(x0, y0, x1, y1, color):
dx = abs(x1 - x0) # distance to travel in X
dy = abs(y1 - y0) # distance to travel in Y
if x0 < x1:
ix = 1 # x will increase at each step
else:
ix = -1 # x will decrease at each step
if y0 < y1:
iy = 1 # y will increase at each step
else:
iy = -1 # y will decrease at each step
e = 0 # Current error
for i in range(dx + dy):
draw_pixel(x0, y0, color)
e1 = e + dy
e2 = e - dx
if abs(e1) < abs(e2):
# Error will be smaller moving on X
x0 += ix
e = e1
else:
# Error will be smaller moving on Y
y0 += iy
e = e2
The idea is that to draw a line you should increment X and Y with a ratio that matches DX/DY of the theoretic line. To do this I start with an error variable e initialized to 0 (we're on the line) and at each step I check if the error is lower if I only increment X or if I only increment Y (Bresenham check is to choose between changing only X or both X and Y).
The naive version for doing this check would be adding 1/dy or 1/dx, but multiplying all increments by dx*dy allows using only integer values and that improves both speed and accuracy and also avoids the need of special cases for dx==0 or dy==0 thus simplifying the logic.
Of course since we're looking for a proportion error, using a scaled increment doesn't affect the result.
Whatever is the line quadrant the two possibilities for the increment will always have a different sign effect on the error... so my arbitrary choice was to increment the error for an X step and decrement the error for an Y step.
The ix and iy variables are the real directions needed for the line (either +1 or -1) depending on whether the initial coordinates are lower or higher than the final coordinates.
The number of pixels to draw in a 4-connected line is obviously dx+dy, so I just do a loop for that many times to draw the line instead of checking if I got to the end point. Note that this algorithm draws all pixels except the last one; if you want also that final pixel then an extra draw_pixel call should be added after the end of the loop.
An example result of the above implementation can be seen in the following picture
For the Python-illiterate, here is a C version of 6502's code:
void drawLine(int x0, int y0, int x1, int y1) {
int dx = abs(x1 - x0);
int dy = abs(y1 - y0);
int sgnX = x0 < x1 ? 1 : -1;
int sgnY = y0 < y1 ? 1 : -1;
int e = 0;
for (int i=0; i < dx+dy; i++) {
drawPixel(x0, y0);
int e1 = e + dy;
int e2 = e - dx;
if (abs(e1) < abs(e2)) {
x0 += sgnX;
e = e1;
} else {
y0 += sgnY;
e = e2;
}
}
}

How do I convert the 2 control points of a cubic curve to the single control point of a quadratic curve?

Having searched the web, I see various people in various forums alluding to approximating a cubic curve with a quadratic one. But I can't find the formula.
What I want is this:
input: startX, startY, control1X, control1Y, control2X, control2Y, endX, endY
output: startX, startY, controlX, controlY, endX, endY
Actually, since the starting and ending points will be the same, all I really need is...
input: startX, startY, control1X, control1Y, control2X, control2Y, endX, endY
output: controlX, controlY
As mentioned, going from 4 control points to 3 is normally going to be an approximation. There's only one case where it will be exact - when the cubic bezier curve is actually a degree-elevated quadratic bezier curve.
You can use the degree elevation equations to come up with an approximation. It's simple, and the results are usually pretty good.
Let's call the control points of the cubic Q0..Q3 and the control points of the quadratic P0..P2. Then for degree elevation, the equations are:
Q0 = P0
Q1 = 1/3 P0 + 2/3 P1
Q2 = 2/3 P1 + 1/3 P2
Q3 = P2
In your case you have Q0..Q3 and you're solving for P0..P2. There are two ways to compute P1 from the equations above:
P1 = 3/2 Q1 - 1/2 Q0
P1 = 3/2 Q2 - 1/2 Q3
If this is a degree-elevated cubic, then both equations will give the same answer for P1. Since it's likely not, your best bet is to average them. So,
P1 = -1/4 Q0 + 3/4 Q1 + 3/4 Q2 - 1/4 Q3
To translate to your terms:
controlX = -0.25*startX + .75*control1X + .75*control2X -0.25*endX
Y is computed similarly - the dimensions are independent, so this works for 3d (or n-d).
This will be an approximation. If you need a better approximation, one way to get it is by subdividing the initial cubic using the deCastlejau algorithm, and then degree-reduce each segment. If you need better continuity, there are other approximation methods that are less quick and dirty.
The cubic can have loops and cusps, which quadratic cannot have. This means that there are not simple solutions nearly never. If cubic is already a quadratic, then the simple solution exists. Normally you have to divide cubic to parts that are quadratics. And you have to decide what are the critical points for subdividing.
http://fontforge.org/bezier.html#ps2ttf says:
"Other sources I have read on the net suggest checking the cubic spline for points of inflection (which quadratic splines cannot have) and forcing breaks there. To my eye this actually makes the result worse, it uses more points and the approximation does not look as close as it does when ignoring the points of inflection. So I ignore them."
This is true, the inflection points (second derivatives of cubic) are not enough. But if you take into account also local extremes (min, max) which are the first derivatives of cubic function, and force breaks on those all, then the sub curves are all quadratic and can be presented by quadratics.
I tested the below functions, they work as expected (find all critical points of cubic and divides the cubic to down-elevated cubics). When those sub curves are drawn, the curve is exactly the same as original cubic, but for some reason, when sub curves are drawn as quadratics, the result is nearly right, but not exactly.
So this answer is not for strict help for the problem, but those functions provide a starting point for cubic to quadratic conversion.
To find both local extremes and inflection points, the following get_t_values_of_critical_points() should provide them. The
function compare_num(a,b) {
if (a < b) return -1;
if (a > b) return 1;
return 0;
}
function find_inflection_points(p1x,p1y,p2x,p2y,p3x,p3y,p4x,p4y)
{
var ax = -p1x + 3*p2x - 3*p3x + p4x;
var bx = 3*p1x - 6*p2x + 3*p3x;
var cx = -3*p1x + 3*p2x;
var ay = -p1y + 3*p2y - 3*p3y + p4y;
var by = 3*p1y - 6*p2y + 3*p3y;
var cy = -3*p1y + 3*p2y;
var a = 3*(ay*bx-ax*by);
var b = 3*(ay*cx-ax*cy);
var c = by*cx-bx*cy;
var r2 = b*b - 4*a*c;
var firstIfp = 0;
var secondIfp = 0;
if (r2>=0 && a!==0)
{
var r = Math.sqrt(r2);
firstIfp = (-b + r) / (2*a);
secondIfp = (-b - r) / (2*a);
if ((firstIfp>0 && firstIfp<1) && (secondIfp>0 && secondIfp<1))
{
if (firstIfp>secondIfp)
{
var tmp = firstIfp;
firstIfp = secondIfp;
secondIfp = tmp;
}
if (secondIfp-firstIfp >0.00001)
return [firstIfp, secondIfp];
else return [firstIfp];
}
else if (firstIfp>0 && firstIfp<1)
return [firstIfp];
else if (secondIfp>0 && secondIfp<1)
{
firstIfp = secondIfp;
return [firstIfp];
}
return [];
}
else return [];
}
function get_t_values_of_critical_points(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),
b = 2 * (c1x - p1x) - 2 * (c2x - c1x),
c = p1x - c1x,
t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a,
t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a,
tvalues=[];
Math.abs(t1) > "1e12" && (t1 = 0.5);
Math.abs(t2) > "1e12" && (t2 = 0.5);
if (t1 >= 0 && t1 <= 1 && tvalues.indexOf(t1)==-1) tvalues.push(t1)
if (t2 >= 0 && t2 <= 1 && tvalues.indexOf(t2)==-1) tvalues.push(t2);
a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);
b = 2 * (c1y - p1y) - 2 * (c2y - c1y);
c = p1y - c1y;
t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a;
t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a;
Math.abs(t1) > "1e12" && (t1 = 0.5);
Math.abs(t2) > "1e12" && (t2 = 0.5);
if (t1 >= 0 && t1 <= 1 && tvalues.indexOf(t1)==-1) tvalues.push(t1);
if (t2 >= 0 && t2 <= 1 && tvalues.indexOf(t2)==-1) tvalues.push(t2);
var inflectionpoints = find_inflection_points(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y);
if (inflectionpoints[0]) tvalues.push(inflectionpoints[0]);
if (inflectionpoints[1]) tvalues.push(inflectionpoints[1]);
tvalues.sort(compare_num);
return tvalues;
};
And when you have those critical t values (which are from range 0-1), you can divide the cubic to parts:
function CPoint()
{
var arg = arguments;
if (arg.length==1)
{
this.X = arg[0].X;
this.Y = arg[0].Y;
}
else if (arg.length==2)
{
this.X = arg[0];
this.Y = arg[1];
}
}
function subdivide_cubic_to_cubics()
{
var arg = arguments;
if (arg.length!=9) return [];
var m_p1 = {X:arg[0], Y:arg[1]};
var m_p2 = {X:arg[2], Y:arg[3]};
var m_p3 = {X:arg[4], Y:arg[5]};
var m_p4 = {X:arg[6], Y:arg[7]};
var t = arg[8];
var p1p = new CPoint(m_p1.X + (m_p2.X - m_p1.X) * t,
m_p1.Y + (m_p2.Y - m_p1.Y) * t);
var p2p = new CPoint(m_p2.X + (m_p3.X - m_p2.X) * t,
m_p2.Y + (m_p3.Y - m_p2.Y) * t);
var p3p = new CPoint(m_p3.X + (m_p4.X - m_p3.X) * t,
m_p3.Y + (m_p4.Y - m_p3.Y) * t);
var p1d = new CPoint(p1p.X + (p2p.X - p1p.X) * t,
p1p.Y + (p2p.Y - p1p.Y) * t);
var p2d = new CPoint(p2p.X + (p3p.X - p2p.X) * t,
p2p.Y + (p3p.Y - p2p.Y) * t);
var p1t = new CPoint(p1d.X + (p2d.X - p1d.X) * t,
p1d.Y + (p2d.Y - p1d.Y) * t);
return [[m_p1.X, m_p1.Y, p1p.X, p1p.Y, p1d.X, p1d.Y, p1t.X, p1t.Y],
[p1t.X, p1t.Y, p2d.X, p2d.Y, p3p.X, p3p.Y, m_p4.X, m_p4.Y]];
}
subdivide_cubic_to_cubics() in above code divides an original cubic curve to two parts by the value t. Because get_t_values_of_critical_points() returns t values as an array sorted by t value, you can easily traverse all t values and get the corresponding sub curve. When you have those divided curves, you have to divide the 2nd sub curve by the next t value.
When all splitting is proceeded, you have the control points of all sub curves. Now there are left only the cubic control point conversion to quadratic. Because all sub curves are now down-elevated cubics, the corresponding quadratic control points are easy to calculate. The first and last of quadratic control points are the same as cubic's (sub curve) first and last control point and the middle one is found in the point, where lines P1-P2 and P4-P3 crosses.
Conventions/terminology
Cubic defined by: P1/2 - anchor points, C1/C2 control points
|x| is the euclidean norm of x
mid-point approx of cubic: a quad that shares the same anchors with the cubic and has the control point at C = (3·C2 - P2 + 3·C1 - P1)/4
Algorithm
pick an absolute precision (prec)
Compute the Tdiv as the root of (cubic) equation sqrt(3)/18 · |P2 - 3·C2 + 3·C1 - P1|/2 · Tdiv ^ 3 = prec
if Tdiv < 0.5 divide the cubic at Tdiv. First segment [0..Tdiv] can be approximated with by a quadratic, with a defect less than prec, by the mid-point approximation. Repeat from step 2 with the second resulted segment (corresponding to 1-Tdiv)
0.5<=Tdiv<1 - simply divide the cubic in two. The two halves can be approximated by the mid-point approximation
Tdiv>=1 - the entire cubic can be approximated by the mid-point approximation
The "magic formula" at step 2 is demonstrated (with interactive examples) on this page.
Another derivation of tfinniga's answer:
First see Wikipedia Bezier curve
for the formulas for quadratic and cubic Bezier curves (also nice animations):
Q(t) = (1-t)^2 P0 + 2 (1-t) t Q + t^2 P3
P(t) + (1-t)^3 P0 + 3 (1-t)^2 t P1 + 3 (1-t) t^2 P2 + t^3 P3
Require these to match at the middle, t = 1/2:
(P0 + 2 Q + P3) / 4 = (P0 + 3 P1 + 3 P2 + P3) / 8
=> Q = P1 + P2 - (P0 + P1 + P2 + P3) / 4
(Q written like this has a geometric interpretation:
Pmid = middle of P0 P1 P2 P3
P12mid = midway between P1 and P2
draw a line from Pmid to P12mid, and that far again: you're at Q.
Hope this makes sense -- draw a couple of examples.)
In general, you'll have to use multiple quadratic curves - many cases of cubic curves can't be even vaguely approximated with a single quadratic curve.
There is a good article discussing the problem, and a number of ways to solve it, at http://www.timotheegroleau.com/Flash/articles/cubic_bezier_in_flash.htm (including interactive demonstrations).
I should note that Adrian's solution is great for single cubics, but when the cubics are segments of a smooth cubic spline, then using his midpoint approximation method causes slope continuity at the nodes of the segments to be lost. So the method described at http://fontforge.org/bezier.html#ps2ttf is much better if you are working with font glyphs or for any other reason you want to retain the smoothness of the curve (which is most probably the case).
Even though this is an old question, many people like me will see it in search results, so I'm posting this here.
I would probably draw a series of curves instead of trying to draw one curve using a different alg. Sort of like drawing two half circles to make up a whole circle.
Try looking for opensource Postcript font to Truetype font converters. I'm sure they have it. Postscript uses cubic bezier curves, whereas Truetype uses quadratic bezier curves. Good luck.

Resources