gumyr / build123d

A python CAD programming library
Apache License 2.0
386 stars 72 forks source link

Issue with inheriting BasePartObject #600

Closed timacro closed 2 months ago

timacro commented 3 months ago

Hi,

I try to define a BlockA by inheriting BasePartObject, and then define BlockB by inheriting from BlockA, in order to continuing to build parts in BlockB, but I encounter the following error:

ValueError                                Traceback (most recent call last)
Cell In[2], [line 21](vscode-notebook-cell:?execution_count=2&line=21)
     [18](vscode-notebook-cell:?execution_count=2&line=18)             extrude(amount=10)
     [19](vscode-notebook-cell:?execution_count=2&line=19)         BasePartObject.__init__(self, part=self.bp.part)
---> [21](vscode-notebook-cell:?execution_count=2&line=21) show(BlockB())

Cell In[2], [line 18](vscode-notebook-cell:?execution_count=2&line=18)
     [16](vscode-notebook-cell:?execution_count=2&line=16)     with BuildSketch(self.bp.faces() >> Axis.Z):
     [17](vscode-notebook-cell:?execution_count=2&line=17)         Circle(5)
---> [18](vscode-notebook-cell:?execution_count=2&line=18)     extrude(amount=10)
     [19](vscode-notebook-cell:?execution_count=2&line=19) BasePartObject.__init__(self, part=self.bp.part)

File [d:\conda\envs\build123d\Lib\site-packages\build123d\operations_part.py:103](file:///D:/conda/envs/build123d/Lib/site-packages/build123d/operations_part.py:103), in extrude(to_extrude, amount, dir, until, target, both, taper, clean, mode)
    [101](file:///D:/conda/envs/build123d/Lib/site-packages/build123d/operations_part.py:101)         context.pending_face_planes = []
    [102](file:///D:/conda/envs/build123d/Lib/site-packages/build123d/operations_part.py:102)     else:
--> [103](file:///D:/conda/envs/build123d/Lib/site-packages/build123d/operations_part.py:103)         raise ValueError("A face or sketch must be provided")
    [104](file:///D:/conda/envs/build123d/Lib/site-packages/build123d/operations_part.py:104) else:
    [105](file:///D:/conda/envs/build123d/Lib/site-packages/build123d/operations_part.py:105)     # Get the faces from the face or sketch
    [106](file:///D:/conda/envs/build123d/Lib/site-packages/build123d/operations_part.py:106)     to_extrude_faces = (
    [107](file:///D:/conda/envs/build123d/Lib/site-packages/build123d/operations_part.py:107)         [*to_extrude]
    [108](file:///D:/conda/envs/build123d/Lib/site-packages/build123d/operations_part.py:108)         if isinstance(to_extrude, (tuple, list, filter))
    [109](file:///D:/conda/envs/build123d/Lib/site-packages/build123d/operations_part.py:109)         else to_extrude.faces()
    [110](file:///D:/conda/envs/build123d/Lib/site-packages/build123d/operations_part.py:110)     )

ValueError: A face or sketch must be provided

It seems BuildSketch doesn't pending a face created by Circle(5) into a sketch, have no idea about that.

Here is my code:

from build123d import *
from ocp_vscode import *
show_clear()

class BlockA(BasePartObject):
    def __init__(self):
        with BuildPart() as bp:
            Box(20,20,10)
        super().__init__(part=bp.part)
        self.bp = bp

class BlockB(BlockA):
    def __init__(self):
        super().__init__()
        with self.bp:
            with BuildSketch(self.bp.faces() >> Axis.Z):
                Circle(5)
            extrude(amount=10)
        BasePartObject.__init__(self, part=self.bp.part)

show(BlockB())
timacro commented 3 months ago

solved:

to_extrude must be explicitly specified when invoking extrude.

from build123d import *
from ocp_vscode import *
show_clear()

class BlockA(BasePartObject):
    def __init__(self):
        with BuildPart() as bp:
            Box(20,20,10)
        super().__init__(part=bp.part)
        self.bp = bp

class BlockB(BlockA):
    def __init__(self):
        super().__init__()
        with self.bp:
            with BuildSketch(self.faces() >> Axis.Z) as sk:
                Circle(5)
            extrude(to_extrude=sk.sketch, amount=10)
        BasePartObject.__init__(self, part=self.bp.part)

show(BlockB())

But don't know why Implicit Builder Instance Variable fails here.

gumyr commented 3 months ago

You're trying to re-use a BuildPart instance created in BlockA in BlockB which is not supported. However, the Part from BlockA can be added to BlockB like this:

class BlockB(BlockA):
    def __init__(self):
        super().__init__()
        print(f"{self.bp=}")
        with BuildPart() as blockb_builder:
            add(self.bp.part)
            with BuildSketch(blockb_builder.faces() >> Axis.Z):
                Circle(5)
            extrude(amount=10)
        BasePartObject.__init__(self, part=blockb_builder.part)

image

There is an open Issue to add this functionality to a Builder: https://github.com/gumyr/build123d/issues/108

timacro commented 2 months ago

@gumyr Thanks! #108 is really helpful to me!