Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weird "Fillets requires that edges be selected" exception #1553

Open
KizzyCode opened this issue Mar 31, 2024 · 3 comments
Open

Weird "Fillets requires that edges be selected" exception #1553

KizzyCode opened this issue Mar 31, 2024 · 3 comments

Comments

@KizzyCode
Copy link

KizzyCode commented Mar 31, 2024

To Reproduce

I'm trying to build some gridfinity stuff, therefore I'm trying to to build the baseplate in CadQuery. However I'm getting some weird Fillets requires that edges be selected-exception.

(The following code are cells from a Jupyter-notebook, where each ##### marks a different cell)

rounding_diameter = 7_500
outer_width = 42_000

layer0_inner = 42_000 - ((2_150 + 700) * 2)
layer0_height = 700
layer0_rounding_diameter_inner = rounding_diameter - (outer_width - layer0_inner)

layer1_inner = 42_000 - (2_150 * 2)
layer1_height = 1_800
layer1_rounding_diameter_inner = rounding_diameter - (outer_width - layer1_inner)

layer2_inner = 42_000 - (2_150 * 2)
layer2_height = 1_900
layer2_rounding_diameter_inner = rounding_diameter - (outer_width - layer2_inner)

#####

from cadquery import Workplane

object = Workplane()\
    .box(outer_width, outer_width, layer0_height, centered=[True, True, False])\
    .faces(">Z")\
        .workplane(invert=True)\
        .box(layer0_inner, layer0_inner, layer0_height, centered=[True, True, False], combine="cut")\
    .edges("|Z and (>X or <X)")\
        .fillet(rounding_diameter / 2)\
    .edges("|Z")\
        .fillet(layer0_rounding_diameter_inner / 2)

display(object)

#####

object = object\
    .faces(">Z")\
        .workplane()\
        .box(outer_width, outer_width, layer1_height, centered=[True, True, False])\
    .faces(">Z")\
        .workplane(invert=True)\
        .box(layer1_inner, layer1_inner, layer1_height, centered=[True, True, False], combine="cut")\
    .edges("|Z and (>X or <X)")\
        .fillet(rounding_diameter / 2)\
    .edges("|Z")\
        .fillet(layer1_rounding_diameter_inner / 2)

display(object)

#####

object = object\
    .faces(">Z")\
        .workplane()\
        .box(outer_width, outer_width, layer2_height, centered=[True, True, False])\
    .faces(">Z")\
        .workplane(invert=True)\
        .box(layer2_inner, layer2_inner, layer2_height, centered=[True, True, False], combine="cut")\
    .edges("|Z and (>X or <X)")\
        .fillet(rounding_diameter / 2)\ # <--- THIS IS THE LINE TRIGGERING THE EXCEPTION
    .edges("|Z")\
        .fillet(layer2_rounding_diameter_inner / 2)

display(object)

The weird thing is: If I change the rounding_diameter / 2 to either rounding_diameter / 2.00001 OR rounding_diameter / 1.99999, it does not throw... for me this looks like some kind of floating point error; but then I'm a noob regarding CAD-kernels, and I'm pretty confused that it works with a deviation in both directions.
Also I'm a newby with CadQuery, so please bear with me if I'm completely misunderstanding some concepts here 🙈

Backtrace

{
	"name": "StdFail_NotDone",
	"message": "BRep_API: command not done",
	"stack": "---------------------------------------------------------------------------
StdFail_NotDone                           Traceback (most recent call last)
Cell In[117], line 9
      1 object = object\\
      2     .faces(\">Z\")\\
      3         .workplane()\\
      4         .box(outer_width, outer_width, layer2_height, centered=[True, True, False])\\
      5     .faces(\">Z\")\\
      6         .workplane(invert=True)\\
      7         .box(layer2_inner, layer2_inner, layer2_height, centered=[True, True, False], combine=\"cut\")\\
      8     .edges(\"|Z and (>X or <X)\")\\
----> 9         .fillet(rounding_diameter / 2)\\
     10     .edges(\"|Z\")\\
     11         .fillet(layer2_rounding_diameter_inner / 2)
     13 display(object)

File /usr/local/lib/python3.11/dist-packages/cadquery/cq.py:1304, in Workplane.fillet(self, radius)
   1301 if len(edgeList) < 1:
   1302     raise ValueError(\"Fillets requires that edges be selected\")
-> 1304 s = solid.fillet(radius, edgeList)
   1305 return self.newObject([s.clean()])

File /usr/local/lib/python3.11/dist-packages/cadquery/occ_impl/shapes.py:2780, in Mixin3D.fillet(self, radius, edgeList)
   2777 for e in nativeEdges:
   2778     fillet_builder.Add(radius, e)
-> 2780 return self.__class__(fillet_builder.Shape())

StdFail_NotDone: BRep_API: command not done"
}

Environment

OS: VSCode dev container running Debian on M1Pro-MacBook Pro:

FROM mcr.microsoft.com/devcontainers/base:debian

ENV APT_PACKAGES libgl1 libnlopt0 libnlopt-cxx0 python3 python3-dev python3-nlopt python3-pip
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update \
    && apt-get upgrade --yes \
    && apt-get install --yes --no-install-recommends ${APT_PACKAGES} \
    && apt-get autoremove --yes \
    && apt-get clean

RUN pip install --break-system-packages \
    ipykernel
# Manually install top-level dependencies of `cadquery` except `nlopt`
RUN pip install --break-system-packages \
    casadi \
    ezdxf \
    multimethod==1.9.1 \
    nptyping==2.0.1 \
    path \
    typish \
    https://github.com/CadQuery/ocp-build-system/releases/download/7.7.2.0/cadquery_ocp-7.7.2-cp311-cp311-manylinux_2_35_aarch64.whl
# Install `cadquery` without automatic dependency resolution
RUN pip install --break-system-packages --no-deps \
    cadquery

Also see my attached workspace if it is any use: Gridfinity.zip

@KizzyCode KizzyCode added the bug Something isn't working label Mar 31, 2024
@lorenzncode
Copy link
Member

It looks like you are creating rounded walls. In general, it's recommended to create this kind of shape in 2D. I don't know the root cause of the issue with your code, however, I'd suggest to try moving the fillet to 2D with something like this:

import cadquery as cq


def make_wall(w1, w2, d1, d2) -> cq.Sketch:
    return (
        cq.Sketch()
        .rect(w1, w1, tag="outer")
        .rect(w2, w2, mode="s", tag="inner")
        .vertices(tag="outer")
        .fillet(d1 / 2)
        .vertices(tag="inner")
        .fillet(d2 / 2)
    )


res = (
    cq.Workplane()
    .placeSketch(make_wall(50, 40, 10, 5))
    .extrude(10)
    .faces(">Z")
    .workplane()
    .placeSketch(make_wall(50, 45, 10, 5))
    .extrude(5)
)

@KizzyCode
Copy link
Author

Thanks, will try it like this instead. Please feel free to close this if it is out-of-scope or probably a problem with the underlying CAD-kernel 😊

@lorenzncode
Copy link
Member

Yes AFAICT it's a kernel issue. Here is a minimal example. It fails with same error as original code.:

import cadquery as cq

b0 = cq.Workplane().box(100, 100, 5).edges(">XY").fillet(10)

b1 = (
    b0.faces(">Z")
    .box(100, 100, 5, centered=[True, True, False])
    .edges(">XY")
    .fillet(10)
)

A workaround could be to set combine to False in b1, then union after the b1 fillet

b1 = (
    b0.faces(">Z")
    .box(100, 100, 5, centered=[True, True, False], combine=False)
    .edges(">XY")
    .fillet(10)
)

b1 = b1.union(b0)

... or move the fillet to 2D as in the previous example.

@lorenzncode lorenzncode added OCC kernel issue and removed bug Something isn't working labels Apr 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants