Rev Author Line No. Line
4641 jacho 1 /* Version 4
2 Added bold property bold=0 (not bold) bold=1(bolder by 1.1) bold=2(bolder by 1.2)
3 Added support for font selection (default is Letters.dxf)
4 Added WriteCube module
5 Added Rotate for text (rotates on the plane of the text)
6 Added writesphere
7 Added space= (spacing between characters in char widths) def=1
8 Added writecylinder()
9  
10 By Harlan Martin
11 harlan@sutlog.com
12 January 2012
13  
14 (The file TestWrite.scad gives More usage examples)
15 (This module requires the file Letters.dxf to reside in the same folder)
16 (The file Letters.dfx was created with inkscape..Each letter is in its own layer)
17 (This module seperates each letter in the string and imports it from Letters.dfx)
18  
19 */
20  
21 pi=3.1415926535897932384626433832795028841971693993751058209;
22 pi2=pi*2;
23  
24  
25 // These control the default values for write() writesphere() writecube()
26 // if the parameters are not included in the call. Feel free to set your own
27 // defaults.
28  
29 //default settings
30 bold=0;
31 center=false;
32 h = 4; //mm letter height
33 t = 1; //mm letter thickness
34 space =1; //extra space between characters in (character widths)
35 rotate=0; // text rotation (clockwise)
36 font = "Letters.dxf"; //default for aditional fonts
37  
38  
39 // write cube defaults
40 face = "front"; // default face (top,bottom,left,right,back,front)
41 up =0; //mm up from center on face of cube
42 down=0;
43 right =0; //mm left from center on face of cube
44 left=0;
45  
46  
47 // write sphere defaults
48 rounded=false; //default for rounded letters on writesphere
49 north=0; // intial text position (I suggest leave these 0 defaults)
50 south=0;
51 east=0;
52 west=0;
53 spin=0;
54 // writecylinder defaults
55 middle=0; //(mm toward middle of circle)
56 ccw=false; //write on top or bottom in a ccw direction
57 r1=0; //(not implimented yet)
58 r2=0; //(not implimented yet)
59  
60  
61  
62 // Contact me if your interested in how to make your own font files
63 // Its tedious and time consuming, but not very hard
64  
65  
66 module writecylinder(text,where,radius,height){
67 wid=(.125* h *5.5 * space);
68 widall=wid*(len(text)-1)/2;
69 //angle that measures width of letters on sphere
70 function NAngle(radius)=(wid/(pi2*radius))*360;
71 //angle of half width of text
72 function mmangle(radius)=(widall/(pi2*radius)*360);
73  
74 if ((face=="top")||(face=="bottom") ){
75 if (face=="top" ){
76 if (center==true){
77 writecircle(text,where+[0,0,height/2],radius-h,rotate=rotate,font=font,h=h,t=t,
78 space=space,east=east,west=west,middle=middle,ccw=ccw,bold=bold);
79 }else{
80 writecircle(text,where+[0,0,height],radius-h,rotate=rotate,font=font,h=h,t=t,
81 space=space,east=east,west=west,middle=middle,ccw=ccw,bold=bold);
82 }
83 }else{
84 rotate(180,[1,0,0])
85 if (center==true){
86 writecircle(text,where+[0,0,height/2],radius-h,rotate=rotate,font=font,h=h,t=t,
87 space=space,east=east,west=west,middle=middle,ccw=ccw,bold=bold);
88 }else{
89 writecircle(text,where+[0,0,0],radius-h,rotate=rotate,font=font,h=h,t=t,
90 space=space,east=east,west=west,middle=middle,ccw=ccw,bold=bold);
91 }
92 }
93  
94 }else{
95 // if (radius>0){
96 if (center==true) {
97 rotate(-mmangle(radius)*(1-abs(rotate)/90),[0,0,1])
98 translate(where)
99 writethecylinder(text,where,radius,height,r1=radius,r2=radius,h=h,
100 rotate=rotate,t=t,font=font,face=face,up=up,down=down,
101 east=east,west=west,center=center,space=space,rounded=rounded,bold=bold);
102 } else{
103 rotate(-mmangle(radius)*(1-abs(rotate)/90),[0,0,1])
104 translate(where+[0,0,height/2])
105 writethecylinder(text,where,radius,height,r1=radius,r2=radius,h=h,
106 rotate=rotate,t=t,font=font,face=face,up=up,down=down,
107 east=east,west=west,center=center,space=space,rounded=rounded,bold=bold);
108 }
109 // the remarked out code is for cone shaped cylinders (not complete)
110 // }else{
111 // if (center==true) {
112 // rotate(-mmangle(radius)*(1-abs(rotate)/90),[0,0,1])
113 // translate(where)
114 // writethecylinder(text,where,radius,height,r1=r1,r2=r2,h=h,
115 // rotate=rotate,t=t,font=font,face=face,up=up,down=down,
116 // east=east,west=west,center=center,space=space,rounded=rounded);
117 // } else{
118 // rotate(-mmangle(radius)*(1-abs(rotate)/90),[0,0,1])
119 // translate(where+[0,0,height/2])
120 // writethecylinder(text,where,radius,height,r1=r1,r2=r2,h=h,
121 // rotate=rotate,t=t,font=font,face=face,up=up,down=down,
122 // east=east,west=west,center=center,space=space,rounded=rounded);
123 // }
124 // }
125 }
126 }
127 module writecircle(text,where,radius){
128 wid=(.125* h *5.5 * space);
129 widall=wid*(len(text)-1)/2;
130 //angle that measures width of letters on sphere
131 function NAngle(radius)=(wid/(pi2*radius))*360;
132 //angle of half width of text
133 function mmangle(radius)=(widall/(pi2*radius)*360);
134  
135 if (ccw==true){
136 rotate(-rotate+east-west,[0,0,1]){
137 rotate(-mmangle(radius-middle),[0,0,1]){
138 translate(where)
139 for (r=[0:len(text)-1]){
140 rotate(-90+r*NAngle(radius-middle),[0,0,1]) // bottom out=-270+r
141 translate([radius-middle,0,0])
142 //rotate(90,[1,0,0])
143 //rotate(90,[0,1,0])
144 rotate(-270,[0,0,1]) // flip text (botom out = -270)
145 write(text[r],center=true,h=h,t=t,font=font,bold=bold);
146 }
147 }
148 }
149 }else{
150 rotate(-rotate-east+west,[0,0,1]){
151 rotate(mmangle(radius-middle),[0,0,1]){
152 translate(where)
153 for (r=[0:len(text)-1]){
154 rotate(90-r*NAngle(radius-middle),[0,0,1]) // bottom out=-270+r
155 translate([radius-middle,0,0])
156 //rotate(90,[1,0,0])
157 //rotate(90,[0,1,0])
158 rotate(270,[0,0,1]) // flip text (botom out = -270)
159 write(text[r],center=true,h=h,t=t,font=font,bold=bold);
160 }
161 }
162 }
163 }
164  
165 }
166 module writethecylinder(text,where,radius,height,r1,r2){
167 wid=(.125* h *5.5 * space);
168 widall=wid*(len(text)-1)/2;
169 //angle that measures width of letters on sphere
170 function NAngle(radius)=(wid/(pi2*radius))*360*(1-abs(rotate)/90);
171 //angle of half width of text
172  
173 function mmangle(radius)=(widall/(pi2*radius)*360);
174 translate([0,0,up-down])
175 rotate(east-west,[0,0,1])
176 for (r=[0:len(text)-1]){
177 rotate(-90+(r*NAngle(radius)),[0,0,1])
178 translate([radius,0,-r*((rotate)/90*wid)+(len(text)-1)/2*((rotate)/90*wid)])
179 rotate(90,[1,0,0])
180 rotate(90,[0,1,0])
181 write(text[r],center=true,h=h,rotate=rotate,t=t,font=font,bold=bold);
182 //echo("zloc=",height/2-r*((rotate)/90*wid)+(len(text)-1)/2*((rotate)/90*wid));
183 }
184  
185 }
186  
187  
188 module writesphere(text,where,radius){
189 wid=(.125* h *5.5 * space);
190 widall=wid*(len(text)-1)/2;
191  
192 echo("-----------------",widall,wid,mmangle(radius));
193 //angle that measures width of letters on sphere
194 function NAngle(radius)=(wid/(pi2*radius))*360;
195 //angle of half width of text
196 function mmangle(radius)=(widall/(pi2*radius)*360);
197  
198 rotate(east-west,[0,0,1]){
199 rotate(south-north,[1,0,0]){
200 rotate(spin,[0,1,0]){
201 rotate(-mmangle(radius),[0,0,1]){
202 if ( rounded== false ){
203 translate(where)
204 for (r=[0:len(text)-1]){
205 rotate(-90+r*NAngle(radius),[0,0,1])
206 translate([radius,0,0])
207 rotate(90,[1,0,0])
208 rotate(90,[0,1,0])
209 write(text[r],center=true,h=h,rotate=rotate,t=t,font=font,bold=bold);
210 }
211 }else{
212 difference(){
213 translate(where)
214 for (r=[0:len(text)-1]){
215 rotate(-90+r*NAngle(radius),[0,0,1])
216 translate([radius,0,0])
217 rotate(90,[1,0,0])
218 rotate(90,[0,1,0])
219 write(text[r],center=true,h=h,rotate=rotate,t=t*2+h,font=font,bold=bold);
220 }
221 difference(){ //rounded outside
222 sphere(radius+(t*2+h)*2);
223 sphere(radius+t/2);
224 }
225 sphere(radius-t/2); // rounded inside for indented text
226 }
227 }
228 }
229 }}}
230 }
231  
232  
233 module writecube(text,where,size){
234 if (str(size)[0] != "["){
235 // its a square cube (size was not a matrix so make it one)
236 writethecube(text,where,[size,size,size],h=h,rotate=rotate,space=space,
237 t=t,font=font,face=face,up=up,down=down,right=right,left=left,bold=bold);
238  
239 }else{
240 // its not square
241 writethecube(text,where,size,h=h,rotate=rotate,space=space,
242 t=t,font=font,face=face,up=up,down=down,right=right,left=left,bold=bold);
243 }
244 }
245 // I split the writecube module into 2 pieces.. easier to add features later
246 module writethecube(text,where,size){
247 if (face=="front") {
248 translate([where[0]+right-left,where[1]-size[1]/2,where[2]+up-down])
249 rotate(90,[1,0,0])
250 write(text,center=true,h=h,rotate=rotate,t=t,font=font,space=space,bold=bold);
251 }
252 if (face=="back") {
253 translate([where[0]+right-left,where[1]+size[1]/2,where[2]+up-down])
254 rotate(90,[1,0,0]) // rotate around the x axis
255 rotate(180,[0,1,0]) // rotate around the y axis (z before rotation)
256 write(text,center=true,h=h,rotate=rotate,t=t,font=font,space=space,bold=bold);
257 }
258 if (face=="left") {
259 translate([where[0]-size[0]/2,where[1]-right+left,where[2]+up-down ])
260 rotate(90,[1,0,0]) // rotate around the x axis
261 rotate(90,[0,-1,0]) // rotate around the y axis (z before rotation)
262 write(text,center=true,h=h,rotate=rotate,t=t,font=font,space=space,bold=bold);
263 }
264 if (face=="right") {
265 translate([where[0]+size[0]/2,where[1]+right-left,where[2] +up-down])
266 rotate(90,[1,0,0]) // rotate around the x axis
267 rotate(90,[0,1,0]) // rotate around the y axis (z before rotation)
268 write(text,center=true,h=h,rotate=rotate,t=t,font=font,space=space,bold=bold);
269 }
270 if (face=="top") {
271 translate([where[0]+right-left,where[1]+up-down,where[2]+size[2]/2 ])
272 write(text,center=true,h=h,rotate=rotate,t=t,font=font,space=space,bold=bold);
273 }
274 if (face=="bottom") {
275 translate([where[0]+right-left,where[1]-up+down,where[2]-size[2]/2 ])
276 rotate(180,[1,0,0])
277 write(text,center=true,h=h,rotate=rotate,t=t,font=font,space=space,bold=bold);
278 }
279 }
280  
281 module write(word){
282  
283 echo (h);
284 echo (word);
285 echo ("There are " ,len(word) ," letters in this string");
286 // echo ("The second letter is ",word[1]);
287 // echo (str(word[0],"_"));
288 minkowski() {
289 rotate(rotate,[0,0,-1]){
290  
291 for (r = [0:len(word)]){ // count off each character
292 // if the letter is lower case, add an underscore to the end for file lookup
293 if ((word[r] == "a" ) || (word[r]== "b") || (word[r]== "c")
294 || (word[r]== "d") || (word[r]== "e") || (word[r]== "f")
295 || (word[r]== "g") || (word[r]== "h") || (word[r]== "i")
296 || (word[r]== "j") || (word[r]== "k") || (word[r]== "l")
297 || (word[r]== "m") || (word[r]== "n") || (word[r]== "o")
298 || (word[r]== "p") || (word[r]== "q") || (word[r]== "r")
299 || (word[r]== "s") || (word[r]== "t") || (word[r]== "u")
300 || (word[r]== "v") || (word[r]== "w") || (word[r]== "x")
301 || (word[r]== "y" )|| (word[r]== "z")){
302 if (center == true) {
303 translate([0,-h/2,0]){
304 scale([.125*h,.125*h,t]){
305 translate([ (-len(word)*5.5*space/2) + (r*5.5*space),0,0])
306 //offset(delta = 20, join_type = "round") {
307 linear_extrude(height=1,convexity=10,center=true){
308 import(file = font,layer=str(word[r],"_"));
309 }//}
310 }
311 }
312 }else{
313 translate([0,0,t/2]){
314 scale([.125*h,.125*h,t]){
315 translate([r*5.5*space,0,0])
316 //offset(delta = 20, join_type = "round") {
317 linear_extrude(height=1,convexity=10,center=true){
318 import(file = font,layer=str(word[r],"_"));
319 }//}
320 }
321 }
322 }
323  
324 }else{
325 if (center == true) {
326 translate([0,-h/2,0]){
327 scale([.125*h,.125*h,t]){
328 translate([ (-len(word)*5.5*space/2) + (r*5.5*space),0,0])
329 //offset(delta = 20, join_type = "round") {
330 linear_extrude(height=1,convexity=10,center=true){
331 import(file = font,layer=str(word[r]));
332 }//}
333 }
334 }
335 }else{
336 translate([0,0,t/2]){
337 scale([.125*h,.125*h,t]){
338 translate([r*5.5*space,0,0])
339 //offset(delta = 20, join_type = "round") {
340 linear_extrude(height=1,convexity=10,center=true){
341 import(file = font,layer=str(word[r]));
342 }//}
343 }
344 }
345 }
346 }
347 }
348 }
349 cube([bold*.1*h,bold*.1*h,.00001]);
350 }
351 }
352  
353 /*writecylinder test
354 translate([0,0,0])
355 %cylinder(r=20,h=40,center=true);
356 color([1,0,0])
357 writecylinder("rotate=90",[0,0,0],20,40,center=true,down=0,rotate=90);
358 writecylinder("rotate = 30,east = 90",[0,0,0],20,40,center=true,down=0,rotate=30,east=90);
359 writecylinder("ccw = true",[0,0,0],20,40,center=true,down=0,face="top",ccw=true);
360 writecylinder("middle = 8",[0,0,0],20,40,h=3,center=true,down=0,face="top",middle=8);
361 writecylinder("face = top",[0,0,0],20,40,center=true,down=0,face="top");
362 writecylinder("east=90",[0,0,0],20,40,h=3,center=true,down=0,face="top",east=90);
363 writecylinder("west=90",[0,0,0],20,40,h=3,center=true,down=0,face="top",ccw=true,west=90);
364 writecylinder("face = bottom",[0,0,0],20,40,center=true,down=0,face="bottom");
365 */
366 /*writesphere test
367 sphere(20);
368 color([1,0,0])
369 writesphere("Hello World",[0,0,0],20,t=1,h=6);
370 */
371 /* writecube test
372 translate([30,30,30])
373 cube([10,15,30],center=true);
374 write("hello",center=true,rotate =30);
375 color([1,0,0])
376 writecube( "front",[30,30,30],[10,15,30],h=5,rotate=-90);
377 color([0,1,0])
378 writecube( "back",[30,30,30],size=[10,15,30],h=5,face="back",rotate=90,t=4);
379 color([0,0,1])
380 writecube( "left",[30,30,30],[10,15,30],h=5,face="left",up=5);
381 color([1,1,0])
382 writecube( "right",where=[30,30,30],size=[10,15,30],h=5,face="right",rotate=55);
383 color([1,0,1])
384 writecube( "top",where=[30,30,30],size=[10,15,30],h=5,face="top");
385 color([1,1,1])
386 writecube( "bttm",where=[30,30,30],size=[10,15,30],h=5,face="bottom",rotate=90);
387 */
388