def create_rendered_obj_if_needed(self, openSCADObj, **kw): need_create_obj = False scad_str = None if DEBUG: print('create_rendered kw:', kw) if 'outfile' in kw: need_create_obj = True if not hasattr(openSCADObj, 'rendered_object'): if DEBUG: print( 'OpenSCADObject does not have a rendered_object, need to create.' ) need_create_obj = True else: scad_str = solid.scad_render(openSCADObj) digest = self._get_digest(scad_str) if digest != openSCADObj.rendered_object.scad_digest: if DEBUG: print( 'OpenSCADObject.rendered_object digest does not match, need to recreate.' ) need_create_obj = True if need_create_obj: if scad_str is None: scad_str = solid.scad_render(openSCADObj) rend_obj = self.render_openscad_str(scad_str, **kw) if rend_obj is not None: openSCADObj.rendered_object = rend_obj openSCADObj.rendered_object.scad_digest = self._get_digest( scad_str) else: if hasattr(openSCADObj, 'rendered_object'): delattr(openSCADObj, 'rendered_object')
def genScadSource(name, vectors, spieces, bonds, lFact=1, r=1, bondR=None, bondSpacingFactor=3): if not bondR: bondR = 0.05 * r spiecesDescr = {el: mendeleev.element(el) for el in spieces} maxRad = max((sp.covalent_radius for sp in spiecesDescr.values())) def createElementCall(name, el): class element(sld.OpenSCADObject): def __init__(self, pos): sld.OpenSCADObject.__init__(self, el.name, {"pos": pos}) element.__name__ = el.name return element elToScadRemap = { elN: createElementCall(elN, sp) for elN, sp in spiecesDescr.items() } spiecesChem = [spiecesDescr[el] for el in spieces] spiecesScad = [elToScadRemap[el] for el in spieces] def createElementModule(name, sp): elModSrc = "module " + sp.name + "(pos=[0,0,0]){" + useOpenScadVariable( sld.translate("%%%positionExprPlaceholder%%%")(sld.color( convertWebColorToOpenScad(sp.cpk_color))(sld.sphere( r * sp.covalent_radius / maxRad))), {"%%%positionExprPlaceholder%%%": "pos*lFact"}) + "\n}" return elModSrc src = [ "$fs=0.1;", "r=" + str(r) + ";", "bondR=" + str(bondR) + ";", "lFact=" + str(lFact) + ";", "bondSpacingFactor=" + str(bondSpacingFactor) + ";", "include <./util.scad>", ] src.extend( (createElementModule(elN, sp) for elN, sp in spiecesDescr.items())) for i, v in enumerate(vectors): src.append(sld.scad_render(spiecesScad[i](v))) for i, (a1, a2, mult) in enumerate(bonds): src.append( sld.scad_render( makeBond(vectors[a1], vectors[a2], spiecesChem[a1].cpk_color, spiecesChem[a2].cpk_color, mult))) return src
def main(): parser = argparse.ArgumentParser() parser.add_argument("--slice", type=int) parser.add_argument("-s", "--sub-scaffold", action="store_true") args = parser.parse_args() if args.slice is not None: sl = single_slice(args.slice) if args.sub_scaffold: sl = sl - scaffold(mdf_strength) preamble() print solid.scad_render(sl) else: preamble() print solid.scad_render(full_cone() - scaffold(cone_length))
def test(d1, d2, c, h): disc = solid.cylinder(h=h, d=d2 + 3) cuts = fret1(d1, d2, c, h + FIDDLE * 2) t = solid.difference()(disc, solid.translate((0, 0, -FIDDLE))(cuts)) pf = pathlib.Path('scadout/test.scad') with pf.open('w') as pfo: pfo.write(solid.scad_render(t))
def test_split_body_planar(self): offset = [10, 10, 10] body = translate(offset)(sphere(20)) body_bb = BoundingBox([40, 40, 40], offset) actual = [] for split_dir in [RIGHT_VEC, FORWARD_VEC, UP_VEC]: actual_tuple = split_body_planar(body, body_bb, cutting_plane_normal=split_dir, cut_proportion=0.25) actual.append(actual_tuple) # Ignore the bounding box object that come back, taking only the SCAD # objects actual = [scad_render(a) for splits in actual for a in splits[::2]] expected = [ '\n\nintersection() {\n\ttranslate(v = [10, 10, 10]) {\n\t\tsphere(r = 20);\n\t}\n\ttranslate(v = [-5.0000000000, 10, 10]) {\n\t\tcube(center = true, size = [10.0000000000, 40, 40]);\n\t}\n}', '\n\nintersection() {\n\ttranslate(v = [10, 10, 10]) {\n\t\tsphere(r = 20);\n\t}\n\ttranslate(v = [15.0000000000, 10, 10]) {\n\t\tcube(center = true, size = [30.0000000000, 40, 40]);\n\t}\n}', '\n\nintersection() {\n\ttranslate(v = [10, 10, 10]) {\n\t\tsphere(r = 20);\n\t}\n\ttranslate(v = [10, -5.0000000000, 10]) {\n\t\tcube(center = true, size = [40, 10.0000000000, 40]);\n\t}\n}', '\n\nintersection() {\n\ttranslate(v = [10, 10, 10]) {\n\t\tsphere(r = 20);\n\t}\n\ttranslate(v = [10, 15.0000000000, 10]) {\n\t\tcube(center = true, size = [40, 30.0000000000, 40]);\n\t}\n}', '\n\nintersection() {\n\ttranslate(v = [10, 10, 10]) {\n\t\tsphere(r = 20);\n\t}\n\ttranslate(v = [10, 10, -5.0000000000]) {\n\t\tcube(center = true, size = [40, 40, 10.0000000000]);\n\t}\n}', '\n\nintersection() {\n\ttranslate(v = [10, 10, 10]) {\n\t\tsphere(r = 20);\n\t}\n\ttranslate(v = [10, 10, 15.0000000000]) {\n\t\tcube(center = true, size = [40, 40, 30.0000000000]);\n\t}\n}' ] self.assertEqual(actual, expected)
def assertEqualOpenScadObject(self, expected: str, actual: Union[OpenSCADObject, str]): if isinstance(actual, OpenSCADObject): act = scad_render(actual) elif isinstance(actual, str): act = actual self.assertEqualNoWhitespace(expected, act)
def scad_source(self, fn: int = None) -> str: # pragma: no cover """The OpenSCAD source code that this component corresponds to""" header = "" if fn: header = f"$fn = {fn};" return solid.scad_render(self.body, header)
def test_fillet_2d_remove(self): pts = list((project_to_2D(p) for p in tri)) poly = polygon(euc_to_arr(pts)) newp = fillet_2d([pts], orig_poly=poly, fillet_rad=2, remove_material=True) expected = 'difference(){polygon(paths=[[0,1,2]],points=[[0,0],[10,0],[0,10]]);translate(v=[5.1715728753,2.0000000000]){difference(){intersection(){rotate(a=-90.1000000000){translate(v=[-998,0,0]){square(center=false,size=[1000,1000]);}}rotate(a=45.1000000000){translate(v=[-998,-1000,0]){square(center=false,size=[1000,1000]);}}}circle(r=2);}}}' actual = scad_render(newp) self.assertEqualNoWhitespace(expected, actual)
def main(): ssid = "Family Guest Network" security = "WPA" password = "******" qr = create_wifi_qr(ssid, security, password) arr = qr2array(qr) solid_object = make_solid(arr) print(scad_render(solid_object))
def test_fillet_2d_add(self): pts = [[0, 5], [5, 5], [5, 0], [10, 0], [10, 10], [0, 10], ] p = polygon(pts) three_points = [euclidify(pts[0:3], Point2)] newp = fillet_2d(three_points, orig_poly=p, fillet_rad=2, remove_material=False) expected = 'union(){polygon(paths=[[0,1,2,3,4,5]],points=[[0,5],[5,5],[5,0],[10,0],[10,10],[0,10]]);translate(v=[3.0000000000,3.0000000000]){difference(){intersection(){rotate(a=359.9000000000){translate(v=[-998,0,0]){square(center=false,size=[1000,1000]);}}rotate(a=450.1000000000){translate(v=[-998,-1000,0]){square(center=false,size=[1000,1000]);}}}circle(r=2);}}}' actual = scad_render(newp) self.assertEqualNoWhitespace(expected, actual)
def dump(root, fn, prefix=""): if fn.endswith(".py"): fn = __file__.replace(".py", "") if hasattr(root, "__call__"): root = root() with open(fn, "wb") as op: op.write(prefix.encode("utf-8")) op.write(solid.scad_render(root).encode("utf-8"))
def render(object): scad = scad_render(object) lines = scad.split("\n") count = 0 for each in lines: if each.startswith('use') or each.startswith('import'): count += 1 else: break return '\n'.join(lines[0:count] + ['$fn=200;'] + lines[count:])
def render(self, in_obj, **kw): if 'dollar_sign_vars' not in kw: kw['dollar_sign_vars'] = {'fn': DEFAULT_FN} else: if 'fn' not in kw['dollar_sign_vars']: kw['dollar_sign_vars']['fn'] = DEFAULT_FN if isinstance(in_obj, solid.OpenSCADObject): self.render_openscad_str(solid.scad_render(in_obj), **kw) elif isinstance(in_obj, str): self.render_openscad_str(in_obj, **kw)
def test_fillet_2d_remove(self): pts = tri poly = polygon(euc_to_arr(tri)) newp = fillet_2d(tri, orig_poly=poly, fillet_rad=2, remove_material=True) expected = '\n\ndifference() {\n\tpolygon(paths = [[0, 1, 2]], points = [[0, 0, 0], [10, 0, 0], [0, 10, 0]]);\n\ttranslate(v = [5.1715728753, 2.0000000000, 0.0000000000]) {\n\t\tdifference() {\n\t\t\tintersection() {\n\t\t\t\trotate(a = 268.0000000000) {\n\t\t\t\t\ttranslate(v = [-998, 0, 0]) {\n\t\t\t\t\t\tsquare(center = false, size = [1000, 1000]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\trotate(a = 407.0000000000) {\n\t\t\t\t\ttranslate(v = [-998, -1000, 0]) {\n\t\t\t\t\t\tsquare(center = false, size = [1000, 1000]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcircle(r = 2);\n\t\t}\n\t}\n}' actual = scad_render(newp) if expected != actual: print(''.join(difflib.unified_diff(expected, actual))) self.assertEqual(expected, actual)
def process(outline_file, solderpaste_file, stencil_thickness=0.2, include_ledge=True, ledge_height=1.2, ledge_gap=0.0, increase_hole_size_by=0.0): outline_shape = create_outline_shape(outline_file) cutout_polygon = create_cutouts( solderpaste_file, increase_hole_size_by=increase_hole_size_by) if ledge_gap: # Add a gap between the ledge and the stencil outline_shape = offset_shape(outline_shape, ledge_gap) outline_polygon = polygon(outline_shape) stencil = linear_extrude(height=stencil_thickness)(outline_polygon - cutout_polygon) if include_ledge: ledge_shape = offset_shape(outline_shape, 1.2) ledge_polygon = polygon(ledge_shape) - outline_polygon # Cut the ledge in half by taking the bounding box of the outline, cutting it in half # and removing the resulting shape from the ledge shape # We always leave the longer side of the ledge intact so we don't end up with a tiny ledge. cutter = bounding_box(ledge_shape) height = abs(cutter[1][1] - cutter[0][1]) width = abs(cutter[0][0] - cutter[3][0]) if width > height: cutter[1][1] -= height / 2 cutter[2][1] -= height / 2 else: cutter[2][0] -= width / 2 cutter[3][0] -= width / 2 ledge_polygon = ledge_polygon - polygon(cutter) ledge = utils.down(ledge_height - stencil_thickness)( linear_extrude(height=ledge_height)(ledge_polygon)) stencil = ledge + stencil # Rotate the stencil to make it printable stencil = rotate(a=180, v=[1, 0, 0])(stencil) return scad_render(stencil)
def test_fillet_2d_add(self): pts = [ [0, 5], [5, 5], [5, 0], [10, 0], [10, 10], [0, 10], ] p = polygon(pts) newp = fillet_2d(euclidify(pts[0:3], Point3), orig_poly=p, fillet_rad=2, remove_material=False) expected = '\n\nunion() {\n\tpolygon(paths = [[0, 1, 2, 3, 4, 5]], points = [[0, 5], [5, 5], [5, 0], [10, 0], [10, 10], [0, 10]]);\n\ttranslate(v = [3.0000000000, 3.0000000000, 0.0000000000]) {\n\t\tdifference() {\n\t\t\tintersection() {\n\t\t\t\trotate(a = 358.0000000000) {\n\t\t\t\t\ttranslate(v = [-998, 0, 0]) {\n\t\t\t\t\t\tsquare(center = false, size = [1000, 1000]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\trotate(a = 452.0000000000) {\n\t\t\t\t\ttranslate(v = [-998, -1000, 0]) {\n\t\t\t\t\t\tsquare(center = false, size = [1000, 1000]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcircle(r = 2);\n\t\t}\n\t}\n}' actual = scad_render(newp) self.assertEqual(expected, actual)
def arr2scad(arr, HEIGHT: int = 2): """ Convert an array `arr` into valid OpenSCAD text. """ SCALE = 2 # output defaults to 1 mm per unit; this lets us increase the size of objects proportionally. cubes = [ translate([i * SCALE, j * SCALE, 0])(color('black')(cube(size=[SCALE, SCALE, HEIGHT]))) for i, row in enumerate(arr) for j, col in enumerate(row) if arr[i, j] == 1 ] base_plate = color('white')(cube(size=(arr.shape[0] * SCALE, arr.shape[1] * SCALE, HEIGHT / 2))) qrobj = union()(*cubes, base_plate) return scad_render(qrobj)
def process(outline_file, solderpaste_file, stencil_thickness=0.2, include_ledge=True, ledge_height=1.2, ledge_gap=0.0, increase_hole_size_by=0.0): outline_shape = create_outline_shape(outline_file) cutout_polygon = create_cutouts(solderpaste_file, increase_hole_size_by=increase_hole_size_by) if ledge_gap: # Add a gap between the ledge and the stencil outline_shape = offset_shape(outline_shape, ledge_gap) outline_polygon = polygon(outline_shape) stencil = linear_extrude(height=stencil_thickness)(outline_polygon - cutout_polygon) if include_ledge: ledge_shape = offset_shape(outline_shape, 1.2) ledge_polygon = polygon(ledge_shape) - outline_polygon # Cut the ledge in half by taking the bounding box of the outline, cutting it in half # and removing the resulting shape from the ledge shape # We always leave the longer side of the ledge intact so we don't end up with a tiny ledge. cutter = bounding_box(ledge_shape) height = abs(cutter[1][1] - cutter[0][1]) width = abs(cutter[0][0] - cutter[3][0]) if width > height: cutter[1][1] -= height/2 cutter[2][1] -= height/2 else: cutter[2][0] -= width/2 cutter[3][0] -= width/2 ledge_polygon = ledge_polygon - polygon(cutter) ledge = utils.down( ledge_height - stencil_thickness )( linear_extrude(height=ledge_height)(ledge_polygon) ) stencil = ledge + stencil # Rotate the stencil to make it printable stencil = rotate(a=180, v=[1, 0, 0])(stencil) return scad_render(stencil)
def test_with_solidpython(self): import solid sys = System() a = sys.add_param(10) b = sys.add_param(3) c = sys.add_param(17) d = sys.add_param(23) #NOTE We should use Point2d, but I don't want to # create a workplane just for that. p1 = Point3d(Param(7), Param(2), Param(0), sys) poly = solid.polygon([[a,b],[c,d], [0,0], p1]) self.assertEqual( solid.scad_render(poly), "\n\npolygon(paths = [[0, 1, 2, 3]], points = [[10.0000000000, 3.0000000000], [17.0000000000, 23.0000000000], [0, 0], [7.0000000000, 2.0000000000, 0.0000000000]]);")
def matrix_to_scad(mat: List[List[List[int]]], voxel_dim: float) -> str: """ matrix_to_scad returns generated openscad code to render a 3D scene with cubes of length voxel_dim placed at every x, y, z location where the input matrix is equal to 1. :param mat: :param voxel_dim: :return: generated openscad code """ op_list = [] for x in range(0, len(mat)): for z in range(0, len(mat[0])): for y in range(0, len(mat[0][0])): if mat[x][z][y] == 1: op_list.append( sp.translate( [x * voxel_dim, y * voxel_dim, z * voxel_dim])(sp.cube(voxel_dim))) u = sp.union()(op_list) return sp.scad_render(u)
import solid as sp import solid.utils as spu from frame.utils import bom def projection(diameter): return sp.circle(d=diameter) @bom.part('Round Bar') def volume(diameter, length, center=False): material = sp.linear_extrude(length)(projection(diameter)) return spu.down(length / 2)(material) if center else material if __name__ == '__main__': print(sp.scad_render(volume(diameter=100)))
gap = .4 # mm inner_circle = sd.circle(d=width) inner_oval = sd.square([length, width], center=True) inner_oval += sd.translate([-length / 2, 0])(inner_circle) inner_oval += sd.translate([length / 2, 0])(inner_circle) punch_circle = sd.circle(d=punch) lip_circle = sd.circle(d=width + 2 * wall + 2 * lip) lip_oval = sd.square([length, width + 2 * wall + 2 * lip], center=True) lip_oval += sd.translate([-length / 2, 0])(lip_circle) lip_oval += sd.translate([length / 2, 0])(lip_circle) hole_oval = lip_oval lip_oval = sd.translate([0, 0, -wall])(sd.linear_extrude(wall)(lip_oval)) outer_circle = sd.circle(d=width + 2 * wall) outer_oval = sd.square([length, width + 2 * wall], center=True) outer_oval += sd.translate([-length / 2, 0])(outer_circle) outer_oval += sd.translate([length / 2, 0])(outer_circle) center_piece = hole_oval + sd.linear_extrude(height)(outer_oval - inner_oval) press_circle = sd.circle(d=width - 2 * gap) press_oval = sd.square([length, width - 2 * gap], center=True) press_oval += sd.translate([-length / 2, 0])(press_circle) press_oval += sd.translate([length / 2, 0])(press_circle) press_oval = sd.linear_extrude(height - 2 * wall)(press_oval) press_piece = lip_oval + press_oval # print(sd.scad_render(center_piece)) print(sd.scad_render(press_piece))
def process_gerber( outline_file, solderpaste_file, stencil_thickness=0.2, include_ledge=True, ledge_height=1.2, ledge_gap=0.0, increase_hole_size_by=0.0, simplify_regions=False, flip_stencil=False, ): """Convert gerber outline and solderpaste files to an scad file.""" outline_shape = create_outline_shape(outline_file) cutout_polygon = create_cutouts( solderpaste_file, increase_hole_size_by=increase_hole_size_by, simplify_regions=simplify_regions, ) # debugging! # return scad_render(linear_extrude(height=stencil_thickness)(polygon(outline_shape))) if ledge_gap: # Add a gap between the ledge and the stencil outline_shape = offset_shape(outline_shape, ledge_gap) outline_polygon = polygon([v.as_tuple() for v in outline_shape]) if flip_stencil: mirror_normal = (-1, 0, 0) outline_bounds = geometry.bounding_box(outline_shape) outline_polygon = translate((outline_bounds[2][0], 0, 0))( mirror(mirror_normal)(outline_polygon) ) cutout_polygon = translate((outline_bounds[2][0], 0, 0))( mirror(mirror_normal)(cutout_polygon) ) stencil = linear_extrude(height=stencil_thickness)(outline_polygon - cutout_polygon) if include_ledge: ledge_shape = offset_shape(outline_shape, 1.2) ledge_polygon = polygon([v.as_tuple() for v in ledge_shape]) - outline_polygon # Cut the ledge in half by taking the bounding box of the outline, cutting it in half # and removing the resulting shape from the ledge shape # We always leave the longer side of the ledge intact so we don't end up with a tiny ledge. cutter = geometry.bounding_box(ledge_shape) height = abs(cutter[1][1] - cutter[0][1]) width = abs(cutter[0][0] - cutter[3][0]) if width > height: cutter[1].y -= height / 2 cutter[2].y -= height / 2 else: cutter[2].x -= width / 2 cutter[3].x -= width / 2 ledge_polygon = ledge_polygon - polygon([v.as_tuple() for v in cutter]) ledge = utils.down(ledge_height - stencil_thickness)( linear_extrude(height=ledge_height)(ledge_polygon) ) stencil = ledge + stencil # Rotate the stencil to make it printable stencil = rotate(a=180, v=(1, 0, 0))(stencil) # for debugging, output just the cutout polygon (extruded) # return scad_render(linear_extrude(height=stencil_thickness)(cutout_polygon)) return scad_render(stencil)
def qr2array(qr): arr = [] for line in qr.text().split('\n'): if len(line) != 0: arr.append([int(bit) for bit in line]) return np.vstack(arr) arr = qr2array(qr) """ Build 3d Model from Array """ from solid import color, cube, scad_render, translate, union HEIGHT = 1 SCALE = 2 # output defaults to 1 mm per unit; this lets us increase the size of objects proportionally. cubes = [ translate([i * SCALE, j * SCALE, 0])(color('black')(cube(size=[SCALE, SCALE, HEIGHT]))) for i, row in enumerate(arr) for j, col in enumerate(row) if arr[i, j] == 1 ] base_plate = color('white')(cube(size=(arr.shape[0] * SCALE, arr.shape[1] * SCALE, HEIGHT / 2))) qrobj = union()(*cubes, base_plate) print(scad_render(qrobj))
axis_base = solid.cube(size=(d, width_hole / 2, h), center=True) axis_1 = solid.rotate(a=X)(axis_base) axis_2 = solid.rotate(a=-X)(axis_base) outer_cylinder = solid.cylinder(d=d, h=h, center=True, segments=256) ret = (center + axis_1 + axis_2) * outer_cylinder return solid.translate(v=(0, 0, z + h / 2))(ret) base = thing(h=10) base2 = thing(X=30, width=13) tip = thing(h=4, z=0, width=16) for x in range(40, 100, 5): x /= 10.0 tip += thing(h=0.5, z=x, width=20.01 - x) tip += thing(h=2, z=10, width=0, d=15.8) with open('tip.scad', 'w') as f: f.write(solid.scad_render(tip)) with open('base2.scad', 'w') as f: f.write(solid.scad_render(base2)) with open('base.scad', 'w') as f: f.write(solid.scad_render(base))
''' light = solid.cube([5,15,123])- solid.translate([1,1,1])(solid.cube([5,13,121])) light = solid.color([.4,.4,.4])(light) tube1 = solid.color([1,1,1])(solid.translate([4,4,1])(solid.cylinder(r=2, h=121))) tube2 = solid.translate([0,6,0])(tube1) trough = solid.color([.4,.4,.4])(solid.translate([15,-2.5,0])(solid.cube([10,20,123]))) trough -= solid.translate([16,-1.5,-1])(solid.cube([8,18,125])) thole = solid.translate([14,7.5,10])(solid.rotate([0,90,0])(solid.cylinder(r=8, h = 5) )) tslots = [] for i in range(6): tslots += [solid.translate([0,0,i*18])(thole)] trough -= solid.translate([0,0,7])(join_list(tslots)) bucket = solid.translate([22.5,7.5,10])(solid.rotate([0,-90,0])(splanter())) bslots = [] for i in range(6): bslots += [solid.translate([0,0,i*18])(bucket)] planters = join_list(bslots) planters = solid.translate([0,0,7])(planters) object = [trough, light, tube1, tube2, planters] rack = join_list(object) rack = solid.rotate([0,90,0])(rack) print>>out_file, solid.scad_render(rack)
def test_scad(self): scad_obj = func(*args) actual = scad_render(scad_obj) self.assertEqual(expected, actual)
def test_label(self): expected = 'translate(v=[0,5.0000000000,0]){resize(newsize=[15,0,0.5000000000]){union(){translate(v=[0,0.0000000000,0]){linear_extrude(height=1){text($fn=40,font="MgOpenModata:style=Bold",halign="left",spacing=1,text="Hello,",valign="baseline");}}translate(v=[0,-11.5000000000,0]){linear_extrude(height=1){text($fn=40,font="MgOpenModata:style=Bold",halign="left",spacing=1,text="World",valign="baseline");}}}}}' actual = scad_render(label("Hello,\nWorld")) self.assertEqualNoWhitespace(expected, actual)
rbutt = 20 rail1 = solid.utils.arc( rad = rcling, start_degrees = 0, end_degrees = 180) rail1 -= solid.utils.arc( rad = rcling-1, start_degrees = 0, end_degrees = 180) rail2= solid.translate([0,0,6])(rail1) rail3 = solid.translate([0,0,6])(rail2) rails = solid.translate([0,0,4])(join_list([rail1,rail2, rail3])) rails += solid.translate([1,-.5,0])(solid.cube([4,1,20])) rails = solid.translate([30,20,-rcling+2])((solid.rotate([90,90,0])(rails))) rails = solid.color([0,0,0])(rails) buttress1 = solid.utils.arc( rad = rbutt, start_degrees = 0, end_degrees = 90) buttress1 -= solid.utils.arc( rad = rbutt-3, start_degrees = 0, end_degrees = 180) buttress1 += solid.translate([0,rbutt-2, -1.5])(solid.cube([rbutt, 2,3])) buttress2 = solid.translate([0,0,10])(buttress1) buttresses = buttress1 + buttress2 buttresses = solid.rotate([-90,-90,0])(solid.translate([0,0,5])(buttresses)) buttresses = solid.translate([30-rbutt-5,0,-rbutt+2])(buttresses) buttresses = solid.color([0,0,.8])(buttresses) board = solid.color([.4,.4,.4])(solid.cube([30,20,2])) object = [board, rails, buttresses] print>>out_file, solid.scad_render(join_list(object))
dump.add_geometry(geometry, width=1) dump.dump() return holes parser = argparse.ArgumentParser(description="Send a bunch of emails") parser.add_argument("--parts", required=False, type=str, nargs="+", help="parts to make holes for") parser.add_argument("--brd", required=True, help="Board to use") parser.add_argument("--scad", required=True, help="scad file output") args = parser.parse_args() brd = ShapelySwoop.open(args.brd) output = make_package_scad(args.parts) open(args.scad, "w").write(""" module {a}() {{ {b} }} """.format(a=args.brd[:-4].split("/")[-1].replace("-", "_"), b=solid.scad_render(output))) #"../Motor Driver/MotorDriver-rev1.brd") #["J1", "J2", "J3", "J4"]
def test_extrude_along_path_end_caps(self): path = [[0, 0, 0], [0, 20, 0]] actual = scad_render(extrude_along_path(tri, path, connect_ends=False)) expected = 'polyhedron(faces = [[0, 3, 1], [1, 3, 4], [1, 4, 2], [2, 4, 5], [2, 5, 0], [0, 5, 3], [6, 0, 1], [6, 1, 2], [6, 2, 0], [7, 3, 4], [7, 4, 5], [7, 5, 3]], points = [[0.0000000000, 0.0000000000, 0.0000000000], [10.0000000000, 0.0000000000, 0.0000000000], [0.0000000000, 0.0000000000, 10.0000000000], [0.0000000000, 20.0000000000, 0.0000000000], [10.0000000000, 20.0000000000, 0.0000000000], [0.0000000000, 20.0000000000, 10.0000000000], [3.3333333333, 0.0000000000, 3.3333333333], [3.3333333333, 20.0000000000, 3.3333333333]]);' self.assertEqualNoWhitespace(expected, actual)
import solid as sp import solid.utils as spu from frame.utils import bom, place_at_centres body_dimensions = (60., 40., 2.) mounting_hole_centres = (56., 36.) mounting_hole_diameter = 2.2 def holes(): return place_at_centres( mounting_hole_centres, sp.circle(d=mounting_hole_diameter, segments=16) ) def projection(): return sp.square(body_dimensions[:2], center=True) - holes() @bom.part('Lighting Control Board') def volume(): return sp.linear_extrude(body_dimensions[2])(projection()) if __name__ == '__main__': print(sp.scad_render(volume()))
def scad(ctx): click.echo(sp.scad_render(ctx.obj))