1
0
mirror of https://github.com/JustinSDK/dotSCAD.git synced 2025-09-25 22:09:12 +02:00
Files
dotSCAD/src/function_grapher.scad
Justin Lin 7dcf44cd67 refactor
2019-09-19 17:53:11 +08:00

231 lines
6.6 KiB
OpenSCAD

/**
* function_grapher.scad
*
* @copyright Justin Lin, 2017
* @license https://opensource.org/licenses/lgpl-3.0.html
*
* @see https://openhome.cc/eGossip/OpenSCAD/lib-function_grapher.html
*
**/
include <util/__comm__/__reverse.scad>;
module function_grapher(points, thickness, style = "FACES", slicing = "SLASH") {
rows = len(points);
columns = len(points[0]);
yi_range = [0:rows - 2];
xi_range = [0:columns - 2];
// Increasing $fn will be slow when you use "LINES", "HULL_FACES" or "HULL_LINES".
module faces() {
function xy_to_index(x, y, columns) = y * columns + x;
top_pts = [
for(row_pts = points)
for(pt = row_pts)
pt
];
base_pts = [
for(pt = top_pts)
[pt[0], pt[1], pt[2] - thickness]
];
leng_pts = len(top_pts);
top_tri_faces1 = slicing == "SLASH" ? [
for(yi = yi_range)
for(xi = xi_range)
[
xy_to_index(xi, yi, columns),
xy_to_index(xi + 1, yi + 1, columns),
xy_to_index(xi + 1, yi, columns)
]
] : [
for(yi = yi_range)
for(xi = xi_range)
[
xy_to_index(xi, yi, columns),
xy_to_index(xi, yi + 1, columns),
xy_to_index(xi + 1, yi, columns)
]
];
top_tri_faces2 = slicing == "SLASH" ? [
for(yi = yi_range)
for(xi = xi_range)
[
xy_to_index(xi, yi, columns),
xy_to_index(xi, yi + 1, columns),
xy_to_index(xi + 1, yi + 1, columns)
]
] : [
for(yi = yi_range)
for(xi = xi_range)
[
xy_to_index(xi, yi + 1, columns),
xy_to_index(xi + 1, yi + 1, columns),
xy_to_index(xi + 1, yi, columns)
]
];
offset_v = [leng_pts, leng_pts, leng_pts];
base_tri_faces1 = [
for(face = top_tri_faces1)
__reverse(face) + offset_v
];
base_tri_faces2 = [
for(face = top_tri_faces2)
__reverse(face) + offset_v
];
side_faces1 = [
for(xi = xi_range)
let(
idx1 = xy_to_index(xi, 0, columns),
idx2 = xy_to_index(xi + 1, 0, columns)
)
[
idx1,
idx2,
idx2 + leng_pts,
idx1 + leng_pts
]
];
side_faces2 = [
for(yi = yi_range)
let(
xi = columns - 1,
idx1 = xy_to_index(xi, yi, columns),
idx2 = xy_to_index(xi, yi + 1, columns)
)
[
idx1,
idx2,
idx2 + leng_pts,
idx1 + leng_pts
]
];
side_faces3 = [
for(xi = xi_range)
let(
yi = rows - 1,
idx1 = xy_to_index(xi, yi, columns),
idx2 = xy_to_index(xi + 1, yi, columns)
)
[
idx2,
idx1,
idx1 + leng_pts,
idx2 + leng_pts
]
];
side_faces4 = [
for(yi = yi_range)
let(
idx1 = xy_to_index(0, yi, columns),
idx2 = xy_to_index(0, yi + 1, columns)
)
[
idx2,
idx1,
idx1 + leng_pts,
idx2 + leng_pts
]
];
pts = concat(top_pts, base_pts);
face_idxs = concat(
top_tri_faces1, top_tri_faces2,
base_tri_faces1, base_tri_faces2,
side_faces1,
side_faces2,
side_faces3,
side_faces4
);
polyhedron(
points = pts,
faces = face_idxs
);
// hook for testing
test_function_grapher_faces(pts, face_idxs);
}
module tri_to_lines(tri1, tri2) {
polyline3d(concat(tri1, [tri1[0]]), thickness);
polyline3d(concat(tri2, [tri2[0]]), thickness);
}
module tri_to_hull_lines(tri1, tri2) {
hull_polyline3d(concat(tri1, [tri1[0]]), thickness);
hull_polyline3d(concat(tri2, [tri2[0]]), thickness);
}
module hull_pts(tri) {
half_thickness = thickness / 2;
hull() {
translate(tri[0]) sphere(half_thickness);
translate(tri[1]) sphere(half_thickness);
translate(tri[2]) sphere(half_thickness);
}
}
module tri_to_hull_faces(tri1, tri2) {
hull_pts(tri1);
hull_pts(tri2);
}
module tri_to_graph(tri1, tri2) {
if(style == "LINES") {
tri_to_lines(tri1, tri2);
} else if(style == "HULL_FACES") { // Warning: May be very slow!!
tri_to_hull_faces(tri1, tri2);
} else if(style == "HULL_LINES") { // Warning: very very slow!!
tri_to_hull_lines(tri1, tri2);
}
}
if(style == "FACES") {
faces();
} else {
for(yi = yi_range) {
for(xi = xi_range) {
if(slicing == "SLASH") {
tri_to_graph([
points[yi][xi],
points[yi][xi + 1],
points[yi + 1][xi + 1]
], [
points[yi][xi],
points[yi + 1][xi + 1],
points[yi + 1][xi]
]);
} else {
tri_to_graph([
points[yi][xi],
points[yi][xi + 1],
points[yi + 1][xi]
], [
points[yi + 1][xi],
points[yi][xi + 1],
points[yi + 1][xi + 1]
]);
}
}
}
}
}
// override it to test
module test_function_grapher_faces(points, faces) {
}