Merge branch 'master' of github.com:revarbat/BOSL2 into revarbat_dev

This commit is contained in:
Revar Desmera 2021-12-13 15:51:06 -08:00
commit aa109de9d7
36 changed files with 1652 additions and 1635 deletions

View file

@ -35,7 +35,7 @@ $tags_hidden = [];
_ANCHOR_TYPES = ["intersect","hull"];
// Section: Anchors, Spin, and Orientation
// Section: Terminology and Shortcuts
// This library adds the concept of anchoring, spin and orientation to the `cube()`, `cylinder()`
// and `sphere()` builtins, as well as to most of the shapes provided by this library itself.
// - An anchor is a place on an object which you can align the object to, or attach other objects
@ -44,8 +44,13 @@ _ANCHOR_TYPES = ["intersect","hull"];
// - Spin is a simple rotation around the Z axis.
// - Orientation is rotating an object so that its top is pointed towards a given vector.
// An object will first be translated to its anchor position, then spun, then oriented.
// For a detailed step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
// .
// ## Anchor
// For describing directions, faces, edges, and corners the library provides a set of shortcuts
// all based on combinations of unit direction vectors. You can use these for anchoring and orienting
// attachable objects. You can also them to specify edge sets for rounding or chamfering cuboids,
// or for placing edge, face and corner masks.
// SubSection: Anchor
// Anchoring is specified with the `anchor` argument in most shape modules. Specifying `anchor`
// when creating an object will translate the object so that the anchor point is at the origin
// (0,0,0). Anchoring always occurs before spin and orientation are applied.
@ -54,8 +59,8 @@ _ANCHOR_TYPES = ["intersect","hull"];
// .
// When given as a vector, it points, in a general way, towards the face, edge, or corner of the
// object that you want the anchor for, relative to the center of the object. There are directional
// constants named `TOP`, `BOTTOM`, `FRONT`, `BACK`, `LEFT`, and `RIGHT` that you can add together
// to specify an anchor point.
// constants with names like `TOP`, `BOTTOM`, `LEFT`, `RIGHT` and `BACK` that you can add together
// to specify an anchor point. See ?????? below for the full list of pre-defined directional constants.
// .
// For example:
// - `[0,0,1]` is the same as `TOP` and refers to the center of the top face.
@ -72,24 +77,277 @@ _ANCHOR_TYPES = ["intersect","hull"];
// Some more complex objects, like screws and stepper motors, have named anchors to refer to places
// on the object that are not at one of the standard faces, edges or corners. For example, stepper
// motors have anchors for `"screw1"`, `"screw2"`, etc. to refer to the various screwholes on the
// stepper motor shape. The names, positions, directions, and spins of these anchors will be
// specific to the object, and will be documented when they exist.
// .
// ## Spin
// Spin is specified with the `spin` argume// nt in most shape modules. Specifying a scalar `spin`
// stepper motor shape. The names, positions, directions, and spins of these anchors are
// specific to the object, and are documented when they exist.
// SubSection: Spin
// Spin is specified with the `spin` argument in most shape modules. Specifying a scalar `spin`
// when creating an object will rotate the object counter-clockwise around the Z axis by the given
// number of degrees. If given as a 3D vector, the object will be rotated around each of the X, Y, Z
// axes by the number of degrees in each component of the vector. Spin is always applied after
// anchoring, and before orientation.
// .
// ## Orient
// anchoring, and before orientation. Since spin is applied after anchoring it is not what
// you might think of intuitively as spinning the shape. To do that, apply `zrot()` to the shape before anchoring.
// SubSection: Orient
// Orientation is specified with the `orient` argument in most shape modules. Specifying `orient`
// when creating an object will rotate the object such that the top of the object will be pointed
// at the vector direction given in the `orient` argument. Orientation is always applied after
// anchoring and spin. The constants `UP`, `DOWN`, `FRONT`, `BACK`, `LEFT`, and `RIGHT` can be
// added together to form the directional vector for this. ie: `LEFT+BACK`
// .
// For a more step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
// SubSection: Specifying Directions
// You can use direction vectors to specify anchors for objects or to specify edges, faces, and
// corners of cubes. You can simply specify these direction vectors numerically, but another
// option is to use named constants for direction vectors. These constants define unit vectors
// for the six axis directions as shown below.
// Figure(3D,Big,VPD=6): Named constants for direction vectors. Some directions have more than one name.
// $fn=12;
// stroke([[0,0,0],RIGHT], endcap2="arrow2", width=.05);
// color("black")right(.05)up(.05)move(RIGHT)atext("RIGHT",size=.1,h=.01,anchor=LEFT,orient=FRONT);
// stroke([[0,0,0],LEFT], endcap2="arrow2", width=.05);
// color("black")left(.05)up(.05)move(LEFT)atext("LEFT",size=.1,h=.01,anchor=RIGHT,orient=FRONT);
// stroke([[0,0,0],FRONT], endcap2="arrow2", width=.05);
// color("black")
// left(.1){
// up(.12)move(FRONT)atext("FRONT",size=.1,h=.01,anchor=RIGHT,orient=FRONT);
// move(FRONT)atext("FWD",size=.1,h=.01,anchor=RIGHT,orient=FRONT);
// down(.12)move(FRONT)atext("FORWARD",size=.1,h=.01,anchor=RIGHT,orient=FRONT);
// }
// stroke([[0,0,0],BACK], endcap2="arrow2", width=.05);
// right(.05)
// color("black")move(BACK)atext("BACK",size=.1,h=.01,anchor=LEFT,orient=FRONT);
// stroke([[0,0,0],DOWN], endcap2="arrow2", width=.05);
// color("black")
// right(.1){
// up(.12)move(BOT)atext("DOWN",size=.1,h=.01,anchor=LEFT,orient=FRONT);
// move(BOT)atext("BOTTOM",size=.1,h=.01,anchor=LEFT,orient=FRONT);
// down(.12)move(BOT)atext("BOT",size=.1,h=.01,anchor=LEFT,orient=FRONT);
// }
// stroke([[0,0,0],TOP], endcap2="arrow2", width=.05);
// color("black")left(.05){
// up(.12)move(TOP)atext("TOP",size=.1,h=.01,anchor=RIGHT,orient=FRONT);
// move(TOP)atext("UP",size=.1,h=.01,anchor=RIGHT,orient=FRONT);
// }
// SubSection: Specifying Faces
// Modules operating on faces accept a list of faces to describe the faces to operate on. Each
// face is given by a vector that points to that face. Attachments of cuboid objects onto their faces also
// work by choosing an attachment face with a single vector in the same manner.
// Figure(3D,Big,NoScales,VPD=275): The six faces of the cube. Some have faces have more than one name.
// ydistribute(50) {
// xdistribute(35){
// _show_cube_faces([BACK], botlabel=["BACK"]);
// _show_cube_faces([UP],botlabel=["TOP","UP"]);
// _show_cube_faces([RIGHT],botlabel=["RIGHT"]);
// }
// xdistribute(35){
// _show_cube_faces([FRONT],toplabel=["FRONT","FWD", "FORWARD"]);
// _show_cube_faces([DOWN],toplabel=["BOTTOM","BOT","DOWN"]);
// _show_cube_faces([LEFT],toplabel=["LEFT"]);
// }
// }
// SubSection: Specifying Edges
// Modules operating on edges use two arguments to describe the edge set they will use: The `edges` argument
// is a list of edge set descriptors to include in the edge set, and the `except` argument is a list of
// edge set descriptors to remove from the edge set.
// The default value for `edges` is `"ALL"`, the set of all edges.
// The default value for `except` is the empty set, meaning no edges are removed.
// If either argument is just a single edge set
// descriptor it can be passed directly rather than in a singleton list.
// Each edge set descriptor must be one of:
// - A vector pointing towards an edge, indicating that single 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.
// - The string `"X"`, indicating all X axis aligned edges.
// - The string `"Y"`, indicating all Y axis aligned edges.
// - The string `"Z"`, indicating all Z axis aligned edges.
// - The string `"ALL"`, indicating all edges.
// - The string `"NONE"`, indicating no edges at all.
// - A 3x4 array, where each entry corresponds to one of the 12 edges and is set to 1 if that edge is included and 0 if the edge is not. 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+]
// ]
// ```
// You can specify edge descriptors directly by giving a vector, or you can use sums of the
// named direction vectors described above. Below we show all of the edge sets you can
// describe with sums of the direction vectors, and then we show some examples of combining
// edge set descriptors.
// Figure(3D,Big,VPD=300,NoScales): Vectors pointing toward an edge select that single edge
// ydistribute(50) {
// xdistribute(30) {
// _show_edges(edges=BOT+RIGHT);
// _show_edges(edges=BOT+BACK);
// _show_edges(edges=BOT+LEFT);
// _show_edges(edges=BOT+FRONT);
// }
// xdistribute(30) {
// _show_edges(edges=FWD+RIGHT);
// _show_edges(edges=BACK+RIGHT);
// _show_edges(edges=BACK+LEFT);
// _show_edges(edges=FWD+LEFT);
// }
// xdistribute(30) {
// _show_edges(edges=TOP+RIGHT);
// _show_edges(edges=TOP+BACK);
// _show_edges(edges=TOP+LEFT);
// _show_edges(edges=TOP+FRONT);
// }
// }
// Figure(3D,Med,VPD=205,NoScales): Vectors pointing toward a face select all edges surrounding that face.
// ydistribute(50) {
// xdistribute(30) {
// _show_edges(edges=LEFT);
// _show_edges(edges=FRONT);
// _show_edges(edges=RIGHT);
// }
// xdistribute(30) {
// _show_edges(edges=TOP);
// _show_edges(edges=BACK);
// _show_edges(edges=BOTTOM);
// }
// }
// Figure(3D,Big,VPD=300,NoScales): Vectors pointing toward a corner select all edges surrounding that corner.
// ydistribute(50) {
// xdistribute(30) {
// _show_edges(edges=FRONT+LEFT+TOP);
// _show_edges(edges=FRONT+RIGHT+TOP);
// _show_edges(edges=FRONT+LEFT+BOT);
// _show_edges(edges=FRONT+RIGHT+BOT);
// }
// xdistribute(30) {
// _show_edges(edges=TOP+LEFT+BACK);
// _show_edges(edges=TOP+RIGHT+BACK);
// _show_edges(edges=BOT+LEFT+BACK);
// _show_edges(edges=BOT+RIGHT+BACK);
// }
// }
// Figure(3D,Med,VPD=205,NoScales): Named Edge Sets
// ydistribute(50) {
// xdistribute(30) {
// _show_edges(edges="X");
// _show_edges(edges="Y");
// _show_edges(edges="Z");
// }
// xdistribute(30) {
// _show_edges(edges="ALL");
// _show_edges(edges="NONE");
// }
// }
// Figure(3D,Big,VPD=310,NoScales): Next are some examples showing how you can combine edge descriptors to obtain different edge sets. You can specify the top front edge with a numerical vector or by combining the named direction vectors. If you combine them as a list you get all the edges around the front or top faces. Adding `except` removes an edge.
// xdistribute(43){
// _show_edges(_edges([0,-1,1]),toplabel=["edges=[0,-1,1]"]);
// _show_edges(_edges(TOP+FRONT),toplabel=["edges=TOP+FRONT"]);
// _show_edges(_edges([TOP,FRONT]),toplabel=["edges=[TOP,FRONT]"]);
// _show_edges(_edges([TOP,FRONT],TOP+FRONT),toplabel=["edges=[TOP,FRONT]","except=TOP+FRONT"]);
// }
// Figure(3D,Big,VPD=310,NoScales): Using `except=BACK` removes the four edges surrounding the back face if they are present in the edge set. In the first example only one edge needs to be removed. In the second example we remove two of the Z-aligned edges. The third example removes all four back edges from the default edge set of all edges. You can explicitly give `edges="ALL"` but it is not necessary, since this is the default. In the fourth example, the edge set of Y-aligned edges contains no back edges, so the `except` parameter has no effect.
// xdistribute(43){
// _show_edges(_edges(BOT,BACK), toplabel=["edges=BOT","except=BACK"]);
// _show_edges(_edges("Z",BACK), toplabel=["edges=\"Z\"", "except=BACK"]);
// _show_edges(_edges("ALL",BACK), toplabel=["(edges=\"ALL\")", "except=BACK"]);
// _show_edges(_edges("Y",BACK), toplabel=["edges=\"Y\"","except=BACK"]);
// }
// Figure(3D,Big,NoScales,VPD=310): On the left `except` is a list to remove two edges. In the center we show a corner edge set defined by a numerical vector, and at the right we remove that same corner edge set with named direction vectors.
// xdistribute(52){
// _show_edges(_edges("ALL",[FRONT+RIGHT,FRONT+LEFT]),
// toplabel=["except=[FRONT+RIGHT,"," FRONT+LEFT]"]);
// _show_edges(_edges([1,-1,1]),toplabel=["edges=[1,-1,1]"]);
// _show_edges(_edges([TOP,BOT], TOP+RIGHT+FRONT),toplabel=["edges=[TOP,BOT]","except=TOP+RIGHT+FRONT"]);
// }
// SubSection: Specifying Corners
// Modules operating on corners use two arguments to describe the corner set they will use: The `corners` argument
// is a list of corner set descriptors to include in the corner set, and the `except` argument is a list of
// corner set descriptors to remove from the corner set.
// The default value for `corners` is `"ALL"`, the set of all corners.
// The default value for `except` is the empty set, meaning no corners are removed.
// If either argument is just a single corner set
// descriptor it can be passed directly rather than in a singleton list.
// Each corner set descriptor must be one of:
// - A vector pointing towards a corner, indicating that corner.
// - A vector pointing towards an edge indicating both corners at the ends of that edge.
// - A vector pointing towards a face, indicating all the corners of that face.
// - The string `"ALL"`, indicating all corners.
// - The string `"NONE"`, indicating no corners at all.
// - A length 8 vector where each entry corresponds to a corner and is 1 if the corner is included and 0 if it is excluded. The corner ordering is
// ```
// [X-Y-Z-, X+Y-Z-, X-Y+Z-, X+Y+Z-, X-Y-Z+, X+Y-Z+, X-Y+Z+, X+Y+Z+]
// ```
// You can specify corner descriptors directly by giving a vector, or you can use sums of the
// named direction vectors described above. Below we show all of the corner sets you can
// describe with sums of the direction vectors and then we show some examples of combining
// corner set descriptors.
// Figure(3D,Big,NoScales,VPD=300): Vectors pointing toward a corner select that corner.
// ydistribute(55) {
// xdistribute(35) {
// _show_corners(corners=FRONT+LEFT+TOP);
// _show_corners(corners=FRONT+RIGHT+TOP);
// _show_corners(corners=FRONT+LEFT+BOT);
// _show_corners(corners=FRONT+RIGHT+BOT);
// }
// xdistribute(35) {
// _show_corners(corners=TOP+LEFT+BACK);
// _show_corners(corners=TOP+RIGHT+BACK);
// _show_corners(corners=BOT+LEFT+BACK);
// _show_corners(corners=BOT+RIGHT+BACK);
// }
// }
// Figure(3D,Big,NoScales,VPD=340): Vectors pointing toward an edge select the corners and the ends of the edge.
// ydistribute(55) {
// xdistribute(35) {
// _show_corners(corners=BOT+RIGHT);
// _show_corners(corners=BOT+BACK);
// _show_corners(corners=BOT+LEFT);
// _show_corners(corners=BOT+FRONT);
// }
// xdistribute(35) {
// _show_corners(corners=FWD+RIGHT);
// _show_corners(corners=BACK+RIGHT);
// _show_corners(corners=BACK+LEFT);
// _show_corners(corners=FWD+LEFT);
// }
// xdistribute(35) {
// _show_corners(corners=TOP+RIGHT);
// _show_corners(corners=TOP+BACK);
// _show_corners(corners=TOP+LEFT);
// _show_corners(corners=TOP+FRONT);
// }
// }
// Figure(3D,Med,NoScales,VPD=225): Vectors pointing toward a face select the corners of the face.
// ydistribute(55) {
// xdistribute(35) {
// _show_corners(corners=LEFT);
// _show_corners(corners=FRONT);
// _show_corners(corners=RIGHT);
// }
// xdistribute(35) {
// _show_corners(corners=TOP);
// _show_corners(corners=BACK);
// _show_corners(corners=BOTTOM);
// }
// }
// Figure(3D,Med,NoScales,VPD=200): Corners by name
// xdistribute(35) {
// _show_corners(corners="ALL");
// _show_corners(corners="NONE");
// }
// Figure(3D,Big,NoScales,VPD=300): Next are some examples showing how you can combine corner descriptors to obtain different corner sets. You can specify corner sets numerically or by adding together named directions. The third example shows a list of two corner specifications, giving all the corners on the front face or the right face.
// xdistribute(52){
// _show_corners(_corners([1,-1,-1]),toplabel=["corners=[1,-1,-1]"]);
// _show_corners(_corners(BOT+RIGHT+FRONT),toplabel=["corners=BOT+RIGHT+FRONT"]);
// _show_corners(_corners([FRONT,RIGHT]), toplabel=["corners=[FRONT,RIGHT]"]);
// }
// Figure(3D,Big,NoScales,VPD=300): Corners for one edge, two edges, and all the edges except the two on one edge. Note that since the default is all edges, you only need to give the except argument in this case:
// xdistribute(52){
// _show_corners(_corners(FRONT+TOP), toplabel=["corners=FRONT+TOP"]);
// _show_corners(_corners([FRONT+TOP,BOT+BACK]), toplabel=["corners=[FRONT+TOP,"," BOT+BACK]"]);
// _show_corners(_corners("ALL",FRONT+TOP), toplabel=["(corners=\"ALL\")","except=FRONT+TOP"]);
// }
// Figure(3D,Med,NoScales,VPD=240): The first example shows a single corner removed from the top corners using a numerical vector. The second one shows removing a set of two corner descriptors from the implied set of all corners.
// xdistribute(58){
// _show_corners(_corners(TOP,[1,1,1]), toplabel=["corners=TOP","except=[1,1,1]"]);
// _show_corners(_corners("ALL",[FRONT+RIGHT+TOP,FRONT+LEFT+BOT]),
// toplabel=["except=[FRONT+RIGHT+TOP,"," FRONT+LEFT+BOT]"]);
// }
// Section: Attachment Positioning
@ -508,7 +766,7 @@ module hulling(a)
// Takes a 3D mask shape, and attaches it to the given edges, with the appropriate orientation to be
// `diff()`ed away. The mask shape should be vertically oriented (Z-aligned) with the back-right
// quadrant (X+Y+) shaped to be diffed away from the edge of parent attachable shape.
// For details on specifying the edges to mask see [Specifying Edges](edges.scad#section-specifying-edges).
// For details on specifying the edges to mask see [Specifying Edges](attachments.scad#subsection-specifying-edges).
// For a step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
// Figure: A Typical Edge Rounding Mask
// module roundit(l,r) difference() {
@ -519,8 +777,8 @@ module hulling(a)
// }
// roundit(l=30,r=10);
// Arguments:
// edges = Edges to mask. See [Specifying Edges](edges.scad#section-specifying-edges). Default: All edges.
// except = Edges to explicitly NOT mask. See [Specifying Edges](edges.scad#section-specifying-edges). Default: No edges.
// edges = Edges to mask. See [Specifying Edges](attachments.scad#subsection-specifying-edges). Default: All edges.
// except = Edges to explicitly NOT mask. See [Specifying Edges](attachments.scad#subsection-specifying-edges). Default: No edges.
// Side Effects:
// Sets `$tags = "mask"` for all children.
// Example:
@ -562,11 +820,11 @@ module edge_mask(edges=EDGES_ALL, except=[]) {
// Description:
// Takes a 3D mask shape, and attaches it to the specified corners, with the appropriate orientation to
// be `diff()`ed away. The 3D corner mask shape should be designed to mask away the X+Y+Z+ octant.
// See [Specifying Corners](edges.scad#section-specifying-corners) for information on how to specify corner sets.
// See [Specifying Corners](attachments.scad#subsection-specifying-corners) for information on how to specify corner sets.
// For a step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
// Arguments:
// corners = Corners to mask. See [Specifying Corners](edges.scad#section-specifying-corners). Default: All corners.
// except = Corners to explicitly NOT mask. See [Specifying Corners](edges.scad#section-specifying-corners). Default: No corners.
// corners = Corners to mask. See [Specifying Corners](attachments.scad#subsection-specifying-corners). Default: All corners.
// except = Corners to explicitly NOT mask. See [Specifying Corners](attachments.scad#subsection-specifying-corners). Default: No corners.
// Side Effects:
// Sets `$tags = "mask"` for all children.
// Example:
@ -604,7 +862,7 @@ module corner_mask(corners=CORNERS_ALL, except=[]) {
// 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.
// See [Specifying Faces](edges.scad#section-specifying-faces) for information on specifying faces.
// See [Specifying Faces](attachments.scad#subsection-specifying-faces) for information on specifying faces.
// For a step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
// Arguments:
// faces = Faces to mask edges and corners of.
@ -637,12 +895,12 @@ module face_profile(faces=[], r, d, convexity=10) {
// Description:
// Takes a 2D mask shape and attaches it to the selected edges, with the appropriate orientation and
// extruded length to be `diff()`ed away, to give the edge a matching profile.
// For details on specifying the edges to mask see [Specifying Edges](edges.scad#section-specifying-edges).
// For details on specifying the edges to mask see [Specifying Edges](attachments.scad#subsection-specifying-edges).
// For a step-by-step
// explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
// Arguments:
// edges = Edges to mask. See [Specifying Edges](edges.scad#section-specifying-edges). Default: All edges.
// except = Edges to explicitly NOT mask. See [Specifying Edges](edges.scad#section-specifying-edges). Default: No edges.
// edges = Edges to mask. See [Specifying Edges](attachments.scad#subsection-specifying-edges). Default: All edges.
// except = Edges to explicitly NOT mask. See [Specifying Edges](attachments.scad#subsection-specifying-edges). Default: No edges.
// convexity = Max number of times a line could intersect the perimeter of the mask shape. Default: 10
// Side Effects:
// Sets `$tags = "mask"` for all children.
@ -693,11 +951,11 @@ module edge_profile(edges=EDGES_ALL, except=[], convexity=10) {
// Takes a 2D mask shape, rotationally extrudes and converts it into a corner mask, and attaches it
// to the selected corners with the appropriate orientation. Tags it as a "mask" to allow it to be
// `diff()`ed away, to give the corner a matching profile.
// See [Specifying Corners](edges.scad#section-specifying-corners) for information on how to specify corner sets.
// See [Specifying Corners](attachments.scad#subsection-specifying-corners) for information on how to specify corner sets.
// For a step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
// Arguments:
// corners = Corners to mask. See [Specifying Corners](edges.scad#section-specifying-corners). Default: All corners.
// except = Corners to explicitly NOT mask. See [Specifying Corners](edges.scad#section-specifying-corners). Default: No corners.
// corners = Corners to mask. See [Specifying Corners](attachments.scad#subsection-specifying-corners). Default: All corners.
// except = Corners to explicitly NOT mask. See [Specifying Corners](attachments.scad#subsection-specifying-corners). Default: No corners.
// ---
// r = Radius of corner mask.
// d = Diameter of corner mask.
@ -810,9 +1068,9 @@ module corner_profile(corners=CORNERS_ALL, except=[], r, d, convexity=10) {
// For a more step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
//
// Arguments:
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// ---
// size = If given as a 3D vector, contains the XY size of the bottom of the cuboidal/prismoidal volume, and the Z height. If given as a 2D vector, contains the front X width of the rectangular/trapezoidal shape, and the Y length.
// size2 = If given as a 2D vector, contains the XY size of the top of the prismoidal volume. If given as a number, contains the back width of the trapezoidal shape.
@ -1097,9 +1355,9 @@ function named_anchor(name, pos=[0,0,0], orient=UP, spin=0) = [name, pos, orient
// For a more step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
//
// Arguments:
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// ---
// size = If given as a 3D vector, contains the XY size of the bottom of the cuboidal/prismoidal volume, and the Z height. If given as a 2D vector, contains the front X width of the rectangular/trapezoidal shape, and the Y length.
// size2 = If given as a 2D vector, contains the XY size of the top of the prismoidal volume. If given as a number, contains the back width of the trapezoidal shape.
@ -1448,9 +1706,9 @@ function _attach_geom_size(geom) =
// Returns the affine3d transformation matrix needed to `anchor`, `spin`, and `orient`
// the given geometry `geom` shape into position.
// Arguments:
// anchor = Anchor point to translate to the origin `[0,0,0]`. See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Anchor point to translate to the origin `[0,0,0]`. See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// geom = The geometry description of the shape.
// p = If given as a VNF, path, or point, applies the affine3d transformation matrix to it and returns the result.
function _attach_transform(anchor, spin, orient, geom, p) =
@ -1973,5 +2231,422 @@ module frame_ref(s=15, opacity=1) {
}
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Code after this is internal code for managing edge and corner sets and for displaying
/// edge and corners in the docs
///
module _edges_text3d(txt,size=3) {
if (is_list(txt)) {
for (i=idx(txt)) {
down((i-len(txt)/2+0.5)*size*1.5) {
_edges_text3d(txt[i], size=size);
}
}
} else {
xrot(90) color("#000")
linear_extrude(height=0.1) {
text(text=txt, size=size, halign="center", valign="center");
}
}
}
function _edges_vec_txt(x) = is_string(x)? str("\"", x, "\"") :
assert(is_string(x) || is_vector(x,3), str(x))
let(
lst = concat(
x.z>0? ["TOP"] : x.z<0? ["BOT"] : [],
x.y>0? ["BACK"] : x.y<0? ["FWD"] : [],
x.x>0? ["RIGHT"] : x.x<0? ["LEFT"] : []
),
out = [
for (i = idx(lst))
i>0? str("+",lst[i]) : lst[i]
]
) out;
function _edges_text(edges) =
is_string(edges) ? [str("\"",edges,"\"")] :
edges==EDGES_NONE ? ["EDGES_NONE"] :
edges==EDGES_ALL ? ["EDGES_ALL"] :
_is_edge_array(edges) ? [""] :
is_vector(edges,3) ? _edges_vec_txt(edges) :
is_list(edges) ? let(
lst = [for (x=edges) each _edges_text(x)],
out = [
for (i=idx(lst))
str(
(i==0? "[" : ""),
lst[i],
(i<len(lst)-1? "," : ""),
(i==len(lst)-1? "]" : "")
)
]
) out :
[""];
/// Internal Constant: EDGES_NONE
/// Topics: Edges
/// See Also: EDGES_ALL, edges()
/// Description:
/// The set of no edges.
/// Figure(3D):
/// _show_edges(edges="NONE");
EDGES_NONE = [[0,0,0,0], [0,0,0,0], [0,0,0,0]];
/// Internal Constant: EDGES_ALL
/// Topics: Edges
/// See Also: EDGES_NONE, edges()
/// Description:
/// The set of all edges.
/// Figure(3D):
/// _show_edges(edges="ALL");
EDGES_ALL = [[1,1,1,1], [1,1,1,1], [1,1,1,1]];
/// Internal Constant: EDGES_OFFSETS
/// Topics: Edges
/// See Also: EDGES_NONE, EDGES_ALL, edges()
/// Description:
/// The vectors pointing to the center of each edge of a unit sized cube.
/// Each item in an edge array will have a corresponding vector in this array.
EDGE_OFFSETS = [
[
[ 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]
]
];
/// Internal Function: _is_edge_array()
/// Topics: Edges, Type Checking
/// Usage:
/// bool = _is_edge_array(x);
/// Description:
/// Returns true if the given value has the form of an edge array.
/// Arguments:
/// x = The item to check the type of.
/// See Also: edges(), EDGES_NONE, EDGES_ALL
function _is_edge_array(x) = is_list(x) && is_vector(x[0]) && len(x)==3 && len(x[0])==4;
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(v_abs(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
]
];
/// Internal Function: _normalize_edges()
/// Topics: Edges
/// Usage:
/// edges = _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`.
/// See Also: edges(), EDGES_NONE, EDGES_ALL
function _normalize_edges(v) = [for (ax=v) [for (edge=ax) edge>0? 1 : 0]];
/// Internal Function: _edges()
/// Topics: Edges
/// Usage:
/// edgs = _edges(v);
/// edgs = _edges(v, except);
///
/// Description:
/// Takes a list of edge set descriptors, and returns a normalized edges array
/// that represents all those given edges.
/// Arguments:
/// v = The edge set to include.
/// except = The edge set to specifically exclude, even if they are in `v`.
///
/// See Also: EDGES_NONE, EDGES_ALL
///
function _edges(v, except=[]) =
v==[] ? EDGES_NONE :
(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)])
);
/// Internal Module: _show_edges()
/// Topics: Edges, Debugging
/// Usage:
/// _show_edges(edges, [size=], [text=], [txtsize=]);
/// Description:
/// Draws a semi-transparent cube with the given edges highlighted in red.
/// Arguments:
/// edges = The edges to highlight.
/// size = The scalar size of the cube.
/// text = The text to show on the front of the cube.
/// txtsize = The size of the text.
/// See Also: _edges(), EDGES_NONE, EDGES_ALL
/// Example:
/// _show_edges(size=30, edges=["X","Y"]);
module _show_edges(edges="ALL", size=20, text, txtsize=3,toplabel) {
edge_set = _edges(edges);
text = !is_undef(text) ? text : _edges_text(edges);
color("red") {
for (axis=[0:2], i=[0:3]) {
if (edge_set[axis][i] > 0) {
translate(EDGE_OFFSETS[axis][i]*size/2) {
if (axis==0) xcyl(h=size, d=2);
if (axis==1) ycyl(h=size, d=2);
if (axis==2) zcyl(h=size, d=2);
}
}
}
}
fwd(size/2) _edges_text3d(text, size=txtsize);
color("yellow",0.7) cuboid(size=size);
vpr = [55,0,25];
color("black")
if (is_def(toplabel))
for(h=idx(toplabel)) up(21+6*h)rot(vpr)atext(select(toplabel,-h-1),size=3.3,h=0.1,orient=UP,anchor=FRONT);
}
/// Internal Constant: CORNERS_NONE
/// Topics: Corners
/// Description:
/// The set of no corners.
/// Figure(3D):
/// _show_corners(corners="NONE");
/// See Also: CORNERS_ALL, corners()
CORNERS_NONE = [0,0,0,0,0,0,0,0]; // No corners.
/// Internal Constant: CORNERS_ALL
/// Topics: Corners
/// Description:
/// The set of all corners.
/// Figure(3D):
/// _show_corners(corners="ALL");
/// See Also: CORNERS_NONE, _corners()
CORNERS_ALL = [1,1,1,1,1,1,1,1];
/// Internal Constant: CORNER_OFFSETS
/// Topics: Corners
/// Description:
/// The vectors pointing to each corner of a unit sized cube.
/// Each item in a corner array will have a corresponding vector in this array.
/// See Also: CORNERS_NONE, CORNERS_ALL, _corners()
CORNER_OFFSETS = [
[-1,-1,-1], [ 1,-1,-1], [-1, 1,-1], [ 1, 1,-1],
[-1,-1, 1], [ 1,-1, 1], [-1, 1, 1], [ 1, 1, 1]
];
/// Internal Function: _is_corner_array()
/// Topics: Corners, Type Checking
/// Usage:
/// bool = _is_corner_array(x)
/// Description:
/// Returns true if the given value has the form of a corner array.
/// See Also: CORNERS_NONE, CORNERS_ALL, _corners()
function _is_corner_array(x) = is_vector(x) && len(x)==8 && all([for (xx=x) xx==1||xx==0]);
/// Internal Function: _normalize_corners()
/// Topics: Corners
/// Usage:
/// corns = _normalize_corners(v);
/// Description:
/// Normalizes all values in a corner array to be `1`, if it was originally greater than `0`,
/// or `0`, if it was originally less than or equal to `0`.
/// See Also: CORNERS_NONE, CORNERS_ALL, _corners()
function _normalize_corners(v) = [for (x=v) x>0? 1 : 0];
function _corner_set(v) =
_is_corner_array(v)? v : [
for (i=[0:7]) let(
v2 = CORNER_OFFSETS[i]
) (
is_string(v)? (
v=="ALL"? true : // Return all corners.
v=="NONE"? false : // Return no corners.
let(valid_values = ["ALL", "NONE"])
assert(
in_list(v, valid_values),
str(v, " must be a vector, corner array, or one of ", valid_values)
) v
) :
all([for (i=[0:2]) !v[i] || (v[i]==v2[i])])
)? 1 : 0
];
/// Function: _corners()
/// Topics: Corners
/// Usage:
/// corns = _corners(v);
/// corns = _corners(v, except);
/// Description:
/// Takes a list of corner set descriptors, and returns a normalized corners array
/// that represents all those given corners. If the `except` argument is given
/// a list of corner set descriptors, then all those corners will be removed
/// from the returned corners array. If either argument only has a single corner
/// set descriptor, you do not have to pass it in a list.
function _corners(v, except=[]) =
v==[] ? CORNERS_NONE :
(is_string(v) || is_vector(v) || _is_corner_array(v))? _corners([v], except=except) :
(is_string(except) || is_vector(except) || _is_corner_array(except))? _corners(v, except=[except]) :
except==[]? _normalize_corners(sum([for (x=v) _corner_set(x)])) :
let(
a = _normalize_corners(sum([for (x=v) _corner_set(x)])),
b = _normalize_corners(sum([for (x=except) _corner_set(x)]))
) _normalize_corners(a - b);
/// Internal Function: _corner_edges()
/// Topics: Corners
/// Description:
/// Returns [XCOUNT,YCOUNT,ZCOUNT] where each is the count of edges aligned with that
/// axis that are in the edge set and touch the given corner.
/// Arguments:
/// edges = Standard edges array.
/// v = Vector pointing to the corner to count edge intersections at.
/// See Also: CORNERS_NONE, CORNERS_ALL, _corners()
function _corner_edges(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]];
/// InternalFunction: _corner_edge_count()
/// Topics: Corners
/// 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.
/// See Also: CORNERS_NONE, CORNERS_ALL, _corners()
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];
function _corners_text(corners) =
is_string(corners) ? [str("\"",corners,"\"")] :
corners==CORNERS_NONE ? ["CORNERS_NONE"] :
corners==CORNERS_ALL ? ["CORNERS_ALL"] :
_is_corner_array(corners) ? [""] :
is_vector(corners,3) ? _edges_vec_txt(corners) :
is_list(corners) ? let(
lst = [for (x=corners) each _corners_text(x)],
out = [
for (i=idx(lst))
str(
(i==0? "[" : ""),
lst[i],
(i<len(lst)-1? "," : ""),
(i==len(lst)-1? "]" : "")
)
]
) out :
[""];
/// Internal Module: _show_corners()
/// Topics: Corners, Debugging
/// Usage:
/// _show_corners(corners, [size=], [text=], [txtsize=]);
/// Description:
/// Draws a semi-transparent cube with the given corners highlighted in red.
/// Arguments:
/// corners = The corners to highlight.
/// size = The scalar size of the cube.
/// text = If given, overrides the text to be shown on the front of the cube.
/// txtsize = The size of the text.
/// See Also: CORNERS_NONE, CORNERS_ALL, corners()
/// Example:
/// _show_corners(corners=FWD+RIGHT, size=30);
module _show_corners(corners="ALL", size=20, text, txtsize=3,toplabel) {
corner_set = _corners(corners);
text = !is_undef(text) ? text : _corners_text(corners);
for (i=[0:7]) if (corner_set[i]>0)
translate(CORNER_OFFSETS[i]*size/2)
color("red") sphere(d=2, $fn=16);
fwd(size/2) _edges_text3d(text, size=txtsize);
color("yellow",0.7) cuboid(size=size);
vpr = [55,0,25];
color("black")
if (is_def(toplabel))
for(h=idx(toplabel)) up(21+6*h)rot(vpr)atext(select(toplabel,-h-1),size=3.3,h=.1,orient=UP,anchor=FRONT);
}
module _show_cube_faces(faces, size=20, toplabel,botlabel) {
color("red")
for(f=faces){
move(f*size/2) rot(from=UP,to=f)
cuboid([size,size,.1]);
}
vpr = [55,0,25];
color("black"){
if (is_def(toplabel))
for(h=idx(toplabel)) up(21+6*h)rot(vpr)atext(select(toplabel,-h-1),size=3.3,h=.1,orient=UP,anchor=FRONT);
if (is_def(botlabel))
for(h=idx(botlabel)) down(26+6*h)rot(vpr)atext(botlabel[h],size=3.3,h=.1,orient=UP,anchor=FRONT);
}
color("yellow",0.7) cuboid(size=size);
}
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap

View file

@ -25,9 +25,9 @@ include <rounding.scad>
// Arguments:
// wall = Wall thickness in mm.
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// "tamper-ring" = Centered at the top of the anti-tamper ring channel.
// "support-ring" = Centered at the bottom of the support ring.
@ -147,9 +147,9 @@ function pco1810_neck(wall=2, anchor="support-ring", spin=0, orient=UP) =
// wall = Wall thickness in mm.
// texture = The surface texture of the cap. Valid values are "none", "knurled", or "ribbed". Default: "none"
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// "inside-top" = Centered on the inside top of the cap.
// Examples:
@ -217,9 +217,9 @@ function pco1810_cap(wall=2, texture="none", anchor=BOTTOM, spin=0, orient=UP) =
// Arguments:
// wall = Wall thickness in mm.
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// "tamper-ring" = Centered at the top of the anti-tamper ring channel.
// "support-ring" = Centered at the bottom of the support ring.
@ -338,9 +338,9 @@ function pco1881_neck(wall=2, anchor="support-ring", spin=0, orient=UP) =
// Arguments:
// wall = Wall thickness in mm.
// texture = The surface texture of the cap. Valid values are "none", "knurled", or "ribbed". Default: "none"
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// "inside-top" = Centered on the inside top of the cap.
// Examples:
@ -407,9 +407,9 @@ function pco1881_cap(wall=2, texture="none", anchor=BOTTOM, spin=0, orient=UP) =
// pitch = Thread pitch
// round_supp = True to round the lower edge of the support ring
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// "support-ring" = Centered at the bottom of the support ring.
// Example:
@ -532,9 +532,9 @@ function generic_bottle_neck(
// neck_od = Outer diameter of neck in mm.
// flank_angle = Angle of taper on threads.
// pitch = Thread pitch in mm.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// "inside-top" = Centered on the inside top of the cap.
// Examples:
@ -974,9 +974,9 @@ function bottle_adapter_neck_to_neck(
// id = inner diameter
// style = Either "L" or "M" to specify the thread style. Default: "L"
// bead = if true apply a bad to the neck. Default: false
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Examples:
// sp_neck(48,400,2);
// sp_neck(48,400,2,bead=true);

View file

@ -353,7 +353,7 @@ function max_index(vals, all=false) =
// Description:
// Finds the first item in `list` that matches `val`, returning the index. Returns `undef` if there is no match.
// Arguments:
// val = The value to search for. If given a function literal of signature `function (x)`, uses that function to check list items. Returns true for a match.
// val = The value to search for.
// list = The list to search through.
// ---
// start = The index to start searching from. Default: 0
@ -516,9 +516,6 @@ function unique_count(list) =
// Section: Sorting
@ -781,7 +778,7 @@ function group_sort(list, idx) =
// Function: group_data()
// Usage:
// groupings = group_data(groups, values);
// Topics: Array Handling
// Topics: List Handling
// Description:
// Given a list of integer group numbers, and an equal-length list of values,
// returns a list of groups with the values sorted into the corresponding groups.

View file

@ -44,9 +44,9 @@ function cubetruss_dist(cubes=0, gaps=0, size, strut) =
// strut = The width of the struts on the cubetruss cubes. Default: `$cubetruss_strut_size` (usually 3)
// bracing = If true, adds internal cross-braces. Default: `$cubetruss_bracing` (usually true)
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Topics: Attachable, Trusses
// Examples:
// cubetruss_segment(bracing=false);
@ -113,9 +113,9 @@ module cubetruss_segment(size, strut, bracing, anchor=CENTER, spin=0, orient=UP)
// strut = The width of the struts on the cubetruss cubes. Default: `$cubetruss_strut_size` (usually 3)
// extents = If given as an integer, specifies the number of vertical segments for the support. If given as a list of 3 integers, specifies the number of segments in the X, Y, and Z directions. Default: 1.
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Topics: Attachable, Trusses
// Example(VPT=[0,0,0],VPD=150):
// cubetruss_support();
@ -174,9 +174,9 @@ module cubetruss_support(size, strut, extents=1, anchor=CENTER, spin=0, orient=U
// strut = The width of the struts on the cubetruss cubes. Default: `$cubetruss_strut_size` (usually 3)
// clipthick = The thickness of the clip. Default: `$cubetruss_clip_thickness` (usually 1.6)
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Topics: Attachable, Trusses
// Examples:
// cubetruss_clip(extents=2);
@ -238,9 +238,9 @@ module cubetruss_clip(extents=1, size, strut, clipthick, anchor=CENTER, spin=0,
// strut = The width of the struts on the cubetruss cubes. Default: `$cubetruss_strut_size` (usually 3)
// clipthick = The thickness of the clips. Default: `$cubetruss_clip_thickness` (usually 1.6)
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Topics: Attachable, Trusses
// Examples:
// cubetruss_foot(w=1);
@ -315,9 +315,9 @@ module cubetruss_foot(w=1, size, strut, clipthick, anchor=CENTER, spin=0, orient
// strut = The width of the struts on the cubetruss cubes. Default: `$cubetruss_strut_size` (usually 3)
// clipthick = The thickness of the clips. Default: `$cubetruss_clip_thickness` (usually 1.6)
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Topics: Attachable, Trusses
// Examples:
// cubetruss_joiner(w=1, vert=false);
@ -381,9 +381,9 @@ module cubetruss_joiner(w=1, vert=true, size, strut, clipthick, anchor=CENTER, s
// strut = The width of the struts on the cubetruss cubes. Default: `$cubetruss_strut_size` (usually 3)
// clipthick = The thickness of the clips. Default: `$cubetruss_clip_thickness` (usually 1.6)
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Topics: Attachable, Trusses
// Examples:
// cubetruss_uclip(dual=false);
@ -428,9 +428,9 @@ module cubetruss_uclip(dual=true, size, strut, clipthick, anchor=CENTER, spin=0,
// bracing = If true, adds internal cross-braces. Default: `$cubetruss_bracing` (usually true)
// clipthick = The thickness of the clips. Default: `$cubetruss_clip_thickness` (usually 1.6)
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Topics: Attachable, Trusses
// Examples:
// cubetruss(extents=3);
@ -498,9 +498,9 @@ module cubetruss(extents=6, clips=[], bracing, size, strut, clipthick, anchor=CE
// bracing = If true, adds internal cross-braces. Default: `$cubetruss_bracing` (usually true)
// clipthick = The thickness of the clips. Default: `$cubetruss_clip_thickness` (usually 1.6)
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Topics: Attachable, Trusses
// Examples:
// cubetruss_corner(extents=2);

View file

@ -327,13 +327,17 @@ module zcopies(spacing, n, l, sp)
// zrot(180/6)
// cylinder(h=20, d=10/cos(180/6)+0.01, $fn=6);
// }
module grid2d(spacing, n, size, stagger=false, inside=undef, nonzero=false)
module grid2d(spacing, n, size, stagger=false, inside=undef, nonzero)
{
assert(in_list(stagger, [false, true, "alt"]));
bounds = is_undef(inside)? undef :
is_path(inside)? pointlist_bounds(inside) :
assert(is_region(inside))
pointlist_bounds(flatten(inside));
nonzero = is_path(inside) ? default(nonzero,false)
: assert(is_undef(nonzero), "nonzero only allowed if inside is a polygon")
false;
size = is_num(size)? [size, size] :
is_vector(size)? assert(len(size)==2) size :
bounds!=undef? [
@ -362,7 +366,7 @@ module grid2d(spacing, n, size, stagger=false, inside=undef, nonzero=false)
if (
is_undef(inside) ||
(is_path(inside) && point_in_polygon(pos, inside, nonzero=nonzero)>=0) ||
(is_region(inside) && point_in_region(pos, inside, nonzero=nonzero)>=0)
(is_region(inside) && point_in_region(pos, inside)>=0)
) {
$col = col;
$row = row;
@ -384,7 +388,7 @@ module grid2d(spacing, n, size, stagger=false, inside=undef, nonzero=false)
pos = v_mul([2*col,row],spacing) + [rowdx,0] - offset;
if (
is_undef(inside) ||
(is_path(inside) && point_in_polygon(pos, inside)>=0) ||
(is_path(inside) && point_in_polygon(pos, inside, nonzero=nonzero)>=0) ||
(is_region(inside) && point_in_region(pos, inside)>=0)
) {
$col = col * 2 + ((row%2!=staggermod)? 1 : 0);

View file

@ -627,8 +627,8 @@ module dashed_stroke(path, dashpat=[3,3], width=1, closed=false) {
// start = Start angle of arc.
// wedge = If true, include centerpoint `cp` in output to form pie slice shape.
// endpoint = If false exclude the last point (function only). Default: true
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). (Module only) Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). (Module only) Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). (Module only) Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). (Module only) Default: `0`
// Examples(2D):
// arc(N=4, r=30, angle=30, wedge=true);
// arc(r=30, angle=30, wedge=true);

View file

@ -1,672 +0,0 @@
//////////////////////////////////////////////////////////////////////
// LibFile: edges.scad
// This file describes how to specify directions, face sets, edge sets and corner sets.
// Includes:
// include <BOSL2/std.scad>
//////////////////////////////////////////////////////////////////////
// Section: Specifying Directions
// You can use direction vectors to specify anchors for objects or to specify edges, faces, and
// corners of cubes. You can simply specify these direction vectors numerically, but another
// option is to use named constants for direction vectors. These constants define unit vectors
// for the six axis directions as shown below.
// Figure(3D,Big,VPD=6): Named constants for direction vectors. Some directions have more than one name.
// $fn=12;
// stroke([[0,0,0],RIGHT], endcap2="arrow2", width=.05);
// color("black")right(.05)up(.05)move(RIGHT)atext("RIGHT",size=.1,h=.01,anchor=LEFT,orient=FRONT);
// stroke([[0,0,0],LEFT], endcap2="arrow2", width=.05);
// color("black")left(.05)up(.05)move(LEFT)atext("LEFT",size=.1,h=.01,anchor=RIGHT,orient=FRONT);
// stroke([[0,0,0],FRONT], endcap2="arrow2", width=.05);
// color("black")
// left(.1){
// up(.12)move(FRONT)atext("FRONT",size=.1,h=.01,anchor=RIGHT,orient=FRONT);
// move(FRONT)atext("FWD",size=.1,h=.01,anchor=RIGHT,orient=FRONT);
// down(.12)move(FRONT)atext("FORWARD",size=.1,h=.01,anchor=RIGHT,orient=FRONT);
// }
// stroke([[0,0,0],BACK], endcap2="arrow2", width=.05);
// right(.05)
// color("black")move(BACK)atext("BACK",size=.1,h=.01,anchor=LEFT,orient=FRONT);
// stroke([[0,0,0],DOWN], endcap2="arrow2", width=.05);
// color("black")
// right(.1){
// up(.12)move(BOT)atext("DOWN",size=.1,h=.01,anchor=LEFT,orient=FRONT);
// move(BOT)atext("BOTTOM",size=.1,h=.01,anchor=LEFT,orient=FRONT);
// down(.12)move(BOT)atext("BOT",size=.1,h=.01,anchor=LEFT,orient=FRONT);
// }
// stroke([[0,0,0],TOP], endcap2="arrow2", width=.05);
// color("black")left(.05){
// up(.12)move(TOP)atext("TOP",size=.1,h=.01,anchor=RIGHT,orient=FRONT);
// move(TOP)atext("UP",size=.1,h=.01,anchor=RIGHT,orient=FRONT);
// }
// Section: Specifying Faces
// Modules operating on faces accept a list of faces to describe the faces to operate on. Each
// face is given by a vector that points to that face. Attachments of cuboid objects onto their faces also
// work by choosing an attachment face with a single vector in the same manner.
// Figure(3D,Big,NoScales,VPD=275): The six faces of the cube. Some have faces have more than one name.
// ydistribute(50) {
// xdistribute(35){
// _show_cube_faces([BACK], botlabel=["BACK"]);
// _show_cube_faces([UP],botlabel=["TOP","UP"]);
// _show_cube_faces([RIGHT],botlabel=["RIGHT"]);
// }
// xdistribute(35){
// _show_cube_faces([FRONT],toplabel=["FRONT","FWD", "FORWARD"]);
// _show_cube_faces([DOWN],toplabel=["BOTTOM","BOT","DOWN"]);
// _show_cube_faces([LEFT],toplabel=["LEFT"]);
// }
// }
// Section: Specifying Edges
// Modules operating on edges use two arguments to describe the edge set they will use: The `edges` argument
// is a list of edge set descriptors to include in the edge set, and the `except` argument is a list of
// edge set descriptors to remove from the edge set.
// The default value for `edges` is `"ALL"`, the set of all edges.
// The default value for `except` is the empty set, meaning no edges are removed.
// If either argument is just a single edge set
// descriptor it can be passed directly rather than in a singleton list.
// Each edge set descriptor must be one of:
// - A vector pointing towards an edge, indicating that single 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.
// - The string `"X"`, indicating all X axis aligned edges.
// - The string `"Y"`, indicating all Y axis aligned edges.
// - The string `"Z"`, indicating all Z axis aligned edges.
// - The string `"ALL"`, indicating all edges.
// - The string `"NONE"`, indicating no edges at all.
// - A 3x4 array, where each entry corresponds to one of the 12 edges and is set to 1 if that edge is included and 0 if the edge is not. 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+]
// ]
// ```
// You can specify edge descriptors directly by giving a vector, or you can use sums of the
// named direction vectors described above. Below we show all of the edge sets you can
// describe with sums of the direction vectors, and then we show some examples of combining
// edge set descriptors.
// Figure(3D,Big,VPD=300,NoScales): Vectors pointing toward an edge select that single edge
// ydistribute(50) {
// xdistribute(30) {
// _show_edges(edges=BOT+RIGHT);
// _show_edges(edges=BOT+BACK);
// _show_edges(edges=BOT+LEFT);
// _show_edges(edges=BOT+FRONT);
// }
// xdistribute(30) {
// _show_edges(edges=FWD+RIGHT);
// _show_edges(edges=BACK+RIGHT);
// _show_edges(edges=BACK+LEFT);
// _show_edges(edges=FWD+LEFT);
// }
// xdistribute(30) {
// _show_edges(edges=TOP+RIGHT);
// _show_edges(edges=TOP+BACK);
// _show_edges(edges=TOP+LEFT);
// _show_edges(edges=TOP+FRONT);
// }
// }
// Figure(3D,Med,VPD=205,NoScales): Vectors pointing toward a face select all edges surrounding that face.
// ydistribute(50) {
// xdistribute(30) {
// _show_edges(edges=LEFT);
// _show_edges(edges=FRONT);
// _show_edges(edges=RIGHT);
// }
// xdistribute(30) {
// _show_edges(edges=TOP);
// _show_edges(edges=BACK);
// _show_edges(edges=BOTTOM);
// }
// }
// Figure(3D,Big,VPD=300,NoScales): Vectors pointing toward a corner select all edges surrounding that corner.
// ydistribute(50) {
// xdistribute(30) {
// _show_edges(edges=FRONT+LEFT+TOP);
// _show_edges(edges=FRONT+RIGHT+TOP);
// _show_edges(edges=FRONT+LEFT+BOT);
// _show_edges(edges=FRONT+RIGHT+BOT);
// }
// xdistribute(30) {
// _show_edges(edges=TOP+LEFT+BACK);
// _show_edges(edges=TOP+RIGHT+BACK);
// _show_edges(edges=BOT+LEFT+BACK);
// _show_edges(edges=BOT+RIGHT+BACK);
// }
// }
// Figure(3D,Med,VPD=205,NoScales): Named Edge Sets
// ydistribute(50) {
// xdistribute(30) {
// _show_edges(edges="X");
// _show_edges(edges="Y");
// _show_edges(edges="Z");
// }
// xdistribute(30) {
// _show_edges(edges="ALL");
// _show_edges(edges="NONE");
// }
// }
// Figure(3D,Big,VPD=310,NoScales): Next are some examples showing how you can combine edge descriptors to obtain different edge sets. You can specify the top front edge with a numerical vector or by combining the named direction vectors. If you combine them as a list you get all the edges around the front or top faces. Adding `except` removes an edge.
// xdistribute(43){
// _show_edges(_edges([0,-1,1]),toplabel=["edges=[0,-1,1]"]);
// _show_edges(_edges(TOP+FRONT),toplabel=["edges=TOP+FRONT"]);
// _show_edges(_edges([TOP,FRONT]),toplabel=["edges=[TOP,FRONT]"]);
// _show_edges(_edges([TOP,FRONT],TOP+FRONT),toplabel=["edges=[TOP,FRONT]","except=TOP+FRONT"]);
// }
// Figure(3D,Big,VPD=310,NoScales): Using `except=BACK` removes the four edges surrounding the back face if they are present in the edge set. In the first example only one edge needs to be removed. In the second example we remove two of the Z-aligned edges. The third example removes all four back edges from the default edge set of all edges. You can explicitly give `edges="ALL"` but it is not necessary, since this is the default. In the fourth example, the edge set of Y-aligned edges contains no back edges, so the `except` parameter has no effect.
// xdistribute(43){
// _show_edges(_edges(BOT,BACK), toplabel=["edges=BOT","except=BACK"]);
// _show_edges(_edges("Z",BACK), toplabel=["edges=\"Z\"", "except=BACK"]);
// _show_edges(_edges("ALL",BACK), toplabel=["(edges=\"ALL\")", "except=BACK"]);
// _show_edges(_edges("Y",BACK), toplabel=["edges=\"Y\"","except=BACK"]);
// }
// Figure(3D,Big,NoScales,VPD=310): On the left `except` is a list to remove two edges. In the center we show a corner edge set defined by a numerical vector, and at the right we remove that same corner edge set with named direction vectors.
// xdistribute(52){
// _show_edges(_edges("ALL",[FRONT+RIGHT,FRONT+LEFT]),
// toplabel=["except=[FRONT+RIGHT,"," FRONT+LEFT]"]);
// _show_edges(_edges([1,-1,1]),toplabel=["edges=[1,-1,1]"]);
// _show_edges(_edges([TOP,BOT], TOP+RIGHT+FRONT),toplabel=["edges=[TOP,BOT]","except=TOP+RIGHT+FRONT"]);
// }
// Section: Specifying Corners
// Modules operating on corners use two arguments to describe the corner set they will use: The `corners` argument
// is a list of corner set descriptors to include in the corner set, and the `except` argument is a list of
// corner set descriptors to remove from the corner set.
// The default value for `corners` is `"ALL"`, the set of all corners.
// The default value for `except` is the empty set, meaning no corners are removed.
// If either argument is just a single corner set
// descriptor it can be passed directly rather than in a singleton list.
// Each corner set descriptor must be one of:
// - A vector pointing towards a corner, indicating that corner.
// - A vector pointing towards an edge indicating both corners at the ends of that edge.
// - A vector pointing towards a face, indicating all the corners of that face.
// - The string `"ALL"`, indicating all corners.
// - The string `"NONE"`, indicating no corners at all.
// - A length 8 vector where each entry corresponds to a corner and is 1 if the corner is included and 0 if it is excluded. The corner ordering is
// ```
// [X-Y-Z-, X+Y-Z-, X-Y+Z-, X+Y+Z-, X-Y-Z+, X+Y-Z+, X-Y+Z+, X+Y+Z+]
// ```
// You can specify corner descriptors directly by giving a vector, or you can use sums of the
// named direction vectors described above. Below we show all of the corner sets you can
// describe with sums of the direction vectors and then we show some examples of combining
// corner set descriptors.
// Figure(3D,Big,NoScales,VPD=300): Vectors pointing toward a corner select that corner.
// ydistribute(55) {
// xdistribute(35) {
// _show_corners(corners=FRONT+LEFT+TOP);
// _show_corners(corners=FRONT+RIGHT+TOP);
// _show_corners(corners=FRONT+LEFT+BOT);
// _show_corners(corners=FRONT+RIGHT+BOT);
// }
// xdistribute(35) {
// _show_corners(corners=TOP+LEFT+BACK);
// _show_corners(corners=TOP+RIGHT+BACK);
// _show_corners(corners=BOT+LEFT+BACK);
// _show_corners(corners=BOT+RIGHT+BACK);
// }
// }
// Figure(3D,Big,NoScales,VPD=340): Vectors pointing toward an edge select the corners and the ends of the edge.
// ydistribute(55) {
// xdistribute(35) {
// _show_corners(corners=BOT+RIGHT);
// _show_corners(corners=BOT+BACK);
// _show_corners(corners=BOT+LEFT);
// _show_corners(corners=BOT+FRONT);
// }
// xdistribute(35) {
// _show_corners(corners=FWD+RIGHT);
// _show_corners(corners=BACK+RIGHT);
// _show_corners(corners=BACK+LEFT);
// _show_corners(corners=FWD+LEFT);
// }
// xdistribute(35) {
// _show_corners(corners=TOP+RIGHT);
// _show_corners(corners=TOP+BACK);
// _show_corners(corners=TOP+LEFT);
// _show_corners(corners=TOP+FRONT);
// }
// }
// Figure(3D,Med,NoScales,VPD=225): Vectors pointing toward a face select the corners of the face.
// ydistribute(55) {
// xdistribute(35) {
// _show_corners(corners=LEFT);
// _show_corners(corners=FRONT);
// _show_corners(corners=RIGHT);
// }
// xdistribute(35) {
// _show_corners(corners=TOP);
// _show_corners(corners=BACK);
// _show_corners(corners=BOTTOM);
// }
// }
// Figure(3D,Med,NoScales,VPD=200): Corners by name
// xdistribute(35) {
// _show_corners(corners="ALL");
// _show_corners(corners="NONE");
// }
// Figure(3D,Big,NoScales,VPD=300): Next are some examples showing how you can combine corner descriptors to obtain different corner sets. You can specify corner sets numerically or by adding together named directions. The third example shows a list of two corner specifications, giving all the corners on the front face or the right face.
// xdistribute(52){
// _show_corners(_corners([1,-1,-1]),toplabel=["corners=[1,-1,-1]"]);
// _show_corners(_corners(BOT+RIGHT+FRONT),toplabel=["corners=BOT+RIGHT+FRONT"]);
// _show_corners(_corners([FRONT,RIGHT]), toplabel=["corners=[FRONT,RIGHT]"]);
// }
// Figure(3D,Big,NoScales,VPD=300): Corners for one edge, two edges, and all the edges except the two on one edge. Note that since the default is all edges, you only need to give the except argument in this case:
// xdistribute(52){
// _show_corners(_corners(FRONT+TOP), toplabel=["corners=FRONT+TOP"]);
// _show_corners(_corners([FRONT+TOP,BOT+BACK]), toplabel=["corners=[FRONT+TOP,"," BOT+BACK]"]);
// _show_corners(_corners("ALL",FRONT+TOP), toplabel=["(corners=\"ALL\")","except=FRONT+TOP"]);
// }
// Figure(3D,Med,NoScales,VPD=240): The first example shows a single corner removed from the top corners using a numerical vector. The second one shows removing a set of two corner descriptors from the implied set of all corners.
// xdistribute(58){
// _show_corners(_corners(TOP,[1,1,1]), toplabel=["corners=TOP","except=[1,1,1]"]);
// _show_corners(_corners("ALL",[FRONT+RIGHT+TOP,FRONT+LEFT+BOT]),
// toplabel=["except=[FRONT+RIGHT+TOP,"," FRONT+LEFT+BOT]"]);
// }
module _edges_text3d(txt,size=3) {
if (is_list(txt)) {
for (i=idx(txt)) {
down((i-len(txt)/2+0.5)*size*1.5) {
_edges_text3d(txt[i], size=size);
}
}
} else {
xrot(90) color("#000")
linear_extrude(height=0.1) {
text(text=txt, size=size, halign="center", valign="center");
}
}
}
function _edges_vec_txt(x) = is_string(x)? str("\"", x, "\"") :
assert(is_string(x) || is_vector(x,3), str(x))
let(
lst = concat(
x.z>0? ["TOP"] : x.z<0? ["BOT"] : [],
x.y>0? ["BACK"] : x.y<0? ["FWD"] : [],
x.x>0? ["RIGHT"] : x.x<0? ["LEFT"] : []
),
out = [
for (i = idx(lst))
i>0? str("+",lst[i]) : lst[i]
]
) out;
function _edges_text(edges) =
is_string(edges) ? [str("\"",edges,"\"")] :
edges==EDGES_NONE ? ["EDGES_NONE"] :
edges==EDGES_ALL ? ["EDGES_ALL"] :
_is_edge_array(edges) ? [""] :
is_vector(edges,3) ? _edges_vec_txt(edges) :
is_list(edges) ? let(
lst = [for (x=edges) each _edges_text(x)],
out = [
for (i=idx(lst))
str(
(i==0? "[" : ""),
lst[i],
(i<len(lst)-1? "," : ""),
(i==len(lst)-1? "]" : "")
)
]
) out :
[""];
/// Internal Constant: EDGES_NONE
/// Topics: Edges
/// See Also: EDGES_ALL, edges()
/// Description:
/// The set of no edges.
/// Figure(3D):
/// _show_edges(edges="NONE");
EDGES_NONE = [[0,0,0,0], [0,0,0,0], [0,0,0,0]];
/// Internal Constant: EDGES_ALL
/// Topics: Edges
/// See Also: EDGES_NONE, edges()
/// Description:
/// The set of all edges.
/// Figure(3D):
/// _show_edges(edges="ALL");
EDGES_ALL = [[1,1,1,1], [1,1,1,1], [1,1,1,1]];
/// Internal Constant: EDGES_OFFSETS
/// Topics: Edges
/// See Also: EDGES_NONE, EDGES_ALL, edges()
/// Description:
/// The vectors pointing to the center of each edge of a unit sized cube.
/// Each item in an edge array will have a corresponding vector in this array.
EDGE_OFFSETS = [
[
[ 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]
]
];
/// Internal Function: _is_edge_array()
/// Topics: Edges, Type Checking
/// Usage:
/// bool = _is_edge_array(x);
/// Description:
/// Returns true if the given value has the form of an edge array.
/// Arguments:
/// x = The item to check the type of.
/// See Also: edges(), EDGES_NONE, EDGES_ALL
function _is_edge_array(x) = is_list(x) && is_vector(x[0]) && len(x)==3 && len(x[0])==4;
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(v_abs(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
]
];
/// Internal Function: _normalize_edges()
/// Topics: Edges
/// Usage:
/// edges = _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`.
/// See Also: edges(), EDGES_NONE, EDGES_ALL
function _normalize_edges(v) = [for (ax=v) [for (edge=ax) edge>0? 1 : 0]];
/// Internal Function: _edges()
/// Topics: Edges
/// Usage:
/// edgs = _edges(v);
/// edgs = _edges(v, except);
///
/// Description:
/// Takes a list of edge set descriptors, and returns a normalized edges array
/// that represents all those given edges.
/// Arguments:
/// v = The edge set to include.
/// except = The edge set to specifically exclude, even if they are in `v`.
///
/// See Also: EDGES_NONE, EDGES_ALL
///
function _edges(v, except=[]) =
v==[] ? EDGES_NONE :
(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)])
);
/// Internal Module: _show_edges()
/// Topics: Edges, Debugging
/// Usage:
/// _show_edges(edges, [size=], [text=], [txtsize=]);
/// Description:
/// Draws a semi-transparent cube with the given edges highlighted in red.
/// Arguments:
/// edges = The edges to highlight.
/// size = The scalar size of the cube.
/// text = The text to show on the front of the cube.
/// txtsize = The size of the text.
/// See Also: _edges(), EDGES_NONE, EDGES_ALL
/// Example:
/// _show_edges(size=30, edges=["X","Y"]);
module _show_edges(edges="ALL", size=20, text, txtsize=3,toplabel) {
edge_set = _edges(edges);
text = !is_undef(text) ? text : _edges_text(edges);
color("red") {
for (axis=[0:2], i=[0:3]) {
if (edge_set[axis][i] > 0) {
translate(EDGE_OFFSETS[axis][i]*size/2) {
if (axis==0) xcyl(h=size, d=2);
if (axis==1) ycyl(h=size, d=2);
if (axis==2) zcyl(h=size, d=2);
}
}
}
}
fwd(size/2) _edges_text3d(text, size=txtsize);
color("yellow",0.7) cuboid(size=size);
vpr = [55,0,25];
color("black")
if (is_def(toplabel))
for(h=idx(toplabel)) up(21+6*h)rot(vpr)atext(select(toplabel,-h-1),size=3.3,h=0.1,orient=UP,anchor=FRONT);
}
/// Internal Constant: CORNERS_NONE
/// Topics: Corners
/// Description:
/// The set of no corners.
/// Figure(3D):
/// _show_corners(corners="NONE");
/// See Also: CORNERS_ALL, corners()
CORNERS_NONE = [0,0,0,0,0,0,0,0]; // No corners.
/// Internal Constant: CORNERS_ALL
/// Topics: Corners
/// Description:
/// The set of all corners.
/// Figure(3D):
/// _show_corners(corners="ALL");
/// See Also: CORNERS_NONE, _corners()
CORNERS_ALL = [1,1,1,1,1,1,1,1];
/// Internal Constant: CORNER_OFFSETS
/// Topics: Corners
/// Description:
/// The vectors pointing to each corner of a unit sized cube.
/// Each item in a corner array will have a corresponding vector in this array.
/// See Also: CORNERS_NONE, CORNERS_ALL, _corners()
CORNER_OFFSETS = [
[-1,-1,-1], [ 1,-1,-1], [-1, 1,-1], [ 1, 1,-1],
[-1,-1, 1], [ 1,-1, 1], [-1, 1, 1], [ 1, 1, 1]
];
/// Internal Function: _is_corner_array()
/// Topics: Corners, Type Checking
/// Usage:
/// bool = _is_corner_array(x)
/// Description:
/// Returns true if the given value has the form of a corner array.
/// See Also: CORNERS_NONE, CORNERS_ALL, _corners()
function _is_corner_array(x) = is_vector(x) && len(x)==8 && all([for (xx=x) xx==1||xx==0]);
/// Internal Function: _normalize_corners()
/// Topics: Corners
/// Usage:
/// corns = _normalize_corners(v);
/// Description:
/// Normalizes all values in a corner array to be `1`, if it was originally greater than `0`,
/// or `0`, if it was originally less than or equal to `0`.
/// See Also: CORNERS_NONE, CORNERS_ALL, _corners()
function _normalize_corners(v) = [for (x=v) x>0? 1 : 0];
function _corner_set(v) =
_is_corner_array(v)? v : [
for (i=[0:7]) let(
v2 = CORNER_OFFSETS[i]
) (
is_string(v)? (
v=="ALL"? true : // Return all corners.
v=="NONE"? false : // Return no corners.
let(valid_values = ["ALL", "NONE"])
assert(
in_list(v, valid_values),
str(v, " must be a vector, corner array, or one of ", valid_values)
) v
) :
all([for (i=[0:2]) !v[i] || (v[i]==v2[i])])
)? 1 : 0
];
/// Function: _corners()
/// Topics: Corners
/// Usage:
/// corns = _corners(v);
/// corns = _corners(v, except);
/// Description:
/// Takes a list of corner set descriptors, and returns a normalized corners array
/// that represents all those given corners. If the `except` argument is given
/// a list of corner set descriptors, then all those corners will be removed
/// from the returned corners array. If either argument only has a single corner
/// set descriptor, you do not have to pass it in a list.
function _corners(v, except=[]) =
v==[] ? CORNERS_NONE :
(is_string(v) || is_vector(v) || _is_corner_array(v))? _corners([v], except=except) :
(is_string(except) || is_vector(except) || _is_corner_array(except))? _corners(v, except=[except]) :
except==[]? _normalize_corners(sum([for (x=v) _corner_set(x)])) :
let(
a = _normalize_corners(sum([for (x=v) _corner_set(x)])),
b = _normalize_corners(sum([for (x=except) _corner_set(x)]))
) _normalize_corners(a - b);
/// Internal Function: _corner_edges()
/// Topics: Corners
/// Description:
/// Returns [XCOUNT,YCOUNT,ZCOUNT] where each is the count of edges aligned with that
/// axis that are in the edge set and touch the given corner.
/// Arguments:
/// edges = Standard edges array.
/// v = Vector pointing to the corner to count edge intersections at.
/// See Also: CORNERS_NONE, CORNERS_ALL, _corners()
function _corner_edges(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]];
/// InternalFunction: _corner_edge_count()
/// Topics: Corners
/// 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.
/// See Also: CORNERS_NONE, CORNERS_ALL, _corners()
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];
function _corners_text(corners) =
is_string(corners) ? [str("\"",corners,"\"")] :
corners==CORNERS_NONE ? ["CORNERS_NONE"] :
corners==CORNERS_ALL ? ["CORNERS_ALL"] :
_is_corner_array(corners) ? [""] :
is_vector(corners,3) ? _edges_vec_txt(corners) :
is_list(corners) ? let(
lst = [for (x=corners) each _corners_text(x)],
out = [
for (i=idx(lst))
str(
(i==0? "[" : ""),
lst[i],
(i<len(lst)-1? "," : ""),
(i==len(lst)-1? "]" : "")
)
]
) out :
[""];
/// Internal Module: _show_corners()
/// Topics: Corners, Debugging
/// Usage:
/// _show_corners(corners, [size=], [text=], [txtsize=]);
/// Description:
/// Draws a semi-transparent cube with the given corners highlighted in red.
/// Arguments:
/// corners = The corners to highlight.
/// size = The scalar size of the cube.
/// text = If given, overrides the text to be shown on the front of the cube.
/// txtsize = The size of the text.
/// See Also: CORNERS_NONE, CORNERS_ALL, corners()
/// Example:
/// _show_corners(corners=FWD+RIGHT, size=30);
module _show_corners(corners="ALL", size=20, text, txtsize=3,toplabel) {
corner_set = _corners(corners);
text = !is_undef(text) ? text : _corners_text(corners);
for (i=[0:7]) if (corner_set[i]>0)
translate(CORNER_OFFSETS[i]*size/2)
color("red") sphere(d=2, $fn=16);
fwd(size/2) _edges_text3d(text, size=txtsize);
color("yellow",0.7) cuboid(size=size);
vpr = [55,0,25];
color("black")
if (is_def(toplabel))
for(h=idx(toplabel)) up(21+6*h)rot(vpr)atext(select(toplabel,-h-1),size=3.3,h=.1,orient=UP,anchor=FRONT);
}
module _show_cube_faces(faces, size=20, toplabel,botlabel) {
color("red")
for(f=faces){
move(f*size/2) rot(from=UP,to=f)
cuboid([size,size,.1]);
}
vpr = [55,0,25];
color("black"){
if (is_def(toplabel))
for(h=idx(toplabel)) up(21+6*h)rot(vpr)atext(select(toplabel,-h-1),size=3.3,h=.1,orient=UP,anchor=FRONT);
if (is_def(botlabel))
for(h=idx(botlabel)) down(26+6*h)rot(vpr)atext(botlabel[h],size=3.3,h=.1,orient=UP,anchor=FRONT);
}
color("yellow",0.7) cuboid(size=size);
}
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap

View file

@ -449,8 +449,8 @@ module gear_tooth_profile(
// backlash = Gap between two meshing teeth, in the direction along the circumference of the pitch circle
// interior = If true, create a mask for difference()ing from something else.
// mod = The metric module/modulus of the gear.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Example(2D): Typical Gear Shape
// spur_gear2d(pitch=5, teeth=20);
// Example(2D): Metric Gear
@ -545,8 +545,8 @@ module spur_gear2d(
// pressure_angle = Controls how straight or bulged the tooth sides are. In degrees.
// backlash = Gap between two meshing teeth, in the direction along the circumference of the pitch circle
// mod = The metric module/modulus of the gear.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Extra Anchors:
// "adendum" = At the tips of the teeth, at the center of rack.
// "adendum-left" = At the tips of the teeth, at the left end of the rack.
@ -691,9 +691,9 @@ module rack2d(
// scale = Scale of top of gear compared to bottom. Useful for making crown gears.
// interior = If true, create a mask for difference()ing from something else.
// mod = The metric module/modulus of the gear.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example: Spur Gear
// spur_gear(pitch=5, teeth=20, thickness=8, shaft_diam=5);
// Example: Metric Gear
@ -858,9 +858,9 @@ module spur_gear(
// slices = Number of vertical layers to divide gear into. Useful for refining gears with `spiral`. Default: 1
// interior = If true, create a mask for difference()ing from something else.
// mod = The metric module/modulus of the gear.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// "apex" = At the pitch cone apex for the bevel gear.
// "pitchbase" = At the natural height of the pitch radius of the beveled gear.
@ -1091,9 +1091,9 @@ module bevel_gear(
// clearance = Clearance gap at the bottom of the inter-tooth valleys.
// helical = The angle of the rack teeth away from perpendicular to the rack length. Used to match helical spur gear pinions. Default: 0
// mod = The metric module/modulus of the gear.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// "adendum" = At the tips of the teeth, at the center of rack.
// "adendum-left" = At the tips of the teeth, at the left end of the rack.
@ -1232,9 +1232,9 @@ function rack(
// backlash = Gap between two meshing teeth, in the direction along the circumference of the pitch circle. Default: 0
// clearance = Clearance gap at the bottom of the inter-tooth valleys.
// mod = The metric module/modulus of the gear.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// worm(pitch=8, d=30, l=50, $fn=72);
// Example: Multiple Starts.
@ -1352,9 +1352,9 @@ module worm(
// clearance = Clearance gap at the bottom of the inter-tooth valleys.
// slices = The number of vertical slices to refine the curve of the worm throat. Default: 10
// mod = The metric module/modulus of the gear.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example: Right-Handed
// worm_gear(pitch=5, teeth=36, worm_diam=30, worm_starts=1);
// Example: Left-Handed

View file

@ -23,9 +23,9 @@
// layerheight = The expected printing layer height in mm.
// foldangle = The interior angle in degrees of the joint to be created with the hinge. Default: 90
// hingegap = Size in mm of the gap at the bottom of the hinge, to make room for folding.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// folding_hinge_mask(l=100, thick=3, foldangle=60);
module folding_hinge_mask(l, thick, layerheight=0.2, foldangle=90, hingegap=undef, anchor=CENTER, spin=0, orient=UP)
@ -52,9 +52,9 @@ module folding_hinge_mask(l, thick, layerheight=0.2, foldangle=90, hingegap=unde
// layerheight = The expected printing layer height in mm.
// foldangle = The interior angle in degrees of the joint to be created with the hinge. Default: 90
// hingegap = Size in mm of the gap at the bottom of the hinge, to make room for folding.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// snap_lock(thick=3, foldangle=60);
module snap_lock(thick, snaplen=5, snapdiam=5, layerheight=0.2, foldangle=90, hingegap=undef, anchor=CENTER, spin=0, orient=UP)
@ -86,9 +86,9 @@ module snap_lock(thick, snaplen=5, snapdiam=5, layerheight=0.2, foldangle=90, hi
// layerheight = The expected printing layer height in mm.
// foldangle = The interior angle in degrees of the joint to be created with the hinge. Default: 90
// hingegap = Size in mm of the gap at the bottom of the hinge, to make room for folding.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// snap_socket(thick=3, foldangle=60);
module snap_socket(thick, snaplen=5, snapdiam=5, layerheight=0.2, foldangle=90, hingegap=undef, anchor=CENTER, spin=0, orient=UP)

View file

@ -26,9 +26,9 @@ include <rounding.scad>
// a = Overhang angle of the joiner.
// clearance = Extra width to clear.
// overlap = Extra depth to clear.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// half_joiner_clear();
module half_joiner_clear(h=20, w=10, a=30, clearance=0, overlap=0.01, anchor=CENTER, spin=0, orient=UP)
@ -72,9 +72,9 @@ module half_joiner_clear(h=20, w=10, a=30, clearance=0, overlap=0.01, anchor=CEN
// a = Overhang angle of the half_joiner.
// screwsize = Diameter of screwhole.
// guides = If true, create sliding alignment guides.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = Printer specific slop value to make parts fit more closely.
// Examples(FlatSpin,VPD=75):
// half_joiner(screwsize=3);
@ -151,9 +151,9 @@ module half_joiner(h=20, w=10, l=10, a=30, screwsize=undef, guides=true, anchor=
// a = Overhang angle of the half_joiner.
// screwsize = Diameter of screwhole.
// guides = If true, create sliding alignment guides.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Examples(FlatSpin,VPD=75):
// half_joiner2(screwsize=3);
// half_joiner2(h=20,w=10,l=10);
@ -200,9 +200,9 @@ module half_joiner2(h=20, w=10, l=10, a=30, screwsize=undef, guides=true, anchor
// a = Overhang angle of the joiner.
// clearance = Extra width to clear.
// overlap = Extra depth to clear.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// joiner_clear();
module joiner_clear(h=40, w=10, a=30, clearance=0, overlap=0.01, anchor=CENTER, spin=0, orient=UP)
@ -235,9 +235,9 @@ module joiner_clear(h=40, w=10, a=30, clearance=0, overlap=0.01, anchor=CENTER,
// a = Overhang angle of the joiner.
// screwsize = Diameter of screwhole.
// guides = If true, create sliding alignment guides.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = Printer specific slop value to make parts fit more closely.
// Examples(FlatSpin,VPD=125):
// joiner(screwsize=3);
@ -271,9 +271,9 @@ module joiner(h=40, w=10, l=10, a=30, screwsize=undef, guides=true, anchor=CENTE
// n = Number of joiners (2 by default) to clear for.
// clearance = Extra width to clear.
// overlap = Extra depth to clear.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Examples:
// joiner_pair_clear(spacing=50, n=2);
// joiner_pair_clear(spacing=50, n=3);
@ -309,9 +309,9 @@ module joiner_pair_clear(spacing=100, h=40, w=10, a=30, n=2, clearance=0, overla
// alternate = If true (default), each joiner alternates it's orientation. If alternate is "alt", do opposite alternating orientations.
// screwsize = Diameter of screwhole.
// guides = If true, create sliding alignment guides.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = Printer specific slop value to make parts fit more closely.
// Example(FlatSpin,VPD=200):
// joiner_pair(spacing=50, l=10);
@ -354,9 +354,9 @@ module joiner_pair(spacing=100, h=40, w=10, l=10, a=30, n=2, alternate=true, scr
// n = Number of joiners in a row. Default: 2
// clearance = Extra width to clear.
// overlap = Extra depth to clear.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Examples:
// joiner_quad_clear(spacing1=50, spacing2=50, n=2);
// joiner_quad_clear(spacing1=50, spacing2=50, n=3);
@ -392,9 +392,9 @@ module joiner_quad_clear(xspacing=undef, yspacing=undef, spacing1=undef, spacing
// screwsize = Diameter of screwhole.
// guides = If true, create sliding alignment guides.
// $slop = Printer specific slop value to make parts fit more closely.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example(FlatSpin,VPD=250):
// joiner_quad(spacing1=50, spacing2=50, l=10);
// Examples:

View file

@ -40,9 +40,9 @@
// rounding = The radius of the rounding on the ends of the cylinder. Default: none.
// rounding1 = The radius of the rounding on the bottom end of the cylinder.
// rounding2 = The radius of the rounding on the top end of the cylinder.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Examples(Med):
// knurled_cylinder(l=30, r=20, count=30, profile=120, helix=45);
// knurled_cylinder(l=30, r=20, count=30, profile=120, helix=30);
@ -143,9 +143,9 @@ module knurled_cylinder(
// count = The number of grooves to have around the surface of the cylinder. Default: 30
// profile = The angle of the bottom of the groove, in degrees. Default 120
// helix = The helical angle of the grooves, in degrees. Default: 30
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Examples:
// knurled_cylinder_mask(l=30, r=20, overage=5, profile=120, helix=30);
// knurled_cylinder_mask(l=30, r=20, overage=10, profile=120, helix=30);

View file

@ -91,7 +91,7 @@ module echo_matrix(M,description,sig=4,eps=1e-9)
// Function: column()
// Usage:
// list = column(M, i);
// Topics: Array Handling, List Handling
// Topics: Matrices, List Handling
// See Also: select(), slice()
// Description:
// Extracts entry i from each list in M, or equivalently column i from the matrix M, and returns it as a vector.
@ -118,7 +118,7 @@ function column(M, i) =
// Function: submatrix()
// Usage:
// mat = submatrix(M, idx1, idx2);
// Topics: Matrices, Array Handling
// Topics: Matrices
// See Also: column(), block_matrix(), submatrix_set()
// Description:
// The input must be a list of lists (a matrix or 2d array). Returns a submatrix by selecting the rows listed in idx1 and columns listed in idx2.
@ -183,7 +183,7 @@ function ident(n) = [
// Function: diagonal_matrix()
// Usage:
// mat = diagonal_matrix(diag, [offdiag]);
// Topics: Matrices, Array Handling
// Topics: Matrices
// See Also: column(), submatrix()
// Description:
// Creates a square matrix with the items in the list `diag` on
@ -200,7 +200,7 @@ function diagonal_matrix(diag, offdiag=0) =
// Function: transpose()
// Usage:
// M = transpose(M, [reverse]);
// Topics: Matrices, Array Handling
// Topics: Matrices
// See Also: submatrix(), block_matrix(), hstack(), flatten()
// Description:
// Returns the transpose of the given input matrix. The input can be a matrix with arbitrary entries or
@ -289,7 +289,7 @@ function outer_product(u,v) =
// Function: submatrix_set()
// Usage:
// mat = submatrix_set(M, A, [m], [n]);
// Topics: Matrices, Array Handling
// Topics: Matrices
// See Also: column(), submatrix()
// Description:
// Sets a submatrix of M equal to the matrix A. By default the top left corner of M is set to A, but
@ -319,7 +319,7 @@ function submatrix_set(M,A,m=0,n=0) =
// A = hstack(M1, M2)
// A = hstack(M1, M2, M3)
// A = hstack([M1, M2, M3, ...])
// Topics: Matrices, Array Handling
// Topics: Matrices
// See Also: column(), submatrix(), block_matrix()
// Description:
// Constructs a matrix by horizontally "stacking" together compatible matrices or vectors. Vectors are treated as columsn in the stack.
@ -371,7 +371,7 @@ function hstack(M1, M2, M3) =
// Function: block_matrix()
// Usage:
// bmat = block_matrix([[M11, M12,...],[M21, M22,...], ... ]);
// Topics: Matrices, Array Handling
// Topics: Matrices
// See Also: column(), submatrix()
// Description:
// Create a block matrix by supplying a matrix of matrices, which will

View file

@ -76,9 +76,9 @@ function get_lmXuu_bearing_length(size) = lookup(size, [
// wall = Wall thickness of clamp housing. (Default: 3)
// gap = Gap in clamp. (Default: 5)
// screwsize = Size of screw to use to tighten clamp. (Default: 3)
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// linear_bearing_housing(d=19, l=29, wall=2, tab=6, screwsize=2.5);
module linear_bearing_housing(d=15, l=24, tab=7, gap=5, wall=3, tabwall=5, screwsize=3, anchor=BOTTOM, spin=0, orient=UP)
@ -135,9 +135,9 @@ module linear_bearing_housing(d=15, l=24, tab=7, gap=5, wall=3, tabwall=5, screw
// wall = Wall thickness of clamp housing. Default: 3
// gap = Gap in clamp. Default: 5
// screwsize = Size of screw to use to tighten clamp. Default: 3
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// lmXuu_housing(size=10, wall=2, tab=6, screwsize=2.5);
module lmXuu_housing(size=8, tab=7, gap=5, wall=3, tabwall=5, screwsize=3, anchor=BOTTOM, spin=0, orient=UP)

View file

@ -9,15 +9,12 @@
//////////////////////////////////////////////////////////////////////
// Terminology:
// **List** = An ordered collection of zero or more items. ie: `["a", "b", "c"]`
// **List** = An ordered collection of zero or more arbitrary items. ie: `["a", "b", "c"]`, or `[3, "a", [4,5]]`
// **Vector** = A list of numbers. ie: `[4, 5, 6]`
// **Array** = A nested list of lists, or list of lists of lists, or deeper. ie: `[[2,3], [4,5], [6,7]]`
// **Set** = A list of unique items.
// Section: List Query Operations
// Function: is_homogeneous()
// Alias: is_homogenous()
// Usage:
@ -56,34 +53,34 @@ function _same_type(a,b, depth) =
// Function: min_length()
// Usage:
// llen = min_length(array);
// llen = min_length(list);
// Topics: List Handling
// See Also: max_length()
// Description:
// Returns the length of the shortest sublist in a list of lists.
// Arguments:
// array = A list of lists.
// list = A list of lists.
// Example:
// slen = min_length([[3,4,5],[6,7,8,9]]); // Returns: 3
function min_length(array) =
assert(is_list(array), "Invalid input." )
min([for (v = array) len(v)]);
function min_length(list) =
assert(is_list(list), "Invalid input." )
min([for (v = list) len(v)]);
// Function: max_length()
// Usage:
// llen = max_length(array);
// llen = max_length(list);
// Topics: List Handling
// See Also: min_length()
// Description:
// Returns the length of the longest sublist in a list of lists.
// Arguments:
// array = A list of lists.
// list = A list of lists.
// Example:
// llen = max_length([[3,4,5],[6,7,8,9]]); // Returns: 4
function max_length(array) =
assert(is_list(array), "Invalid input." )
max([for (v = array) len(v)]);
function max_length(list) =
assert(is_list(list), "Invalid input." )
max([for (v = list) len(v)]);
@ -111,7 +108,7 @@ function _list_shape_recurse(v) =
// Function: list_shape()
// Usage:
// dims = list_shape(v, [depth]);
// Topics: Matrices, Array Handling
// Topics: Matrices, List Handling
// Description:
// Returns the size of a multi-dimensional array, a list of the lengths at each depth.
// If the returned value has `dims[i] = j` then it means the ith index ranges of j items.
@ -332,21 +329,21 @@ function list_tail(list, from=1) =
// Function: bselect()
// Usage:
// array = bselect(array, index);
// sublist = bselect(list, index);
// Topics: List Handling
// See Also: list_bset()
// Description:
// Returns the items in `array` whose matching element in `index` is true.
// Returns the items in `list` whose matching element in `index` is true.
// Arguments:
// array = Initial list to extract items from.
// list = Initial list to extract items from.
// index = List of booleans.
// Example:
// a = bselect([3,4,5,6,7], [false,true,true,false,true]); // Returns: [4,5,7]
function bselect(array,index) =
assert(is_list(array)||is_string(array), "Improper array." )
assert(is_list(index) && len(index)>=len(array) , "Improper index list." )
is_string(array)? str_join(bselect( [for (x=array) x], index)) :
[for(i=[0:len(array)-1]) if (index[i]) array[i]];
function bselect(list,index) =
assert(is_list(list)||is_string(list), "Improper list." )
assert(is_list(index) && len(index)>=len(list) , "Improper index list." )
is_string(list)? str_join(bselect( [for (x=list) x], index)) :
[for(i=[0:len(list)-1]) if (index[i]) list[i]];
@ -361,7 +358,7 @@ function bselect(array,index) =
// Topics: List Handling
// See Also: count(), lerpn()
// Description:
// Generates a list or array of `n` copies of the given value `val`.
// Generates a list of `n` copies of the given value `val`.
// If the count `n` is given as a list of counts, then this creates a
// multi-dimensional array, filled with `val`.
// Arguments:
@ -483,7 +480,7 @@ function force_list(value, n=1, fill) =
// Topics: List Handling
// See Also: select(), list_rotate()
// Description:
// Reverses a list/array or string.
// Reverses a list or string.
// Arguments:
// x = The list or string to reverse.
// Example:
@ -607,21 +604,21 @@ function repeat_entries(list, N, exact=true) =
// Function: list_pad()
// Usage:
// arr = list_pad(array, minlen, [fill]);
// newlist = list_pad(list, minlen, [fill]);
// Topics: List Handling
// See Also: force_list(), scalar_vec3()
// Description:
// If the list `array` is shorter than `minlen` length, pad it to length with the value given in `fill`.
// If the list `list` is shorter than `minlen` length, pad it to length with the value given in `fill`.
// Arguments:
// array = A list.
// list = A list.
// minlen = The minimum length to pad the list to.
// fill = The value to pad the list with. Default: `undef`
// Example:
// list = [3,4,5];
// nlist = list_pad(list,5,23); // Returns: [3,4,5,23,23]
function list_pad(array, minlen, fill) =
assert(is_list(array), "Invalid input." )
concat(array,repeat(fill,minlen-len(array)));
function list_pad(list, minlen, fill) =
assert(is_list(list), "Invalid input." )
concat(list,repeat(fill,minlen-len(list)));
// Function: list_set()
@ -972,22 +969,22 @@ function permutations(l,n=2) =
// Function: list_to_matrix()
// Usage:
// groups = list_to_matrix(v, [cnt], [dflt]);
// groups = list_to_matrix(v, cnt, [dflt]);
// Description:
// Takes a flat array of values, and groups items in sets of `cnt` length.
// Takes a flat list of values, and groups items in sets of `cnt` length.
// The opposite of this is `flatten()`.
// Topics: Matrices, Array Handling
// Topics: Matrices, List Handling
// See Also: column(), submatrix(), hstack(), flatten(), full_flatten()
// Arguments:
// v = The list of items to group.
// cnt = The number of items to put in each grouping. Default:2
// dflt = The default value to fill in with if the list is not a multiple of `cnt` items long. Default: 0
// cnt = The number of items to put in each grouping.
// dflt = The default value to fill in with if the list is not a multiple of `cnt` items long. Default: undef
// Example:
// v = [1,2,3,4,5,6];
// a = list_to_matrix(v,2) returns [[1,2], [3,4], [5,6]]
// b = list_to_matrix(v,3) returns [[1,2,3], [4,5,6]]
// c = list_to_matrix(v,4,0) returns [[1,2,3,4], [5,6,0,0]]
function list_to_matrix(v, cnt=2, dflt=0) =
function list_to_matrix(v, cnt, dflt=undef) =
[for (i = [0:cnt:len(v)-1]) [for (j = [0:1:cnt-1]) default(v[i+j], dflt)]];
@ -995,7 +992,7 @@ function list_to_matrix(v, cnt=2, dflt=0) =
// Function: flatten()
// Usage:
// list = flatten(l);
// Topics: Matrices, Array Handling
// Topics: Matrices, List Handling
// See Also: column(), submatrix(), hstack(), full_flatten()
// Description:
// Takes a list of lists and flattens it by one level.
@ -1011,7 +1008,7 @@ function flatten(l) =
// Function: full_flatten()
// Usage:
// list = full_flatten(l);
// Topics: Matrices, Array Handling
// Topics: Matrices, List Handling
// See Also: column(), submatrix(), hstack(), flatten()
// Description:
// Collects in a list all elements recursively found in any level of the given list.

View file

@ -33,8 +33,8 @@
// excess = Extra amount of mask shape to creates on the X- and Y- sides of the shape. Default: 0.01
// ---
// d = Diameter of the roundover.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Example(2D): 2D Roundover Mask
// mask2d_roundover(r=10);
// Example(2D): 2D Bead Mask
@ -90,8 +90,8 @@ function mask2d_roundover(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) =
// excess = Extra amount of mask shape to creates on the X- and Y- sides of the shape. Default: 0.01
// ---
// d = Diameter of the cove.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Example(2D): 2D Cove Mask
// mask2d_cove(r=10);
// Example(2D): 2D Inset Cove Mask
@ -153,8 +153,8 @@ function mask2d_cove(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) =
// ---
// x = The width of the chamfer.
// y = The height of the chamfer.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Example(2D): 2D Chamfer Mask
// mask2d_chamfer(x=10);
// Example(2D): 2D Chamfer Mask by Width.
@ -216,8 +216,8 @@ function mask2d_chamfer(edge, angle=45, inset=0, excess=0.01, x, y, anchor=CENTE
// size = The size of the rabbet, either as a scalar or an [X,Y] list.
// excess = Extra amount of mask shape to creates on the X- and Y- sides of the shape. Default: 0.01
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Example(2D): 2D Rabbet Mask
// mask2d_rabbet(size=10);
// Example(2D): 2D Asymmetrical Rabbet Mask
@ -274,8 +274,8 @@ function mask2d_rabbet(size, excess=0.01, anchor=CENTER,spin=0) =
// ---
// x = The width of the dovetail.
// y = The height of the dovetail.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Example(2D): 2D Dovetail Mask
// mask2d_dovetail(x=10);
// Example(2D): 2D Dovetail Mask by Width.
@ -341,8 +341,8 @@ function mask2d_dovetail(edge, angle=30, inset=0, shelf=0, excess=0.01, x, y, an
// excess = Extra amount of mask shape to creates on the X- and Y- sides of the shape. Default: 0.01
// ---
// d = Diameter of the rounding.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Example(2D): 2D Teardrop Mask
// mask2d_teardrop(r=10);
// Example(2D): Using a Custom Angle
@ -408,8 +408,8 @@ module mask2d_teardrop(r, angle=45, excess=0.01, d, anchor=CENTER, spin=0) {
// pattern = A list of pattern pieces to describe the Ogee.
// excess = Extra amount of mask shape to creates on the X- and Y- sides of the shape. Default: 0.01
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
//
// Example(2D): 2D Ogee Mask
// mask2d_ogee([

View file

@ -24,9 +24,9 @@
// l = Length of mask.
// chamfer = Size of chamfer.
// excess = The extra amount to add to the length of the mask so that it differences away from other shapes cleanly. Default: `0.1`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// chamfer_edge_mask(l=50, chamfer=10);
// Example:
@ -58,9 +58,9 @@ module chamfer_edge_mask(l=1, chamfer=1, excess=0.1, anchor=CENTER, spin=0, orie
// Arguments:
// chamfer = Size of chamfer.
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// chamfer_corner_mask(chamfer=10);
// Example:
@ -96,9 +96,9 @@ module chamfer_corner_mask(chamfer=1, anchor=CENTER, spin=0, orient=UP) {
// chamfer = Size of the edge chamfered, inset from edge. (Default: 0.25)
// ang = Angle of chamfer in degrees from vertical. (Default: 45)
// from_end = If true, chamfer size is measured from end of cylinder. If false, chamfer is measured outset from the radius of the cylinder. (Default: false)
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// difference() {
// cylinder(r=50, h=100, center=true);
@ -144,9 +144,9 @@ module chamfer_cylinder_mask(r, d, chamfer=0.25, ang=45, from_end=false, anchor=
// d1 = Bottom diameter of rounding.
// d2 = Top diameter of rounding.
// excess = Extra size for the mask. Defaults: 0.1
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example(VPD=200,VPR=[55,0,120]):
// rounding_edge_mask(l=50, r1=10, r2=25);
// Example:
@ -214,9 +214,9 @@ module rounding_edge_mask(l, r, r1, r2, d, d1, d2, excess=0.1, anchor=CENTER, sp
// ---
// excess = Extra size for the mask. Defaults: 0.1
// style = The style of the sphere cutout's construction. One of "orig", "aligned", "stagger", "octa", or "icosa". Default: "octa"
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// rounding_corner_mask(r=20.0);
// Example:
@ -267,9 +267,9 @@ module rounding_corner_mask(r, d, style="octa", excess=0.1, anchor=CENTER, spin=
// d1 = Bottom diameter of rounding.
// d2 = Top diameter of rounding.
// ang = Angle that the planes meet at.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// difference() {
// pie_slice(ang=70, h=50, d=100, center=true);
@ -325,9 +325,9 @@ module rounding_angled_edge_mask(h=1.0, r, r1, r2, d, d1, d2, ang=90, anchor=CEN
// r = Radius of the rounding.
// d = Diameter of the rounding.
// ang = Angle between planes that you need to round the corner of.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example(Med):
// ang=60;
// difference() {
@ -412,9 +412,9 @@ module rounding_cylinder_mask(r, rounding=0.25, d)
// d = Diameter of hole to rounding.
// rounding = Radius of the rounding. (Default: 0.25)
// excess = The extra thickness of the mask. Default: `0.1`.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// rounding_hole_mask(r=40, rounding=20, $fa=2, $fs=2);
// Example(Med):
@ -456,9 +456,9 @@ module rounding_hole_mask(r, rounding=0.25, excess=0.1, d, anchor=CENTER, spin=0
// d = Diameter of the mask rounding.
// angle = Maximum angle from vertical. Default: 45
// excess = Excess mask size. Default: 0.1
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example(VPD=50,VPR=[55,0,120]):
// teardrop_edge_mask(l=20, r=10, angle=40);
// Example(VPD=300,VPR=[75,0,25]):
@ -492,9 +492,9 @@ module teardrop_edge_mask(l, r, angle, excess=0.1, d, anchor=CENTER, spin=0, ori
// d = Diameter of the mask rounding.
// angle = Maximum angle from vertical. Default: 45
// excess = Excess mask size. Default: 0.1
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// teardrop_corner_mask(r=20, angle=40);
// Example:

View file

@ -368,9 +368,9 @@ function get_metric_nut_thickness(size) = lookup(size, [
// screwlen = length of threaded part of screw.
// headsize = diameter of the screw head.
// headlen = length of the screw head.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// "base" = At the base of the head.
// "countersunk" = At the head height that would be just barely exposed when countersunk.
@ -429,9 +429,9 @@ module generic_screw(
// flange = Radius of flange beyond the head. Default = 0 (no flange)
// phillips = If given, the size of the phillips drive hole to add. (ie: "#1", "#2", or "#3")
// torx = If given, the size of the torx drive hole to add. (ie: 10, 20, 30, etc.)
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// "base" = At the base of the head.
// "countersunk" = At the head height that would be just barely exposed when countersunk.
@ -632,9 +632,9 @@ module metric_bolt(
// pitch = pitch of threads in the hole. No threads if not given.
// flange = radius of flange beyond the head. Default = 0 (no flange)
// details = true if model should be rendered with extra details. (Default: false)
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// center = If true, centers the nut at the origin. If false, sits on top of XY plane. Overrides `anchor` if given.
// Example: No details, No Hole. Useful for a mask.
// metric_nut(size=10, hole=false);

View file

@ -106,16 +106,17 @@ module bounding_box(excess=0, planar=false) {
// Description:
// Slices an object at a cut plane, and masks away everything that is on one side. The v parameter is either a plane specification or
// a normal vector. The s parameter is needed for the module
// version to control the size of the masking cube, which affects preview display.
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
// wrong half, but if it is too small it won't fully mask your model.
// When called as a function, you must supply a vnf, path or region in p. If planar is set to true for the module version the operation
// is performed in and UP and DOWN are treated as equivalent to BACK and FWD respectively.
// is performed in 2D and UP and DOWN are treated as equivalent to BACK and FWD respectively.
//
// Arguments:
// p = path, region or VNF to slice. (Function version)
// v = Normal of plane to slice at. Keeps everything on the side the normal points to. Default: [0,0,1] (UP)
// cp = If given as a scalar, moves the cut plane along the normal by the given amount. If given as a point, specifies a point on the cut plane. Default: [0,0,0]
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, it messes with centering your view. Ignored for function version. Default: 100
// planar = If true, perform a 2D operation. When planar, a `v` of `UP` or `DOWN` becomes equivalent of `BACK` and `FWD` respectively.
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
// planar = If true, perform a 2D operation. When planar, a `v` of `UP` or `DOWN` becomes equivalent of `BACK` and `FWD` respectively. (Module version). Default: false.
//
// Examples:
// half_of(DOWN+BACK, cp=[0,-10,0]) cylinder(h=40, r1=10, r2=0, center=false);
@ -210,13 +211,15 @@ function half_of(p, v=UP, cp) =
//
// Description:
// Slices an object at a vertical Y-Z cut plane, and masks away everything that is right of it.
// The s parameter is needed for the module
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
// wrong half, but if it is too small it won't fully mask your model.
//
// Arguments:
// p = VNF, region or path to slice (function version)
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may be incorrect. Default: 100
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
// x = The X coordinate of the cut-plane. Default: 0
// planar = If true, perform a 2D operation.
//
// planar = If true, perform a 2D operation. (Module version) Default: false.
// Examples:
// left_half() sphere(r=20);
// left_half(x=-8) sphere(r=20);
@ -250,13 +253,14 @@ function left_half(p,x=0) = half_of(p, LEFT, [x,0,0]);
//
// Description:
// Slices an object at a vertical Y-Z cut plane, and masks away everything that is left of it.
//
// The s parameter is needed for the module
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
// wrong half, but if it is too small it won't fully mask your model.
// Arguments:
// p = VNF, region or path to slice (function version)
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may be incorrect. Default: 100
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
// x = The X coordinate of the cut-plane. Default: 0
// planar = If true perform a 2D operation.
//
// planar = If true, perform a 2D operation. (Module version) Default: false.
// Examples(FlatSpin,VPD=175):
// right_half() sphere(r=20);
// right_half(x=-5) sphere(r=20);
@ -290,13 +294,14 @@ function right_half(p,x=0) = half_of(p, RIGHT, [x,0,0]);
//
// Description:
// Slices an object at a vertical X-Z cut plane, and masks away everything that is behind it.
//
// The s parameter is needed for the module
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
// wrong half, but if it is too small it won't fully mask your model.
// Arguments:
// p = VNF, region or path to slice (function version)
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may be incorrect. Default: 100
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
// y = The Y coordinate of the cut-plane. Default: 0
// planar = If true perform a 2D operation.
//
// planar = If true, perform a 2D operation. (Module version) Default: false.
// Examples(FlatSpin,VPD=175):
// front_half() sphere(r=20);
// front_half(y=5) sphere(r=20);
@ -330,13 +335,14 @@ function front_half(p,y=0) = half_of(p, FRONT, [0,y,0]);
//
// Description:
// Slices an object at a vertical X-Z cut plane, and masks away everything that is in front of it.
//
// The s parameter is needed for the module
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
// wrong half, but if it is too small it won't fully mask your model.
// Arguments:
// p = VNF, region or path to slice (function version)
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may be incorrect. Default: 100
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
// y = The Y coordinate of the cut-plane. Default: 0
// planar = If true perform a 2D operation.
//
// planar = If true, perform a 2D operation. (Module version) Default: false.
// Examples:
// back_half() sphere(r=20);
// back_half(y=8) sphere(r=20);
@ -369,12 +375,13 @@ function back_half(p,y=0) = half_of(p, BACK, [0,y,0]);
//
// Description:
// Slices an object at a horizontal X-Y cut plane, and masks away everything that is above it.
//
// The s parameter is needed for the module
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
// wrong half, but if it is too small it won't fully mask your model.
// Arguments:
// p = VNF, region or path to slice (function version)
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may be incorrect. Default: 100
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
// z = The Z coordinate of the cut-plane. Default: 0
//
// Examples:
// bottom_half() sphere(r=20);
// bottom_half(z=-10) sphere(r=20);
@ -400,12 +407,13 @@ function bottom_half(p,z=0) = half_of(p,BOTTOM,[0,0,z]);
//
// Description:
// Slices an object at a horizontal X-Y cut plane, and masks away everything that is below it.
//
// The s parameter is needed for the module
// version to control the size of the masking cube. If s is too large then the preview display will flip around and display the
// wrong half, but if it is too small it won't fully mask your model.
// Arguments:
// p = VNF, region or path to slice (function version)
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may be incorrect. Default: 100
// s = Mask size to use. Use a number larger than twice your object's largest axis. If you make this too large, OpenSCAD's preview rendering may display the wrong half. (Module version) Default: 100
// z = The Z coordinate of the cut-plane. Default: 0
//
// Examples(Spin,VPD=175):
// top_half() sphere(r=20);
// top_half(z=5) sphere(r=20);
@ -695,9 +703,9 @@ module extrude_from_to(pt1, pt2, convexity, twist, scale, slices) {
// higbee1 = Taper length at start
// higbee2 = Taper length at end
// internal = direction to taper the threads with higbee. If true threads taper outward; if false they taper inward. Default: false
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=BOTTOM`.
// Example:
// poly = [[-10,0], [-3,-5], [3,-5], [10,0], [0,-30]];

View file

@ -99,9 +99,9 @@ function nema_motor_screw_depth(size) = lookup(size, [
// h = Length of motor body. Default: 24mm
// shaft = Shaft diameter. Default: 5mm
// shaft_len = Length of shaft protruding out the top of the stepper motor. Default: 20mm
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// "shaft-top" = The top of the shaft.
// "shaft-middle" = The middle of the shaft.
@ -164,9 +164,9 @@ module nema11_stepper(h=24, shaft=5, shaft_len=20, anchor=TOP, spin=0, orient=UP
// h = Length of motor body. Default: 24mm
// shaft = Shaft diameter. Default: 5mm
// shaft_len = Length of shaft protruding out the top of the stepper motor. Default: 24mm
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// "shaft-top" = The top of the shaft.
// "shaft-middle" = The middle of the shaft.
@ -229,9 +229,9 @@ module nema14_stepper(h=24, shaft=5, shaft_len=24, anchor=TOP, spin=0, orient=UP
// h = Length of motor body. Default: 34mm
// shaft = Shaft diameter. Default: 5mm
// shaft_len = Length of shaft protruding out the top of the stepper motor. Default: 20mm
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// "shaft-top" = The top of the shaft.
// "shaft-middle" = The middle of the shaft.
@ -313,9 +313,9 @@ module nema17_stepper(h=34, shaft=5, shaft_len=20, anchor=TOP, spin=0, orient=UP
// h = Length of motor body. Default: 50mm
// shaft = Shaft diameter. Default: 6.35mm
// shaft_len = Length of shaft protruding out the top of the stepper motor. Default: 25mm
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// "shaft-top" = The top of the shaft.
// "shaft-middle" = The middle of the shaft.
@ -380,9 +380,9 @@ module nema23_stepper(h=50, shaft=6.35, shaft_len=25, anchor=TOP, spin=0, orient
// h = Length of motor body. Default: 75mm
// shaft = Shaft diameter. Default: 12.7mm
// shaft_len = Length of shaft protruding out the top of the stepper motor. Default: 32mm
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// "shaft-top" = The top of the shaft.
// "shaft-middle" = The middle of the shaft.
@ -451,9 +451,9 @@ module nema34_stepper(h=75, shaft=12.7, shaft_len=32, anchor=TOP, spin=0, orient
// size = The standard NEMA motor size to make a mount for.
// depth = The thickness of the mounting hole mask. Default: 5
// l = The length of the slots, for making an adjustable motor mount. Default: 5
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value to make parts fit just right.
// Extra Anchors:
// "screw1" = The center top of the screw hole/slot in the X+Y+ quadrant.
@ -516,9 +516,9 @@ module nema_mount_holes(size=17, depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
// Arguments:
// depth = The thickness of the mounting hole mask. Default: 5
// l = The length of the slots, for making an adjustable motor mount. Default: 5
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value to make parts fit just right.
// Extra Anchors:
// "screw1" = The center top of the screw hole/slot in the X+Y+ quadrant.
@ -541,9 +541,9 @@ module nema11_mount_holes(depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
// Arguments:
// depth = The thickness of the mounting hole mask. Default: 5
// l = The length of the slots, for making an adjustable motor mount. Default: 5
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value to make parts fit just right.
// Extra Anchors:
// "screw1" = The center top of the screw hole/slot in the X+Y+ quadrant.
@ -566,9 +566,9 @@ module nema14_mount_holes(depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
// Arguments:
// depth = The thickness of the mounting hole mask. Default: 5
// l = The length of the slots, for making an adjustable motor mount. Default: 5
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value to make parts fit just right.
// Extra Anchors:
// "screw1" = The center top of the screw hole/slot in the X+Y+ quadrant.
@ -591,9 +591,9 @@ module nema17_mount_holes(depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
// Arguments:
// depth = The thickness of the mounting hole mask. Default: 5
// l = The length of the slots, for making an adjustable motor mount. Default: 5
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value to make parts fit just right.
// Extra Anchors:
// "screw1" = The center top of the screw hole/slot in the X+Y+ quadrant.
@ -616,9 +616,9 @@ module nema23_mount_holes(depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
// Arguments:
// depth = The thickness of the mounting hole mask. Default: 5
// l = The length of the slots, for making an adjustable motor mount. Default: 5
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value to make parts fit just right.
// Extra Anchors:
// "screw1" = The center top of the screw hole/slot in the X+Y+ quadrant.

View file

@ -66,8 +66,8 @@ function _partition_cutpath(l, h, cutsize, cutpath, gap) =
// cutpath = The cutpath to use. Standard named paths are "flat", "sawtooth", "sinewave", "comb", "finger", "dovetail", "hammerhead", and "jigsaw". Alternatively, you can give a cutpath as a 2D path, where X is between 0 and 1, and Y is between -0.5 and 0.5.
// gap = Empty gaps between cutpath iterations. Default: 0
// inverse = If true, create a cutpath that is meant to mate to a non-inverted cutpath.
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The amount to shrink the mask by, to correct for printer-specific fitting.
// Examples:
// partition_mask(w=50, gap=0, cutpath="jigsaw");
@ -117,8 +117,8 @@ module partition_mask(l=100, w=100, h=100, cutsize=10, cutpath="jigsaw", gap=0,
// cutsize = The width of the cut pattern to be used.
// cutpath = The cutpath to use. Standard named paths are "flat", "sawtooth", "sinewave", "comb", "finger", "dovetail", "hammerhead", and "jigsaw". Alternatively, you can give a cutpath as a 2D path, where X is between 0 and 1, and Y is between -0.5 and 0.5. Default: "jigsaw"
// gap = Empty gaps between cutpath iterations. Default: 0
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The width of the cut mask, to correct for printer-specific fitting. Min: 0.05.
// Examples:
// partition_cut_mask(gap=0, cutpath="dovetail");
@ -157,7 +157,7 @@ module partition_cut_mask(l=100, h=100, cutsize=10, cutpath="jigsaw", gap=0, anc
// cutsize = The width of the cut pattern to be used.
// cutpath = The cutpath to use. Standard named paths are "flat", "sawtooth", "sinewave", "comb", "finger", "dovetail", "hammerhead", and "jigsaw". Alternatively, you can give a cutpath as a 2D path, where X is between 0 and 1, and Y is between -0.5 and 0.5.
// gap = Empty gaps between cutpath iterations. Default: 0
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// Examples(Med):
// partition(spread=12, cutpath="dovetail") cylinder(h=50, d=80, center=false);
// partition(spread=12, gap=30, cutpath="dovetail") cylinder(h=50, d=80, center=false);

View file

@ -288,8 +288,8 @@ function force_region(poly) = is_path(poly) ? [poly] : poly;
// displayed result is the exclusive-or of the polygons listed in the input.
// Arguments:
// r = region to create as geometry
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `"origin"`
// spin = Rotate this many degrees after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `"origin"`
// spin = Rotate this many degrees after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// cp = Centerpoint for determining intersection anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 2D point. Default: "centroid"
// atype = Set to "hull" or "intersect" to select anchor type. Default: "hull"
// Example(2D): Displaying a region
@ -618,11 +618,11 @@ function region_parts(region) =
// scale = The amount to scale the shape, from bottom to top. Default: 1
// style = The style to use when triangulating the surface of the object. Valid values are `"default"`, `"alt"`, or `"quincunx"`.
// convexity = Max number of surfaces any single ray could pass through. Module use only.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `"origin"`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `"origin"`
// atype = Set to "hull" or "intersect" to select anchor type. Default: "hull"
// cp = Centerpoint for determining intersection anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid"
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example: Extruding a Compound Region.
// rgn1 = [for (d=[10:10:60]) circle(d=d,$fn=8)];
// rgn2 = [square(30,center=false)];

View file

@ -18,9 +18,9 @@
// Arguments:
// size = The size of the bit as a number or string. "#0", "#1", "#2", "#3", or "#4"
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// xdistribute(10) {
// phillips_mask(size="#1");
@ -306,9 +306,9 @@ module torx_mask2d(size) {
// l = Length of bit.
// center = If true, centers bit vertically.
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Examples:
// torx_mask(size=30, l=10, $fa=1, $fs=1);
module torx_mask(size, l=5, center, anchor, spin=0, orient=UP) {

View file

@ -178,11 +178,10 @@ function screw_info(name, head, thread="coarse", drive, drive_size=undef, oversi
function _screw_info_english(diam, threadcount, head, thread, drive) =
let(
inch = 25.4,
diameter = is_string(diam) ? str_int(substr(diam,1))*0.013 +0.06 :
diam,
pitch =
is_def(threadcount) ? inch/threadcount :
is_def(threadcount) ? INCH/threadcount :
is_num(thread) ? thread :
let(
tind=struct_val([["coarse",0],["unc",0],
@ -220,7 +219,7 @@ function _screw_info_english(diam, threadcount, head, thread, drive) =
[2, [ 4.5, undef, undef]],
]
)
inch / struct_val(UTS_thread, diam)[tind],
INCH / struct_val(UTS_thread, diam)[tind],
head_data =
head=="none" || is_undef(head) ? let (
UTS_setscrew = [ // hex width, hex depth
@ -250,8 +249,8 @@ function _screw_info_english(diam, threadcount, head, thread, drive) =
[2, [1 , 1.000]],
],
entry = struct_val(UTS_setscrew, diam),
drive_dims = drive == "hex" ? [["drive_size", inch*entry[0]], ["drive_depth", inch*entry[1]]] :
drive == "torx" ? [["drive_size", entry[2]], ["drive_depth", inch*entry[3]]] : []
drive_dims = drive == "hex" ? [["drive_size", INCH*entry[0]], ["drive_depth", INCH*entry[1]]] :
drive == "torx" ? [["drive_size", entry[2]], ["drive_depth", INCH*entry[3]]] : []
) concat([["head","none"]], drive_dims) :
head=="hex" ? let(
UTS_hex = [
@ -280,7 +279,7 @@ function _screw_info_english(diam, threadcount, head, thread, drive) =
],
entry = struct_val(UTS_hex, diam)
)
[["head", "hex"], ["head_size", inch*entry[0]], ["head_height", inch*entry[1]]] :
[["head", "hex"], ["head_size", INCH*entry[0]], ["head_height", INCH*entry[1]]] :
head=="socket" ? let(
UTS_socket = [ // height = screw diameter
//diam, hex, torx size, philips depth, torx depth
@ -315,10 +314,10 @@ function _screw_info_english(diam, threadcount, head, thread, drive) =
hexdepth = is_def(entry[3]) ? entry[3]
: is_def(diam) ? diam/2
: undef,
drive_size = drive=="hex" ? [["drive_size",inch*entry[1]], ["drive_depth",inch*hexdepth]] :
drive=="torx" ? [["drive_size",entry[2]],["drive_depth",inch*entry[4]]] : []
drive_size = drive=="hex" ? [["drive_size",INCH*entry[1]], ["drive_depth",INCH*hexdepth]] :
drive=="torx" ? [["drive_size",entry[2]],["drive_depth",INCH*entry[4]]] : []
)
concat([["head","socket"],["head_size",inch*entry[0]], ["head_height", inch*diameter]],drive_size) :
concat([["head","socket"],["head_size",INCH*entry[0]], ["head_height", INCH*diameter]],drive_size) :
head=="pan" ? let (
UTS_pan = [ // pan head for phillips or slotted
// diam, head ht slotted, head height phillips, phillips drive, phillips diam, phillips width, phillips depth, slot width, slot depth
@ -338,9 +337,9 @@ function _screw_info_english(diam, threadcount, head, thread, drive) =
],
htind = drive=="slot" ? 1 : 2,
entry = struct_val(UTS_pan, diam),
drive_size = drive=="phillips" ? [["drive_size", entry[3]], ["drive_diameter",inch*entry[4]],["drive_width",inch*entry[5]],["drive_depth",inch*entry[6]]] :
[["drive_width", inch*entry[7]], ["drive_depth",inch*entry[8]]])
concat([["head","pan"], ["head_size", inch*entry[0]], ["head_height", inch*entry[htind]]], drive_size) :
drive_size = drive=="phillips" ? [["drive_size", entry[3]], ["drive_diameter",INCH*entry[4]],["drive_width",INCH*entry[5]],["drive_depth",INCH*entry[6]]] :
[["drive_width", INCH*entry[7]], ["drive_depth",INCH*entry[8]]])
concat([["head","pan"], ["head_size", INCH*entry[0]], ["head_height", INCH*entry[htind]]], drive_size) :
head=="button" || head=="round" ? let(
UTS_button = [ // button, hex or torx drive
// head diam, height, phillips, hex, torx, hex depth
@ -383,14 +382,14 @@ function _screw_info_english(diam, threadcount, head, thread, drive) =
drive_index = drive=="phillips" ? 2 :
drive=="hex" ? 3 :
drive=="torx" ? 4 : undef,
drive_size = drive=="phillips" && head=="round" ? [["drive_size", entry[2]], ["drive_diameter",inch*entry[5]],
["drive_width",inch*entry[6]],["drive_depth",inch*entry[7]]] :
drive=="slot" && head=="round" ? [["drive_width", inch*entry[8]], ["drive_depth",inch*entry[9]]] :
drive=="hex" && head=="button" ? [["drive_size", inch*entry[drive_index]], ["drive_depth", inch*entry[5]]]:
drive=="torx" && head=="button" ? [["drive_size", entry[drive_index]], ["drive_depth", inch*entry[6]]]:
drive_size = drive=="phillips" && head=="round" ? [["drive_size", entry[2]], ["drive_diameter",INCH*entry[5]],
["drive_width",INCH*entry[6]],["drive_depth",INCH*entry[7]]] :
drive=="slot" && head=="round" ? [["drive_width", INCH*entry[8]], ["drive_depth",INCH*entry[9]]] :
drive=="hex" && head=="button" ? [["drive_size", INCH*entry[drive_index]], ["drive_depth", INCH*entry[5]]]:
drive=="torx" && head=="button" ? [["drive_size", entry[drive_index]], ["drive_depth", INCH*entry[6]]]:
is_def(drive_index) && head=="button" ? [["drive_size", entry[drive_index]]] : []
)
concat([["head",head],["head_size",inch*entry[0]], ["head_height", inch*entry[1]]],drive_size) :
concat([["head",head],["head_size",INCH*entry[0]], ["head_height", INCH*entry[1]]],drive_size) :
head=="fillister" ? let(
UTS_fillister = [ // head diam, head height, slot width, slot depth, phillips diam, phillips depth, phillips width, phillips #
["#0", [0.096, 0.055, 0.023, 0.025, 0.067, 0.039, 0.013, 0]],
@ -408,11 +407,11 @@ function _screw_info_english(diam, threadcount, head, thread, drive) =
[3/8, [0.622, 0.355, 0.094, 0.164, 0.389, 0.233, 0.065, 4]],
],
entry = struct_val(UTS_fillister, diam),
drive_size = drive=="phillips" ? [["drive_size", entry[7]], ["drive_diameter",inch*entry[4]],
["drive_width",inch*entry[6]],["drive_depth",inch*entry[5]]] :
drive=="slot"? [["drive_width", inch*entry[2]], ["drive_depth",inch*entry[3]]] : []
drive_size = drive=="phillips" ? [["drive_size", entry[7]], ["drive_diameter",INCH*entry[4]],
["drive_width",INCH*entry[6]],["drive_depth",INCH*entry[5]]] :
drive=="slot"? [["drive_width", INCH*entry[2]], ["drive_depth",INCH*entry[3]]] : []
)
concat([["head", "fillister"], ["head_size", inch*entry[0]], ["head_height", inch*entry[1]]], drive_size) :
concat([["head", "fillister"], ["head_size", INCH*entry[0]], ["head_height", INCH*entry[1]]], drive_size) :
starts_with(head,"flat") ? let(
small = head == "flat small" || head == "flat undercut" || (head=="flat" && (drive!="hex" && drive!="torx")),
undercut = head=="flat undercut",
@ -465,26 +464,26 @@ function _screw_info_english(diam, threadcount, head, thread, drive) =
undef,
fff=echo("------------------------", driveind),
drive_dims = small ? (
drive=="phillips" && !undercut ? [["drive_diameter",inch*entry[4]],
["drive_width",inch*entry[6]],["drive_depth",inch*entry[5]]] :
drive=="phillips" && undercut ? [["drive_diameter",inch*entry[9]],
["drive_width",inch*entry[11]],["drive_depth",inch*entry[10]]] :
drive=="slot" && !undercut ? [["drive_width", inch*entry[7]], ["drive_depth",inch*entry[8]]] :
drive=="slot" && undercut ? [["drive_width", inch*entry[7]], ["drive_depth",inch*entry[12]]] :
drive=="phillips" && !undercut ? [["drive_diameter",INCH*entry[4]],
["drive_width",INCH*entry[6]],["drive_depth",INCH*entry[5]]] :
drive=="phillips" && undercut ? [["drive_diameter",INCH*entry[9]],
["drive_width",INCH*entry[11]],["drive_depth",INCH*entry[10]]] :
drive=="slot" && !undercut ? [["drive_width", INCH*entry[7]], ["drive_depth",INCH*entry[8]]] :
drive=="slot" && undercut ? [["drive_width", INCH*entry[7]], ["drive_depth",INCH*entry[12]]] :
[]
)
:
(
drive=="hex" ? [["drive_depth", inch*entry[3]]] :
drive=="torx" ? [["drive_depth", inch*entry[4]]] : []
drive=="hex" ? [["drive_depth", INCH*entry[3]]] :
drive=="torx" ? [["drive_depth", INCH*entry[4]]] : []
)
)
concat([["head","flat"],["head_angle",82],["head_size",inch*entry[0]]],
is_def(driveind) ? [["drive_size", (drive=="hex"?inch:1)*entry[driveind]]] : [],
undercut ? [["head_height", inch*entry[3]]] : [], drive_dims
concat([["head","flat"],["head_angle",82],["head_size",INCH*entry[0]]],
is_def(driveind) ? [["drive_size", (drive=="hex"?INCH:1)*entry[driveind]]] : [],
undercut ? [["head_height", INCH*entry[3]]] : [], drive_dims
) : []
)
concat([["system","UTS"],["diameter",inch*diameter],["pitch", pitch],["drive",drive]],
concat([["system","UTS"],["diameter",INCH*diameter],["pitch", pitch],["drive",drive]],
head_data
);
@ -960,10 +959,9 @@ module screw_head(screw_info,details=false) {
// Example(2D): This example shows the gap between nut and bolt at the loosest tolerance for UTS. This gap is what enables the parts to mesh without binding and is part of the definition for standard metal hardware.
// $slop=0;
// $fn=32;
// inch=25.4;
// projection(cut=true)xrot(-90){
// screw("1/4-20,1/4", head="hex",orient=UP,anchor=BOTTOM,tolerance="1A");
// down(inch*1/20*2.58) nut("1/4-20", thickness=8, diameter=0.5*inch,tolerance="1B");
// down(INCH*1/20*2.58) nut("1/4-20", thickness=8, diameter=0.5*INCH,tolerance="1B");
// }
module screw(name, head, thread="coarse", drive, drive_size, oversize=0, spec, length, shank=0, tolerance=undef, details=true, anchor=undef,anchor_head=undef,spin=0, orient=UP)
@ -1159,9 +1157,8 @@ function _ISO_thread_tolerance(diameter, pitch, internal=false, tolerance=undef)
function _UTS_thread_tolerance(diam, pitch, internal=false, tolerance=undef) =
let(
inch = 25.4,
d = diam/inch, // diameter in inches
P = pitch/inch, // pitch in inches
d = diam/INCH, // diameter in inches
P = pitch/INCH, // pitch in inches
H = P*sqrt(3)/2,
tolerance = first_defined([tolerance, internal?"2B":"2A"]),
tolOK = in_list(tolerance, ["1A","1B","2A","2B","3A","3B"]),
@ -1204,8 +1201,8 @@ function _UTS_thread_tolerance(diam, pitch, internal=false, tolerance=undef) =
minordiam = internal ? [basic_minordiam, basic_minordiam + minortol]
: [pitchdiam[0] - 3/4*H, basic_minordiam - allowance - H/8] // the -H/8 is for the UNR case, 0 for UN case
)
[["pitch",P*inch],["d_major",majordiam*inch], ["d_pitch", pitchdiam*inch], ["d_minor",minordiam*inch],
["basic", inch*[basic_minordiam, basic_pitchdiam, d]]];
[["pitch",P*INCH],["d_major",majordiam*INCH], ["d_pitch", pitchdiam*INCH], ["d_minor",minordiam*INCH],
["basic", INCH*[basic_minordiam, basic_pitchdiam, d]]];
function _exact_thread_tolerance(d,P) =
let(
@ -1232,43 +1229,11 @@ function _exact_thread_tolerance(d,P) =
// - basic: vector `[minor, pitch, major]` of the nominal or "basic" diameters for the threads
function thread_specification(screw_spec, internal=false, tolerance=undef) =
let( diam = struct_val(screw_spec, "diameter"),
pitch = struct_val(screw_spec, "pitch")
,k=
tolerance == 0 || tolerance=="none" ? _exact_thread_tolerance(diam, pitch) :
struct_val(screw_spec,"system") == "ISO" ? _ISO_thread_tolerance(diam, pitch, internal, tolerance) :
struct_val(screw_spec,"system") == "UTS" ? _UTS_thread_tolerance(diam, pitch, internal, tolerance) :
assert(false,"Unknown screw system ",struct_val(screw_spec,"system")),
fff=echo(k))
k;
function _thread_profile(thread) =
let(
pitch = struct_val(thread,"pitch"),
meanpitchrad = mean(struct_val(thread,"d_pitch"))/2,
meanminorrad = mean(struct_val(thread,"d_minor"))/2,
meanmajorrad = mean(struct_val(thread,"d_major"))/2,
depth = meanmajorrad-meanminorrad,
crestwidth = pitch/2 - 2*(meanmajorrad-meanpitchrad)/sqrt(3)
)
[
[-depth/sqrt(3)-crestwidth/2, -depth],
[ -crestwidth/2, 0],
[ crestwidth/2, 0],
[ depth/sqrt(3)+crestwidth/2, -depth]
]/pitch;
/* Old non-centered profile
[
[-1/2,-depth],
[depth/sqrt(3)-1/2,0],
[depth/sqrt(3)+crestwidth-1/2, 0],
[crestwidth + 2*depth/sqrt(3)-1/2,-depth]
]
;
*/
pitch = struct_val(screw_spec, "pitch"))
tolerance == 0 || tolerance=="none" ? _exact_thread_tolerance(diam, pitch)
: struct_val(screw_spec,"system") == "ISO" ? _ISO_thread_tolerance(diam, pitch, internal, tolerance)
: struct_val(screw_spec,"system") == "UTS" ? _UTS_thread_tolerance(diam, pitch, internal, tolerance)
: assert(false,"Unknown screw system ",struct_val(screw_spec,"system"));
module _rod(spec, length, tolerance, orient=UP, spin=0, anchor=CENTER)
@ -1280,16 +1245,9 @@ module _rod(spec, length, tolerance, orient=UP, spin=0, anchor=CENTER)
threaded_rod([mean(struct_val(threadspec, "d_minor")),
mean(struct_val(threadspec, "d_pitch")),
mean(struct_val(threadspec, "d_major"))],
pitch = struct_val(threadspec, "pitch"),
l=length, left_handed=false,
bevel=false, orient=orient, anchor=anchor, spin=spin);
/*
generic_threaded_rod( d=mean(struct_val(threadspec, "d_major")),
l=length,
pitch = struct_val(threadspec, "pitch"),
profile = _thread_profile(threadspec),left_handed=false,
bevel=false, orient=orient, anchor=anchor, spin=spin);
*/
pitch = struct_val(threadspec, "pitch"),
l=length, left_handed=false,
bevel=false, orient=orient, anchor=anchor, spin=spin);
}
@ -1322,31 +1280,29 @@ module _rod(spec, length, tolerance, orient=UP, spin=0, anchor=CENTER)
// thread = thread type or specification. Default: "coarse"
// oversize = amount to increase screw diameter for clearance holes. Default: 0
// spec = screw specification from `screw_info()`. If you specify this you can omit all the preceeding parameters.
// details = toggle some details in rendering. Default: false
// bevel = bevel the nut. Default: false
// tolerance = nut tolerance. Determines actual nut thread geometry based on nominal sizing. Default is "2B" for UTS and "6H" for ISO.
// $slop = extra space left to account for printing over-extrusion. Default: 0
// Example: A metric and UTS nut
// inch=25.4;
// nut("3/8", 5/8*inch, 1/4*inch);
// nut("3/8", 5/8*INCH, 1/4*INCH);
// right(25)
// nut("M8", 16, 6);
// Example: The three different UTS nut tolerances
// inch=25.4;
// module mark(number)
// {
// difference(){
// children();
// ycopies(n=number, spacing=1.5)right(.25*inch-2)up(8-.35)cyl(d=1, h=1);
// ycopies(n=number, spacing=1.5)right(.25*INCH-2)up(8-.35)cyl(d=1, h=1);
// }
// }
// $fn=64;
// xdistribute(spacing=17){
// mark(1) nut("1/4-20", thickness=8, diameter=0.5*inch,tolerance="1B");
// mark(2) nut("1/4-20", thickness=8, diameter=0.5*inch,tolerance="2B");
// mark(3) nut("1/4-20", thickness=8, diameter=0.5*inch,tolerance="3B");
// mark(1) nut("1/4-20", thickness=8, diameter=0.5*INCH,tolerance="1B");
// mark(2) nut("1/4-20", thickness=8, diameter=0.5*INCH,tolerance="2B");
// mark(3) nut("1/4-20", thickness=8, diameter=0.5*INCH,tolerance="3B");
// }
module nut(name, diameter, thickness, thread="coarse", oversize=0, spec, tolerance=undef,
details=true, anchor=BOTTOM,spin=0, orient=UP)
bevel=false, anchor=BOTTOM,spin=0, orient=UP)
{
assert(is_num(diameter) && diameter>0);
assert(is_num(thickness) && thickness>0);
@ -1354,11 +1310,15 @@ module nut(name, diameter, thickness, thread="coarse", oversize=0, spec, toleran
threadspec = thread_specification(spec, internal=true, tolerance=tolerance);
echo(threadspec=threadspec,"for nut threads");
echo(nut_minor_diam = mean(struct_val(threadspec,"d_minor")));
generic_threaded_nut(
od=diameter, id=mean(struct_val(threadspec, "d_major")), h=thickness,
pitch=struct_val(threadspec, "pitch"),
profile=_thread_profile(threadspec),
bevel=false,anchor=anchor,spin=spin,orient=orient);
threaded_nut(
od=diameter,
id=[mean(struct_val(threadspec, "d_minor")),
mean(struct_val(threadspec, "d_pitch")),
mean(struct_val(threadspec, "d_major"))],
pitch = struct_val(threadspec, "pitch"),
h=thickness,
bevel=bevel,
anchor=anchor,spin=spin,orient=orient);
}

View file

@ -36,8 +36,8 @@ use <builtins.scad>
// size = The size of the square to create. If given as a scalar, both X and Y will be the same size.
// center = If given and true, overrides `anchor` to be `CENTER`. If given and false, overrides `anchor` to be `FRONT+LEFT`.
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Example(2D):
// square(40);
// Example(2D): Centered
@ -72,11 +72,11 @@ module square(size=1, center, anchor, spin) {
// Function&Module: rect()
// Usage: As Module
// rect(size, [center], [rounding], [chamfer], ...);
// rect(size, [rounding], [chamfer], ...);
// Usage: With Attachments
// rect(size, [center], ...) { attachables }
// rect(size, ...) { attachables }
// Usage: As Function
// path = rect(size, [center], [rounding], [chamfer], ...);
// path = rect(size, [rounding], [chamfer], ...);
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable
// See Also: square()
// Description:
@ -86,38 +86,34 @@ module square(size=1, center, anchor, spin) {
// size = The size of the rectangle to create. If given as a scalar, both X and Y will be the same size.
// rounding = The rounding radius for the corners. If given as a list of four numbers, gives individual radii for each corner, in the order [X+Y+,X-Y+,X-Y-,X+Y-]. Default: 0 (no rounding)
// chamfer = The chamfer size for the corners. If given as a list of four numbers, gives individual chamfers for each corner, in the order [X+Y+,X-Y+,X-Y-,X+Y-]. Default: 0 (no chamfer)
// center = If given and true, overrides `anchor` to be `CENTER`. If given and false, overrides `anchor` to be `FRONT+LEFT`.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Example(2D):
// rect(40);
// Example(2D): Centered
// rect([40,30], center=true);
// Example(2D): Anchored
// rect([40,30], anchor=FRONT);
// Example(2D): Spun
// rect([40,30], anchor=FRONT, spin=30);
// Example(2D): Chamferred Rect
// rect([40,30], chamfer=5, center=true);
// rect([40,30], chamfer=5);
// Example(2D): Rounded Rect
// rect([40,30], rounding=5, center=true);
// rect([40,30], rounding=5);
// Example(2D): Mixed Chamferring and Rounding
// rect([40,30],center=true,rounding=[5,0,10,0],chamfer=[0,8,0,15],$fa=1,$fs=1);
// rect([40,30],rounding=[5,0,10,0],chamfer=[0,8,0,15],$fa=1,$fs=1);
// Example(2D): Called as Function
// path = rect([40,30], chamfer=5, anchor=FRONT, spin=30);
// stroke(path, closed=true);
// move_copies(path) color("blue") circle(d=2,$fn=8);
module rect(size=1, center, rounding=0, chamfer=0, anchor, spin=0) {
module rect(size=1, rounding=0, chamfer=0, anchor=CENTER, spin=0) {
size = is_num(size)? [size,size] : point2d(size);
anchor = point2d(get_anchor(anchor, center, FRONT+LEFT, CENTER));
if (rounding==0 && chamfer==0) {
attachable(anchor,spin, two_d=true, size=size) {
attachable(anchor, spin, two_d=true, size=size) {
square(size, center=true);
children();
}
} else {
pts = rect(size=size, rounding=rounding, chamfer=chamfer, center=true);
attachable(anchor,spin, two_d=true, path=pts) {
attachable(anchor, spin, two_d=true, path=pts) {
polygon(pts);
children();
}
@ -125,13 +121,14 @@ module rect(size=1, center, rounding=0, chamfer=0, anchor, spin=0) {
}
function rect(size=1, center, rounding=0, chamfer=0, anchor, spin=0) =
function rect(size=1, rounding=0, chamfer=0, anchor=CENTER, spin=0) =
assert(is_num(size) || is_vector(size))
assert(is_num(chamfer) || len(chamfer)==4)
assert(is_num(rounding) || len(rounding)==4)
let(
anchor=point2d(anchor),
size = is_num(size)? [size,size] : point2d(size),
anchor = point2d(get_anchor(anchor, center, FRONT+LEFT, CENTER)),
complex = rounding!=0 || chamfer!=0
)
(rounding==0 && chamfer==0)? let(
@ -141,7 +138,8 @@ function rect(size=1, center, rounding=0, chamfer=0, anchor, spin=0) =
[-size.x/2, size.y/2],
[ size.x/2, size.y/2]
]
) rot(spin, p=move(-v_mul(anchor,size/2), p=path)) :
)
rot(spin, p=move(-v_mul(anchor,size/2), p=path)) :
let(
chamfer = is_list(chamfer)? chamfer : [for (i=[0:3]) chamfer],
rounding = is_list(rounding)? rounding : [for (i=[0:3]) rounding],
@ -190,8 +188,8 @@ function rect(size=1, center, rounding=0, chamfer=0, anchor, spin=0) =
// r = The radius of the circle to create.
// d = The diameter of the circle to create.
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Example(2D): By Radius
// circle(r=25);
// Example(2D): By Diameter
@ -236,8 +234,8 @@ module circle(r, d, anchor=CENTER, spin=0) {
// d = Diameter of the circle or a pair giving the full X and Y axis lengths.
// realign = If false starts the approximate ellipse with a point on the X+ axis. If true the midpoint of a side is on the X+ axis and the first point of the polygon is below the X+ axis. This can result in a very different polygon when $fn is small. Default: false
// circum = If true, the polygon that approximates the circle will be upsized slightly to circumscribe the theoretical circle. If false, it inscribes the theoretical circle. Default: false
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Example(2D): By Radius
// ellipse(r=25);
// Example(2D): By Diameter
@ -419,8 +417,8 @@ function ellipse(r, d, realign=false, circum=false, uniform=false, anchor=CENTER
// realign = If false, vertex 0 will lie on the X+ axis. If true then the midpoint of the last edge will lie on the X+ axis, and vertex 0 will be below the X axis. Default: false
// align_tip = If given as a 2D vector, rotates the whole shape so that the first vertex points in that direction. This occurs before spin.
// align_side = If given as a 2D vector, rotates the whole shape so that the normal of side0 points in that direction. This occurs before spin.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Extra Anchors:
// "tip0", "tip1", etc. = Each tip has an anchor, pointing outwards.
// "side0", "side1", etc. = The center of each side has an anchor, pointing outwards.
@ -554,8 +552,8 @@ module regular_ngon(n=6, r, d, or, od, ir, id, side, rounding=0, realign=false,
// realign = If false, vertex 0 will lie on the X+ axis. If true then the midpoint of the last edge will lie on the X+ axis, and vertex 0 will be below the X axis. Default: false
// align_tip = If given as a 2D vector, rotates the whole shape so that the first vertex points in that direction. This occurs before spin.
// align_side = If given as a 2D vector, rotates the whole shape so that the normal of side0 points in that direction. This occurs before spin.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Extra Anchors:
// "tip0" ... "tip4" = Each tip has an anchor, pointing outwards.
// "side0" ... "side4" = The center of each side has an anchor, pointing outwards.
@ -618,8 +616,8 @@ module pentagon(r, d, or, od, ir, id, side, rounding=0, realign=false, align_tip
// realign = If false, vertex 0 will lie on the X+ axis. If true then the midpoint of the last edge will lie on the X+ axis, and vertex 0 will be below the X axis. Default: false
// align_tip = If given as a 2D vector, rotates the whole shape so that the first vertex points in that direction. This occurs before spin.
// align_side = If given as a 2D vector, rotates the whole shape so that the normal of side0 points in that direction. This occurs before spin.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Extra Anchors:
// "tip0" ... "tip5" = Each tip has an anchor, pointing outwards.
// "side0" ... "side5" = The center of each side has an anchor, pointing outwards.
@ -681,8 +679,8 @@ module hexagon(r, d, or, od, ir, id, side, rounding=0, realign=false, align_tip,
// realign = If false, vertex 0 will lie on the X+ axis. If true then the midpoint of the last edge will lie on the X+ axis, and vertex 0 will be below the X axis. Default: false
// align_tip = If given as a 2D vector, rotates the whole shape so that the first vertex points in that direction. This occurs before spin.
// align_side = If given as a 2D vector, rotates the whole shape so that the normal of side0 points in that direction. This occurs before spin.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Extra Anchors:
// "tip0" ... "tip7" = Each tip has an anchor, pointing outwards.
// "side0" ... "side7" = The center of each side has an anchor, pointing outwards.
@ -729,8 +727,8 @@ module octagon(r, d, or, od, ir, id, side, rounding=0, realign=false, align_tip,
// size = The width and length of the right triangle, given as a scalar or an XY vector.
// center = If true, forces `anchor=CENTER`. If false, forces `anchor=[-1,-1]`. Default: undef (use `anchor=`)
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Example:
// right_triangle([40,30]);
// Example: With `center=true`
@ -787,8 +785,8 @@ module right_triangle(size=[1,1], center, anchor, spin=0) {
// shift = Scalar value to shift the back of the trapezoid along the X axis by. Default: 0
// rounding = The rounding radius for the corners. If given as a list of four numbers, gives individual radii for each corner, in the order [X+Y+,X-Y+,X-Y-,X+Y-]. Default: 0 (no rounding)
// chamfer = The Length of the chamfer faces at the corners. If given as a list of four numbers, gives individual chamfers for each corner, in the order [X+Y+,X-Y+,X-Y-,X+Y-]. Default: 0 (no chamfer)
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Examples(2D):
// trapezoid(h=30, w1=40, w2=20);
// trapezoid(h=25, w1=20, w2=35);
@ -891,8 +889,8 @@ module trapezoid(h, w1, w2, angle, shift=0, chamfer=0, rounding=0, anchor=CENTER
// realign = If false, vertex 0 will lie on the X+ axis. If true then the midpoint of the last edge will lie on the X+ axis, and vertex 0 will be below the X axis. Default: false
// align_tip = If given as a 2D vector, rotates the whole shape so that the first star tip points in that direction. This occurs before spin.
// align_pit = If given as a 2D vector, rotates the whole shape so that the first inner corner is pointed towards that direction. This occurs before spin.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// atype = Choose "hull" or "intersect" anchor methods. Default: "hull"
// Extra Anchors:
// "tip0" ... "tip4" = Each tip has an anchor, pointing outwards.
@ -1083,8 +1081,8 @@ module jittered_poly(path, dist=1/512) {
// cap_h = if given, height above center where the shape will be truncated.
// ---
// d = diameter of spherical portion of bottom. (Use instead of r)
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
//
// Example(2D): Typical Shape
// teardrop2d(r=30, ang=30);
@ -1146,8 +1144,8 @@ function teardrop2d(r, ang=45, cap_h, d, anchor=CENTER, spin=0) =
// tangent = The angle in degrees of the tangent point for the joining arcs, measured away from the Y axis. Default: 30
// ---
// d = The diameter of the end circles.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Examples(2D):
// glued_circles(r=15, spread=40, tangent=45);
// glued_circles(d=30, spread=30, tangent=30);
@ -1224,8 +1222,8 @@ function _superformula(theta,m1,m2,n1,n2=1,n3=1,a=1,b=1) =
// r = Radius of the shape. Scale shape to fit in a circle of radius r.
// ---
// d = Diameter of the shape. Scale shape to fit in a circle of diameter d.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// atype = Select "hull" or "intersect" style anchoring. Default: "hull".
// Example(2D):
// supershape(step=0.5,m1=16,m2=16,n1=0.5,n2=0.5,n3=16,r=50);
@ -1293,8 +1291,8 @@ module supershape(step=0.5,m1=4,m2=undef,n1,n2=undef,n3=undef,a=1,b=undef, r=und
// r = Radius of the shape. Scale shape to fit in a circle of radius r.
// ---
// d = Diameter of the shape. Scale shape to fit in a circle of diameter d.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Extra Anchors:
// "tip0", "tip1", etc. = Each tip has an anchor, pointing outwards.
// Examples(2D):

View file

@ -34,9 +34,9 @@ use <builtins.scad>
// size = The size of the cube.
// center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=FRONT+LEFT+BOTTOM`.
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example: Simple cube.
// cube(40);
// Example: Rectangular cube.
@ -104,20 +104,20 @@ function cube(size=1, center, anchor, spin=0, orient=UP) =
// Negative chamfers and roundings can be applied to create external fillets, but they
// but only apply to edges around the top or bottom faces. If you specify an edge set other than "ALL"
// with such roundings or chamfers then you will get an error. See
// [Specifying Edges](edges.scad#section-specifying-edges) for information on how to specify edge sets.
// [Specifying Edges](attachments.scad#section-specifying-edges) for information on how to specify edge sets.
// Arguments:
// size = The size of the cube, a number or length 3 vector.
// ---
// chamfer = Size of chamfer, inset from sides. Default: No chamfering.
// rounding = Radius of the edge rounding. Default: No rounding.
// edges = Edges to mask. See [Specifying Edges](edges.scad#section-specifying-edges). Default: all edges.
// except = Edges to explicitly NOT mask. See [Specifying Edges](edges.scad#section-specifying-edges). Default: No edges.
// edges = Edges to mask. See [Specifying Edges](attachments.scad#section-specifying-edges). Default: all edges.
// except = Edges to explicitly NOT mask. See [Specifying Edges](attachments.scad#section-specifying-edges). Default: No edges.
// trimcorners = If true, rounds or chamfers corners where three chamfered/rounded edges meet. Default: `true`
// p1 = Align the cuboid's corner at `p1`, if given. Forces `anchor=FRONT+LEFT+BOTTOM`.
// p2 = If given with `p1`, defines the cornerpoints of the cuboid.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example: Simple regular cube.
// cuboid(40);
// Example: Cube with minimum cornerpoint given.
@ -481,9 +481,9 @@ function cuboid(
// chamfer = The chamfer size for the vertical-ish edges of the prismoid. If given as a list of four numbers, gives individual chamfers for each corner, in the order [X+Y+,X-Y+,X-Y-,X+Y-]. Default: 0 (no chamfer)
// chamfer1 = The chamfer size for the bottom of the vertical-ish edges of the prismoid. If given as a list of four numbers, gives individual chamfers for each corner, in the order [X+Y+,X-Y+,X-Y-,X+Y-].
// chamfer2 = The chamfer size for the top of the vertical-ish edges of the prismoid. If given as a list of four numbers, gives individual chamfers for each corner, in the order [X+Y+,X-Y+,X-Y-,X+Y-].
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// See Also: rounded_prism()
//
@ -663,9 +663,9 @@ function prismoid(
// Arguments:
// size = Width of the octahedron, tip to tip.
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// octahedron(size=40);
// Example: Anchors
@ -741,9 +741,9 @@ function octahedron(size=1, anchor=CENTER, spin=0, orient=UP) =
// ichamfer = The chamfer size for the inside edges of the rectangular tube. Default: Same as `chamfer`
// ichamfer1 = The chamfer size for the inside bottom corner of the rectangular tube.
// ichamfer2 = The chamfer size for the inside top corner of the rectangular tube.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `BOTTOM`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `BOTTOM`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Examples:
// rect_tube(size=50, wall=5, h=30);
// rect_tube(size=[100,60], wall=5, h=30);
@ -898,9 +898,9 @@ function rect_tube(
// size = [width, thickness, height]
// center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=UP`.
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `FRONT+LEFT+BOTTOM`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `FRONT+LEFT+BOTTOM`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// Example: Centered
// wedge([20, 40, 15], center=true);
@ -967,9 +967,9 @@ function wedge(size=[1,1,1], center, anchor, spin=0, orient=UP) =
// d2 = The top diameter of the cylinder. (Before orientation.)
// r = The radius of the cylinder.
// d = The diameter of the cylinder.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example: By Radius
// xdistribute(30) {
// cylinder(h=40, r=10);
@ -1072,9 +1072,9 @@ function cylinder(h, r1, r2, center, l, r, d, d1, d2, anchor, spin=0, orient=UP)
// rounding1 = The radius of the rounding on the bottom end of the cylinder.
// rounding2 = The radius of the rounding on the top end of the cylinder.
// realign = If true, rotate the cylinder by half the angle of one face.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// Example: By Radius
// xdistribute(30) {
@ -1248,7 +1248,7 @@ module cyl(
// d = Optional diameter of cylinder. (use instead of `r`)
// d1 = Optional diameter of left (X-) end of cylinder.
// d2 = Optional diameter of right (X+) end of cylinder.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
//
// Example: By Radius
// ydistribute(50) {
@ -1295,7 +1295,7 @@ module xcyl(h, r, d, r1, r2, d1, d2, l, anchor=CENTER)
// d = Diameter of cylinder.
// d1 = Diameter of front (Y-) end of one.
// d2 = Diameter of back (Y+) end of one.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
//
// Example: By Radius
// xdistribute(50) {
@ -1342,7 +1342,7 @@ module ycyl(h, r, d, r1, r2, d1, d2, l, anchor=CENTER)
// d = Diameter of cylinder.
// d1 = Diameter of front (Y-) end of one.
// d2 = Diameter of back (Y+) end of one.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
//
// Example: By Radius
// xdistribute(50) {
@ -1396,9 +1396,9 @@ module zcyl(h, r, d, r1, r2, d1, d2, l, anchor=CENTER)
// id1 = Inner diameter of bottom of tube.
// id2 = Inner diameter of top of tube.
// realign = If true, rotate the tube by half the angle of one face.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// Example: These all Produce the Same Tube
// tube(h=30, or=40, wall=5);
@ -1470,9 +1470,9 @@ module tube(
// d = diameter of pie slice.
// d1 = bottom diameter of pie slice.
// d2 = top diameter of pie slice.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// Example: Cylindrical Pie Slice
// pie_slice(ang=45, l=20, r=30);
@ -1525,9 +1525,9 @@ module pie_slice(
// d = Diameter of the sphere.
// circum = If true, the sphere is made large enough to circumscribe the sphere of the ideal side. Otherwise inscribes. Default: false (inscribes)
// style = The style of the sphere's construction. One of "orig", "aligned", "stagger", "octa", or "icosa". Default: "orig"
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example: By Radius
// sphere(r=50);
// Example: By Diameter
@ -1598,9 +1598,9 @@ function sphere(r, d, circum=false, style="orig", anchor=CENTER, spin=0, orient=
// ---
// d = Diameter of the spheroid.
// circum = If true, the spheroid is made large enough to circumscribe the sphere of the ideal side. Otherwise inscribes. Default: false (inscribes)
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example: By Radius
// spheroid(r=50);
// Example: By Diameter
@ -1846,8 +1846,8 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or
// ir = inside radius of the torus. (use with 'or', or 'od')
// od = outer diameter of the torus. (use with 'ir' or 'id')
// id = inside diameter of the torus. (use with 'or' or 'od')
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// Example:
// // These all produce the same torus.
@ -1917,9 +1917,9 @@ module torus(
// d2 = Diameter of circular portion of the back end of the teardrop shape.
// cap_h1 = If given, height above center where the shape will be truncated, on the front side. Default: `undef` (no truncation)
// cap_h2 = If given, height above center where the shape will be truncated, on the back side. Default: `undef` (no truncation)
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// Extra Anchors:
// cap = The center of the top of the cap, oriented with the cap face normal.
@ -2002,9 +2002,9 @@ module teardrop(h, r, ang=45, cap_h, r1, r2, d, d1, d2, cap_h1, cap_h2, l, ancho
// cap_h = If given, height above sphere center to truncate teardrop shape. Default: `undef` (no truncation)
// ---
// d = diameter of spherical portion of bottom.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// Example: Typical Shape
// onion(r=30, ang=30);
@ -2049,9 +2049,9 @@ module onion(r, ang=45, cap_h, d, anchor=CENTER, spin=0, orient=UP)
// size = The font size used to create the text block. Default: 10
// font = The name of the font used to create the text block. Default: "Courier"
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `"baseline"`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `"baseline"`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// See Also: attachable()
// Extra Anchors:
// "baseline" = Anchors at the baseline of the text, at the start of the string.
@ -2083,7 +2083,7 @@ module atext(text, h=1, size=9, font="Courier", anchor="baseline", spin=0, orien
anch = !any([for (c=anchor) c=="["])? anchor :
let(
parts = str_split(str_split(str_split(anchor,"]")[0],"[")[1],","),
vec = [for (p=parts) str_float(str_strip_leading(p," "))]
vec = [for (p=parts) str_float(str_strip(p," ",start=true))]
) vec;
ha = anchor=="baseline"? "left" :
anchor==anch && is_string(anchor)? "center" :
@ -2326,9 +2326,9 @@ module path_text(path, text, font, size, thickness, lettersize, offset=0, revers
// overlap = Overlap size for unioning with faces.
// ---
// d = Diameter of fillet.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `FRONT+LEFT`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `FRONT+LEFT`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// Example:
// union() {
@ -2393,9 +2393,9 @@ module interior_fillet(l=1.0, r, ang=90, overlap=0.01, d, anchor=FRONT+LEFT, spi
// style = The style of subdividing the quads into faces. Valid options are "default", "alt", and "quincunx". Default: "default"
// ---
// convexity = Max number of times a line could intersect a wall of the surface being formed. Module only. Default: 10
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// heightfield(size=[100,100], bottom=-20, data=[
// for (y=[-180:4:180]) [
@ -2518,9 +2518,9 @@ function heightfield(data, size=[100,100], bottom=-20, maxz=100, xrange=[-1:0.04
// alpha = transparency value. Default: 1.0
// unit = unit to mark. Scales the ruler marks to a different length. Default: 1
// inch = set to true for a ruler scaled to inches (assuming base dimension is mm). Default: false
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `LEFT+BACK+TOP`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `LEFT+BACK+TOP`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Examples(2D,Big):
// ruler(100,depth=3);
// ruler(100,depth=3,labels=true);

View file

@ -1260,55 +1260,55 @@ function _smooth(data,len,closed=false,angle=false) =
// long = resample the "long way" around the rotation, a boolean or list of booleans. Default: false
// turns = add extra turns. If a scalar adds the turns to every rotation, or give a vector. Default: 0
// closed = if true then the rotation list is treated as closed. Default: false
// Example: Resampling the arc from a compound rotation with translations thrown in.
// Example(3D): Resampling the arc from a compound rotation with translations thrown in.
// tran = rot_resample([ident(4), back(5)*up(4)*xrot(-10)*zrot(-20)*yrot(117,cp=[10,0,0])], N=25);
// sweep(circle(r=1,$fn=3), tran);
// Example: Applying a scale factor
// Example(3D): Applying a scale factor
// tran = rot_resample([ident(4), back(5)*up(4)*xrot(-10)*zrot(-20)*yrot(117,cp=[10,0,0])], N=25, scale=2);
// sweep(circle(r=1,$fn=3), tran);
// Example: Applying twist
// Example(3D): Applying twist
// tran = rot_resample([ident(4), back(5)*up(4)*xrot(-10)*zrot(-20)*yrot(117,cp=[10,0,0])], N=25, twist=60);
// sweep(circle(r=1,$fn=3), tran);
// Example: Going the long way
// Example(3D): Going the long way
// tran = rot_resample([ident(4), back(5)*up(4)*xrot(-10)*zrot(-20)*yrot(117,cp=[10,0,0])], N=25, long=true);
// sweep(circle(r=1,$fn=3), tran);
// Example: Getting transformations from turtle3d
// Example(3D): Getting transformations from turtle3d
// include<BOSL2/turtle3d.scad>
// tran=turtle3d(["arcsteps",1,"up", 10, "arczrot", 10,170],transforms=true);
// sweep(circle(r=1,$fn=3),rot_resample(tran, N=40));
// Example: If you specify a larger angle in turtle you need to use the long argument
// Example(3D): If you specify a larger angle in turtle you need to use the long argument
// include<BOSL2/turtle3d.scad>
// tran=turtle3d(["arcsteps",1,"up", 10, "arczrot", 10,270],transforms=true);
// sweep(circle(r=1,$fn=3),rot_resample(tran, N=40,long=true));
// Example: And if the angle is over 360 you need to add turns to get the right result. Note long is false when the remaining angle after subtracting full turns is below 180:
// Example(3D): And if the angle is over 360 you need to add turns to get the right result. Note long is false when the remaining angle after subtracting full turns is below 180:
// include<BOSL2/turtle3d.scad>
// tran=turtle3d(["arcsteps",1,"up", 10, "arczrot", 10,90+360],transforms=true);
// sweep(circle(r=1,$fn=3),rot_resample(tran, N=40,long=false,turns=1));
// Example: Here the remaining angle is 270, so long must be set to true
// Example(3D): Here the remaining angle is 270, so long must be set to true
// include<BOSL2/turtle3d.scad>
// tran=turtle3d(["arcsteps",1,"up", 10, "arczrot", 10,270+360],transforms=true);
// sweep(circle(r=1,$fn=3),rot_resample(tran, N=40,long=true,turns=1));
// Example: Note the visible line at the scale transition
// Example(3D): Note the visible line at the scale transition
// include<BOSL2/turtle3d.scad>
// tran = turtle3d(["arcsteps",1,"arcup", 10, 90, "arcdown", 10, 90], transforms=true);
// rtran = rot_resample(tran,200,scale=[1,6]);
// sweep(circle(1,$fn=32),rtran);
// Example: Observe how using a large smoothlen value eases that transition
// Example(3D): Observe how using a large smoothlen value eases that transition
// include<BOSL2/turtle3d.scad>
// tran = turtle3d(["arcsteps",1,"arcup", 10, 90, "arcdown", 10, 90], transforms=true);
// rtran = rot_resample(tran,200,scale=[1,6],smoothlen=17);
// sweep(circle(1,$fn=32),rtran);
// Example: A similar issues can arise with twist, where a "line" is visible at the transition
// Example(3D): A similar issues can arise with twist, where a "line" is visible at the transition
// include<BOSL2/turtle3d.scad>
// tran = turtle3d(["arcsteps", 1, "arcup", 10, 90, "move", 10], transforms=true,state=[1,-.5,0]);
// rtran = rot_resample(tran,100,twist=[0,60],smoothlen=1);
// sweep(subdivide_path(rect([3,3]),40),rtran);
// Example: Here's the smoothed twist transition
// Example(3D): Here's the smoothed twist transition
// include<BOSL2/turtle3d.scad>
// tran = turtle3d(["arcsteps", 1, "arcup", 10, 90, "move", 10], transforms=true,state=[1,-.5,0]);
// rtran = rot_resample(tran,100,twist=[0,60],smoothlen=17);
// sweep(subdivide_path(rect([3,3]),40),rtran);
// Example: toothed belt based on list-comprehension-demos example. This version has a smoothed twist transition. Try changing smoothlen to 1 to see the more abrupt transition that occurs without smoothing.
// Example(3D): toothed belt based on list-comprehension-demos example. This version has a smoothed twist transition. Try changing smoothlen to 1 to see the more abrupt transition that occurs without smoothing.
// include<BOSL2/turtle3d.scad>
// r_small = 19; // radius of small curve
// r_large = 46; // radius of large curve

View file

@ -24,9 +24,9 @@
// base = Height of slider base.
// wall = Width of wall behind each side of the slider.
// ang = Overhang angle for slider, to facilitate supportless printig.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value to make parts fit just right.
// Example:
// slider(l=30, base=10, wall=4, $slop=0.2, spin=90);
@ -71,9 +71,9 @@ module slider(l=30, w=10, h=10, base=10, wall=5, ang=30, anchor=BOTTOM, spin=0,
// h = Height of slider.
// chamfer = Size of chamfer at end of rail.
// ang = Overhang angle for slider, to facilitate supportless printig.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `BOTTOM`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `BOTTOM`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example:
// rail(l=100, w=10, h=10);
module rail(l=30, w=10, h=10, chamfer=1.0, ang=30, anchor=BOTTOM, spin=0, orient=UP)

View file

@ -20,7 +20,6 @@ include <drawing.scad>
include <masks3d.scad>
include <masks2d.scad>
include <paths.scad>
include <edges.scad>
include <lists.scad>
include <comparisons.scad>
include <math.scad>

View file

@ -9,7 +9,7 @@
//////////////////////////////////////////////////////////////////////
// Section: Extracting Substrings
// Section: Extracting substrings
// Function: substr()
// Usage:
@ -51,69 +51,256 @@ function suffix(str,len) =
// Section: String Searching
// Section: Checking character class
// Function: is_lower()
// Function: str_find()
// Usage:
// x = is_lower(s);
// str_find(str,pattern,[last],[all],[start])
// Description:
// Returns true if all the characters in the given string are lowercase letters. (a-z)
function is_lower(s) =
assert(is_string(s))
s==""? false :
len(s)>1? all([for (v=s) is_lower(v)]) :
let(v = ord(s[0])) (v>=ord("a") && v<=ord("z"));
// Searches input string `str` for the string `pattern` and returns the index or indices of the matches in `str`.
// By default `str_find()` returns the index of the first match in `str`. If `last` is true then it returns the index of the last match.
// If the pattern is the empty string the first match is at zero and the last match is the last character of the `str`.
// If `start` is set then the search begins at index start, working either forward and backward from that position. If you set `start`
// and `last` is true then the search will find the pattern if it begins at index `start`. If no match exists, returns `undef`.
// If you set `all` to true then `str_find()` returns all of the matches in a list, or an empty list if there are no matches.
// Arguments:
// str = String to search.
// pattern = string pattern to search for
// last = set to true to return the last match. Default: false
// all = set to true to return all matches as a list. Overrides last. Default: false
// start = index where the search starts
// Example:
// str_find("abc123def123abc","123"); // Returns 3
// str_find("abc123def123abc","b"); // Returns 1
// str_find("abc123def123abc","1234"); // Returns undef
// str_find("abc",""); // Returns 0
// str_find("abc123def123", "123", start=4); // Returns 9
// str_find("abc123def123abc","123",last=true); // Returns 9
// str_find("abc123def123abc","b",last=true); // Returns 13
// str_find("abc123def123abc","1234",last=true); // Returns undef
// str_find("abc","",last=true); // Returns 3
// str_find("abc123def123", "123", start=8, last=true)); // Returns 3
// str_find("abc123def123abc","123",all=true); // Returns [3,9]
// str_find("abc123def123abc","b",all=true); // Returns [1,13]
// str_find("abc123def123abc","1234",all=true); // Returns []
// str_find("abc","",all=true); // Returns [0,1,2]
function str_find(str,pattern,start=undef,last=false,all=false) =
all? _str_find_all(str,pattern) :
let( start = first_defined([start,last?len(str)-len(pattern):0]) )
pattern==""? start :
last? _str_find_last(str,pattern,start) :
_str_find_first(str,pattern,len(str)-len(pattern),start);
function _str_find_first(str,pattern,max_sindex,sindex) =
sindex<=max_sindex && !_str_cmp(str,sindex, pattern)?
_str_find_first(str,pattern,max_sindex,sindex+1) :
(sindex <= max_sindex ? sindex : undef);
function _str_find_last(str,pattern,sindex) =
sindex>=0 && !_str_cmp(str,sindex, pattern)?
_str_find_last(str,pattern,sindex-1) :
(sindex >=0 ? sindex : undef);
function _str_find_all(str,pattern) =
pattern == "" ? count(len(str)) :
[for(i=[0:1:len(str)-len(pattern)]) if (_str_cmp(str,i,pattern)) i];
// _str_cmp(str,sindex,pattern)
// returns true if the string pattern matches the string
// starting at index position sindex in the string.
//
// This is carefully optimized for speed. Precomputing the length
// cuts run time in half when the string is long. Two other string
// comparison methods were slower.
function _str_cmp(str,sindex,pattern) =
len(str)-sindex <len(pattern)? false :
_str_cmp_recurse(str,sindex,pattern,len(pattern));
function _str_cmp_recurse(str,sindex,pattern,plen,pindex=0,) =
pindex < plen && pattern[pindex]==str[sindex] ? _str_cmp_recurse(str,sindex+1,pattern,plen,pindex+1): (pindex==plen);
// Function: is_upper()
// Function: starts_with()
// Usage:
// x = is_upper(s);
// starts_with(str,pattern)
// Description:
// Returns true if all the characters in the given string are uppercase letters. (A-Z)
function is_upper(s) =
assert(is_string(s))
s==""? false :
len(s)>1? all([for (v=s) is_upper(v)]) :
let(v = ord(s[0])) (v>=ord("A") && v<=ord("Z"));
// Returns true if the input string `str` starts with the specified string pattern, `pattern`.
// Otherwise returns false.
// Arguments:
// str = String to search.
// pattern = String pattern to search for.
// Example:
// starts_with("abcdef","abc"); // Returns true
// starts_with("abcdef","def"); // Returns false
// starts_with("abcdef",""); // Returns true
function starts_with(str,pattern) = _str_cmp(str,0,pattern);
// Function: is_digit()
// Function: ends_with()
// Usage:
// x = is_digit(s);
// ends_with(str,pattern)
// Description:
// Returns true if all the characters in the given string are digits. (0-9)
function is_digit(s) =
assert(is_string(s))
s==""? false :
len(s)>1? all([for (v=s) is_digit(v)]) :
let(v = ord(s[0])) (v>=ord("0") && v<=ord("9"));
// Returns true if the input string `str` ends with the specified string pattern, `pattern`.
// Otherwise returns false.
// Arguments:
// str = String to search.
// pattern = String pattern to search for.
// Example:
// ends_with("abcdef","def"); // Returns true
// ends_with("abcdef","de"); // Returns false
// ends_with("abcdef",""); // Returns true
function ends_with(str,pattern) = _str_cmp(str,len(str)-len(pattern),pattern);
// Function: is_hexdigit()
// Function: str_split()
// Usage:
// x = is_hexdigit(s);
// str_split(str, sep, [keep_nulls])
// Description:
// Returns true if all the characters in the given string are valid hexadecimal digits. (0-9 or a-f or A-F))
function is_hexdigit(s) =
assert(is_string(s))
s==""? false :
len(s)>1? all([for (v=s) is_hexdigit(v)]) :
let(v = ord(s[0]))
(v>=ord("0") && v<=ord("9")) ||
(v>=ord("A") && v<=ord("F")) ||
(v>=ord("a") && v<=ord("f"));
// Breaks an input string into substrings using a separator or list of separators. If keep_nulls is true
// then two sequential separator characters produce an empty string in the output list. If keep_nulls is false
// then no empty strings are included in the output list.
// .
// If sep is a single string then each character in sep is treated as a delimiting character and the input string is
// split at every delimiting character. Empty strings can occur whenever two delimiting characters are sequential.
// If sep is a list of strings then the input string is split sequentially using each string from the list in order.
// If keep_nulls is true then the output will have length equal to `len(sep)+1`, possibly with trailing null strings
// if the string runs out before the separator list.
// Arguments:
// str = String to split.
// sep = a string or list of strings to use for the separator
// keep_nulls = boolean value indicating whether to keep null strings in the output list. Default: true
// Example:
// str_split("abc+def-qrs*iop","*-+"); // Returns ["abc", "def", "qrs", "iop"]
// str_split("abc+*def---qrs**iop+","*-+");// Returns ["abc", "", "def", "", "", "qrs", "", "iop", ""]
// str_split("abc def"," "); // Returns ["abc", "", "", "", "", "", "def"]
// str_split("abc def"," ",keep_nulls=false); // Returns ["abc", "def"]
// str_split("abc+def-qrs*iop",["+","-","*"]); // Returns ["abc", "def", "qrs", "iop"]
// str_split("abc+def-qrs*iop",["-","+","*"]); // Returns ["abc+def", "qrs*iop", "", ""]
function str_split(str,sep,keep_nulls=true) =
!keep_nulls ? _remove_empty_strs(str_split(str,sep,keep_nulls=true)) :
is_list(sep) ? _str_split_recurse(str,sep,i=0,result=[]) :
let( cutpts = concat([-1],sort(flatten(search(sep, str,0))),[len(str)]))
[for(i=[0:len(cutpts)-2]) substr(str,cutpts[i]+1,cutpts[i+1]-cutpts[i]-1)];
function _str_split_recurse(str,sep,i,result) =
i == len(sep) ? concat(result,[str]) :
let(
pos = search(sep[i], str),
end = pos==[] ? len(str) : pos[0]
)
_str_split_recurse(
substr(str,end+1),
sep, i+1,
concat(result, [substr(str,0,end)])
);
function _remove_empty_strs(list) =
list_remove(list, search([""], list,0)[0]);
// Function: is_letter()
// Section: String modification
// Function: str_join()
// Usage:
// x = is_letter(s);
// str_join(list, [sep])
// Description:
// Returns true if all the characters in the given string are standard ASCII letters. (A-Z or a-z)
function is_letter(s) =
assert(is_string(s))
s==""? false :
all([for (v=s) is_lower(v) || is_upper(v)]);
// Returns the concatenation of a list of strings, optionally with a
// separator string inserted between each string on the list.
// Arguments:
// list = list of strings to concatenate
// sep = separator string to insert. Default: ""
// Example:
// str_join(["abc","def","ghi"]); // Returns "abcdefghi"
// str_join(["abc","def","ghi"], " + "); // Returns "abc + def + ghi"
function str_join(list,sep="",_i=0, _result="") =
_i >= len(list)-1 ? (_i==len(list) ? _result : str(_result,list[_i])) :
str_join(list,sep,_i+1,str(_result,list[_i],sep));
// Function: str_strip()
// Usage:
// str_strip(s,c,[start],[end]);
// Description:
// Takes a string `s` and strips off all leading and/or trailing characters that exist in string `c`.
// By default strips both leading and trailing characters. If you set start or end to true then
// it will strip only the leading or trailing characters respectively. If you set start
// or end to false then it will strip only lthe trailing or leading characters.
// Arguments:
// s = The string to strip leading or trailing characters from.
// c = The string of characters to strip.
// start = if true then strip leading characters
// end = if true then strip trailing characters
// Example:
// str_strip("--##--123--##--","#-"); // Returns: "123"
// str_strip("--##--123--##--","-"); // Returns: "##--123--##"
// str_strip("--##--123--##--","#"); // Returns: "--##--123--##--"
// str_strip("--##--123--##--","#-",end=true); // Returns: "--##--123"
// str_strip("--##--123--##--","-",end=true); // Returns: "--##--123--##"
// str_strip("--##--123--##--","#",end=true); // Returns: "--##--123--##--"
// str_strip("--##--123--##--","#-",start=true); // Returns: "123--##--"
// str_strip("--##--123--##--","-",start=true); // Returns: "##--123--##--"
// str_strip("--##--123--##--","#",start=true); // Returns: "--##--123--##--"
function _str_count_leading(s,c,_i=0) =
(_i>=len(s)||!in_list(s[_i],[each c]))? _i :
_str_count_leading(s,c,_i=_i+1);
function _str_count_trailing(s,c,_i=0) =
(_i>=len(s)||!in_list(s[len(s)-1-_i],[each c]))? _i :
_str_count_trailing(s,c,_i=_i+1);
function str_strip(s,c,start,end) =
let(
nstart = (is_undef(start) && !end) ? true : start,
nend = (is_undef(end) && !start) ? true : end,
startind = nstart ? _str_count_leading(s,c) : 0,
endind = len(s) - (nend ? _str_count_trailing(s,c) : 0)
)
substr(s,startind, endind-startind);
// Function: str_pad()
// Usage:
// padded = str_pad(str, length, char, [left]);
// Description:
// Pad the given string `str` with to length `length` with the specified character,
// which must be a length 1 string. If left is true then pad on the left, otherwise
// pad on the right. If the string is longer than the specified length the full string
// is returned unchanged.
// Arguments:
// str = string to pad
// length = length to pad to
// char = character to pad with. Default: " " (space)
// left = if true, pad on the left side. Default: false
function str_pad(str,length,char=" ",left=false) =
assert(is_str(str))
assert(is_str(char) && len(char)==1, "char must be a single character string")
assert(is_bool(left))
let(
padding = str_join(repeat(char,length-len(str)))
)
left ? str(padding,str) : str(str,padding);
// Function: str_replace_char()
// Usage:
// newstr = str_replace_char(str, char, replace)
// Description:
// Replace every occurence of `char` in the input string with the string `replace` which
// can be any string.
function str_replace_char(str,char,replace) =
assert(is_str(str))
assert(is_str(char) && len(char)==1, "Search pattern 'char' must be a single character string")
assert(is_str(replace))
str_join([for(c=str) c==char ? replace : c]);
// Function: downcase()
@ -146,6 +333,7 @@ function upcase(str) =
// Section: Converting strings to numbers
// Function: str_int()
@ -368,7 +556,7 @@ function fmt_float(f,sig=12) =
)
str_join([
str(whole),
str_strip_trailing(
str_strip(end=true,
str_join([
".",
fmt_int(part, mindigits=mv)
@ -535,264 +723,72 @@ module echofmt(fmt, vals) {
}
// Section: Uncategorized string functions
// Function: str_join()
// Section: Checking character class
// Function: is_lower()
// Usage:
// str_join(list, [sep])
// x = is_lower(s);
// Description:
// Returns the concatenation of a list of strings, optionally with a
// separator string inserted between each string on the list.
// Arguments:
// list = list of strings to concatenate
// sep = separator string to insert. Default: ""
// Example:
// str_join(["abc","def","ghi"]); // Returns "abcdefghi"
// str_join(["abc","def","ghi"], " + "); // Returns "abc + def + ghi"
function str_join(list,sep="",_i=0, _result="") =
_i >= len(list)-1 ? (_i==len(list) ? _result : str(_result,list[_i])) :
str_join(list,sep,_i+1,str(_result,list[_i],sep));
// Returns true if all the characters in the given string are lowercase letters. (a-z)
function is_lower(s) =
assert(is_string(s))
s==""? false :
len(s)>1? all([for (v=s) is_lower(v)]) :
let(v = ord(s[0])) (v>=ord("a") && v<=ord("z"));
// Function: str_split()
// Function: is_upper()
// Usage:
// str_split(str, sep, [keep_nulls])
// x = is_upper(s);
// Description:
// Breaks an input string into substrings using a separator or list of separators. If keep_nulls is true
// then two sequential separator characters produce an empty string in the output list. If keep_nulls is false
// then no empty strings are included in the output list.
// .
// If sep is a single string then each character in sep is treated as a delimiting character and the input string is
// split at every delimiting character. Empty strings can occur whenever two delimiting characters are sequential.
// If sep is a list of strings then the input string is split sequentially using each string from the list in order.
// If keep_nulls is true then the output will have length equal to `len(sep)+1`, possibly with trailing null strings
// if the string runs out before the separator list.
// Arguments:
// str = String to split.
// sep = a string or list of strings to use for the separator
// keep_nulls = boolean value indicating whether to keep null strings in the output list. Default: true
// Example:
// str_split("abc+def-qrs*iop","*-+"); // Returns ["abc", "def", "qrs", "iop"]
// str_split("abc+*def---qrs**iop+","*-+");// Returns ["abc", "", "def", "", "", "qrs", "", "iop", ""]
// str_split("abc def"," "); // Returns ["abc", "", "", "", "", "", "def"]
// str_split("abc def"," ",keep_nulls=false); // Returns ["abc", "def"]
// str_split("abc+def-qrs*iop",["+","-","*"]); // Returns ["abc", "def", "qrs", "iop"]
// str_split("abc+def-qrs*iop",["-","+","*"]); // Returns ["abc+def", "qrs*iop", "", ""]
function str_split(str,sep,keep_nulls=true) =
!keep_nulls ? _remove_empty_strs(str_split(str,sep,keep_nulls=true)) :
is_list(sep) ? _str_split_recurse(str,sep,i=0,result=[]) :
let( cutpts = concat([-1],sort(flatten(search(sep, str,0))),[len(str)]))
[for(i=[0:len(cutpts)-2]) substr(str,cutpts[i]+1,cutpts[i+1]-cutpts[i]-1)];
function _str_split_recurse(str,sep,i,result) =
i == len(sep) ? concat(result,[str]) :
let(
pos = search(sep[i], str),
end = pos==[] ? len(str) : pos[0]
)
_str_split_recurse(
substr(str,end+1),
sep, i+1,
concat(result, [substr(str,0,end)])
);
function _remove_empty_strs(list) =
list_remove(list, search([""], list,0)[0]);
// Returns true if all the characters in the given string are uppercase letters. (A-Z)
function is_upper(s) =
assert(is_string(s))
s==""? false :
len(s)>1? all([for (v=s) is_upper(v)]) :
let(v = ord(s[0])) (v>=ord("A") && v<=ord("Z"));
// _str_cmp(str,sindex,pattern)
// returns true if the string pattern matches the string
// starting at index position sindex in the string.
//
// This is carefully optimized for speed. Precomputing the length
// cuts run time in half when the string is long. Two other string
// comparison methods were slower.
function _str_cmp(str,sindex,pattern) =
len(str)-sindex <len(pattern)? false :
_str_cmp_recurse(str,sindex,pattern,len(pattern));
function _str_cmp_recurse(str,sindex,pattern,plen,pindex=0,) =
pindex < plen && pattern[pindex]==str[sindex] ? _str_cmp_recurse(str,sindex+1,pattern,plen,pindex+1): (pindex==plen);
// Function: str_find()
// Function: is_digit()
// Usage:
// str_find(str,pattern,[last],[all],[start])
// x = is_digit(s);
// Description:
// Searches input string `str` for the string `pattern` and returns the index or indices of the matches in `str`.
// By default `str_find()` returns the index of the first match in `str`. If `last` is true then it returns the index of the last match.
// If the pattern is the empty string the first match is at zero and the last match is the last character of the `str`.
// If `start` is set then the search begins at index start, working either forward and backward from that position. If you set `start`
// and `last` is true then the search will find the pattern if it begins at index `start`. If no match exists, returns `undef`.
// If you set `all` to true then `str_find()` returns all of the matches in a list, or an empty list if there are no matches.
// Arguments:
// str = String to search.
// pattern = string pattern to search for
// last = set to true to return the last match. Default: false
// all = set to true to return all matches as a list. Overrides last. Default: false
// start = index where the search starts
// Example:
// str_find("abc123def123abc","123"); // Returns 3
// str_find("abc123def123abc","b"); // Returns 1
// str_find("abc123def123abc","1234"); // Returns undef
// str_find("abc",""); // Returns 0
// str_find("abc123def123", "123", start=4); // Returns 9
// str_find("abc123def123abc","123",last=true); // Returns 9
// str_find("abc123def123abc","b",last=true); // Returns 13
// str_find("abc123def123abc","1234",last=true); // Returns undef
// str_find("abc","",last=true); // Returns 3
// str_find("abc123def123", "123", start=8, last=true)); // Returns 3
// str_find("abc123def123abc","123",all=true); // Returns [3,9]
// str_find("abc123def123abc","b",all=true); // Returns [1,13]
// str_find("abc123def123abc","1234",all=true); // Returns []
// str_find("abc","",all=true); // Returns [0,1,2]
function str_find(str,pattern,start=undef,last=false,all=false) =
all? _str_find_all(str,pattern) :
let( start = first_defined([start,last?len(str)-len(pattern):0]) )
pattern==""? start :
last? _str_find_last(str,pattern,start) :
_str_find_first(str,pattern,len(str)-len(pattern),start);
function _str_find_first(str,pattern,max_sindex,sindex) =
sindex<=max_sindex && !_str_cmp(str,sindex, pattern)?
_str_find_first(str,pattern,max_sindex,sindex+1) :
(sindex <= max_sindex ? sindex : undef);
function _str_find_last(str,pattern,sindex) =
sindex>=0 && !_str_cmp(str,sindex, pattern)?
_str_find_last(str,pattern,sindex-1) :
(sindex >=0 ? sindex : undef);
function _str_find_all(str,pattern) =
pattern == "" ? count(len(str)) :
[for(i=[0:1:len(str)-len(pattern)]) if (_str_cmp(str,i,pattern)) i];
// Returns true if all the characters in the given string are digits. (0-9)
function is_digit(s) =
assert(is_string(s))
s==""? false :
len(s)>1? all([for (v=s) is_digit(v)]) :
let(v = ord(s[0])) (v>=ord("0") && v<=ord("9"));
// Function: starts_with()
// Function: is_hexdigit()
// Usage:
// starts_with(str,pattern)
// x = is_hexdigit(s);
// Description:
// Returns true if the input string `str` starts with the specified string pattern, `pattern`.
// Otherwise returns false.
// Arguments:
// str = String to search.
// pattern = String pattern to search for.
// Example:
// starts_with("abcdef","abc"); // Returns true
// starts_with("abcdef","def"); // Returns false
// starts_with("abcdef",""); // Returns true
function starts_with(str,pattern) = _str_cmp(str,0,pattern);
// Returns true if all the characters in the given string are valid hexadecimal digits. (0-9 or a-f or A-F))
function is_hexdigit(s) =
assert(is_string(s))
s==""? false :
len(s)>1? all([for (v=s) is_hexdigit(v)]) :
let(v = ord(s[0]))
(v>=ord("0") && v<=ord("9")) ||
(v>=ord("A") && v<=ord("F")) ||
(v>=ord("a") && v<=ord("f"));
// Function: ends_with()
// Function: is_letter()
// Usage:
// ends_with(str,pattern)
// x = is_letter(s);
// Description:
// Returns true if the input string `str` ends with the specified string pattern, `pattern`.
// Otherwise returns false.
// Arguments:
// str = String to search.
// pattern = String pattern to search for.
// Example:
// ends_with("abcdef","def"); // Returns true
// ends_with("abcdef","de"); // Returns false
// ends_with("abcdef",""); // Returns true
function ends_with(str,pattern) = _str_cmp(str,len(str)-len(pattern),pattern);
// Returns true if all the characters in the given string are standard ASCII letters. (A-Z or a-z)
function is_letter(s) =
assert(is_string(s))
s==""? false :
all([for (v=s) is_lower(v) || is_upper(v)]);
function _str_count_leading(s,c,_i=0) =
(_i>=len(s)||!in_list(s[_i],[each c]))? _i :
_str_count_leading(s,c,_i=_i+1);
function _str_count_trailing(s,c,_i=0) =
(_i>=len(s)||!in_list(s[len(s)-1-_i],[each c]))? _i :
_str_count_trailing(s,c,_i=_i+1);
// Function: str_strip_leading()
// Usage:
// str_strip_leading(s,c);
// Description:
// Takes a string `s` and strips off all leading characters that exist in string `c`.
// Arguments:
// s = The string to strip leading characters from.
// c = The string of characters to strip.
// Example:
// str_strip_leading("--##--123--##--","#-"); // Returns: "123--##--"
// str_strip_leading("--##--123--##--","-"); // Returns: "##--123--##--"
// str_strip_leading("--##--123--##--","#"); // Returns: "--##--123--##--"
function str_strip_leading(s,c) = substr(s,pos=_str_count_leading(s,c));
// Function: str_strip_trailing()
// Usage:
// str_strip_trailing(s,c);
// Description:
// Takes a string `s` and strips off all trailing characters that exist in string `c`.
// Arguments:
// s = The string to strip trailing characters from.
// c = The string of characters to strip.
// Example:
// str_strip_trailing("--##--123--##--","#-"); // Returns: "--##--123"
// str_strip_trailing("--##--123--##--","-"); // Returns: "--##--123--##"
// str_strip_trailing("--##--123--##--","#"); // Returns: "--##--123--##--"
function str_strip_trailing(s,c) = substr(s,len=len(s)-_str_count_trailing(s,c));
// Function: str_strip()
// Usage:
// str_strip(s,c);
// Description:
// Takes a string `s` and strips off all leading or trailing characters that exist in string `c`.
// Arguments:
// s = The string to strip leading or trailing characters from.
// c = The string of characters to strip.
// Example:
// str_strip("--##--123--##--","#-"); // Returns: "123"
// str_strip("--##--123--##--","-"); // Returns: "##--123--##"
// str_strip("--##--123--##--","#"); // Returns: "--##--123--##--"
function str_strip(s,c) = str_strip_trailing(str_strip_leading(s,c),c);
// Function: str_pad()
// Usage:
// padded = str_pad(str, length, char, [left]);
// Description:
// Pad the given string `str` with to length `length` with the specified character,
// which must be a length 1 string. If left is true then pad on the left, otherwise
// pad on the right. If the string is longer than the specified length the full string
// is returned unchanged.
// Arguments:
// str = string to pad
// length = length to pad to
// char = character to pad with. Default: " " (space)
// left = if true, pad on the left side. Default: false
function str_pad(str,length,char=" ",left=false) =
assert(is_str(str))
assert(is_str(char) && len(char)==1, "char must be a single character string")
assert(is_bool(left))
let(
padding = str_join(repeat(char,length-len(str)))
)
left ? str(padding,str) : str(str,padding);
// Function: str_replace_char()
// Usage:
// newstr = str_replace_char(str, char, replace)
// Description:
// Replace every occurence of `char` in the input string with the string `replace` which
// can be any string.
function str_replace_char(str,char,replace) =
assert(is_str(str))
assert(is_str(char) && len(char)==1, "Search pattern 'char' must be a single character string")
assert(is_str(replace))
str_join([for(c=str) c==char ? replace : c]);

View file

@ -798,21 +798,59 @@ module test_reindex_polygon() {
module test_align_polygon() {
/*
pentagon = subdivide_path(pentagon(side=2),10);
hexagon = subdivide_path(hexagon(side=2.7),10);
aligned = [[2.7,0],[2.025,-1.16913429511],[1.35,-2.33826859022],
[-1.35,-2.33826859022],[-2.025,-1.16913429511],[-2.7,0],
[-2.025,1.16913429511],[-1.35,2.33826859022],[1.35,2.33826859022],
[2.025,1.16913429511]];
assert_approx(align_polygon(pentagon,hexagon,[0:10:359]), aligned);
aligned2 = [[1.37638192047,0],[1.37638192047,-1],[0.425325404176,-1.30901699437],
[-0.525731112119,-1.61803398875],[-1.11351636441,-0.809016994375],
[-1.7013016167,0],[-1.11351636441,0.809016994375],
[-0.525731112119,1.61803398875],[0.425325404176,1.30901699437],
[1.37638192047,1]];
assert_approx(align_polygon(hexagon,pentagon,[0:10:359]), aligned2);
*/
// These tests fail because align_polygon displays output
/*
ellipse = yscale(3,circle(r=10, $fn=32));
tri = move([-50/3,-9],
subdivide_path([[0,0], [50,0], [0,27]], 32));
aligned = align_polygon(ellipse,tri, [0:5:180]);
assert_approx(aligned,
[[8.6933324366, 2.32937140592], [9.77174512453,
-1.69531953695], [10.8501578125, -5.72001047982],
[11.9285705004, -9.74470142269], [13.0069831883,
-13.7693923656], [9.28126928691, -14.7676943967],
[5.55555538551, -15.7659964278], [1.82984148411,
-16.7642984589], [-1.89587241729, -17.76260049],
[-5.62158631869, -18.7609025211], [-9.34730022009,
-19.7592045522], [-13.0730141215, -20.7575065833],
[-12.0623183481, -16.5048600039], [-11.0516225746,
-12.2522134245], [-10.0409268012, -7.99956684512],
[-9.03023102775, -3.74692026572], [-8.01953525431,
0.505726313678], [-7.00883948087, 4.75837289308],
[-5.99814370744, 9.01101947248], [-4.987447934,
13.2636660519], [-3.97675216056, 17.5163126313],
[-2.96605638713, 21.7689592107], [-1.95536061369,
26.0216057901], [-0.944664840253, 30.2742523695],
[0.0660309331843, 34.5268989489], [1.14444362111,
30.502208006], [2.22285630904, 26.4775170631],
[3.30126899697, 22.4528261203], [4.37968168489,
18.4281351774], [5.45809437282, 14.4034442345],
[6.53650706075, 10.3787532917], [7.61491974867,
6.35406234879]]);
ellipse2 = yscale(2,circle(r=10, $fn=32));
tri2 = subdivide_path([[0,0], [27,0], [-7,50]], 32);
T = [for(x=[-10:0], y=[-30:-15]) move([x,y])];
aligned2 = align_polygon(ellipse2,tri2, trans=T);
assert_approx(aligned2,
[[10.5384615385, -3.61538461538], [13.1538461538,
-7.46153846154], [15.7692307692, -11.3076923077],
[18.3846153846, -15.1538461538], [21, -19],
[17.1428571429, -19], [13.2857142857, -19],
[9.42857142857, -19], [5.57142857143, -19],
[1.71428571429, -19], [-2.14285714286, -19], [-6, -19],
[-6.58333333333, -14.8333333333], [-7.16666666667,
-10.6666666667], [-7.75, -6.5], [-8.33333333333,
-2.33333333333], [-8.91666666667, 1.83333333333], [-9.5,
6], [-10.0833333333, 10.1666666667], [-10.6666666667,
14.3333333333], [-11.25, 18.5], [-11.8333333333,
22.6666666667], [-12.4166666667, 26.8333333333], [-13,
31], [-10.3846153846, 27.1538461538], [-7.76923076923,
23.3076923077], [-5.15384615385, 19.4615384615],
[-2.53846153846, 15.6153846154], [0.0769230769231,
11.7692307692], [2.69230769231, 7.92307692308],
[5.30769230769, 4.07692307692], [7.92307692308,
0.230769230769]]);
*/
}
*test_align_polygon();

View file

@ -29,11 +29,8 @@ test_circle();
module test_rect() {
assert_equal(rect(100,anchor=CENTER), [[50,-50],[-50,-50],[-50,50],[50,50]]);
assert_equal(rect(100), [[50,-50],[-50,-50],[-50,50],[50,50]]);
assert_equal(rect(100,center=false), [[100,0],[0,0],[0,100],[100,100]]);
assert_equal(rect([100,80],center=false), [[100,0],[0,0],[0,80],[100,80]]);
assert_equal(rect([100,80],anchor=CENTER), [[50,-40],[-50,-40],[-50,40],[50,40]]);
assert_equal(rect([100,80]), [[50,-40],[-50,-40],[-50,40],[50,40]]);
assert_equal(rect([100,80],center=true), [[50,-40],[-50,-40],[-50,40],[50,40]]);
assert_equal(rect([100,80],anchor=FRONT+LEFT), [[100,0],[0,0],[0,80],[100,80]]);
assert_equal(rect([100,80],anchor=BACK+RIGHT), [[0,-80],[-100,-80],[-100,0],[0,0]]);
assert_approx(rect([100,80],rounding=10,anchor=CENTER,$fn=12), [[50,-30],[48.6602540378,-35],[45,-38.6602540378],[40,-40],[-40,-40],[-45,-38.6602540378],[-48.6602540378,-35],[-50,-30],[-50,30],[-48.6602540378,35],[-45,38.6602540378],[-40,40],[40,40],[45,38.6602540378],[48.6602540378,35],[50,30]]);

View file

@ -273,34 +273,35 @@ module test_str_strip() {
assert(str_strip("abcdef ", " ") == "abcdef");
assert(str_strip(" abcdef ", " ") == "abcdef");
assert(str_strip(" abcdef ", " ") == "abcdef");
assert(str_strip("abcdef", " ",start=true) == "abcdef");
assert(str_strip(" abcdef", " ",start=true) == "abcdef");
assert(str_strip(" abcdef", " ",start=true) == "abcdef");
assert(str_strip("abcdef ", " ",start=true) == "abcdef ");
assert(str_strip("abcdef ", " ",start=true) == "abcdef ");
assert(str_strip(" abcdef ", " ",start=true) == "abcdef ");
assert(str_strip(" abcdef ", " ",start=true) == "abcdef ");
assert(str_strip("abcdef", " ",end=true) == "abcdef");
assert(str_strip(" abcdef", " ",end=true) == " abcdef");
assert(str_strip(" abcdef", " ",end=true) == " abcdef");
assert(str_strip("abcdef ", " ",end=true) == "abcdef");
assert(str_strip("abcdef ", " ",end=true) == "abcdef");
assert(str_strip(" abcdef ", " ",end=true) == " abcdef");
assert(str_strip(" abcdef ", " ",end=true) == " abcdef");
assert(str_strip("123abc321","12") == "3abc3");
assert(str_strip("123abc321","12",start=true,end=true) == "3abc3");
assert(str_strip("123abc321","12",start=true,end=false) == "3abc321");
assert(str_strip("123abc321","12",start=false,end=false) == "123abc321");
assert(str_strip("123abc321","12",start=false,end=true) == "123abc3");
assert(str_strip("123abc321","12",start=false) == "123abc3");
assert(str_strip("123abc321","12",start=true) == "3abc321");
assert(str_strip("123abc321","12",end=false) == "3abc321");
assert(str_strip("123abc321","12",end=true) == "123abc3");
assert(str_strip("abcde","abcde")=="");
assert(str_strip("","abc")=="");
}
test_str_strip();
module test_str_strip_leading() {
assert(str_strip_leading("abcdef", " ") == "abcdef");
assert(str_strip_leading(" abcdef", " ") == "abcdef");
assert(str_strip_leading(" abcdef", " ") == "abcdef");
assert(str_strip_leading("abcdef ", " ") == "abcdef ");
assert(str_strip_leading("abcdef ", " ") == "abcdef ");
assert(str_strip_leading(" abcdef ", " ") == "abcdef ");
assert(str_strip_leading(" abcdef ", " ") == "abcdef ");
}
test_str_strip_leading();
module test_str_strip_trailing() {
assert(str_strip_trailing("abcdef", " ") == "abcdef");
assert(str_strip_trailing(" abcdef", " ") == " abcdef");
assert(str_strip_trailing(" abcdef", " ") == " abcdef");
assert(str_strip_trailing("abcdef ", " ") == "abcdef");
assert(str_strip_trailing("abcdef ", " ") == "abcdef");
assert(str_strip_trailing(" abcdef ", " ") == " abcdef");
assert(str_strip_trailing(" abcdef ", " ") == " abcdef");
}
test_str_strip_trailing();
module test_substr() {
assert(substr("abcdefg",3,3) == "def");
assert(substr("abcdefg",2) == "cdefg");

View file

@ -408,10 +408,10 @@ module test_apply() {
module check_path_apply(mat,path)
assert_approx(apply(mat,path),path3d([for (p=path) mat*concat(p,1)]));
check_path_apply(xrot(45), path3d(rect(100,center=true)));
check_path_apply(yrot(45), path3d(rect(100,center=true)));
check_path_apply(zrot(45), path3d(rect(100,center=true)));
check_path_apply(rot([20,30,40])*scale([0.9,1.1,1])*move([10,20,30]), path3d(rect(100,center=true)));
check_path_apply(xrot(45), path3d(rect(100)));
check_path_apply(yrot(45), path3d(rect(100)));
check_path_apply(zrot(45), path3d(rect(100)));
check_path_apply(rot([20,30,40])*scale([0.9,1.1,1])*move([10,20,30]), path3d(rect(100)));
module check_patch_apply(mat,patch)
assert_approx(apply(mat,patch), [for (path=patch) path3d([for (p=path) mat*concat(p,1)])]);

View file

@ -33,9 +33,9 @@
// higbee = Length to taper thread ends over. Default: 0
// higbee1 = Length to taper bottom thread end over.
// higbee2 = Length to taper top thread end over.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
// Example(2D):
// projection(cut=true)
@ -127,20 +127,34 @@ module threaded_rod(
// bevel = if true, bevel the thread ends. Default: false
// bevel1 = if true bevel the bottom end.
// bevel2 = if true bevel the top end.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
// Examples(Med):
// threaded_nut(od=16, id=8, h=8, pitch=1.25, $slop=0.05, $fa=1, $fs=1);
// threaded_nut(od=16, id=8, h=8, pitch=1.25, left_handed=true, bevel=true, $slop=0.1, $fa=1, $fs=1);
module threaded_nut(
od, id, h,
pitch, starts=1, left_handed=false, bevel, bevel1, bevel2,
pitch, starts=1, left_handed=false, bevel, bevel1, bevel2, id1,id2,
anchor, spin, orient
) {
depth = pitch * cos(30) * 5/8;
profile = [
dummy1=
assert(all_positive(pitch))
assert(all_positive(id))
assert(all_positive(h));
basic = is_num(id) || is_undef(id) || is_def(id1) || is_def(id2);
dummy2 = assert(basic || is_vector(id,3));
depth = basic ? cos(30) * 5/8
: (id[2] - id[0])/2/pitch;
crestwidth = basic ? 1/8 : 1/2 - (id[2]-id[1])/sqrt(3)/pitch;
profile = [
[-depth/sqrt(3)-crestwidth/2, -depth],
[ -crestwidth/2, 0],
[ crestwidth/2, 0],
[ depth/sqrt(3)+crestwidth/2, -depth]
];
oprofile = [
[-6/16, -depth/pitch],
[-1/16, 0],
[-1/32, 0.02],
@ -149,7 +163,9 @@ module threaded_nut(
[ 6/16, -depth/pitch]
];
generic_threaded_nut(
od=od, id=id, h=h,
od=od,
id=basic ? id : id[2], id1=id1, id2=id2,
h=h,
pitch=pitch,
profile=profile,starts=starts,
left_handed=left_handed,
@ -215,9 +231,9 @@ module threaded_nut(
// higbee1 = Length to taper bottom thread end over.
// higbee2 = Length to taper top thread end over.
// center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=UP`.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
// Example(2D):
// projection(cut=true)
@ -290,9 +306,9 @@ module trapezoidal_threaded_rod(
// bevel = if true, bevel the thread ends. Default: false
// bevel1 = if true bevel the bottom end.
// bevel2 = if true bevel the top end.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
// Examples(Med):
// trapezoidal_threaded_nut(od=16, id=8, h=8, pitch=2, $slop=0.1, anchor=UP);
@ -351,9 +367,9 @@ module trapezoidal_threaded_nut(
// higbee = Length to taper thread ends over. Default: 0 (No higbee thread tapering)
// higbee1 = Length to taper bottom thread end over.
// higbee2 = Length to taper top thread end over.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
// Example(2D):
// projection(cut=true)
@ -402,9 +418,9 @@ module acme_threaded_rod(
// bevel = if true, bevel the thread ends. Default: false
// bevel1 = if true bevel the bottom end.
// bevel2 = if true bevel the top end.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
// Examples(Med):
// acme_threaded_nut(od=16, id=3/8*INCH, h=8, tpi=8, $slop=0.05);
@ -452,9 +468,9 @@ module acme_threaded_nut(
// bevel2 = if true bevel the top end.
// hollow = If true, create a pipe with the correct internal diameter.
// internal = If true, make this a mask for making internal threads.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.p
// Example(2D): The straight gray rectangle reveals the tapered threads.
// projection(cut=true) npt_threaded_rod(size=1/4, orient=BACK);
@ -566,9 +582,9 @@ module npt_threaded_rod(
// higbee2 = Length to taper top thread end over.
// d1 = Bottom outside diameter of threads.
// d2 = Top outside diameter of threads.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
// Example(2D):
// projection(cut=true)
@ -626,9 +642,9 @@ module buttress_threaded_rod(
// bevel = if true, bevel the thread ends. Default: false
// bevel1 = if true bevel the bottom end.
// bevel2 = if true bevel the top end.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
// Examples(Med):
// buttress_threaded_nut(od=16, id=8, h=8, pitch=1.25, left_handed=true, $slop=0.05, $fa=1, $fs=1);
@ -681,9 +697,9 @@ module buttress_threaded_nut(
// higbee2 = Length to taper top thread end over.
// d1 = Bottom outside diameter of threads.
// d2 = Top outside diameter of threads.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
// Example(2D):
// projection(cut=true)
@ -734,9 +750,9 @@ module square_threaded_rod(
// bevel1 = if true bevel the bottom end.
// bevel2 = if true bevel the top end.
// starts = The number of lead starts. Default = 1
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
// Examples(Med):
// square_threaded_nut(od=16, id=10, h=10, pitch=2, starts=2, $slop=0.1, $fn=32);
@ -780,9 +796,9 @@ module square_threaded_nut(
// bevel1 = if true bevel the bottom end.
// bevel2 = if true bevel the top end.
// internal = If true, make this a mask for making internal threads.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
// Example(2D): Thread Profile, ball_diam=4, ball_arc=100
// projection(cut=true) ball_screw_rod(d=10, l=15, pitch=5, ball_diam=4, ball_arc=100, orient=BACK, $fn=24);
@ -866,9 +882,9 @@ module ball_screw_rod(
// higbee1 = Angle to taper bottom thread end over.
// higbee2 = Angle to taper top thread end over.
// center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=UP`.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
// Example(2DMed): Example Tooth Profile
// pitch = 2;
@ -1062,9 +1078,9 @@ module generic_threaded_rod(
// bevel2 = if true bevel the top end.
// id1 = inner diameter at the bottom
// id2 = inner diameter at the top
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
module generic_threaded_nut(
od,
@ -1149,9 +1165,9 @@ module generic_threaded_nut(
// higbee = Length to taper thread ends over. Default: 0
// higbee1 = Length to taper bottom thread end over.
// higbee2 = Length to taper top thread end over.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Example(2DMed): Typical Tooth Profile
// pitch = 2;
// depth = pitch * cos(30) * 5/8;

View file

@ -749,7 +749,10 @@ function _slice_3dpolygons(polys, dir, cuts) =
)
flatten([for (poly = polys)
let(
plane = plane_from_polygon(poly),
plane = plane_from_polygon(poly)
)
assert(plane,"Found non-coplanar face.")
let(
normal = point3d(plane),
pnormal = normal - (normal*I[dir_ind])*I[dir_ind]
)
@ -787,9 +790,9 @@ function _slice_3dpolygons(polys, dir, cuts) =
// convexity = Max number of times a line could intersect a wall of the shape.
// extent = If true, calculate anchors by extents, rather than intersection. Default: true.
// cp = Centerpoint for determining intersection anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid"
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `"origin"`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `"origin"`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// atype = Select "hull" or "intersect" anchor type. Default: "hull"
module vnf_polyhedron(vnf, convexity=2, extent=true, cp="centroid", anchor="origin", spin=0, orient=UP, atype="hull") {
vnf = is_vnf_list(vnf)? vnf_join(vnf) : vnf;

View file

@ -28,9 +28,9 @@
// l = Length of the strut.
// wall = height of rectangular portion of the strut.
// ang = angle that the trianglar side will converge at.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// Example:
// narrowing_strut(w=10, l=100, wall=5, ang=30);
@ -75,9 +75,9 @@ module narrowing_strut(w=10, l=100, wall=5, ang=30, anchor=BOTTOM, spin=0, orien
// ang = Maximum overhang angle of diagonal brace.
// braces = If true, adds diagonal crossbraces for strength.
// strut = The width of the borders and diagonal braces. Default: `thick/2`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// Example: Typical Shape
// thinning_wall(h=50, l=80, thick=4);
@ -254,9 +254,9 @@ module thinning_wall(h=50, l=100, thick=5, ang=30, braces=false, strut, wall, an
// wall = the thickness of the thinned portion of the wall.
// diagonly = boolean, which denotes only the diagonal side (hypotenuse) should be thick.
// center = If true, centers shape. If false, overrides `anchor` with `UP+BACK`.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// Example: Centered
// thinning_triangle(h=50, l=80, thick=4, ang=30, strut=5, wall=2, center=true);
@ -314,9 +314,9 @@ module thinning_triangle(h=50, l=100, thick=5, ang=30, strut=5, wall=3, diagonly
// maxang = maximum overhang angle of cross-braces.
// max_bridge = maximum bridging distance between cross-braces.
// strut = the width of the cross-braces.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// Example: Typical Shape
// sparse_strut(h=40, l=100, thick=3);
@ -383,9 +383,9 @@ module sparse_strut(h=50, l=100, thick=4, maxang=30, strut=5, max_bridge=20, anc
// maxang = maximum overhang angle of cross-braces.
// max_bridge = maximum bridging distance between cross-braces.
// strut = the width of the cross-braces.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// Example(Med): Typical Shape
// sparse_strut3d(h=30, w=30, l=100);
@ -480,9 +480,9 @@ module sparse_strut3d(h=50, l=100, w=50, thick=3, maxang=40, strut=3, max_bridge
// thick = thickness of strut wall.
// strut = the width of the cross-braces.
// wall = thickness of corrugations.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// Example: Typical Shape
// corrugated_wall(h=50, l=100);