CadQuery / cadquery

A python parametric CAD scripting framework based on OCCT
https://cadquery.readthedocs.io
Other
3.21k stars 293 forks source link

Thin-feature extrude of trajectory traces on a plane #1659

Closed farinha93 closed 1 month ago

farinha93 commented 2 months ago

Hi all, I'm trying to create an stl file which is composed of a single extruded sketch. This sketch contains something like the trajectories of multiple particles which are generated recursively (imagine that every timestep a particle may divide into 2 and thuse 2 traces need to be tracked from now on). Ideally what I would like to do is define these trajectories as polylines and then do a thin feature extrude, which can be found in some commercial software. I couldn't find a function to straight up do that, so started using Sketch().rect for each segment of each trajectory, combining them, and finally extruding the sketch. - which is slightly more efficient than extruding each time. Unfortunately I'm reaching bottleneck on the number and length of trajectories I can do in useful time. It's my first time using cadquery, so maybe I'm not doing this the smartest way. Would appreciate any suggestions.

Bellow is a simplified example of what I've doing so far:

import cadquery as cq
import numpy as np

length = 10
width = 1
point = [0, 0]
angle = 0

def rot(v, angle):
    a = np.deg2rad(angle)
    R = [[np.cos(a), np.sin(a)], [np.sin(a), np.cos(a)]]
    vr = R @ np.array(v).T
    return vr

for i in range(10):
    point += rot([length / 2, 0], angle)
    if i == 0:
        result = cq.Sketch().rect(length + width, width, angle).vertices().fillet(width / 2.1).reset()
        result = result.moved(cq.Location(cq.Vector(point[0], point[1], 0)))
    else:
        s = cq.Sketch().rect(length + width, width, angle).vertices().fillet(width / 2.1).reset()
        s = s.moved(cq.Location(cq.Vector(point[0], point[1], 0)))
        result.face(s, mode='a')
    point += rot([length / 2, 0], angle)
    angle += np.random.normal() * 30

result = cq.Workplane("XY").placeSketch(result).extrude(1)
lorenzncode commented 2 months ago

Ideally what I would like to do is define these trajectories as polylines and then do a thin feature extrude

This is possible. (I don't know if it helps with your performance issue)

from cadquery.occ_impl.shapes import *

pts = [
    (0, 0),
    (10, 0),
    (10, 10),
    (20, 10),
    (20, 20),
]

wire1 = polyline(*pts)
wire2 = wire1.fillet(2, wire1.vertices())
shell1 = extrude(wire2, (0, 0, 1))
solid1 = offset(shell1, 1)
adam-urbanczyk commented 2 months ago

Alternative solution:

from cadquery.occ_impl.shapes import *

pts = [
    (0, 0),
    (10, 0),
    (10, 10),
    (20, 10),
    (20, 20),
]

w = 1
h = 0.5

wire1 = polyline(*pts)
face1 = face(wire1.offset2D(w))
solid1 = extrude(face1, (0,0,h))
farinha93 commented 1 month ago

Hi both, thank you for your recommendations. I've tested both options now and there is a considerable improvement in performance. This is likely as good as it will get, as there is really nothing that can be done to avoid the recursive step. For my code, I ended up creating one Worplane.polyline.offset2D.extrude geometry per trajectory and used boolean operations to add them together.