Close SVG path (Z) with control points? - svg

I draw SVG path like this:
Start:
M x, y
Add Curve
Q x1, y1, x, y
etc etc.... and when I want to close path I just add Z
But that last line segment now doesn't have any control points.
How can I close path and also have control points on that last segment?
Something like : Z Q x1, y1 where Z closes path (current point to first point) but it uses x1 and y1 as control points, not just straight line.

I understand your desire. Every time I draw a freehand blob in Illustrator I always set the final point on the original point and then drag to create a tangent for the control points on either side.
SVG has no such feature like this. There is no path command that does this. The closest are the shorthand path commands S and T, but these derive the first control point from the last control point on the previous command, whereas what you want is something that derives the second control point from the first control point on the next command (wrap-around style).
You could do this with JavaScript, e.g. markup like
<path d="… Z" class="smooth-close" />
…and a small script that finds all the smooth-close paths, determines the appropriate control point from the first commands and generates a S or T command and appends it to the path data. But since you did not tag your question with javascript I assume such a solution would not interest you.

Related

Drawing quadrant shape with cv2 in Python

I'm extracting door shapes with Cubicasa5k dataset but I don't know how svg draws quarter rounds.
Extracted some nodes of svg files with xml encoding, I found that it had a dictionary including 'd' key and value under of "Panel" id tree node like :
{'d': 'M825.47,986.05 q0.00,-72.92 72.92,-72.92 l0.00,72.92Z'}
It draws like this quarter round on svg image.
I want to draw that shape on raster image with cv2 in Python with that dictionary value.
Read article about 'd' commands but I'm still confused.
How can I draw it?
Okay, I hope I understood that d command of svg clearly now
That arc shape is Bézier curve, and it is drawn concavely based on the outer point, not on the centripetal point.
According to the example above ('M825.47,986.05 q0.00,-72.92 72.92,-72.92 l0.00,72.92Z'), it means drawing process following this:
The starting point of arc shape(called Bézier curve) is (825.47, 986.05).
The drawn reference point exists at a position shifted only to the y-axis. So the reference point is (825.47+0.00, 986.05-72.92) = (825.47, 913.13)
And the end point of arc shape is set following calculation about starting point like 2 : (825.47+72.92, 986.05-72.92) = (898.39, 913.13)
Drawing door shape finishes with drawing straight line that starts from the end point of the curve and ends with l code, it points (898.39+0.00, 913.13+72.92) = (898.39, 986.05)
Simply speaking, the door shape is drawn with arc and straight line, arc starts from left bottom and ends right top, then straight line starts from that right top and ends right bottom.
So if using cv2, should call cv2.ellipse, and set center point from process 4 above, axes(same value will show circle-like shape, so it's radius) from q command above, startangle and endangle(it differs from command above)

SVG path data format differences

I'm working on a project where I need to parse svg path data.
Right now we're loading an svg, looking for the path tag, and pulling out it's d attribute.
For some of the artwork we'll get path data that is made up of coordinates which we can translate into the data types we need. E.g.
But other times the d value is in a more g-code-esq format.
Like in this case I drew a rectangle, converted it to a compound path:
And when I export it and look at the svg I get a d value like this:
Which we can't easily parse for the project.
My questions are:
How do I read this second format? It doesn't seem to fit what I'm reading on MDN so I suspect there's some other documentation I need to refer to: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d
For illustrator users, is there a way of changing the format when exporting?
I know that this seems like more of an art question than a programming question, but I'm trying to understand the underlying reasoning behind the svg data structure so I can better parse it.
Oh! Oh ok, I was 100% misunderstanding the path data that I was reading. I didn't realize that the delimiting information was based on the letter. My brain wanted some specific character as a delimiter like a comma or pipe.
So reading (and in some cases re-reading :| ) the documentation, when I see:
M753,315H435.27V165H753Z
I can read that as:
M753,315 Move to x,y coordinates x: 753 y:315
H435.27 Starting at the current location, draw a horizontal line to the absolute x coordinate of 435.27
V165 Starting at the current location, draw a vertical line to the absolute y coordinate of 165
H753 Starting at the current location, draw a horizontal line to the absolute x coordinate of 753
ZDraw a straight line to the initial point of this path to close the path. This doesn't necessarily mean a horizontal or vertical line, but the coincidence that we're at the same x coordinate that we started at means that if we draw a straight line we will get a vertical line to complete the rectangle
That seems right. Anything I missed or misunderstood?
Also, thank for all of the links. I appreciate the points :clap: :bows:

Converting relative (‘m’) command to absolute (‘M’) commands in SVG files

I like to understand how I can change SVG path which contains relative (‘m’) command to absolute (‘M’) commands. I have created two identical paths where Green path should cover Black, but that is not is case. How SVG compiler render relative path. Your help will be very much appreciated.
In SVG files a letter represents a command followed by some arguments. The lower command letter represents relative coordinates where upper case represents absolute coordinates. The Z commands the closing loop. The closing loop means the pen has gone back to the same position where it started. In my case I was not going back to the same position which gave me the bad output. Please note in case of small 'm' we have to add coordinates the previous absolute coordinates.
Now my application works fine.

d3.js (svg) path directionality vs. marker-end, hive plots

Scenario:
I am currently working with d3.js Hive Plots, and for an experimental scenario, I need control of the visual directionality of the links.
Problem Source:
I am using d3.hive.v0.js "add-on", and due to the fact that Hive Plots charts do not inherently carry any visual directionality information on the links, the add-on does not adhere to source and target nodes with regards to directionality of the drawn path, and always draws the paths clockwise, and hence always pointing in the direction of the node to the left when snapping on a marker-end.
Problem Effect
Pointers are unreliable because the path "end" that the marker adheres to, is not nescessarily at the target, but may be at the source, depending on the source and targets relative position to each other.
What it boils down to
I know that I could draw my own links with my own Arcs and gain more control, instead of using the d3 Hive Plot library links, and I have tried it, but it's not easy to get nice, and the Hive Plot algorithm is pretty and I would like to use it.
Let's say I intercept d, when it comes back from the Hive Plot link path algo.
I find d = "M 8.327598234202001e-15,-136 C 101.06769626492562,-91.00176246480473 135.0052608777338,14.189624701397365 79.7912059004442,109.82317321396422";
That gives me a nice path, starting in the top, and drawing down (CW) as demostrated in
http://jsfiddle.net/hwehqhtm/1/
svg.selectAll(".test")
.data(d3.range(1))
.enter().append("path")
.attr("class", "link")
.style("stroke", "green")
.attr("stroke-width", 3)
.attr("marker-end", "url(#arrow)")
.attr("d", d)
My question is, now that I have d, is it possible to "reverse the draw direction" of the line by doing something on d ? , - making "path end" be the top end of the line, and make the marker-end go here, effectivly making the link point the other direction.
The line should be visually identical, only logically "beginning" in the other end.
The parent fiddle http://jsfiddle.net/hwehqhtm uses two different markers for start and end, but then I would have to include new logic in some marker-end and marker-start callbacks to switch them on off, and I would really prefer to just mathemagically make it draw "the other way" by "reversing d" if possible. I'm not good enough at trig to know if this even makes sense. Any comments and solutions on path directionality and markers are very welcome !
Thx
Seems that it can be done by switching around the parameters. The d above, created by the hive plot algorithm turns out to be a moveto and a curveto (bezier) in the format M x y C x1 y1 x2 y2 x y.
To reverse the curve, switching endpoint x,y in C with startpoint x,y in M and then switching the bezier control points x1,y1 with x2,y2 seems to do it.

SVG "Smooth curve" clarification

In the W3C standard for SVGs, I read for 'S' and 's':
(x2 y2 x y)+
Draws a cubic Bézier curve from the current point to (x,y). The first control point is assumed to be the reflection of the second control point on the previous command relative to the current point. (If there is no previous command or if the previous command was not an C, c, S or s, assume the first control point is coincident with the current point.) (x2,y2) is the second control point (i.e., the control point at the end of the curve). S (uppercase) indicates that absolute coordinates will follow; s (lowercase) indicates that relative coordinates will follow. Multiple sets of coordinates may be specified to draw a polybézier. At the end of the command the new current point becomes the final (x,y) coordinate pair used in the polybézier.
In the case of a polybezier, does the "current point" or "previous command" change during this subpath?
In other words, does implicitly calculated first control point ever change during a S or s subpath if multiple sets of coordinates are specified?
The standard says "at the end of the [S or s] command", so I suspect not.
I'm not sure I understand what you are asking, or what you mean by "change".
The following example:
M 0,0 S 100,100, 120,120, 200,200, 220,220
is considered to be a shorthand for:
M 0,0 S 100,100, 120,120 S 200,200, 220,220
So when you get to the second set of S coordinates (the 200s), the "previous command" is considered to be the "S 100,100 120,120", not the "M 0,0".
Is that what you are asking?

Resources