I just toured around looking for fractals, and when I found something that had a scaling geometry, I would ask the folks what was going on - why they had made it that way.
— Ron Eglash

Biplane

Scalable Vector Graphics

SVG is 'just another parametric way to describe 2D shapes', but it’s quite elegant in it’s elementary simplicity. It has always — i.e., since I started working with OpenSCAD — struck me as natural that there should be an SVG implementation in OpenSCAD, and this library provides just that.

If you’ve ever looked at some clipart or image on the old interwebs, and thought 'That would be nice, embossed on my 3D-printed such-and-such design…​', here’s some good news for you: As long as your image is an SVG (and there are very many in the public domain), the GHOUL will take it’s 'd' path property, a path-string, and turn it into a polygon for you.

Note The closing sentence of the preceding paragraph contains the main caveat you should keep in mind when using this library. The SVG specification contains a massive number of elements with a huge number of properties. Have a look here if you wish to be depressed, but because OpenSCAD isn’t Inkscape, or a web-client, this library only implements what’s of real interest to us as OpenSCAD users: the 'd' property which defines a path to be drawn, to be made into a polygon, to have another shape extruded along, as a baseline for text, or…​ You know what they say about the sky.[1]

Let’s have a look at what the specification says:

"Paths represent the geometry of the outline of an object, defined in terms of moveto (set a new current point), lineto (draw a straight line), curveto (draw a curve using a cubic Bézier), arc (elliptical or circular arc) and closepath (close the current shape by connecting to the last moveto) commands. Compound paths (i.e., a path with multiple subpaths) are possible to allow effects such as 'donut holes' in objects."

If that doesn’t remind you of the OpenSCAD manual entry for polygon(), well, I guess you might not have read the entry…​

Smiley

Grab an SVG image, open it in your text editor, copy the d property of the path element, paste it in The GHOUL’s SVG() call, and there you are. You like the fontawesome icons? Same thing goes. With a little effort you can convert any 'ttf' font into SVG glyphs, offline or online. Then you can grab any icon or character from the font and do what you want. Scale it, skew it, stretch, mirror, extrude, change and adopt it to exactly what you need. Grab a sub-path, combine letters, paths, shapes…​ You get the drift.

TheAlmightyDollar

The GHOUL’s SVG library will correctly parse and process successive smooth cubic and quadratic Bézier curve commands in the SVG path — I’m kind of proud of that — whether they are relative or absolute. Arcs are a breeze. I haven’t stumbled on a valid path that this library hiccups over, but if you do, I’d very much like to know. I’ll leave you to it, you’ll be a while ;-)

Since I mentioned images and fonts, you may know about the different coordinate systems used by the SVG specification for these two different applications:

Warning Unlike standard graphics in SVG, where the initial coordinate system has the y-axis pointing downward, the design grid for SVG fonts has the y-axis pointing upward for consistency with accepted industry practice for many popular font formats.

What? You mean standard SVG graphics are working with screen coordinates with the origin in the top-left corner? Yep. That’s what they mean. But here’s the really great news: not always. When describing fonts, the coordinate system has the origin in the bottom-left corner, with the X-axis and Y-axis where you normally find them. And not all images use the screen coordinates, some use the regular coordinate system. Right? SM#H =/

The GHOUL SVG library takes all that in it’s stride: through the SVG_Coords parameter, the different coordinate systems used by SVG images and fonts are all parsed and displayed correctly. More about that later.

TTF to SVG conversion

If you didn’t read this already, here’s how to convert TTF fonts to SVG, if you run Gnu-Linux. If you don’t, I’m no help to you, but there’s plenty online, just Google that stuff.

Make sure you have FontForge installed, then simply save the next few lines of code in a Perl script, let’s call it ttf2svg.pl

#! /usr/bin/env fontforge

Open($1)
Generate($1:t:r + ".svg")

For simplicity have the script and the font-file in the same (working) directory and call it like:

ttf2svg.pl MyLovelyFont.ttf

now you can open `MyLovelyFont.svg with a text editor — I like the Geany IDE — and enjoy…​

An intro to the SVG Path

Before we dive into the library proper, let’s have a quick basic run-through of the SVG path element, the d property, and some of the commands that make up a path. An SVG image or font description is a text file, just like the OpenSCAD .scad files, but SVG uses the .xml standard which uses tags much like a .html file does. When you open an SVG .xml file, you will normally find one (in image files) or several (in font files) tags like this:

<path d="M 0 0 L 100 0 L 100 100 l -100 0 z"
        fill="red" stroke="blue" stroke-width="5" />

SimpleSquare

What we’re interested in is the path data, the d="M 0 0 L…​ assignment; the d property of the path element. In an image, this should be a single string, containing all the subpaths and commands. It’s important to remember that the subpaths influence each other with difference()-like operations when they overlap or fall within each other.

PlayPauseStop

The path in the above code snippet describes a simple square, drawn in blue lines with red fill. The SVG specification for paths includes properties like 'stroke' and 'fill' for colors and 'stroke-width' &c. We are only generating polygons and stroke and all the other attributes are not implemented in this library. Think of the implementation here as SVG with stroke 'off' and fill always 'on'. If that makes you sad, ditch OpenSCAD and get Inkscape.

The call for that same path, using this library, would look like the first one in the code snippet below (note that the string is copied literally), the others are variations you may come across, they all work; SVG() is smart when it comes to interpreting the path-string, but I think the first one is much more easy to read, and what do we save by omitting spaces…​

SVG("M 0 0 L 100 0 L 100 100 l -100 0 z");

SVG("M0 0L100 0L100 100l-100 0z");
SVG("M 0,0 L 100,0 L 100,100 l -100,0 z");

Let’s have a quick look at these commands:

M

moveto (absolute) [0,0] Although the SVG specification states that, without an initial moveto command, the polygon is drawn beginning at [0,0], it behooves a good programmer to explicitly state this. The library will enforce this by prepending this command to strings where it is missing.

L

lineto (absolute) [100,0] &c. Draw a line to this coordinate.

l

lineto (relative) [-100,0] Draw a line to this relative coordinate (from the current point).

z

closepath This command is in the SVG specification as a line may be drawn and not a polygon. At this moment this is not implemented by this library, as a closed path is implicit in the OpenSCAD polygon() definition, and The GHOUL complies with that.

Ampersand

There are several more commands for horizontal (H/h) and vertical (V/v) straight lines, arcs (A/a), circular and elliptical — yes, I know…​ — and cubic (C/c) and quadratic (Q/q) Bézier curves. The curves can be 'smooth', in which case they mirror the previous curve’s last control point in the current point (the end-point generated by the previous command), they are the smooth cubic (S/s) and the smooth quadratic (T/t) Bézier curves. Here’s a primer on Bézier curves if you’re not familiar with them, they’re simply marvellous.

All commands have an uppercase and a lowercase variant, indicating that they refer to absolute or relative coordinates.

There is lots of information available online, even though much is discussed in the commands below, I suggest you read one of these pages from W3C or Mozilla or this really neat illustarated guide on css-tricks before you start writing your own paths. Brew a good jug of strong Java before you do, they’re a bit of a read, but very useful…​ I’m going to repeat that for the 'scan and go' type of visitor here:

Tip WOULD-BE PATH WRITERS, READ A GUIDE FROM EITHER: W3C or Mozilla or this cool one at css-tricks.

SVG() also accepts a 'path-array' instead of a 'path-string'. This makes it much easier to integrate variables and parameters into the path. The Thread() module, through ThreadData() makes use of that. An example of this is:

    SVG([
        "M",_Height/2,_Height,
        "A",_Height,_Height,0,0,1,_Height*_MaD,-_Pitch/2,
        "L",_Height*_MiD,-_Pitch/2,
            _Height*_MiD, _Pitch/2,
            _Height*_MaD+_ClrR, _Pitch/2-_ClrA,
        "A",_Height*_MaRr,_Height*_MaRr,0,0,1,_Height-_TaperRm,_Pitch/2,
        "L",_Height/2,_Pitch/2
    ])

As you can see from the example, the array consists of the commands as strings, followed by their parameters as normal scalar values. Jolly useful.

Using The GHOUL’s SVG library

Let’s have a look at the one and only call you’ll ever need to make to use SVG graphics in OpenSCAD:

SVGoutput

SVG()

SVG(PathString,SVG_Coords=false,Size=[1,1]

  • Pathstring, string, any valid SVG path-string,OR a 'path-array' as discussed above.

  • SVG_Coords, Boolean, if true, the Pathstring will be interpreted as an image path, with the positive Y-axis pointing down. If false, the Pathstring will be interpreted as a font path, with the positive Y-axis pointing up.

  • Size, vector, 2D scaling vector with x- and y-scaling factors.

SVG() takes a valid SVG path element d property, the PathString, parses the string, generates the points along the paths, and returns the points and paths in the format required by the OpenSCAD polygon() call. If $Verbose is set to true, it will echo the point, path and command count in the console, as seen in the image here. (If your eyes are like mine, Right-Click  View Image)

Note If you’re wondering how to get such pretty console output; since 2021.1, the console no longer renders html font tags, so the beautiful colours and bold print you see here in the images is a thing of the past. Apparently that’s what they call 'improvement'…​ SM#H :-[

Like many other routines in The GHOUL, SVG.scad contains both an SVG() module and a function. The function returns a pair of lists [PolyPoints,PolyPaths], PolyPoints contains all the polygon points in a single list, and PolyPaths contains — nomen est omen — list(s) of the points of the path(s) for the OpenSCAD polygon() call. The module simply takes the result from the function and generates the polygon(s) for you, no hassle. The main reason for the separate function is that it allows you to post-process the resulting points-list.

You can, for example, make a quick path to use for a rotate_extrude() call:

rotate_extrude(angle=180,convexity=10)
SVG("M 0 0 L 4 0 C 2 5 5 2 5 6 Q 5 8 2 8 h -2 v -0.5 h 2 Q 4.5 7.5 4.5 6 C 4.5 2.5 1.5 5 3.5 0 ",true);

RotateExtrudeExample

How nice is that? Because SVG is so blissfully simple, and makes great use of smooth cubic and quadratic Bézier curves, it allows you to quickly create smooth paths like this in a very short time, off the top of your head, no math, no notes, no prep, no sketches. Just close your eyes, see the shape, write the path. I think, as a kind of 'top layer' it makes the GHOUL’s Bézier curve library much more accessible and easier to use.

There. That’s it, SVG() is the only call you’ll ever need to make to use SVG paths in OpenSCAD. And, there’s more—​but we can’t do this all day…​ ;-) SVG() is so easy to use and versatile, and with the ability to describe complex shapes in a single string, doesn’t it seem natural to have indexable or searchable shape collections, defined in arrays, that can be easily called like:

SVG_Shape(FavIcons,"YinYang");

SVG_Shape() does exactly that, simple, convenient. Create collections of shapes you regularly extrude, emblems you emboss on objects &c.

YinYang

SVG_Shape()

SVG_Shape(Collection,Name,Size=[1,1],Center=false,Home=false)

  • Collection, array variable name, i.e., a collection name.

  • Shape, string, SVG-shape record name, i.e., it’s identifier.

  • Size, tuple, scaling factors for the shape.

  • Center, Boolean, center shape on origin.

  • Home, Boolean, place the shape at 'home' in the first quadrant.

It’s easy to have all your SVG shapes in one collection, or define different classes in separate collections. /TheGHOUL/Lib/SVG/Shapes/ directory contains a collection called FavIcons.scad, mostly as an example, you’ll be making your own, and you can easily add a directory to The GHOUL to keep personal collections &c. separate from the rest of The GHOUL.

Collections of shapes are arrays of records like:

    CollectionName=[
        ["ShapeName","SVG_Path",SVG_Coords,"ID", ... ],
        [...]
    ];

SVG_Shape() expects each shape record to contain at least these elements:

  • Name, string, name of the shape or icon

  • SVG_Path, string, a valid SVG path-string

  • SVG_Coords, Boolean, flag, use SVG coordinates if 'true'

You can give the record as many additional elements as you like…​

SVG_Shape() searches the array for the record containing the identifier, then takes the pathstring from that record and generates the polygon. It uses the SVG_Coords Boolean to switch to SVG coordinates, i.e., 'upside-down', if it is true. Like many of The GHOUL’s routines, SVG_Shape.scad also contains a function SVG_Shape(), which returns a 'polygon-tuple' like [points,paths].

When SVG_Coords is true, the shape is generated in the fourth quadrant. The Home and Center Booleans are available to move the shape, either in the first quadrant and touching the X-axis and Y-axis, or centered on the origin. The Shape’s size is published to the console if $Verbose is true (See Config.scad).

CapitalA

SVG_Glyph()

SVG_Glyph(Font,Character,Size=[1,1])

  • Font, string, font identifier.

  • Character, string or unicode, glyph identifier.

  • Size, tuple, scaling factors.

SVG_Glyph() uses font definition files that are stored in TheGHOUL/Lib/SVG/Fonts/ and which are loaded by Lib_SVGFonts.scad. The font definition file contains a single array, the name of which is the font-identifier Font. If the required character is one of the 'printable characters' (Ascii 33-126), simply use the character itself as Character, i.e. the string "A" will generate a capital letter 'A' &c. For any of the characters that are not in that Ascii range, the four-digit hexadecimal UniCode is used as the identifier, e.g. "215E" would yield '⅞'.

SevenEights

SVG_Glyph(OpenSans_SemiBold,"215E")

The next development for the SVG library will be string support with proper kerning. The font-definition files already contain the kerning tables, but right now I’m a little preoccupied with developing routines to bevel any complex polygon(), it’s a bit of a "Squirrel!" moment.

Warning SVG_Glyph() is not yet quite as polished as I’d like, expect it to change it’s behaviour some time in the future, also see 'TODO' comments in SVG_Glyph.scad.

SVG path commands

For those wanting to write their own paths, this is an intro to the commands and their syntax. Also check out the links to online information above.

Warning This SVG library is more than reasonable with regards to tolerating garbage in the path-string that it’s being fed, but it draws the line at /newline and /return characters. It will throw a wobbly, and the proverbial matter will hit the rotating air-mover. I can live with that, and you will have to as well, they have no place in an SVG path to begin with, but they are often found inside pathstrings in xml definitions of SVG images and fonts, so:

Be nice. Write (or copy and edit) clean, well parsed path-strings without newlines or returns.

It’s not too much to ask: remove /newline and /return characters, most other garbage can stay.

Convention

In discussions of SVG commands below, I follow this naming convention with regards to SVG parameters:

Px,Py

Current point coordinates. Not strictly parameters but they feature in the definitions. The 'current point' in SVG terms, is the last point generated by the previous command, and thus the point from where the current command starts to 'draw'.

Nx,Ny

Next point coordinates. The 'next point' is the point where the current command will 'draw' to, it is the current command’s curve or line endpoint, and thus the next command’s 'current point'.

Cx,Cy

Quadratic Bézier curve controlpoint coordinates. A QBC only has one controlpoint.

C1x,C1y,C2x,C2y

Cubic Bézier curve controlpoint coordinates. A CBC has two controlpoints.

XRot

X-axis rotation. The SVG A/a arc command allows you to rotate an ellipse before fitting it onto the 'current point to next point' segment. There are four ways an ellipse arc can be drawn between two points (provided the distance between them is not too large). More about this at the arc command discussion.

Rx,Ry

Arc radii (major/minor semi-axes). When the radii are identical the arc will be a circle segment of course.

LAF

Large-Arc-Flag. The LAF determines whether the large or small arc of an ellipse or circle will be drawn between the current point and next point.

SF

Sweep-Flag. The SF determines the direction of the 'sweep' of the drawn segment, either counter-clockwise or clockwise, i.e., to the right of the 'current point to next point' line-segment, looking forward, or to the left.

(…​)+

A command may accept multiple parameter sets. This is indicated by '+' after the set in brackets. The '+' and brackets are not part of the syntax!

Everything is (potentially) relative…​

Any of the SVG commands can take parameter sets that contain either absolute coordinates, or relative coordinates. Relative command parameters, in SVG terms, are always relative to the the 'current point', which is the last point generated by the previous command, or, where the last command 'stopped drawing'.

LargeArcSweepFlags

A/a

A/a (Rx Ry XRot LAF SF Nx Ny)+

  • Rx,Ry,Nx,Ny, radii, i.e., major and minor semi-axes and next point coordinates, see convention.

  • XRot, angle, rotation of the ellipse. Rotation, in the SVG specification as well as The GHOUL convention, is always positive from the positive X-axis towards the positive Y-axis. If SVG coordinates are in force (Y-axis pointing 'down'), positive rotation results in clockwise movement 'on the canvas'.

  • LAF, SF, Large-Arc-Flag and Sweep-Flag, 0/1, looking from [Px,Py], the current point, to [Nx,Ny], the next point, the Sweep Flag determines arc direction: SF=0 yields a counter-clockwise arc, and SF=1 yields a clockwise arc. The Large Arc Flag determines which of the fitting arcs is drawn, LAF=0 yields the smaller and LAF=1 yields the larger arc. See the accompanying image.

Multiple parameter sets can be given to the same A/a command, and are processed successively according to the SVG specifications. Don’t lose track of the current point when writing relative arc commands with multiple parameter sets…​

//               Large Arc Flag --v v-- Sweep Flag
color(BLU)SVG("M 0 0 A 150 100 20 0 0 100 100z",true); // small ccw
color(CYN)SVG("M 0 0 A 150 100 20 1 0 100 100z",true); // large ccw
color(RED)SVG("M 0 0 A 150 100 20 0 1 100 100z",true); // small cw
color(YLW)SVG("M 0 0 A 150 100 20 1 1 100 100z",true); // large cw

SVG_Cubic

C/c

C/c (C1x,C1y,C2x,C2y,Nx,Ny)+

  • C1x,C1y,C2x,C2y, control-point coordinates, see convention.

  • Nx,Ny, next point coordinates, see convention.

C/c accepts multiple parameter sets, but it is usually followed by a smooth curve command S/s or T/t, as that makes much more sense. Nonetheless, multiple sets are parsed and processed correctly according to the SVG specifications.

SVG("M 0 0 C 50 0 50 100 100 100 v -100z");

The cubic Bézier curve is fully described by four points; a beginpoint, two control points and an endpoint. In SVG terms, the 'current point' is the beginpoint and the 'next point' is the endpoint, the controlpoints determine the direction and shape of the curve at the endpoints.

Tip The cubic Bézier curve gives you total control over the direction of the curve at the endpoints. If you want to have several curved sections in succession, start with a cubic curve, then continue with smooth cubics S/s or smooth quadratics T/t. The smooth curves give you full control over the direction of the curve at the endpoint as well.
Note If you’re completely new to Bézier curves, please have a look at the GHOUL’s Bézier curve library first.

SVG_Horizontal

H/h

H/h (Coord/Dist)+

  • Coord/Dist, H/h only takes one parameter, which has two different meanings, Coordinate or Distance, depending on whether the command is absolute H or relative h. In an absolute call it draws a line to the point with X=Coordinate and Y=Py. In a relative call it draws a line to the point with X=Coordinate+Px and Y=Py.

It is possible to give H/h multiple X-coordinates or distances, but since it’s a 1D command, that doesn’t seem to make a lot of sense. Either way, the library will deal with them correctly, according to the SVG specifications.

The code snippet below contains both the absolute and the relative call that would result in the accompanying image.

SVG("M 20 0 H 100 Q 60 100 20 0z") // absolute
SVG("M 20 0 h 80 Q 60 100 20 0z")  // relative

SVG_Line

L/l

L/l (Nx,Ny)+

Multiple coordinates can be given to quickly draw a complex shape.

The code snippet below contains both the absolute and the relative call that would result in the accompanying image.

SVG("M 0 0 H 100 L 0 100z")
SVG("M 0 0 H 100 l -100 100z")

SVG_Move

M/m

M/m (Nx,Ny)+

The SVG M/m move command is a double edged sword; when given more than one set of coordinates, the first coordinates are interpreted as a 'moveto' command and all subsequent coordinates are interpreted as a 'lineto' L/l command. The code snippet below contains the call that would result in the accompanying image.

SVG("M 0 0 100 20 50 50 20 100 M 15 15 65 25 40 40 25 65z");

In an absolute call, the current path is terminated with the current point as it’s endpoint, and a new path is started at the next point coordinates. In a relative call, the current path is terminated with the current point as it’s endpoint, and a new path is started at the current point plus the next point coordinates.

SVG_Quadratic

Q/q

Q/q (Cx,Cy,Nx,Ny)+

The SVG Q/q command yields a quadratic Bézier curve, it accepts multiple parameter sets, but it is usually followed by a smooth curve command S/s or T/t, as that makes much more sense. Nonetheless, multiple sets are parsed and processed correctly according to the SVG specifications.

The code snippet below contains the call that would result in the accompanying image.

SVG("M 0 0 H 100 L 40 60 Q 0 100 0 50 V 0z");
Tip CubicQuadraticRadiused The quadratic Bézier curve is very well suited for curved corners. Finish the straight sections either side of the corner at equal distances, put the quadratic curve’s controlpoint on the intersection of the lines and Bob’s your uncle: a perfectly smooth rounded corner like the blue curve in the image.
The corner will not have a circular shape, i.e., not a constant radius. To closely mimic a circular shape, use a cubic curve, and put the control points at 0.552 of the distance between the line ends and the corner point like the green curve in the image. Even putting the controlpoints simply halfway will give a reasonably circular shape to the corner. Also see Bézier circle approximation.
Note If you’re completely new to Bézier curves, please have a look at the GHOUL’s Bézier curve library first.

SmoothCubic

S/s

S/s (C2x,C2y,Nx,Ny)+

  • C2x,C2y, second control-point coordinates, see convention.

  • Nx,Ny, next point coordinates, see convention.

The SVG S/s command yields a cubic Bézier curve, but it only takes one controlpoint. That should alarm you a little, if not; please have a look at the GHOUL’s Bézier curve library first. The first controlpoint is a reflection of the previous curve’s last controlpoint in the current point. Even though there’s a failsafe built into the specifications, a smooth Bézier curve command only makes sense after another Bézier curve command. If the previous command isn’t a curve, there’s no controlpoint to reflect after all…​ It accepts multiple parameter sets, all of which take only one (the second) controlpoint, and all of which will have smooth transitions thanks to their reflected first controlpoints.

The code snippet below contains the call that would result in the accompanying image.

SVG("M 0 0 H 100 Q 75 75 50 50 S 0 100 0 50 z")

SmoothQuadratic

T/t

T/t (Nx,Ny)+

The SVG T/t command yields a quadratic Bézier curve, but it takes no controlpoint. As above, that should alarm you a little, if not; please have a look at the GHOUL’s Bézier curve library first. The controlpoint is a reflection of the previous curve’s last controlpoint in the current point. Even though there’s a failsafe built into the specifications, a smooth Bézier curve command only makes sense after another Bézier curve command. If the previous command isn’t a curve, there’s no controlpoint to reflect after all…​ It accepts multiple parameter sets, all of which take only the next point, and all of which will have smooth transitions thanks to their reflected controlpoints.

The code snippet below contains the call that would result in the accompanying image.

SVG("M 0 0 H 100 Q 100 80 80 50 T 0 100z");

SVG_Vertical

V/v

V/v (Coord/Dist)+

  • Coord/Dist, V/v only takes one parameter, which has two different meanings, Coordinate or Distance, depending on whether the command is absolute V or relative v. In an absolute call it draws a line to the point with X=Px and Y=Coordinate. In a relative call it draws a line to the point with X=Px and Y=Coordinate+Py.

It is possible to give V/v multiple Y-coordinates or distances, but since it’s a 1D command, that doesn’t seem to make a lot of sense. Either way, the library will deal with them correctly, according to the SVG specifications.

The code snippet below contains both the absolute and the relative call that would result in the accompanying image.

SVG("M 0 20 V 100 Q 100 60 0 20z") // absolute
SVG("M 0 20 v 80 Q 100 60 0 20z")  // relative

Behind the scenes

Important The functions discussed in this section are what makes this SVG library tick 'behind the scenes', they are NOT user routines, you’ll never call them directly.

SVG path-strings are a chain of commands, each executed after the other, each starting off where the previous command left off. The GHOUL’s SVG library works just like that. After a command has generated it’s points, it calls the next command — via SVG_NextCommand() — and so on. The commands all share the same set of parameters, they are passed from command to command as the path is 'drawn' and points are added. To avoid repetition, only A/a is discussed here, just because it’s at the top of the alphabetical list…​

Arc

SVG_…​() functions

SVG_A(PathCommands,CC,Paths,LastCommand,Calls=1,PointsOnly=false)

  • PathCommands, array, all SVG subpaths and commands that SVG() is processing. This is a 3D array, in this format: [svg shape[subpaths[command parameters]]]. SVG() processes the paths and commands like a chain of function calls; each command calls the next until the last returns it’s points and the whole chain cascades back to return the final result.

  • CC, tuple, a 3-tuple containing the indices of the current path, command and parameter, it points to 'where we are on the path at this moment'.

  • Paths, array, the vertices of all subpaths and commands processed so far. The last vertex of this path is also used as the 'current point' for successive calls.

  • LastCommand, tuple, the endpoint and last curve controlpoint of the previous command. It’s a convenient way to pass the current point to the next command, and the last controlpoint of previous curve commands, needed by 'smooth' Bézier curve calls to calculate their own (first) mirrored controlpoint.

  • Calls, scalar, counter of commands processed so far. This is only to inform the user at the end of the process, it has no function in the routines.

  • PointsOnly, Boolean, if true, the function will not hand control to the next command, but return an array containing only the points it has generated.

After a command has generated it’s points or line segment, it advances the parameter index by the length of it’s own parameter sets. The parameter index now points at the first parameter of the next set (if there is another set in this command) or it points past the end of the command (the index is greater than len(Command). SVGNextCommand() uses this information to decide whether to call the next command, or the same command with the next parameter set.

SlideShow

SVGNextCommand()

SVGNextCommand(PathCommands,CC,Paths,Points,LastCommand,Calls)

  • Points, array, points generated by the previous command

  • For the other parameter descriptions see SVG_A above.

SVGNextCommand() has three main functions:

  1. Add the Points generated by the previous command to Paths.

  2. Call the next command in the path:

    1. If the next command is a 'moveto' M/m command, start a new subpath first.

    2. Call the next command with the updated CC and Paths parameters and incremented Calls parameter.

  3. Return Paths and Calls when the shape is complete.

SVGNextCommand() is the nerve-center, it sends the path-string to the successive commands, processes their output, keeps track of the current point and last controlpoint, counts the command executions for bragging rights, and finally returns the finished polygon points and paths to SVG().

Cog

SVGParsePath()

SVGParsePath(PathString)

  • Pathstring, string, any valid SVG path-string.

SVGParsePath() is used by SVG() to parse the SVG path-string into an array so we can address the individual commands and parameters.

It takes the initial path-string, uses SVGMovePositions() to find the 'moveto' commands and cuts the path-string into subpaths at their locations. Then it separates the commands in each subpath using SVGPathCommandPositions() and parses them and their parameters using SVGParameterPositions().

The image has nothing to do with SVGParsePath() per sé, but I got so exited and made too many, I had to put it somewhere…​

Note I’m not discussing those last few functions here; there’s no sense, and the curious can check the .scad files, they’re commented profusely, remember, this is The GHOUL.

Future plans and notes

I intend to write a function for chamfers, as well as one for circular fillets, probably soon, but not today; today I’m tired. Coffee. Coffee is what I do for the rest of today…​

CoffeeToday

That, there, in the image, is Wobble() working away. It’s a bonus function, combined with Tumble() in Tumble.scad. Have a look. It does exactly what it says, it makes an object 'wobble', I’ll write the documentation soon, not today, today, you know, coffee…​

This image, and all others on this page, is included in The GHOUL in the Demofiles directory in SVG_Images.scad You’ll see I cheated a little; by tilting the image 'North' a bit, the wobble effect gets more 'depth'.

TheGHOUL/DemoFiles/SVG_Images.scad is full of SVG path-strings you can have fun with. Go on, you know you want to…​ The images are all on single, commented lines, like in the code snippet below so just un-comment the line of the image you want to see.

//Eye
//translate([-300,300])linear_extrude(30,twist=5)SVG("M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288...

1. It’s the limit. See, you already knew that.