Skip to content

Commit 36345f3

Browse files
authored
Merge pull request #175 from EmperorArthur/affine_hell
Use Affine Transformation Matrices For sweep_rounded
2 parents fc51ba8 + e7ef96b commit 36345f3

File tree

2 files changed

+170
-57
lines changed

2 files changed

+170
-57
lines changed

generic-helpers.scad

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/**
2+
* @file generic-helpers.scad
3+
* @brief Generic Helper Functions. Not gridfinity specific.
4+
*/
5+
6+
function clp(x,a,b) = min(max(x,a),b);
7+
8+
module rounded_rectangle(length, width, height, rad) {
9+
linear_extrude(height)
10+
offset(rad)
11+
offset(-rad)
12+
square([length,width], center = true);
13+
}
14+
15+
module rounded_square(length, height, rad) {
16+
rounded_rectangle(length, length, height, rad);
17+
}
18+
19+
module copy_mirror(vec=[0,1,0]) {
20+
children();
21+
if (vec != [0,0,0])
22+
mirror(vec)
23+
children();
24+
}
25+
26+
module pattern_linear(x = 1, y = 1, sx = 0, sy = 0) {
27+
yy = sy <= 0 ? sx : sy;
28+
translate([-(x-1)*sx/2,-(y-1)*yy/2,0])
29+
for (i = [1:ceil(x)])
30+
for (j = [1:ceil(y)])
31+
translate([(i-1)*sx,(j-1)*yy,0])
32+
children();
33+
}
34+
35+
module pattern_circular(n=2) {
36+
for (i = [1:n])
37+
rotate(i*360/n)
38+
children();
39+
}
40+
41+
/**
42+
* @brief Unity (no change) affine transformation matrix.
43+
* @details For use with multmatrix transforms.
44+
*/
45+
unity_matrix = [
46+
[1, 0, 0, 0],
47+
[0, 1, 0, 0],
48+
[0, 0, 1, 0],
49+
[0, 0, 0, 1]
50+
];
51+
52+
/**
53+
* @brief Get the magnitude of a 2d or 3d vector
54+
* @param vector A 2d or 3d vectorm
55+
* @returns Magnitude of the vector.
56+
*/
57+
function vector_magnitude(vector) =
58+
sqrt(vector.x^2 + vector.y^2 + (len(vector) == 3 ? vector.z^2 : 0));
59+
60+
/**
61+
* @brief Convert a 2d or 3d vector into a unit vector
62+
* @returns The unit vector. Where total magnitude is 1.
63+
*/
64+
function vector_as_unit(vector) = vector / vector_magnitude(vector);
65+
66+
/**
67+
* @brief Convert a 2d vector into an angle.
68+
* @details Just a wrapper around atan2.
69+
* @param A 2d vectorm
70+
* @returns Angle of the vector.
71+
*/
72+
function atanv(vector) = atan2(vector.y, vector.x);
73+
74+
function _affine_rotate_x(angle_x) = [
75+
[1, 0, 0, 0],
76+
[0, cos(angle_x), -sin(angle_x), 0],
77+
[0, sin(angle_x), cos(angle_x), 0],
78+
[0, 0, 0, 1]
79+
];
80+
81+
function _affine_rotate_y(angle_y) = [
82+
[cos(angle_y), 0, sin(angle_y), 0],
83+
[0, 1, 0, 0],
84+
[-sin(angle_y), 0, cos(angle_y), 0],
85+
[0, 0, 0, 1]
86+
];
87+
88+
function _affine_rotate_z(angle_z) = [
89+
[cos(angle_z), -sin(angle_z), 0, 0],
90+
[sin(angle_z), cos(angle_z), 0, 0],
91+
[0, 0, 1, 0],
92+
[0, 0, 0, 1]
93+
];
94+
95+
96+
/**
97+
* @brief Affine transformation matrix equivalent of `rotate`
98+
* @param angle_vector @see `rotate`
99+
* @details Equivalent to `rotate([0, angle, 0])`
100+
* @returns An affine transformation matrix for use with `multmatrix()`
101+
*/
102+
function affine_rotate(angle_vector) =
103+
_affine_rotate_z(angle_vector.z) * _affine_rotate_y(angle_vector.y) * _affine_rotate_x(angle_vector.x);
104+
105+
/**
106+
* @brief Affine transformation matrix equivalent of `translate`
107+
* @param vector @see `translate`
108+
* @returns An affine transformation matrix for use with `multmatrix()`
109+
*/
110+
function affine_translate(vector) = [
111+
[1, 0, 0, vector.x],
112+
[0, 1, 0, vector.y],
113+
[0, 0, 1, vector.z],
114+
[0, 0, 0, 1]
115+
];
116+
117+
/**
118+
* @brief Create a rectangle with rounded corners by sweeping a 2d object along a path.
119+
* Centered on origin.
120+
*/
121+
module sweep_rounded(width=10, length=10) {
122+
half_width = width/2;
123+
half_length = length/2;
124+
path_points = [
125+
[-half_width, half_length], //Start
126+
[half_width, half_length], // Over
127+
[half_width, -half_length], //Down
128+
[-half_width, -half_length], // Back over
129+
[-half_width, half_length] // Up to start
130+
];
131+
path_vectors = [
132+
path_points[1] - path_points[0],
133+
path_points[2] - path_points[1],
134+
path_points[3] - path_points[2],
135+
path_points[4] - path_points[3],
136+
];
137+
// These contain the translations, but not the rotations
138+
// OpenSCAD requires this hacky for loop to get accumulate to work!
139+
first_translation = affine_translate([path_points[0].y, 0,path_points[0].x]);
140+
affine_translations = concat([first_translation], [
141+
for (i = 0, a = first_translation;
142+
i < len(path_vectors);
143+
a=a * affine_translate([path_vectors[i].y, 0, path_vectors[i].x]), i=i+1)
144+
a * affine_translate([path_vectors[i].y, 0, path_vectors[i].x])
145+
]);
146+
147+
// Bring extrusion to the xy plane
148+
affine_matrix = affine_rotate([90, 0, 90]);
149+
150+
walls = [
151+
for (i = [0 : len(path_vectors) - 1])
152+
affine_matrix * affine_translations[i]
153+
* affine_rotate([0, atanv(path_vectors[i]), 0])
154+
];
155+
156+
union()
157+
{
158+
for (i = [0 : len(walls) - 1]){
159+
multmatrix(walls[i])
160+
linear_extrude(vector_magnitude(path_vectors[i]))
161+
children();
162+
163+
// Rounded Corners
164+
multmatrix(walls[i] * affine_rotate([-90, 0, 0]))
165+
rotate_extrude(angle = 90, convexity = 4)
166+
children();
167+
}
168+
}
169+
}

gridfinity-rebuilt-utility.scad

Lines changed: 1 addition & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
include <standard.scad>
8+
use <generic-helpers.scad>
89

910
// ===== User Modules ===== //
1011

@@ -623,60 +624,3 @@ module profile_cutter_tab(h, tab, ang) {
623624
polygon([[0,h],[tab,h],[0,h-tab*tan(ang)]]);
624625

625626
}
626-
627-
// ==== Utilities =====
628-
629-
function clp(x,a,b) = min(max(x,a),b);
630-
631-
module rounded_rectangle(length, width, height, rad) {
632-
linear_extrude(height)
633-
offset(rad)
634-
offset(-rad)
635-
square([length,width], center = true);
636-
}
637-
638-
module rounded_square(length, height, rad) {
639-
rounded_rectangle(length, length, height, rad);
640-
}
641-
642-
module copy_mirror(vec=[0,1,0]) {
643-
children();
644-
if (vec != [0,0,0])
645-
mirror(vec)
646-
children();
647-
}
648-
649-
module pattern_linear(x = 1, y = 1, sx = 0, sy = 0) {
650-
yy = sy <= 0 ? sx : sy;
651-
translate([-(x-1)*sx/2,-(y-1)*yy/2,0])
652-
for (i = [1:ceil(x)])
653-
for (j = [1:ceil(y)])
654-
translate([(i-1)*sx,(j-1)*yy,0])
655-
children();
656-
}
657-
658-
module pattern_circular(n=2) {
659-
for (i = [1:n])
660-
rotate(i*360/n)
661-
children();
662-
}
663-
664-
module sweep_rounded(w=10, h=10) {
665-
union() pattern_circular(2) {
666-
copy_mirror([1,0,0])
667-
translate([w/2,h/2,0])
668-
rotate_extrude(angle = 90, convexity = 4)
669-
children();
670-
671-
translate([w/2,0,0])
672-
rotate([90,0,0])
673-
linear_extrude(height = h, center = true)
674-
children();
675-
676-
rotate([0,0,90])
677-
translate([h/2,0,0])
678-
rotate([90,0,0])
679-
linear_extrude(height = w, center = true)
680-
children();
681-
}
682-
}

0 commit comments

Comments
 (0)