Path
From Svg wiki
<page>
Contents |
The Path
Paths are explained in section 8 of the SVG specification.
Paths describe a series of connected points, and how connections between those points are drawn, be they straight lines or a variety of curved ones.
The syntax used to describe a path is used by several SVG elements some of which include <path>, <clipPath>, <mask>, <textPath> , <glyph> , <missing-glyph> , <animateMotion>
Path Commands
To quote the spec, "A path is defined by including a 'path' element which contains a d="(path data)" attribute, where the d attribute contains the moveto, line, curve (both cubic and quadratic Béziers), arc and closepath instructions."
For example:
<path d="M200,300 Q400,50 600,300 T1000,300" fill="none" stroke="red" stroke-width="5" />
Most of working with paths is a matter of figuring out the "commands" inside the path, such as M and Q in the above example.
Path commands
| command type | command | definition | parameters=== |
|---|---|---|---|
| moveto | M | absolute moveto | (x y)+ |
| m | relative moveto | (x y)+ | |
| closepath | Z | absolute closepath | (none) |
| z | relative closepath | (none) | |
| lineto | L | absolute lineto | (x y)+ |
| l | relative lineto | (x y)+ | |
| horizontal lineto | H | absolute horizontal lineto | x+ |
| h | relative horizontal lineto | x+ | |
| vertical lineto | V | absolute vertical lineto | y+ |
| v | relative vertical lineto | y+ | |
| curveto (cubic bezier) | C | absolute curveto | (x1 y1 x2 y2 x y)+ |
| c | relative curveto | (x1 y1 x2 y2 x y)+ | |
| smooth curveto | S | absolute smooth curveto | (x2 y2 x y)+ |
| s | relative smooth curveto | (x2 y2 x y)+ | |
| quadratic bezier curveto | Q | absolute quadratic bezier curveto | (x1 y1 x y)+ |
| q | relative quadratic bezier curveto | (x1 y1 x y)+ | |
| smooth quadratic bezier curveto | T | absolute smooth quadratic bezier curveto | (x y)+ |
| t | relative smooth quadratic bezier curveto | (x y)+ | |
| eliptical arc | A | absolute elliptical arc | (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ |
| a | relative elliptical arc | (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ |
elliptical arc paths
Why is elliptical arc like that in SVG
A standalone elliptical arc is most easily described by defining the entire ellipse—the centre x and y, the semi-major and semi-minor radii (the radius at largest and smallest points) and then, in a coordinate system centred on the centre of the ellipse, giving the start and end angles.
In a path, the start of the path and the start of each subpath sets up a current point valid for the scope of that path only (there is no global current point in SVG, as that is generally considered a bad thing in computer graphics circles).
Path commands that draw something start with the current point, add whatever other points they need to (zero or more) and then, finish off with a new current point, which is used by the next command.
In early drafts of SVG, the elliptical arc command was an exception. It used the more usual parameterisation of an ellipse. This meant that it ignored the current point it was given (but it was the responsibility of the arc-generating software to ensure the ellipse lined up with that point) and it failed to provide a new current point (so there had to be extra software to calculate that point and to pass it along, and the software for all the other commands had to look in two places for the current point—get it from the path, unless the previous command was an elliptical arc in which case...).
Later drafts of SVG fixed this and regularised the syntax by re-parameterising the ellipse in terms of a current point and an end point, which is the new current point for the next command as with all other path commands. The details are described in http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes, which not only covers conversion between the two parameterisations of an ellipse, but also allows consistent implementation even in edge cases such as exactly semi-circular arcs and those caused by round-off error or radii that tend towards zero.
What do large-arc-flag and sweep-flag mean?
Consider an (analogue) clock, ie one with hands. It's nine o'clock. We could talk of the circular act defined by the position of the two hands.
But wait—that's ambiguous. There are two circular arcs: one (the short one) from the hour hand at 9 through 10 and 11 to the minute hand at 12 and the other (the long one) from the minute hand at 12 through 1, 2 ... 8 to the hour hand at 9.
Another way to say it is, from the minute hand, one arc goes clockwise (1, 2, 3, 4, etc.) and the other arc goes anticlockwise (12, 11, ...).
For a clock, which is circular, we only need one of those two means of resolving the ambiguity. Either one would do.
For an elliptical arc, and a given start point and end point, there are four possible arcs and we need both methods at once—to say whether it is the large arc (true or false, zero or one) and whether it is a line from the center of the ellipse to the start point sweeps through increasing angles (45, 50, 55) or decreasing angles (45, 40, 35). Bear in mind that SVG has a Y-down coordinate system so increasing angles is clockwise.
Now look at the example and diagram at the end of section 8.3.8 with a new understanding ;-) locate the start and end points, see if the arc is big or little, see if it goes through increasing or decreasing angles.
http://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
Bézier theory
Some 2D Bézier theory, howto split a Bézier curve, and howto draw a Bézier ellipse. Bézier everywhere ;)
By Philippe Elsass (beez::svg bezier animator - open source project).
Interactive examples are links to Michael Hirtzler's web site ([Pilat Informative Educative | http://pilat.free.fr/english/])
This is not intented to fully present the Bézier theory, but to show how it is used. If you want more informations look at the Bézier related links (at page bottom).
Basics
The Bézier curve is a parametric function that describes an interpolated curve.
Let's say it is composed from N+1 control points. The curve starts from the first point P0 and ends with the last point PN.
Just imagine that there would be a straight line between P0 and PN. Then, each points between P0 and PN attracts and distorts the line.
Why did i said N+1 control points? Because the equations are polynomials N degree. That's why, with 3 control points, it is called quadratic Bézier, and with 4 control points, it is called cubic Bézier...
What does parametric mean?
* Let 'u' be the parameter ('u' is a float value between 0 and 1).
* Let P(u) be a point of a parametric path (ie. line or curve).
Then, P(u=0) is the path's start point, P(u=0.5) is the middle point, and P(u=1) is the end point. This means that the point P(u) will be the point between O% (u=0) and 100% (u=1) of the length of the path.
Some properties
- The origin of the curve is tangent to the line (P0,P1) and the end is tangent to the line (PN-1,PN).
- The curve is contained within the convex hull of the control points.
- The curve in general does not pass through any of the control points except the first and last.
- Closed curves can be generated by making the end point the same as the origin point.
Smooth junction between 2 Bézier curves
Let's consider curve 1 defined by the points Pi and curve 2 defined by the points Qi. Then for a smooth junction, you just need the points (PN-1, PN=Q0, Q1) to be on the same line. Another way to say it, is that curve 1 end's tangent equals curve 2 start's tangent.
Geometric approach and spliting
A very comprehensive way to draw Bézier curves is geometrical. Actually this is a very nice method: smart and easy.
Quadratic Bézier: 3 control points
See Cubic Bézier example.
To find P(u) like described above about parametric functions, we define several temporairy points:
- A(u) on the straight line between P0 (start point) and P1 (end point),
- B(u) between P1 and P2,
- C(u) between A(u) and B(u),
That's all: P(u) is C(u)!
See Cubic Bézier for interactive example.
Cubic Bézier: 4 control points
To find P(u) like described above about parametric functions, we define several temporairy points:
- A(u) on the straight line between P0 (start point) and P1 (end point),
- B(u) between P1 and P2,
- C(u) between P2 and P3,
- D(u) between A(u) and B(u),
- E(u) between B(u) and C(u),
- F(u) between D(u) and E(u).
That's all: P(u) is F(u). (I think you guess it becomes tedious with more than 4 points)
A great interactive example (choose u on the line between P1 and P3):
- [Cubic Bézier : construction with barycentres | http://pilat.free.fr/english/svg/bezier_cub_bary.htm]
Spliting Bézier curves
Now, take a closer look at the temporairy points we found for the geometric method. That is really really nice: we have cut the curve into 2 new ones!
P0,A(u),D(u),F(u) and F(u),E(u),C(u),P3
Amazing isn't it?
Common Bézier equations
Usually only quadratic and cubic Bézier are used because they are fast to compute. Moreover, any Bézier curve can be decomposed in several Bézier curves of lower or equal degree.
Linear Bézier: 2 control points
Just to help understand. This theory is so nice that a Bézier curve defined by 2 control points is precisely a parametric line ;)
Parametric equations:
x(u) = x0*(1-u) + x1*u = x0 + (x1-x0)*u y(u) = y0*(1-u) + y1*u = y0 + (y1-y0)*u
With SVG:
L (x y)+
P0 is the current point. P1 is (x,y)
Quadratic Bézier: 3 control points
Typically, Macromedia Flash's smooth drawings are made from quadratic Bézier curves. That is the reason why you can freely distort the curves (it is more complicated with cubic Bézier curves).
Parametric equations:
x(u) = x0*(1-u)^2 + x1*2*u(1-u) + x2*u^2 y(u) = y0*(1-u)^2 + y1*2*u(1-u) + y2*u^2
With SVG:
Q (x1 y1 x y)+ T (x y)+
P0 is the current point. P1 is (x1,y1). P2 is (x,y). When creating a shape with several Bézier curves, you can use SVG's smooth quadratic Bézier (T). SVG will reuse the previous P1: the new P1 will be previous P1's symetric point relative to the actual current point.
Smooth continuity interactive examples with 2 quadratic Bézier:
- [Q and Q Bézier curves | http://pilat.free.fr/english/svg/bezier.htm]
- [Q and T Bézier curves | http://pilat.free.fr/english/svg/bezier_qua.htm]
Cubic Bézier: 4 control points
Typically, shapes in vector drawing programs like Adobe Illustrator are made from cubic Bézier curves. The control points are presented as nodes (start and end points) with antennas (like in the following svg with a circle quarter).
Parametric equations:
x(u) = x0*(1-u)^3 + x1*3*u*(1-u)^2 + x2*3*u^2*(1-u) + x3*u^3 y(u) = y0*(1-u)^3 + y1*3*u*(1-u)^2 + y2*3*u^2*(1-u) + y3*u^3
With SVG:
C (x1 y1 x2 y2 x y)+ S (x2 y2 x y)+
P0 is the current point. P1 is (x1,y1). P2 is (x2,y2). P3 is (x,y). When creating a shape with several Bézier curves, you can use SVG's smooth cubic Bézier (S). SVG will reuse the previous P2: the new P1 will be previous P2's symetric point relative to the actual current point.
Interactive example of a cubic Bézier:
- [C Bézier curve | http://pilat.free.fr/english/svg/bezier_cub.htm]
Circle approximation with cubic Bézier curves
Note: A circle is a quadratic curve. With a cubic Bézier you will just have an approximation (it's good but not perfect). The right way is to do it with quadratic Bézier curves but it requires more points.
Circle quarter
We choose the control points for a radius = 1.
P0(0,1), P1(k,1), P2(1,k), P3(1,0)
We want to find k to obtain a circle!
You can take any of the equations for the x or the y coordinate. Let u=1/2 (middle of the curve):
x(1/2) = 0*1/8 + k*3/8 + 1*3/8 + 1*1/8
= cos(45) // to have a circle
...
k = (sqrt(2)-1)*4/3 =~ 0.552 (it seems to be precise enough)
Now let's repeat this quarter four times, and we will have a nice circle. Let's scale it, and we will have a nice ellipse.
With SVG
Attention: don't forget that if you use transforms to scale your circle, the stroke will be scaled too. If you scale it by 100, "stroke-width:1" will become 100!
Circle:
d="m 0,1 // translate(radius) from center
C 0.552,1 1,0.552 1,0 // 1st quarter
1,-0.552 0.552,-1 0,-1 // 2nd
-0.552,-1 -1,-0.552 -1,0 // 3rd
-1,0.552 -0.552,1 0,1z" // 4th
Ellipse example:
<path style="fill:none; stroke:blue; stroke-width:0.04"
transform="translate(55,30) scale(50,25)"
d="m0,1 C0.552,1 1,0.552 1,0 1,-0.552 0.552,-1 0,-1 -0.552,-1 -1,-0.552 -1,0 -1,0.552 -0.552,1 0,1z" />
General Bézier Related Links
- A link discussing Bézier theory and c example: http://astronomy.swin.edu.au/pbourke/curves/bezier/
- A link discussing drawing Béziers using a geometrical method: http://www.kevlindev.com/tutorials/primitives/bezier/index.htm
- A link to more discussion about approximating a circle with a Bézier: http://www.whizkidtech.net/bezier/circle/
- A nice java applet (we will have to replace this with an SVG example ;) ): http://www.cs.princeton.edu/~min/cs426/jar/bezier.html
- A Dr Math background on the topic: http://mam2000.mathforum.org/dr.math/problems/deichmeister12.3.96.html
