# Any interest in METAPOST? Need a full set of Carbide 3D-style wrenches?

And now for something really different.

For a while now, I’ve been working on using METAPOST for a fancy box project, but in the course of that, I realized that I could pretty easily take any file, set it to view in cm, and then copy the coordinates out of it and multiply them times an input value in mm and get a file which could be rendered at any desired size:

\documentclass{standalone}
\usepackage{luamplib}
\begin{document}
\begin{mplibcode}
beginfig(1);

%filecontents:  parameters.txt
S=8mm;
%input parameters.txt

draw (S*2.0203, S*1.25)--(S*1.73165, S*0.75)-- (S*0.37422, S*0.75){left}..(S*0.33075, S*0.67635)--(S*0.68535, S*0.06245)..{right}(S*0.79355,0)--(S*2.0925,0){right}..(S*2.2007,S*0.06245)--(S*2.3813,S*0.375)--(S*9.593,S*0.375){right}..(S*10.468,S*1.25)..{left}(S*9.593,S*2.125)--(S*2.3812,S*2.125)--(S*2.2007,S*2.4373)..{left}(S*2.0925,S*2.5)--(S*0.79355, S*2.5){left}..(S*0.68535,S*2.4373)--(S*0.33105, S*1.8239)..{right}(S*0.3742, S*1.74985)--(S*1.73165, S*1.74985)--cycle;

endfig;
\end{mplibcode}
\end{document}


Anyway, you’d install TeX, save the above in a file (or a pair of files — one would be parameters.txt and have the single line which declares the desired jaw size for the wrench), typeset it using lualatex (which include the library version of METAPOST mplib), and one would then get a .pdf suitable for importing into any vector drawing program (verifying the size) and then saving to an SVG and importing to Carbide Create and doing CAM — apparently I should get out more, it seems as if METAPOST will directly create an SVG — will have to investigate that.

Or of course, one could just calculate the scaling factor to apply to a pre-drawn SVG:

(This definitely would’ve been way cooler if I had the math chops to calculate the hexagons, rounded corners, &c. — some time over a beer ask me about the fabulous school I attended for 3rd and 4th grade which my father pulled me out of, and ultimately the Mississippi State Supreme Court adjudged illegal since it granted exceptional advantages to intelligent and disciplined children, while magnifying the inadequacies of other students or some such)

How about doing it in OpenSCAD, which will export to SVG and DXF?

points=[
[13.655,10.088],
[11.345,6.089],
[0.486,6.089],
[0.138,5.499],
[2.975,0.588],
[3.841,0.089],
[14.232,0.089],
[15.098,0.588],
[16.542,3.089],
[74.236,3.089],
[81.235,10.088],
[74.236,17.088],
[16.542,17.088],
[15.098,19.587],
[14.232,20.088],
[3.841,20.088],
[2.975,19.587],
[0.140,14.679],
[0.485,14.087],
[11.345,14.087]
];
edges=[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]];
polygon(points,edges);
translate([74.236,10.088,0]) circle(7);


(I got the dimensions by converting the SVG to PostScript and knocking together a quick Perl script to extract the moveto/lineto/curveto commands and convert from PS points to MM, then adding the big half-circle; the rest of the curves are left as an exercise for the reader…)

To do it natively in OpenSCAD, maybe something like this:

nut_size=8;
wrench_length=70;
wrench_width=14;
r=nut_size/2/cos(30);
translate([r,-wrench_width/2,0])
square([wrench_length,wrench_width]);
translate([r+wrench_length,0,0])
circle(wrench_width/2);
difference() {
circle(head_size,$fn=6); circle(r,$fn=6);
};


The downside of this method is that I’d have to figure out where the corners are in order to round them off.

-j

For the same reason I didn’t use hexagons, &c in MP — headache of getting the locations for the arcs.

I solved the rounding problem without using real math…

$fa=1;$fs=1;
nut_size=8;
wrench_length=70;
wrench_width=14;
r=nut_size/2/cos(30);
round=1.5;
difference() {
offset(r=round) {
difference() {
circle(head_size-round/2,$fn=6); translate([-head_size,-nut_size/2-round,0]) square([head_size+r/2,nut_size+round*2]); }; }; circle(r,$fn=6);
};
translate([r,-wrench_width/2,0])
square([wrench_length,wrench_width]);
translate([r+wrench_length,0,0])
circle(wrench_width/2);
1 Like

Elegant!

After sleeping on it, I’d arrived at a slightly less elegant conclusion: just shorten the lengths by the radius of a circle drawn at the intersection.

Which reminds me of the major reason to use MP rather than OpenSCAD or some 3D modeling tool — more accurate representation of circles — using Béziers the order of error is much lower.

Yeah, lack of Bezier creation or import is a serious limitation in OpenSCAD. The best workaround I’ve found for importing complex curves is to design them in Inkscape, convert the SVG into a font using FontForge, then render it at any scale with:

use <mycurves.ttf>;
text(text="A", size=100, font = "mycurves");


FontForge is scriptable, so you don’t even have to learn its GUI; I automated the process with a little Python script.

(all of which kind of circles back to where METAPOST originally came from…)

-j

1 Like

Yeah, there’s also an export to OpenSCAD plug-in for Inkscape which I’ve used w/ good success.

Still doesn’t alter the error inherent in rendering a curve as a series of triangles though.

In practice, the error isn’t necessarily a big deal. I used the Inkscape->font->OpenSCAD trick to render this pipe rest, and it came out pretty smooth, with any minor triangulation pretty much covered by the 10% stepover on the ballnose bit:

(the broken edge is me overestimating the strength of Renshape…)

-j

2 Likes

In case you haven’t noticed, I’m an idealist — really wish I could get ImplicitCAD up and running.

Hmm, I got it running on my Mac just now without any trouble, and then remembered why I’d deleted it last time and used OpenSCAD instead: not enough functionality. The internal modeling precision and actual variable-handling are appealing, but the language is missing a lot of what makes OpenSCAD useful.

Now, if they added SVG import and extended the pack() function to include rotation, then it would be an easy way to fit multiple objects onto a sheet for optimized cutting…

-j

1 Like

Well, since METAPOST can directly output an SVG, I’m going to do some hopefully serious work with it here in the near future — asked on the other forum if it’d be okay to put my notes on a page on the wiki:

we’ll have to see if anyone objects, and if not, what comes of it — I am definitely going to have to revisit the wrenches.

On that note, I did the math for you.

Rn = nut_size / (2 * cos(30))
X1,X5 = X0 - Rn / 2
X2,X4 = X0 + Rn / 2
Y1,Y2 = Y0 + nut_size / 2
Y4,Y5 = Y0 - nut_size / 2
X3 = X0 + r
X6 = X0 - r
Y3,Y6 = Y0

Rh = head_size / (2 * cos(30))
Xa,Xb = X0 - Rh + nut_size / (2 * tan(60))
Ya = Y0 + nut_size / 2
Yb = Y0 - nut_size / 2

Xc,Xd = X0 + Rh - wrench_width / (2 * tan(60))
Yc = Y0 + wrench_width / 2
Yd = Y0 - wrench_width / 2
1 Like