Context Free Art

Parameter

From Context Free Art

Jump to: navigation, search

Parameters are like variables, but they are evaluated at the invocation of a shape or path and bound to the parameter variables when the shape or path is executed.

startshape LeftOrRightFlower
 
shape curve(number shrink, number turn) {
SQUARE []
curve(=) [[y 0.5 r turn s shrink y 0.5]]
// Invoke shape curve recursively, reusing whatever parameters that were provided
}
 
stem = curve(0.97, 1) // bind 0.97 to shrink and 1 to turn in shape curve, and bind shape curve to stem
 
shape LeftOrRightFlower
rule { LeftFlower [] }
rule { LeftFlower [flip 90] }
 
shape LeftFlower {
curve(0.98, -3) [x 1.5 y 0.125 size 0.25] // bind 0.98 to shrink and -3 to turn in shape curve, and invoke.
curve(0.98, -2) [x 1.0 y 0.125 size 0.25] // bind 0.98 to shrink and -2 to turn in shape curve, and invoke.
curve(0.98, -1) [x 0.5 y 0.125 size 0.25] // bind 0.98 to shrink and -1 to turn in shape curve, and invoke.
curve(0.98, 1) [x -0.5 y 0.125 size 0.25] // bind 0.98 to shrink and 1 to turn in shape curve, and invoke.
curve(0.98, 2) [x -1.0 y 0.125 size 0.25] // bind 0.98 to shrink and 2 to turn in shape curve, and invoke.
curve(0.98, 3) [x -1.5 y 0.125 size 0.25] // bind 0.98 to shrink and 3 to turn in shape curve, and invoke.
stem [y 0.5] // Invoke stem shape replacement variable
Blossom [x -13.25 y 26.3]
}
 
shape Blossom {
CIRCLE [size 2]
loop 6 [r 60] LeftOrRightFlower [size 0.4 y 3]
}

Contents

Parameter Types

As you can see from the example, a parameter declaration is a type followed by a name. There are four parameter types: number, adjustment, shape, and natural. The first three are equivalent to the numeric, shape adjustment, and shape replacement variable types. The natural type is a numeric type that is constrained to be a non-negative integer. The type specifier is optional for number parameters.

Number parameters

Number parameters are floating point numbers. They can be used in any expression within a rule or path.

Natural Parameters

Natural parameters are numeric parameters that are constrained to be natural numbers (non-negative integers). They can be used in any expression within a rule or path.

Adjustment parameters

There are two ways to use adjustment parameters: they can be inserted into a shape adjustment list using the new transform adjustment (which has the abbreviated form tr). Or the parameter can be directly inserted an expression that has adjustment type.

Shape parameters

Shape parameters are used in place of the shape name in a shape replacement.

startshape test
 
shape foo(scale) // equivalent to shape foo(number scale)
{
SQUARE [r 0..90 s scale]
}
 
shape recurse(adjustment change, shape thingie)
{
thingie[] // invoke thingie with parameters already bound
recurse(=) [transform change] // can be abbreviated as trans
}
 
shape test {
recurse( [[y 0.5 s 0.97 r 3 y 0.5]], foo(0.5) ) [] // bind 0.5 to scale in shape foo here
}

The above example shows how adjustment and shape parameters are passed to a shape and used within a shape.

Restriction to Preserve Context Free Purity

Allowing unrestricted use of parameters would change CFDG files from context free grammars to indexed grammars, which are considered context-sensitive. So there are two types of numeric parameters, each with its own restrictions.

Number Parameter Restrictions

number parameters can either be one of two forms: purely local or purely non-local. A purely local expression does not depend on any incoming parameters: it does not reference an incoming parameter, does not reference a variable that depends on an incoming parameter, and does not reference a loop index which has loop bounds that depend on an incoming parameter. A purely non-local expression is simply a direct reference to an incoming parameter.

shape taper(number shrink) {
SQUARE []
taper(0.5) [size shrink] // Allowed, 0.5 is constant
taper(rand(0.5, 1.5)) [size shrink] // Allowed, rand() is random, and 0.5 & 1.5 are constant
taper(shrink) [size shrink] // Allowed, shrink is a number parameter
taper(=) [size shrink] // Allowed, same as previous line
taper(shrink * 0.5) [size shrink] // Not allowed, expression includes a number parameter
taper(rand(shrink * 2, shrink * 2.000000001)) [size shrink]
// Not allowed, rand() is random but its arguments are not constant
}

Natural Parameter Restrictions

natural parameters are restricted to be natural numbers (positive integers or zero). Any expression can be evaluated and bound to a natural parameter as long as it meets the natural number restrictions. The natural number restrictions are:

shape fibspiral(natural last, natural current)
rule 0.001 {}
rule {
quarter [sat 1 b 1]
fibspiral(current, last+current)
[h 30 x -1 y 1 r 90
s ((last+current)/current)]
}

Defeating Parameter Restrictions

By default, number and natural parameter restrictions are enabled, but they can be turned off. Simply provide a CF::Impure configuration declaration to turn checking on or off.

CF::Impure = 1  // Turn purity restrictions off
CF::Impure = 0  // Turn purity restrictions on

Reusing Parameters

In the curve example above the curve rule invokes itself recursively using the same parameters. There is a shorthand for doing this common operation, put an equal sign, =, in place of the parameters in the shape invocation. This works for recursive shape invocation and also for invoking a different shape that has the same parameter types. Using the parameter reuse syntax is optional. This curve shape draws exactly the same as the other one:

shape curve(number shrink, number turn) {
SQUARE []
curve(shrink, turn) [[y 0.5 r turn s shrink y 0.5]]
}

But using the parameter reuse syntax makes your code simpler, more expressive, and faster.

Views
Personal tools
Navigation
Toolbox
Powered by MediaWiki
Attribution-Share Alike 2.5
book coverSee our book:
Community of Variation