1/**
2 * @file generic-helpers.scad
3 * @brief Generic Helper Functions. Not gridfinity specific.
4 */
5
6function clp(x,a,b) = min(max(x,a),b);
7
8module rounded_rectangle(length, width, height, rad) {
9 linear_extrude(height)
10 offset(rad)
11 offset(-rad)
12 square([length,width], center = true);
13}
14
15module rounded_square(length, height, rad) {
16 rounded_rectangle(length, length, height, rad);
17}
18
19module copy_mirror(vec=[0,1,0]) {
20 children();
21 if (vec != [0,0,0])
22 mirror(vec)
23 children();
24}
25
26module 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
35module 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 */
45unity_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 */
64function 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 */
72function atanv(vector) = atan2(vector.y, vector.x);
73
74function _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
81function _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
88function _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 */
102function 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 */
110function 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 */
121module 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}