My first SVG
SVG stands for Scalable Vector Graphics. It's a pretty common type of image.
My first idea was to vectorize with Inkscape the file I created with Gimp:
Gimp -> PNG file -> Inkscape -> SVG file -> FreeCAD
The result was poor, because the vectorization process created a lot of path (above 2000, whereas I have only 140 objects).
I definitely needed a more precise process. The idea was to create the SVG from scratch:
1- precisely measuring the coordinates of all the objects (holes)
2- creating a SVG file from scratch with Inkscape
3- importing the file in FreeCAD
Fortunately, all the objects I need to cut boxes, circles and paths (shapes bazed on Bezier curves) and all are symmetrical around vertical and horizontal axis (top is symmetrical to bottom, left to right). So with Gimp, I measured precisely the coordinates of the centers of all objects. I ended up with a LibreOffice spreadsheet.
<svg height="100" width="100">
<circle cx="100" cy="100" r="100" style="fill:rgb(192,192,255);stroke:none;stroke-width:1" />
<rect x="0" y="0" width="40" height="40" style="fill:rgb(147,147,255);stroke:none;stroke-width:1" />
<rect x="16" y="16" width="35" height="35" style="fill:rgb(127,127,245);stroke:none;stroke-width:1" />
<rect x="32" y="32" width="27" height="27" style="fill:rgb(107,107,235);stroke:none;stroke-width:1" />
<rect x="48" y="48" width="17" height="17" style="fill:rgb(87,87,225);stroke:none;stroke-width:1" />
</svg>
The result is:
Full documentation available here: https://developer.mozilla.org/en-US/docs/Web/SVG
In my spreasheet, the columns were:
A: Object Id (unused)
B: Object Label (unused)
C: Object Type on sheet 1 & 2: rect, circle or path
D: Object Type on sheet 3: rect, circle or path
E: Object width in mm
F: Object height in mm
G: Object absolute x in mm
H: Object absolute y in mm
I: Object x relative to the casing (identical to G)
J: Object y relative to the casing (identical to H)
K: SVG code for the objects, relative to the casing
L: Object x relative to the silkscreen
M: Object y relative to the silkscreen
N: SVG code for the objects, relative to the silkscreen
In column K, I created a formula to generate all the paths:
="<" & $C4 &
IF($C4="rect",
" x=""" & ROUND(Params.$B$1*(L4-$E4/2),3) & """" &
" y=""" & ROUND(Params.$B$1*(M4-$F4/2),3) & """" &
" width=""" & ROUND(Params.$B$1*($E4),3) & """" &
" height=""" & ROUND(Params.$B$1*($F4),3),
IF($C4="circle",
" cx=""" & ROUND(Params.$B$1*(L4),3) & """" &
" cy=""" & ROUND(Params.$B$1*(M4),3) & """" &
" r=""" & ROUND(Params.$B$1*($F4/2),3),
IF($C4="path",
" d=""M" & ROUND(Params.$B$1*(L4-$E4/2),3) & "," & ROUND(Params.$B$1*(M4-$F4/2+Params.$B$2),3) &
" C" & ROUND(Params.$B$1*(L4-$E4/2),3) & "," & ROUND(Params.$B$1*(M4-$F4/2),3) &
" " & ROUND(Params.$B$1*(L4+$E4/2),3) & "," & ROUND(Params.$B$1*(M4-$F4/2),3) &
" " & ROUND(Params.$B$1*(L4+$E4/2),3) & "," & ROUND(Params.$B$1*(M4-$F4/2+Params.$B$2),3) &
" L" & ROUND(Params.$B$1*(L4+$E4/2),3) & "," & ROUND(Params.$B$1*(M4+$F4/2-Params.$B$2),3) &
" C" & ROUND(Params.$B$1*(L4+$E4/2),3) & "," & ROUND(Params.$B$1*(M4+$F4/2),3) &
" " & ROUND(Params.$B$1*(L4-$E4/2),3) & "," & ROUND(Params.$B$1*(M4+$F4/2),3) &
" " & ROUND(Params.$B$1*(L4-$E4/2),3) & "," & ROUND(Params.$B$1*(M4+$F4/2-Params.$B$2),3) &
" L" & ROUND(Params.$B$1*(L4-$E4/2),3) & "," & ROUND(Params.$B$1*(M4-$F4/2+Params.$B$2),3), "" )))
& """ " &Params.$B$3&" />"
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="1012.756" height="411.142" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ev="http://www.w3.org/2001/xml-events"
version="1.1"
baseProfile="full">
<rect x="50.998" y="358.762"
width="25.296"
height="12.311"
style="fill:#000000;fill-opacity:1;
fill-rule:evenodd;stroke:none;
stroke-width:1px;stroke-linecap:butt;
stroke-linejoin:miter;stroke-opacity:1" />
<circle cx="63.646" cy="347.264" r="3.484"
style="fill:#000000;fill-opacity:1;
fill-rule:evenodd;stroke:none;
stroke-width:1px;stroke-linecap:butt;
stroke-linejoin:miter;stroke-opacity:1" />
...
<path d="M115.213,206.616
C115.213,201.97 123.343,201.97 123.343,206.616
L123.343,286.754
C123.343,291.4 115.213,291.4 115.213,286.754
L115.213,206.616"
style="fill:#000000;fill-opacity:1;
fill-rule:evenodd;stroke:none;
stroke-width:1px;stroke-linecap:butt;
stroke-linejoin:miter;stroke-opacity:1" />
...
Nice! The fact I had to repeat the style tag on every line is due to a bug when importing in FreeCAD.
The overall result is the following:
A closer look:
In FreeCAD, I could create the casing:
Why?
For my project (recreation of an MPG-80), I need to cut a sheet of metal. Because the cut has to be precise, I choosed to use a laser cutting service. To do so, I need to produce a file (SVG) which represents the path of the laser beam.My first idea was to vectorize with Inkscape the file I created with Gimp:
Gimp -> PNG file -> Inkscape -> SVG file -> FreeCAD
The result was poor, because the vectorization process created a lot of path (above 2000, whereas I have only 140 objects).
I definitely needed a more precise process. The idea was to create the SVG from scratch:
1- precisely measuring the coordinates of all the objects (holes)
2- creating a SVG file from scratch with Inkscape
3- importing the file in FreeCAD
Fortunately, all the objects I need to cut boxes, circles and paths (shapes bazed on Bezier curves) and all are symmetrical around vertical and horizontal axis (top is symmetrical to bottom, left to right). So with Gimp, I measured precisely the coordinates of the centers of all objects. I ended up with a LibreOffice spreadsheet.
First try...
My attempt to created the SVG with Inkscape went nowehere. Happily, I quick search on Google shows writing a SVG file is rather simple. Here is my first SVG:<svg height="100" width="100">
<circle cx="100" cy="100" r="100" style="fill:rgb(192,192,255);stroke:none;stroke-width:1" />
<rect x="0" y="0" width="40" height="40" style="fill:rgb(147,147,255);stroke:none;stroke-width:1" />
<rect x="16" y="16" width="35" height="35" style="fill:rgb(127,127,245);stroke:none;stroke-width:1" />
<rect x="32" y="32" width="27" height="27" style="fill:rgb(107,107,235);stroke:none;stroke-width:1" />
<rect x="48" y="48" width="17" height="17" style="fill:rgb(87,87,225);stroke:none;stroke-width:1" />
</svg>
The result is:
Full documentation available here: https://developer.mozilla.org/en-US/docs/Web/SVG
The spreasheet
For my project, I need to cut 3 sheets: the casing (metal, 1.3 mm), a plastic sheet (lexan) containg the silkscreen, and another metal sheet holding the PCB. The need for 2 metal sheets is leaded to the fact by buttons are enclosed between the two sheets. The coordinate set is differents for each sheet.In my spreasheet, the columns were:
A: Object Id (unused)
B: Object Label (unused)
C: Object Type on sheet 1 & 2: rect, circle or path
D: Object Type on sheet 3: rect, circle or path
E: Object width in mm
F: Object height in mm
G: Object absolute x in mm
H: Object absolute y in mm
I: Object x relative to the casing (identical to G)
J: Object y relative to the casing (identical to H)
K: SVG code for the objects, relative to the casing
L: Object x relative to the silkscreen
M: Object y relative to the silkscreen
N: SVG code for the objects, relative to the silkscreen
In column K, I created a formula to generate all the paths:
="<" & $C4 &
IF($C4="rect",
" x=""" & ROUND(Params.$B$1*(L4-$E4/2),3) & """" &
" y=""" & ROUND(Params.$B$1*(M4-$F4/2),3) & """" &
" width=""" & ROUND(Params.$B$1*($E4),3) & """" &
" height=""" & ROUND(Params.$B$1*($F4),3),
IF($C4="circle",
" cx=""" & ROUND(Params.$B$1*(L4),3) & """" &
" cy=""" & ROUND(Params.$B$1*(M4),3) & """" &
" r=""" & ROUND(Params.$B$1*($F4/2),3),
IF($C4="path",
" d=""M" & ROUND(Params.$B$1*(L4-$E4/2),3) & "," & ROUND(Params.$B$1*(M4-$F4/2+Params.$B$2),3) &
" C" & ROUND(Params.$B$1*(L4-$E4/2),3) & "," & ROUND(Params.$B$1*(M4-$F4/2),3) &
" " & ROUND(Params.$B$1*(L4+$E4/2),3) & "," & ROUND(Params.$B$1*(M4-$F4/2),3) &
" " & ROUND(Params.$B$1*(L4+$E4/2),3) & "," & ROUND(Params.$B$1*(M4-$F4/2+Params.$B$2),3) &
" L" & ROUND(Params.$B$1*(L4+$E4/2),3) & "," & ROUND(Params.$B$1*(M4+$F4/2-Params.$B$2),3) &
" C" & ROUND(Params.$B$1*(L4+$E4/2),3) & "," & ROUND(Params.$B$1*(M4+$F4/2),3) &
" " & ROUND(Params.$B$1*(L4-$E4/2),3) & "," & ROUND(Params.$B$1*(M4+$F4/2),3) &
" " & ROUND(Params.$B$1*(L4-$E4/2),3) & "," & ROUND(Params.$B$1*(M4+$F4/2-Params.$B$2),3) &
" L" & ROUND(Params.$B$1*(L4-$E4/2),3) & "," & ROUND(Params.$B$1*(M4-$F4/2+Params.$B$2),3), "" )))
& """ " &Params.$B$3&" />"
Where Params.$B$1 contains a scaling ratio (90*177/(25.4*270)=2.3228346457) and Params.$B$2 contains a rounding factor for the path objects.
This gave the following result (abstract):<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="1012.756" height="411.142" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ev="http://www.w3.org/2001/xml-events"
version="1.1"
baseProfile="full">
<rect x="50.998" y="358.762"
width="25.296"
height="12.311"
style="fill:#000000;fill-opacity:1;
fill-rule:evenodd;stroke:none;
stroke-width:1px;stroke-linecap:butt;
stroke-linejoin:miter;stroke-opacity:1" />
<circle cx="63.646" cy="347.264" r="3.484"
style="fill:#000000;fill-opacity:1;
fill-rule:evenodd;stroke:none;
stroke-width:1px;stroke-linecap:butt;
stroke-linejoin:miter;stroke-opacity:1" />
...
<path d="M115.213,206.616
C115.213,201.97 123.343,201.97 123.343,206.616
L123.343,286.754
C123.343,291.4 115.213,291.4 115.213,286.754
L115.213,206.616"
style="fill:#000000;fill-opacity:1;
fill-rule:evenodd;stroke:none;
stroke-width:1px;stroke-linecap:butt;
stroke-linejoin:miter;stroke-opacity:1" />
...
Nice! The fact I had to repeat the style tag on every line is due to a bug when importing in FreeCAD.
The overall result is the following:
A closer look:
In FreeCAD, I could create the casing:
Comments