CadQuery / cadquery

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

Same code produces different outputs #1516

Closed XiXinping closed 8 months ago

XiXinping commented 9 months ago

Hey there, I've been using CadQuery for about two weeks, and so far I've been really enjoying it. I've noticed, though, that when I run code that creates an assembly with constraints and save it to a file, the model occasionally renders completely incorrectly. If I run the exact same code with zero modifications, I've found it'll render incorrectly about once or twice per 10 runs. This seems to happen pretty randomly, and I can't think of anything that's causing it. I'm currently outputting to an STL file, but I've found the same thing happens with STEP.

Here are some pictures of what I'm talking about. This is what the model is supposed to look like: correct_model

This is one variant of the incorrect rendering: screwed_up_model1

Here's another flavor: screwed_up_model2

All three variants were produced with the same code:

from cadquery import (
    importers,
    Assembly,
    Color,
    Location,
    Vector,
    Workplane,
)

def left_tubes(length: int) -> Workplane:
    pvc_radius = 10.766
    # center to center width
    width = 332.111
    # center to center height
    height = 132.165

    #  total_width = 360.0
    total_height = 160.054

    # total height 160.054
    # total width 360.000
    # padding 13.945
    return (
        Workplane("YZ")
        .rect(width, total_height - pvc_radius / 2, forConstruction=True)
        .vertices("<Y and <X")
        .tag("bottom_left")
        .translate(Vector(-length, 0, 0))
        .tag("bottom_back_left")
        .end()
        .end()
        .rect(width, height, forConstruction=True)
        .vertices()
        .circle(pvc_radius)
        .extrude(-length)
    )

def right_tubes(length: int) -> Workplane:
    pvc_radius = 10.766
    # center to center width
    width = 332.111
    # center to center height
    height = 290.805

    total_height = 318.694
    # total length 360.000
    return (
        Workplane("YZ")
        .rect(width, total_height - pvc_radius / 2, forConstruction=True)
        .vertices("<Y and <X")
        .tag("bottom_left")
        .translate(Vector(length, 0, 0))
        .tag("bottom_back_left")
        .end()
        .end()
        .rect(width, height, forConstruction=True)
        .vertices()
        .circle(pvc_radius)
        .extrude(length)
    )

def top_tubes(height: int) -> Workplane:
    pvc_radius = 10.766
    # center to center length
    length = 346.5
    # center to center width
    width = 332.111

    total_length = 374.389
    #  total_width = 360.000

    return (
        Workplane("XY")
        .rect(
            total_length - pvc_radius / 2,
            width,
            forConstruction=True,
        )
        .vertices(">Y and >X")
        .tag("bottom_anchor_point")
        .translate(Vector(0, 0, height))
        .tag("top_anchor_point")
        .end()
        .end()
        .rect(length, width, forConstruction=True)
        .vertices()
        .circle(12)
        .extrude(height)
    )

left_side = importers.importStep("assets/left_side.step")
right_side = importers.importStep("assets/right_side.step")
top_side = importers.importStep("assets/top_side_with_coral.step")
center_box = importers.importStep("assets/center_box.step")

left_tubes = left_tubes(300)
right_tubes = right_tubes(400)
top_tubes = top_tubes(400)

assembly = (
    Assembly()
    .add(
        center_box,
        name="center_box",
        loc=Location(Vector(0, 0, 0)),
        color=Color("red"),
    )
    .add(left_side, name="left_side")
    .add(right_side, name="right_side")
    .add(left_tubes, name="left_tubes")
    .add(right_tubes, name="right_tubes")
    .add(top_side, name="top_side")
    .add(top_tubes, name="top_tubes")
)
assembly.constrain("center_box", "Fixed")

# left side
assembly.constrain("left_side", "FixedRotation", (0, 0, 0))
assembly.constrain("left_tubes", "FixedRotation", (0, 0, 0))
assembly.constrain(
    "left_side@vertices@>(1, -1, -1)",
    "left_tubes?bottom_back_left",
    "Point",
)

assembly.constrain(
    "left_tubes?bottom_left", "center_box@vertices@>(-1, -1, -1)", "Point"
)
# right side
assembly.constrain("right_side", "FixedRotation", (0, 0, 0))
assembly.constrain("right_tubes", "FixedRotation", (0, 0, 0))

assembly.constrain(
    "right_side@vertices@>(-1, -1, -1)",
    "right_tubes?bottom_back_left",
    "Point",
)
assembly.constrain(
    "right_tubes?bottom_left", "center_box@vertices@>(1, -1, -1)", "Point"
)
assembly.constrain("right_tubes", "FixedRotation", (0, 0, 0))

# top side
assembly.constrain("top_side", "FixedRotation", (0, 0, 0))
assembly.constrain("top_tubes", "FixedRotation", (0, 0, 0))
assembly.constrain(
    "top_side@vertices@>(1, 1, -1)", "top_tubes?top_anchor_point", "Point"
)
assembly.constrain(
    "top_tubes?bottom_anchor_point", "center_box@vertices@>(1, 1, 1)", "Point"
)

assembly.solve()

assembly.save("result.stl")

I'm currently running CadQuery 2.4.0 installed via pip in a Python 3.11.5 virtual environment. I'm viewing the outputted models in F3D. My operating system is Manjaro Linux, although I've tried running it in a virtual environment on Ubuntu Server 20.04 and I've gotten the same issue. I'm wondering if anyone else can replicate this issue. I'm not sure if this is a bug, or if there's something I'm doing wrong. I'd greatly appreciate help with this. Thank you!

adam-urbanczyk commented 9 months ago

Cannot reproduce without you sharing the steps

XiXinping commented 9 months ago

I have the code in a file called main.py I run python main.py And then run f3d result.stl to view the model

Let me know if there's any other info you need. Thank you!

adam-urbanczyk commented 9 months ago

Sorry, I meant STEPs, so STEP files.

XiXinping commented 9 months ago

Ohhhhh. Sorry about that. Here they are: step_files.zip

XiXinping commented 8 months ago

Hey there, I'm still struggling with this issue and haven't found any way to fix it. I'd greatly appreciate if someone could let me know if there's a problem with my code or if this is an issue with Cadquery. Thanks!

lorenzncode commented 8 months ago

In left_tubes you have tagged two vertices. You can check the selection with.: left_tubes.vertices(tag="bottom_left").vals()

To fix it select a single vertex for the Point constraint.

Change the selector from .vertices("<Y and <X") to .vertices("<YZ")

Do the same for right_tubes.

XiXinping commented 8 months ago

That seemed to fix it! Thank you! I'm not 100% sure why it generates different results randomly, but at least I know how to avoid it. Thanks again.