discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

3D keychains and cutting out the "whitespace" of text?

P
playmeforafool
Wed, Nov 4, 2020 3:00 AM

Back when I was doing woodworking, using a scrollsaw, I would cut 3D
keychains with 2 words (usually first and last name).  Basically you start
out with a length of wood that is the same depth and height and tape a
pattern of the words on the top and face of the block and cut out the wood
AROUND the letters -- examples  here
https://www.youtube.com/watch?v=6tvOxHixwoo  and  here
http://www.scrollbench.com/2011/02/using-scroll-saw-workshops-keychain.html
.
Since I got my 3D printer I've been wanting to recreate these in plastic.
I can sort of SIMULATE the result of cutting the first word by creating a
rectangle, cutting out a smaller version of the block and then putting in
the text and extruding it:

----------8<---Cut-Here---8<----------
fName="FNAME";
lName="LNAME";
height=10;

difference() {
cube([44,height,height]);
translate([1,-1,1]) cube([42,52,height-2]);
}

translate([1.5,10,1])
rotate(90,[1,0,0])
linear_extrude(height)
text(lName,8.5);
----------8<---Cut-Here---8<----------
http://forum.openscad.org/file/t3003/lname_block.png
But then I'm stuck, as I can't do that again for the 2nd word from the top.
What I REALLY need is a way to cut out the whitespace around the letters.
Does anyone have any ideas of how to do this?
The other problem is trying to figure out how long to make the block based
on the size of the text/font...
... Billy ...

--
Sent from: http://forum.openscad.org/

Back when I was doing woodworking, using a scrollsaw, I would cut 3D keychains with 2 words (usually first and last name). Basically you start out with a length of wood that is the same depth and height and tape a pattern of the words on the top and face of the block and cut out the wood AROUND the letters -- examples here <https://www.youtube.com/watch?v=6tvOxHixwoo> and here <http://www.scrollbench.com/2011/02/using-scroll-saw-workshops-keychain.html> . Since I got my 3D printer I've been wanting to recreate these in plastic. I can sort of SIMULATE the result of cutting the first word by creating a rectangle, cutting out a smaller version of the block and then putting in the text and extruding it: ----------8<---Cut-Here---8<---------- fName="FNAME"; lName="LNAME"; height=10; difference() { cube([44,height,height]); translate([1,-1,1]) cube([42,52,height-2]); } translate([1.5,10,1]) rotate(90,[1,0,0]) linear_extrude(height) text(lName,8.5); ----------8<---Cut-Here---8<---------- <http://forum.openscad.org/file/t3003/lname_block.png> But then I'm stuck, as I can't do that again for the 2nd word from the top. What I REALLY need is a way to cut out the whitespace around the letters. Does anyone have any ideas of how to do this? The other problem is trying to figure out how long to make the block based on the size of the text/font... ... Billy ... -- Sent from: http://forum.openscad.org/
R
rickan
Wed, Nov 4, 2020 4:15 AM

fname="BARB";
lname="WALLS";

height = 1;
length = 5;
margin = .1;
sf = 20;

module cutcubes(){
cube([length - margin2, height - margin2, height + .02], center=true);
}

module cutcubec(){
cube([length - margin2, height - margin2, height - margin*2 ],
center=true);
}

module cutname(name){
difference(){
difference(){
union(){
difference(){
cube([length, height, height], center=true);
cutcubes();
}
translate([0, 0, -height/2])
linear_extrude(height, convexity=2)
text(name, height - margin, valign="center", halign="center");
}
cutcubec();
}
rotate(90, [1, 0, 0])
cutcubes();
}
}

scale(sf){
cutname(fname);
rotate(90, [1, 0, 0])
cutname(lname);
}

--
Sent from: http://forum.openscad.org/

fname="BARB"; lname="WALLS"; height = 1; length = 5; margin = .1; sf = 20; module cutcubes(){ cube([length - margin*2, height - margin*2, height + .02], center=true); } module cutcubec(){ cube([length - margin*2, height - margin*2, height - margin*2 ], center=true); } module cutname(name){ difference(){ difference(){ union(){ difference(){ cube([length, height, height], center=true); cutcubes(); } translate([0, 0, -height/2]) linear_extrude(height, convexity=2) text(name, height - margin, valign="center", halign="center"); } cutcubec(); } rotate(90, [1, 0, 0]) cutcubes(); } } scale(sf){ cutname(fname); rotate(90, [1, 0, 0]) cutname(lname); } -- Sent from: http://forum.openscad.org/
TP
Torsten Paul
Wed, Nov 4, 2020 4:17 AM

The general answer is probably intersection():

fName="FNAME";
lName="LNAME";
height=10;

intersection() {
linear_extrude(height, center = true, convexity = 3)
text(fName,height, font="Courier New:style=Bold", halign="center", valign="center");

rotate([90, 0, 0])
linear_extrude(height, center = true, convexity = 3)
text(lName,height, font="Courier New:style=Bold", halign="center", valign="center");
}

I suspect that works best with a bold mono-spaced font.

(See also File->Examples->Advanced->GEB for a 3 axis version)

ciao,
Torsten.

The general answer is probably intersection(): fName="FNAME"; lName="LNAME"; height=10; intersection() { linear_extrude(height, center = true, convexity = 3) text(fName,height, font="Courier New:style=Bold", halign="center", valign="center"); rotate([90, 0, 0]) linear_extrude(height, center = true, convexity = 3) text(lName,height, font="Courier New:style=Bold", halign="center", valign="center"); } I suspect that works best with a bold mono-spaced font. (See also File->Examples->Advanced->GEB for a 3 axis version) ciao, Torsten.
R
rickan
Wed, Nov 4, 2020 1:12 PM

$fn = 50;
fname="BARB";
lname="WALLS";

height = 1;
length = 5;
margin = .1;
sf = 20;

module stock(){
hl = (length - 1)/2;
cube([length - 1, height, height], center=true);
translate([-hl, 0, 0])
cylinder(height, d=height, center=true);
translate([hl, 0, 0])
cylinder(height, d=height, center=true);
}

module cutstock(){
hl = (length - 1)/2;
cube([length - 1, height - margin2, height + .02], center=true);
translate([-hl, 0, 0])
cylinder(height + .02, d=height-margin
2, center=true);
translate([hl, 0, 0])
cylinder(height + .02, d=height-margin*2, center=true);
}

module case(){
difference(){
stock();
cutstock();
}
}

module cutname(name){
case();
translate([0, 0, -height/2])
linear_extrude(height, convexity=2)
text(name, height - margin, valign="center", halign="center");
}

scale(sf){
intersection(){
cutname(fname);
rotate(90, [1, 0, 0])
cutname(lname);
}
}

/*
I like that this enables rounding the ends, but I'm not so sure I like the
messy internals even though that's probably what the sawn version looks
like.
*/

--
Sent from: http://forum.openscad.org/

$fn = 50; fname="BARB"; lname="WALLS"; height = 1; length = 5; margin = .1; sf = 20; module stock(){ hl = (length - 1)/2; cube([length - 1, height, height], center=true); translate([-hl, 0, 0]) cylinder(height, d=height, center=true); translate([hl, 0, 0]) cylinder(height, d=height, center=true); } module cutstock(){ hl = (length - 1)/2; cube([length - 1, height - margin*2, height + .02], center=true); translate([-hl, 0, 0]) cylinder(height + .02, d=height-margin*2, center=true); translate([hl, 0, 0]) cylinder(height + .02, d=height-margin*2, center=true); } module case(){ difference(){ stock(); cutstock(); } } module cutname(name){ case(); translate([0, 0, -height/2]) linear_extrude(height, convexity=2) text(name, height - margin, valign="center", halign="center"); } scale(sf){ intersection(){ cutname(fname); rotate(90, [1, 0, 0]) cutname(lname); } } /* I like that this enables rounding the ends, but I'm not so sure I like the messy internals even though that's probably what the sawn version looks like. */ -- Sent from: http://forum.openscad.org/
R
rickan
Wed, Nov 4, 2020 1:33 PM

But it's easy to ream out the center in cutname() using a modified
cutcubec().

--
Sent from: http://forum.openscad.org/

But it's easy to ream out the center in cutname() using a modified cutcubec(). -- Sent from: http://forum.openscad.org/
F
fred_dot_u
Wed, Nov 4, 2020 2:01 PM

This is comparable to creating an ambigram, although on two different axes
from the tutorial I found.
This  tutorial https://www.youtube.com/watch?v=baO1-HSodIs  uses Fusion
360 to create text in two planes by intersection, just as with the samples
of code provided in the posts here. The video is 26 minutes long.

I've used it with the hobbyist version of F360 and it works great, resulting
in a number of 3D printed gifts to friends and family.

I had often suspected that the same concepts could be applied to OpenSCAD.
One aspect of this process is that the text is "collected" along a diagonal
and joined to a base, rather than enclosed in a cage.

--
Sent from: http://forum.openscad.org/

This is comparable to creating an ambigram, although on two different axes from the tutorial I found. This tutorial <https://www.youtube.com/watch?v=baO1-HSodIs> uses Fusion 360 to create text in two planes by intersection, just as with the samples of code provided in the posts here. The video is 26 minutes long. I've used it with the hobbyist version of F360 and it works great, resulting in a number of 3D printed gifts to friends and family. I had often suspected that the same concepts could be applied to OpenSCAD. One aspect of this process is that the text is "collected" along a diagonal and joined to a base, rather than enclosed in a cage. -- Sent from: http://forum.openscad.org/
R
rickan
Wed, Nov 4, 2020 2:15 PM

playmeforafool wrote

The other problem is trying to figure out how long to make the block based
on the size of the text/font...

You can get the bounding box of rendered text in PostScript (GhostScript)
and print it out. If you use the same font in both OpenSCAD and PostScript
and you scale the font to unity (or the same scale you use in OpenSCAD) in
Postscript you can have a very short PostScript program print out the length
for use in a shell script. I haven't tried this, but it seems it should
work.

I can write the program for you if you like.

--
Sent from: http://forum.openscad.org/

playmeforafool wrote > The other problem is trying to figure out how long to make the block based > on the size of the text/font... > You can get the bounding box of rendered text in PostScript (GhostScript) and print it out. If you use the same font in both OpenSCAD and PostScript and you scale the font to unity (or the same scale you use in OpenSCAD) in Postscript you can have a very short PostScript program print out the length for use in a shell script. I haven't tried this, but it seems it should work. I can write the program for you if you like. -- Sent from: http://forum.openscad.org/
TP
Torsten Paul
Wed, Nov 4, 2020 2:51 PM

On 04.11.20 15:15, rickan wrote:

You can get the bounding box of rendered text in PostScript (GhostScript)

It's possible to generate geometry that covers the bounding
box in OpenSCAD:

https://en.m.wikibooks.org/wiki/OpenSCAD_User_Manual/Tips_and_Tricks#Computing_a_bounding_box

ciao,
Torsten.

On 04.11.20 15:15, rickan wrote: > You can get the bounding box of rendered text in PostScript (GhostScript) It's possible to generate geometry that covers the bounding box in OpenSCAD: https://en.m.wikibooks.org/wiki/OpenSCAD_User_Manual/Tips_and_Tricks#Computing_a_bounding_box ciao, Torsten.
R
rickan
Wed, Nov 4, 2020 7:38 PM

rickan wrote

You can get the bounding box of rendered text in PostScript (GhostScript)
and print it out. If you use the same font in both OpenSCAD and PostScript
and you scale the font to unity (or the same scale you use in OpenSCAD) in
Postscript you can have a very short PostScript program print out the
length
for use in a shell script. I haven't tried this, but it seems it should
work.

Now I've looked into this I find that PostScript and OpenSCAD scale the
fonts differently. OpenSCAD scales them to a the height you specify and
PostScript seems to scale them to a line spacing. So making this work is not
so easy and you might have to tweak it for each font you use.

--
Sent from: http://forum.openscad.org/

rickan wrote > You can get the bounding box of rendered text in PostScript (GhostScript) > and print it out. If you use the same font in both OpenSCAD and PostScript > and you scale the font to unity (or the same scale you use in OpenSCAD) in > Postscript you can have a very short PostScript program print out the > length > for use in a shell script. I haven't tried this, but it seems it should > work. Now I've looked into this I find that PostScript and OpenSCAD scale the fonts differently. OpenSCAD scales them to a the height you specify and PostScript seems to scale them to a line spacing. So making this work is not so easy and you might have to tweak it for each font you use. -- Sent from: http://forum.openscad.org/
P
playmeforafool
Thu, Nov 5, 2020 1:30 AM

WOW!  I was really only looking for some pointers, not expecting a complete
solution!  Thank you!  Now I just need to figure out what you've done...  I
printed one out already -- not sure what's up with the stringing -- might
have do do some tuning to the printer or something, but other than that,
pretty good!  Thanks again!

http://forum.openscad.org/file/t3003/3d_keychain_barb_ward_480x222.jpg

--
Sent from: http://forum.openscad.org/

WOW! I was really only looking for some pointers, not expecting a complete solution! Thank you! Now I just need to figure out what you've done... I printed one out already -- not sure what's up with the stringing -- might have do do some tuning to the printer or something, but other than that, pretty good! Thanks again! <http://forum.openscad.org/file/t3003/3d_keychain_barb_ward_480x222.jpg> -- Sent from: http://forum.openscad.org/
R
rickan
Thu, Nov 5, 2020 2:59 AM

rickan wrote

Now I've looked into this I find that PostScript and OpenSCAD scale the
fonts differently. OpenSCAD scales them to a the height you specify and
PostScript seems to scale them to a line spacing. So making this work is
not
so easy and you might have to tweak it for each font you use.

Now I've looked into it even further I've written a postscript file that
automatically finds the OpenSCAD scale for the specified font and then finds
the length of the specified string and prints it out:

/fn fn cvn def
fn findfont 1 scalefont setfont
0 0 moveto (yk) true charpath flattenpath pathbbox 1 exch div /fsf exch def
pop pop pop
fn findfont fsf scalefont setfont
is stringwidth pop ==

Name the above file OSsw.ps or choose your own name and and change the name
in the script below to what you choose. The length is for a text height of 1
so if you want a different height you'll have to scale what the above
produces accordingly however most convenient.

And here's a bash script as an example how to use it in a script:

#!/bin/bash

String for which length is wanted is first argument

PostScript font name second argument

Youll need quotes around a string with spaces.

Both arguments are required.

Run gs -sis=<string> -sfn=<FontName> OSsw.ps to check the font name.

gs will default to it's own choice if it can't find yours and the message

announcing that is suppressed in this script.

On a system running fontconfig use fc-match -v to find the PostScript

name of a font. Example:

$ fc-match -v DeJaVuSans:style=oblique | grep postscriptname

$     postscriptname: "DejaVuSans-Oblique"(w)

Use OpenSCAD Hellp > Font List to get the pattern for fc-match

Remove the spaces from the font name listed by OpenSCAD.

sw=gs -q -dBATCH -dNOPAUSE -sis="$1" -sfn=$2 OSsw.ps
echo The width of $1 in font $2 is $sw

Now it is possible to construct an OpenSCAD command line to execute

in a script similar to this one using $1, $2, and $sw

--
Sent from: http://forum.openscad.org/

rickan wrote > Now I've looked into this I find that PostScript and OpenSCAD scale the > fonts differently. OpenSCAD scales them to a the height you specify and > PostScript seems to scale them to a line spacing. So making this work is > not > so easy and you might have to tweak it for each font you use. Now I've looked into it even further I've written a postscript file that automatically finds the OpenSCAD scale for the specified font and then finds the length of the specified string and prints it out: /fn fn cvn def fn findfont 1 scalefont setfont 0 0 moveto (yk) true charpath flattenpath pathbbox 1 exch div /fsf exch def pop pop pop fn findfont fsf scalefont setfont is stringwidth pop == Name the above file OSsw.ps or choose your own name and and change the name in the script below to what you choose. The length is for a text height of 1 so if you want a different height you'll have to scale what the above produces accordingly however most convenient. And here's a bash script as an example how to use it in a script: #!/bin/bash # String for which length is wanted is first argument # PostScript font name second argument # Youll need quotes around a string with spaces. # Both arguments are required. # Run gs -sis=<string> -sfn=<FontName> OSsw.ps to check the font name. # gs will default to it's own choice if it can't find yours and the message # announcing that is suppressed in this script. # On a system running fontconfig use fc-match -v to find the PostScript # name of a font. Example: # $ fc-match -v DeJaVuSans:style=oblique | grep postscriptname # $ postscriptname: "DejaVuSans-Oblique"(w) # Use OpenSCAD Hellp > Font List to get the pattern for fc-match # Remove the spaces from the font name listed by OpenSCAD. sw=`gs -q -dBATCH -dNOPAUSE -sis="$1" -sfn=$2 OSsw.ps` echo The width of $1 in font $2 is $sw # Now it is possible to construct an OpenSCAD command line to execute # in a script similar to this one using $1, $2, and $sw -- Sent from: http://forum.openscad.org/
P
playmeforafool
Thu, Nov 5, 2020 3:01 AM

Thanks.  I didn't even notice those examples under the File menu!

--
Sent from: http://forum.openscad.org/

Thanks. I didn't even notice those examples under the File menu! -- Sent from: http://forum.openscad.org/