!trPFMasOMDqcwYBXEy:matrix.org

CadQuery

251 Members
https://github.com/CadQuery/cadquery3 Servers

Load older messages


SenderMessageTime
14 May 2022
@_discord_332903554807234560:t2bot.ioqwelyt#8390 Marble filament can look so dang cool. 19:00:20
@_discord_908172247359963226:t2bot.iofpq473#6357 Is there a nice way to get a "named" workplane from an existing workplane? E.g.
cq.Workplane().rect(3,4,5).workplane("ZY")  # fails; I want the ZY workplane
20:45:37
@_discord_896482168103125002:t2bot.ioRoger Maitland#7070 Sorry, I don't understand what you're trying to do here. Transform the rectangle so that it's on the ZY plane? 20:57:17
@_discord_908172247359963226:t2bot.iofpq473#6357 My bad. I mean, I want that solid that I just made, but now I want my plane to be the ZY plane so that I can do things that direction, e.g. extrude a cylinder in the X direction 21:03:51
@_discord_908172247359963226:t2bot.iofpq473#6357 So something like cq.Workplane().box(3,4,5). ????? .circle(6).extrude(7) where the circle is in the ZY plane and I'm extruding along X. 21:05:01
@_discord_908172247359963226:t2bot.iofpq473#6357 * So something like cq.Workplane().cylinder(4,5). ????? .circle(6).extrude(7) where the circle is in the ZY plane and I'm extruding along X. 21:05:38
@_discord_186253289476587521:t2bot.ioDraek#9615 Use transformed to change your wp or use copyWorkplane to copy another Workplane object that you'd initialize with the wp you want 21:23:01
@_discord_209043174960660490:t2bot.ioJern Just as a specific example, this is what I typically do, but the copyWorkplane idea is maybe better
.transformed(rotate=cq.Vector(90,0,0)
21:23:42
@_discord_209043174960660490:t2bot.ioJern * Just as a specific illustration, this is what I typically do, but the copyWorkplane idea is maybe better
.transformed(rotate=cq.Vector(90,0,0)
21:23:53
@_discord_209043174960660490:t2bot.ioJern * Just as a specific illustration, this is what I typically do, but the copyWorkplane idea is maybe better
.transformed(rotate=cq.Vector(90,0,0))
21:24:24
@_discord_908172247359963226:t2bot.iofpq473#6357 Thanks both. .copyWorkplane(cq.Workplane("ZY")) works nicely. I knew about this method but never thought to use it because of the name -- I wanted to copy the plane, not the workplane (which I think of as plane + parent + stack + ctx). 21:26:41
@_discord_908172247359963226:t2bot.iofpq473#6357 * Thanks both. .copyWorkplane(cq.Workplane("ZY")) works nicely. I knew about this method but never thought to use it because of the name -- I wanted to copy the plane, not the workplane (which I think of as plane + parent + stack + ctx). [edit: maybe the name is right if I think of it as copying everything (from self) except the plane?] 21:28:13
@_discord_209043174960660490:t2bot.ioJern Will do! I have a lot more releases in the works and a lot of unreleased stuff too 21:57:52
15 May 2022
@_discord_944119318554243094:t2bot.iosethfischer Yes thanks Roger Maitland this will be useful 10:11:46
@_discord_774666487407443978:t2bot.ioamundsen#5368 Yes, that makes it! Thank a lot! 16:17:26
@_discord_332903554807234560:t2bot.ioqwelyt#839020220515_234056.png
Download 20220515_234056.png
21:43:26
@_discord_332903554807234560:t2bot.ioqwelyt#8390 If I have a face like this, how can I extrude it? I thought I could do thing.faces(">Z").wires().toPending().extrude(10) but that just tells me that the wires are not planar. 21:43:26
@_discord_896482168103125002:t2bot.ioRoger Maitland#7070unknown.png
Download unknown.png
21:57:39
@_discord_896482168103125002:t2bot.ioRoger Maitland#7070 Two solutions - one with Solid.extrudeLinear() which creates a Solid by extending in a specific direction (gold) and one with cq_warehouse's Face.thicken() which extends along the normal of the non planar Face (blue):
import cadquery as cq
import cq_warehouse.extensions

non_planar_face = (
    cq.Workplane().parametricSurface(lambda x, y: (x, y, x**2 + y**2)).val()
)
extrude = cq.Solid.extrudeLinear(non_planar_face, cq.Vector(0, 0, 0.2))
thicken = non_planar_face.thicken(0.2)

show_object(extrude, name="extrude")
show_object(
    thicken.rotate(cq.Vector(), cq.Vector(0, 0, 1), 180),
    options={"color": (64, 164, 223)},
    name="thicken",
)
21:57:39
16 May 2022
@_discord_209043174960660490:t2bot.ioJern I was browsing the cq_warehouse docs and saw the Face.thicken method and it seems so useful! 02:15:52
@_discord_332903554807234560:t2bot.ioqwelyt#8390 extrudeLinear was exactly what I wanted! Many thanks! 06:34:09
@_discord_896482168103125002:t2bot.ioRoger Maitland#7070 It's very useful when you want a feature to follow another surface, like projecting text onto a surface then using thicken to either make it proud or embedded into that surface - as done with the Shape.projectText() method (https://cq-warehouse.readthedocs.io/en/latest/extensions.html#extensions_doc.Shape.projectText). I found that working with Face normals can be frustrating as they don't always point in the same direction (for example in a string of text, sometimes a face normal will be flipped) so I added an optional direction parameter that is an very approximate indication (+/- 90 degrees) of what you'd like to be "up". For example, when thickening faces wrapped around a cylinder, direction would be the direction towards the center (i.e. in Vector math, the face center minus the cylinder center). 13:38:57
@_discord_774666487407443978:t2bot.ioamundsen#5368 Hello, I'm trying to fuse a set of solids using union but only one of the solids is kept in the end:
import cadquery as cq from math import sin import random big_rad = 80 small_rad = 10 height = 20 amount = 20 export_activation = False # positions for the toruses pts = [cq.Vector(0,0,p * height + small_rad * 2) for p in range (amount)] # X components for the dir Vector myXDir = [random.uniform(-0.25,0.25) for p in range (amount)] toruses = [ cq.Solid.makeTorus( radius1=big_rad, radius2=small_rad, pnt=pts[p], dir=cq.Vector(myXDir[p], 0, 1), angleDegrees1=0.0, angleDegrees2=360.0, ) for p in range(amount) ] assy = cq.Workplane("XY") for i in range(len(toruses)): assy.union(toruses[i]) show_object(assy)
14:47:32
@_discord_774666487407443978:t2bot.ioamundsen#5368 * Hello, I'm trying to fuse a set of solids using union but only one of the solids is kept in the end:
import cadquery as cq from math import sin import random big_rad = 80 small_rad = 10 height = 20 amount = 20 export_activation = False # positions for the toruses pts = [cq.Vector(0,0,p * height + small_rad * 2) for p in range (amount)] # X components for the dir Vector myXDir = [random.uniform(-0.25,0.25) for p in range (amount)] toruses = [ cq.Solid.makeTorus( radius1=big_rad, radius2=small_rad, pnt=pts[p], dir=cq.Vector(myXDir[p], 0, 1), angleDegrees1=0.0, angleDegrees2=360.0, ) for p in range(amount) ] assy = cq.Workplane("XY").union(toruses[0]) for i in range(1,len(toruses)): assy.union(toruses[i]) show_object(assy)
14:49:12
@_discord_896482168103125002:t2bot.ioRoger Maitland#7070 A Solid is a contiguous object - if your toruses don't all intersect they can't be a single Solid. A Compound is a set of objects that don't necessarily intersect with each other. So do all the toruses intersect with each other? 14:52:47
@_discord_774666487407443978:t2bot.ioamundsen#5368 Some of them do intersect, some don't. So, a compound is the right way to go I guess. Thank you. Also, in a former message in another topic you mentioned the combine method. Could this be used too? 14:56:36
@_discord_896482168103125002:t2bot.ioRoger Maitland#7070 Yes, cq.Compound.makeCompound will make a Compound object out of a list of shapes. 14:57:44
@_discord_774666487407443978:t2bot.ioamundsen#5368 Is there a way to fuse parts together so that intersecting sections are not duplicated? Could this be done within a Compound? 15:14:26
@_discord_896482168103125002:t2bot.ioRoger Maitland#7070 A Compound doesn't fuse intersecting shapes. If you want to do this you could check to see if the parts intersect and if so fuse them before adding them to the Compound. To illustrate how to check for an intersection, here is an Assembly method I created to determine if any of the parts in the Assembly intersect:
def _doObjectsIntersect(self, tolerance: float = 1e-5) -> bool:
    """Do Objects Intersect

    Determine if any of the objects within an Assembly intersect by
    intersecting each of the shapes with each other and checking for
    a common volume.

    Args:
        self (Assembly): Assembly to test
        tolerance (float, optional): maximum allowable volume difference. Defaults to 1e-5.

    Returns:
        bool: do the object intersect
    """
    shapes = [
        shape.moved(self.findLocation(name))
        if isinstance(shape, Shape)
        else shape.val().moved(self.findLocation(name))
        for name, part in self.traverse()
        for shape in part.shapes
    ]
    shape_index_pairs = [
        tuple(map(int, comb))
        for comb in combinations([i for i in range(len(shapes))], 2)
    ]
    for shape_index_pair in shape_index_pairs:
        common_volume = (
            shapes[shape_index_pair[0]].intersect(shapes[shape_index_pair[1]]).Volume()
        )
        if common_volume > tolerance:
            return True
    return False
Assembly.doObjectsIntersect = _doObjectsIntersect

Here I'm testing all combination of 2 parts for a volume of intersection. You likely can cheat and only test sequential toruses.
15:24:50
@_discord_896482168103125002:t2bot.ioRoger Maitland#7070 Ever have a hard time tracking what's going on deep in your design?

I'm in the middle of debugging a finger joint extension and found logging is really helping me. Here is how I create a log:
logging.debug(
    f"Corner {corner}, {cornerFaceCounter[corner]=}, start={corner == start_vertex}, normal={self.normalAt(face_center)}"
)

with this setup:
import logging

# Logging configuration - all cq_warehouse logs are level DEBUG or WARNING
logging.basicConfig(
    filename="cq_warehouse.log",
    encoding="utf-8",
    level=logging.DEBUG,
    # level=logging.CRITICAL,
    format="%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)s - %(funcName)20s() ] - %(message)s",
)

which generates the following in a log file:
2022-05-16 11:04:48,847 - DEBUG - [extensions.py:1942 - _makeFingerJoints_face() ] - Corner Vertex: (10.0, -50.0, 0.0), cornerFaceCounter[corner]=2, start=False, normal=Vector: (0.0, -1.0, -0.0)
2022-05-16 11:04:48,911 - DEBUG - [extensions.py:1942 - _makeFingerJoints_face() ] - Corner Vertex: (10.0, -20.0, 0.0), cornerFaceCounter[corner]=3, start=False, normal=Vector: (1.0, -0.0, -0.0)
2022-05-16 11:04:48,939 - DEBUG - [extensions.py:1942 - _makeFingerJoints_face() ] - Corner Vertex: (10.0, -50.0, 0.0), cornerFaceCounter[corner]=3, start=True, normal=Vector: (-0.0, -0.0, -1.0)

These logs can be suppressed by changing the logging level to something higher than DEBUG without having to go back and comment out print statements. They show the time (down to the millisecond), line number, method and message which is super useful.

Logs likely won't be anything new if you develop S/W professionally, but if you haven't used them and are looking for more visibility into your code they might be helpful.
15:44:36

There are no newer messages yet.


Back to Room List