from cqmore import Workplane from cqmore.curve import archimedeanSpiral, circle from cqmore.polygon import regularPolygon, star from random import randint, choice import cadquery as cq import functools as fnc import itertools as it from cad_utilities.shapes import makeTriangle coaster_radius = 50 def add_triangle(plane, width, height, offset): return plane.triangle(width, height, y_offset=offset) def addXmas(self, offsets): xmas_tree_offset = -25 xmas_tree_height = 8 xmas_tree_width = 6 w_off, h_off, y_off = offsets return self.triangle( xmas_tree_width + (choice([-1, 1]) * w_off), xmas_tree_height + (choice([-1, 1]) * h_off), y_offset=-(xmas_tree_offset + (y_off)), ) def makeXmasTree(self): xmas_tree_offset = -25 xmas_tree_height = 8 xmas_tree_width = 6 offsets = [(0, 0, 0)] + [tuple(randint(1, 5) for _ in range(4)) for _ in range(3)] print(offsets) offsets_added = list( it.accumulate(offsets, lambda t1, t2: list(a + b for a, b in zip(t1, t2))) ) last_y = offsets_added[-1][2] # offsets = [(0,0,0), (3,2,6), (4,11,13), (4,13,16)] tree = fnc.reduce(addXmas, offsets_added, self.center(0, 0)) return tree.moveTo(0, -(xmas_tree_offset + last_y)).rect(2, 5).cutThruAll() Workplane.triangle = makeTriangle Workplane.xmasTree = makeXmasTree polygon = ( Workplane() .makePolygon( regularPolygon(nSides=16, radius=coaster_radius, thetaStart=0, thetaEnd=360) ) .extrude(7, clean=True, combine=True, taper=15) .xmasTree() ) result = polygon.workplane().text( "Wes", 10, 40, clean=True, combine="cut", fontPath="/home/wes/fonts/TiltNeon-Regular-VariableFont_XROT,YROT.ttf", ) result = ( result.faces("Z") .workplane() .makePolygon( regularPolygon( nSides=10, radius=coaster_radius - 5, thetaStart=0, thetaEnd=360 ), forConstruction=True, ) .vertices() .circle(2) .extrude(5) ) cq.exporters.export(result, "/home/deck/cad_files/coaster.step")