Copyright notice inclussion
[3dmodels/seg_digit.git] / seg_digit.scad
1 /*
2  * seg_digit.scad : 7 segment and 16 segment digit generation library
3  * 
4  * Author : Jose Ignacio Croce Busquets <jose@crossforests.com>
5  *
6  * Date : 15-FEB-2014
7  *
8  * Copyright 2014, 2015 Jose Ignacio Croce Busquets
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  * Usage
24  * The module contains the following public methods
25  *
26  * segment_a(size, on = true)
27  * segment_b(size, on = true)
28  * segment_c(size, on = true)
29  * segment_d(size, on = true)
30  * segment_e(size, on = true)
31  * segment_f(size, on = true)
32  * segment_g(size, on = true) Write the corresponding segment for a 7
33  *                            segment display
34  *                            size = segment size
35  *                            on = on-relief/low-relief flag
36  *
37  * segment_a1(size, on = true)
38  * segment_a2(size, on = true)
39  * segment_d1(size, on = true)
40  * segment_d2(size, on = true)
41  * segment_g1(size, on = true)
42  * segment_g2(size, on = true)
43  * segment_h(size, on = true)
44  * segment_i(size, on = true)
45  * segment_j(size, on = true)
46  * segment_k(size, on = true)
47  * segment_l(size, on = true)
48  * segment_m(size, on = true)  Write the aditional segments for a 16
49  *                             segment display
50  *                             size = segment size
51  *                             on = on-relief/low-relief flag
52  *
53  * segment_dp(digit_size, on = true)
54  *                            Write the decimal point for a 7 segment display
55  *                            digit_size = whole digit size
56  *                            on = on-relief/low-relief flag
57  */
58
59 /* Segment length based on digit height */
60 function segment_length(height) = height / 2;
61
62 /* digit height based on segment length */
63 function digit_height(seglen) = 2 * seglen;
64
65 /* Segment radius based on segment length */
66 function segment_radius(seglen) = seglen / 10;
67
68 /* Position (horiz) for next digit based on digit length */
69 function digit_spacing(height) = segment_length(height)
70                                + 6 * segment_radius(segment_length(height));
71
72 /* Draws A segment (top)
73  *  size segment size
74  *  on   on-relief/low-relief flag
75  */
76 module segment_a(size, on = true)
77 {
78  translate(v = [ 0, digit_height(size), 0 ])
79    segment(size, on = on);
80 }
81
82 /* Draws A1 segment (top)
83  *  size segment size
84  *  on   on-relief/low-relief flag
85  */
86 module segment_a1(size, on = true)
87 {
88  translate(v = [ 0, digit_height(size), 0 ])
89    segment(size /2 , r = segment_radius(size), on = on);
90 }
91
92 /* Draws A2 segment (top)
93  *  size segment size
94  *  on   on-relief/low-relief flag
95  */
96 module segment_a2(size, on = true)
97 {
98  translate(v = [ size / 2, digit_height(size), 0 ])
99    segment(size /2 , r = segment_radius(size), on = on);
100 }
101
102 /* Draws B segment (right top)
103  *  size segment size
104  *  on   on-relief/low-relief flag
105  */
106 module segment_b(size, on = true)
107 {
108  translate(v = [ 0, size, 0 ])
109    segment_c(size, on = on);
110 }
111
112 /* Draws C segment (right bottom)
113  *  size segment size
114  *  on   on-relief/low-relief flag
115  */
116 module segment_c(size, on = true)
117 {
118  translate(v = [ size, size, 0 ])
119    rotate(a = [ 0, 0, 270 ])
120      segment(size, on = on);
121 }
122
123 /* Draws D segment (bottom)
124  *  size segment size
125  *  on   on-relief/low-relief flag
126  */
127 module segment_d(size, on = true)
128 {
129  segment(size, on = on);
130 }
131
132 /* Draws D1 segment (top)
133  *  size segment size
134  *  on   on-relief/low-relief flag
135  */
136 module segment_d1(size, on = true)
137 {
138  segment(size /2 , r = segment_radius(size), on = on);
139 }
140
141 /* Draws D2 segment (top)
142  *  size segment size
143  *  on   on-relief/low-relief flag
144  */
145 module segment_d2(size, on = true)
146 {
147  translate(v = [ size / 2, 0, 0 ])
148    segment(size /2 , r = segment_radius(size), on = on);
149 }
150
151 /* Draws E segment (left bottom)
152  *  size segment size
153  *  on   on-relief/low-relief flag
154  */
155 module segment_e(size, on = true)
156 {
157  rotate(a = [ 0, 0, 90 ])
158    segment(size, on = on);
159 }
160
161 /* Draws F segment (left top)
162  *  size segment size
163  *  on   on-relief/low-relief flag
164  */
165 module segment_f(size, on = true)
166 {
167  translate(v = [ 0, size, 0 ])
168    segment_e(size, on = on);
169 }
170
171 /* Draws G segment (middle)
172  *  size segment size
173  *  on   on-relief/low-relief flag
174  */
175 module segment_g(size, on = true)
176 {
177  translate(v = [ 0, size, 0 ])
178    segment_d(size, on = on);
179 }
180
181 /* Draws G1 segment (top)
182  *  size segment size
183  *  on   on-relief/low-relief flag
184  */
185 module segment_g1(size, on = true)
186 {
187  translate(v = [ 0, size, 0 ])
188    segment(size /2 , r = segment_radius(size), on = on);
189 }
190
191 /* Draws G2 segment (top)
192  *  size segment size
193  *  on   on-relief/low-relief flag
194  */
195 module segment_g2(size, on = true)
196 {
197  translate(v = [ size / 2, size, 0 ])
198    segment(size /2 , r = segment_radius(size), on = on);
199 }
200
201 /* Draws H segment (upper left diagonal)
202  *  size segment size
203  *  on   on-relief/low-relief flag
204  */
205 module segment_h(size, on = true)
206 {
207  translate(v = [ size / 2, size, 0 ])
208    mirror([ 1, 0, 0 ])
209      diag_segment(size, on = on);
210 }
211
212 /* Draws I segment (middle top)
213  *  size segment size
214  *  on   on-relief/low-relief flag
215  */
216 module segment_i(size, on = true)
217 {
218  translate(v = [ -size / 2, 0, 0 ])
219    segment_b(size, on = on);
220 }
221
222 /* Draws J segment (upper right diagonal)
223  *  size segment size
224  *  on   on-relief/low-relief flag
225  */
226 module segment_j(size, on = true)
227 {
228  translate(v = [ size / 2, size, 0 ])
229    diag_segment(size, on = on);
230 }
231
232 /* Draws K segment (lower right diagonal)
233  *  size segment size
234  *  on   on-relief/low-relief flag
235  */
236 module segment_k(size, on = true)
237 {
238  translate(v = [ size, 0, 0 ])
239    mirror([ 1, 0, 0 ])
240      diag_segment(size, on = on);
241 }
242
243 /* Draws L segment (middle bottom)
244  *  size segment size
245  *  on   on-relief/low-relief flag
246  */
247 module segment_l(size, on = true)
248 {
249  translate(v = [ -size / 2, 0, 0 ])
250    segment_c(size, on = on);
251 }
252
253 /* Draws M segment (lower left diagonal)
254  *  size segment size
255  *  on   on-relief/low-relief flag
256  */
257 module segment_m(size, on = true)
258 {
259  diag_segment(size, on = on);
260 }
261
262 /*
263  * Place the decimal point at the end of the character
264  * size segment size
265  * on on-relief/low-relief flag
266  */
267 module segment_p(size, on = true)
268 {
269  radius = segment_radius(size);
270  translate(v = [ size + radius, 0, 0 ])
271    decimal_point(size, on = on);
272 }
273
274 //---------------------------------------------------------------------------
275 // End of public modules - Just jump to the examples
276 //---------------------------------------------------------------------------
277
278 /*
279  * Draws a decimal point
280  * size segment size
281  * on on-relief/low-relief flag
282  */
283 module decimal_point(size, on = true)
284 {
285  radius = segment_radius(size);
286  if (on)
287  {
288   translate(v = [ radius, 0, 0 ])
289     polyhedron(points = [ [ -radius, -radius,      0 ]
290                         , [ -radius,  radius,      0 ]
291                         , [  radius,  radius,      0 ]
292                         , [  radius, -radius,      0 ]
293                         , [       0,       0, radius ]
294                         ]
295           , triangles = [ [ 0, 1, 4 ]
296                         , [ 1, 2, 4 ]
297                         , [ 2, 3, 4 ]
298                         , [ 0, 4, 3 ]
299                         , [ 0, 3, 1 ]
300                         , [ 1, 3, 2 ]
301                         ]);
302  } else {
303   translate(v = [ radius, 0, 0 ])
304   {
305    polyhedron(points = [ [ -radius, -radius,       0 ]
306                        , [ -radius,  radius,       0 ]
307                        , [  radius,  radius,       0 ]
308                        , [  radius, -radius,       0 ]
309                        , [       0,       0, -radius ]
310                        ]
311          , triangles = [ [ 0, 4, 1 ]
312                        , [ 1, 4, 2 ]
313                        , [ 2, 4, 3 ]
314                        , [ 0, 3, 4 ]
315                        , [ 0, 1, 3 ]
316                        , [ 1, 2, 3 ]
317                        ]);
318    translate(v = [ 0, 0, radius / 2 ])
319      cube(size= [ 2 * radius, 2 * radius, radius ], center = true);
320   }
321  }
322 }
323
324 /* Draws a single segment
325  *  size segment size
326  *  r    segment radius (default = segment_radius(h))
327  *  on   on-relief/low-relief flag
328  */
329 module segment(size, r = 0, on = true)
330 {
331  radius = (r == 0) ? segment_radius(size) : r;
332  length = (size > 2 * radius) ? size - 2 * radius : 0;
333  if (on)
334  {
335   polyhedron(points = [ [                   0,       0,      0 ]
336                       , [     radius         ,  radius,      0 ]
337                       , [     radius + length,  radius,      0 ]
338                       , [ 2 * radius + length,       0,      0 ]
339                       , [     radius + length, -radius,      0 ]
340                       , [     radius         , -radius,      0 ]
341                       , [     radius         ,       0, radius ]
342                       , [     radius + length,       0, radius ]
343                       ]
344         , triangles = [ [ 0, 1, 6 ]
345                       , [ 1, 2, 6 ]
346                       , [ 2, 7, 6 ]
347                       , [ 2, 3, 7 ]
348                       , [ 3, 4, 7 ]
349                       , [ 4, 5, 7 ]
350                       , [ 5, 6, 7 ]
351                       , [ 0, 6, 5 ]
352                       , [ 0, 5, 1 ]
353                       , [ 1, 5, 4 ]
354                       , [ 1, 4, 2 ]
355                       , [ 2, 4, 3 ]
356                       ]);
357  } else {
358   polyhedron(points = [ [                   0,       0,       0 ]
359                       , [     radius         ,  radius,       0 ]
360                       , [     radius + length,  radius,       0 ]
361                       , [ 2 * radius + length,       0,       0 ]
362                       , [     radius + length, -radius,       0 ]
363                       , [     radius         , -radius,       0 ]
364                       , [     radius         ,       0, -radius ]
365                       , [     radius + length,       0, -radius ]
366                       ]
367         , triangles = [ [ 0, 6, 1 ]
368                       , [ 1, 6, 2 ]
369                       , [ 2, 6, 7 ]
370                       , [ 2, 7, 3 ]
371                       , [ 3, 7, 4 ]
372                       , [ 4, 7, 5 ]
373                       , [ 5, 7, 6 ]
374                       , [ 0, 5, 6 ]
375                       , [ 0, 1, 5 ]
376                       , [ 1, 4, 5 ]
377                       , [ 1, 2, 4 ]
378                       , [ 2, 3, 4 ]
379                       ]);
380   linear_extrude(height = radius)
381     polygon(points = [ [ 0                  ,        0]
382                      , [     radius         ,  radius ]
383                      , [     radius + length,  radius ]
384                      , [ 2 * radius + length,       0 ]
385                      , [     radius + length, -radius ]
386                      , [     radius         , -radius ]
387                      ]
388            , paths = [ [ 0, 1, 2, 3, 4, 5 ] ]);
389  }
390 }
391
392 /* Draws a diagonal segment
393  *  size segment size
394  *  r    segment radius (default = segment_radius(h))
395  *  on   on-relief/low-relief flag
396  */
397 module diag_segment(size, r = 0, on = true)
398 {
399  radius = (r == 0) ? segment_radius(size) : r;
400  length = (size > 2 * radius) ? size - 2 * radius : 0;
401  if (on)
402  {
403   polyhedron(points = [
404                     [                   radius,               radius,      0 ]
405                   , [                   radius,        2.41 * radius,      0 ]
406                   , [ size / 2 - 2.41 * radius, size -        radius,      0 ]
407                   , [ size / 2 -        radius, size -        radius,      0 ]
408                   , [ size / 2 -        radius, size - 2.41 * radius,      0 ]
409                   , [            2.41 * radius,               radius,      0 ]
410                   , [            1.70 * radius,        1.70 * radius, radius ]
411                   , [ size / 2 - 1.70 * radius, size - 1.70 * radius, radius ]
412                       ]
413         , triangles = [ [ 0, 1, 6 ]
414                       , [ 1, 2, 6 ]
415                       , [ 2, 7, 6 ]
416                       , [ 2, 3, 7 ]
417                       , [ 3, 4, 7 ]
418                       , [ 4, 5, 7 ]
419                       , [ 5, 6, 7 ]
420                       , [ 0, 6, 5 ]
421                       , [ 0, 5, 1 ]
422                       , [ 1, 5, 4 ]
423                       , [ 1, 4, 2 ]
424                       , [ 2, 4, 3 ]
425                       ]);
426  } else {
427   polyhedron(points = [
428                    [                   radius,               radius,       0 ]
429                  , [                   radius,        2.41 * radius,       0 ]
430                  , [ size / 2 - 2.41 * radius, size -        radius,       0 ]
431                  , [ size / 2 -        radius, size -        radius,       0 ]
432                  , [ size / 2 -        radius, size - 2.41 * radius,       0 ]
433                  , [            2.41 * radius,               radius,       0 ]
434                  , [            1.70 * radius,        1.70 * radius, -radius ]
435                  , [ size / 2 - 1.70 * radius, size - 1.70 * radius, -radius ]
436                       ]
437         , triangles = [ [ 0, 1, 6 ]
438                       , [ 1, 2, 6 ]
439                       , [ 2, 7, 6 ]
440                       , [ 2, 3, 7 ]
441                       , [ 3, 4, 7 ]
442                       , [ 4, 5, 7 ]
443                       , [ 5, 6, 7 ]
444                       , [ 0, 6, 5 ]
445                       , [ 0, 5, 1 ]
446                       , [ 1, 5, 4 ]
447                       , [ 1, 4, 2 ]
448                       , [ 2, 4, 3 ]
449                       ]);
450   linear_extrude(height = radius)
451     polygon(points = [ [                   radius,               radius ]
452                      , [                   radius,        2.41 * radius ]
453                      , [ size / 2 - 2.41 * radius, size -        radius ]
454                      , [ size / 2 -        radius, size -        radius ]
455                      , [ size / 2 -        radius, size - 2.41 * radius ]
456                      , [            2.41 * radius,               radius ]
457                      ]
458            , paths = [ [ 0, 1, 2, 3, 4, 5 ] ]);
459  }
460 }
461
462 //---------------------------------------------------------------------------
463 // Examples
464 //---------------------------------------------------------------------------
465
466 ex_seglen = 100;        // segment length for all examples
467
468 // Base for on-relief examples
469 translate(v = [ 0
470               , -2 * digit_height(ex_seglen)
471               , -2 * segment_radius(digit_height(ex_seglen)) ])
472   cube(size = [ 2 * digit_spacing(digit_height(ex_seglen))
473               , 4 * digit_height(ex_seglen)
474               , 2 * segment_radius(digit_height(ex_seglen))
475               ]);
476
477 // On relief examples
478
479 // 7 segment on-relief example
480 translate(v = [ digit_spacing(digit_height(ex_seglen)) / 2
481               , digit_height(ex_seglen) / 2
482               , 0 ])
483 {
484  segment_a(ex_seglen);
485  segment_b(ex_seglen);
486  segment_c(ex_seglen);
487  segment_d(ex_seglen);
488  segment_e(ex_seglen);
489  segment_f(ex_seglen);
490  segment_g(ex_seglen);
491  segment_p(ex_seglen);
492 }
493
494 // 16 segment on-relief example
495 translate(v = [ digit_spacing(digit_height(ex_seglen)) / 2
496               , -1.5 * digit_height(ex_seglen)
497               , 0 ])
498 {
499  segment_a1(ex_seglen);
500  segment_a2(ex_seglen);
501  segment_b(ex_seglen);
502  segment_c(ex_seglen);
503  segment_d1(ex_seglen);
504  segment_d2(ex_seglen);
505  segment_e(ex_seglen);
506  segment_f(ex_seglen);
507  segment_g1(ex_seglen);
508  segment_g2(ex_seglen);
509  segment_h(ex_seglen);
510  segment_i(ex_seglen);
511  segment_j(ex_seglen);
512  segment_k(ex_seglen);
513  segment_l(ex_seglen);
514  segment_m(ex_seglen);
515  segment_p(ex_seglen);
516 }
517
518 // Low relief examples
519 // Low relief effect is performed by substracting from the base
520 translate(v = [ 2 * digit_spacing(digit_height(ex_seglen)), 0, 0 ])
521   difference()
522   {
523     // Base for low-relief examples
524    translate(v = [ 0
525                  , -2 * digit_height(ex_seglen)
526                  , -2 * segment_radius(digit_height(ex_seglen)) ])
527       cube(size = [ 2 * digit_spacing(digit_height(ex_seglen))
528                   , 4 * digit_height(ex_seglen)
529                   , 2 * segment_radius(digit_height(ex_seglen))
530                   ]);
531
532     // 7 segment low-relief example
533     translate(v = [ digit_spacing(digit_height(ex_seglen)) / 2
534                   , digit_height(ex_seglen) / 2
535                   , 0 ])
536     {
537      segment_a(ex_seglen, on = false);
538      segment_b(ex_seglen, on = false);
539      segment_c(ex_seglen, on = false);
540      segment_d(ex_seglen, on = false);
541      segment_e(ex_seglen, on = false);
542      segment_f(ex_seglen, on = false);
543      segment_g(ex_seglen, on = false);
544      segment_p(ex_seglen, on = false);
545     }
546
547     // 16 segment on-relief example
548     translate(v = [ digit_spacing(digit_height(ex_seglen)) / 2
549                   , -1.5 * digit_height(ex_seglen)
550                   , 0 ])
551     {
552      segment_a1(ex_seglen, on = false);
553      segment_a2(ex_seglen, on = false);
554      segment_b(ex_seglen, on = false);
555      segment_c(ex_seglen, on = false);
556      segment_d1(ex_seglen, on = false);
557      segment_d2(ex_seglen, on = false);
558      segment_e(ex_seglen, on = false);
559      segment_f(ex_seglen, on = false);
560      segment_g1(ex_seglen, on = false);
561      segment_g2(ex_seglen, on = false);
562      segment_h(ex_seglen, on = false);
563      segment_i(ex_seglen, on = false);
564      segment_j(ex_seglen, on = false);
565      segment_k(ex_seglen, on = false);
566      segment_l(ex_seglen, on = false);
567      segment_m(ex_seglen, on = false);
568      segment_p(ex_seglen, on = false);
569     }
570
571   }
572
573 /* EOF : seg_digit.scad */