omdl  v0.9.5
OpenSCAD Mechanical Design Library
extrude.scad
Go to the documentation of this file.
1 //! Shape extrusion tools.
2 /***************************************************************************//**
3  \file
4  \author Roy Allen Sutton
5  \date 2015-2023
6 
7  \copyright
8 
9  This file is part of [omdl] (https://github.com/royasutton/omdl),
10  an OpenSCAD mechanical design library.
11 
12  The \em omdl is free software; you can redistribute it and/or modify
13  it under the terms of the [GNU Lesser General Public License]
14  (http://www.gnu.org/licenses/lgpl.html) as published by the Free
15  Software Foundation; either version 2.1 of the License, or (at
16  your option) any later version.
17 
18  The \em omdl is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  Lesser General Public License for more details.
22 
23  You should have received a copy of the GNU Lesser General Public
24  License along with the \em omdl; if not, write to the Free Software
25  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26  02110-1301, USA; or see <http://www.gnu.org/licenses/>.
27 
28  \details
29 
30  \amu_define group_name (Extrude)
31  \amu_define group_brief (Shape extrusion tools.)
32 
33  \amu_include (include/amu/pgid_path_pstem_pg.amu)
34 *******************************************************************************/
35 
36 //----------------------------------------------------------------------------//
37 // group and macros.
38 //----------------------------------------------------------------------------//
39 
40 /***************************************************************************//**
41  \amu_include (include/amu/group_in_parent_start.amu)
42  \amu_include (include/amu/includes_required.amu)
43 
44  \amu_define image_view (diag)
45 
46  \amu_define group_id (${parent})
47  \amu_include (include/amu/scope_diagrams_3d_in_group.amu)
48 
49  \amu_define group_id (${group})
50  \amu_include (include/amu/scope_diagrams_3d_in_group.amu)
51 
52  \amu_include (include/amu/scope_diagram_3d_object.amu)
53 *******************************************************************************/
54 
55 //----------------------------------------------------------------------------//
56 
57 //! Translate, rotate, and revolve a 2d shape about the z-axis.
58 /***************************************************************************//**
59  \param r <decimal> The rotation radius.
60  \param pa <decimal> The profile pitch angle in degrees.
61  \param ra <decimal> The rotation sweep angle in degrees.
62 
63  \details
64 
65  \amu_eval ( object=extrude_rotate_tr ${object_ex_diagram_3d} )
66 *******************************************************************************/
67 module extrude_rotate_tr
68 (
69  r,
70  pa = 0,
71  ra = 360
72 )
73 {
74  rotate_extrude(angle = ra)
75  translate([r, 0])
76  rotate([0, 0, pa])
77  children();
78 }
79 
80 //! Translate, rotate, scale, and revolve a 2d shape about the z-axis.
81 /***************************************************************************//**
82  \copydetails extrude_rotate_tr()
83 
84  \param s <decimal-list-2 | decimal> The start and end scale factor.
85  A list [s1, s2] of decimals or a single decimal for (s1=s2)
86  \param m <integer> The facet number mode (either \b 0 or \b 1).
87  With \p m = \b 1, fewer scaled-steps are generated during
88  the revolution.
89 
90  \details
91 
92  When the parameter \p s is not specified, the shape profile is
93  revolved using extrude_rotate_tr(). When the parameter \p s is
94  specified, the shape profile is scaled from \p s1 to \p s2 along
95  the revolution path.
96 
97  \amu_eval ( object=extrude_rotate_trs ${object_ex_diagram_3d} )
98 *******************************************************************************/
99 module extrude_rotate_trs
100 (
101  r,
102  pa = 0,
103  ra = 360,
104 
105  s,
106  m = 0
107 )
108 {
109  if ( is_undef(s) )
110  {
111  extrude_rotate_tr(r=r, pa=pa, ra=ra)
112  children();
113  }
114  else
115  {
116  sd = is_scalar(s) ? s : 1;
117  s1 = defined_e_or(s, 0, sd);
118  s2 = defined_e_or(s, 1, sd);
119 
120  sn = (m == 0) ? ceil(get_fn(r) * ra/360)
121  : ceil(sqrt(get_fn(r) * ra/360));
122 
123  sa = ra/sn; // section angle
124  ss = (s2-s1)/sn; // uniform section scale
125  so = 360*eps; // section overlap
126 
127  for (f=[0:sn-1])
128  rotate(sa * f - so/2)
129  rotate_extrude(angle = sa + so)
130  translate([r, 0])
131  scale(s1 + ss * f)
132  rotate([0, 0, pa])
133  children();
134  }
135 }
136 
137 //! Translate, rotate, and revolve a 2d shape about the z-axis with linear elongation.
138 /***************************************************************************//**
139  \copydetails extrude_rotate_tr()
140 
141  \param l <decimal-list-2 | decimal> The elongation length.
142  A list [x, y] of decimals or a single decimal for (x=y)
143  \param m <integer> The section render mode. An 8-bit encoded integer
144  that indicates the revolution sections to render.
145  Bit values \b 1 enables the corresponding section and bit values
146  \b 0 are disabled. Sections are assigned to the bit position in
147  counter-clockwise order.
148 
149  \details
150 
151  When the parameter \p l is not specified, the shape profile is
152  revolved using extrude_rotate_tr(). When the parameter \p l is
153  specified, the shape profile may be linearly extruded along the the
154  \em x-axis and \em y-axis, with the linear extrusion lengths
155  specified by \p l, and is revolved 90 degrees to transition between
156  the axes. In this mode, the parameter \p ra is defined to be 90 for
157  all corners and the parameter \p m controls which of the eight path
158  sections to render during the 360 degree revolution.
159 
160  \amu_eval ( object=extrude_rotate_trl ${object_ex_diagram_3d} )
161 *******************************************************************************/
162 module extrude_rotate_trl
163 (
164  r,
165  pa = 0,
166  ra = 360,
167 
168  l,
169  m = 255
170 )
171 {
172  if ( is_undef(l) )
173  {
174  extrude_rotate_tr(r=r, pa=pa, ra=ra)
175  children();
176  }
177  else
178  {
179  ld = is_scalar(l) ? l : 0;
180  lx = defined_e_or(l, 0, ld);
181  ly = defined_e_or(l, 1, ld);
182 
183  // corner rotation
184  for
185  (
186  i = [
187  [+lx/2, +ly/2, 0, 1],
188  [-lx/2, +ly/2, 90, 3],
189  [-lx/2, -ly/2, 180, 5],
190  [+lx/2, -ly/2, 270, 7]
191  ]
192  )
193  if ( binary_bit_is(m, i[3], 1) )
194  {
195  translate([i[0], i[1], 0])
196  rotate([0, 0, i[2]])
197  extrude_rotate_tr(r=r, pa=pa, ra=90)
198  children();
199  }
200 
201  // linear extrusion
202  for
203  (
204  i = [
205  [ +r +lx/2, +ly/2, 0, ly, 0],
206  [ -lx/2, +r +ly/2, 90, lx, 2],
207  [ -r -lx/2, -ly/2, 180, ly, 4],
208  [ lx/2, -r -ly/2, 270, lx, 6]
209  ]
210  )
211  if ( binary_bit_is(m, i[4], 1) )
212  {
213  translate([i[0], i[1], 0])
214  rotate([90, 0, i[2]])
215  translate([0, 0, -eps])
216  linear_extrude(height=i[3] + eps*2)
217  rotate([0, 0, pa])
218  children();
219  }
220  }
221 }
222 
223 //! Linearly extrude a 2d shape with uniformly-spaced profile scaling.
224 /***************************************************************************//**
225  \param h <datastruct | decimal> A data structure or a single decimal.
226  \param center <boolean> Center extrusion about origin.
227  \param c <boolean> conditional.
228  \param ha <decimal> An extrusion height adjustment value.
229 
230  \details
231 
232  When \p c is \b true, apply the transformation to the children
233  objects, otherwise return the children unmodified.
234 
235  <b>Data structure syntax</b>
236 
237  h[n] | type | description
238  :----:|:-----------------:|:---------------------------------------
239  0 | <decimal> | total extrusion height
240  1 | <decimal-list-n> | list of one or more scale factors
241 
242  Each scale factor can be either a single decimal or a list of two
243  decimals to scale \b x and \b y independently. When the scale
244  factor is a single decimal, both dimensions are scaled equally.
245 
246  When \p h is a decimal, or a list with a single decimal, the shape
247  is linearly extruded to the height specified by the decimal value
248  without scaling. When \p h is a list, the first element of \p h
249  specifies the extrusion height and the second element of \p h
250  specifies the scale factor, or scale factors in the case that the
251  second element is a list, When s list of scaling factors is
252  specified, the scale factors are applied sequentially with uniform
253  spacing along the linear extrusion height.
254 
255  \note The parameter \p ha may be used to add (small) values to the
256  extrusion height to construct overlapping shapes when multiple
257  extrusions are stacked.
258 
259  \amu_eval ( object=extrude_linear_uss ${object_ex_diagram_3d} )
260 *******************************************************************************/
261 module extrude_linear_uss
262 (
263  h,
264  center = false,
265  c = true,
266  ha = 0
267 )
268 {
269  if ( is_undef(h) || (c == false) )
270  {
271  children();
272  }
273  else if ( is_scalar(h) )
274  {
275  linear_extrude(height=h + ha, center=center)
276  children();
277  }
278  else
279  {
280  ht = defined_e_or(h, 0, 1) + ha; // section height
281  ss = defined_e_or(h, 1, 1); // section scale steps
282 
283  su = is_list(ss) ? ss : [ss]; // make sure 'ss' is a list
284 
285  // handle single scale section case
286  sv = (len(su) == 1) ? concat(su, su) : su;
287 
288  sn = len(sv); // section count
289  sz = ht/(sn-1); // uniform section size
290  so = eps; // section overlap
291 
292  translate(center==true ? [0, 0, -ht/2] : origin3d)
293  for (f=[0:sn-2])
294  {
295  cl = is_list(sv[f]);
296  nl = is_list(sv[f+1]);
297 
298  // handle one, two, and mixed-dimensional scaling
299  es = cl && nl ? [first(sv[f+1])/first(sv[f]), second(sv[f+1])/second(sv[f])]
300  : !cl && nl ? [first(sv[f+1])/ sv[f] , second(sv[f+1])/ sv[f] ]
301  : sv[f+1]/sv[f];
302 
303  translate([0, 0, sz * f - so/2])
304  linear_extrude(height=sz + so, scale=es)
305  scale(sv[f])
306  children();
307  }
308  }
309 }
310 
311 //! Linearly extrude a 2d shape with multi-segment uniformly-spaced profile scaling.
312 /***************************************************************************//**
313  \param h <datastruct-list-n | decimal> A data structure or a single decimal.
314  \param center <boolean> Center extrusion about origin.
315  \param c <boolean> conditional.
316 
317  \details
318 
319  When \p c is \b true, apply the transformation to the children
320  objects, otherwise return the children unmodified.
321 
322  <b>Data structure syntax</b>
323 
324  The scaled extrusion can be divided across as many segments \em (n)
325  as desired with each being specified by a data structure using the
326  syntax of the function extrude_linear_uss(). Scaling for multiple
327  segments are placed in a list and each segment is processed
328  sequentially, in the listed order, until all \em n-segments have
329  been linearly extruded and stacked.
330 
331  \note As with extrude_linear_uss(), each scale factor can be either
332  a single decimal or a list of two decimals to scale \b x and \b y
333  independently. When the scale factor is a single decimal, both
334  dimensions are scaled equally.
335 
336  \amu_eval ( object=extrude_linear_mss ${object_ex_diagram_3d} )
337 *******************************************************************************/
338 module extrude_linear_mss
339 (
340  h,
341  center = false,
342  c = true
343 )
344 {
345  if ( is_undef(h) || (c == false) )
346  {
347  children();
348  }
349  else if ( is_scalar(h) )
350  {
351  linear_extrude(height=h, center=center)
352  children();
353  }
354  else
355  {
356  // calculate total height of all sections
357  hv = [for (e=h) is_list(e) ? first(e) : e];
358  ht = sum( hv );
359 
360  sn = len(hv); // section count
361  so = eps; // section overlap
362 
363  translate(center==true ? [0, 0, -ht/2] : origin3d)
364  for (f=[0:sn-1])
365  {
366  // calculate total height of prior sections
367  tv = (f == 0) ? [0] : [ for (g=[0:f-1]) is_list(h[g]) ? first(h[g]) : h[g] ];
368  tt = sum( tv );
369 
370  // extrude current section
371  translate([0, 0, tt - so/2])
372  extrude_linear_uss(h=h[f], ha=so, center=false)
373  children();
374  }
375  }
376 }
377 
378 //! @}
379 //! @}
380 
381 //----------------------------------------------------------------------------//
382 // openscad-amu auxiliary scripts
383 //----------------------------------------------------------------------------//
384 
385 /*
386 BEGIN_SCOPE diagram;
387  BEGIN_OPENSCAD;
388  include <omdl-base.scad>;
389 
390  shape = "extrude_rotate_tr";
391  $fn = 36;
392 
393  if (shape == "extrude_rotate_tr")
394  extrude_rotate_tr( r=50, pa=45, ra=270 ) square( [10,5], center=true );
395  if (shape == "extrude_rotate_trs")
396  extrude_rotate_trs( r=50, pa=45, ra=180, s=[1, 3] ) circle( 5, center=true );
397  else if (shape == "extrude_rotate_trl")
398  extrude_rotate_trl( r=25, l=[5, 50], pa=45, m=31 ) square( [10,5], center=true );
399  else if (shape == "extrude_linear_uss")
400  extrude_linear_uss( [10, [1,1/2,[1,1/2],[1/4,1/2]]], center=true) circle( d=10 );
401  else if (shape == "extrude_linear_mss")
402  extrude_linear_mss( h=[[10, [1.25, 1]], 20, [35, [for (i=[90:-1:10]) sin(i)]]], center=true) circle(15);
403  END_OPENSCAD;
404 
405  BEGIN_MFSCRIPT;
406  include --path "${INCLUDE_PATH}" {var_init,var_gen_png2eps}.mfs;
407 
408  views name "views" views "diag";
409  defines name "shapes" define "shape"
410  strings "
411  extrude_rotate_tr
412  extrude_rotate_trs
413  extrude_rotate_trl
414  extrude_linear_uss
415  extrude_linear_mss
416  ";
417  variables add_opts_combine "views shapes";
418  variables add_opts "--viewall --autocenter --view=axes";
419 
420  include --path "${INCLUDE_PATH}" scr_make_mf.mfs;
421  END_MFSCRIPT;
422 END_SCOPE;
423 */
424 
425 //----------------------------------------------------------------------------//
426 // end of file
427 //----------------------------------------------------------------------------//
origin3d
<point-3d> The origin point coordinate in 3-dimensional Euclidean space.
Definition: constants.scad:425
eps
<decimal> Epsilon, small distance to deal with overlapping shapes.
Definition: constants.scad:195
function binary_bit_is(v, b, t=1)
Test if a binary bit position of an integer value equals a test bit.
function defined_e_or(v, i, d)
Return an element of an iterable when it exists or a default value otherwise.
function second(v)
Return the second element of an iterable value.
function first(v)
Return the first element of an iterable value.
function sum(v, i1, i2)
Compute the sum of a list of numbers.
function is_scalar(v)
Test if a value is a single non-iterable value.
function get_fn(r)
Return facets number for the given arc radius.
module extrude_rotate_trs(r, pa=0, ra=360, s, m=0)
Translate, rotate, scale, and revolve a 2d shape about the z-axis.
Definition: extrude.scad:494
module extrude_rotate_tr(r, pa=0, ra=360)
Translate, rotate, and revolve a 2d shape about the z-axis.
Definition: extrude.scad:457
module extrude_linear_mss(h, center=false, c=true)
Linearly extrude a 2d shape with multi-segment uniformly-spaced profile scaling.
Definition: extrude.scad:748
module extrude_rotate_trl(r, pa=0, ra=360, l, m=255)
Translate, rotate, and revolve a 2d shape about the z-axis with linear elongation.
Definition: extrude.scad:562
module extrude_linear_uss(h, center=false, c=true, ha=0)
Linearly extrude a 2d shape with uniformly-spaced profile scaling.
Definition: extrude.scad:666
function angle(a, from=angle_unit_default, to=angle_unit_base)
Convert an angle from some units to another.