2019-04-17 02:16:50 +00:00
//////////////////////////////////////////////////////////////////////
// LibFile: primitives.scad
// The basic built-in shapes, reworked to integrate better with
2019-04-19 06:45:46 +00:00
// other BOSL2 library shapes and utilities.
2019-04-17 02:16:50 +00:00
// To use, add the following lines to the beginning of your file:
// ```
2019-04-19 07:25:10 +00:00
// include <BOSL2/std.scad>
2019-04-17 02:16:50 +00:00
// ```
//////////////////////////////////////////////////////////////////////
2019-04-24 02:13:43 +00:00
// Section: 2D Primitives
2019-05-27 04:14:22 +00:00
// Function&Module: square()
2019-04-24 02:13:43 +00:00
// Usage:
// square(size, [center], [anchor])
// Description:
2020-01-29 09:09:39 +00:00
// When called as a module, creates a 2D square of the given size, with optional rounding or chamferring.
2019-05-27 04:14:22 +00:00
// When called as a function, returns a 2D path/list of points for a square/rectangle of the given size.
2019-04-24 02:13:43 +00:00
// Arguments:
// size = The size of the square to create. If given as a scalar, both X and Y will be the same size.
2020-01-29 09:09:39 +00:00
// 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)
2019-04-24 02:13:43 +00:00
// center = If given and true, overrides `anchor` to be `CENTER`. If given and false, overrides `anchor` to be `FRONT+LEFT`.
2019-05-26 19:47:50 +00:00
// 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`
2019-04-24 10:33:22 +00:00
// Example(2D):
// square(40);
// Example(2D): Centered
// square([40,30], center=true);
2019-12-27 05:43:42 +00:00
// Example(2D): Anchored
2019-04-24 10:33:22 +00:00
// square([40,30], anchor=FRONT);
2019-12-27 05:43:42 +00:00
// Example(2D): Spun
2019-05-27 04:44:28 +00:00
// square([40,30], anchor=FRONT, spin=30);
2019-12-27 05:43:42 +00:00
// Example(2D): Chamferred Rect
2019-12-27 05:49:05 +00:00
// square([40,30], chamfer=5, center=true);
2019-12-27 05:43:42 +00:00
// Example(2D): Rounded Rect
2019-12-27 05:49:05 +00:00
// square([40,30], rounding=5, center=true);
2020-01-29 09:09:39 +00:00
// Example(2D): Mixed Chamferring and Rounding
// square([40,30],center=true,rounding=[5,0,10,0],chamfer=[0,8,0,15],$fa=1,$fs=1);
2019-12-27 05:43:42 +00:00
// Example(2D): Called as Function
// path = square([40,30], chamfer=5, anchor=FRONT, spin=30);
// stroke(path, closed=true);
2019-12-27 21:37:22 +00:00
// place_copies(path) color("blue") circle(d=2,$fn=8);
2019-12-27 05:43:42 +00:00
module square ( size = 1 , rounding = 0 , chamfer = 0 , center , anchor = FRONT + LEFT , spin = 0 ) {
2019-04-24 02:13:43 +00:00
size = is_num ( size ) ? [ size , size ] : point2d ( size ) ;
2019-12-27 05:43:42 +00:00
pts = square ( size = size , rounding = rounding , center = false , chamfer = chamfer ) ;
2019-05-26 06:31:05 +00:00
orient_and_anchor ( point3d ( size ) , UP , anchor , spin = spin , center = center , noncentered = FRONT + LEFT , two_d = true , chain = true ) {
2019-08-08 23:25:07 +00:00
translate ( - size / 2 ) polygon ( pts ) ;
2019-04-24 02:13:43 +00:00
children ( ) ;
}
}
2019-11-03 23:02:49 +00:00
2019-12-27 05:43:42 +00:00
function square ( size = 1 , rounding = 0 , chamfer = 0 , center , anchor = FRONT + LEFT , spin = 0 ) =
2020-01-29 09:09:39 +00:00
assert ( is_num ( chamfer ) || len ( chamfer ) = = 4 )
assert ( is_num ( rounding ) || len ( rounding ) = = 4 )
2019-05-27 04:14:22 +00:00
let (
2020-01-29 09:09:39 +00:00
chamfer = is_list ( chamfer ) ? chamfer : [ for ( i = [ 0 : 3 ] ) chamfer ] ,
rounding = is_list ( rounding ) ? rounding : [ for ( i = [ 0 : 3 ] ) rounding ] ,
2019-06-17 06:53:59 +00:00
anchor = center = = true ? CENTER : center = = false ? FRONT + LEFT : anchor ,
2019-05-27 04:14:22 +00:00
size = is_num ( size ) ? [ size , size ] : point2d ( size ) ,
2020-01-29 09:09:39 +00:00
quadorder = [ 3 , 2 , 1 , 0 ] ,
quadpos = [ [ 1 , 1 ] , [ - 1 , 1 ] , [ - 1 , - 1 ] , [ 1 , - 1 ] ] ,
insets = [ for ( i = [ 0 : 3 ] ) chamfer [ i ] > 0 ? chamfer [ i ] : rounding [ i ] > 0 ? rounding [ i ] : 0 ] ,
insets_x = max ( insets [ 0 ] + insets [ 1 ] , insets [ 2 ] + insets [ 3 ] ) ,
insets_y = max ( insets [ 0 ] + insets [ 3 ] , insets [ 1 ] + insets [ 2 ] )
)
assert ( insets_x < = size . x , "Requested roundings and/or chamfers exceed the square width." )
assert ( insets_y < = size . y , "Requested roundings and/or chamfers exceed the square height." )
let (
path = [
for ( i = [ 0 : 3 ] )
let (
quad = quadorder [ i ] ,
inset = insets [ quad ] ,
cverts = quant ( segs ( inset ) , 4 ) / 4 ,
cp = vmul ( size / 2 - [ inset , inset ] , quadpos [ quad ] ) ,
step = 90 / cverts ,
angs =
chamfer [ quad ] > 0 ? [ 0 , - 90 ] - 90 * [ i , i ] :
rounding [ quad ] > 0 ? [ for ( j = [ 0 : 1 : cverts ] ) 360 - j * step - i * 90 ] :
[ 0 ]
)
each [ for ( a = angs ) cp + inset * [ cos ( a ) , sin ( a ) ] ]
]
) rot ( spin , p = move ( - vmul ( anchor , size / 2 ) , p = path ) ) ;
2019-04-24 02:13:43 +00:00
2019-05-27 04:14:22 +00:00
// Function&Module: circle()
2019-04-24 02:13:43 +00:00
// Usage:
// circle(r|d, [anchor])
// Description:
2019-11-04 02:44:14 +00:00
// When called as a module, creates a 2D polygon that approximates a circle of the given size.
// When called as a function, returns a 2D list of points (path) for a polygon that approximates a circle of the given size.
2019-04-24 02:13:43 +00:00
// Arguments:
// r = The radius of the circle to create.
// d = The diameter of the circle to create.
2019-11-04 02:44:14 +00:00
// realign = If true, rotates the polygon that approximates the circle by half of one size.
// 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
2019-05-26 19:47:50 +00:00
// 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`
2019-04-24 10:33:22 +00:00
// Example(2D): By Radius
// circle(r=25);
// Example(2D): By Diameter
// circle(d=50);
// Example(2D): Anchoring
// circle(d=50, anchor=FRONT);
2019-05-27 04:44:28 +00:00
// Example(2D): Spin
// circle(d=50, anchor=FRONT, spin=45);
// Example(NORENDER): Called as Function
// path = circle(d=50, anchor=FRONT, spin=45);
2019-11-24 02:23:04 +00:00
module circle ( r , d , realign = false , circum = false , anchor = CENTER , spin = 0 ) {
2019-04-24 02:13:43 +00:00
r = get_radius ( r = r , d = d , dflt = 1 ) ;
sides = segs ( r ) ;
2019-11-04 02:44:14 +00:00
rr = circum ? r / cos ( 180 / sides ) : r ;
pts = circle ( r = rr , realign = realign , $fn = sides ) ;
orient_and_anchor ( [ 2 * rr , 2 * rr , 0 ] , UP , anchor , spin = spin , geometry = "cylinder" , two_d = true , chain = true ) {
2019-04-24 02:13:43 +00:00
polygon ( pts ) ;
children ( ) ;
}
}
2019-11-24 02:23:04 +00:00
function circle ( r , d , realign = false , circum = false , anchor = CENTER , spin = 0 ) =
2019-05-27 04:14:22 +00:00
let (
r = get_radius ( r = r , d = d , dflt = 1 ) ,
sides = segs ( r ) ,
2019-11-04 02:44:14 +00:00
offset = realign ? 180 / sides : 0 ,
rr = r / ( circum ? cos ( 180 / sides ) : 1 ) ,
pts = [ for ( i = [ 0 : 1 : sides - 1 ] ) let ( a = 360 - offset - i * 360 / sides ) rr * [ cos ( a ) , sin ( a ) ] ]
) rot ( spin , p = move ( - normalize ( anchor ) * rr , p = pts ) ) ;
2019-05-27 04:14:22 +00:00
2019-04-24 02:13:43 +00:00
2020-01-15 22:18:11 +00:00
// Section: Primitive 3D Shapes
2019-04-17 02:16:50 +00:00
// Module: cube()
//
// Description:
2019-04-23 03:55:03 +00:00
// Creates a cube object, with support for anchoring and attachments.
2019-04-17 02:16:50 +00:00
// This is a drop-in replacement for the built-in `cube()` module.
//
// Arguments:
// size = The size of the cube.
2019-11-24 02:23:04 +00:00
// center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=ALLNEG`.
2019-05-26 19:47:50 +00:00
// 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`
2019-04-17 02:16:50 +00:00
//
2019-05-26 06:31:05 +00:00
// Example: Simple cube.
2019-04-17 02:16:50 +00:00
// cube(40);
2019-04-22 08:08:41 +00:00
// Example: Rectangular cube.
2019-05-27 04:44:28 +00:00
// cube([20,40,50]);
// Example: Anchoring.
// cube([20,40,50], anchor=BOTTOM+FRONT);
// Example: Spin.
// cube([20,40,50], anchor=BOTTOM+FRONT, spin=30);
// Example: Orientation.
// cube([20,40,50], anchor=BOTTOM+FRONT, spin=30, orient=FWD);
2019-04-22 08:08:41 +00:00
// Example: Standard Connectors.
2019-04-23 03:55:03 +00:00
// cube(40, center=true) show_anchors();
2019-11-24 02:23:04 +00:00
module cube ( size = 1 , center , anchor = ALLNEG , spin = 0 , orient = UP )
2019-04-17 02:16:50 +00:00
{
size = scalar_vec3 ( size ) ;
2019-05-26 06:31:05 +00:00
orient_and_anchor ( size , orient , anchor , center , spin = spin , noncentered = ALLNEG , chain = true ) {
2019-04-17 02:16:50 +00:00
linear_extrude ( height = size . z , convexity = 2 , center = true ) {
square ( [ size . x , size . y ] , center = true ) ;
}
children ( ) ;
}
}
// Module: cylinder()
// Usage:
2019-05-26 20:45:22 +00:00
// cylinder(h, r|d, [center]);
// cylinder(h, r1/d1, r2/d2, [center]);
2019-04-17 02:16:50 +00:00
// Description:
2019-04-23 03:55:03 +00:00
// Creates a cylinder object, with support for anchoring and attachments.
2019-04-17 02:16:50 +00:00
// This is a drop-in replacement for the built-in `cylinder()` module.
// Arguments:
// l / h = The height of the cylinder.
// r1 = The bottom radius of the cylinder. (Before orientation.)
// r2 = The top radius of the cylinder. (Before orientation.)
2019-11-24 02:23:04 +00:00
// center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=BOTTOM`.
2019-04-17 02:16:50 +00:00
// d1 = The bottom diameter of the cylinder. (Before orientation.)
// d2 = The top diameter of the cylinder. (Before orientation.)
2019-11-24 02:23:04 +00:00
// r = The radius of the cylinder.
// d = The diameter of the cylinder.
2019-05-26 19:47:50 +00:00
// 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`
2019-04-17 02:16:50 +00:00
// Example: By Radius
// xdistribute(30) {
// cylinder(h=40, r=10);
// cylinder(h=40, r1=10, r2=5);
// }
// Example: By Diameter
// xdistribute(30) {
// cylinder(h=40, d=25);
// cylinder(h=40, d1=25, d2=10);
// }
2019-05-27 04:44:28 +00:00
// Example(Med): Anchoring
// cylinder(h=40, r1=10, r2=5, anchor=BOTTOM+FRONT);
// Example(Med): Spin
// cylinder(h=40, r1=10, r2=5, anchor=BOTTOM+FRONT, spin=45);
// Example(Med): Orient
// cylinder(h=40, r1=10, r2=5, anchor=BOTTOM+FRONT, spin=45, orient=FWD);
// Example(Big): Standard Connectors
2019-04-22 08:08:41 +00:00
// xdistribute(40) {
2019-04-23 03:55:03 +00:00
// cylinder(h=30, d=25) show_anchors();
// cylinder(h=30, d1=25, d2=10) show_anchors();
2019-04-22 08:08:41 +00:00
// }
2019-11-24 02:23:04 +00:00
module cylinder ( h , r1 , r2 , center , l , r , d , d1 , d2 , anchor = BOTTOM , spin = 0 , orient = UP )
2019-04-17 02:16:50 +00:00
{
r1 = get_radius ( r1 = r1 , r = r , d1 = d1 , d = d , dflt = 1 ) ;
r2 = get_radius ( r1 = r2 , r = r , d1 = d2 , d = d , dflt = 1 ) ;
2019-10-24 05:52:42 +00:00
l = first_defined ( [ h , l , 1 ] ) ;
2019-06-20 06:33:33 +00:00
hh = l / 2 ;
2019-04-17 02:16:50 +00:00
sides = segs ( max ( r1 , r2 ) ) ;
size = [ r1 * 2 , r1 * 2 , l ] ;
2019-06-20 06:33:33 +00:00
path = [ [ 0 , hh ] , [ r2 , hh ] , [ r1 , - hh ] , [ 0 , - hh ] ] ;
2019-05-26 06:31:05 +00:00
orient_and_anchor ( size , orient , anchor , center , spin = spin , size2 = [ r2 * 2 , r2 * 2 ] , noncentered = BOTTOM , geometry = "cylinder" , chain = true ) {
2019-06-12 04:47:48 +00:00
rotate_extrude ( convexity = 2 , $fn = sides ) {
2019-06-20 06:33:33 +00:00
polygon ( path ) ;
2019-04-17 02:16:50 +00:00
}
children ( ) ;
}
}
// Module: sphere()
// Usage:
2019-05-26 20:45:22 +00:00
// sphere(r|d)
2019-04-17 02:16:50 +00:00
// Description:
2019-04-23 03:55:03 +00:00
// Creates a sphere object, with support for anchoring and attachments.
2019-04-17 02:16:50 +00:00
// This is a drop-in replacement for the built-in `sphere()` module.
// Arguments:
// r = Radius of the sphere.
// d = Diameter of the sphere.
2019-05-26 19:47:50 +00:00
// 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`
2019-04-22 08:08:41 +00:00
// Example: By Radius
// sphere(r=50);
// Example: By Diameter
// sphere(d=100);
2019-05-27 04:44:28 +00:00
// Example: Anchoring
// sphere(d=100, anchor=FRONT);
// Example: Spin
// sphere(d=100, anchor=FRONT, spin=45);
// Example: Orientation
// sphere(d=100, anchor=FRONT, spin=45, orient=FWD);
2019-04-22 08:08:41 +00:00
// Example: Standard Connectors
2019-04-23 03:55:03 +00:00
// sphere(d=50) show_anchors();
2019-11-24 02:23:04 +00:00
module sphere ( r , d , anchor = CENTER , spin = 0 , orient = UP )
2019-04-17 02:16:50 +00:00
{
r = get_radius ( r = r , d = d , dflt = 1 ) ;
sides = segs ( r ) ;
size = [ r * 2 , r * 2 , r * 2 ] ;
2019-05-26 06:31:05 +00:00
orient_and_anchor ( size , orient , anchor , spin = spin , geometry = "sphere" , chain = true ) {
2019-04-17 02:16:50 +00:00
rotate_extrude ( convexity = 2 ) {
difference ( ) {
circle ( r = r , $fn = sides ) ;
left ( r + 0.1 ) square ( r * 2 + 0.2 , center = true ) ;
}
}
children ( ) ;
}
}
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap