Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Adrian Mariano 2023-01-31 16:49:19 -05:00
commit 3426fa2df6
5 changed files with 867 additions and 277 deletions

View File

@ -392,7 +392,7 @@ _ANCHOR_TYPES = ["intersect","hull"];
// Module: position()
// Usage:
// position(from) CHILDREN;
// PARENT() position(from) CHILDREN;
//
// Topics: Attachments
// See Also: attachable(), attach(), orient()
@ -402,6 +402,10 @@ _ANCHOR_TYPES = ["intersect","hull"];
// of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
// Arguments:
// from = The vector, or name of the parent anchor point to attach to.
// Side Effects:
// `$attach_anchor` for each `from=` anchor given, this is set to the `[ANCHOR, POSITION, ORIENT, SPIN]` information for that anchor.
// `$attach_to` is set to `undef`.
// `$attach_norot` is set to `true`.
// Example:
// spheroid(d=20) {
// position(TOP) cyl(l=10, d1=10, d2=5, anchor=BOTTOM);
@ -426,7 +430,7 @@ module position(from)
// Module: orient()
// Usage:
// orient(dir, [spin=]) CHILDREN;
// orient(anchor=, [spin=]) CHILDREN;
// PARENT() orient(anchor=, [spin=]) CHILDREN;
// Topics: Attachments
// Description:
// Orients children such that their top is tilted towards the given direction, or towards the
@ -437,6 +441,10 @@ module position(from)
// ---
// anchor = The anchor on the parent which you want to match the orientation of. Use instead of `dir`.
// spin = The spin to add to the children. (Overrides anchor spin.)
// Side Effects:
// `$attach_anchor` is set to the `[ANCHOR, POSITION, ORIENT, SPIN]` information for the `anchor=`, if given.
// `$attach_to` is set to `undef`.
// `$attach_norot` is set to `true`.
// See Also: attachable(), attach(), orient()
// Example: Orienting by Vector
// prismoid([50,50],[30,30],h=40) {
@ -494,8 +502,8 @@ module orient(dir, anchor, spin) {
// Module: attach()
// Usage:
// attach(from, [overlap=], [norot=]) CHILDREN;
// attach(from, to, [overlap=], [norot=]) CHILDREN;
// PARENT() attach(from, [overlap=], [norot=]) CHILDREN;
// PARENT() attach(from, to, [overlap=], [norot=]) CHILDREN;
// Topics: Attachments
// See Also: attachable(), position(), face_profile(), edge_profile(), corner_profile()
// Description:
@ -511,6 +519,11 @@ module orient(dir, anchor, spin) {
// ---
// overlap = Amount to sink child into the parent. Equivalent to `down(X)` after the attach. This defaults to the value in `$overlap`, which is `0` by default.
// norot = If true, don't rotate children when attaching to the anchor point. Only translate to the anchor point.
// Side Effects:
// `$idx` is set to the index number of each anchor if a list of anchors is given. Otherwise is set to `0`.
// `$attach_anchor` for each `from=` anchor given, this is set to the `[ANCHOR, POSITION, ORIENT, SPIN]` information for that anchor.
// `$attach_to` is set to the value of the `to=` argument, if given. Otherwise, `undef`
// `$attach_norot` is set to the value of the `norot=` argument.
// Example:
// spheroid(d=20) {
// attach(TOP) down(1.5) cyl(l=11.5, d1=10, d2=5, anchor=BOTTOM);
@ -523,7 +536,8 @@ module attach(from, to, overlap, norot=false)
assert($parent_geom != undef, "No object to attach to!");
overlap = (overlap!=undef)? overlap : $overlap;
anchors = (is_vector(from)||is_string(from))? [from] : from;
for (anchr = anchors) {
for ($idx = idx(anchors)) {
anchr = anchors[$idx];
anch = _find_anchor(anchr, $parent_geom);
two_d = _attach_geom_2d($parent_geom);
$attach_to = to;
@ -543,7 +557,7 @@ module attach(from, to, overlap, norot=false)
// Module: tag()
// Usage:
// tag(tag) CHILDREN;
// PARENT() tag(tag) CHILDREN;
// Topics: Attachments
// See Also: force_tag(), recolor(), hide(), show_only(), diff(), intersect()
// Description:
@ -580,7 +594,7 @@ module tag(tag)
// Module: force_tag()
// Usage:
// force_tag([tag]) CHILDREN;
// PARENT() force_tag([tag]) CHILDREN;
// Topics: Attachments
// See Also: tag(), recolor(), hide(), show_only(), diff(), intersect()
// Description:
@ -642,7 +656,7 @@ module force_tag(tag)
// Module: default_tag()
// Usage:
// default_tag(tag) CHILDREN;
// PARENT() default_tag(tag) CHILDREN;
// Topics: Attachments
// See Also: force_tag(), recolor(), hide(), show_only(), diff(), intersect()
// Description:
@ -686,6 +700,8 @@ module default_tag(tag)
// Creates a tag scope with locally altered tag names to avoid tag name conflict with other code.
// This is necessary when writing modules because the module's caller might happen to use the same tags.
// Note that if you directly set the `$tag` variable then tag scoping will not work correctly.
// Side Effects:
// `$tag_prefix` is set to the value of `scope=` if given, otherwise is set to a random string.
// Example: In this example the ring module uses "remove" tags which will conflict with use of the same tags by the parent.
// module ring(r,h,w=1,anchor,spin,orient)
// {
@ -723,7 +739,7 @@ module tag_scope(scope){
// Module: diff()
// Usage:
// diff([remove], [keep]) CHILDREN;
// diff([remove], [keep]) PARENT() CHILDREN;
// Topics: Attachments
// See Also: tag(), force_tag(), recolor(), show_only(), hide(), tag_diff(), intersect(), tag_intersect()
// Description:
@ -904,7 +920,7 @@ module diff(remove="remove", keep="keep")
// Module: tag_diff()
// Usage:
// tag_diff(tag, [remove], [keep]) CHILDREN;
// tag_diff(tag, [remove], [keep]) PARENT() CHILDREN;
// Topics: Attachments
// See Also: tag(), force_tag(), recolor(), show_only(), hide(), diff(), intersect(), tag_intersect()
// Description:
@ -953,7 +969,6 @@ module diff(remove="remove", keep="keep")
// cyl(r=7,h=7)
// tag("remove")cyl(r=6,h=8)
// tag("keep")cyl(r=5,h=9);
//
module tag_diff(tag,remove="remove", keep="keep")
{
req_children($children);
@ -975,7 +990,7 @@ module tag_diff(tag,remove="remove", keep="keep")
// Module: intersect()
// Usage:
// intersect([intersect], [keep]) CHILDREN;
// intersect([intersect], [keep]) PARENT() CHILDREN;
// Topics: Attachments
// See Also: tag(), force_tag(), recolor(), show_only(), hide(), diff(), tag_diff(), tag_intersect()
// Description:
@ -1044,7 +1059,7 @@ module intersect(intersect="intersect",keep="keep")
// Module: tag_intersect()
// Usage:
// tag_intersect(tag, [intersect], [keep]) CHILDREN;
// tag_intersect(tag, [intersect], [keep]) PARENT() CHILDREN;
// Topics: Attachments
// See Also: tag(), force_tag(), recolor(), show_only(), hide(), diff(), tag_diff(), intersect()
// Description:
@ -1284,11 +1299,53 @@ module show_int(tags)
// Section: Attachable Masks
// Module: face_mask()
// Usage:
// PARENT() face_mask(faces) CHILDREN;
// Topics: Attachments, Masking
// Description:
// Takes a 3D mask shape, and attaches it to the given faces, with the appropriate orientation to be
// differenced away. The mask shape should be vertically oriented (Z-aligned) with the bottom half
// (Z-) shaped to be diffed away from the face of parent attachable shape. If no tag is set then
// `face_mask()` sets the tag for children to "remove" so that it will work with the default {{diff()}} tag.
// For details on specifying the faces to mask see [Specifying Faces](attachments.scad#subsection-specifying-faces).
// For a step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
// Arguments:
// edges = Faces to mask. See [Specifying Faces](attachments.scad#subsection-specifying-faces) for information on specifying faces. Default: All faces
// Side Effects:
// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
// `$idx` is set to the index number of each face in the list of faces given.
// `$attach_anchor` is set for each face given, to the `[ANCHOR, POSITION, ORIENT, SPIN]` information for that anchor.
// See Also: attachable(), position(), attach(), face_profile(), edge_profile(), corner_mask(), edge_mask()
// Example:
// diff()
// cylinder(r=30, h=60)
// face_mask(TOP) {
// rounding_cylinder_mask(r=30,rounding=5);
// cuboid([5,61,10]);
// }
// Example: Using `$idx`
// diff()
// cylinder(r=30, h=60)
// face_mask([TOP, BOT])
// zrot(45*$idx) zrot_copies([0,90]) cuboid([5,61,10]);
module face_mask(faces=[LEFT,RIGHT,FRONT,BACK,BOT,TOP]) {
req_children($children);
faces = is_vector(faces)? [faces] : faces;
assert(all([for (face=faces) is_vector(face) && sum([for (x=face) x!=0? 1 : 0])==1]), "Vector in faces doesn't point at a face.");
assert($parent_geom != undef, "No object to attach to!");
attach(faces) {
if ($tag=="") tag("remove") children();
else children();
}
}
// Module: edge_mask()
// Usage:
// edge_mask([edges], [except]) CHILDREN;
// Topics: Attachments
// See Also: attachable(), position(), attach(), face_profile(), edge_profile(), corner_mask()
// PARENT() edge_mask([edges], [except]) CHILDREN;
// Topics: Attachments, Masking
// See Also: attachable(), position(), attach(), face_profile(), edge_profile(), corner_mask(), face_mask()
// Description:
// Takes a 3D mask shape, and attaches it to the given edges, with the appropriate orientation to be
// differenced away. The mask shape should be vertically oriented (Z-aligned) with the back-right
@ -1309,6 +1366,10 @@ module show_int(tags)
// except = Edges to explicitly NOT mask. See [Specifying Edges](attachments.scad#subsection-specifying-edges). Default: No edges.
// Side Effects:
// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
// Side Effects:
// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
// `$idx` is set to the index number of each edge.
// `$attach_anchor` is set for each edge given, to the `[ANCHOR, POSITION, ORIENT, SPIN]` information for that anchor.
// Example:
// diff()
// cube([50,60,70],center=true)
@ -1323,7 +1384,8 @@ module edge_mask(edges=EDGES_ALL, except=[]) {
if (edges[axis][i]>0)
EDGE_OFFSETS[axis][i]
];
for (vec = vecs) {
for ($idx = idx(vecs)) {
vec = vecs[$idx];
vcount = (vec.x?1:0) + (vec.y?1:0) + (vec.z?1:0);
dummy=assert(vcount == 2, "Not an edge vector!");
anch = _find_anchor(vec, $parent_geom);
@ -1344,8 +1406,8 @@ module edge_mask(edges=EDGES_ALL, except=[]) {
// Module: corner_mask()
// Usage:
// corner_mask([corners], [except]) CHILDREN;
// Topics: Attachments
// PARENT() corner_mask([corners], [except]) CHILDREN;
// Topics: Attachments, Masking
// See Also: attachable(), position(), attach(), face_profile(), edge_profile(), edge_mask()
// Description:
// Takes a 3D mask shape, and attaches it to the specified corners, with the appropriate orientation to
@ -1358,6 +1420,8 @@ module edge_mask(edges=EDGES_ALL, except=[]) {
// except = Corners to explicitly NOT mask. See [Specifying Corners](attachments.scad#subsection-specifying-corners). Default: No corners.
// Side Effects:
// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
// `$idx` is set to the index number of each corner.
// `$attach_anchor` is set for each corner given, to the `[ANCHOR, POSITION, ORIENT, SPIN]` information for that anchor.
// Example:
// diff()
// cube(100, center=true)
@ -1371,7 +1435,8 @@ module corner_mask(corners=CORNERS_ALL, except=[]) {
assert($parent_geom != undef, "No object to attach to!");
corners = _corners(corners, except=except);
vecs = [for (i = [0:7]) if (corners[i]>0) CORNER_OFFSETS[i]];
for (vec = vecs) {
for ($idx = idx(vecs)) {
vec = vecs[$idx];
vcount = (vec.x?1:0) + (vec.y?1:0) + (vec.z?1:0);
dummy=assert(vcount == 3, "Not an edge vector!");
anch = _find_anchor(vec, $parent_geom);
@ -1390,8 +1455,8 @@ module corner_mask(corners=CORNERS_ALL, except=[]) {
// Module: face_profile()
// Usage:
// face_profile(faces, r|d=, [convexity=]) CHILDREN;
// Topics: Attachments
// PARENT() face_profile(faces, r|d=, [convexity=]) CHILDREN;
// Topics: Attachments, Masking
// See Also: attachable(), position(), attach(), edge_profile(), corner_profile()
// Description:
// Given a 2D edge profile, extrudes it into a mask for all edges and corners bounding each given face. If no tag is set
@ -1406,6 +1471,9 @@ module corner_mask(corners=CORNERS_ALL, except=[]) {
// convexity = Max number of times a line could intersect the perimeter of the mask shape. Default: 10
// Side Effects:
// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
// `$idx` is set to the index number of each face.
// `$attach_anchor` is set for each edge or corner given, to the `[ANCHOR, POSITION, ORIENT, SPIN]` information for that anchor.
// `$profile_type` is set to `"edge"` or `"corner"`, depending on what is being masked.
// Example:
// diff()
// cube([50,60,70],center=true)
@ -1424,8 +1492,8 @@ module face_profile(faces=[], r, d, convexity=10) {
// Module: edge_profile()
// Usage:
// edge_profile([edges], [except], [convexity]) CHILDREN;
// Topics: Attachments
// PARENT() edge_profile([edges], [except], [convexity]) CHILDREN;
// Topics: Attachments, Masking
// See Also: attachable(), position(), attach(), face_profile(), corner_profile()
// Description:
// Takes a 2D mask shape and attaches it to the selected edges, with the appropriate orientation and
@ -1440,6 +1508,9 @@ module face_profile(faces=[], r, d, convexity=10) {
// convexity = Max number of times a line could intersect the perimeter of the mask shape. Default: 10
// Side Effects:
// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
// `$idx` is set to the index number of each edge.
// `$attach_anchor` is set for each edge given, to the `[ANCHOR, POSITION, ORIENT, SPIN]` information for that anchor.
// `$profile_type` is set to `"edge"`.
// Example:
// diff()
// cube([50,60,70],center=true)
@ -1454,13 +1525,15 @@ module edge_profile(edges=EDGES_ALL, except=[], convexity=10) {
if (edges[axis][i]>0)
EDGE_OFFSETS[axis][i]
];
for (vec = vecs) {
for ($idx = idx(vecs)) {
vec = vecs[$idx];
vcount = (vec.x?1:0) + (vec.y?1:0) + (vec.z?1:0);
dummy=assert(vcount == 2, "Not an edge vector!");
anch = _find_anchor(vec, $parent_geom);
$attach_to = undef;
$attach_anchor = anch;
$attach_norot = true;
$profile_type = "edge";
psize = point3d($parent_size);
length = [for (i=[0:2]) if(!vec[i]) psize[i]][0]+0.1;
rotang =
@ -1481,8 +1554,8 @@ module edge_profile(edges=EDGES_ALL, except=[], convexity=10) {
// Module: corner_profile()
// Usage:
// corner_profile([corners], [except], [r=|d=], [convexity=]) CHILDREN;
// Topics: Attachments
// PARENT() corner_profile([corners], [except], [r=|d=], [convexity=]) CHILDREN;
// Topics: Attachments, Masking
// See Also: attachable(), position(), attach(), face_profile(), edge_profile()
// Description:
// Takes a 2D mask shape, rotationally extrudes and converts it into a corner mask, and attaches it
@ -1499,6 +1572,9 @@ module edge_profile(edges=EDGES_ALL, except=[], convexity=10) {
// convexity = Max number of times a line could intersect the perimeter of the mask shape. Default: 10
// Side Effects:
// Tags the children with "remove" (and hence sets $tag) if no tag is already set.
// `$idx` is set to the index number of each corner.
// `$attach_anchor` is set for each corner given, to the `[ANCHOR, POSITION, ORIENT, SPIN]` information for that anchor.
// `$profile_type` is set to `"corner"`.
// Example:
// diff()
// cuboid([50,60,70],rounding=10,edges="Z",anchor=CENTER) {
@ -1511,13 +1587,15 @@ module corner_profile(corners=CORNERS_ALL, except=[], r, d, convexity=10) {
assert(is_num(r));
corners = _corners(corners, except=except);
vecs = [for (i = [0:7]) if (corners[i]>0) CORNER_OFFSETS[i]];
for (vec = vecs) {
for ($idx = idx(vecs)) {
vec = vecs[$idx];
vcount = (vec.x?1:0) + (vec.y?1:0) + (vec.z?1:0);
dummy=assert(vcount == 3, "Not an edge vector!");
anch = _find_anchor(vec, $parent_geom);
$attach_to = undef;
$attach_anchor = anch;
$attach_norot = true;
$profile_type = "corner";
rotang = vec.z<0?
[ 0,0,180+v_theta(vec)-45] :
[180,0,-90+v_theta(vec)-45];
@ -2371,7 +2449,6 @@ function _attach_transform(anchor, spin, orient, geom, p) =
function _get_cp(geom) =
let(cp=select(geom,-3))
is_vector(cp) ? cp
: let(
@ -3258,7 +3335,6 @@ module _show_cube_faces(faces, size=20, toplabel,botlabel) {
move(f*size/2) rot(from=UP,to=f)
cuboid([size,size,.1]);
}
vpr = [55,0,25];
color("black"){
if (is_def(toplabel))

File diff suppressed because it is too large Load Diff

View File

@ -2585,9 +2585,15 @@ function associate_vertices(polygons, split, curpoly=0) =
// Another serious limitation is more subtle. In the 2D examples above, it is obvious how to connect the
// dots together. But in 3D example we need to triangulate the points on a grid, and this triangulation is not unique.
// The `style` argument lets you specify how the points are triangulated using the styles supported by {{vnf_vertex_array()}}.
// In the example below we have expanded the 2D example into 3D: `[[0,0,0,0],[0,1,1,0],[0,1,1,0],[0,0,0,0]]`, and we show the
// 3D triangulations produced by the different styles:
// Figure(Big,NoAxes,VPR=[39.2,0,13.3],VPT=[3.76242,-5.50969,4.51854],VPD=32.0275):
// In the example below we have expanded the 2D example into 3D:
// ```openscad
// [[0,0,0,0],
// [0,1,1,0],
// [0,1,1,0],
// [0,0,0,0]]
// ```
// and we show the 3D triangulations produced by the different styles:
// Figure(3D,Big,NoAxes,VPR=[39.2,0,13.3],VPT=[3.76242,-5.50969,4.51854],VPD=32.0275):
// tex = [
// [0,0,0,0,0],
// [0,1,1,0,0],
@ -2628,10 +2634,10 @@ function associate_vertices(polygons, split, curpoly=0) =
// to make a valid object is to have no points at all on the Y=0 line, and of course none on Y=1. In this case, the resulting texture produces
// a collection of disconnected objects. Note that the Z coordinates of your tile can be anything, but for the dimensional settings on textures
// to work intuitively, you should construct your tile so that Z ranges from 0 to 1.
// Figure: This is the "hexgrid" VNF tile, which creates a hexagonal grid texture, something which doesn't work well with a height field because the edges of the hexagon don't align with the grid. Note how the tile ranges between 0 and 1 in both X, Y and Z.
// Figure(3D): This is the "hexgrid" VNF tile, which creates a hexagonal grid texture, something which doesn't work well with a height field because the edges of the hexagon don't align with the grid. Note how the tile ranges between 0 and 1 in both X, Y and Z.
// tex = texture("hex_grid");
// vnf_polyhedron(tex);
// Figure: This is an example of a tile that has no edges at the top or bottom, so it creates disconnected rings. See below for examples showing this tile in use.
// Figure(3D): This is an example of a tile that has no edges at the top or bottom, so it creates disconnected rings. See below for examples showing this tile in use.
// shape = skin([
// rect(2/5),
// rect(2/3),

View File

@ -2,15 +2,15 @@ include <../std.scad>
module test_line_copies() {
assert_equal(line_copies(l=100,n=5), [[-50,0,0],[-25,0,0],[0,0,0],[25,0,0],[50,0,0]]);
assert_equal(line_copies(20,n=5), [[-40,0,0],[-20,0,0],[0,0,0],[20,0,0],[40,0,0]]);
assert_equal(line_copies(spacing=20,n=5), [[-40,0,0],[-20,0,0],[0,0,0],[20,0,0],[40,0,0]]);
assert_equal(line_copies(spacing=[0,20],n=5), [[0,-40,0],[0,-20,0],[0,0,0],[0,20,0],[0,40,0]]);
assert_equal(line_copies(l=100,n=5,p=[0,0,0]), [[-50,0,0],[-25,0,0],[0,0,0],[25,0,0],[50,0,0]]);
assert_equal(line_copies(20,n=5,p=[0,0,0]), [[-40,0,0],[-20,0,0],[0,0,0],[20,0,0],[40,0,0]]);
assert_equal(line_copies(spacing=20,n=5,p=[0,0,0]), [[-40,0,0],[-20,0,0],[0,0,0],[20,0,0],[40,0,0]]);
assert_equal(line_copies(spacing=[0,20],n=5,p=[0,0,0]), [[0,-40,0],[0,-20,0],[0,0,0],[0,20,0],[0,40,0]]);
assert_equal(line_copies(p1=[0,0],l=100,n=5), [[0,0,0],[25,0,0],[50,0,0],[75,0,0],[100,0,0]]);
assert_equal(line_copies(p1=[0,0],20,n=5), [[0,0,0],[20,0,0],[40,0,0],[60,0,0],[80,0,0]]);
assert_equal(line_copies(p1=[0,0],spacing=20,n=5), [[0,0,0],[20,0,0],[40,0,0],[60,0,0],[80,0,0]]);
assert_equal(line_copies(p1=[0,0],spacing=[0,20],n=5), [[0,0,0],[0,20,0],[0,40,0],[0,60,0],[0,80,0]]);
assert_equal(line_copies(p1=[0,0],l=100,n=5,p=[0,0,0]), [[0,0,0],[25,0,0],[50,0,0],[75,0,0],[100,0,0]]);
assert_equal(line_copies(p1=[0,0],20,n=5,p=[0,0,0]), [[0,0,0],[20,0,0],[40,0,0],[60,0,0],[80,0,0]]);
assert_equal(line_copies(p1=[0,0],spacing=20,n=5,p=[0,0,0]), [[0,0,0],[20,0,0],[40,0,0],[60,0,0],[80,0,0]]);
assert_equal(line_copies(p1=[0,0],spacing=[0,20],n=5,p=[0,0,0]), [[0,0,0],[0,20,0],[0,40,0],[0,60,0],[0,80,0]]);
}
test_line_copies();

View File

@ -76,7 +76,7 @@ _NO_ARG = [true,[123232345],false];
//
// Usage: As Module
// move(v) CHILDREN;
// Usage: As a function to translate points, VNF, or Bezier patch
// Usage: As a function to translate points, VNF, or Bezier patches
// pts = move(v, p);
// pts = move(STRING, p);
// Usage: Get Translation Matrix