omdl  v0.9.5
OpenSCAD Mechanical Design Library
primitive.scad
Go to the documentation of this file.
1 //! Drafting base functions and primitives.
2 /***************************************************************************//**
3  \file
4  \author Roy Allen Sutton
5  \date 2019
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 (Primitives)
31  \amu_define group_brief (Drafting base functions and primitives.)
32 
33  \amu_include (include/amu/pgid_path_pstem_g.amu)
34 *******************************************************************************/
35 
36 //----------------------------------------------------------------------------//
37 // group and macros.
38 //----------------------------------------------------------------------------//
39 
40 /***************************************************************************//**
41  \amu_include (include/amu/group_in_parent_start.amu)
42 
43  \amu_include (include/amu/scope_diagram_2d_object.amu)
44 *******************************************************************************/
45 
46 //----------------------------------------------------------------------------//
47 
48 //! \name Layers
49 //! @{
50 
51 //! Check if any identified layers are active.
52 /***************************************************************************//**
53  \param layers <string-list> The list of layer names.
54 
55  \returns <boolean> \b true if any identified layer is active as
56  indicated by \ref draft_layers_show.
57 *******************************************************************************/
59 (
60  layers = draft_get_config("layers-default")
61 ) = exists( is_list(layers) ? layers : [layers], draft_layers_show, true );
62 
63 //! @}
64 
65 //----------------------------------------------------------------------------//
66 
67 //! \name Placement
68 //! @{
69 
70 //! \cond DOXYGEN_SHOULD_SKIP_THIS
71 
72 //! Get sheet, sheet-frame, or sheet-zone reference window or limits.
73 /***************************************************************************//**
74  \param rx <string> A sheet x-axis zone reference identifier.
75  \param ry <string> A sheet y-axis zone reference identifier.
76 
77  \param ix <integer> A sheet x-axis zone reference index.
78  \param iy <integer> A sheet x-axis zone reference index.
79 
80  \param limits <boolean> Return window limits rather than coordinates.
81  \param frame <boolean> Use frame when zone not specified.
82 
83  \returns <datastruct> The reference window.
84 
85  \details
86 
87  The returned datastruct will be one of the following forms:
88 
89  limits | description | data type
90  :------:|:--------------------------------|:------------------------
91  true | [[xmin, xmax], [ymin, ymax]] | <decimal-list-2-list-2>
92  false | [p0, p1, p2, p3], pn=[x,y] | <point-2d-list-4>
93 
94  The windows coordinate points [p0, p1, p2, p3] are clockwise
95  ordered with p0=[xmin, ymin].
96 
97  \private
98 *******************************************************************************/
99 function draft_sheet_get_window
100 (
101  rx,
102  ry,
103  ix,
104  iy,
105  limits = false,
106  frame = false
107 ) =
108  let
109  (
110  //
111  // get configuration values (scale all lengths)
112  //
113 
114  // sheet size
115  sdx = draft_get_sheet_size(ci="sdx") * draft_sheet_scale,
116  sdy = draft_get_sheet_size(ci="sdy") * draft_sheet_scale,
117 
118  // sheet layout
119  sll = draft_get_sheet_config(ci="sll"),
120 
121  // sheet frame and zone margins
122  smx = draft_get_sheet_config(ci="smx") * draft_sheet_scale,
123  smy = draft_get_sheet_config(ci="smy") * draft_sheet_scale,
124  szm = draft_get_sheet_config(ci="szm") * draft_sheet_scale,
125 
126  // reference zone labels
127  zox = draft_get_sheet_config(ci="zox"),
128  zoy = draft_get_sheet_config(ci="zoy"),
129  zlx = draft_get_sheet_config(ci="zlx"),
130  zly = draft_get_sheet_config(ci="zly"),
131 
132  // sheet layout dimensions
133  ldx = sll ? sdy : sdx,
134  ldy = sll ? sdx : sdy,
135 
136  // sheet frame dimensions
137  fdx = ldx - smx,
138  fdy = ldy - smy,
139 
140  // working dimensions excluding reference zone
141  wdx = fdx - szm * 2,
142  wdy = fdy - szm * 2,
143 
144  // zone start coordinates
145  zxs = is_defined(ix) ?
146  let
147  ( // reference ordering
148  iox = (zox > 0) ? ix : len(zlx)-1-ix
149  )
150  iox * fdx/len(zlx) -fdx/2
151  : is_defined(rx) ?
152  let
153  ( // assign '-1', outside of frame, if not found
154  zxi = defined_or(first(find(rx, zlx)), -1),
155  iox = (zox > 0) ? zxi : len(zlx)-1-zxi
156  )
157  iox * fdx/len(zlx) -fdx/2
158  : 0,
159  zys = is_defined(iy) ?
160  let
161  ( // reference ordering
162  ioy = (zoy > 0) ? iy : len(zly)-1-iy
163  )
164  ioy * fdy/len(zly) -fdy/2
165  : is_defined(ry) ?
166  let
167  ( // assign '-1', outside of frame, if not found
168  zyi = defined_or(first(find(ry, zly)), -1),
169  ioy = (zoy > 0) ? zyi : len(zly)-1-zyi
170  )
171  ioy * fdy/len(zly) - fdy/2
172  : 0,
173 
174  // reference window coordinates
175  wx = is_defined(ix) || is_defined(rx) ?
176  [zxs, zxs + fdx/len(zlx)]
177  : frame ?
178  [-fdx/2, fdx/2]
179  : [-wdx/2, wdx/2],
180  wy = is_defined(iy) || is_defined(ry) ?
181  [zys, zys + fdy/len(zly)]
182  : frame ?
183  [-fdy/2, fdy/2]
184  : [-wdy/2, wdy/2]
185  )
186  limits ?
187  // limits: [[xmin, xmax], [ymin, ymax]
188  [wx, wy]
189  // window points in cw order from [xmin, ymin]
190  : [[wx[0],wy[0]], [wx[0],wy[1]], [wx[1],wy[1]], [wx[1],wy[0]]];
191 
192 //! \endcond
193 
194 //! Get sheet, sheet-frame, or sheet-zone reference coordinates.
195 /***************************************************************************//**
196  \param rx <string-list | string> Sheet x-axis zone reference identifier(s).
197  \param ry <string-list | string> Sheet y-axis zone reference identifier(s).
198 
199  \param ix <integer-list | integer> Sheet x-axis zone reference index(es).
200  \param iy <integer-list | integer> Sheet x-axis zone reference index(es).
201 
202  \param zp <integer-list-2 | integer> The window coordinate scaler. A
203  list [zpx, zpy] of decimals or a single decimal for (zpx=zpy).
204 
205  \param window <boolean> Return window rather than point.
206  \param frame <boolean> Use frame when zone not specified.
207 
208  \returns <datastruct> The reference coordinates.
209 
210  \details
211 
212  The returned datastruct will be one of the following forms:
213 
214  window | description | data type
215  :------:|:--------------------------------|:------------------------
216  true | [p0, p1, p2, p3], pn=[x,y] | <point-2d-list-4>
217  false | [x, y] | <point-2d>
218 
219  The parameter \p zp is used to linearly scale the window
220  coordinate. For both axes, \b -1 = left/bottom, \b 0 =
221  center/middle, and \b +1 = right/top. The windows coordinate points
222  [p0, p1, p2, p3] are clockwise ordered with p0=[xmin, ymin].
223 *******************************************************************************/
224 function draft_sheet_get_zone
225 (
226  rx,
227  ry,
228  ix,
229  iy,
230  zp = 0,
231  window = false,
232  frame = false
233 ) =
234  let
235  (
236  // get reference window xy-limits
237  wl = !is_list(rx) && !is_list(ix) && !is_list(ry) && !is_list(iy) ?
238  // no reference lists, just get single zone window
239  draft_sheet_get_window( rx=rx, ry=ry, ix=ix, iy=iy, frame=frame, limits=true )
240  : let
241  (
242  // determine x-limits
243  wx = is_list(ix) ?
244  let
245  (
246  w1 = draft_sheet_get_window( ix=first(ix), frame=frame, limits=true ),
247  w2 = draft_sheet_get_window( ix=last(ix), frame=frame, limits=true )
248  )
249  [min(w1[0][0], w2[0][0]), max(w1[0][1], w2[0][1])]
250  : is_list(rx) ?
251  let
252  (
253  w1 = draft_sheet_get_window( rx=first(rx), frame=frame, limits=true ),
254  w2 = draft_sheet_get_window( rx=last(rx), frame=frame, limits=true )
255  )
256  [min(w1[0][0], w2[0][0]), max(w1[0][1], w2[0][1])]
257  : let
258  (
259  w1 = draft_sheet_get_window( rx=rx, ix=ix, frame=frame, limits=true )
260  )
261  w1[0],
262 
263  // determine y-limits
264  wy = is_list(iy) ?
265  let
266  (
267  w1 = draft_sheet_get_window( iy=first(iy), frame=frame, limits=true ),
268  w2 = draft_sheet_get_window( iy=last(iy), frame=frame, limits=true )
269  )
270  [min(w1[1][0], w2[1][0]), max(w1[1][1], w2[1][1])]
271  : is_list(ry) ?
272  let
273  (
274  w1 = draft_sheet_get_window( ry=first(ry), frame=frame, limits=true ),
275  w2 = draft_sheet_get_window( ry=last(ry), frame=frame, limits=true )
276  )
277  [min(w1[1][0], w2[1][0]), max(w1[1][1], w2[1][1])]
278  : let
279  (
280  w1 = draft_sheet_get_window( ry=ry, iy=iy, frame=frame, limits=true )
281  )
282  w1[1]
283  )
284  // xy-limits
285  [wx, wy]
286  )
287  window ?
288  // window points in cw order from [xmin, ymin]
289  [
290  [wl[0][0], wl[1][0]],
291  [wl[0][0], wl[1][1]],
292  [wl[0][1], wl[1][1]],
293  [wl[0][1], wl[1][0]]
294  ]
295  : let
296  (
297  // linearly scale window by px, py
298  // [-1]=left/bottom, [0]=center/middle, [+1]=right/top]
299  px = defined_e_or(zp, 0, zp),
300  py = defined_e_or(zp, 1, px),
301 
302  cx = ( px * (wl[0][1]-wl[0][0]) + (wl[0][0]+wl[0][1]) )/2,
303  cy = ( py * (wl[1][1]-wl[1][0]) + (wl[1][0]+wl[1][1]) )/2
304  )
305  // point
306  [cx, cy];
307 
308 //! @}
309 
310 //----------------------------------------------------------------------------//
311 
312 //! \name Tables
313 //! @{
314 
315 //! Get a coordinate point for a defined draft table column and row.
316 /***************************************************************************//**
317  \param ix <integer> A table column vertical line index.
318  \param iy <integer> A table row horizontal line index.
319 
320  \param map <map> A table definition map.
321  \param fmap <map> A table format map.
322 
323  \returns <point-2d> The table column and row intersection coordinate
324  point.
325 
326  \private
327 *******************************************************************************/
328 function draft_table_get_point
329 (
330  ix,
331  iy,
332  map,
333  fmap
334 ) =
335  let
336  (
337  // get table format
338  cmh = map_get_firstof2_or(map, fmap, "cmh", draft_get_config("table-cmh")) * $draft_scale,
339  cmv = map_get_firstof2_or(map, fmap, "cmv", draft_get_config("table-cmv")) * $draft_scale,
340 
341  coh = map_get_firstof2_or(map, fmap, "coh", draft_get_config("table-coh")),
342  cov = map_get_firstof2_or(map, fmap, "cov", draft_get_config("table-cov")),
343 
344  // get table data
345  title = map_get_value(map, "title"),
346  heads = map_get_value(map, "heads"),
347  cols = map_get_value(map, "cols"),
348  rows = map_get_value(map, "rows"),
349 
350  // vertical line index
351  xu = is_undef(ix) ? 0 // not specified
352  : (ix <= 0) ? 0 // left
353  : sum([for( i=[1:ix] ) cols[i-1]]), // sum column units widths
354 
355  yt = defined_e_or(title, 1, 0), // title: '0' unit default height
356  yh = defined_e_or(heads, 1, 0), // heads: '0' unit default height
357 
358  // horizontal line index
359  yu = is_undef(iy) ? 0 // not specified
360  : (iy <= 0) ? 0 // top
361  : (iy == 1) ? yt // title
362  : (iy == 2) ? sum( [yt, yh] ) // title + heads
363  : sum
364  (
365  [
366  yt, yh, // rows: '1' unit default height
367  for( i=[3:iy] ) defined_e_or(rows[i-3], 1, 1)
368  ]
369  )
370  )
371  [xu*cmh*coh, yu*cmv*cov]; // units * unit-size * order
372 
373 //! Get table cell coordinates given a column and row.
374 /***************************************************************************//**
375  \param ix <integer> A table column vertical line index.
376  \param iy <integer> A table row horizontal line index.
377 
378  \param zp <integer-list-2 | integer> The cell coordinate scaler. A
379  list [zpx, zpy] of decimals or a single decimal for (zpx=zpy).
380 
381  \param limits <boolean> Return cell limits rather than coordinates.
382  \param window <boolean> Return cell window rather than point.
383 
384  \param map <map> A table definition map.
385  \param fmap <map> A table format map.
386 
387  \returns <datastruct> The table cell coordinates.
388 
389  \details
390 
391  The returned datastruct will be one of the following forms:
392 
393  limits | window | description | data type
394  :------:|:------:|:--------------------------------|:------------------------
395  true | - | [[xmin, xmax], [ymin, ymax]] | <decimal-list-2-list-2>
396  false | true | [p0, p1, p2, p3], pn=[x,y] | <point-2d-list-4>
397  false | false | [x, y] | <point-2d>
398 
399  The parameter \p zp is used to linearly scale the window
400  coordinate. For both axes, \b -1 = left/bottom, \b 0 =
401  center/middle, and \b +1 = right/top. The windows coordinate points
402  [p0, p1, p2, p3] are clockwise ordered with p0=[xmin, ymin].
403 *******************************************************************************/
404 function draft_table_get_cell
405 (
406  ix,
407  iy,
408  zp = 0,
409  limits = false,
410  window = false,
411  map,
412  fmap
413 ) =
414  let
415  (
416  // get table data
417  cols = map_get_value(map, "cols"),
418  rows = map_get_value(map, "rows"),
419 
420  // vertical lines
421  lv = is_undef(ix) ? [0, len(cols)] // table width
422  : (iy <= 0) ? [0, len(cols)] // title cell
423  : [ix, ix+1], // heading or row
424 
425  // horizontal lines
426  lh = is_undef(iy) ? [0, len(rows)+2] // table height
427  : [iy, iy+1], // any row
428 
429  // get cell window xy-limits [min, max]
430  wl =
431  [
432  [ for( i=[0, 1] ) draft_table_get_point( ix=lv[i], map=map, fmap=fmap )[0] ],
433  [ for( i=[0, 1] ) draft_table_get_point( iy=lh[i], map=map, fmap=fmap )[1] ]
434  ]
435  )
436  limits ?
437  // limits: [[xmin, xmax], [ymin, ymax]
438  wl
439  : window ?
440  // window points in cw order from [xmin, ymin]
441  [
442  [wl[0][0], wl[1][0]],
443  [wl[0][0], wl[1][1]],
444  [wl[0][1], wl[1][1]],
445  [wl[0][1], wl[1][0]]
446  ]
447  : let
448  (
449  // linearly scale window by px, py
450  // [-1]=left/bottom, [0]=center/middle, [+1]=right/top]
451  px = defined_e_or(zp, 0, zp),
452  py = defined_e_or(zp, 1, px),
453 
454  cx = ( px * (wl[0][1]-wl[0][0]) + (wl[0][0]+wl[0][1]) )/2,
455  cy = ( py * (wl[1][1]-wl[1][0]) + (wl[1][0]+wl[1][1]) )/2
456  )
457  // point
458  [cx, cy];
459 
460 //! Add text to table cell at a given a column and row.
461 /***************************************************************************//**
462  \param ix <integer> A table column vertical line index.
463  \param iy <integer> A table row horizontal line index.
464 
465  \param text <string | string-list> The text to add. A single string
466  or a list of strings for multiple line text.
467  \param size <decimal> The text size.
468 
469  \param dfmt <datastruct> The default text format.
470 
471  \param map <map> A table definition map.
472  \param fmap <map> A table format map.
473 
474  \details
475 
476  The parameter \p dfmt of type <datastruct> is a list of eleven
477  values:
478 
479  \verbatim
480  <datastruct> =
481  [
482  0:text, 1:<align-point>, 2:<align-offset>, 3:<multi-line-offset>,
483  4:rotate, 5:text-scale, 6:<text-align>, 7:font,
484  8:spacing, 9:direction, 10:language, 11:script
485  ]
486  \endverbatim
487 
488  field | description | data type
489  :------:|-----------------------|:--------------------------
490  0 | text | <string>
491  1 | [h-align, v-align] | <decimal-list-2>
492  2 | [h-offset, v-offset] | <decimal-list-2>
493  3 | [h-offset, v-offset] | <decimal-list-2>
494  4 | rotate | <decimal>
495  5 | text-scale | <decimal>
496  6 | [h-align, v-align] | <string-list-2>
497  7 | font | <string>
498  8 | spacing | <decimal>
499  9 | direction | <string>
500  10 | language | <string>
501  11 | script | <string>
502 
503  \b Example
504  \code{.C}
505  dfmt = [empty_str, [-1,-1], [2/5,-9/10], [0,-1-1/5], 0, 1, ["left", "center"]]];
506  \endcode
507 
508  Unassigned fields are initialized with defaults.
509 *******************************************************************************/
510 module draft_table_text
511 (
512  ix,
513  iy,
514  text,
515  size,
516  dfmt,
517  map,
518  fmap
519 )
520 { // element-wise default assignment
521  function erdefined_or (v, r, d) = [for (i = r) defined_or( v[i], d[i] )];
522 
523  /*
524  handled-input-cases tv(text) sf(text)
525  (1) "t1" ["t1"] [ "t1" ]
526  (2) [ "t1" ] ["t1"] [ "t1" ]
527  (3) [ "t1", "t2" ] ["t1", "t2"] [ ["t1", "t2"] ]
528  (4) [ ["t1", "t2"] ] ["t1", "t2"] [ ["t1", "t2"] ]
529  (5) [ ["t1", "t2"], [0,0] ] ["t1", "t2"] [ ["t1", "t2"], [0,0] ]
530  (6) [ "t1", [0,0] ] ["t1"] [ "t1", [0,0] ]
531  */
532 
533  // text format
534  sf = is_string(text) ? [text] // (1)
535  : all_strings(text) ? [text] // (2), (3)
536  : text; // (4), (5), (6)
537 
538  // text list
539  tv = is_string(text) ? [text] // (1)
540  : all_strings(text) ? text // (2), (3)
541  : is_list(text[0]) ? text[0] // (4), (5)
542  : [text[0]]; // (6)
543 
544  // assign defaults where needed
545  df = erdefined_or( sf, [0:11], dfmt );
546 
547  for ( l=[0:len(tv)-1] )
548  translate
549  (
550  // cell coordinates
551  draft_table_get_cell( ix=ix, iy=iy, zp=df[1], map=map, fmap=fmap )
552  // configured offset
553  + [ df[2][0], df[2][1] ] * size * df[5]
554  // multi-line offset
555  + df[3] * size * df[5] * l
556  )
557  rotate( df[4] )
558  text
559  (
560  text=tv[l],
561  size=df[5]*size,
562  halign=df[6][0],
563  valign=df[6][1],
564  font=df[7],
565  spacing=df[8],
566  direction=df[9],
567  language=df[10],
568  script=df[11]
569  );
570 }
571 
572 //! Get a coordinate point for a defined draft zoned-table column and row.
573 /***************************************************************************//**
574  \param ix <integer> A ztable column vertical line index.
575  \param iy <integer> A ztable row horizontal line index.
576 
577  \param map <map> A ztable definition map.
578 
579  \returns <point-2d> The ztable column and row intersection coordinate
580  point.
581 
582  \private
583 *******************************************************************************/
584 function draft_ztable_get_point
585 (
586  ix,
587  iy,
588  map
589 ) =
590  let
591  (
592  // get table configuration
593  cmh = map_get_value(map, "cmh") * $draft_scale,
594  cmv = map_get_value(map, "cmv") * $draft_scale,
595 
596  coh = map_get_value(map, "coh"),
597  cov = map_get_value(map, "cov"),
598 
599  vlines = map_get_value(map, "vlines"),
600  hlines = map_get_value(map, "hlines"),
601 
602  x = is_undef(ix) ? 0 : sum([for( i=[0:ix] ) vlines[i][0]]) * cmh * coh,
603  y = is_undef(iy) ? 0 : sum([for( i=[0:iy] ) hlines[i][0]]) * cmv * cov
604  )
605  [x, y];
606 
607 //! Get ztable zone coordinates given a zone index.
608 /***************************************************************************//**
609  \param i <integer> A ztable zone index.
610 
611  \param zp <integer-list-2 | integer> The zone coordinate scaler. A
612  list [zpx, zpy] of decimals or a single decimal for (zpx=zpy).
613 
614  \param limits <boolean> Return zone limits rather than coordinates.
615  \param window <boolean> Return zone window rather than point.
616 
617  \param map <map> A ztable definition map.
618 
619  \returns <datastruct> The ztable cell coordinates.
620 
621  \details
622 
623  The returned datastruct will be one of the following forms:
624 
625  limits | window | description | data type
626  :------:|:------:|:--------------------------------|:------------------------
627  true | - | [[xmin, xmax], [ymin, ymax]] | <decimal-list-2-list-2>
628  false | true | [p0, p1, p2, p3], pn=[x,y] | <point-2d-list-4>
629  false | false | [x, y] | <point-2d>
630 
631  The parameter \p zp is used to linearly scale the window
632  coordinate. For both axes, \b -1 = left/bottom, \b 0 =
633  center/middle, and \b +1 = right/top. The windows coordinate points
634  [p0, p1, p2, p3] are clockwise ordered with p0=[xmin, ymin].
635 *******************************************************************************/
636 function draft_ztable_get_zone
637 (
638  i,
639  zp = 0,
640  limits = false,
641  window = false,
642  map
643 ) =
644  let
645  (
646  // get table configuration
647  zones = map_get_value(map, "zones"),
648 
649  // [min vline, max vline]
650  zx = is_undef(i) ? [0, len(map_get_value(map, "vlines"))-1] : zones[i][0],
651 
652  // [min hline, max hline]
653  zy = is_undef(i) ? [0, len(map_get_value(map, "hlines"))-1] : zones[i][1],
654 
655  // get zone window xy-limits [min, max]
656  wl =
657  [
658  [ for( i=[1, 0] ) draft_ztable_get_point( ix=zx[i], map=map )[0] ],
659  [ for( i=[0, 1] ) draft_ztable_get_point( iy=zy[i], map=map )[1] ]
660  ]
661  )
662  limits ?
663  // limits: [[xmin, xmax], [ymin, ymax]
664  wl
665  : window ?
666  // window points in cw order from [xmin, ymin]
667  [
668  [wl[0][0], wl[1][0]],
669  [wl[0][0], wl[1][1]],
670  [wl[0][1], wl[1][1]],
671  [wl[0][1], wl[1][0]]
672  ]
673  : let
674  (
675  // linearly scale window by px, py
676  // [-1]=left/bottom, [0]=center/middle, [+1]=right/top]
677  px = defined_e_or(zp, 0, zp),
678  py = defined_e_or(zp, 1, px),
679 
680  cx = ( px * (wl[0][1]-wl[0][0]) + (wl[0][0]+wl[0][1]) )/2,
681  cy = ( py * (wl[1][1]-wl[1][0]) + (wl[1][0]+wl[1][1]) )/2
682  )
683  // point
684  [cx, cy];
685 
686 //! Add text to ztable at a given zone index.
687 /***************************************************************************//**
688  \param i <integer> A ztable zone index.
689 
690  \param text <string | string-list> The text to add. A single string
691  or a list of strings for multiple line text.
692  \param size <decimal> The text size.
693 
694  \param fmt <datastruct> The text format.
695  \param dfmt <datastruct> The default text format.
696 
697  \param map <map> A ztable definition map.
698 
699  \details
700 
701  The parameters \p fmt and \p dfmt of type <datastruct> is a list of
702  eleven values:
703 
704  \verbatim
705  <datastruct> =
706  [
707  0:text, 1:<align-point>, 2:<align-offset>, 3:<multi-line-offset>,
708  4:rotate, 5:text-scale, 6:<text-align>, 7:font,
709  8:spacing, 9:direction, 10:language, 11:script
710  ]
711  \endverbatim
712 
713  field | description | data type
714  :------:|-----------------------|:--------------------------
715  0 | text | <string>
716  1 | [h-align, v-align] | <decimal-list-2>
717  2 | [h-offset, v-offset] | <decimal-list-2>
718  3 | [h-offset, v-offset] | <decimal-list-2>
719  4 | rotate | <decimal>
720  5 | text-scale | <decimal>
721  6 | [h-align, v-align] | <string-list-2>
722  7 | font | <string>
723  8 | spacing | <decimal>
724  9 | direction | <string>
725  10 | language | <string>
726  11 | script | <string>
727 
728  \b Example
729  \code{.C}
730  dfmt = [empty_str, [-1,-1], [2/5,-9/10], [0,-1-1/5], 0, 1, ["left", "center"]]];
731  \endcode
732 
733  Unassigned fields are initialized with defaults.
734 *******************************************************************************/
735 module draft_ztable_text
736 (
737  i,
738  text,
739  size,
740  fmt,
741  dfmt,
742  map
743 )
744 { // element-wise default assignment
745  function erdefined_or (v, r, d) = [for (i = r) defined_or( v[i], d[i] )];
746 
747  // multi- or single-line
748  tv = is_list(text) ? text : [text];
749 
750  // assign defaults where needed
751  df = erdefined_or( fmt, [0:11], dfmt );
752 
753  for ( l=[0:len(tv)-1] )
754  translate
755  (
756  // zone coordinates
757  draft_ztable_get_zone( i=i, zp=df[1], map=map )
758  // configured offset
759  + [ df[2][0], df[2][1] ] * size * df[5]
760  // multi-line offset
761  + df[3] * size * df[5] * l
762  )
763  rotate( df[4] )
764  text
765  (
766  text=tv[l],
767  size=df[5]*size,
768  halign=df[6][0],
769  valign=df[6][1],
770  font=df[7],
771  spacing=df[8],
772  direction=df[9],
773  language=df[10],
774  script=df[11]
775  );
776 }
777 
778 //! @}
779 
780 //----------------------------------------------------------------------------//
781 
782 //! \name Shapes
783 //! @{
784 
785 //! Draft a simple line from an initial to a terminal point.
786 /***************************************************************************//**
787  \param i <point-2d> The initial point coordinate [x, y].
788  \param t <point-2d> The terminal point coordinate [x, y].
789  \param w <decimal> The line weight.
790 
791  \details
792 
793  \ref $draft_line_fn sets arc fragment number for line construction.
794 
795  | see: \ref draft_config_map |
796  |:---------------------------:|
797  | line-width-min |
798  | line-use-hull |
799 *******************************************************************************/
800 module draft_line_pp
801 (
802  i,
803  t,
804  w = 1
805 )
806 {
807  $fn = $draft_line_fn;
808  p = draft_get_config("line-width-min") * w * $draft_scale;
809 
810  if ( draft_get_config("line-use-hull") )
811  {
812  // hulled end-circles
813  hull() { translate(i) circle(d=p); translate(t) circle(d=p); }
814  }
815  else
816  {
817  // rectangle line
818  align_ll(r=[i, t], rp=2, l=y_axis3d_ul)
819  square([p, distance_pp(i, t)], center=true);
820 
821  // add rounded ends
822  // translate(i) circle(d=p); translate(t) circle(d=p);
823  }
824 }
825 
826 //! Draft an arrowhead at the terminal point of a line.
827 /***************************************************************************//**
828  \param l <line> A line or vector.
829  \param w <decimal> The line segment weight.
830  \param s <integer | integer-list-5> The arrowhead style.
831 
832  \details
833 
834  The style can be customize via the following optional parameter
835  list fields.
836 
837  field | description | data type | default
838  :------:|:--------------------------------|:--------------------|:-------:
839  0 | style | <integer> | 0
840  1 | fill: 0,1 or true,false | <integer \| boolean>| 0
841  2 | side: 0=both, 1=left, 2=right | <integer> | 0
842  3 | length multiplier | <decimal> | 1
843  4 | angle multiplier | <decimal> | 1
844 
845  When parameter \p s is assigned a single integer it sets the style
846  and the other fields are assigned their default values.
847 
848  style | description
849  :------:|:--------------------------
850  0 | no arrowhead
851  1 | closed 3-point arrowhead
852  2 | closed 4-point arrowhead
853  3 | open 3-point arrowhead
854  4 | slash / cross arrowhead
855  5 | circle arrowhead
856 
857  \amu_eval ( object=draft_arrow ${object_diagram_2d} )
858 
859  \ref $draft_arrow_fn sets arc fragment number for arrowhead
860  construction. The line segments are constructed by \ref draft_line_pp().
861 
862  | see: \ref draft_config_map |
863  |:---------------------------:|
864  | arrow-line-length-min |
865  | arrow-angle-min |
866 *******************************************************************************/
867 module draft_arrow
868 (
869  l = x_axis2d_ul,
870  w = 1,
871  s = 1
872 )
873 {
874  s1 = defined_e_or(s, 0, s); // arrow selection
875 
876  if ( s1 )
877  {
878  s2 = defined_e_or(s, 1, 0); // fill [0:1, t:f]
879  s3 = defined_e_or(s, 2, 0); // sections [0:all,1:left,2:right]
880 
881  s4 = defined_e_or(s, 3, 1); // length multiplier
882  s5 = defined_e_or(s, 4, 1); // angle multiplier
883 
884 
885  al = draft_get_config("arrow-line-length-min") * s4 * $draft_scale;
886  // length
887 
888  ca = draft_get_config("arrow-angle-min") * s5;
889  // cut angle
890 
891  alx = angle_ll(x_axis2d_uv, l, true); // line angle
892  aa1 = alx+180-ca; // angle a1
893  aa2 = alx-180+ca; // angle a2
894 
895  pah = line_tp(l); // head point
896 
897  ls1 = line2d_new(m=al, a=aa1, p1=pah); // side line1
898  ls2 = line2d_new(m=al, a=aa2, p1=pah); // side line2
899 
900  ps1 = line_tp(ls1); // line1 end point
901  ps2 = line_tp(ls2); // line2 end point
902 
903  ptm = (ps1 + ps2)/2; // tail mid point
904  pam = (ptm + pah)/2; // middle point
905 
906  // update fn for arrow line construction
908 
909  if ( s1 == 1 )
910  { // closed 3-point
911  hull_cs( !s2 )
912  {
913  draft_line_pp(pah, ptm, w=w);
914  if (binary_bit_is(s3, 0, 0))
915  { draft_line_pp(ls1[0], ls1[1], w=w); draft_line_pp(ps1, ptm, w=w); }
916  if (binary_bit_is(s3, 1, 0))
917  { draft_line_pp(ls2[0], ls2[1], w=w); draft_line_pp(ps2, ptm, w=w); }
918  }
919  }
920  else if ( s1 == 2 )
921  { // closed 4-point
922  hull_cs( !s2 )
923  {
924  draft_line_pp(pah, pam, w=w);
925  if (binary_bit_is(s3, 0, 0))
926  { draft_line_pp(ls1[0], ls1[1], w=w); draft_line_pp(ps1, pam, w=w); }
927  }
928  hull_cs( !s2 )
929  {
930  draft_line_pp(pah, pam, w=w);
931  if (binary_bit_is(s3, 1, 0))
932  { draft_line_pp(ls2[0], ls2[1], w=w); draft_line_pp(ps2, pam, w=w); }
933  }
934  }
935  else if ( s1 == 3 )
936  { // open 3-point
937  if (binary_bit_is(s3, 0, 0))
938  draft_line_pp(ls1[0], ls1[1], w=w);
939  if (binary_bit_is(s3, 1, 0))
940  draft_line_pp(ls2[0], ls2[1], w=w);
941  }
942  else if ( s1 == 4 )
943  { // slash / cross
944  if (binary_bit_is(s3+1, 0, 1))
945  {
946  xl1 = line2d_new(m=+al/3*2, a=alx+180-ca*2, p1=pah);
947  xl2 = line2d_new(m=-al/3*2, a=alx+180-ca*2, p1=pah);
948 
949  draft_line_pp(xl1[0], xl1[1], w=w);
950  draft_line_pp(xl2[0], xl2[1], w=w);
951  }
952  if (binary_bit_is(s3+1, 1, 1))
953  {
954  xl1 = line2d_new(m=+al/3*2, a=alx-180+ca*2, p1=pah);
955  xl2 = line2d_new(m=-al/3*2, a=alx-180+ca*2, p1=pah);
956 
957  draft_line_pp(xl1[0], xl1[1], w=w);
958  draft_line_pp(xl2[0], xl2[1], w=w);
959  }
960  }
961  else if ( s1 == 5 )
962  { // circle
963  hull_cs( !s2 )
964  for ( ls = sequence_ns( polygon_arc_p( r=al/3, c=pah, fn=$draft_arrow_fn ), 2, 1 ) )
965  draft_line_pp(ls[0], ls[1], w=w);
966  }
967  }
968 }
969 
970 //! Draft a line with configurable style and optional arrowheads.
971 /***************************************************************************//**
972  \param l <line> A line or vector.
973  \param w <decimal> The line weight.
974  \param s <integer | integer-list> The line style.
975  \param a1 <integer | integer-list-5> The arrowhead style at initial point.
976  \param a2 <integer | integer-list-5> The arrowhead style at terminal point.
977 
978  \details
979 
980  When parameter \p s is assigned a single integer it sets the style
981  with its default optional values. The line style \p s can be one of
982  the following:
983 
984  style | description
985  :------:|:--------------------------
986  0 | no line
987  1 | solid line
988  2 | single dash pattern centered
989  3 | dual overlapped dash patterns
990  4 | both ends and center
991  5 | line section break
992 
993  Each style can be customize via optional parameter list fields. The
994  options differ by style:
995 
996  <b>style 2</b>
997 
998  field | description | data type | default
999  :------:|:--------------------------------|:--------------------|:-------:
1000  1 | length multiplier | <decimal> | 1
1001  2 | stride | <decimal> | 2
1002 
1003  <b>style 3</b>
1004 
1005  field | description | data type | default
1006  :------:|:--------------------------------|:--------------------|:-------:
1007  1 | length multiplier 1 | <decimal> | 1
1008  2 | stride 1 | <decimal> | 2
1009  3 | length multiplier 2 | <decimal> | 2
1010  4 | stride 2 | <decimal> | 3
1011 
1012  <b>style 4</b>
1013 
1014  field | description | data type | default
1015  :------:|:--------------------------------|:--------------------|:-------:
1016  1 | number of centered segments | <decimal> | 1
1017  2 | centered-length multiplier | <decimal> | 1
1018  3 | end-length multiplier | <decimal> | 1
1019 
1020  <b>style 5</b>
1021 
1022  field | description | data type | default
1023  :------:|:--------------------------------|:--------------------|:-------:
1024  1 | number of breaks | <decimal> | 1
1025  2 | break length multiplier | <decimal> | 2
1026  3 | break width multiplier | <decimal> | 2
1027  4 | break angle | <decimal> | 67.5
1028 
1029  \amu_eval ( object=draft_line ${object_diagram_2d} )
1030 
1031  The line segments are constructed by \ref draft_line_pp().
1032 
1033  | see: \ref draft_config_map |
1034  |:---------------------------:|
1035  | line-segment-min |
1036 *******************************************************************************/
1037 module draft_line
1038 (
1039  l = x_axis2d_ul,
1040  w = 1,
1041  s = 1,
1042  a1 = 0,
1043  a2 = 0
1044 )
1045 {
1046  s1 = defined_e_or(s, 0, s); // line selection
1047 
1048  if ( !all_equal([s1, a1, a2], 0) )
1049  {
1050  lsm = draft_get_config("line-segment-min") * $draft_scale;
1051 
1052  i = line_ip(l);
1053  t = line_tp(l);
1054 
1055  if ( s1 == 1 )
1056  { // solid line
1057  draft_line_pp(i, t, w);
1058  }
1059  else if ( s1 == 2 )
1060  { // single pattern centered
1061  s2 = defined_e_or(s, 1, 1)*lsm; // length multiplier
1062  s3 = defined_e_or(s, 2, 2); // stride
1063 
1064  for ( ls = sequence_ns( polygon_line_p(l=l, ft=s2), 2, s3 ) )
1065  draft_line_pp(ls[0], ls[1], w);
1066  }
1067  else if ( s1 == 3 )
1068  { // dual overlapped patterns
1069  s2 = defined_e_or(s, 1, 1)*lsm; // length multiplier 1
1070  s3 = defined_e_or(s, 2, 2); // stride 1
1071  s4 = defined_e_or(s, 3, 2)*lsm; // length multiplier 2
1072  s5 = defined_e_or(s, 4, 3); // stride 2
1073 
1074  for ( ls = sequence_ns( polygon_line_p(l=l, fs=s2), 2, s3 ) )
1075  draft_line_pp(ls[0], ls[1], w);
1076 
1077  for ( ls = sequence_ns( polygon_line_p(l=l, fs=s4), 2, s5 ) )
1078  draft_line_pp(ls[0], ls[1], w);
1079  }
1080  else if ( s1 == 4 )
1081  { // at both ends and 'n' centered
1082  s2 = defined_e_or(s, 1, 1); // number 'n'
1083  s3 = defined_e_or(s, 2, 1)*lsm; // centered-length multiplier
1084  s4 = defined_e_or(s, 3, 1)*lsm; // end-length multiplier
1085 
1086  // at both ends
1087  el1 = line2d_new(s4, p1=i, v=[i, t]);
1088  el2 = line2d_new(s4, p1=t, v=[t, i]);
1089 
1090  draft_line_pp(el1[0], el1[1], w);
1091  draft_line_pp(el2[0], el2[1], w);
1092 
1093  // 'n' centered
1094  if (s2 > 0)
1095  {
1096  mp = polygon_line_p(l=l, fn=s2+1);
1097  for (j = [1:len(mp)-2])
1098  {
1099  cl1 = line2d_new(s3/2, p1=mp[j], v=[t, i]);
1100  cl2 = line2d_new(s3/2, p1=mp[j], v=[i, t]);
1101 
1102  draft_line_pp(cl1[1], cl2[1], w);
1103  }
1104  }
1105  }
1106  else if ( s1 == 5 )
1107  { // line break(s)
1108  s2 = defined_e_or(s, 1, 1); // number of breaks
1109  s3 = defined_e_or(s, 2, 2)*lsm; // length multiplier
1110  s4 = defined_e_or(s, 3, 2)*lsm; // width multiplier
1111  s5 = defined_e_or(s, 4, 67.5); // angle*
1112 
1113  // *s5=90 invokes bug: https://github.com/CGAL/cgal/issues/2631
1114 
1115  la = angle_ll(x_axis2d_uv, l);
1116  bp = polygon_line_p(l=l, fn=1+max(1,s2));
1117 
1118  xp =
1119  [
1120  for (i = [1:len(bp)-2])
1121  let
1122  (
1123  mp = bp[i], // mid, cross, & line points
1124  xp = polygon_regular_p(n=2, r=s4, o=la+s5, c=mp),
1125  lp = polygon_regular_p(n=2, r=s3, o=la, c=mp)
1126  )
1127  [ lp[1], xp[0], xp[1], lp[0] ]
1128  ];
1129 
1130  for ( ls = sequence_ns(concat([i],merge_s(xp),[t]), 2, 1 ) )
1131  draft_line_pp(ls[0], ls[1], w);
1132  }
1133 
1134  // arrows
1135  draft_arrow(l=[t, i], w=w, s=a1);
1136  draft_arrow(l=[i, t], w=w, s=a2);
1137  }
1138 }
1139 
1140 //! Draft an arc with configurable style and optional arrowheads.
1141 /***************************************************************************//**
1142  \copydetails polygon_arc_p()
1143  These coordinates will be used to draft an arc according to the
1144  following additional parameters.
1145 
1146  \param w <decimal> The line weight.
1147  \param s <integer | integer-list> The line style.
1148  \param a1 <integer | integer-list-5> The arrowhead style at initial point.
1149  \param a2 <integer | integer-list-5> The arrowhead style at terminal point.
1150 
1151  \details
1152 
1153  When parameter \p s is assigned a single integer it sets the style
1154  with its default optional values. The line style \p s can be one of
1155  the following:
1156 
1157  style | description
1158  :------:|:--------------------------
1159  0 | no line
1160  1 | solid line
1161  2 | single dash pattern
1163  Style 2 can be customize via optional parameter as shown below:
1164 
1165  <b>style 2</b>
1166 
1167  field | description | data type | default
1168  :------:|:--------------------------------|:--------------------|:-------:
1169  1 | stride | <decimal> | 2
1170 
1171  \amu_eval ( object=draft_arc ${object_diagram_2d} )
1172 
1173  The line segments are constructed by \ref draft_line_pp().
1174 *******************************************************************************/
1175 module draft_arc
1176 (
1177  r = 1,
1178  c = origin2d,
1179  v1 = x_axis2d_uv,
1180  v2 = x_axis2d_uv,
1181  fn,
1182  cw = true,
1183 
1184  w = 1,
1185  s = 1,
1186  a1 = 0,
1187  a2 = 0
1188 )
1189 {
1190  s1 = defined_e_or(s, 0, s); // line selection
1191 
1192  if ( !all_equal([s1, a1, a2], 0) )
1193  {
1194  pp = polygon_arc_p( r=r, c=c, v1=v1, v2=v2, fn=fn, cw=cw );
1195 
1196  if ( s1 == 1 )
1197  { // solid line
1198  for ( ls = sequence_ns( pp, 2, 1 ) )
1199  draft_line_pp(ls[0], ls[1], w);
1200  }
1201  else if ( s1 == 2 )
1202  { // single pattern
1203  s2 = defined_e_or(s, 1, 2); // point stride
1204 
1205  for ( ls = sequence_ns( pp, 2, s2 ) )
1206  draft_line_pp(ls[0], ls[1], w);
1207  }
1208 
1209  // arrows
1210  draft_arrow(l=reverse(firstn(pp, 2)), w=w, s=a1);
1211  draft_arrow(l=lastn(pp, 2), w=w, s=a2);
1212  }
1213 }
1214 
1215 //! Draft a rectangle with configurable style.
1216 /***************************************************************************//**
1217  \param d <decimal-list-2 | decimal> A list [x, y] of decimals
1218  or a single decimal for (x=y).
1219  \param c <point-2d> The center coordinate [x, y].
1220  \param w <decimal> The line weight.
1221  \param s <integer | integer-list> The line style.
1222 
1223  \details
1224 
1225  \amu_eval ( object=draft_rectangle ${object_diagram_2d} )
1226 
1227  The line segments are constructed by \ref draft_line().
1228 *******************************************************************************/
1229 module draft_rectangle
1230 (
1231  d = 1,
1232  c = origin2d,
1233  w = 1,
1234  s = 1
1235 )
1236 {
1237  dx = defined_e_or(d, 0, d);
1238  dy = defined_e_or(d, 1, dx);
1239 
1240  mx = dx/2;
1241  my = dy/2;
1242 
1243  pl =
1244  [
1245  [-mx, -my] + c,
1246  [-mx, my] + c,
1247  [ mx, my] + c,
1248  [ mx, -my] + c
1249  ];
1250 
1251  // draft each edge
1252  for ( cp = sequence_ns(pl, n=2, s=1, w=true) )
1253  draft_line(l=[cp[0], cp[1]], w=w, s=s);
1254 }
1255 
1256 //! Draft a polygon with configurable style.
1257 /***************************************************************************//**
1258  \param c <coords-2d> A list of 2d coordinate points.
1259 
1260  \param p <integer-list-list> A list of paths that enclose the
1261  shape where each face is a list of coordinate indexes.
1262  \param e <integer-list-2-list> A list of edges where each edge is
1263  a list of two coordinate indexes.
1264  \param i <index> An index sequence [specification].
1265 
1266  \param w <decimal> The line weight.
1267  \param s <integer | integer-list> The line style.
1268 
1269  \details
1270 
1271  Parameter \p p is optional and when it is not given, the listed
1272  order of the coordinates establishes the polygon path. When
1273  parameter \p e is not specified, it is computed from \p p using
1274  polytope_faces2edges(). Parameter \p i allows coordinate indexes to
1275  be selected using several selection [schemes][specification].
1276 
1277  \amu_eval ( object=draft_polygon ${object_diagram_2d} )
1278 
1279  The line segments are constructed by \ref draft_line().
1280 
1281  [specification]: \ref dt_index
1282 *******************************************************************************/
1283 module draft_polygon
1284 (
1285  c,
1286  p,
1287  e,
1288  i = true,
1289 
1290  w = 1,
1291  s = 1
1292 )
1293 {
1294  el = is_defined(e) ? e // use supplied edge list 'e'
1295  : polytope_faces2edges // construct from paths
1296  (
1297  is_defined(p) ? p // use supplied path list 'p'
1298  : [consts(len(c))] // connect all points in order supplied
1299  );
1300 
1301  // draft each selected edge
1302  for (i = index_gen(el, i)) // allow edge selection index
1303  draft_line(l=[c[first(el[i])], c[second(el[i])]], w=w, s=s);
1305 
1306 //! @}
1307 
1308 //----------------------------------------------------------------------------//
1309 
1310 //! \name Miscellaneous
1311 //! @{
1312 
1313 //! Extrude 2D drafted constructions to 3D if configured.
1314 /***************************************************************************//**
1315  \details
1316 
1317  When \ref $draft_make_3d is \b true, all children objects are
1318  extruded to 3D.
1319 
1320  | see: \ref draft_config_map |
1321  |:---------------------------:|
1322  | make-3d-height |
1323 *******************************************************************************/
1325 (
1326 )
1327 {
1328  if ( $draft_make_3d )
1329  linear_extrude
1330  (
1331  height=draft_get_config("make-3d-height") * $draft_scale, center=true
1332  )
1333  children();
1334  else
1335  children();
1336 }
1337 
1338 //! @}
1339 
1340 //! @}
1341 //! @}
1342 
1343 //----------------------------------------------------------------------------//
1344 // openscad-amu auxiliary scripts
1345 //----------------------------------------------------------------------------//
1346 
1347 /*
1348 BEGIN_SCOPE diagram;
1349  BEGIN_OPENSCAD;
1350  include <omdl-base.scad>;
1351  include <tools/align.scad>;
1352  include <tools/operation_cs.scad>;
1353  include <tools/polytope.scad>;
1354  include <tools/drafting/draft-base.scad>;
1355 
1356  object = "draft_arrow";
1357 
1358  if (object == "draft_arrow")
1359  {
1360  grid = [20, 10];
1361 
1362  for ( s=[1:5], f=[0:1], p=[0:2] )
1363  translate( [(p+1)*first(grid) + f*3*first(grid), s*second(grid)] )
1364  draft_arrow( l=x_axis2d_ul, s=[s, f, p] );
1365  }
1366 
1367  if (object == "draft_line")
1368  {
1369  line = [[0,0], [100,0]];
1370  for ( s=[1:5] )
1371  translate( [0, s*5] )
1372  draft_line(l=line, s=s);
1373  }
1374 
1375  if (object == "draft_arc")
1376  {
1377  for ( s=[1:2] )
1378  draft_arc (r=50-5*s, v1=[-1,1], v2=45, cw=true, s=s);
1379  }
1380 
1381  if (object == "draft_rectangle")
1382  {
1383  draft_rectangle ([100, 30], s=[4, 3, 2, 5]);
1384  }
1385 
1386  if (object == "draft_polygon")
1387  {
1388  pp = length
1389  (
1390  [ [+1.5 + 1/3, -1.25], [+1.5/4, 0], [+1.5 - 1/3, +1.25],
1391  [-1.5 + 1/3, +1.25], [-1.5/4, 0], [-1.5 - 1/3, -1.25]
1392  ], "in"
1393  );
1394 
1395  polytope_number(pp, vi=true, ei=false, fi=false);
1396 
1397  rp = polygon_round_eve_all_p(c=pp, vr=length(1/4, "in"), vrm=1, cw=false);
1398  draft_polygon(rp, s=2);
1399  }
1400  END_OPENSCAD;
1401 
1402  BEGIN_MFSCRIPT;
1403  include --path "${INCLUDE_PATH}" {var_init,var_gen_svg}.mfs;
1404 
1405  defines name "objects" define "object"
1406  strings "
1407  draft_arrow
1408  draft_line
1409  draft_arc
1410  draft_rectangle
1411  draft_polygon
1412  ";
1413  variables add_opts_combine "objects";
1414  variables add_opts "--viewall --autocenter";
1415 
1416  include --path "${INCLUDE_PATH}" scr_make_mf.mfs;
1417  END_MFSCRIPT;
1418 END_SCOPE;
1419 */
1421 //----------------------------------------------------------------------------//
1422 // end of file
1423 //----------------------------------------------------------------------------//
x_axis2d_ul
<line-2d> A positively-directed unit line centered on the x-axis in 2d Euclidean space.
Definition: constants.scad:416
origin2d
<point-2d> The origin point coordinate in 2d Euclidean space.
Definition: constants.scad:407
y_axis3d_ul
<line-3d> A positively-directed unit line centered on the y-axis in 3d Euclidean space.
Definition: constants.scad:440
x_axis2d_uv
<vector-2d> The unit vector of the positive x-axis in 2d Euclidean space.
Definition: constants.scad:410
function binary_bit_is(v, b, t=1)
Test if a binary bit position of an integer value equals a test bit.
function line_tp(l)
Return the terminal point of a line or vector.
function angle_ll(l1, l2, s=true)
Compute the angle between two lines or vectors in a 3d or 2d-space.
function line_ip(l)
Return the initial point of a line or vector.
function line2d_new(m=1, a=0, p1=origin2d, p2, v)
Construct a 2 dimensional directed line.
function distance_pp(p1, p2)
Compute the distance between two points.
function firstn(v, n=1)
Return a list containing the first n elements of an iterable value.
function find(mv, v, c=1, i, i1=0, i2)
Find the occurrences of a match value in an iterable value.
function defined_e_or(v, i, d)
Return an element of an iterable when it exists or a default value otherwise.
function last(v)
Return the last element of an iterable value.
function exists(mv, v, s=true, i)
Check for the existence of a match value in an iterable value.
function second(v)
Return the second element of an iterable value.
function lastn(v, n=1)
Return a list containing the last n elements of an iterable value.
function first(v)
Return the first element of an iterable value.
function sequence_ns(v, n=1, s=1, w=false)
Return a list of all n-element sequential-subsets of an iterable value.
function reverse(v)
Reverse the elements of an iterable value.
function all_equal(v, cv)
Test if all elements of an iterable value equal a comparison value.
function all_strings(v, c=0)
Test if all elements of an iterable value are strings.
function index_gen(l, s=true, rs)
Create a element selection index list for a given list of values.
function consts(l, v, u=false)
Create a list of constant or incrementing elements.
function merge_s(v, r=false)
Serially merge the elements of a list.
function sum(v, i1, i2)
Compute the sum of a list of numbers.
function map_get_value(m, k)
Get the map value associated with a key.
function map_get_firstof2_or(m1, m2, k, d)
Get the the first value associated with an existing key in one of two maps.
function defined_or(v, d)
Return given value, if defined, or a secondary value, if primary is not defined.
function is_defined(v)
Test if a value is defined.
function polygon_arc_p(r=1, c=origin2d, v1=x_axis2d_uv, v2=x_axis2d_uv, fn, cw=true)
Compute coordinates of an arc with constant radius between two vectors in 2D.
function polygon_regular_p(n, r, a, c=origin2d, o=0, vr, cw=true)
Compute coordinates for an n-sided regular polygon in 2D.
function polygon_line_p(p1=origin2d, p2=x_axis2d_uv, l, x, y, r, fs, ft, fn=1)
Compute coordinates along a line in 2D.
function polytope_faces2edges(f)
List the edge coordinate index pairs of a polytope.
module align_ll(l=z_axis3d_ul, r=z_axis3d_ul, lp=0, rp=0, ar=0, to=origin3d, ro=zero3d)
Align a line or vector to a reference line or vector.
Definition: align.scad:208
function draft_get_sheet_config(ci)
Get sheet configuration value helper function.
draft_layers_show
<string-list> List of active drafting layer names.
Definition: config.scad:554
$draft_make_3d
<boolean> Extrude 2D drafted constructions to 3D.
Definition: config.scad:89
$draft_scale
<integer> Line construction drafting scale multiplier.
Definition: config.scad:98
$draft_line_fn
<integer> Arc fragment size for line construction.
Definition: config.scad:92
function draft_get_config(k)
Get drafting configuration default helper function.
$draft_arrow_fn
<integer> Arc fragment size for arrowhead construction.
Definition: config.scad:95
function draft_get_sheet_size(ci)
Get sheet size value helper function.
draft_sheet_scale
<integer> Sheet construction drafting scale multiplier.
Definition: config.scad:101
module draft_line(l=x_axis2d_ul, w=1, s=1, a1=0, a2=0)
Draft a line with configurable style and optional arrowheads.
module draft_rectangle(d=1, c=origin2d, w=1, s=1)
Draft a rectangle with configurable style.
function draft_sheet_get_zone(rx, ry, ix, iy, zp=0, window=false, frame=false)
Get sheet, sheet-frame, or sheet-zone reference coordinates.
function draft_ztable_get_zone(i, zp=0, limits=false, window=false, map)
Get ztable zone coordinates given a zone index.
module draft_line_pp(i, t, w=1)
Draft a simple line from an initial to a terminal point.
Definition: primitive.scad:918
module draft_arrow(l=x_axis2d_ul, w=1, s=1)
Draft an arrowhead at the terminal point of a line.
Definition: primitive.scad:989
function draft_table_get_cell(ix, iy, zp=0, limits=false, window=false, map, fmap)
Get table cell coordinates given a column and row.
module draft_make_3d_if_configured()
Extrude 2D drafted constructions to 3D if configured.
function draft_layers_any_active(layers=draft_get_config("layers-default"))
Check if any identified layers are active.
module draft_ztable_text(i, text, size, fmt, dfmt, map)
Add text to ztable at a given zone index.
Definition: primitive.scad:853
module draft_polygon(c, p, e, i=true, w=1, s=1)
Draft a polygon with configurable style.
module draft_arc(r=1, c=origin2d, v1=x_axis2d_uv, v2=x_axis2d_uv, fn, cw=true, w=1, s=1, a1=0, a2=0)
Draft an arc with configurable style and optional arrowheads.
module draft_table_text(ix, iy, text, size, dfmt, map, fmap)
Add text to table cell at a given a column and row.
Definition: primitive.scad:628
module hull_cs(c=true, s)
Conditionally apply the convex hull transformation.