Blame | Last modification | View Log | RSS feed
/**************************************\* ** OpenSCAD Mesh Display ** by Thinkyhead - April 2017 ** ** Copy the grid output from Marlin, ** paste below as shown, and use ** OpenSCAD to see a visualization ** of your mesh. ** *\**************************************///$t = 0.15; // comment out during animation//// Mesh info and points//mesh_width = 200; // X Size in mm of the probed areamesh_height = 200; // Y Size...zprobe_offset = 0; // Added to the pointsNAN = 0; // Z to use for un-measured pointsmeasured_z = [[ -1.20, -1.13, -1.09, -1.03, -1.19 ],[ -1.16, -1.25, -1.27, -1.25, -1.08 ],[ -1.13, -1.26, -1.39, -1.31, -1.18 ],[ -1.09, -1.20, -1.26, -1.21, -1.18 ],[ -1.13, -0.99, -1.03, -1.06, -1.32 ]];//// Geometry//max_z_scale = 100; // Scale at Time 0.5min_z_scale = 10; // Scale at Time 0.0 and 1.0thickness = 0.5; // thickness of the mesh trianglestesselation = 1; // levels of tesselation from 0-2alternation = 2; // direction change modulus (try it)//// Appearance//show_plane = true;show_labels = true;arrow_length = 5;label_font_lg = "Arial";label_font_sm = "Arial";mesh_color = [1,1,1,0.5];plane_color = [0.4,0.6,0.9,0.6];//================================================ Derive useful valuesbig_z = max_2D(measured_z,0);lil_z = min_2D(measured_z,0);mean_value = (big_z + lil_z) / 2.0;mesh_points_y = len(measured_z);mesh_points_x = len(measured_z[0]);xspace = mesh_width / (mesh_points_x - 1);yspace = mesh_height / (mesh_points_y - 1);// At $t=0 and $t=1 scale will be 100%z_scale_factor = min_z_scale + (($t > 0.5) ? 1.0 - $t : $t) * (max_z_scale - min_z_scale) * 2;//// Min and max recursive functions for 1D and 2D arrays// Return the smallest or largest value in the array//function min_1D(b,i) = (i<len(b)-1) ? min(b[i], min_1D(b,i+1)) : b[i];function min_2D(a,j) = (j<len(a)-1) ? min_2D(a,j+1) : min_1D(a[j], 0);function max_1D(b,i) = (i<len(b)-1) ? max(b[i], max_1D(b,i+1)) : b[i];function max_2D(a,j) = (j<len(a)-1) ? max_2D(a,j+1) : max_1D(a[j], 0);//// Get the corner probe points of a grid square.//// Input : x,y grid indexes// Output : An array of the 4 corner points//function grid_square(x,y) = [[x * xspace, y * yspace, z_scale_factor * (measured_z[y][x] - mean_value)],[x * xspace, (y+1) * yspace, z_scale_factor * (measured_z[y+1][x] - mean_value)],[(x+1) * xspace, (y+1) * yspace, z_scale_factor * (measured_z[y+1][x+1] - mean_value)],[(x+1) * xspace, y * yspace, z_scale_factor * (measured_z[y][x+1] - mean_value)]];// The corner point of a grid square with Z centered on the meanfunction pos(x,y,z) = [x * xspace, y * yspace, z_scale_factor * (z - mean_value)];//// Draw the point markers and labels//module point_markers(show_home=true) {// Mark the home position 0,0color([0,0,0,0.25]) translate([1,1]) cylinder(r=1, h=z_scale_factor, center=true);for (x=[0:mesh_points_x-1], y=[0:mesh_points_y-1]) {z = measured_z[y][x];down = z < mean_value;translate(pos(x, y, z)) {// Label each point with the Zif (show_labels) {v = z - mean_value;color(abs(v) < 0.1 ? [0,0.5,0] : [0.25,0,0])translate([0,0,down?-10:10]) {$fn=8;rotate([90,0])text(str(z), 6, label_font_lg, halign="center", valign="center");translate([0,0,down?-6:6]) rotate([90,0])text(str(down ? "" : "+", v), 3, label_font_sm, halign="center", valign="center");}}// Show an arrow pointing up or downrotate([0, down ? 180 : 0]) translate([0,0,-1])cylinder(r1=0.5,r2=0.1,h=arrow_length, $fn=12, center=1);}}}//// Split a square on the diagonal into// two triangles and render them.//// s : a square// alt : a flag to split on the other diagonal//module tesselated_square(s, alt=false) {add = [0,0,thickness];p1 = [s[0], s[1], s[2], s[3],s[0]+add, s[1]+add, s[2]+add, s[3]+add];f1 = alt? [ [0,1,3], [4,5,1,0], [4,7,5], [5,7,3,1], [7,4,0,3] ]: [ [0,1,2], [4,5,1,0], [4,6,5], [5,6,2,1], [6,4,0,2] ];f2 = alt? [ [1,2,3], [5,6,2,1], [5,6,7], [6,7,3,2], [7,5,1,3] ]: [ [0,2,3], [4,6,2,0], [4,7,6], [6,7,3,2], [7,4,0,3] ];// Use the other diagonalpolyhedron(points=p1, faces=f1);polyhedron(points=p1, faces=f2);}/*** The simplest mesh display*/module simple_mesh(show_plane=show_plane) {if (show_plane) color(plane_color) cube([mesh_width, mesh_height, thickness]);color(mesh_color)for (x=[0:mesh_points_x-2], y=[0:mesh_points_y-2])tesselated_square(grid_square(x, y));}/*** Subdivide the mesh into smaller squares.*/module bilinear_mesh(show_plane=show_plane,tesselation=tesselation) {if (show_plane) color(plane_color) translate([-5,-5]) cube([mesh_width+10, mesh_height+10, thickness]);tesselation = tesselation % 4;color(mesh_color)for (x=[0:mesh_points_x-2], y=[0:mesh_points_y-2]) {square = grid_square(x, y);if (tesselation < 1) {tesselated_square(square,(x%alternation)-(y%alternation));}else {subdiv_4 = subdivided_square(square);if (tesselation < 2) {for (i=[0:3]) tesselated_square(subdiv_4[i],i%alternation);}else {for (i=[0:3]) {subdiv_16 = subdivided_square(subdiv_4[i]);if (tesselation < 3) {for (j=[0:3]) tesselated_square(subdiv_16[j],j%alternation);}else {for (j=[0:3]) {subdiv_64 = subdivided_square(subdiv_16[j]);if (tesselation < 4) {for (k=[0:3]) tesselated_square(subdiv_64[k]);}}}}}}}}//// Subdivision helpers//function ctrz(a) = (a[0][2]+a[1][2]+a[3][2]+a[2][2])/4;function avgx(a,i) = (a[i][0]+a[(i+1)%4][0])/2;function avgy(a,i) = (a[i][1]+a[(i+1)%4][1])/2;function avgz(a,i) = (a[i][2]+a[(i+1)%4][2])/2;//// Convert one square into 4, applying bilinear averaging//// Input : 1 square (4 points)// Output : An array of 4 squares//function subdivided_square(a) = [[ // SW squarea[0], // SW[a[0][0],avgy(a,0),avgz(a,0)], // CW[avgx(a,1),avgy(a,0),ctrz(a)], // CC[avgx(a,1),a[0][1],avgz(a,3)] // SC],[ // NW square[a[0][0],avgy(a,0),avgz(a,0)], // CWa[1], // NW[avgx(a,1),a[1][1],avgz(a,1)], // NC[avgx(a,1),avgy(a,0),ctrz(a)] // CC],[ // NE square[avgx(a,1),avgy(a,0),ctrz(a)], // CC[avgx(a,1),a[1][1],avgz(a,1)], // NCa[2], // NE[a[2][0],avgy(a,0),avgz(a,2)] // CE],[ // SE square[avgx(a,1),a[0][1],avgz(a,3)], // SC[avgx(a,1),avgy(a,0),ctrz(a)], // CC[a[2][0],avgy(a,0),avgz(a,2)], // CEa[3] // SE]];//================================================ Run the plantranslate([-mesh_width / 2, -mesh_height / 2]) {$fn = 12;point_markers();bilinear_mesh();}