Context Free Art

Path declaration

From Context Free Art

Jump to: navigation, search

A path declaration creates a new primitive shape. The declaration contains a number of moving and drawing operations that define a path (or several paths). These paths can be filled or stroked to actually draw the new primitive shape.

path box {
MOVETO( 0.5, 0.5)
LINETO(-0.5, 0.5)
LINETO(-0.5, -0.5)
LINETO( 0.5, -0.5)
CLOSEPOLY() // go back to (0.5, 0.5) and close the path
STROKE()[] // draw a line on the path using the default line width (10%)
}

Like shapes, paths can have parameters:

path flower(number petals, number filled) {
MOVETO(cos(-180/petals), sin(-180/petals))
loop petals [r (360/petals)]
ARCTO(cos(180/petals), sin(180/petals),
0.4, 0.4 + 0.2 * (petals - 5), 90)
CLOSEPOLY(CF::Align)
if (filled) FILL[a -0.5]
MOVETO(0.65, 0)
ARCTO(-0.65, 0, 0.65, CF::ArcCW)
ARCTO( 0.65, 0, 0.65, CF::ArcCW)
CLOSEPOLY()
FILL[a -0.5]
}

Contents

Path Operations

† The smooth forms of the quadratic and cubic curve operations infer the unspecified control point by looking at the preceding curve operation. If the preceding operation is not a curve operation (CURVETO, CURVEREL, ARCTO, or ARCREL) then a smooth curve operation is not permitted.

Relative Variants

The path operations all have relative variants: MOVEREL(), LINEREL(), ARCREL(), and CURVEREL(). In the relative path operations the end point (or bezier control points) are specified relative to the current position instead of in absolute terms.

Arc Flags

The basic arc drawing operation specifies a start point, an end point, and an ellipse. The ellipse is positioned such that the start point and end points touch the ellipse and the arc is drawn from the start to the finish. However, in general there are two possible ellipse positions for any pair of starting and ending points, and two different arcs on each ellipse that can be drawn. The CF::ArcCW and CF::ArcLarge flags indicate which of the four possible arcs are drawn.

Image:Arcs.png

Two of the four arcs are large, i.e., more than 180°. Specifying the CF::ArcLarge flag indicates that one of these arcs should be drawn. Otherwise one of the arcs that are less than 180° will be drawn. Two of the four arcs draw from start to end clockwise around the ellipse and two draw counter-clockwise. Specifying the CF::ArcCW flag indicates that a clockwise arc should be drawn. Otherwise a counter-clockwise arc will be drawn.

Setting the radius of the arc to be negative has the effect of inverting the arc drawing direction. A counter-clockwise arc will be drawn clockwise if the radius is negative. A clockwise arc will be drawn counter-clockwise if the radius is negative.

Bezier Control Points

The control points for bezier curve segments control the slope of the curve at the ends. For cubic bezier curves each end has its own control point and the slope at each end is indicated by the slope of the line from the end to the control point. For quadratic bezier curves both ends share a single control point and the slope at each end is indicated by the slope of the line from each end to the shared control point.

Image:Bezier.png

For smooth cubic bezier curves the starting control point is the mirror of the ending control point on the previous bezier curve or arc curve. For smooth quadratic bezier curves the single control point is the mirror of the ending control point on the previous bezier curve or arc curve. The preceding curve does not need to be of the same order (quadratic or cubic) as the smooth curve. The preceding curve can even be an ARCTO. Context Free will figure out what control point will match the slope and curvature between the smooth curve and the curve the precedes it.

Path Commands

After a path sequence there can be one or more path commands. Path commands instruct Context Free to draw (stroke or fill) all of the path sequences between the path command and the previous group of path commands.

Stroke Flags

Join types linejoin.png

Cap types linecap.png

path iso {
ARCTO(0, 1, 0.5)
ARCTO(0, 0, 0.5)
CLOSEPOLY()
STROKE() [s 2 0.5]
STROKE(CF::IsoWidth) [s 2 0.5 y -0.75]
}

Fill Flags

Non-Zero filling fillrule-nonzero.png

Even-Odd filling fillrule-evenodd.png

Note that the shape adjustments in path commands can either be basic or ordered (see basic vs. ordered).

If a path is completed (by a closing curly brace, '}') with no path command following the last set of path sequences then an implicit fill command is appended to the path.

Control Flow

Paths support all of the control flow elements that shapes support: loops, if statements, switch statements, variables, and transform blocks.

Subpaths

Paths can invoke other paths. The path sequences from the invoked path are inserted directly into the current path. This is useful for including the same path sequence into multiple paths. Also, subpath invocations can be passed to a path as a shape parameter, but only if the the subpath contains only path operations. A path can only invoke subpaths that occur earlier in the CFDG file. A path cannot invoke itself recursively or invoke paths that are after it in the file. Context Free cannot silently drop small path sequences the way that it can silently drop small shapes. If you manage to make a very large path sequence you will crash Context Free.

path star {
MOVETO(0,1)
loop 4 [r 144]
LINETO(cos(234), sin(234))
CLOSEPOLY()
}
 
path stars {
loop 5 [r 72]
path star[y ((sqrt(5)+1)/2)]
STROKE[]
}
Views
Personal tools
Navigation
Toolbox
Powered by MediaWiki
Attribution-Share Alike 2.5
book coverSee our book:
Community of Variation