BOSL2/edges.scad

239 lines
7.9 KiB
OpenSCAD
Raw Normal View History

2019-05-08 05:42:44 +00:00
//////////////////////////////////////////////////////////////////////
// LibFile: edges.scad
// Routines to work with edge sets and edge set descriptors.
// To use this, add the following line to the top of your file.
// ```
// include <BOSL2/std.scad>
// ```
//////////////////////////////////////////////////////////////////////
// Section: Sets of Edges
// Constants for specifying edges for `cuboid()`, etc.
EDGES_NONE = [[0,0,0,0], [0,0,0,0], [0,0,0,0]]; // No edges.
EDGES_ALL = [[1,1,1,1], [1,1,1,1], [1,1,1,1]]; // All edges.
// Section: Edge Helpers
// Function: is_edge_array()
// Usage:
// is_edge_array(v)
// Description:
// Returns true if the given value has the form of an edge array.
function is_edge_array(v) = is_list(v) && is_vector(v[0]) && len(v)==3 && len(v[0])==4;
2019-11-06 01:30:47 +00:00
// Function: edge_set()
2019-05-08 05:42:44 +00:00
// Usage:
2019-11-06 01:30:47 +00:00
// edge_set(v);
2019-05-08 05:42:44 +00:00
// Description:
2019-05-10 11:02:58 +00:00
// Takes an edge set descriptor and returns the edges array representing those edges.
2019-05-08 05:42:44 +00:00
// This function is useful for modules that take `edges` arguments, like `cuboid()`.
// An edge set descriptor can be any of:
// - A vector pointing towards an edge, indicating just that edge.
// - A vector pointing towards a face, indicating all edges surrounding that face.
// - A vector pointing towards a corner, indicating all edges that meet at that corner.
2019-05-10 11:02:58 +00:00
// - The string `"X"`, indicating all X axis aligned edges.
// - The string `"Y"`, indicating all Y axis aligned edges.
2019-11-06 02:16:00 +00:00
// - The string `"Z"`, indicating all Z axis aligned edges.
2019-05-10 11:02:58 +00:00
// - The string `"ALL"`, indicating all edges.
// - The string `"NONE"`, indicating no edges at all.
// - A raw edges array, where each edge is represented by a 1 or a 0. The edge ordering is:
// ```
// [
// [Y-Z-, Y+Z-, Y-Z+, Y+Z+],
// [X-Z-, X+Z-, X-Z+, X+Z+],
// [X-Y-, X+Y-, X-Y+, X+Y+]
// ]
// ```
2019-05-08 05:42:44 +00:00
function edge_set(v) =
is_edge_array(v)? v : [
for (ax=[0:2]) [
for (b=[-1,1], a=[-1,1]) let(
v2=[[0,a,b],[a,0,b],[a,b,0]][ax]
) (
is_string(v)? (
v=="X"? (ax==0) : // Return all X axis aligned edges.
v=="Y"? (ax==1) : // Return all Y axis aligned edges.
v=="Z"? (ax==2) : // Return all Z axis aligned edges.
v=="ALL"? true : // Return all edges.
v=="NONE"? false : // Return no edges.
let(valid_values = ["X", "Y", "Z", "ALL", "NONE"])
assert(
in_list(v, valid_values),
str(v, " must be a vector, edge array, or one of ", valid_values)
) v
) :
let(nonz = sum(vabs(v)))
nonz==2? (v==v2) : // Edge: return matching edge.
let(
matches = count_true([
for (i=[0:2]) v[i] && (v[i]==v2[i])
])
)
nonz==1? (matches==1) : // Face: return surrounding edges.
(matches==2) // Corner: return touching edges.
)? 1 : 0
]
];
// Function: normalize_edges()
// Usage:
// normalize_edges(v);
// Description:
// Normalizes all values in an edge array to be `1`, if it was originally greater than `0`,
// or `0`, if it was originally less than or equal to `0`.
function normalize_edges(v) = [for (ax=v) [for (edge=ax) edge>0? 1 : 0]];
// Function: edges()
// Usage:
// edges(v)
// edges(v, except)
// Description:
2019-05-10 11:02:58 +00:00
// Takes a list of edge set descriptors, and returns a normalized edges array
2019-05-08 05:42:44 +00:00
// that represents all those given edges. If the `except` argument is given
// a list of edge set descriptors, then all those edges will be removed
2019-05-10 11:02:58 +00:00
// from the returned edges array. If either argument only has a single edge
2019-05-08 05:42:44 +00:00
// set descriptor, you do not have to pass it in a list.
// Each edge set descriptor can be any of:
// - A vector pointing towards an edge.
// - A vector pointing towards a face, indicating all edges surrounding that face.
// - A vector pointing towards a corner, indicating all edges touching that corner.
2019-05-10 11:02:58 +00:00
// - The string `"X"`, indicating all X axis aligned edges.
// - The string `"Y"`, indicating all Y axis aligned edges.
2019-11-06 02:16:00 +00:00
// - The string `"Z"`, indicating all Z axis aligned edges.
2019-05-10 11:02:58 +00:00
// - The string `"ALL"`, indicating all edges.
// - The string `"NONE"`, indicating no edges at all.
// - A raw edges array, where each edge is represented by a 1 or a 0. The edge ordering is:
// ```
// [
// [Y-Z-, Y+Z-, Y-Z+, Y+Z+],
// [X-Z-, X+Z-, X-Z+, X+Z+],
// [X-Y-, X+Y-, X-Y+, X+Y+]
// ]
// ```
2019-11-12 07:45:58 +00:00
// Figure(3DBig): Face Vector Edge Sets
// module text3d(txt) {
// xrot(90)
// color("#000")
// linear_extrude(height=0.1) {
// text(text=txt, size=3, halign="center", valign="center");
// }
// }
// ydistribute(50) {
// ydistribute(10) {
// xdistribute(30) {
2019-11-12 08:00:07 +00:00
// text3d("LEFT");
// text3d("FRONT");
// text3d("RIGHT");
// }
// xdistribute(30) {
2019-11-12 08:00:07 +00:00
// cuboid(20,chamfer=3,edges=LEFT);
// cuboid(20,chamfer=3,edges=FRONT);
// cuboid(20,chamfer=3,edges=RIGHT);
// }
// }
// ydistribute(10) {
// xdistribute(30) {
2019-11-12 08:00:07 +00:00
// text3d("TOP");
// text3d("BACK");
// text3d("BOTTOM");
// }
// xdistribute(30) {
2019-11-12 08:00:07 +00:00
// cuboid(20,chamfer=3,edges=TOP);
// cuboid(20,chamfer=3,edges=BACK);
// cuboid(20,chamfer=3,edges=BOTTOM);
// }
// }
// }
// Figure(3DBig): Named Edge Sets
// module text3d(txt) {
// xrot(90)
// color("#000")
// linear_extrude(height=0.1) {
// text(text=txt, size=3.5, halign="center", valign="center");
// }
// }
// ydistribute(75) {
// ydistribute(10) {
// xdistribute(30) {
// text3d("\"X\"");
// text3d("\"Y\"");
// text3d("\"Z\"");
// }
// xdistribute(30) {
// cuboid(20,chamfer=3,edges="X");
// cuboid(20,chamfer=3,edges="Y");
// cuboid(20,chamfer=3,edges="Z");
// }
// }
// ydistribute(10) {
// xdistribute(30) {
// text3d("\"ALL\"");
// text3d("\"NONE\"");
// }
// xdistribute(30) {
// cuboid(20,chamfer=3,edges="ALL");
// cuboid(20,chamfer=3,edges="NONE");
// }
// }
// }
2019-05-08 05:42:44 +00:00
// Example: Just the front-top edge
// edges(FRONT+TOP)
// Example: All edges surrounding either the front or top faces
// edges([FRONT,TOP])
// Example: All edges around the bottom face, except any that are also on the front
// edges(BTM, except=FRONT)
// Example: All edges except those around the bottom face.
// edges("ALL", except=BOTTOM)
// Example: All Z-aligned edges except those around the back face.
// edges("Z", except=BACK)
// Example: All edges around the bottom or front faces, except the bottom-front edge.
// edges([BOTTOM,FRONT], except=BOTTOM+FRONT)
// Example: All edges, except Z-aligned edges on the front.
// edges("ALL", except=edges("Z", except=BACK))
function edges(v, except=[]) =
(is_string(v) || is_vector(v) || is_edge_array(v))? edges([v], except=except) :
(is_string(except) || is_vector(except) || is_edge_array(except))? edges(v, except=[except]) :
except==[]? normalize_edges(sum([for (x=v) edge_set(x)])) :
normalize_edges(
normalize_edges(sum([for (x=v) edge_set(x)])) -
sum([for (x=except) edge_set(x)])
);
EDGE_OFFSETS = [ // Array of XYZ offsets to the center of each edge.
[
[ 0,-1,-1],
[ 0, 1,-1],
[ 0,-1, 1],
[ 0, 1, 1]
], [
[-1, 0,-1],
[ 1, 0,-1],
[-1, 0, 1],
[ 1, 0, 1]
], [
[-1,-1, 0],
[ 1,-1, 0],
[-1, 1, 0],
[ 1, 1, 0]
]
];
// Function: corner_edge_count()
// Description: Counts how many given edges intersect at a specific corner.
// Arguments:
// edges = Standard edges array.
// v = Vector pointing to the corner to count edge intersections at.
function corner_edge_count(edges, v) =
let(u = (v+[1,1,1])/2) edges[0][u.y+u.z*2] + edges[1][u.x+u.z*2] + edges[2][u.x+u.y*2];
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap