Exporting designs in apps as vector (XML/svg) file? - svg

My ultimate goal is to export designs created in mobile apps as vector graphics. Say I have a list of points of corners of shapes and the respective color that goes inside each shape and this design is being displayed on a mobile app (iOS and Android because cocos2d-x is being used). Is it possible to convert this information into a vector file (SVG file which is essentially an XML file)?

SVG contains a path element that stores the lines that make up a shape's path. The d attribute stores a path string, and the style attribute stores the path's styling, such as stroke and fill. To export a shape to SVG there are several things you should care about:
The size of the SVG in pixels (the width and height attributes).
Example:<svg width='640px' height='640px'
The size of the shape in pixels (the viewBox attribute: left, right, width, height).
Example:viewBox='0 0 100 100'
The color used to stroke the shape and the stroke width.
Example:style='stroke:red;stroke-width:1px' or style='stroke:none;'
The color used to fill each shape.
Example:style='fill:blue;' or style='fill:none;'
The shape of the path.
Example:d='M10 10L20 20 L30 10Z'
Each path is divided into commands. The M command moves the pen,
the L command draws to a new position, and the Z command closes the shape.
There can be any number of paths in a single SVG file.
Example SVG file:
<svg width='640px' height='640px' viewBox='0 0 100 100'
xmlns='http://www.w3.org/2000/svg'>
<path style='stroke:red;fill:none' d='M10 10L20 20 L30 10Z'/>
</svg>

Related

Explanation of SVG path?

I have an SVG path that I'm trying to dynamically create, but the resources I've found on SVG paths don't describe that path I have.
This is the path:
m41.5 1.5v15l-40 10v100h60v-100l-10-10v-15z
I don't even understand the start of it - the m41.6; m moves the pen to a coordinate relative to the last known position. I assume this is the origin? but everywhere I've found says that the syntax is m x,y. If I supply m41.6,0 instead, the svg just disappears - opening in Inkscape doesn't show it either.
I need a step-by-step explanation please of each term.
The full SVG is:
<svg id="svg11" version="1.1" viewBox="0 0 63 128" xmlns="http://www.w3.org/2000/svg">
<path d="m41.5 1.5v15l-40 10v100h60v-100l-10-10v-15z" fill="#ffd42a"/>
</svg>
the resources I've found on SVG paths don't describe that path I have.
Then I guess you didn't consider reading the SVG specification? :)
Try reading the Paths section of the SVG specification . It's all explained quite clearly there.
Explanation
m41.5 1.5
Move to (41.5, 1.5). m is a relative move normally, but the spec says:
If a relative moveto (m) appears as the first element of the path, then it is treated as a pair of absolute coordinates.
Coordinates can be separated by a comma, whitespace, both, or even neither. For example, M1.5.5 is a valid path command, since a coord can't have more than one decimal point, and leading zeros are optional.
M 1.5,0.5, M1.5 0.5, M1.5, 0.5, M 1.5 .5, and M1.5.5 are all equivalent.
v15
Draw a line vertically (downward) by 15 units
l-40 10
Draw a line left by 40 and down by 10 units.
v100
Draw a line down by 100 units
h60
Draw a line right by 60 units
v-100
Draw a line upwards by 100 units
l-10-10
Draw a line diagonally up and left by (10,10)
v-15
Draw a line vertically upwards by 15 units
z
Close the path (ie back to 41.5,1.5)
The path can be rewritten as:
m41.5,1.5 v15 l-40,10 v100 h60 v-100 l-10,-10 v-15 z
or
m41.5 1.5 v15 l-40 10 v100 h60 v-100 l-10 -10 v-15 z
This better separates the individual pen movements which I was confused by when they were all merged together in the original version.

How do you control size of imported SVG's in Three.js?

I am importing an SVG using the SVGLoader and turning each path into a mesh that is then put into a group. When I do so, the group is much larger than I would like it to be. Rather than scaling, I'd like to import it at the correct size to begin with. When I change the width and height attributes on the SVG: <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25"> nothing changes with respect to the size of the rendered meshes. I haven't seen anything actually describing how SVG sizes are determined by the loader. Is it a viewbox? Is there something special that has to be done?
In your 3d world, you can only change the size of your object by Object3D.scale.set(x, y, z),and the x, y, z value determine the size of your mesh in you 3d world. When you change the width and height attributes on the SVG, you can only change the resolution but not the size

How do SVG/EPS (vectors) clip a path by another path?

I try to understand how SVG programs (like browsers) draw a shape by the given paths. I struggle to understand how a path is drawn and one clips part of a shape.
For example, consider the letter Å, and A with a top ring. The SVG code is like
<svg viewBox="0 0 1800 1800" xmlns="http://www.w3.org/2000/svg">
<path
d="
M484 0l-42 137h-245l-47 -137h-147l237 664h161l234 -664h-151z
M426 822q0 -47 -24 -71.5t-80 -24.5q-104 0 -104 96q0 46 25.5 71t78.5 25q56 0 80 -25t24 -71z
M319 515h-1l-85 -264h169z
M374 822q0 51 -52 51q-50 0 -50 -51q0 -49 50 -49q52 0 52 49z
" />
</svg>
JSFIDDLE
First line: draws the body of an A.
Second line: draws a top circle.
Third line: clips a triangle from the first line.
Fourth line: clips a small circle from the second line.
My question is: how do SVG programs understand to draw a shape by the second line, but clip a shape from an existing shape?
Obviously the answer is: if the path is within another path, it clips otherwise it draws.
There are two reasons that I think this not the whole picture:
It needs huge calculations to find if a path is within another path.
The order of lines is not important (the clipping path does not necessarily come after the drawing path).
This is, of course, not limited to SVG, as other vector formats such as EPS does the same.
To add a pragmatic perspective, please read the question as: how can we parse (in any programming language) the above d element to find out which path is drawing (black) and which is clipping (white) out of the four paths given in the above SVG?
Broadly speaking, you don't parse the paths at all.
Instead you 'scan convert' each path to a series of rectangles, at the current resolution. Each reactangle may be as little as one pixel high, and there may be more than one rectangle at a given y value.
Do this for both the path to be filled or stroked and the path to apply as a clip, then intersect the series of rectangles. This is, obviously, a much simpler task. Then fill the rectangles.
This does, of course, produce a result which is only correct at a given resolution. Change the resolution and you get a different series of rectangles. However it produces the correct output at a decent speed. Intersecting two arbitrary paths to produce a new arbitrary path is obviously a much more complex task, and for the purpose of drawing the result, not one we need to perform.
In the next examples I'm using the path for the letter A in your example.
In the first svg element the letter A is drawn from right to left while the hole of is drawn in the opposite dirrection: you get the "clipping".
In the second example I've reversed the part that is drawing the hole. Now this part is drawn in the same direction as the main part of the letter A. Now you won't get the "clipping"
In the third example I'm using the reversed path as before but I'm adding fill-rule="evenodd" Now the hole is clipped since the "fill-rule attribute is a presentation attribute defining the algorithm to use to determine the inside part of a shape".
svg{width:30%;border:solid}
<svg viewBox="-40 -40 900 900" xmlns="http://www.w3.org/2000/svg">
<path
d="
M484 0l-42 137h-245l-47 -137h-147l237 664h161l234 -664h-151z
M319 515h-1l-85 -264h169z
" />
</svg>
<svg viewBox="-40 -40 900 900" xmlns="http://www.w3.org/2000/svg">
<path
d="
M484 0l-42 137h-245l-47 -137h-147l237 664h161l234 -664h-151z
M319,515L402,251L233,251L318,515L319,515z
" />
</svg>
<svg viewBox="-40 -40 900 900" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd"
d="
M484 0l-42 137h-245l-47 -137h-147l237 664h161l234 -664h-151z
M319,515L402,251L233,251L318,515L319,515z
" />
</svg>
Whether a given path is "filled" or "clipped" depends on the "winding" algorithm being used, which is determined by the SVG fill-rule property, which defaults to nonzero.
For the nonzero mode:
This rule determines the "insideness" of a point on the canvas by drawing a ray from that point to infinity in any direction and then examining the places where a segment of the shape crosses the ray. Starting with a count of zero, add one each time a path segment crosses the ray from left to right and subtract one each time a path segment crosses the ray from right to left. After counting the crossings, if the result is zero then the point is outside the path. Otherwise, it is inside. The following drawing illustrates the nonzero rule:
The nonzero default is why you'll often hear that rotational direction is important, because clockwise creates fills and counterclockwise creates clips. (This is how it works in GeoJSON as well.)
For the evenodd mode:
This rule determines the "insideness" of a point on the canvas by drawing a ray from that point to infinity in any direction and counting the number of path segments from the given shape that the ray crosses. If this number is odd, the point is inside; if even, the point is outside. The following drawing illustrates the evenodd rule:
The evenodd mode is a simpler to understand for basic shapes with holes, but not as flexible for clipping arbitrary chunks out that may not be completely isolated as islands.
Here's a great article called Understanding the SVG fill-rule Property that explains it further with code examples.

Defining viewport and viewbox in SVG to scale shapes with physical real world units

I am confused how to properly define viewport and viewbox in SVG file to convey shapes that have real world physical units.
I am mapping my AutoCAD design to a SVG file. The units in my AutoCAD file are defined in millimeters (mm). Image below shows my AutoCAD design. The orange box (16mm x 9mm) are my boundaries for visible part of the SVG file, thus anything outside the orange box will get cut off. My end application requires a PNG image that is a specific resolution, 1920x1080. (Notice how the aspect ratio is the same).
In my SVG file, all shapes (elements) are defined without units, however I know the values are in millimeters in the physical world. For example, below is an example of a circle. The radius of the circle is 0.474mm as set in the AutoCAD file.
<circle cx="1.22996130982" cy="2.27139057943" r="0.474" />
My question is, how do I properly define the viewport and viewbox in my SVG file? How do I properly define the viewport/viewbox such that the physical units in real world get scaled to fit in my desired image resolution?
I used the following method below to define my viewport/viewbox. However, this approach did not work. The resulting SVG image was a canvas of 1920x1080 however all my shapes were very tiny and it did NOT cut off the shapes desired outside the orange boundary box.
<svg width="1920px" height="1080px" viewbox="0 0 16mm 9mm">
<circle cx="1.22996130982" cy="2.27139057943" r="0.474" />
<!-- Other shapes in SVG here-->
</svg>

svg preserveAspectRatio="xMidYMid slice" is changing the svg viewbox size

In my app I'm create an SVG scene which include an image - the scene background, and some shapes (rect, circle) on it.
on the svg element im setting a view-box for working with logical unit and not with pixels for example.
so, on the svg element i'm setting the preserveAspectRatio attribute to be "xMidYMid slice", same on image - the background scene inside.
everything looks as expected, except the that now the position x=0, y=0 is not where it's supposed to be, the x=0, y=0 is according to where the scene was before it was "sliced", although the SVG element width and height is the same.
I need that the x=0,y=0 be where it should be, on the left corner of the scene.
Thanks for your help.
N, St.
If you don't want the origin (top left) of the SVG to move, then try:
preserveAspectRatio="xMinYMin slice"
Perhaps this was what you were after?

Resources