diff --git a/WRITING_DOCS.md b/WRITING_DOCS.md index d62330c..438124d 100644 --- a/WRITING_DOCS.md +++ b/WRITING_DOCS.md @@ -56,6 +56,11 @@ All files must have either a `// File:` block or a `// LibFile:` block at the st // denote a paragraph break with a comment line with three // trailing spaces, or just a period. // . + // You can have links in this text to functions, modules, or + // constants in other files by putting the name in double- + // braces like {{cyl()}} or {{lerp()}} or {{DOWN}}. If you want to + // link to another file, or section in another file you can use + // a manual markdown link like [Section: Cuboids](shapes.scad#section-cuboids). // The end of the block is denoted by a line without a comment. Which outputs Markdown code that renders like: @@ -67,9 +72,15 @@ Which outputs Markdown code that renders like: > denote a paragraph break with a comment line with three > trailing spaces, or just a period. > +> You can have links in this text to functions, modules, or +> constants in other files by putting the name in double- +> braces like [cyl()](shapes.scad#functionmodule-cyl) or [lerp()](math.scad#function-lerp) or [DOWN](constants.scad-down). If you want to +> link to another file, or section in another file you can use +> a manual markdown link like [Section: Cuboids](shapes.scad#section-cuboids). > The end of the block is denoted by a line without a comment. -Or: +You can use `// File:` instead of `// LibFile:`, if it seems more apropriate for +your particular context:: // File: Foobar.scad // This file contains a collection of metasyntactical nonsense. @@ -129,20 +140,32 @@ Section blocks take a title, and an optional body that will be shown as the desc // denote a paragraph break with a comment line with three // trailing spaces, or just a period. // . + // You can have links in this text to functions, modules, or + // constants in other files by putting the name in double- + // braces like {{cyl()}} or {{lerp()}} or {{DOWN}}. If you want to + // link to another file, or section in another file you can use + // a manual markdown link like [Section: Cuboids](shapes.scad#section-cuboids). + // . // The end of the block is denoted by a line without a comment. // or a line that is unindented after the comment. Which outputs Markdown code that renders like: ->## Section: Foobar ->You can have several lines of markdown formatted text here. ->You just need to make sure that each line is indented, with ->at least three spaces after the comment marker. You can ->denote a paragraph break with a comment line with three ->trailing spaces, or just a period. +> ## Section: Foobar +> You can have several lines of markdown formatted text here. +> You just need to make sure that each line is indented, with +> at least three spaces after the comment marker. You can +> denote a paragraph break with a comment line with three +> trailing spaces, or just a period. > ->The end of the block is denoted by a line without a comment. ->or a line that is unindented after the comment. +> You can have links in this text to functions, modules, or +> constants in other files by putting the name in double- +> braces like [cyl()](shapes.scad#functionmodule-cyl) or [lerp()](math.scad#function-lerp) or [DOWN](constants.scad-down). If you want to +> link to another file, or section in another file you can use +> a manual markdown link like [Section: Cuboids](shapes.scad#section-cuboids). +> +> The end of the block is denoted by a line without a comment. +> or a line that is unindented after the comment. Sections can also include Figures; images generated from code that is not shown in a code block. @@ -160,9 +183,9 @@ The `Constant` header is used to document a code constant. It should have a Des Which outputs Markdown code that renders like: ->### Constant: PHI ->**Description:** ->The golden ration phi. +> ### Constant: PHI +> **Description:** +> The golden ration phi. The `Module` header is used to document a module. It should have a Description sub-block. It is recommended to also have Usage, Arguments, and Example/Examples sub-blocks: @@ -183,23 +206,23 @@ The `Module` header is used to document a module. It should have a Description Which outputs Markdown code that renders like: ->### Module: cross() ->**Usage:** ->- cross(size); -> ->**Description:** ->Creates a 2D cross/plus shape. -> ->**Arguments:** ->Positional Arg | What it does ->-------------------- | ------------------- ->size | The scalar size of the cross. -> ->**Example:** ->```openscad ->cross(size=100); ->``` ->GENERATED IMAGE GOES HERE +> ### Module: cross() +> **Usage:** +> - cross(size); +> +> **Description:** +> Creates a 2D cross/plus shape. +> +> **Arguments:** +> Positional Arg | What it does +> -------------------- | ------------------- +> size | The scalar size of the cross. +> +> **Example:** +> ```openscad +> cross(size=100); +> ``` +> GENERATED IMAGE GOES HERE The `Function` header is used to document a function. It should have a Description sub-block. It is recommended to also have Usage, Arguments, and Example/Examples sub-blocks. By default, Examples will not generate images for function blocks: @@ -222,26 +245,26 @@ The `Function` header is used to document a function. It should have a Descript Which outputs Markdown code that renders like: ->### Function: vector_angle() ->**Usage:** ->- ang = vector_angle(v1, v2); -> ->**Description:** ->Calculates the angle between two vectors in degrees. -> ->**Arguments:** ->Positional Arg | What it does ->-------------------- | ------------------- ->`v1` | The first vector. ->`v2` | The second vector. -> ->**Example:** ->```openscad ->v1 = [1,1,0]; ->v2 = [1,0,0]; ->angle = vector_angle(v1, v2); ->// Returns: 45 ->``` +> ### Function: vector_angle() +> **Usage:** +> - ang = vector_angle(v1, v2); +> +> **Description:** +> Calculates the angle between two vectors in degrees. +> +> **Arguments:** +> Positional Arg | What it does +> -------------------- | ------------------- +> `v1` | The first vector. +> `v2` | The second vector. +> +> **Example:** +> ```openscad +> v1 = [1,1,0]; +> v2 = [1,0,0]; +> angle = vector_angle(v1, v2); +> // Returns: 45 +> ``` The `Function&Module` header is used to document a function which has a related module of the same name. It should have a Description sub-block. It is recommended to also have Usage, Arguments, and Example/Examples sub-blocks. You should have Usage blocks for both calling as a function, and calling as a module: @@ -271,52 +294,67 @@ module: Which outputs Markdown code that renders like: ->### Function&Module: oval() ->**Topics:** 2D Shapes, Geometry +> ### Function&Module: oval() +> **Topics:** 2D Shapes, Geometry > ->**Usage:** As a Module +> **Usage:** As a Module > ->- oval(rx,ry); +> - oval(rx,ry); > ->**Usage:** As a Function +> **Usage:** As a Function > ->- path = oval(rx,ry); +> - path = oval(rx,ry); > ->**Description:** ->When called as a function, returns the perimeter path of the oval. ->When called as a module, creates a 2D oval shape. +> **Description:** +> When called as a function, returns the perimeter path of the oval. +> When called as a module, creates a 2D oval shape. > ->**Arguments:** ->Positional Arg | What it does ->-------------------- | ------------------- ->rx | X axis radius. ->ry | Y axis radius. +> **Arguments:** +> Positional Arg | What it does +> -------------------- | ------------------- +> rx | X axis radius. +> ry | Y axis radius. > ->**Example:** Called as a Function +> **Example:** Called as a Function > ->```openscad ->path = oval(100,60); ->polygon(path); ->``` ->GENERATED IMAGE SHOWN HERE +> ```openscad +> path = oval(100,60); +> polygon(path); +> ``` +> GENERATED IMAGE SHOWN HERE > ->**Example:** Called as a Module +> **Example:** Called as a Module > ->```openscad ->oval(80,60); ->``` ->GENERATED IMAGE SHOWN HERE +> ```openscad +> oval(80,60); +> ``` +> GENERATED IMAGE SHOWN HERE These Type blocks can have a number of sub-blocks. Most sub-blocks are optional, The available standard sub-blocks are: +- `// Aliases: alternatename(), anothername()` - `// Status: DEPRECATED` - `// Topics: Comma, Delimited, Topic, List` - `// Usage:` - `// Description:` - `// Arguments:` - `// Figure:` or `// Figures` +- `// See Also: otherfunc(), othermod(), OTHERCONST` - `// Example:` or `// Examples:` +Aliases Block +------------- + +The Aliases block is used to give alternate names for a function, module, or +constant. This is reflected in the indexes generated. It looks like: + + // Aliases: secondname(), thirdname() + +Which outputs Markdown code that renders like: + +> **Aliases:** secondname(), thirdname() + + Status Block ------------ @@ -326,7 +364,7 @@ The Status block is used to mark a function, module, or constant as deprecated: Which outputs Markdown code that renders like: ->**Status:** DEPRECATED, use foo() instead +> **Status:** DEPRECATED, use foo() instead Topics Block @@ -338,7 +376,7 @@ The Topics block can associate various topics with the current function or modul Which outputs Markdown code that renders like: ->**Topics:** 2D Shapes, Geometry, Masks +> **Topics:** 2D Shapes, Geometry, Masks Usage Block @@ -353,12 +391,12 @@ The Usage block describes the various ways that the current function or module c Which outputs Markdown code that renders like: ->**Usage:** As a Module ->- oval(rx, ry, ); -> ->**Usage:** As a Function -> ->- path = oval(rx, ry, ); +> **Usage:** As a Module +> - oval(rx, ry, ); +> +> **Usage:** As a Function +> +> - path = oval(rx, ry, ); Description Block @@ -369,15 +407,30 @@ The Description block just describes the currect function, module, or constant: // It can be multiple lines long. Markdown syntax code will be used // verbatim in the output markdown file, with the exception of `_`, // which will traslate to `\_`, so that underscores in function/module - // names don't get butchered. + // names don't get butchered. A line with just a period (`.`) will be + // treated as a blank line. + // . + // You can have links in this text to functions, modules, or + // constants in other files by putting the name in double- + // braces like {{cyl()}} or {{lerp()}} or {{DOWN}}. If you want to + // link to another file, or section in another file you can use + // a manual markdown link like [Section: Cuboids](shapes.scad#section-cuboids). Which outputs Markdown code that renders like: ->**Description:** ->It can be multiple lines long. Markdown syntax code will be used ->verbatim in the output markdown file, with the exception of `_`, ->which will traslate to `\_`, so that underscores in function/module ->names don't get butchered. +> **Description:** +> It can be multiple lines long. Markdown syntax code will be used +> verbatim in the output markdown file, with the exception of `_`, +> which will traslate to `\_`, so that underscores in function/module +> names don't get butchered. A line with just a period (`.`) will be +> treated as a blank line. +> +> You can have links in this text to functions, modules, or +> constants in other files by putting the name in double- +> braces like [cyl()](shapes.scad#functionmodule-cyl) or [lerp()](math.scad#function-lerp) or [DOWN](constants.scad-down). If you want to +> link to another file, or section in another file you can use +> a manual markdown link like [Section: Cuboids](shapes.scad#section-cuboids). + Arguments Block --------------- @@ -388,22 +441,36 @@ The Arguments block creates a table that describes the positional arguments for // v2 = This supplies the second vector. // --- // fast = Use fast, but less comprehensive calculation method. + // bar = Takes an optional `bar` struct. See {{bar()}}. // dflt = Default value. Which outputs Markdown code that renders like: ->**Arguments:** ->Positional Arg | What it Does ->-------------------- | --------------------------------- ->`v1` | This supplies the first vector. ->`v2` | The supplies the second vector. -> ->Named Arg | What it Does ->------------------ | --------------------------------- ->`fast` | If true, use fast, but less accurate calculation method. ->`dflt` | Default value. +> **Arguments:** +> Positional Arg | What it Does +> -------------- | --------------------------------- +> `v1` | This supplies the first vector. +> `v2` | The supplies the second vector. +> +> Named Arg | What it Does +> -------------- | --------------------------------- +> `fast` | If true, use fast, but less accurate calculation method. +> `bar` | Takes an optional `bar` struct. See [bar()](foobar.scad#function-bar). +> `dflt` | Default value. + + +See Also Block +-------------- + +The See Also block is used to give links to related functions, modules, or +constants. It looks like: + + // See Also: relatedfunc(), similarmodule() + +Which outputs Markdown code that renders like: + +> **See Also:** [relatedfunc()](otherfile.scad#relatedfunc), [similarmodule()](otherfile.scad#similarmodule) ---- Figure Block -------------- @@ -423,20 +490,20 @@ A Figure block generates and shows an image from a script in the multi-line body Which outputs Markdown code that renders like: ->**Figure 1:** Figure description ->GENERATED IMAGE SHOWN HERE -> ->**Figure 2:** Animated figure that spins to show all faces. ->GENERATED IMAGE SHOWN HERE -> ->**Figure 3:** ->GENERATED IMAGE OF CUBE SHOWN HERE -> ->**Figure 4:** ->GENERATED IMAGE OF CYLINDER SHOWN HERE -> ->**Figure 5:** ->GENERATED IMAGE OF SPHERE SHOWN HERE +> **Figure 1:** Figure description +> GENERATED IMAGE SHOWN HERE +> +> **Figure 2:** Animated figure that spins to show all faces. +> GENERATED IMAGE SHOWN HERE +> +> **Figure 3:** +> GENERATED IMAGE OF CUBE SHOWN HERE +> +> **Figure 4:** +> GENERATED IMAGE OF CYLINDER SHOWN HERE +> +> **Figure 5:** +> GENERATED IMAGE OF SPHERE SHOWN HERE The metadata of the Figure block can contain various directives to alter how the image will be generated. These can be comma separated to give multiple @@ -452,6 +519,7 @@ metadata directives: - `Spin`: Animate camera orbit around the `[0,1,1]` axis to display all sides of an object. - `FlatSpin`: Animate camera orbit around the Z axis, above the XY plane. - `Anim`: Make an animation where `$t` varies from `0.0` to almost `1.0`. +- `Frames=36`: Number of animation frames to make. - `FrameMS=250`: Sets the number of milliseconds per frame for spins and animation. - `Small`: Make the image small sized. - `Med`: Make the image medium sized. @@ -461,6 +529,7 @@ metadata directives: - `Render`: Force full rendering from OpenSCAD, instead of the normal preview. - `Edges`: Highlight face edges. - `NoAxes`: Hides the axes and scales. +- `ScriptUnder`: Display script text under image, rather than beside it. Example Block @@ -484,37 +553,37 @@ Any images, if generated, will be created by running it in OpenSCAD: Which outputs Markdown code that renders like: ->**Example 1:** Example description ->```openscad ->cylinder(h=100, d1=75, d2=50); ->up(100) cylinder(h=100, d1=50, d2=75); ->``` ->GENERATED IMAGE SHOWN HERE -> ->**Example 2:** Animated shape that spins to show all faces. ->```openscad ->cube([10,100,50], center=true); ->cube([100,10,30], center=true); ->``` ->GENERATED IMAGE SHOWN HERE -> ->**Example 3:** ->```openscad ->cube(100); ->``` ->GENERATED IMAGE OF CUBE SHOWN HERE -> ->**Example 4:** ->```openscad ->cylinder(h=100,d=50); ->``` ->GENERATED IMAGE OF CYLINDER SHOWN HERE -> ->**Example 5:** ->```openscad ->sphere(d=100); ->``` ->GENERATED IMAGE OF SPHERE SHOWN HERE +> **Example 1:** Example description +> ```openscad +> cylinder(h=100, d1=75, d2=50); +> up(100) cylinder(h=100, d1=50, d2=75); +> ``` +> GENERATED IMAGE SHOWN HERE +> +> **Example 2:** Animated shape that spins to show all faces. +> ```openscad +> cube([10,100,50], center=true); +> cube([100,10,30], center=true); +> ``` +> GENERATED IMAGE SHOWN HERE +> +> **Example 3:** +> ```openscad +> cube(100); +> ``` +> GENERATED IMAGE OF CUBE SHOWN HERE +> +> **Example 4:** +> ```openscad +> cylinder(h=100,d=50); +> ``` +> GENERATED IMAGE OF CYLINDER SHOWN HERE +> +> **Example 5:** +> ```openscad +> sphere(d=100); +> ``` +> GENERATED IMAGE OF SPHERE SHOWN HERE The metadata of the Example block can contain various directives to alter how the image will be generated. These can be comma separated to give multiple @@ -531,6 +600,7 @@ metadata directives: - `FlatSpin`: Animate camera orbit around the Z axis, above the XY plane. - `Anim`: Make an animation where `$t` varies from `0.0` to almost `1.0`. - `FrameMS=250`: Sets the number of milliseconds per frame for spins and animation. +- `Frames=36`: Number of animation frames to make. - `Small`: Make the image small sized. - `Med`: Make the image medium sized. - `Big`: Make the image big sized. @@ -539,6 +609,7 @@ metadata directives: - `Render`: Force full rendering from OpenSCAD, instead of the normal preview. - `Edges`: Highlight face edges. - `NoAxes`: Hides the axes and scales. +- `ScriptUnder`: Display script text under image, rather than beside it. Modules will default to generating and displaying the image as if the `3D` directive is given. Functions and constants will default to not generating @@ -586,6 +657,7 @@ The Generic block header type takes both title and body lines and generates a ma // Result: For Typical Cases // Does typical things. // Or something like that. + // Refer to {{stuff()}} for more info. // Result: For Atypical Cases // Performs an atypical thing. @@ -595,6 +667,7 @@ Which outputs Markdown code that renders like: > > Does typical things. > Or something like that. +> Refer to [stuff()](foobar.scad#function-stuff) for more info. > > **Result:** For Atypical Cases > @@ -614,6 +687,7 @@ line blocks: // Reason: This is a complex reason. // It is a multi-line explanation // about why this does what it does. + // Refer to {{nonsense()}} for more info. Which outputs Markdown code that renders like: @@ -626,6 +700,7 @@ Which outputs Markdown code that renders like: > This is a complex reason. > It is a multi-line explanation > about why this does what it does. +> Refer to [nonsense()](foobar.scad#function-nonsense) for more info. Label Block Type @@ -652,7 +727,7 @@ numbered list block: // DefineHeader(NumList): Steps // Steps: How to handle being on fire. // Stop running around and panicing. - // Drop to the ground. + // Drop to the ground. Refer to {{drop()}}. // Roll on the ground to smother the flames. Which outputs Markdown code that renders like: @@ -660,7 +735,7 @@ Which outputs Markdown code that renders like: > **Steps:** How to handle being on fire. > > 1. Stop running around and panicing. -> 2. Drop to the ground. +> 2. Drop to the ground. Refer to [drop()](foobar.scad#function-drop). > 3. Roll on the ground to smother the flames. > @@ -672,14 +747,14 @@ The BulletList block header type takes both title and body lines: // DefineHeader(BulletList): Side Effects // Side Effects: For Typical Uses - // The variable `foo` gets set. + // The variable {{$foo}} gets set. // The default for subsequent calls is updated. Which outputs Markdown code that renders like: > **Side Effects:** For Typical Uses > -> - The variable $foo gets set. +> - The variable [$foo](foobar.scad#function-foo) gets set. > - The default for subsequent calls is updated. > @@ -698,17 +773,17 @@ separated by `=` (equals signs): // DefineHeader(Table:^Link Name|Description): Anchors // Anchors: by Name - // "link1" = Anchor for the joiner Located at the back side of the shape. - // "a"/"b" = Anchor for the joiner Located at the front side of the shape. + // "link1" = Anchor for the joiner Located at the {{BACK}} side of the shape. + // "a"/"b" = Anchor for the joiner Located at the {{FRONT}} side of the shape. Which outputs Markdown code that renders like: > **Anchors:** by Name > -> Link Name | Description -> ----------------------- | -------------------- -> `"link1"` | Anchor for the joiner at the back side of the shape. -> `"a"` / `"b"` | Anchor for the joiner at the front side of the shape. +> Link Name | Description +> -------------- | -------------------- +> `"link1"` | Anchor for the joiner at the [BACK](constants.scad#constant-back) side of the shape. +> `"a"` / `"b"` | Anchor for the joiner at the [FRONT](constants.scad#constant-front) side of the shape. > You can have multiple subtables, separated by a line with only three dashes: `---`: @@ -726,14 +801,14 @@ Which outputs Markdown code that renders like: > **Args:** > > Pos Arg | What it Does -> -------------- | -------------------- +> ----------- | -------------------- > `foo` | The foo argument. > `bar` | The bar argument. > -> Named Arg | What it Does -> -------------------- | -------------------- -> `baz` | The baz argument. -> `qux` | The qux argument. +> Named Arg | What it Does +> ----------- | -------------------- +> `baz` | The baz argument. +> `qux` | The qux argument. > Defaults Configuration diff --git a/affine.scad b/affine.scad index fd26c86..aa2b629 100644 --- a/affine.scad +++ b/affine.scad @@ -11,6 +11,7 @@ // Function: ident() // Usage: // mat = ident(n); +// Topics: Affine, Matrices // Description: // Create an `n` by `n` square identity matrix. // Arguments: @@ -42,6 +43,8 @@ function ident(n) = [ // Function: is_affine() // Usage: // bool = is_affine(x,); +// Topics: Affine, Matrices, Transforms +// See Also: is_matrix() // Description: // Tests if the given value is an affine matrix, possibly also checking it's dimenstion. // Arguments: @@ -64,6 +67,8 @@ function is_affine(x,dim=[2,3]) = // Function: is_2d_transform() // Usage: // x = is_2d_transform(t); +// Topics: Affine, Matrices, Transforms +// See Also: is_affine(), is_matrix() // Description: // Checks if the input is a 3D transform that does not act on the z coordinate, except possibly // for a simple scaling of z. Note that an input which is only a zscale returns false. @@ -84,6 +89,8 @@ function is_2d_transform(t) = // z-parameters are zero, except we allow t[2][ // Function: affine2d_to_3d() // Usage: // mat = affine2d_to_3d(m); +// Topics: Affine, Matrices, Transforms +// See Also: affine3d_to_2d() // Description: // Takes a 3x3 affine2d matrix and returns its 4x4 affine3d equivalent. // Example: @@ -106,6 +113,8 @@ function affine2d_to_3d(m) = [ // Function: affine3d_to_2d() // Usage: // mat = affine3d_to_2d(m); +// Topics: Affine, Matrices +// See Also: affine2d_to_3d() // Description: // Takes a 4x4 affine3d matrix and returns its 3x3 affine2d equivalent. 3D transforms that would alter the Z coordinate are disallowed. // Example: @@ -128,6 +137,7 @@ function affine3d_to_2d(m) = // Function: apply() // Usage: // pts = apply(transform, points); +// Topics: Affine, Matrices, Transforms // Description: // Applies the specified transformation matrix to a point, pointlist, bezier patch or VNF. // Both inputs can be 2D or 3D, and it is also allowed to supply 3D transformations with 2D @@ -176,12 +186,13 @@ function apply(transform,points) = // Function: rot_decode() // Usage: // info = rot_decode(rotation); // Returns: [angle,axis,cp,translation] +// Topics: Affine, Matrices, Transforms // Description: // Given an input 3D rigid transformation operator (one composed of just rotations and translations) represented // as a 4x4 matrix, compute the rotation and translation parameters of the operator. Returns a list of the // four parameters, the angle, in the interval [0,180], the rotation axis as a unit vector, a centerpoint for -// the rotation, and a translation. If you set `parms=rot_decode(rotation)` then the transformation can be -// reconstructed from parms as `move(parms[3])*rot(a=parms[0],v=parms[1],cp=parms[2])`. This decomposition +// the rotation, and a translation. If you set `parms = rot_decode(rotation)` then the transformation can be +// reconstructed from parms as `move(parms[3]) * rot(a=parms[0],v=parms[1],cp=parms[2])`. This decomposition // makes it possible to perform interpolation. If you construct a transformation using `rot` the decoding // may flip the axis (if you gave an angle outside of [0,180]). The returned axis will be a unit vector, and // the centerpoint lies on the plane through the origin that is perpendicular to the axis. It may be different @@ -230,6 +241,7 @@ function rot_decode(M) = // Function: affine2d_identity() // Usage: // mat = affine2d_identify(); +// Topics: Affine, Matrices, Transforms // Description: // Create a 3x3 affine2d identity matrix. // Example: @@ -246,6 +258,8 @@ function affine2d_identity() = ident(3); // Function: affine2d_translate() // Usage: // mat = affine2d_translate(v); +// Topics: Affine, Matrices, Transforms, Translation +// See Also: translate(), move(), affine3d_translate() // Description: // Returns the 3x3 affine2d matrix to perform a 2D translation. // Arguments: @@ -270,6 +284,8 @@ function affine2d_translate(v=[0,0]) = // Function: affine2d_scale() // Usage: // mat = affine2d_scale(v); +// Topics: Affine, Matrices, Transforms, Scaling +// See Also: scale(), xscale(), yscale(), zscale(), affine3d_scale() // Description: // Returns the 3x3 affine2d matrix to perform a 2D scaling transformation. // Arguments: @@ -294,6 +310,8 @@ function affine2d_scale(v=[1,1]) = // Function: affine2d_zrot() // Usage: // mat = affine2d_zrot(ang); +// Topics: Affine, Matrices, Transforms, Rotation +// See Also: rot(), xrot(), yrot(), zrot(), affine3d_zrot() // Description: // Returns the 3x3 affine2d matrix to perform a rotation of a 2D vector around the Z axis. // Arguments: @@ -318,6 +336,8 @@ function affine2d_zrot(ang=0) = // Function: affine2d_mirror() // Usage: // mat = affine2d_mirror(v); +// Topics: Affine, Matrices, Transforms, Reflection, Mirroring +// See Also: mirror(), xflip(), yflip(), zflip(), affine3d_mirror() // Description: // Returns the 3x3 affine2d matrix to perform a reflection of a 2D vector across the line given by its normal vector. // Arguments: @@ -361,6 +381,8 @@ function affine2d_mirror(v) = // mat = affine2d_skew(xa); // mat = affine2d_skew(ya=); // mat = affine2d_skew(xa, ya); +// Topics: Affine, Matrices, Transforms, Skewing +// See Also: skew(), affine3d_skew() // Description: // Returns the 3x3 affine2d matrix to skew a 2D vector along the XY plane. // Arguments: @@ -391,6 +413,7 @@ function affine2d_skew(xa=0, ya=0) = // Function: affine3d_identity() // Usage: // mat = affine3d_identity(); +// Topics: Affine, Matrices, Transforms // Description: // Create a 4x4 affine3d identity matrix. // Example: @@ -408,6 +431,8 @@ function affine3d_identity() = ident(4); // Function: affine3d_translate() // Usage: // mat = affine3d_translate(v); +// Topics: Affine, Matrices, Transforms, Translation +// See Also: translate(), move(), affine2d_translate() // Description: // Returns the 4x4 affine3d matrix to perform a 3D translation. // Arguments: @@ -435,6 +460,8 @@ function affine3d_translate(v=[0,0,0]) = // Function: affine3d_scale() // Usage: // mat = affine3d_scale(v); +// Topics: Affine, Matrices, Transforms, Scaling +// See Also: scale(), affine2d_scale() // Description: // Returns the 4x4 affine3d matrix to perform a 3D scaling transformation. // Arguments: @@ -462,6 +489,8 @@ function affine3d_scale(v=[1,1,1]) = // Function: affine3d_xrot() // Usage: // mat = affine3d_xrot(ang); +// Topics: Affine, Matrices, Transforms, Rotation +// See Also: rot(), xrot(), yrot(), zrot(), affine2d_zrot() // Description: // Returns the 4x4 affine3d matrix to perform a rotation of a 3D vector around the X axis. // Arguments: @@ -488,6 +517,8 @@ function affine3d_xrot(ang=0) = // Function: affine3d_yrot() // Usage: // mat = affine3d_yrot(ang); +// Topics: Affine, Matrices, Transforms, Rotation +// See Also: rot(), xrot(), yrot(), zrot(), affine2d_zrot() // Description: // Returns the 4x4 affine3d matrix to perform a rotation of a 3D vector around the Y axis. // Arguments: @@ -514,6 +545,8 @@ function affine3d_yrot(ang=0) = // Function: affine3d_zrot() // Usage: // mat = affine3d_zrot(ang); +// Topics: Affine, Matrices, Transforms, Rotation +// See Also: rot(), xrot(), yrot(), zrot(), affine2d_zrot() // Description: // Returns the 4x4 affine3d matrix to perform a rotation of a 3D vector around the Z axis. // Arguments: @@ -540,6 +573,8 @@ function affine3d_zrot(ang=0) = // Function: affine3d_rot_by_axis() // Usage: // mat = affine3d_rot_by_axis(u, ang); +// Topics: Affine, Matrices, Transforms, Rotation +// See Also: rot(), xrot(), yrot(), zrot(), affine2d_zrot() // Description: // Returns the 4x4 affine3d matrix to perform a rotation of a 3D vector around an axis. // Arguments: @@ -574,6 +609,8 @@ function affine3d_rot_by_axis(u=UP, ang=0) = // Function: affine3d_rot_from_to() // Usage: // mat = affine3d_rot_from_to(from, to); +// Topics: Affine, Matrices, Transforms, Rotation +// See Also: rot(), xrot(), yrot(), zrot(), affine2d_zrot() // Description: // Returns the 4x4 affine3d matrix to perform a rotation of a 3D vector from one vector direction to another. // Arguments: @@ -616,6 +653,8 @@ function affine3d_rot_from_to(from, to) = // map = affine3d_frame_map(x=VECTOR1, y=VECTOR2, ); // map = affine3d_frame_map(x=VECTOR1, z=VECTOR2, ); // map = affine3d_frame_map(y=VECTOR1, z=VECTOR2, ); +// Topics: Affine, Matrices, Transforms, Rotation +// See Also: rot(), xrot(), yrot(), zrot(), affine2d_zrot() // Description: // Returns a transformation that maps one coordinate frame to another. You must specify two or // three of `x`, `y`, and `z`. The specified axes are mapped to the vectors you supplied. If you @@ -672,6 +711,8 @@ function affine3d_frame_map(x,y,z, reverse=false) = // Function: affine3d_mirror() // Usage: // mat = affine3d_mirror(v); +// Topics: Affine, Matrices, Transforms, Reflection, Mirroring +// See Also: mirror(), xflip(), yflip(), zflip(), affine2d_mirror() // Description: // Returns the 4x4 affine3d matrix to perform a reflection of a 3D vector across the plane given by its normal vector. // Arguments: @@ -710,6 +751,8 @@ function affine3d_mirror(v) = // Function: affine3d_skew() // Usage: // mat = affine3d_skew(, , , , , ); +// Topics: Affine, Matrices, Transforms, Skewing +// See Also: skew(), affine3d_skew_xy(), affine3d_skew_xz(), affine3d_skew_yz(), affine2d_skew() // Description: // Returns the 4x4 affine3d matrix to perform a skew transformation. // Arguments: @@ -741,6 +784,8 @@ function affine3d_skew(sxy=0, sxz=0, syx=0, syz=0, szx=0, szy=0) = [ // mat = affine3d_skew_xy(xa); // mat = affine3d_skew_xy(ya=); // mat = affine3d_skew_xy(xa, ya); +// Topics: Affine, Matrices, Transforms, Skewing +// See Also: skew(), affine3d_skew(), affine3d_skew_xz(), affine3d_skew_yz(), affine2d_skew() // Description: // Returns the 4x4 affine3d matrix to perform a skew transformation along the XY plane. // Arguments: @@ -771,6 +816,8 @@ function affine3d_skew_xy(xa=0, ya=0) = // mat = affine3d_skew_xz(xa); // mat = affine3d_skew_xz(za=); // mat = affine3d_skew_xz(xa, za); +// Topics: Affine, Matrices, Transforms, Skewing +// See Also: skew(), affine3d_skew(), affine3d_skew_xy(), affine3d_skew_yz(), affine2d_skew() // Description: // Returns the 4x4 affine3d matrix to perform a skew transformation along the XZ plane. // Arguments: @@ -801,6 +848,8 @@ function affine3d_skew_xz(xa=0, za=0) = // mat = affine3d_skew_yz(ya); // mat = affine3d_skew_yz(za=); // mat = affine3d_skew_yz(ya, za); +// Topics: Affine, Matrices, Transforms, Skewing +// See Also: skew(), affine3d_skew(), affine3d_skew_xy(), affine3d_skew_xz(), affine2d_skew() // Description: // Returns the 4x4 affine3d matrix to perform a skew transformation along the YZ plane. // Arguments: diff --git a/transforms.scad b/transforms.scad index 542d311..5d1497a 100644 --- a/transforms.scad +++ b/transforms.scad @@ -12,15 +12,20 @@ // Function&Module: move() +// Aliases: translate() // // Usage: As Module -// move(, , ) ... +// move(, , ) ... // move(v) ... // Usage: Translate Points // pts = move(v, p); -// pts = move(, , , p); +// pts = move(, , , p=); // Usage: Get Translation Matrix // mat = move(v); +// mat = move(, , ); +// +// Topics: Affine, Matrices, Transforms, Translation +// See Also: left(), right(), fwd(), back(), down(), up(), affine2d_translate(), affine3d_translate() // // Description: // Translates position by the given amount. @@ -35,10 +40,11 @@ // // Arguments: // v = An [X,Y,Z] vector to translate by. +// p = Either a point, or a list of points to be translated when used as a function. +// --- // x = X axis translation. // y = Y axis translation. // z = Z axis translation. -// p = Either a point, or a list of points to be translated when used as a function. // // Example: // #sphere(d=10); @@ -64,18 +70,18 @@ // pt4 = move(y=11, p=[[1,2,3],[4,5,6]]); // Returns: [[1,13,3], [4,16,6]] // mat2d = move([2,3]); // Returns: [[1,0,2],[0,1,3],[0,0,1]] // mat3d = move([2,3,4]); // Returns: [[1,0,0,2],[0,1,0,3],[0,0,1,4],[0,0,0,1]] -module move(v=[0,0,0], x=0, y=0, z=0) -{ +module move(v=[0,0,0], p, x=0, y=0, z=0) { + assert(is_undef(p), "Module form `move()` does not accept p= argument."); translate(point3d(v)+[x,y,z]) children(); } -function move(v=[0,0,0], p=undef, x=0, y=0, z=0) = +function move(v=[0,0,0], p, x=0, y=0, z=0) = is_undef(p)? ( len(v)==2? affine2d_translate(v+[x,y]) : affine3d_translate(point3d(v)+[x,y,z]) ) : ( assert(is_list(p)) - let(v=v+[x,y,z]) + let(v=point3d(v)+[x,y,z]) is_num(p.x)? p+v : is_vnf(p)? [move(v=v,p=p.x), p.y] : [for (l=p) is_vector(l)? l+v : move(v=v, p=l)] @@ -93,6 +99,9 @@ function translate(v=[0,0,0], p=undef) = move(v=v, p=p); // Usage: Get Translation Matrix // mat = left(x); // +// Topics: Affine, Matrices, Transforms, Translation +// See Also: move(), right(), fwd(), back(), down(), up(), affine2d_translate(), affine3d_translate() +// // Description: // If called as a module, moves/translates all children left (in the X- direction) by the given amount. // If called as a function with the `p` argument, returns the translated point or list of points. @@ -111,9 +120,12 @@ function translate(v=[0,0,0], p=undef) = move(v=v, p=p); // pt2 = left(20, p=[15,23,42]); // Returns: [-5,23,42] // pt3 = left(3, p=[[1,2,3],[4,5,6]]); // Returns: [[-2,2,3], [1,5,6]] // mat3d = left(4); // Returns: [[1,0,0,-4],[0,1,0,0],[0,0,1,0],[0,0,0,1]] -module left(x=0) translate([-x,0,0]) children(); +module left(x=0, p) { + assert(is_undef(p), "Module form `left()` does not accept p= argument."); + translate([-x,0,0]) children(); +} -function left(x=0,p=undef) = move([-x,0,0],p=p); +function left(x=0, p) = move([-x,0,0],p=p); // Function&Module: right() @@ -125,6 +137,9 @@ function left(x=0,p=undef) = move([-x,0,0],p=p); // Usage: Get Translation Matrix // mat = right(x); // +// Topics: Affine, Matrices, Transforms, Translation +// See Also: move(), left(), fwd(), back(), down(), up(), affine2d_translate(), affine3d_translate() +// // Description: // If called as a module, moves/translates all children right (in the X+ direction) by the given amount. // If called as a function with the `p` argument, returns the translated point or list of points. @@ -143,9 +158,12 @@ function left(x=0,p=undef) = move([-x,0,0],p=p); // pt2 = right(20, p=[15,23,42]); // Returns: [35,23,42] // pt3 = right(3, p=[[1,2,3],[4,5,6]]); // Returns: [[4,2,3], [7,5,6]] // mat3d = right(4); // Returns: [[1,0,0,4],[0,1,0,0],[0,0,1,0],[0,0,0,1]] -module right(x=0) translate([x,0,0]) children(); +module right(x=0, p) { + assert(is_undef(p), "Module form `right()` does not accept p= argument."); + translate([x,0,0]) children(); +} -function right(x=0,p=undef) = move([x,0,0],p=p); +function right(x=0, p) = move([x,0,0],p=p); // Function&Module: fwd() @@ -157,6 +175,9 @@ function right(x=0,p=undef) = move([x,0,0],p=p); // Usage: Get Translation Matrix // mat = fwd(y); // +// Topics: Affine, Matrices, Transforms, Translation +// See Also: move(), left(), right(), back(), down(), up(), affine2d_translate(), affine3d_translate() +// // Description: // If called as a module, moves/translates all children forward (in the Y- direction) by the given amount. // If called as a function with the `p` argument, returns the translated point or list of points. @@ -175,9 +196,12 @@ function right(x=0,p=undef) = move([x,0,0],p=p); // pt2 = fwd(20, p=[15,23,42]); // Returns: [15,3,42] // pt3 = fwd(3, p=[[1,2,3],[4,5,6]]); // Returns: [[1,-1,3], [4,2,6]] // mat3d = fwd(4); // Returns: [[1,0,0,0],[0,1,0,-4],[0,0,1,0],[0,0,0,1]] -module fwd(y=0) translate([0,-y,0]) children(); +module fwd(y=0, p) { + assert(is_undef(p), "Module form `fwd()` does not accept p= argument."); + translate([0,-y,0]) children(); +} -function fwd(y=0,p=undef) = move([0,-y,0],p=p); +function fwd(y=0, p) = move([0,-y,0],p=p); // Function&Module: back() @@ -189,6 +213,9 @@ function fwd(y=0,p=undef) = move([0,-y,0],p=p); // Usage: Get Translation Matrix // mat = back(y); // +// Topics: Affine, Matrices, Transforms, Translation +// See Also: move(), left(), right(), fwd(), down(), up(), affine2d_translate(), affine3d_translate() +// // Description: // If called as a module, moves/translates all children back (in the Y+ direction) by the given amount. // If called as a function with the `p` argument, returns the translated point or list of points. @@ -207,9 +234,12 @@ function fwd(y=0,p=undef) = move([0,-y,0],p=p); // pt2 = back(20, p=[15,23,42]); // Returns: [15,43,42] // pt3 = back(3, p=[[1,2,3],[4,5,6]]); // Returns: [[1,5,3], [4,8,6]] // mat3d = back(4); // Returns: [[1,0,0,0],[0,1,0,4],[0,0,1,0],[0,0,0,1]] -module back(y=0) translate([0,y,0]) children(); +module back(y=0, ) { + assert(is_undef(p), "Module form `back()` does not accept p= argument."); + translate([0,y,0]) children(); +} -function back(y=0,p=undef) = move([0,y,0],p=p); +function back(y=0,p) = move([0,y,0],p=p); // Function&Module: down() @@ -221,6 +251,9 @@ function back(y=0,p=undef) = move([0,y,0],p=p); // Usage: Get Translation Matrix // mat = down(z); // +// Topics: Affine, Matrices, Transforms, Translation +// See Also: move(), left(), right(), fwd(), back(), up(), affine2d_translate(), affine3d_translate() +// // Description: // If called as a module, moves/translates all children down (in the Z- direction) by the given amount. // If called as a function with the `p` argument, returns the translated point or list of points. @@ -238,9 +271,12 @@ function back(y=0,p=undef) = move([0,y,0],p=p); // pt1 = down(20, p=[15,23,42]); // Returns: [15,23,22] // pt2 = down(3, p=[[1,2,3],[4,5,6]]); // Returns: [[1,2,0], [4,5,3]] // mat3d = down(4); // Returns: [[1,0,0,0],[0,1,0,0],[0,0,1,-4],[0,0,0,1]] -module down(z=0) translate([0,0,-z]) children(); +module down(z=0, p) { + assert(is_undef(p), "Module form `down()` does not accept p= argument."); + translate([0,0,-z]) children(); +} -function down(z=0,p=undef) = move([0,0,-z],p=p); +function down(z=0, p) = move([0,0,-z],p=p); // Function&Module: up() @@ -252,6 +288,9 @@ function down(z=0,p=undef) = move([0,0,-z],p=p); // Usage: Get Translation Matrix // mat = up(z); // +// Topics: Affine, Matrices, Transforms, Translation +// See Also: move(), left(), right(), fwd(), back(), down(), affine2d_translate(), affine3d_translate() +// // Description: // If called as a module, moves/translates all children up (in the Z+ direction) by the given amount. // If called as a function with the `p` argument, returns the translated point or list of points. @@ -269,9 +308,12 @@ function down(z=0,p=undef) = move([0,0,-z],p=p); // pt1 = up(20, p=[15,23,42]); // Returns: [15,23,62] // pt2 = up(3, p=[[1,2,3],[4,5,6]]); // Returns: [[1,2,6], [4,5,9]] // mat3d = up(4); // Returns: [[1,0,0,0],[0,1,0,0],[0,0,1,4],[0,0,0,1]] -module up(z=0) translate([0,0,z]) children(); +module up(z=0, p) { + assert(is_undef(p), "Module form `up()` does not accept p= argument."); + translate([0,0,z]) children(); +} -function up(z=0,p=undef) = move([0,0,z],p=p); +function up(z=0, p) = move([0,0,z],p=p); @@ -282,11 +324,24 @@ function up(z=0,p=undef) = move([0,0,z],p=p); // Function&Module: rot() // -// Usage: -// rot(a, , ) ... -// rot([X,Y,Z], , ) ... -// rot(a, v, , ) ... -// rot(from, to, , ) ... +// Usage: As a Module +// rot(a, , ) {...} +// rot([X,Y,Z], , ) {...} +// rot(a, v, , ) {...} +// rot(from, to, , ) {...} +// Usage: Get Transformation Matrix +// pts = rot(a, , , ); +// pts = rot([X,Y,Z], , , ); +// pts = rot(a, v, , , ); +// pts = rot(from=, to=, , , ); +// Usage: As a Function +// pts = rot(a, p=, , ); +// pts = rot([X,Y,Z], p=, , ); +// pts = rot(a, v, p=, , ); +// pts = rot(, from=, to=, p=, ); +// +// Topics: Affine, Matrices, Transforms, Rotation +// See Also: xrot(), yrot(), zrot(), affine2d_zrot(), affine3d_xrot(), affine3d_yrot(), affine3d_zrot(), affine3d_rot_by_axis(), affine3d_rot_from_to() // // Description: // This is a shorthand version of the built-in `rotate()`, and operates similarly, with a few additional capabilities. @@ -310,6 +365,7 @@ function up(z=0,p=undef) = move([0,0,z],p=p); // Arguments: // a = Scalar angle or vector of XYZ rotation angles to rotate by, in degrees. If `planar` is true and `p` is not given, then `a` must be a finite scalar. Default: `0` // v = vector for the axis of rotation. Default: [0,0,1] or UP +// --- // cp = centerpoint to rotate around. Default: [0,0,0] // from = Starting vector for vector-based rotations. // to = Target vector for vector-based rotations. @@ -333,7 +389,7 @@ function up(z=0,p=undef) = move([0,0,z],p=p); // path = square([50,30], center=true); // #stroke(path, closed=true); // stroke(rot(30,p=path), closed=true); -module rot(a=0, v=undef, cp=undef, from=undef, to=undef, reverse=false) +module rot(a=0, v, cp, from, to, reverse=false) { m = rot(a=a, v=v, cp=cp, from=from, to=to, reverse=reverse, planar=false); multmatrix(m) children(); @@ -395,11 +451,14 @@ function rot(a=0, v, cp, from, to, reverse=false, planar=false, p, _m) = // Function&Module: xrot() // // Usage: As Module -// xrot(a, ) ... +// xrot(a, ) ... // Usage: Rotate Points -// rotated = xrot(a, p, ); +// rotated = xrot(a, p, ); // Usage: Get Rotation Matrix -// mat = xrot(a, ); +// mat = xrot(a, ); +// +// Topics: Affine, Matrices, Transforms, Rotation +// See Also: rot(), yrot(), zrot(), affine2d_zrot(), affine3d_xrot(), affine3d_yrot(), affine3d_zrot() // // Description: // Rotates around the X axis by the given number of degrees. If `cp` is given, rotations are performed around that centerpoint. @@ -413,14 +472,16 @@ function rot(a=0, v, cp, from, to, reverse=false, planar=false, p, _m) = // // Arguments: // a = angle to rotate by in degrees. -// cp = centerpoint to rotate around. Default: [0,0,0] // p = If called as a function, this contains a point or list of points to rotate. +// --- +// cp = centerpoint to rotate around. Default: [0,0,0] // // Example: // #cylinder(h=50, r=10, center=true); // xrot(90) cylinder(h=50, r=10, center=true); -module xrot(a=0, cp=undef) +module xrot(a=0, p, cp) { + assert(is_undef(p), "Module form `xrot()` does not accept p= argument."); if (a==0) { children(); // May be slightly faster? } else if (!is_undef(cp)) { @@ -430,17 +491,20 @@ module xrot(a=0, cp=undef) } } -function xrot(a=0, cp=undef, p=undef) = rot([a,0,0], cp=cp, p=p); +function xrot(a=0, p, cp) = rot([a,0,0], cp=cp, p=p); // Function&Module: yrot() // // Usage: As Module -// yrot(a, ) ... +// yrot(a, ) ... // Usage: Rotate Points -// rotated = yrot(a, p, ); +// rotated = yrot(a, p, ); // Usage: Get Rotation Matrix -// mat = yrot(a, ); +// mat = yrot(a, ); +// +// Topics: Affine, Matrices, Transforms, Rotation +// See Also: rot(), xrot(), zrot(), affine2d_zrot(), affine3d_xrot(), affine3d_yrot(), affine3d_zrot() // // Description: // Rotates around the Y axis by the given number of degrees. If `cp` is given, rotations are performed around that centerpoint. @@ -454,14 +518,16 @@ function xrot(a=0, cp=undef, p=undef) = rot([a,0,0], cp=cp, p=p); // // Arguments: // a = angle to rotate by in degrees. -// cp = centerpoint to rotate around. Default: [0,0,0] // p = If called as a function, this contains a point or list of points to rotate. +// --- +// cp = centerpoint to rotate around. Default: [0,0,0] // // Example: // #cylinder(h=50, r=10, center=true); // yrot(90) cylinder(h=50, r=10, center=true); -module yrot(a=0, cp=undef) +module yrot(a=0, p, cp) { + assert(is_undef(p), "Module form `yrot()` does not accept p= argument."); if (a==0) { children(); // May be slightly faster? } else if (!is_undef(cp)) { @@ -471,17 +537,20 @@ module yrot(a=0, cp=undef) } } -function yrot(a=0, cp=undef, p=undef) = rot([0,a,0], cp=cp, p=p); +function yrot(a=0, p, cp) = rot([0,a,0], cp=cp, p=p); // Function&Module: zrot() // // Usage: As Module -// zrot(a, ) ... +// zrot(a, ) ... // Usage: Rotate Points -// rotated = zrot(a, p, ); +// rotated = zrot(a, p, ); // Usage: Get Rotation Matrix -// mat = zrot(a, ); +// mat = zrot(a, ); +// +// Topics: Affine, Matrices, Transforms, Rotation +// See Also: rot(), xrot(), yrot(), affine2d_zrot(), affine3d_xrot(), affine3d_yrot(), affine3d_zrot() // // Description: // Rotates around the Z axis by the given number of degrees. If `cp` is given, rotations are performed around that centerpoint. @@ -495,14 +564,16 @@ function yrot(a=0, cp=undef, p=undef) = rot([0,a,0], cp=cp, p=p); // // Arguments: // a = angle to rotate by in degrees. -// cp = centerpoint to rotate around. Default: [0,0,0] // p = If called as a function, this contains a point or list of points to rotate. +// --- +// cp = centerpoint to rotate around. Default: [0,0,0] // // Example: // #cube(size=[60,20,40], center=true); // zrot(90) cube(size=[60,20,40], center=true); -module zrot(a=0, cp=undef) +module zrot(a=0, p, cp) { + assert(is_undef(p), "Module form `zrot()` does not accept p= argument."); if (a==0) { children(); // May be slightly faster? } else if (!is_undef(cp)) { @@ -512,17 +583,20 @@ module zrot(a=0, cp=undef) } } -function zrot(a=0, cp=undef, p=undef) = rot(a, cp=cp, p=p); +function zrot(a=0, p, cp) = rot(a, cp=cp, p=p); // Function&Module: xyrot() // // Usage: As Module -// xyrot(a, ) ... +// xyrot(a, ) ... // Usage: Rotate Points -// rotated = xyrot(a, p, ); +// rotated = xyrot(a, p, ); // Usage: Get Rotation Matrix -// mat = xyrot(a, ); +// mat = xyrot(a, ); +// +// Topics: Affine, Matrices, Transforms, Rotation +// See Also: rot(), xrot(), yrot(), zrot(), xzrot(), yzrot(), xyzrot(), affine3d_rot_by_axis() // // Description: // Rotates around the [1,1,0] vector axis by the given number of degrees. If `cp` is given, rotations are performed around that centerpoint. @@ -542,8 +616,9 @@ function zrot(a=0, cp=undef, p=undef) = rot(a, cp=cp, p=p); // Example: // #cylinder(h=50, r=10, center=true); // xyrot(90) cylinder(h=50, r=10, center=true); -module xyrot(a=0, cp) +module xyrot(a=0, p, cp) { + assert(is_undef(p), "Module form `xyrot()` does not accept p= argument."); if (a==0) { children(); // May be slightly faster? } else { @@ -558,11 +633,14 @@ function xyrot(a=0, p, cp) = rot(a=a, v=[1,1,0], cp=cp, p=p); // Function&Module: xzrot() // // Usage: As Module -// xzrot(a, ) ... +// xzrot(a, ) ... // Usage: Rotate Points -// rotated = xzrot(a, p, ); +// rotated = xzrot(a, p, ); // Usage: Get Rotation Matrix -// mat = xzrot(a, ); +// mat = xzrot(a, ); +// +// Topics: Affine, Matrices, Transforms, Rotation +// See Also: rot(), xrot(), yrot(), zrot(), xyrot(), yzrot(), xyzrot(), affine3d_rot_by_axis() // // Description: // Rotates around the [1,0,1] vector axis by the given number of degrees. If `cp` is given, rotations are performed around that centerpoint. @@ -582,8 +660,9 @@ function xyrot(a=0, p, cp) = rot(a=a, v=[1,1,0], cp=cp, p=p); // Example: // #cylinder(h=50, r=10, center=true); // xzrot(90) cylinder(h=50, r=10, center=true); -module xzrot(a=0, cp) +module xzrot(a=0, p, cp) { + assert(is_undef(p), "Module form `xzrot()` does not accept p= argument."); if (a==0) { children(); // May be slightly faster? } else { @@ -598,11 +677,14 @@ function xzrot(a=0, p, cp) = rot(a=a, v=[1,0,1], cp=cp, p=p); // Function&Module: yzrot() // // Usage: As Module -// yzrot(a, ) ... +// yzrot(a, ) ... // Usage: Rotate Points -// rotated = yzrot(a, p, ); +// rotated = yzrot(a, p, ); // Usage: Get Rotation Matrix -// mat = yzrot(a, ); +// mat = yzrot(a, ); +// +// Topics: Affine, Matrices, Transforms, Rotation +// See Also: rot(), xrot(), yrot(), zrot(), xyrot(), xzrot(), xyzrot(), affine3d_rot_by_axis() // // Description: // Rotates around the [0,1,1] vector axis by the given number of degrees. If `cp` is given, rotations are performed around that centerpoint. @@ -622,8 +704,9 @@ function xzrot(a=0, p, cp) = rot(a=a, v=[1,0,1], cp=cp, p=p); // Example: // #cylinder(h=50, r=10, center=true); // yzrot(90) cylinder(h=50, r=10, center=true); -module yzrot(a=0, cp) +module yzrot(a=0, p, cp) { + assert(is_undef(p), "Module form `yzrot()` does not accept p= argument."); if (a==0) { children(); // May be slightly faster? } else { @@ -638,11 +721,14 @@ function yzrot(a=0, p, cp) = rot(a=a, v=[0,1,1], cp=cp, p=p); // Function&Module: xyzrot() // // Usage: As Module -// xyzrot(a, ) ... +// xyzrot(a, ) ... // Usage: Rotate Points -// rotated = xyzrot(a, p, ); +// rotated = xyzrot(a, p, ); // Usage: Get Rotation Matrix -// mat = xyzrot(a, ); +// mat = xyzrot(a, ); +// +// Topics: Affine, Matrices, Transforms, Rotation +// See Also: rot(), xrot(), yrot(), zrot(), xyrot(), xzrot(), yzrot(), affine3d_rot_by_axis() // // Description: // Rotates around the [1,1,1] vector axis by the given number of degrees. If `cp` is given, rotations are performed around that centerpoint. @@ -662,8 +748,9 @@ function yzrot(a=0, p, cp) = rot(a=a, v=[0,1,1], cp=cp, p=p); // Example: // #cylinder(h=50, r=10, center=true); // xyzrot(90) cylinder(h=50, r=10, center=true); -module xyzrot(a=0, cp) +module xyzrot(a=0, p, cp) { + assert(is_undef(p), "Module form `xyzrot()` does not accept p= argument."); if (a==0) { children(); // May be slightly faster? } else { @@ -682,12 +769,14 @@ function xyzrot(a=0, p, cp) = rot(a=a, v=[1,1,1], cp=cp, p=p); // Function&Module: scale() // Usage: As Module -// scale(SCALAR, ) ... -// scale([X,Y,Z], ) ... +// scale(SCALAR) ... +// scale([X,Y,Z]) ... // Usage: Scale Points -// pts = scale(v, p, ); +// pts = scale(v, p, ); // Usage: Get Scaling Matrix -// mat = scale(v, ); +// mat = scale(v, ); +// Topics: Affine, Matrices, Transforms, Scaling +// See Also: xscale(), yscale(), zscale(), affine2d_scaling(), affine3d_scaling() // Description: // Scales by the [X,Y,Z] scaling factors given in `v`. If `v` is given as a scalar number, all axes are scaled uniformly by that amount. // * Called as the built-in module, scales all children. @@ -699,8 +788,9 @@ function xyzrot(a=0, p, cp) = rot(a=a, v=[1,1,1], cp=cp, p=p); // * Called as a function without a `p` argument, and a 3D list of scaling factors in `v`, returns an affine3d scaling matrix. // Arguments: // v = Either a numeric uniform scaling factor, or a list of [X,Y,Z] scaling factors. Default: 1 -// cp = If given, centers the scaling on the point `cp`. // p = If called as a function, the point or list of points to scale. +// --- +// cp = If given, centers the scaling on the point `cp`. // Example(NORENDER): // pt1 = scale(3, p=[3,1,4]); // Returns: [9,3,12] // pt2 = scale([2,3,4], p=[3,1,4]); // Returns: [6,3,16] @@ -711,9 +801,10 @@ function xyzrot(a=0, p, cp) = rot(a=a, v=[1,1,1], cp=cp, p=p); // path = circle(d=50,$fn=12); // #stroke(path,closed=true); // stroke(scale([1.5,3],p=path),closed=true); -function scale(v=1, cp=[0,0,0], p) = +function scale(v=1, p, cp=[0,0,0]) = assert(is_num(v) || is_vector(v)) assert(is_undef(p) || is_list(p)) + assert(is_vector(cp)) let( v = is_num(v)? [v,v,v] : v ) is_undef(p)? ( len(v)==2? ( @@ -745,11 +836,14 @@ function scale(v=1, cp=[0,0,0], p) = // // // Usage: As Module -// xscale(x) ... +// xscale(x, ) ... // Usage: Scale Points -// scaled = xscale(x, p); +// scaled = xscale(x, p, ); // Usage: Get Affine Matrix -// mat = xscale(x); +// mat = xscale(x, , ); +// +// Topics: Affine, Matrices, Transforms, Scaling +// See Also: scale(), yscale(), zscale(), affine2d_scaling(), affine3d_scaling() // // Description: // Scales along the X axis by the scaling factor `x`. @@ -763,8 +857,9 @@ function scale(v=1, cp=[0,0,0], p) = // // Arguments: // x = Factor to scale by, along the X axis. -// cp = If given as a point, centers the scaling on the point `cp`. If given as a scalar, centers scaling on the point `[cp,0,0]` // p = A point, path, bezier patch, or VNF to scale, when called as a function. +// --- +// cp = If given as a point, centers the scaling on the point `cp`. If given as a scalar, centers scaling on the point `[cp,0,0]` // planar = If true, and `p` is not given, then the matrix returned is an affine2d matrix instead of an affine3d matrix. // // Example: As Module @@ -774,7 +869,9 @@ function scale(v=1, cp=[0,0,0], p) = // path = circle(d=50,$fn=12); // #stroke(path,closed=true); // stroke(xscale(2,p=path),closed=true); -module xscale(x=1, cp=0) { +module xscale(x=1, p, cp=0, planar) { + assert(is_undef(p), "Module form `xscale()` does not accept p= argument."); + assert(is_undef(planar), "Module form `xscale()` does not accept planar= argument."); cp = is_num(cp)? [cp,0,0] : cp; if (cp == [0,0,0]) { scale([x,1,1]) children(); @@ -783,7 +880,11 @@ module xscale(x=1, cp=0) { } } -function xscale(x=1, cp=0, p, planar=false) = +function xscale(x=1, p, cp=0, planar=false) = + assert(is_finite(x)) + assert(is_undef(p) || is_list(p)) + assert(is_finite(cp) || is_vector(cp)) + assert(is_bool(planar)) let( cp = is_num(cp)? [cp,0,0] : cp ) (planar || (!is_undef(p) && len(p)==2)) ? scale([x,1], cp=cp, p=p) @@ -793,11 +894,14 @@ function xscale(x=1, cp=0, p, planar=false) = // Function&Module: yscale() // // Usage: As Module -// yscale(y) ... +// yscale(y, ) ... // Usage: Scale Points -// scaled = yscale(y, p); +// scaled = yscale(y, p, ); // Usage: Get Affine Matrix -// mat = yscale(y); +// mat = yscale(y, , ); +// +// Topics: Affine, Matrices, Transforms, Scaling +// See Also: scale(), xscale(), zscale(), affine2d_scaling(), affine3d_scaling() // // Description: // Scales along the Y axis by the scaling factor `y`. @@ -811,8 +915,9 @@ function xscale(x=1, cp=0, p, planar=false) = // // Arguments: // y = Factor to scale by, along the Y axis. -// cp = If given as a point, centers the scaling on the point `cp`. If given as a scalar, centers scaling on the point `[0,cp,0]` // p = A point, path, bezier patch, or VNF to scale, when called as a function. +// --- +// cp = If given as a point, centers the scaling on the point `cp`. If given as a scalar, centers scaling on the point `[0,cp,0]` // planar = If true, and `p` is not given, then the matrix returned is an affine2d matrix instead of an affine3d matrix. // // Example: As Module @@ -822,7 +927,9 @@ function xscale(x=1, cp=0, p, planar=false) = // path = circle(d=50,$fn=12); // #stroke(path,closed=true); // stroke(yscale(2,p=path),closed=true); -module yscale(y=1, cp=0) { +module yscale(y=1, p, cp=0, planar) { + assert(is_undef(p), "Module form `yscale()` does not accept p= argument."); + assert(is_undef(planar), "Module form `yscale()` does not accept planar= argument."); cp = is_num(cp)? [0,cp,0] : cp; if (cp == [0,0,0]) { scale([1,y,1]) children(); @@ -831,7 +938,11 @@ module yscale(y=1, cp=0) { } } -function yscale(y=1, cp=0, p, planar=false) = +function yscale(y=1, p, cp=0, planar=false) = + assert(is_finite(y)) + assert(is_undef(p) || is_list(p)) + assert(is_finite(cp) || is_vector(cp)) + assert(is_bool(planar)) let( cp = is_num(cp)? [0,cp,0] : cp ) (planar || (!is_undef(p) && len(p)==2)) ? scale([1,y],p=p) @@ -841,11 +952,14 @@ function yscale(y=1, cp=0, p, planar=false) = // Function&Module: zscale() // // Usage: As Module -// zscale(z) ... +// zscale(z, ) ... // Usage: Scale Points -// scaled = zscale(z, p); +// scaled = zscale(z, p, ); // Usage: Get Affine Matrix -// mat = zscale(z); +// mat = zscale(z, ); +// +// Topics: Affine, Matrices, Transforms, Scaling +// See Also: scale(), xscale(), yscale(), affine2d_scaling(), affine3d_scaling() // // Description: // Scales along the Z axis by the scaling factor `z`. @@ -859,9 +973,9 @@ function yscale(y=1, cp=0, p, planar=false) = // // Arguments: // z = Factor to scale by, along the Z axis. -// cp = If given as a point, centers the scaling on the point `cp`. If given as a scalar, centers scaling on the point `[0,0,cp]` // p = A point, path, bezier patch, or VNF to scale, when called as a function. -// planar = If true, and `p` is not given, then the matrix returned is an affine2d matrix instead of an affine3d matrix. +// --- +// cp = If given as a point, centers the scaling on the point `cp`. If given as a scalar, centers scaling on the point `[0,0,cp]` // // Example: As Module // zscale(3) sphere(r=10); @@ -870,7 +984,8 @@ function yscale(y=1, cp=0, p, planar=false) = // path = xrot(90,p=path3d(circle(d=50,$fn=12))); // #trace_path(path); // trace_path(zscale(2,p=path)); -module zscale(z=1, cp=0) { +module zscale(z=1, p, cp=0) { + assert(is_undef(p), "Module form `zscale()` does not accept p= argument."); cp = is_num(cp)? [0,0,cp] : cp; if (cp == [0,0,0]) { scale([1,1,z]) children(); @@ -879,7 +994,10 @@ module zscale(z=1, cp=0) { } } -function zscale(z=1, cp=0, p) = +function zscale(z=1, p, cp=0) = + assert(is_finite(z)) + assert(is_undef(p) || is_list(p)) + assert(is_finite(cp) || is_vector(cp)) let( cp = is_num(cp)? [0,0,cp] : cp ) scale([1,1,z], cp=cp, p=p); @@ -891,6 +1009,8 @@ function zscale(z=1, cp=0, p) = // pt = mirror(v, p); // Usage: Get Reflection/Mirror Matrix // mat = mirror(v); +// Topics: Affine, Matrices, Transforms, Reflection, Mirroring +// See Also: xflip(), yflip(), zflip(), affine2d_mirror(), affine3d_mirror() // Description: // Mirrors/reflects across the plane or line whose normal vector is given in `v`. // * Called as the built-in module, mirrors all children across the line/plane. @@ -959,9 +1079,12 @@ function mirror(v, p) = // Usage: As Module // xflip() ... // Usage: As Function -// pt = xflip(, p); +// pt = xflip(p, ); // Usage: Get Affine Matrix -// pt = xflip(, ); +// pt = xflip(, ); +// +// Topics: Affine, Matrices, Transforms, Reflection, Mirroring +// See Also: mirror(), yflip(), zflip(), affine2d_mirror(), affine3d_mirror() // // Description: // Mirrors/reflects across the origin [0,0,0], along the X axis. If `x` is given, reflects across [x,0,0] instead. @@ -975,8 +1098,9 @@ function mirror(v, p) = // // Arguments: // x = The X coordinate of the plane of reflection. Default: 0 -// planar = If true, and p is not given, returns a 2D affine transformation matrix. Function use only. Default: False // p = If given, the point, path, patch, or VNF to mirror. Function use only. +// --- +// planar = If true, and p is not given, returns a 2D affine transformation matrix. Function use only. Default: False // // Example: // xflip() yrot(90) cylinder(d1=10, d2=0, h=20); @@ -987,9 +1111,18 @@ function mirror(v, p) = // xflip(x=-5) yrot(90) cylinder(d1=10, d2=0, h=20); // color("blue", 0.25) left(5) cube([0.01,15,15], center=true); // color("red", 0.333) yrot(90) cylinder(d1=10, d2=0, h=20); -module xflip(x=0) translate([x,0,0]) mirror([1,0,0]) translate([-x,0,0]) children(); +module xflip(p, x=0, planar) { + assert(is_undef(p), "Module form `zflip()` does not accept p= argument."); + assert(is_undef(planar), "Module form `zflip()` does not accept planar= argument."); + translate([x,0,0]) + mirror([1,0,0]) + translate([-x,0,0]) children(); +} -function xflip(x=0,planar=false,p) = +function xflip(p, x=0, planar=false) = + assert(is_finite(x)) + assert(is_bool(planar)) + assert(is_undef(p) || is_list(p)) let( v = RIGHT, n = planar? point2d(v) : v @@ -1006,9 +1139,12 @@ function xflip(x=0,planar=false,p) = // Usage: As Module // yflip() ... // Usage: As Function -// pt = yflip(, p); +// pt = yflip(p, ); // Usage: Get Affine Matrix -// pt = yflip(, ); +// pt = yflip(, ); +// +// Topics: Affine, Matrices, Transforms, Reflection, Mirroring +// See Also: mirror(), xflip(), zflip(), affine2d_mirror(), affine3d_mirror() // // Description: // Mirrors/reflects across the origin [0,0,0], along the Y axis. If `y` is given, reflects across [0,y,0] instead. @@ -1021,9 +1157,10 @@ function xflip(x=0,planar=false,p) = // * Called as a function without a `p` argument, and `planar=false`, returns the affine3d 4x4 mirror matrix. // // Arguments: -// y = The Y coordinate of the plane of reflection. Default: 0 -// planar = If true, and p is not given, returns a 2D affine transformation matrix. Function use only. Default: False // p = If given, the point, path, patch, or VNF to mirror. Function use only. +// y = The Y coordinate of the plane of reflection. Default: 0 +// --- +// planar = If true, and p is not given, returns a 2D affine transformation matrix. Function use only. Default: False // // Example: // yflip() xrot(90) cylinder(d1=10, d2=0, h=20); @@ -1034,9 +1171,18 @@ function xflip(x=0,planar=false,p) = // yflip(y=5) xrot(90) cylinder(d1=10, d2=0, h=20); // color("blue", 0.25) back(5) cube([15,0.01,15], center=true); // color("red", 0.333) xrot(90) cylinder(d1=10, d2=0, h=20); -module yflip(y=0) translate([0,y,0]) mirror([0,1,0]) translate([0,-y,0]) children(); +module yflip(p, y=0, planar) { + assert(is_undef(p), "Module form `yflip()` does not accept p= argument."); + assert(is_undef(planar), "Module form `yflip()` does not accept planar= argument."); + translate([0,y,0]) + mirror([0,1,0]) + translate([0,-y,0]) children(); +} -function yflip(y=0,planar=false,p) = +function yflip(p, y=0, planar=false) = + assert(is_finite(y)) + assert(is_bool(planar)) + assert(is_undef(p) || is_list(p)) let( v = BACK, n = planar? point2d(v) : v @@ -1053,10 +1199,13 @@ function yflip(y=0,planar=false,p) = // Usage: As Module // zflip() ... // Usage: As Function -// pt = zflip(, p); +// pt = zflip(p, ); // Usage: Get Affine Matrix // pt = zflip(); // +// Topics: Affine, Matrices, Transforms, Reflection, Mirroring +// See Also: mirror(), xflip(), yflip(), affine2d_mirror(), affine3d_mirror() +// // Description: // Mirrors/reflects across the origin [0,0,0], along the Z axis. If `z` is given, reflects across [0,0,z] instead. // * Called as the built-in module, mirrors all children across the line/plane. @@ -1067,8 +1216,8 @@ function yflip(y=0,planar=false,p) = // * Called as a function without a `p` argument, returns the affine3d 4x4 mirror matrix. // // Arguments: -// z = The Z coordinate of the plane of reflection. Default: 0 // p = If given, the point, path, patch, or VNF to mirror. Function use only. +// z = The Z coordinate of the plane of reflection. Default: 0 // // Example: // zflip() cylinder(d1=10, d2=0, h=20); @@ -1079,9 +1228,16 @@ function yflip(y=0,planar=false,p) = // zflip(z=-5) cylinder(d1=10, d2=0, h=20); // color("blue", 0.25) down(5) cube([15,15,0.01], center=true); // color("red", 0.333) cylinder(d1=10, d2=0, h=20); -module zflip(z=0) translate([0,0,z]) mirror([0,0,1]) translate([0,0,-z]) children(); +module zflip(p, z=0) { + assert(is_undef(p), "Module form `zflip()` does not accept p= argument."); + translate([0,0,z]) + mirror([0,0,1]) + translate([0,0,-z]) children(); +} -function zflip(z=0,p) = +function zflip(p, z=0) = + assert(is_finite(z)) + assert(is_undef(p) || is_list(p)) z==0? mirror([0,0,1],p=p) : move([0,0,z],p=mirror([0,0,1],p=move([0,0,-z],p=p))); @@ -1089,11 +1245,14 @@ function zflip(z=0,p) = // Function&Module: xyflip() // // Usage: As Module -// xyflip() ... +// xyflip() ... // Usage: As Function -// pt = xyflip(, p); +// pt = xyflip(p, ); // Usage: Get Affine Matrix -// pt = xyflip(); +// pt = xyflip(, ); +// +// Topics: Affine, Matrices, Transforms, Reflection, Mirroring +// See Also: mirror(), xflip(), yflip(), zflip(), xzflip(), yzflip(), affine2d_mirror(), affine3d_mirror() // // Description: // Mirrors/reflects across the origin [0,0,0], along the reflection plane where X=Y. If `cp` is given, the reflection plane passes through that point @@ -1106,8 +1265,8 @@ function zflip(z=0,p) = // * Called as a function without a `p` argument, and `planar=false`, returns the affine3d 4x4 mirror matrix. // // Arguments: -// cp = The centerpoint of the plane of reflection, given either as a point, or as a scalar distance away from the origin. // p = If given, the point, path, patch, or VNF to mirror. Function use only. +// cp = The centerpoint of the plane of reflection, given either as a point, or as a scalar distance away from the origin. // --- // planar = If true, and p is not given, returns a 2D affine transformation matrix. Function use only. Default: False // @@ -1131,12 +1290,15 @@ function zflip(z=0,p) = // Example(2D): Called as Function for a 2D matrix // mat = xyflip(planar=true); // multmatrix(mat) text("Foobar", size=20, halign="center"); -module xyflip(cp=0) { +module xyflip(p, cp=0, planar) { + assert(is_undef(p), "Module form `xyflip()` does not accept p= argument."); + assert(is_undef(planar), "Module form `xyflip()` does not accept planar= argument."); mat = xyflip(cp=cp); multmatrix(mat) children(); } -function xyflip(cp=0, p, planar=false) = +function xyflip(p, cp=0, planar=false) = + assert(is_finite(cp) || is_vector(cp)) let( v = unit([-1,1,0]), n = planar? point2d(v) : v @@ -1153,11 +1315,14 @@ function xyflip(cp=0, p, planar=false) = // Function&Module: xzflip() // // Usage: As Module -// xzflip() ... +// xzflip() ... // Usage: As Function -// pt = xzflip(, p); +// pt = xzflip(, p); // Usage: Get Affine Matrix -// pt = xzflip(); +// pt = xzflip(); +// +// Topics: Affine, Matrices, Transforms, Reflection, Mirroring +// See Also: mirror(), xflip(), yflip(), zflip(), xyflip(), yzflip(), affine2d_mirror(), affine3d_mirror() // // Description: // Mirrors/reflects across the origin [0,0,0], along the reflection plane where X=Y. If `cp` is given, the reflection plane passes through that point @@ -1169,8 +1334,8 @@ function xyflip(cp=0, p, planar=false) = // * Called as a function without a `p` argument, returns the affine3d 4x4 mirror matrix. // // Arguments: -// cp = The centerpoint of the plane of reflection, given either as a point, or as a scalar distance away from the origin. // p = If given, the point, path, patch, or VNF to mirror. Function use only. +// cp = The centerpoint of the plane of reflection, given either as a point, or as a scalar distance away from the origin. // // Example: // left(10) frame_ref(); @@ -1185,12 +1350,14 @@ function xyflip(cp=0, p, planar=false) = // Example: Called as Function // mat = xzflip(); // multmatrix(mat) frame_ref(); -module xzflip(cp=0) { +module xzflip(p, cp=0) { + assert(is_undef(p), "Module form `xzflip()` does not accept p= argument."); mat = xzflip(cp=cp); multmatrix(mat) children(); } -function xzflip(cp=0, p) = +function xzflip(p, cp=0) = + assert(is_finite(cp) || is_vector(cp)) let( n = unit([-1,0,1]) ) cp == 0 || cp==[0,0,0]? mirror(n, p=p) : let( @@ -1204,11 +1371,14 @@ function xzflip(cp=0, p) = // Function&Module: yzflip() // // Usage: As Module -// yzflip() ... +// yzflip() ... // Usage: As Function -// pt = yzflip(, p); +// pt = yzflip(p, ); // Usage: Get Affine Matrix -// pt = yzflip(); +// pt = yzflip(); +// +// Topics: Affine, Matrices, Transforms, Reflection, Mirroring +// See Also: mirror(), xflip(), yflip(), zflip(), xyflip(), xzflip(), affine2d_mirror(), affine3d_mirror() // // Description: // Mirrors/reflects across the origin [0,0,0], along the reflection plane where X=Y. If `cp` is given, the reflection plane passes through that point @@ -1220,8 +1390,8 @@ function xzflip(cp=0, p) = // * Called as a function without a `p` argument, returns the affine3d 4x4 mirror matrix. // // Arguments: -// cp = The centerpoint of the plane of reflection, given either as a point, or as a scalar distance away from the origin. // p = If given, the point, path, patch, or VNF to mirror. Function use only. +// cp = The centerpoint of the plane of reflection, given either as a point, or as a scalar distance away from the origin. // // Example: // left(10) frame_ref(); @@ -1236,12 +1406,14 @@ function xzflip(cp=0, p) = // Example: Called as Function // mat = yzflip(); // multmatrix(mat) frame_ref(); -module yzflip(cp=0) { +module yzflip(p, cp=0) { + assert(is_undef(p), "Module form `yzflip()` does not accept p= argument."); mat = yzflip(cp=cp); multmatrix(mat) children(); } -function yzflip(cp=0, p) = +function yzflip(p, cp=0) = + assert(is_finite(cp) || is_vector(cp)) let( n = unit([0,-1,1]) ) cp == 0 || cp==[0,0,0]? mirror(n, p=p) : let( @@ -1260,11 +1432,14 @@ function yzflip(cp=0, p) = // Function&Module: skew() // Usage: As Module -// skew(sxy=0, sxz=0, syx=0, syz=0, szx=0, szy=0) ... +// skew(, , , , , ) ... // Usage: As Function -// pts = skew(p, , , , , , ); +// pts = skew(p, , , , , , ); // Usage: Get Affine Matrix -// mat = skew(, , , , , , ); +// mat = skew(, , , , , , ); +// Topics: Affine, Matrices, Transforms, Skewing +// See Also: affine2d_skew(), affine3d_skew(), affine3d_skew_xy(), affine3d_skew_xz(), affine3d_skew_yz() +// // Description: // Skews geometry by the given skew factors. // * Called as the built-in module, skews all children. @@ -1276,6 +1451,8 @@ function yzflip(cp=0, p) = // * Called as a function without a `p` argument, and with `planar` false, returns the affine3d 4x4 skew matrix. // Each skew factor is a multiplier. For example, if `sxy=2`, then it will skew along the X axis by 2x the value of the Y axis. // Arguments: +// p = If given, the point, path, patch, or VNF to skew. Function use only. +// --- // sxy = Skew factor multiplier for skewing along the X axis as you get farther from the Y axis. Default: 0 // sxz = Skew factor multiplier for skewing along the X axis as you get farther from the Z axis. Default: 0 // syx = Skew factor multiplier for skewing along the Y axis as you get farther from the X axis. Default: 0 @@ -1307,14 +1484,22 @@ function yzflip(cp=0, p) = // Example(FlatSpin,VPD=175): Calling as a 3D Function // pts = skew(p=path3d(square(40,center=true)), szx=0.5, szy=0.3); // trace_path(close_path(pts), showpts=true); -module skew(sxy=0, sxz=0, syx=0, syz=0, szx=0, szy=0) +module skew(p, sxy=0, sxz=0, syx=0, syz=0, szx=0, szy=0) { + assert(is_undef(p), "Module form `skew()` does not accept p= argument.") multmatrix( affine3d_skew(sxy=sxy, sxz=sxz, syx=syx, syz=syz, szx=szx, szy=szy) ) children(); } function skew(p, sxy=0, sxz=0, syx=0, syz=0, szx=0, szy=0, planar=false) = + assert(is_finite(sxy)) + assert(is_finite(sxz)) + assert(is_finite(syx)) + assert(is_finite(syz)) + assert(is_finite(szx)) + assert(is_finite(szy)) + assert(is_bool(planar)) let( planar = planar || (is_list(p) && is_num(p.x) && len(p)==2), m = planar? [