From basic math I know how to get a point from a circle:
x = (int) (xCenter + radius * Math.cos(angle));
y = (int) (yCenter + radius * Math.sin(angle));
So changing variable angle I can get any point of a circle, or draw a circle if I continiously inrement angle from 0 to 2PI.
Is there a way to get a point position from complex objects like Letters, where I can get any point of shapre representing Character or draw it on continious incremention ?
The shape of "a letter" depends on the font, obviously. I believe most vector fonts (like PostScript and TrueType) are just Bézier curves, which are purely mathematical, so you may be able to derive a formula or algorithm by studying Bézier curves.
Some resources to get you started:
Wikipedia: Bézier curve (with lots of juicy formulas!)
PostScript and Geometry by David Austin in GVSU's Math department
Guide to PostScript Programming by Peter Weingartner
PostScript by Peter Kleiweg
Related
My task is to render quadratic Bezier curve (path) via Stage3d (Adobe Flash) technology, which have no any extensions for that drawing out-of-the box (while OpenGl have it, as I know). Yea, there is a Starling-Extension-Graphics, but it uses simple method to divide a curve segment to many straight lines, that generates very many triangles for my long curve path.
So.. There is a perfect way for rendering resolution independed shapes for Loop and Blinn. I've read GPUGems3 article (gpugems3_ch25.html)
and ported that fragment shader to AGAL2:
Quadratic Curve Pixel Shader
float4 QuadraticPS(float2 p : TEXCOORD0,
float4 color : COLOR0) : COLOR
{
// Gradients
float2 px = ddx(p);
float2 py = ddy(p);
// Chain rule
float fx = (2*p.x)*px.x - px.y;
float fy = (2*p.x)*py.x - py.y;
// Signed distance
float sd = (p.x*p.x - p.y)/sqrt(fx*fx + fy*fy);
// Linear alpha
float alpha = thickness - abs(sd);
if (alpha > 1) // Inside
color.a = 1;
else if (alpha < 0) // Outside
clip(-1);
else
// Near boundary
color.a = alpha;
return color;
}
It works. But there are two fundamental problems:
I don't understand that algorithm :(. I read about signed distance field, derivates and other... I thought a lot of hours and read again - but no result! My question is: Does anyone help me and explain what happens in that shader (line by line (!), if it possible)?
The second problem is that the curve is clipped at the corner of triangle and has a variable thickness. Please look at the picture:
https://monosnap.com/file/84EBOuQ1czNM5lprQ5VlnRUKP2mKmW
So if I draw a path it looks like this: https://monosnap.com/file/54Zs5Xui6s3BL6lNdZRCx9ibcV2bCF
I like that method by using one triangle per curve segment, because no any geometry needed. And I don't need to have very thick curves (1-2 px is excellent), but a variable thickness is a problem. Can anybody help me?
(Sorry for my English. It is not my native language.)
[edit1 by Spektre] just moved from comment and invalid answer
I plan to use one triangle per one curve segment, something like on the picture
the path consists from many triangles
one per one path segment (quadratic curve)
How to handle issue with this approach if all control points are collinear (lie on the same straight) or nearly collinear?
For 3 control point Bezier curves I would:
use triangles as primitives
enlarge control points to include area around curve to avoid artifacts
This way is fast and there is no problem to compute A',B',C' from A,B,C and vice versa. If the scale is constant (for example scale=1.25) then the max usable curve thickness<=2.0*min(|control_point-M|)*(scale-1.0).
For safer enlargement you can compute exact scale needed (for example in geometry shader) and pass it to vertex and fragment ... All of above can be done by Geometry shader. You should use transparency to correctly join the curves together. The average middle point should stay the same M=A+B+C=A'+B'+C'
if transparency is not an option
Then you need to change the approach so pass control points and position inside textures.
create one 2D float texture with control points
something like float pnt[9][N]
pnt[0,1,2][] is control point A(x,y,z)
pnt[3,4,5][] is control point B(x,y,z)
pnt[6,7,8][] is control point C(x,y,z)
also create 1D color texture
something like rgba col[N]
The x axis resolution of both textures = N is the number of Bezier curves
now draw single Quad covering entire screen
And inside fragment shader check if pixel is inside any of the curve. If yes output its color ...
This can get very slow for high Bezier curve count N
[edit1] almost collinear control points
for those I would use Quads
D,E are mirrored points A,B around C
D=C+C-A
E=C+C-B
C is the middle point M = (A+B+D+E)/4 = C = (A'+B'+C'+D')/4
and A',B',C',D' are enlarged A,B,D,E control points
A'=C+(A -C)*scale
B'=C+(B -C)*scale
A =C+(A'-C)/scale
B =C+(B'-C)/scale
This can be used for any Bezier not just almost colinear but it uses larger polygons so it will be slower on performance (more fragments then really needed)
Here more advanced/optimized GLSL approach with complete implementation of cubic BEZIER curves:
rendering 2D cubic BEZIER with GLSL
I cant seem to figure out how to calculate the incline of a curve for the following situation...
Essentially what I am trying to do is increase the speed of an object based on the incline of the curve at a particular point. The speed will be reduced if the incline is upwards and increase if downward.
I was using the derivative of a point t on the bezier curve to establish the tangent but this doesnt seem to be right as I would expect that value to be negative if the slope is downward.
I have been using the below equation for the tangent to evaluate X, Y and Z but then I only use Y to establish the incline...I think that step may be wrong
Any ideas?
EDIT:
Ultimately this is an object moving along an inclined plane but I cant establish the angle of the plane in order to do this, I believe if I could correctly find the angle it may solve the problem. I tried to take the point in question and then another point in front (so for example t = 0.5 and then a point in front would be t=0.51) and then calculate the angle using tan. I completely ignore the Z axis but is that wrong? If not how should I calculate the angle?
Thanks a lot
This should help: http://www.physicsclassroom.com/Class/vectors/U3L3e.cfm .
Essentially, you need to calculate the angle of inclination. If the angle is \theta , then the acceleration depends on sin(\theta).
I am assuming z as the vertical dimension.
if dx,dy and dz is are the gradients in each directions, dw = sqrt( dx^2+dy^2). \theta = tan_inverse( dz/dw). Acceleration = g*sin(\theta).
NOTE: You can directly calculate sin(\theta) without explicitly calculating \theta. sin(\theta) = dz/sqrt(dx^2+dy^2+dz^2).
=== More formal description ===
Let x be the east-west dimension, y be the north-south dimension and z be the up-down dimension.
Let z = F(x,y) give the elevation of the terrain at any given location x,y.
Calculate dz/dx = fx(x,y) and dz/dy = fy(x,y), the partial derivatives of z w.r.t to x and y.
Now, sin(\theta) = dz/sqrt(dx^2+dy^2+dz^2) = 1/(sqrt( (dx/dz)^2+ (dy/dz)^2 )= 1/(sqrt( (1/fx(x,y))^2, (1/fy(x,y))^2 ).
This is how you calculate sin(\theta).
The value of derivation is negative when the slope is "downward". And yes, the derivation is the tangent of the slope angle. Only you should pay attention to the directions. They can change the sign, of course. Only you should take dy/dx, not dy/something else. That is all on 2d curves.
You mention Z in the last paragraph. You curve is 3D? Then, of course, the term "derivation" should be put more precisely. Derivation of what to what do you need? The second idea is - please, explain better, what do you want. BTW, maybe after you write down the task correctly, you'll see the solution as obvious.
If it is 3D, let us say, you have your curve as 3 functions of x(t), y(t), z(t). then you need dz/dq, where dq= dt*sqrt((dx/dt)^2+(dy/dt)^2). Obviously, isn't it?
As I said, no maths here. Merely Pythagor's theorem and proportions. (I take z as height)
Addition: it can be rerecounted as tan(a)=dz/(dt*sqrt((dx/dt)^2+(dy/dt)^2)) => tan(a)=(dz/dt)/sqrt((dx/dt)^2+(dy/dt)^2)) ==> a=ATAN((dz/dt)/sqrt((dx/dt)^2+(dy/dt)^2)). But look out for directions you are moving! They can reverse the sign. For under sqrt(^2+^2) we have lost the direction of the dt proection.
So first of all I have such image (and ofcourse I have all points coordinates in 2d so I can regenerate lines and check where they cross each other)
(source: narod.ru)
But hey, I have another Image of same lines (I know thay are same) and new coords of my points like on this image
(source: narod.ru)
So... now Having points (coords) on first image, How can I determin plane rotation and Z depth on second image (asuming first one's center was in point (0,0,0) with no rotation)?
What you're trying to find is called a projection matrix. Determining precise inverse projection usually requires that you have firmly established coordinates in both source and destination vectors, which the images above aren't going to give you. You can approximate using pixel positions, however.
This thread will give you a basic walkthrough of the techniques you need to use.
Let me say this up front: this problem is hard. There is a reason Dan Story's linked question has not been answered. Let provide an explanation for people who want to take a stab at it. I hope I'm wrong about how hard it is, though.
I will assume that the 2D screen coordinates and projection/perspective matrix is known to you. You need to know at least this much (if you don't know the projection matrix, essentially you are using a different camera to look at the world). Let's call each pair of 2D screen coordinates (a_i, b_i), and I will assume the projection matrix is of the form
P = [ px 0 0 0 ]
[ 0 py 0 0 ]
[ 0 0 pz pw]
[ 0 0 s 0 ], s = +/-1
Almost any reasonable projection has this form. Working through the rendering pipeline, you find that
a_i = px x_i / (s z_i)
b_i = py y_i / (s z_i)
where (x_i, y_i, z_i) are the original 3D coordinates of the point.
Now, let's assume you know your shape in a set of canonical coordinates (whatever you want), so that the vertices is (x0_i, y0_i, z0_i). We can arrange these as columns of a matrix C. The actual coordinates of the shape are a rigid transformation of these coordinates. Let's similarly organize the actual coordinates as columns of a matrix V. Then these are related by
V = R C + v 1^T (*)
where 1^T is a row vector of ones with the right length, R is an orthogonal rotation matrix of the rigid transformation, and v is the offset vector of the transformation.
Now, you have an expression for each column of V from above: the first column is { s a_1 z_1 / px, s b_1 z_1 / py, z_1 } and so on.
You must solve the set of equations (*) for the set of scalars z_i, and the rigid transformation defined R and v.
Difficulties
The equation is nonlinear in the unknowns, involving quotients of R and z_i
We have assumed up to now that you know which 2D coordinates correspond to which vertices of the original shape (if your shape is a square, this is slightly less of a problem).
We assume there is even a solution at all; if there are errors in the 2D data, then it's hard to say how well equation (*) will be satisfied; the transformation will be nonrigid or nonlinear.
It's called (digital) photogrammetry. Start Googling.
If you are really interested in this kind of problems (which are common in computer vision, tracking objects with cameras etc.), the following book contains a detailed treatment:
Ma, Soatto, Kosecka, Sastry, An Invitation to 3-D Vision, Springer 2004.
Beware: this is an advanced engineering text, and uses many techniques which are mathematical in nature. Skim through the sample chapters featured on the book's web page to get an idea.
I need an algorithm to convert a closed bezier curve (perhaps self-crossing) to a binary bitmap: 0 for inside pixels and 1 for outside. I'm writing a code that needs to implement some operations on bezier curves, could anybody give me some resources or tutorials about beziere? Wikipedia and others didn't say anything about optimization, subtracting, union, knot insertion and deletion and other operations :-)
alt text http://www.imagechicken.com/uploads/1271001073057545100.jpg
This paper by Charles Loop and Jim Blinn goes into lots of detail on your question.
Another option is to tessellate the Bezier curve into line segments and then use your favorite polygon fill algorithm.
I'd like to add that the tessellation option is very efficient and gives excellent results. It sounds wrong to approximate a Bezier curve by line segments, because you think the output will look like a polygon. The trick is to make the line segments short enough so that the error is very small (say, less than 1/10 of a pixel).
Here is a formula that I have used to compute the step size, to ensure that the maximum error (i.e., deviation of line segments from true curve) is less than delta:
Let (x1,y1), (x2,y2), (x3,y3), (x4,y4) be the control points of the Bezier curve, in pixel coordinates.j
dd0 = square(x1-2*x2+x3) + square(y1-2*y2+y3);
dd1 = square(x2-2*x3+x4) + square(y2-2*y3+y4);
dd = 6*sqrt(max(dd0, dd1));
Then dd is the maximal value of the 2nd derivative over the curve - because the 2nd derivative of a cubic is a linear function, this maximum must occur at an endpoint. Here I have used square(x) as an abbreviation for x*x.
if (8*delta > dd) {
epsilon = 1;
} else {
epsilon = sqrt(8*delta/dd);
}
Then epsilon is your step size: if you choose the endpoints of your line segments at t=0, t=epsilon, t=2*epsilon, ..., (and the last endpoint at t=1), then the line segments will be within delta of the original curve.
Choose delta = 0.1 and you get bitmap output that is visually indistinguishable from the original curve.
This may be a little hard to describe since I don't have a sample. I'm trying to find a math function or full 3d function in php or a similar language that can help me with the following effect:
imagine if you were to take a flat sheet or paper and glue it on a glass of water. It wouldn't be flat any more. It would have a curve, and one of its sides might end up being slightly hidden.
Anyone can refer me to a good library or resource on the web where such functions can be found?
Lets say the center of your paper is x=0, and your cylinder is vertical along the y-axis. Your x-coordinate on the paper could be equated to an arc length on the surface of the cylinder. Arc length (s) is equal to the angle (in radians) times the radius. Your radius is given, so you can compute the angle from the arc length and radius. Angle = Arc Length / Radius. Since you now have the angle and the radius, you can compute the new x-offset, which would be (radius * cos(angle)). So your mapping functions would be:
new_x = radius * cos(old_x/radius)
new_y = old_y; //y-coordinate doesn't change
new_z = radius * sin(old_x/radius);
You'll have to enforce boundaries (keep x on the paper, and make sure it's not more than half the circumference (x must be less than or equal to PI*r). Also, watch the signs... especially the z-coordinate, which will depend on whether your coordinate system is right-handed or left-handed, or where you imagine the paper starting on the cylindar (back or front). Finally, you can use standard matrix transforms to move and position the paper/cylinder in 3D space once you have the warped coordinates.