My self-made 3D-printable designs, mainly in OpenSCAD
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Write.scad 13KB

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