1include <BOSL/constants.scad>
  2use <BOSL/transforms.scad>
  3use <BOSL/beziers.scad>
  4use <BOSL/math.scad>
  5
  6
  7function CR_corner(size, orient=[0,0,0], trans=[0,0,0]) =
  8	let (
  9		r = 0.4,
 10		k = r/2,
 11		// I know this patch is not yet correct for continuous
 12		// rounding, but it's a first approximation proof of concept.
 13		// Currently this is a degree 4 triangular patch.
 14		patch = [
 15			[[0,1,1], [0,r,1], [0,0,1], [r,0,1], [1,0,1]],
 16			[[0,1,r], [0,k,k], [k,0,k], [1,0,r]],
 17			[[0,1,0], [k,k,0], [1,0,0]],
 18			[[r,1,0], [1,r,0]],
 19			[[1,1,0]]
 20		]
 21	) [for (row=patch)
 22		translate_points(v=trans,
 23			rotate_points3d(v=orient,
 24				scale_points(v=size, row)
 25			)
 26		)
 27	];
 28
 29
 30function CR_edge(size, orient=[0,0,0], trans=[0,0,0]) =
 31	let (
 32		r = 0.4,
 33		a = -1/2,
 34		b = -1/4,
 35		c =  1/4,
 36		d =  1/2,
 37		// I know this patch is not yet correct for continuous
 38		// rounding, but it's a first approximation proof of concept.
 39		// Currently this is a degree 4 rectangular patch.
 40		patch = [
 41			[[1,0,a], [1,0,b], [1,0,0], [1,0,c], [1,0,d]],
 42			[[r,0,a], [r,0,b], [r,0,0], [r,0,c], [r,0,d]],
 43			[[0,0,a], [0,0,b], [0,0,0], [0,0,c], [0,0,d]],
 44			[[0,r,a], [0,r,b], [0,r,0], [0,r,c], [0,r,d]],
 45			[[0,1,a], [0,1,b], [0,1,0], [0,1,c], [0,1,d]]
 46		]
 47	) [for (row=patch)
 48		translate_points(v=trans,
 49			rotate_points3d(v=orient,
 50				scale_points(v=size, row)
 51			)
 52		)
 53	];
 54
 55
 56module CR_cube(size=[100,100,100], r=10, splinesteps=8, cheat=false)
 57{
 58	s = size-2*[r,r,r];
 59	h = size/2;
 60	corners = [
 61		CR_corner([r,r,r], orient=ORIENT_Z,     trans=[-size.x/2, -size.y/2, -size.z/2]),
 62		CR_corner([r,r,r], orient=ORIENT_Z_90,  trans=[ size.x/2, -size.y/2, -size.z/2]),
 63		CR_corner([r,r,r], orient=ORIENT_Z_180, trans=[ size.x/2,  size.y/2, -size.z/2]),
 64		CR_corner([r,r,r], orient=ORIENT_Z_270, trans=[-size.x/2,  size.y/2, -size.z/2]),
 65
 66		CR_corner([r,r,r], orient=ORIENT_ZNEG,     trans=[ size.x/2, -size.y/2,  size.z/2]),
 67		CR_corner([r,r,r], orient=ORIENT_ZNEG_90,  trans=[-size.x/2, -size.y/2,  size.z/2]),
 68		CR_corner([r,r,r], orient=ORIENT_ZNEG_180, trans=[-size.x/2,  size.y/2,  size.z/2]),
 69		CR_corner([r,r,r], orient=ORIENT_ZNEG_270, trans=[ size.x/2,  size.y/2,  size.z/2])
 70	];
 71	edges = [
 72		CR_edge([r, r, s.x], orient=ORIENT_X,     trans=[   0, -h.y, -h.z]),
 73		CR_edge([r, r, s.x], orient=ORIENT_X_90,  trans=[   0,  h.y, -h.z]),
 74		CR_edge([r, r, s.x], orient=ORIENT_X_180, trans=[   0,  h.y,  h.z]),
 75		CR_edge([r, r, s.x], orient=ORIENT_X_270, trans=[   0, -h.y,  h.z]),
 76
 77		CR_edge([r, r, s.y], orient=ORIENT_Y,     trans=[ h.x,    0, -h.z]),
 78		CR_edge([r, r, s.y], orient=ORIENT_Y_90,  trans=[-h.x,    0, -h.z]),
 79		CR_edge([r, r, s.y], orient=ORIENT_Y_180, trans=[-h.x,    0,  h.z]),
 80		CR_edge([r, r, s.y], orient=ORIENT_Y_270, trans=[ h.x,    0,  h.z]),
 81
 82		CR_edge([r, r, s.z], orient=ORIENT_Z,     trans=[-h.x, -h.y,    0]),
 83		CR_edge([r, r, s.z], orient=ORIENT_Z_90,  trans=[ h.x, -h.y,    0]),
 84		CR_edge([r, r, s.z], orient=ORIENT_Z_180, trans=[ h.x,  h.y,    0]),
 85		CR_edge([r, r, s.z], orient=ORIENT_Z_270, trans=[-h.x,  h.y,    0])
 86	];
 87	faces = [
 88		// Yes, these are degree 1 bezier patches.  That means just the four corner points.
 89		// Since these are flat, it doesn't matter what degree they are, and this will reduce calculation overhead.
 90		bezier_patch_flat([s.y, s.z], N=1, orient=ORIENT_X,    trans=[ h.x,    0,    0]),
 91		bezier_patch_flat([s.y, s.z], N=1, orient=ORIENT_XNEG, trans=[-h.x,    0,    0]),
 92
 93		bezier_patch_flat([s.x, s.z], N=1, orient=ORIENT_Y,    trans=[   0,  h.y,    0]),
 94		bezier_patch_flat([s.x, s.z], N=1, orient=ORIENT_YNEG, trans=[   0, -h.y,    0]),
 95
 96		bezier_patch_flat([s.x, s.y], N=1, orient=ORIENT_Z,    trans=[   0,    0,  h.z]),
 97		bezier_patch_flat([s.x, s.y], N=1, orient=ORIENT_ZNEG, trans=[   0,    0, -h.z])
 98	];
 99	// Generating all the patches above took about 0.05 secs.
100
101	if (cheat) {
102		// Hulling just the corners takes less than a second.
103		hull() bezier_polyhedron(tris=corners, splinesteps=splinesteps);
104	} else {
105		// Generating the polyhedron fully from bezier patches takes 3 seconds on my laptop.
106		bezier_polyhedron(patches=concat(edges, faces), tris=corners, splinesteps=splinesteps);
107	}
108}
109
110
111CR_cube(size=[100,100,100], r=20, splinesteps=9, cheat=false);
112cube(1);
113
114
115
116// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap