Skip to content

Instantly share code, notes, and snippets.

@glsorre
Last active February 3, 2024 15:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save glsorre/aecdf84179a1fd6706fed2924907d7bc to your computer and use it in GitHub Desktop.
Save glsorre/aecdf84179a1fd6706fed2924907d7bc to your computer and use it in GitHub Desktop.
A printer agnostic, parametric, inspectable and usable clearance test for 3D printing
include <funcutils/string.scad>
use <shape_square.scad>
$fn=400;
epsilon = .1;
rotor_shape = [
[0,0],
[7,0],
[8,1],
[4,5],
[4,6],
[8,10],
[7,11],
[0,11],
[0,0]
];
function shell_shape(clearence) = [
[11 - clearence,0],
[8,0],
[8,1],
[4,5],
[4,6],
[8,10],
[8,11],
[0,11],
[9.5 - clearence,11],
[11 - clearence,10],
[11 - clearence,1.5]
];
shell_cut_shape = [
[0,0],
[15,15],
[15,-15]
];
rotor_handle_shape = shape_square([14,3.5], 1.5, $fn=10);
module rotor(clearence) {
union () {
difference() {
rotate_extrude()
polygon(rotor_shape);
translate([0, 0, -epsilon])
linear_extrude(.5 + epsilon, $fn = 10)
mirror([0, 1, 0])
text(substr(str(clearence), 2), 7, font="FiraCodeNerdFont:Bold", halign = "center", valign = "center");
}
translate([0,0,13-epsilon])
linear_extrude(height=6+epsilon, center=true, scale=.75)
polygon(rotor_handle_shape);
}
}
module shell(clearence) {
difference() {
rotate_extrude()
translate([clearence,0,0])
polygon(shell_shape(clearence));
translate([0,0,-epsilon])
linear_extrude(14 + (2 * epsilon))
polygon(shell_cut_shape);
}
}
module main(clearences) {
union() {
for (i = [0:len(clearences) - 1]) {
let (
step_x = sin(30) * 18.5,
step_y = tan(30) * 18.5,
x = i % 2 == 0 ? step_x : -step_x,
y = step_y * i,
rotation = i % 2 == 0 ? 0 : 180
)
translate([x, y, 0]) {
rotate([0, 0, rotation]) {
shell(clearences[i]);
rotor(clearences[i]);
}
}
}
}
}
function calculate_clearences(line_height, tests_number, step, difference) = [
if (difference == 0)
for (i = [0: tests_number - 1])
line_height + i * step
else
for (i = [0: tests_number - 1])
i == 0 ? line_height - difference : i == 1 ? line_height : line_height + (i - 1) * step
];
detail 400
define rotor_shape {
point 0 0
point 7 0
point 8 1
point 4 5
point 4 6
point 8 10
point 7 11
point 0 11
point 0 0
}
define shell_shape {
option clearence .1
path {
point 11-clearence 0
point 8+clearence 0
point 8+clearence 1
point 4+clearence 5
point 4+clearence 6
point 8+clearence 10
point 8+clearence 11
point 0+clearence 11
point 9.5-clearence 11
point 11-clearence 10
point 11-clearence 0
}
}
define shell_cut_shape {
point 0 0
point 15 -15
point 15 15
point 0 0
}
define rotor_handle {
loft {
position 0 11 0
roundrect {
orientation 0 0 .5
size 14 3.5
radius .42
}
translate 0 6.5 0
scale .75
roundrect {
orientation 0 0 .5
size 14 3.5
radius .42
}
}
}
define rotor {
option clearence .1
define l_text ""(split clearence ".").second""
define label text {
orientation 0 0 .5
font "FiraCode Nerd Font Bold"
size 10
l_text
}
define extrusion extrude {
size 1 1 1
label
}
define solid lathe {
path rotor_shape
}
difference {
union {
solid
rotor_handle
}
extrusion {
position extrusion.bounds.width/2+.5 0 extrusion.bounds.depth/2
orientation 1 0 0
}
}
}
define shell {
option clearence .1
difference {
lathe path shell_shape {
clearence clearence
}
extrude {
position 0 5.5 0
size 1 11 1
path {
orientation 0 0 .5
shell_cut_shape
}
}
}
}
define clearence_test {
option clearence .1
rotor {
clearence clearence
}
shell {
clearence clearence
}
}
define main {
option clearences .1 .2 .3
define step_x ((sin (30/180*pi))*18.5)
define step_z ((tan (30/180*pi))*18.5)
union {
for i in 0 to clearences.count - 1 {
define x {
if i%2=0 {
step_x
} else {
-step_x
}
}
define z step_z*i
define rotation_y {
if i%2=0 {
0
} else {
-1
}
}
clearence_test {
position x 0 z
orientation 0 rotation_y 0
clearence clearences[i]
}
}
}
}
main {
color blue
clearences .05 .1 .15 .2 .25
}
use <clearence_test.scad>;
$fn = 400;
module clearence_test_01_easy() {
main(calculate_clearences(.1, 5, .1, 0));
}
module clearence_test_01_hard() {
main(calculate_clearences(.1, 5, .05, 0));
}
module clearence_test_01_extreme() {
main(calculate_clearences(.1, 5, .05, .05));
}
use <clearence_test.scad>;
$fn = 400;
module clearence_test_02_easy() {
main(calculate_clearences(.2, 5, .1, 0));
}
module clearence_test_02_hard() {
main(calculate_clearences(.2, 5, .05, 0));
}
module clearence_test_02_extreme() {
main(calculate_clearences(.2, 5, .05, .05));
}
ORIGIN_FILES := $(wildcard clearence_test_*.scad)
ORIGIN_FILES_REPEATED := $(foreach scad_file,$(ORIGIN_FILES), $(foreach module,$(shell sed -n 's/module \([a-zA-Z0-9_]*\)() {/\1.scad/p' $(scad_file)), $(scad_file)))
TARGETS := $(foreach scad_file,$(ORIGIN_FILES), $(shell sed -n 's/module \([a-zA-Z0-9_]*\)() {/\1.stl/p' $(scad_file)))
START_LINES := $(foreach scad_file,$(ORIGIN_FILES), $(shell sed -n '/module [a-zA-Z0-9_]*()/=' $(scad_file)))
SCAD_FILES := $(patsubst %.stl,%.scad,$(TARGETS))
CHECKSUM_FILES := $(patsubst %.stl,%.scad.sha256sum,$(TARGETS))
BUILT_TARGETS := $(wildcard */*.stl)
all: ${SCAD_FILES} ${CHECKSUM_FILES} ${TARGETS}
clean:
rm -f ${BUILT_TARGETS}
.PHONY: all ${SCAD_FILES} ${CHECKSUM_FILES} ${TARGETS}
include $(wildcard *.deps)
define SUM_RULE
$(1).sha256sum: $(1)
echo "\n### Creating $$@\n";
$(eval LINE_START := $(3))
$(eval LINE_END := $(shell expr $(3) + 3))
$(eval LINE_SED := '$(LINE_START),$(LINE_END)p')
$(eval CHECKSUM := $(shell sed -n $(LINE_SED) $(2) | sha256sum))
echo "$(CHECKSUM)" > $$(basename $(2))/$$@
endef
define SCAD_RULE
$(1): ${ORIGIN_FILES}
echo "\n### Creating $$@\n";
echo "include <../$(2)>\n$$(basename $$@)();\n" > $$(basename $(2))/$$@
endef
define STL_RULE
$(1): $(2) $(4)
$(eval LINE_START := $(3))
$(eval LINE_END := $(shell expr $(3) + 3))
$(eval LINE_SED := '$(LINE_START),$(LINE_END)p')
$(eval CURRENT_SHA256SUM := $(shell sed -n $(LINE_SED) $(4) | sha256sum))
$(eval SAVED_SHA256SUM := $(shell cat $(basename $(4))/$(2).sha256sum || echo "0"))
if [ "$(CURRENT_SHA256SUM)" != "$(SAVED_SHA256SUM)" ] || [ ! -f $(basename $(4))/$(1) ]; then \
echo "\n### Building $(1)\n"; \
/Applications/OpenSCAD.app/Contents/MacOS/OpenSCAD -m make -o $(basename $(4))/$$@ -d $(basename $(4))/$$@.deps $(basename $(4))/$$<; \
else \
echo "\n### Skipping $(1)\n"; \
fi
endef
$(foreach i,$(shell seq 1 $(words $(SCAD_FILES))), $(eval $(call SCAD_RULE,$(word $(i),$(SCAD_FILES)),$(word $(i),$(ORIGIN_FILES_REPEATED)),$(word $(i),$(START_LINES)))))
$(foreach i,$(shell seq 1 $(words $(CHECKSUM_FILES))), $(eval $(call SUM_RULE,$(word $(i),$(SCAD_FILES)),$(word $(i),$(ORIGIN_FILES_REPEATED)),$(word $(i),$(START_LINES)))))
$(foreach i,$(shell seq 1 $(words $(TARGETS))), $(eval $(call STL_RULE,$(word $(i),$(TARGETS)),$(word $(i),$(SCAD_FILES)),$(word $(i),$(START_LINES)),$(word $(i),$(ORIGIN_FILES_REPEATED)))))
@glsorre
Copy link
Author

glsorre commented Jan 31, 2024

A printer agnostic, parametric, inspectable and usable clearance test for 3D printing

Requirements

Written in OpenSCAD. Requires the following libraries:

Usage

You can pass to the main module a list of clearances.

clearences = [0.1, 0.2, 0.3];
main(clearences);

As alternative you can use the calculate_clearences function. It accepts 4 parameters:

  1. line_height: the line height at which you will slice the model;
  2. tests_number: how many test you want to create;
  3. step: how much each test should grow;
  4. difference: how much you want to go down from like_height for the first test.
clearences = calculate_clearences(.1, 5, .05, .05);
main(clearences);

@glsorre
Copy link
Author

glsorre commented Feb 1, 2024

A GNU Make based batch render script for OpenSCAD

I added a simple make file that gets openscad modules and generate their checksums and STL (only if checksum does not match).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment