how SVG curveTo ( C ) works? - math

I need your help , I am confused a little.
My question is how SVG curveTo works, really I can't understand.
look for this example
<svg height="400" width="400">
<path d="M 200 90 C 200 90 0 0 90 300 " stroke="black" fill="none" stroke-width="3"/>
</svg>
this code draws this shape
but really I can't understand how that done , I can't understand how the curve identified and what control points are and what 0 0 coordinate represents in my example.

You are drawing a Cubic Bezier curve (with two control points). But one of the control points has the same coordinates as the starting point.
Move (M) to (200,90).
Draw a Cubic (C) Bezier Curve
a. starting at current position (200,90)
b. first control point at (200,90) - same as starting point
c. second control point at (0,0)
d. ending at (90,300)

Bezier curves are a bit tricky to get the sense of. Perhaps the section at http://www.w3.org/Graphics/SVG/IG/resources/svgprimer.html#path_C might help, and maybe the section before that on quadratic Beziers. As the earlier poster pointed out, having your start point and the control point coincident makes your case a bit odder, still, perhaps.

Related

What is a generic data structure for bezier curves or b-splines?

I am wondering how you would model arbitrarily complex Bézier curves. I am not quite understanding the underlying abstraction yet of what a bezier curve is fundamentally composed of, as there are too many equations. I would like to have a generic struct that defines a bezier curve. The SVG path gives many examples of the types of curves you can create. They include linear, cubic, and quadratic bezier curves.
If a B-spline is a better generic model, then that would be fine to use too. I am not familiar with those yet tho. Difference between bezier segment and b-spline. I guess "a B-spline curve is a curve that consists of Bezier curves as segments", so that is what I am looking for.
SVG docs say:
Cubic Béziers take in two control points for each point.
<path d="M 10 10 C 20 20, 40 20, 50 10" stroke="black" fill="transparent"/>
Several Bézier curves can be stringed together to create extended, smooth shapes. Often, the control point on one side of a point will be a reflection of the control point used on the other side to keep the slope constant. In this case, a shortcut version of the cubic Bézier can be used, designated by the command S (or s).
<path d="M 10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80" stroke="black" fill="transparent"/>
The other type of Bézier curve, the quadratic curve called with Q, is actually a simpler curve than the cubic one. It requires one control point which determines the slope of the curve at both the start point and the end point. It takes two parameters: the control point and the end point of the curve.
<path d="M 10 80 Q 95 10 180 80" stroke="black" fill="transparent"/>
Arcs and NURBS (non-uniform rational B-splines) are more complex than just plain bezier curves, but it would be nice if the model could be generalized enough to include these as well. Basically I would like a generic model of bezier curves/b-splines/nurbs to use in a drawing/graphics framework, and not sure what that would be.
Must each bezier class be implemented separately, or can they be combined into one generic class?
If separate, are they each basically just an array of control points?
So basically I start to think:
class CubicBezierCurve
include ActiveModel::Model
has_many :control_points
end
class ControlPoint
include ActiveModel::Model
attr_accessor :x, :y
end
But that doesn't quite seem right. A primitive cubic bezier curve, for instance, consists of 2 control points for each point. So perhaps (though, starting to get lost):
class CubicBezierCurve
include ActiveModel::Model
has_many :control_points, class_name: 'CubicBezierCurveControlPoint'
end
class CubicBezierCurveControlPoint
include ActiveModel::Model
attr_accessor :x, :y
end
class Point
include ActiveModel::Model
attr_accessor :x, :y
end
Basically, what is a good generic model for these 3 types of bezier curves (linear, cubic, and quadratic). If it's possible to make them all aspects of the same generic model that would be ideal (as it would mean the fewest number of classes), but if it requires class-specific other classes (like those specific to a cubic bezier curve), that would be fine too.
Implementation can be in any language, such as C structs, typescript, or Ruby models, Python classes, etc..
The reason for this question is so I can then build a DSL for creating curves on top of it, like the SVG path syntax. But the underlying data model will be the compile target.
For further reference, I will be researching these:
https://github.com/twobitcircus/ofxTinyspline, e.g. these structs
https://github.com/pradeep-pyro/tinynurbs/blob/master/include/tinynurbs/core/surface.h
https://github.com/orbingol/NURBS-Python/blob/5.x/geomdl/NURBS.py
https://github.com/StandardCyborg/nurbs
This is just for 2D graphics.
The most generic data structure for a Bezier curve is simply one that contains an array of control points. The degree of the Bezier curve is the number of control points - 1. So, linear, quadratic and cubic Bezier curves can all use the same data structure with difference in number of control points.
For B-spline curve, the generic data structure will contain
Degree (D)
Number of control points (N)
Array of control points
Knot sequence.
The knot sequence is simply a "double[ ]" of length = N+D+1. The knot values need to be in non-decreasing order.
A Bézier curve of degree n is simply d polynomials, one for each dimension.
Each polynomial is written in Bernstein form and has n plus one coefficients (better known as control points). These coefficients alone determine the polynomial. It may thus be helpful to treat each dimension (polynomial) separately, as the Bernstein basis is a rather intuitive way to describe polynomials. See also the paper cited below.
REFERENCES:
Farouki, R.T., 2012. The Bernstein polynomial basis: A centennial retrospective. Computer Aided Geometric Design, 29(6), pp.379-419.

Zero tangent of a 3D Bezier curve, how to handle?

As peculiar as it seems, the direction (tangent) of a Bezier curve may be zero (0,0,0) at some point. E.g. for the symmetrical Bezier curve defined as:
bezier.anchor1.copyFrom(new Vector3D(-1,0,0));
bezier.control1.copyFrom(new Vector3D(1,0,0));
bezier.anchor2.copyFrom(new Vector3D(1,0,0));
bezier.control2.copyFrom(new Vector3D(-1.,0,0));
the direction at t=0.5 is (0,0,0). This might be a rare/extreme use case, but I definitely need to always have a non-zero direction at hand.
Programmatically speaking, how should I handle it? Recalculate the direction at another nearby t (say t1=t*0.99999=0.499995) and return that direction instead?
Things are a little worse than your example. Its quite possible to have a cusp occurring in a cubic Bezier curve. For example with control points [80,214], [217,50], [75,50], [222,206]. Your example is actually a flattened cusp.
.
Cusps are quite tricky to deal with if you follow the tangents to the curve they go through a 180º flip at the cusp point. Cusps are also quite common, if you have an animated sequence of curves you are likely to have a cusp occurring in one frame as a loop unfolds. You see them quite often in the real world, in the pattern of light at the bottom of a teacup, and in the projection of curves in 3D onto 2D (eg project the curve (t,t^2,t^3) onto the Y-Z plane). The good news is that they are generally isolated points, you'll only ever get one on a cubic Bezier curve.
Now how to handle these cusps might depend on you application. If it say describes the path of some object what will happen is the object comes to a standstill at the cusp point and leaves in the opposite direction. It might be quite reasonable to say the object has a zero tangent vector at this point. It might be possible to split the curve at the cusp point.
You can see an interactive example with movable control points http://jsfiddle.net/SalixAlba/QQnvm/6/ In javascript with a canvas
var P = [{X: 80, Y: 214 },
{X: 217, Y: 50 },
{X: 75, Y: 50 },
{X: 222, Y: 206 }, ];
ctx.beginPath();
ctx.moveTo(P[0].X, P[0].Y);
ctx.bezierCurveTo(P[1].X, P[1].Y, P[2].X, P[2].Y, P[3].X, P[3].Y);
ctx.stroke();
I wouldn't know why you can't have a 0 norm vector as a derivative. I suppose you're trying to animate something along a curve, then that derivative is the speed... and your speed at that point is zero because you're momentarily not moving. There should be no problem with that.
Why 0 ? Let's look at a pathological case
See this illustration where the anchors are (-1,-y,0) and (-1,y,0) and control points (1,-y,0), (1,y,0)respectively.
Now you see what happens to the tangent that is drawn at parameter-defined points t=0, t=0.5, and t=1. At t=0.5, the tangent has lost all its component among the x axis but is still shifting slowly towards thee y axis, thus having a small tangent to the right.
However the more you modify this y parameter to become 0, you will flatten the curve and obtain a segment. At the points t=0.5, your tangent not have a zero x compoenent (like before) but also on the y dimension since the figure will be one-dimensional.
So a zero tangent is a pathological case that may arise when your figure has too little dimensions.
Work-around : reducing the degree
There are many orders for a Beziers curve, the formula for a generic order n is :
with Pi the points of your curve, and the bi are known as Bernstein basis polynomials of degree n (see this wikipedia section for different illustrations of different orders of the curve).
In your case, you are going from (-1,0,0) to (1,0,0), with control points on that same line, effectively drawing the segment [(-1,0,0), (1,0,0)]. Thus you draw a segment, and you only really need 2 points : you should use a first order polynomial, which is defined by t * P0 + (1-t) * P1, a trivial interpolation. In your formalism that would be, I guess :
bezier.anchor1.copyFrom(new Vector3D(-1,0,0));
bezier.anchor2.copyFrom(new Vector3D(1,0,0));
and no control points.
Then no 0 tangents (unless you get a cusp) !

SVG curve through predetermined points

I am a beginner in SVG.
I need an SVG curve that passes through a list of points. It is a math function that is calculated in C++ and the output result is supposed to be written in an SVG file. My problem is that the path tag in SVG does not pass through all points. Instead, it skips some of them in the middle and just tends to them. Does SVG have any facility to pass the curve through the whole points and bend the curve appropriately in automatic way?
<svg height="400" width="450">
<path d="M 80 90 C 190 40, 300 60, 380 160" stroke="blue" stroke-width="5" fill="none" />
<path d="M 80 90 L 190 40, 300 60, 380 160" stroke="green" stroke-width="1" fill="none"/>
<g stroke="black" stroke-width="3" fill="black">
<circle id="pointC" cx="80" cy="90" r="3" stroke="black"/>
<circle id="pointA" cx="190" cy="40" r="3" stroke="green"/>
<circle id="pointC" cx="300" cy="60" r="3" stroke="red"/>
<circle id="pointB" cx="380" cy="160" r="3" stroke="blue"/>
</g>
Sorry, your browser does not support inline SVG.
</svg>
If you need to draw smooth curve through many points, considering using Catmull Rom splines or Overhauser splines. Both algorithms will result in a cubic spline with C1 continuity at the segment junctions. Also, they are easier to implement than implementing C2 B-spline interpolation as the latter requires you to solve a linear equation set. You can also convert Catmull Rom spline or Overhauser spline back to Bezier form easily.
in SVG path thee Bezier curve is approximation not interpolation so it is usually not passing through all the control points.
Sp what to do:
use interpolation cubic curve and convert it to Bezier
Look here: Interpolation cubic to Bezier cubic (needed this for similar reasons like you)
I use a specific interpolation cubic there with connectivity C1 (position and 1st derivation) the translation to Bezier is there so you can use it just convert the control points ... Do not forget to 3x multiple only first and last control point for the whole Bezier path not for each Bezier patch !!!
use many lines instead of single Bezier
this will be choppy of coarse (depending on the lines density) just interpolate enough points and connect them by lines
duplicate control points
if you have multipled control points (3x) then the Bezier will go through this point. So if you have curve points: p0,p1,p2,p3,... then do multiple Beziers from them like this:
p0,p0,p0,p1
p0,p0,p1,p2
p0,p1,p2,p3
p1,p2,p3,p3
p2,p3,p3,p3
p3,p3,p3,p4
p3,p3,p4,p5
p3,p4,p5,p6
p4,p5,p6,p6
p5,p6,p6,p6,...
this will go through the points p0,p3,p6,... so you still need to evaluate the non passing control points to ensure desired connectivity
If you need to draw curve through 4 points only, look at the solution in this topic and linked tinaja page.
If you have to draw smooth curve through many points, consider building interpolation cubic splines (NR book, page 113), than transform these splines to Bezier form (change bazis from polynomial to Bernstein)

Simple 2D Plane Trajectory with Bezier Curve

Hello and Happy New Year !
Let me begin with the strict facts instead of writing the whole scenario here.
This is what i have:
A plane in 2D Space (X,Y)
A destination this plane has to fly to in 2D space (X,Y)
A bezier curve class that generates the bezier from 4 points (A,B,C,D)
This is what i need to do:
When user clicks on the space in X', Y' i need to generate a bezier curve
for this plane to fly there.
These are some assumptions:
It is known that plane can't rotate in one place, it has to make some minimal turn
It is known that when destination is in front of the plane it doesn't make any turn
Bezier curve has to be calculated from 4 points where
point A = actual plane position
point B = actual plane position + actual plane direction * 2 (so it goes forward a bit ? )
point C = needs to be calculated
point D = plane destination
Here are few of those scenarios drawn:
Question:
How do i calculate this bezier curve, i already have point A,D but i need those B,C to make this turn proper.
How can i characterize this bezier so that let's say planeA has smaller turns than planeB ?
I almost had it, but almost is nothing in this case so i better rewrite this with your help.
Thanks for any help with this, i am scratching my head with this and found it's not that easy i was thinking... or ?
The point B that you described ("actual plane position + actual plane direction") would work quite well. How far you go along the plane direction will adjust when the plane begins its turn.
For point C, setting it to be same as point D (the destination) will work quite well.
As for turning rates, I'm not sure you're going to get much control using a (cubic) bezier curve. They are all about location and direction, with nothing to tweak the second order curvature. Adjusting point B might be a good compromise, but it's more adjusting reaction time and path rather than turning rate.

How to reflect an angle across the Y axis

I am no mathematician, but I somehow got into game development as a hobby.
Having never studied anything beyond basic math, I have a lot of trouble figuring out how to reverse the angle of something, facing to the opposite direction, along the X axis & across the Y axis.
One image says more than 1000 words though (specially uneducated words):
http://img156.imageshack.us/i/wihwin.png/
I basically want to reverse the direction of cannon objects adhered to a robot. When the robot changes from facing right to facing left, I do (180 - angle) as everyone suggested me, but it literally reverses the angle, making the cannons aim up when they are aiming down. So, I need to do something else, but it escapes my knowledge.
To put it in other words, I work in 2D, so I want an angle that is facing right to face left. My angles are defined:
0 being "totally to the right"
180 "left"
90 "up" and
270 "down"
I want something that is aiming with an angle of 91 to turn into 89 when reversed. There's no Z axis present. Anyone would be so kind to help me with this?
In answer to your edit what you want then is
-( x - 90 ) + 90
i.e.
180 - x
Of course you will likely be working in radians and not degrees if you are using the standard C trigonometric functions so that would actually be
M_PI - x
Basically this breaks down into three steps
( x - 90 ) adjusts your angle so that the zero point is at 90 degrees.
Negating this then flips the transformed angle.
Add 90 back on to transform back to the original angle range.
Edit: Just noticed this is the same as #Paul R but you didn't seem to think that was correct?
This is quite tricky to answer without knowing a bit more about how the cannons are defined in your game, but I'll try to give some pointers.
It sounds like your cannon is viewed from the side, and you are wanting it to turn around from right to left but keeping the cannon facing up. The calculation depends on which direction 0 is, and whether the angles run clockwise or anticlockwise.
If the angle of 0 has the cannon pointing straight up, then the angle is measured from straight up, clockwise. Therefore, the reverse angle will be -angle. If negative angles don't work then use (360-angle).
If the angle of 0 has the cannon pointing to the right and an angle of 45 points to the bottom right, then the upward facing cannon angles are from 180 to 360 with 270 being straight up. Therefore, to reverse an angle, you'd use (540-angle).
If the angle of 0 has the cannon pointing to the right but an angle of 45 points to the top right, then the cannon angles are from 0 to 180. To reverse the angle, use (180-angle).
I hope that helps! Lee.
It depends on how you are defining your angle. If you define it relative to the X axis then the angle is indeed just (180 - alpha).
Looking at your diagram, the angles you've marked are the same - you've simply changed the starting point for them. If you actually intended to measure the angle so that 0 deg is straight up, then it's 360 - x
Thus if you have aimed at 45 degrees, when you reverse it is 360-45 = 315 degrees
Where does your zero degree angle point, and where does 90 degrees point?
If zero is straight up then you could just do -1 * angle.

Resources