function_grapher.scad
1 /** 2 * function_grapher.scad 3 * 4 * @copyright Justin Lin, 2017 5 * @license https://opensource.org/licenses/lgpl-3.0.html 6 * 7 * @see https://openhome.cc/eGossip/OpenSCAD/lib3x-function_grapher.html 8 * 9 **/ 10 11 use <util/reverse.scad> 12 use <hull_polyline3d.scad> 13 use <path_extrude.scad> 14 use <shape_circle.scad> 15 16 module function_grapher(points, thickness = 1, style = "FACES") { 17 echo("`function_grapher` is deprecated since 3.1. Use `sf_thicken` instead."); 18 19 rows = len(points); 20 columns = len(points[0]); 21 22 yi_range = [0:rows - 2]; 23 xi_range = [0:columns - 2]; 24 25 half_thickness = thickness / 2; 26 27 // Increasing $fn will be slow when you use "LINES", "HULL_FACES" or "HULL_LINES". 28 29 module faces() { 30 function xy_to_index(x, y, columns) = y * columns + x; 31 32 top_pts = [ 33 for(row_pts = points) 34 for(pt = row_pts) 35 pt 36 ]; 37 38 base_pts = [ 39 for(pt = top_pts) 40 [pt[0], pt[1], pt[2] - thickness] 41 ]; 42 43 leng_pts = len(top_pts); 44 45 top_tri_faces1 = [ 46 for(yi = yi_range) 47 for(xi = xi_range) 48 [ 49 xy_to_index(xi, yi, columns), 50 xy_to_index(xi + 1, yi + 1, columns), 51 xy_to_index(xi + 1, yi, columns) 52 ] 53 ]; 54 55 top_tri_faces2 = [ 56 for(yi = yi_range) 57 for(xi = xi_range) 58 [ 59 xy_to_index(xi, yi, columns), 60 xy_to_index(xi, yi + 1, columns), 61 xy_to_index(xi + 1, yi + 1, columns) 62 ] 63 ]; 64 65 offset_v = [leng_pts, leng_pts, leng_pts]; 66 base_tri_faces1 = [ 67 for(face = top_tri_faces1) 68 reverse(face) + offset_v 69 ]; 70 71 base_tri_faces2 = [ 72 for(face = top_tri_faces2) 73 reverse(face) + offset_v 74 ]; 75 76 side_faces1 = [ 77 for(xi = xi_range) 78 let( 79 idx1 = xy_to_index(xi, 0, columns), 80 idx2 = xy_to_index(xi + 1, 0, columns) 81 ) 82 [ 83 idx1, 84 idx2, 85 idx2 + leng_pts, 86 idx1 + leng_pts 87 ] 88 ]; 89 90 side_faces2 = [ 91 for(yi = yi_range) 92 let( 93 xi = columns - 1, 94 idx1 = xy_to_index(xi, yi, columns), 95 idx2 = xy_to_index(xi, yi + 1, columns) 96 ) 97 [ 98 idx1, 99 idx2, 100 idx2 + leng_pts, 101 idx1 + leng_pts 102 ] 103 ]; 104 105 side_faces3 = [ 106 for(xi = xi_range) 107 let( 108 yi = rows - 1, 109 idx1 = xy_to_index(xi, yi, columns), 110 idx2 = xy_to_index(xi + 1, yi, columns) 111 ) 112 [ 113 idx2, 114 idx1, 115 idx1 + leng_pts, 116 idx2 + leng_pts 117 ] 118 ]; 119 120 side_faces4 = [ 121 for(yi = yi_range) 122 let( 123 idx1 = xy_to_index(0, yi, columns), 124 idx2 = xy_to_index(0, yi + 1, columns) 125 ) 126 [ 127 idx2, 128 idx1, 129 idx1 + leng_pts, 130 idx2 + leng_pts 131 ] 132 ]; 133 134 pts = concat(top_pts, base_pts); 135 face_idxs = concat( 136 top_tri_faces1, top_tri_faces2, 137 base_tri_faces1, base_tri_faces2, 138 side_faces1, 139 side_faces2, 140 side_faces3, 141 side_faces4 142 ); 143 144 polyhedron( 145 points = pts, 146 faces = face_idxs 147 ); 148 149 // hook for testing 150 test_function_grapher_faces(pts, face_idxs); 151 } 152 153 module hull_pts(tri) { 154 hull() { 155 translate(tri[0]) sphere(half_thickness); 156 translate(tri[1]) sphere(half_thickness); 157 translate(tri[2]) sphere(half_thickness); 158 } 159 } 160 161 module tri_to_hull_faces(tri1, tri2) { 162 hull_pts(tri1); 163 hull_pts(tri2); 164 } 165 166 if(style == "FACES") { 167 faces(); 168 } 169 else if(style == "HULL_FACES") { 170 twintri_lt = 171 [ 172 for(yi = yi_range) 173 for(xi = xi_range) 174 [ 175 [ 176 points[yi][xi], 177 points[yi][xi + 1], 178 points[yi + 1][xi] 179 ], 180 [ 181 points[yi + 1][xi], 182 points[yi][xi + 1], 183 points[yi + 1][xi + 1] 184 ] 185 ] 186 ]; 187 188 for(twintri = twintri_lt) { 189 tri_to_hull_faces(twintri[0], twintri[1]); 190 } 191 } 192 else { 193 if(style == "LINES") { 194 section = shape_circle(radius = half_thickness); 195 for(row = points) { 196 path_extrude(section, row); 197 } 198 199 for(x = [0:columns - 1]) { 200 path_extrude(section, [for(y = [0:rows - 1]) points[y][x]]); 201 } 202 203 for(c = [0:columns - 2]) { 204 path_extrude(section, [for(r = [0:rows - 1 - c]) points[r + c][r]]); 205 } 206 207 for(c = [0:columns - 2]) { 208 path_extrude(section, [for(r = [0:rows - 1 - c]) points[r][r + c]]); 209 } 210 } 211 else { 212 for(row = points) { 213 hull_polyline3d(row, thickness); 214 } 215 216 for(x = [0:columns - 1]) { 217 hull_polyline3d([for(y = [0:rows - 1]) points[y][x]], thickness); 218 } 219 220 for(c = [0:columns - 2]) { 221 hull_polyline3d([for(r = [0:rows - 1 - c]) points[r + c][r]], thickness); 222 } 223 224 for(c = [0:columns - 2]) { 225 hull_polyline3d([for(r = [0:rows - 1 - c]) points[r][r + c]], thickness); 226 } 227 } 228 } 229 } 230 231 // override it to test 232 module test_function_grapher_faces(points, faces) { 233 234 }