How to optimally plot parametric continuous curve? - geometry

Let's say we have a parametric curve, for example a circle:
x = r * cos(t)
y = r * sin(t)
We want to plot the curve on the screen in a way that:
every pixel is painted just once (the optimal part)
there is a painted pixel for each (x, y) that lies on the curve (the continuous part)
If we just plot (x, y) for each t in [t1, t2], these conditions will not be met.
I am searching for a general solution for any parametric curve.

A general solution that 100% satisfies your criteria does not exist.
So we have to compromize.
Usually this is tackled by starting with a stepsize (usually a parameter to your routine), this stepsize can be subdivided triggered by a heuristic e.g.:
subdivide when the distance covered by a segment is larger than a given distance (e.g. one pixel)
subdivide when the curve direction changes too much
Or a combination of these.
Usually some limit to subdivision is also given to avoid taking forever.
Many systems that offer parametric plotting start with some changeable default setting for the heuristic params and step size. The user can adapt these if the curve is not "nice" enough or if it takes too long.
The problem is that there are always pathological curves that will defeat your method of drawing making it miss details or taking overly long.

Check out Bézier splines.

Related

Fitting a transition + circle + transition curve to a set of measured points

I am dealing with a reverse-engineering problem regarding road geometry and estimation of design conditions.
Suppose you have a set of points obtained from the measurement of positions of a road. This road has straight sections as well as curve sections. Straight sections are, of course, represented by lines, and curves are represented by circles of unknown center and radius. There are, as well, transition sections, which may be clothoids / Euler spirals or any other usual track transition curve. A representation of the track may look like this:
We know in advance that the road / track was designed taking this transition + circle + transition principle into account for every curve, yet we only have the measurement points, and the goal is to find the parameters describing every curve on the track, this is, the transition parameters as well as the circle's center and radius.
I have written some code using a nonlinear optimization algorithm, where a user can select start and end points and fit a circle that to the arc section between them, as it shows in next figure:
However, I don't find a suitable way to take the transition into account. After giving it some thought I came to think that this s because, given a set of discrete points -with their measurement error- representing a full curve, it is not entirely clear where to consider it "begins" and where it "ends" and, moreover, it is less clear where to consider the transition, the proper circle and the exit transition "begin" and "end".
Is there any work on this subject which I may have missed? is there a proper way to fit the whole transition + curve + transition structure into the set of points?
As far as I know, there's no method to fit a sequence clothoid1-circle-clothoid2 into a given set of points.
Basic facts are that two points define a straight, and three points define a unique circle.
The clothoid is far more complex, because you need: The parameter A, the final radius Rf, an initial point px,py, the radius Ri at that point, and the tangent T (angle with X-axis) at that point.
These are 5 data you may use to find the solution.
Due to clothoid coords are calculated by expanded Fresnel integrals (see https://math.stackexchange.com/a/3359006/688039 a little explanation), and then apply a translation & rotation, there's no an easy way to fit this spiral into a set of given points.
When I've had to deal with your issue, what I've done is:
Calculate the radius for triplets of consecutive points: p1p2p3, p2p3p4, p3p4p5, etc
Observe the sequence of radius. Similar values mean a circle, increasing/decreasing values mean a clothoid; Big values would mean a straight.
For each basic element (line, circle) find the most probably characteristics (angles, vertices, radius) by hand or by some regression method. Many times the common sense is the best.
For a spiral you may start with aproximated values, taken from the adjacent elements. These values may very well be the initial angle and point, and the initial and final radius. Then you need to iterate, playing with Fresnel and 'space change' until you find a "good" parameter A. Then repeat with small differences in the other values, those you took from adjacents.
Make the changes you consider as good. For example, many values (A, radius) use to be integers, without decimals, just because it was easier for the designer to type.
If you can make a small applet to do these steps then it's enough. Using a typical roads software helps, but doesn't avoid you the iteration process.
If the points are dense compared to the effective radii of curvature, estimate the local curvature by least square fitting of a circle on a small number of points, taking into account that the curvature is most of the time zero.
You will obtain a plot with constant values and ramps that connect them. You can use an estimate of the slope at the inflection points to figure out the transition points.

Covering any surface with helix-shaped curves

I have a question about the feasability of an idea.
I have a surface (which can be parametrized or defined implicitly by an equation F(x,y,z) = 0) and I want to draw some helix that fit the surface, litterally helix on the surface.
What would be the process to achieve that ?
I have a basic idea ,which is inspired from ray marching methods, : I have my surface (which have a finite area) then I 'draw' a big helix curve around it and I decrease the radius of the helix. If the helix intersect the surface then I save that point, and finally I would obtain the set of points that draw an helix on the surface...
Feel free to ask me questions about the problem.
Thank you for your attention.
thomas
There are different ways to understand "drawing a helix curve" on a surface. By the way, I am not sure that you use the proper term, as a helix is a spring-like curve and is not flat at all. I will instead assume some planar curve described by an implicit C(x,y)=0 or parametric x=Xc(t),y=Yc(t) representation.
One approach is by using a (u,v) parameterization of the surface, as used in texture mapping, x=Xs(u,v), y=Ys(u, v), z=Zs(u, v). For example, for a sphere (u,v) could correspond to the angle coordinates in the spherical system. In this case, it suffices to map x=u, y=v and there will be a direct correspondence between the points of the curve and the points of the surface.
Another approach is by "extruding" the curve in the z direction to form a cylindric surface, and intersect the cylindre with the surface. In this case, you form the system
S(x, y, z)= 0
C(x, y)= 0
where z is free, and solve for (x, y) as a function of z. (You can also use the parametric equations, there are different combinations.) In fact, you perform a parallel projection of the curve.
Instead of a cylindre, you can also think of a conic surface, by choosing a vertex point, say the origin, and considering the points (zx, zy, az) where a is an "aperture" coefficient and z is free. This idea is vey close to your "radius decrease" method and corresponds to a central projection.

Choosing step for Bezier curve drawing

Bezier curve is a parametric curve, meaning that there is a paramater t at which one can evaluate the polynomials in order to find out the positions of points laying on the curve.
Polynomials for some common cases can be found at en.wikipedia.org/wiki/B%C3%A9zier_curve#Specific_cases
To draw a Bezier curve on screen, one could evaluate the polynomials from 0 to 1 at ever increasing t by tiny little steps. However, that would very wasteful because, in general, the parameter "space" does not correspond to screen "space", i.e. several little steps may fall onto just one pixel.
My question is: how to find the smallest step which increases Cartesian distance from previous point at least by 1 pixel?
To put it in other way: I would like to draw a Bezier curve on screen. How to choose the (uniform) step by which t should grow so that I never draw at one pixel more the once? I don't mind the "holes" when the t grows too quickly, I just don't want to redraw already drawn pixels.
Edit
By "how to find" I mean O(1). Yes, I could use De Casteljau's algorithm but I was hoping there is a way to "guess" the optimal t step quickly.
The comment above (jozxyqk) gives you a hint. I would give it a try with a recursive binary division of the spline drawing.
Lets say you start with a coarse resolution of the parameter space (delta_t = 0.1), that gives you 11 points on the spline curve s , s(t=0), s(t=0.1), ..., s(t=0.9), s(t=1).
Calculate the distance between s(t_i) and s(t_i+1). If it is >1 than make a binary subdivision between those two points. And so on...
But honestly, I guess it is faster to calculate all points a a higher resolution without any recursive loops or subdivisions. Especially if you are using multithread programming.

Two Dimensional Curve Approximation

here is what I want to do (preferably with Matlab):
Basically I have several traces of cars driving on an intersection. Each one is noisy, so I want to take the mean over all measurements to get a better approximation of the real route. In other words, I am looking for a way to approximate the Curve, which has the smallest distence to all of the meassured traces (in a least-square sense).
At the first glance, this is quite similar what can be achieved with spap2 of the CurveFitting Toolbox (good example in section Least-Squares Approximation here).
But this algorithm has some major drawback: It assumes a function (with exactly one y(x) for every x), but what I want is a curve in 2d (which may have several y(x) for one x). This leads to problems when cars turn right or left with more then 90 degrees.
Futhermore it takes the vertical offsets and not the perpendicular offsets (according to the definition on wolfram).
Has anybody an idea how to solve this problem? I thought of using a B-Spline and change the number of knots and the degree until I reached a certain fitting quality, but I can't find a way to solve this problem analytically or with the functions provided by the CurveFitting Toolbox. Is there a way to solve this without numerical optimization?
mbeckish is right. In order to get sufficient flexibility in the curve shape, you must use a parametric curve representation (x(t), y(t)) instead of an explicit representation y(x). See Parametric equation.
Given n successive points on the curve, assign them their true time if you know it or just integers 0..n-1 if you don't. Then call spap2 twice with vectors T, X and T, Y instead of X, Y. Now for arbitrary t you get a point (x, y) on the curve.
This won't give you a true least squares solution, but should be good enough for your needs.

Trigonometrical ratios for angles higher than 360

Is there any use of Sin(720)or Cos(1440) (angles in degrees)?
Whether in computer programming or in any other situation?
In general, is there any use of Sin/Cosine/Tan of any angle
greater than 360?
In Physics we do use dot products and cross products
a lot, but even they require angles less than 180 degrees
always.
Hi All,
I know how to compute them....
I want to know, if they are ever useful????
When will I ever encounter a situation, when
I need to compute Sin(440) for example???
Both in math and programming:
Sin(x) = Sin(x % 360)
As another answer pointed out, angles greater than 360 represent one or more full rotations over a circle plus the modulo part. This could have a physical meaning in some circumstances.
Also, when doing trigonometric calculations, you should take this fact into consideration. For example:
sin(a)*cos(a) = (1/2)*sin(2a)
For a>180 you will get the sin of an angle greater than 360.
By the way, have a look here.
I have seen such things come up when doing angle arithmetic:
float angleOne = 150;
float angleTwo = 250;
//...
float result = Sin(angleOne + angleTwo); // Sin(400)
float result = Sin(angleOne - angleTwo); // Sin(-100)
In this (contrived) example, it seems obvious, but when you are computing an angle based on arbitrary rotations of several objects, you can't always know what kind of numbers you would be getting. Imagine calculating the poisition of the player in a 3D game while he is standing on top of a spinning platform, for example.
Any time you're dealing with a user interaction technique, it's entirely possible that they'll push you past 0 degrees or 360 degrees. Imagine that you're making a game with a gun turrent. It's currently pointed at 359 degrees and the user yanks the joystick to the right: now it's pointed at 361 degrees. If you implement the angular representation wrong, all of a sudden, the gun with rapidly traverse nearly 360 degrees to the left.
I predict that the users will be ... disappointed with that bug.
There are all sorts of issues that come up with Euler angle representations of the frame of reference that are important in games, simulations and real device control. Gimbal lock is a serious problem in actual rotating device control (it was a problem with camera pan / tilt devices in my life). The "rapid rotation" bug was a very nasty issue in a small boat autopilot system once upon a time - imagine wrapping a steel cable very tightly around the wheel house (i.e., you don't want to be standing there).
There have been times where the normal math means you end up "traversing the circle" one or more times, and if you keep the math simple your angles might be greater than 360. Personally I like to normalize the angles to be 0 to 360 or -180 to 180 after such operations, but it's doesn't really matter much.
Sometimes the greater number might really represent something. To take a trivial example, imagine instructions to open a classic dial combination safe. You need to spin the dial around a couple of times, so the instructions could be:
turn(800); // Twice around plus another 20 degrees
turn(-500); // Once around the other direction plus 140 degrees
turn(40); // Dial in the last digit
In that context, taking the sin or cos would tell you something about the ultimate position of the dial, but you would lose the information about how many turns were involved.
One rotation around a circle is 360 degrees or 2pi radians.
Trigonometric functions such as sine and cosine will "wrap around" when they reach 360 degrees and act the same way as being at 0 degrees. Basically, the following occurs:
angle_in_unit_circle = angle mod 360
Also, some trigonometric functions such as tangent are not defined at certain angles, such as 90 and 270 degrees, where tangent of an angle will return a positive or negative infinity.
This "wrapping" around can be seen by representing the sine, cosine, tangent functions using an right triangle inscribed in an unit circle, and this behavior makes those functions periodic because they will repeat their patterns over and over again.
Wikipedia has an extensive article on Trigonometric functions, so that might be worth taking a look at.
Usage
In terms of use, I can't quite think of a good example off the top of my head, except, maybe perhaps to represent a location of a particle at a certain time in a polar coordinate system, where the angle θ is dependent on time t:
r(θ(t)) = t where θ(t) = t
for values of t from 0 to 720, which could then be represented in a Cartesian coordinate system as:
x(t) = r sin(θ(t)) == t sin(t)
y(t) = r cos(θ(t)) == t cos(t)
The particle will be moving in a spiral type movement, dependent on the time t. In this case, the sine and cosine of angles beyond 360 will be calculated.
(And my math is rusty, so if there are any errors in the equations above, please let me know!)
On a sine curve, Sin(720) == Sin(0) (etc), so I'd expect any decent implementations of those functions to handle degrees "greater than" 360. There's any number of reasons for arriving at an angle greater than 360 or less than 0.
Angles outside the range of "principal angles" [-180,180) are essentially aliases of each other (modulo 360 degrees) and have no physical distinction.
From a mathematical/engineering sense, if you have a process where the # of rotations is important and must be kept track of (e.g. a motor that is spinning back and forth), then 0 degrees and 720 degrees are not the same. Sine and cosine are just periodic functions so they have the same value every 360 degrees. If you have a particle undergoing uniform circular motion where x(t) = A cos (ωt + φ) and y(t) = A sin (ωt + φ), then the phase angle θ = (ωt + φ) is going to be whatever it is, whether 0 or 720 degrees or 82144.33 degrees or whatever.
So the functions cos(θ) and sin(θ) just get used to calculate the x and y coordinates, no matter what the value of θ is. It's not like you have a choice in the matter, if θ is 82144.33 degrees then you're going to want to calculate the sine and cosine of that angle.
I play a PC game called Garry's Mod, and there are moments in the game where, when programming, I want a simple solution to keep an object constantly moving in a constant circle. To do this I use the sine and cosine of a forever increasing timer, measuring the amount of time since the game launched.
The sine of T (time) is equal to the orbit paths X value, while the cosine of T is equal to the orbit paths Y value(X and Y being on a 3 dimensional coordinate plane with Z not being used at the moment.)
Example:
T=1000 ticks
X=sin(T)
Y=cos(T)
So X is 0.8268795405320025 during that moment in time and Y is 0.15466840618074712.
Now let's say the amount of time grows to 1500. X would be -0.9939019569066535 and Y = -0.11026740251372914.
In a nutshell, it would constantly fluctuate from 1 to -1, leaving me the opportunity to multiply that value by say 100, and making the coordinate plane local to my characters position, then I can tell the programmed expression to move an object based on those coordinates and it would move in a constant circular path around me.
Tada. Who says you can't learn from video games?
Because sin(x) = sin(x mod 360°) and cos(x) = cos(x mod 360°) you can use every value in calculation, but you could also normalize to the range [0°,360°) or any other range of 360°. It just depends on the usage if large angles have a well defined meaning or not.
Processors will likley normalize the calculation to just a range of 90° or even less, and derive all other values from this small range.
When will arguments greater than 360° occur?
They naturaly occur in simulations of periodic time or space dependent functions.
Your question does not make much sense seeing as you seem to know the difference here:
No - you will never have to "compute" Sin(720), anymore than you will have a need to "compute" Sin(0). You need to look at the definition of the Sinus function to fully understand what goes on under the covers - and when that is understood it makes total sense for anyone as to why Sin(0) = Sin(720) - there's nothing magical going on, there's (logically) no Angle = FullAngle % 360 going on, it's all in the definition of what the function is supposed to do.
See wikipedia
#dta, I think folks are a little confused. You ask if it's ever "useful." I'd say "It doesn't matter, because you just shift the angle to the proper range when performing the calculation." There are certainly cases where you need to know how far from 0 degrees an object has rotated, accounting for multiple rotations. But aside from those cases, it's more convenient to interpret angles in the normal 0-360 range. Most people build up an intuitive feel for which direction corresponds to angles in that normal range. What direction does 170,234 degrees point? The same as 314 degrees.
As #Chris Arguin and others said, whether sin of an angle greater than 360° (or for that matter less than -360°) is useful to you depends on whether you need the information about rotations (or fractions thereof) that is represented by the difference between angle and angle%360°.
Also, since you get the same answer, you'll save a little processing time if you call sin(angle) instead of sin(angle%360), especially if you are doing many computations in a loop.
OTOH, #Scottie T makes a good point that if it is important for someone to know where around a circle your angle points, people can generally intuit position of an angle with an absolute value of 360 or less easier than they can for larger angles.
There are many circumstances where angles outside of [0,360] are needed. I like the idea of a combination lock. Here one will often see both positive and negative angles outside of the simple [0,360] degree range.
Multiple angle formulas are often important in mathematics. Trig functions are used in places other than just triangles. They appear in a variety of places, Fourier series for example, or image compression schemes, or the solution of differential equations. Computationally, it is true that you can always use mod to reduce the range for a trig function to the default. But it is rarely true that angles will always be provided in that nominal range.
There definitely can be times when you might end up with an angle measure > 360 degrees because of some kind of calculation...but it would be identical to an infinite number of other angle measures, exactly one of which will be between 0 and 360. However, if you are coding a function, you should be able to handle this calculation yourself...not rely on the user to do the mod for you.
ie While it is true that sin(370) == sin(10), and the user could do this translation themselves, they may not want to for one reason or another (see the "bolt" example in the comments for the top rated answer), and so the function should be able to handle any value.
Angles higher than 360 degrees are also used e.g. to describe snowboard tricks:
http://en.wikipedia.org/wiki/List_of_snowboard_tricks#Spins
So you see, there are various real world example where you use higher angles to describe the rotation of an object.

Resources