The svg path for a file created in Inkscape is the following --
d="m 1.2499932,903.60456 0,146.50004 197.7500068,0 0,-146.50004 -197.7500068,0 z m 166.9375068,29.0625 0.75,88.62504 -3.53125,3.5312 -82.312507,0.25 -3.28125,-2.75 0.25,-82.09374 -12.625,0 -2.28125,5.8125 -43.9375,-0.25 c -4.90662,-3.46937 -0.70544,-8.07521 5.03125,-12.875 l 141.937507,-0.25 z"
I usually see an L, H, V, C, S, Q, T, or A command following the x,y position after the initial m command. In this case there are 5 x,y positions following the m command before the next command. This breaks my parsing code. I don't understand the role of the extra four positions.
All pairs of co-ordinates after the initial pair are treated as implicit lineto commands i.e. as if they were preceded by an l (or an L if the inital command was an M).
Related
When creating an SVG path, typically the capital letters (M, L...) in the d attribute refer to absolute coordinates and the lower case letters (m, l...) refer to relative coordinates to the last point.
Here's an example that draws a small right triangle in absolute coordinates:
<path style="stroke:black;fill:none;" d="M100,100 L150,100 V50 Z" />
This draws the same triangle in relative coordinates:
<path style="stroke:black;fill:none;" d="m100,100 l50,0 v-50 z" />
I can use a capital or lowercase M and Z in either case and visually, nothing is changed. Regarding M, I assume that since it is the first point, it is absolute or relative to (0, 0), but please correct me if that is wrong. What is the difference of z and Z?
In all cases:
An upper-case command specifies absolute coordinates, while a lower-case command specifies coordinates relative to the current position. path_commands
But in the case of z/Z, there is no difference (ClosePath). There is no absolute or relative coordinate associated with the z/Z, so it will just create a straight line between the last point and the starting point.
Both z and Z define the Path Command: ClosePath
Path commands are instructions that define a path to be drawn. Each command is composed of a command letter and numbers that represent the command parameters.
SVG defines 6 types of path commands, for a total of 20 commands:
MoveTo: M, m
LineTo: L, l, H, h, V, v
Cubic Bézier Curve: C, c, S, s
Quadratic Bézier Curve: Q, q, T, t
Elliptical Arc Curve: A, a
ClosePath: Z, z
Ive got 2 points in 3d space (with the same y coordinate). Ill call them c and m. I want to find the corner points (marked in the pic as p1-p4) of a square with the width w. The important thing is, that the square is not parallel to the x-axis. If it were, (for p1 as an example) I could just do:
p1.x = m.x + w / 2
p1.y = m.y + w / 2
p1.z = m.z
How would I do the same with a angled square? These are all the given points:
m; c
and lenghts:
w; d
There's multiple ways to do it, but here's one way.
If the two points are guaranteed to have the same y value, you should be able to do it as follows.
Take 'm - c' and call that u. Normalize u. Then take the cross product of u and the y axis to get v, a vector parallel to the xz plane that's perpendicular to u. (This can be optimized, but that's unlikely to be important.) Then take the cross product of u and v to get a third vector, w. Note that you can use 'm - c' or 'c - m', or use different orders for the cross-product arguments, and it'll still work, but the resulting vectors may point in different directions (but only opposite directions). You can also normalize at different points in the process and get the same results at the end.
Once you have m, v, and w, you can use some basic vector math to compute the corners.
[Edit: I see you have a variable named 'w', so I should clarify that the 'w' in my example is a different 'w' than yours. As for your 'w' and 'd', those would factor in in the vector math I mentioned at the end.]
SVG's path defines several commands (M, m, L, l, z, etc). However I sometime see missing/blank commands, e.g.
m 0,0 20,0 0,20 -20,0 z
It would appear that no command is a line command but I can't find this documented anywhere. Is this the case?
This is documented at several places in the SVG specification
https://www.w3.org/TR/SVG11/single-page.html#paths-PathData
The command letter can be eliminated on subsequent commands if the same command is used multiple times in a row (e.g., you can drop the second "L" in "M 100 200 L 200 100 L -100 -200" and use "M 100 200 L 200 100 -100 -200" instead).
and also under the explanation of the M command:
If a moveto is followed by multiple pairs of coordinates, the subsequent pairs are treated as implicit lineto commands.
For example in following case, there are two nested drawings, I want to calculate the area of the larger path and ignore the other.
path style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.0343547;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0"
d="M 207.87305 372.2832 L 207.87305 750.23633 L 585.82617 750.23633 L 585.82617 372.2832 L 207.87305 372.2832 z M 302.36133 466.77148 L 491.33789 466.77148 L 491.33789 655.74805 L 302.36133 655.74805 L 302.36133 466.77148 z " transform="matrix(0.9375,0,0,0.9375,0,5.0439605e-6)" id="path4562" />
I need a function that returns points on a circle in three dimensions.
The circle should "cap" a line segment defined by points A and B and it's radius. each cap is perpendicular to the line segment. and centered at one of the endpoints.
Here is a shitty diagram
Let N be the unit vector in the direction from A to B, i.e., N = (B-A) / length(A-B). The first step is to find two more vectors X and Y such that {N, X, Y} form a basis. That means you want two more vectors so that all pairs of {N, X, Y} are perpendicular to each other and also so that they are all unit vectors. Another way to think about this is that you want to create a new coordinate system whose x-axis lines up with the line segment. You need to find vectors pointing in the direction of the y-axis and z-axis.
Note that there are infinitely many choices for X and Y. You just need to somehow find two that work.
One way to do this is to first find vectors {N, W, V} where N is from above and W and V are two of (1,0,0), (0,1,0), and (0,0,1). Pick the two vectors for W and V that correspond to the smallest coordinates of N. So if N = (.31, .95, 0) then you pick (1,0,0) and (0,0,1) for W and V. (Math geek note: This way of picking W and V ensures that {N,W,V} spans R^3). Then you apply the Gram-Schmidt process to {N, W, V} to get vectors {N, X, Y} as above. Note that you need the vector N to be the first vector so that it doesn't get changed by the process.
So now you have two vectors that are perpendicular to the line segment and perpendicular to each other. This means the points on the circle around A are X * cos t + Y * sin t + A where 0 <= t < 2 * pi. This is exactly like the usual description of a circle in two dimensions; it is just written in the new coordinate system described above.
As David Norman noted the crux is to find two orthogonal unit vectors X,Y that are orthogonal to N. However I think a simpler way to compute these is by finding the householder reflection Q that maps N to a multiple of (1,0,0) and then to take as X the image of (0,1,0) under Q and Y as the image of (0,0,1) under Q. While this might sound complicated it comes down to:
s = (N[0] > 0.0) ? 1.0 : -1.0
t = N[0] + s; f = -1.0/(s*t);
X[0] = f*N[1]*t; X[1] = 1 + f*N[1]*N[1]; X[2] = f*N[1]*N[2];
Y[0] = f*N[2]*t; Y[1] = f*N[1]*N[2]; Y[2] = 1 + f*N[2]*N[2];