Rework of docs for transforms.scad and affine.scad. Fix for #439.

This commit is contained in:
Garth Minette 2021-02-26 13:07:11 -08:00
parent 1ff9bebcf2
commit 2b9a2b2da7
3 changed files with 591 additions and 282 deletions

View file

@ -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,6 +140,12 @@ 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.
@ -141,6 +158,12 @@ 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 a line that is unindented after the comment.
@ -308,15 +331,30 @@ Which outputs Markdown code that renders like:
> 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
------------
@ -369,7 +407,14 @@ 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:
@ -377,7 +422,15 @@ Which outputs Markdown code that renders like:
> 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()](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.
> `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
--------------
@ -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
@ -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.
> -------------- | --------------------
> `"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,12 +801,12 @@ 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.
>

View file

@ -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,<dim>);
// 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,6 +186,7 @@ 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
@ -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, <reverse>);
// map = affine3d_frame_map(x=VECTOR1, z=VECTOR2, <reverse>);
// map = affine3d_frame_map(y=VECTOR1, z=VECTOR2, <reverse>);
// 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(<sxy>, <sxz>, <syx>, <syz>, <szx>, <szy>);
// 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:

View file

@ -12,15 +12,20 @@
// Function&Module: move()
// Aliases: translate()
//
// Usage: As Module
// move(<x>, <y>, <z>) ...
// move(<x=>, <y=>, <z=>) ...
// move(v) ...
// Usage: Translate Points
// pts = move(v, p);
// pts = move(<x>, <y>, <z>, p);
// pts = move(<x=>, <y=>, <z=>, p=);
// Usage: Get Translation Matrix
// mat = move(v);
// mat = move(<x=>, <y=>, <z=>);
//
// 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, <cp>, <reverse>) ...
// rot([X,Y,Z], <cp>, <reverse>) ...
// rot(a, v, <cp>, <reverse>) ...
// rot(from, to, <a>, <reverse>) ...
// Usage: As a Module
// rot(a, <cp>, <reverse>) {...}
// rot([X,Y,Z], <cp>, <reverse>) {...}
// rot(a, v, <cp>, <reverse>) {...}
// rot(from, to, <a>, <reverse>) {...}
// Usage: Get Transformation Matrix
// pts = rot(a, <cp=>, <reverse=>, <planar=>);
// pts = rot([X,Y,Z], <cp=>, <reverse=>, <planar=>);
// pts = rot(a, v, <cp=>, <reverse=>, <planar=>);
// pts = rot(from=, to=, <a=>, <reverse=>, <planar=>);
// Usage: As a Function
// pts = rot(a, p=, <cp=>, <reverse=>);
// pts = rot([X,Y,Z], p=, <cp=>, <reverse=>);
// pts = rot(a, v, p=, <cp=>, <reverse=>);
// pts = rot(<a>, from=, to=, p=, <reverse=>);
//
// 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, <cp>) ...
// xrot(a, <cp=>) ...
// Usage: Rotate Points
// rotated = xrot(a, p, <cp>);
// rotated = xrot(a, p, <cp=>);
// Usage: Get Rotation Matrix
// mat = xrot(a, <cp>);
// mat = xrot(a, <cp=>);
//
// 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, <cp>) ...
// yrot(a, <cp=>) ...
// Usage: Rotate Points
// rotated = yrot(a, p, <cp>);
// rotated = yrot(a, p, <cp=>);
// Usage: Get Rotation Matrix
// mat = yrot(a, <cp>);
// mat = yrot(a, <cp=>);
//
// 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, <cp>) ...
// zrot(a, <cp=>) ...
// Usage: Rotate Points
// rotated = zrot(a, p, <cp>);
// rotated = zrot(a, p, <cp=>);
// Usage: Get Rotation Matrix
// mat = zrot(a, <cp>);
// mat = zrot(a, <cp=>);
//
// 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, <cp>) ...
// xyrot(a, <cp=>) ...
// Usage: Rotate Points
// rotated = xyrot(a, p, <cp>);
// rotated = xyrot(a, p, <cp=>);
// Usage: Get Rotation Matrix
// mat = xyrot(a, <cp>);
// mat = xyrot(a, <cp=>);
//
// 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, <cp>) ...
// xzrot(a, <cp=>) ...
// Usage: Rotate Points
// rotated = xzrot(a, p, <cp>);
// rotated = xzrot(a, p, <cp=>);
// Usage: Get Rotation Matrix
// mat = xzrot(a, <cp>);
// mat = xzrot(a, <cp=>);
//
// 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, <cp>) ...
// yzrot(a, <cp=>) ...
// Usage: Rotate Points
// rotated = yzrot(a, p, <cp>);
// rotated = yzrot(a, p, <cp=>);
// Usage: Get Rotation Matrix
// mat = yzrot(a, <cp>);
// mat = yzrot(a, <cp=>);
//
// 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, <cp>) ...
// xyzrot(a, <cp=>) ...
// Usage: Rotate Points
// rotated = xyzrot(a, p, <cp>);
// rotated = xyzrot(a, p, <cp=>);
// Usage: Get Rotation Matrix
// mat = xyzrot(a, <cp>);
// mat = xyzrot(a, <cp=>);
//
// 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, <cp>) ...
// scale([X,Y,Z], <cp>) ...
// scale(SCALAR) ...
// scale([X,Y,Z]) ...
// Usage: Scale Points
// pts = scale(v, p, <cp>);
// pts = scale(v, p, <cp=>);
// Usage: Get Scaling Matrix
// mat = scale(v, <cp>);
// mat = scale(v, <cp=>);
// 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, <cp=>) ...
// Usage: Scale Points
// scaled = xscale(x, p);
// scaled = xscale(x, p, <cp=>);
// Usage: Get Affine Matrix
// mat = xscale(x);
// mat = xscale(x, <cp=>, <planar=>);
//
// 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, <cp=>) ...
// Usage: Scale Points
// scaled = yscale(y, p);
// scaled = yscale(y, p, <cp=>);
// Usage: Get Affine Matrix
// mat = yscale(y);
// mat = yscale(y, <cp=>, <planar=>);
//
// 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, <cp=>) ...
// Usage: Scale Points
// scaled = zscale(z, p);
// scaled = zscale(z, p, <cp=>);
// Usage: Get Affine Matrix
// mat = zscale(z);
// mat = zscale(z, <cp=>);
//
// 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(<x>) ...
// Usage: As Function
// pt = xflip(<x>, p);
// pt = xflip(p, <x>);
// Usage: Get Affine Matrix
// pt = xflip(<x>, <planar>);
// pt = xflip(<x>, <planar=>);
//
// 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(<y>) ...
// Usage: As Function
// pt = yflip(<y>, p);
// pt = yflip(p, <y>);
// Usage: Get Affine Matrix
// pt = yflip(<y>, <planar>);
// pt = yflip(<y>, <planar=>);
//
// 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(<z>) ...
// Usage: As Function
// pt = zflip(<z>, p);
// pt = zflip(p, <z>);
// Usage: Get Affine Matrix
// pt = zflip(<z>);
//
// 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(<x>) ...
// xyflip(<cp>) ...
// Usage: As Function
// pt = xyflip(<x>, p);
// pt = xyflip(p, <cp>);
// Usage: Get Affine Matrix
// pt = xyflip(<x>);
// pt = xyflip(<cp>, <planar=>);
//
// 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(<x>) ...
// xzflip(<cp>) ...
// Usage: As Function
// pt = xzflip(<x>, p);
// pt = xzflip(<cp>, p);
// Usage: Get Affine Matrix
// pt = xzflip(<x>);
// pt = xzflip(<cp>);
//
// 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(<x>) ...
// yzflip(<x=>) ...
// Usage: As Function
// pt = yzflip(<x>, p);
// pt = yzflip(p, <x=>);
// Usage: Get Affine Matrix
// pt = yzflip(<x>);
// pt = yzflip(<x=>);
//
// 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(<sxy=>, <sxz=>, <syx=>, <syz=>, <szx=>, <szy=>) ...
// Usage: As Function
// pts = skew(p, <sxy>, <sxz>, <syx>, <syz>, <szx>, <szy>);
// pts = skew(p, <sxy=>, <sxz=>, <syx=>, <syz=>, <szx=>, <szy=>);
// Usage: Get Affine Matrix
// mat = skew(<sxy>, <sxz>, <syx>, <syz>, <szx>, <szy>, <planar>);
// mat = skew(<sxy=>, <sxz=>, <syx=>, <syz=>, <szx=>, <szy=>, <planar=>);
// 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? [