From 1c952b907ef1fa99d644015fcf9ed17aff08d871 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Wed, 19 Mar 2025 22:41:56 -0400 Subject: [PATCH] descriptions additions/fixes --- attachments.scad | 60 ++++++++++++++++++++++++++++++++++++++++---- distributors.scad | 2 +- tests/test_math.scad | 12 +++++++++ 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/attachments.scad b/attachments.scad index eeb642da..bf210923 100644 --- a/attachments.scad +++ b/attachments.scad @@ -5039,7 +5039,6 @@ function parent() = // Module: restore() // Synopsis: Restores transformation state and attachment geometry from a description -// SynTags: Trans // Topics: Transforms, Attachments, Descriptions // See Also: parent() // Usage: @@ -5072,7 +5071,7 @@ module restore(desc) } } -// Function desc_point() +// Function: desc_point() // Synopsis: Computes the location in the current context of an anchor point from an attachable description // Topics: Descriptions, Attachments // See Also: parent(), desc_dist() @@ -5097,7 +5096,7 @@ module restore(desc) // attach(TOP+BACK+RIGHT, BOT) // stroke([[0,0,0], desc_point(desc,TOP+FWD+RIGHT)],width=.5,color="red"); function desc_point(desc, anchor=CENTER) = - is_undef(desc) ? linear_solve($transform, [0,0,0,0]) + is_undef(desc) ? linear_solve($transform, [0,0,0,1]) : let( anch = _find_anchor(anchor, desc[1]), T = linear_solve($transform, desc[0]) @@ -5105,8 +5104,39 @@ function desc_point(desc, anchor=CENTER) = apply(T, anch[1]); +// Function: desc_dir() +// Synopsis: Computes the direction in the current context of a direction from an attachable description +// Topics: Descriptions, Attachment +// See Also: parent(), desc_point() +// Usage: +// dir = desc_dir([desc],[anchor]); +// Description: +// Computes the direction in the current context of an anchor direction from an attachable description. If you don't give a description +// then the direction is computed relative to global world coordinates. +// Arguments: +// desc = Description to use. Default: use the global world coordinate system +// anchor = Anchor to get the direction from. Default: UP +// Example(3D): Here we don't give a description so the reference is to the global world coordinate system, and we don't give a direction, so the default of UP applies. This lets the cylinder be placed so it is horizontal in world coordinates. +// prismoid(20,10,h=15) +// attach(RIGHT,BOT) cuboid([4,4,15]) +// position(TOP) cyl(d=12,h=5,orient=desc_dir(),anchor=BACK); +// Example(3D,VPR=[78.1,0,76.1]): Here we use the description of the prismoid, which lets us place the rod so that it is oriented in the direction of the prismoid's face. +// prismoid(20,10,h=15) let(pris=parent()) +// attach(RIGHT,BOT) cuboid([4,4,15]) +// position(TOP) cyl(d=2,h=15,orient=desc_dir(pris,FWD),anchor=LEFT); +function desc_dir(desc, anchor=UP) = + let( + T = is_undef(desc) ? matrix_inverse($transform) + : linear_solve($transform, desc[0]), + dir = is_undef(desc) ? anchor + : let(anch = _find_anchor(anchor, desc[1])) + anch[2] + ) + apply(T, dir)-apply(T,CENTER); + -// Function desc_dist() + +// Function: desc_dist() // Synopsis: Computes the distance between two points specified by attachable descriptions // Topics: Descriptions, Attachments // See Also: parent(), desc_point() @@ -5116,7 +5146,7 @@ function desc_point(desc, anchor=CENTER) = // Description: // Computes the distance between two points specified using attachable descriptions and optional anchor // points. If you omit the anchor point(s) then the computation uses the CENTER anchor. -// Example: Computes the distance between a point on each cube. +// Example(3D): Computes the distance between a point on each cube. // cuboid(10) let(desc=parent()) // right(15) cuboid(10) // echo(desc_dist(parent(),TOP+RIGHT+BACK, desc, TOP+LEFT+FWD)); @@ -5134,5 +5164,25 @@ function desc_dist(desc1,anchor1=CENTER, desc2, anchor2=CENTER)= norm(pt1-pt2); +// Function: trans_desc() +// Synopsis: Applies a transformation matrix to a description +// Topics: Descriptions, Attachments +// See Also: parent() +// Usage: +// new_desc = trans_desc(T, desc); +// Description: +// Applies a transformation matrix to a description, producing a new transformed description as +// output. The transformation matrix can be produced using any of the usual transform commands. +// The resulting description is as if it was produced from an object that had the transformation +// applied. You can also give a list of transformation matrices, in which case the output is +// a list of descriptions. +// Arguments: +// T = transformation or list of transformations to apply (a 4x4 matrix or list of them) +// desc = description to transform + +function trans_desc(T,desc) = + is_consistent(T, ident(4)) ? [for(t=T) [t*desc[0], desc[1]]] + : is_matrix(T,4,4) ? [T*desc[0], desc[1]] + : assert(false,"T must be a 4x4 matrix or list of 4x4 matrices"); // vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap diff --git a/distributors.scad b/distributors.scad index 4d7fa7eb..53f7be6c 100644 --- a/distributors.scad +++ b/distributors.scad @@ -1180,7 +1180,7 @@ function zrot_copies(rots=[], cp=[0,0,0], n, sa=0, r, d, subrot=true, p=_NO_ARG) // // // Description: -// When called as a module, evenly distributes n duplicate children around an ovoid arc on the XY plane. +// When called as a module, evenly distributes n duplicate children around an elliptical arc on the XY plane. // When called as a function, *without* a `p=` argument, returns a list of transformation matrices, one for each copy. // When called as a function, *with* a `p=` argument, returns a list of transformed copies of `p=`. // diff --git a/tests/test_math.scad b/tests/test_math.scad index 58d67cb7..bcd161f6 100644 --- a/tests/test_math.scad +++ b/tests/test_math.scad @@ -124,6 +124,18 @@ module test_modang() { test_modang(); +module test_mean_angle() { + assert_equal(mean_angle(33,95), 64); + assert_equal(mean_angle(355,5), 0); + assert_equal(mean_angle(-270, 180), 135); + assert_equal(mean_angle(155,155+180), 155+90); + assert_equal(mean_angle(155+180,155), posmod(155+180+90,360)); + assert_equal(mean_angle(-75,-75+180), -75+90); + assert_equal(mean_angle(-75+180,-75), -75+90+180); +} +test_mean_angle(); + + module test_sqr() { assert_equal(sqr(-3), 9); assert_equal(sqr(0), 0);