Last active
March 13, 2024 18:05
-
-
Save aavogt/8fb7162e572d72049748e1e42b12bbd2 to your computer and use it in GitHub Desktop.
cadquery 3d strip
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cadquery as cq | |
from copy import copy | |
class Ribbon3: | |
""" A ribbon is a way to make a sequence of Workplane.box | |
end-to-end without repeating dimensions. | |
I like the offset2D approach: | |
cq.Workplane().hLine(5).vLine(6).offset2D(2).extrude(3) | |
The near equivalent is: | |
Ribbon3(cq.Workplane(), w=2, h=3).x(5).y(6).end() | |
unlike offset2D, corners are not rounded, but you can go up with z() | |
offset2D does lengths for the midplane. Ribbon3 x(1).z(10).y(1) should | |
put the two bottom XY planes 10 mm apart. | |
""" | |
def __init__(self, cq=cq.Workplane(), w=5, h=2): | |
self.cq = cq | |
self.axis = 2 | |
self.d = [w, h, 0] | |
self.p = [0, 0, 0] | |
# states for push/pop | |
self.ds = [] | |
self.axes = [] | |
self.ps = [] | |
self.planes = [] | |
def go(self, naxis, length): | |
self.d[naxis], self.d[self.axis] = abs(length), self.d[naxis] | |
if (length < 0): | |
self.p[naxis] = length | |
self.d[naxis] += self.d[self.axis] | |
self.cq = self.cq.transformed(offset=self.p).box(self.d[0], self.d[1], self.d[2], False) | |
self.p[self.axis] = 0 | |
if (length < 0): | |
self.p[naxis] = 0 | |
else: | |
self.p[naxis] = length | |
self.axis = naxis | |
return self | |
def x(self, length): | |
return self.go(0, length) | |
def y(self, length): | |
return self.go(1, length) | |
def z(self, length): | |
return self.go(2, length) | |
def end(self): | |
return self.cq | |
def push(self): | |
""" Save the current state """ | |
self.ps.append(self.p.copy()) | |
self.ds.append(self.d.copy()) | |
self.axes.append(self.axis) | |
self.planes.append(copy(self.cq.plane)) | |
print("pushed", self.ps, self.ds, self.axes) | |
return self | |
def pop(self): | |
""" Restore the previous state """ | |
self.p = self.ps.pop() | |
self.axis = self.axes.pop() | |
self.d = self.ds.pop() | |
self.cq.plane = self.planes.pop() | |
print("restored", self.p, self.d, self.axis) | |
return self | |
def branch(self, f): | |
""" Save the current state, call f, restore the previous state | |
ribbon.branch(lambda c: c.x(4).y(5)).x(-5).y(5).end() | |
Ideally the syntax would be lighter, perhaps | |
ribbon.branch(_.x(4).y(5)).x(-5).y(5).end() | |
fn.py defines an underscore, but when I try to use it I get | |
'int' object has no attribute 'x' | |
from fn import _ | |
ribbon.branch(_.x(4).y(5)).x(-5).y(5).end() | |
I could add x,y,z etc. attributes to _, but could they | |
have written it such that _ has every method which | |
just stores the syntax tree for later use (when the _ | |
is defined). | |
""" | |
return f(self.push()).pop() | |
def __call__(self, f): | |
""" for now this is branch, but it should be something else? """ | |
return self.branch(f) | |
ribbon_test = Ribbon3().x(10).y(20).z(20).x(-10).y(30).z(-5).end() | |
show_object(ribbon_test) # https://i.ibb.co/sW0tBDW/ribbon.png |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment