AttributeError: 'NoneType' object has no attribute 'faces'
alfredopalhares opened this issue · comments
First of all, thank you for creating this awesome library for quicly making dynamic gridfinity supports and tools.
I am trying to make a Drawer Spacer set, with this:
from cqgridfinity import *
spacer = GridfinityDrawerSpacer(510, 303, verbose=True)
spacer.render_half_set()
This produces:
-> % python __main__.py
Best fit for 510.00 x 303.00 mm is 12U x 7U
with 3.00 mm margin each side and 4.50 mm margin front and back
Front/back spacers : not required
Left/right spacers : not required
Traceback (most recent call last):
File "/home/masterkorp/tmp/mesa-gridfinity/__main__.py", line 6, in <module>
spacer.render_half_set()
File "/home/masterkorp/tmp/mesa-gridfinity/venv/lib/python3.11/site-packages/cqgridfinity/gf_drawer.py", line 335, in render_half_s
et
bl = self.render(arrows_bottom=False)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/masterkorp/tmp/mesa-gridfinity/venv/lib/python3.11/site-packages/cqgridfinity/gf_drawer.py", line 176, in render
r = r.faces(">Z or <Z").chamfer(self.safe_chamfer_rad)
^^^^^^^
AttributeError: 'NoneType' object has no attribute 'faces'
I am using the library in a virtualenv:
-> % pip list
Package Version
----------------- -------
cadquery 2.4.0
cadquery-ocp 7.7.2
casadi 3.6.4
cqgridfinity 0.5.5
cqkit 0.5.3
ezdxf 1.1.4
fonttools 4.49.0
multimethod 1.9.1
nlopt 2.7.1
nptyping 2.0.1
numpy 1.26.4
path 16.10.0
pip 23.2.1
pyparsing 3.1.1
setuptools 65.5.0
typing_extensions 4.9.0
typish 1.9.3
Any sugestions ?
@alfredopalhares Thanks for the kind words about cq-gridfinity and hope you find it useful. Looking quickly at your issue, it appears that the dimensions you've chosen result in a grid which has only 4 mm margins and therefore does not require any spacer elements to be made. This is because there is a min_margin
attribute in the GridfinityDrawerSpacer
class. This attribute limits how small a spacer element can be and has a default value of 4 mm. It can be changed as a keyword argument. When running with your test case,
spacers = GridfinityDrawerSpacer(510, 303, verbose=True)
# Best fit for 510.00 x 303.00 mm is 12U x 7U
# with 3.00 mm margin each side and 4.50 mm margin front and back
# Front/back spacers : not required
# Left/right spacers : not required
We can see that no spacers are actually required.
If we set the min_margin
to 3, front/back spacers are required since 4.0 > 3.0 mm margin
spacers = GridfinityDrawerSpacer(510, 303, min_margin=3, verbose=True)
# Best fit for 510.00 x 303.00 mm is 12U x 7U
# with 3.00 mm margin each side and 4.50 mm margin front and back
# Corner spacers : 4U wide x 4.00 mm
# Front/back spacers : 4U wide x 4.00 mm +0.50 mm tolerance
# Left/right spacers : not required
And finally if we set min_margin
to 2, both front/back and left/right spacers are required:
spacers = GridfinityDrawerSpacer(510, 303, min_margin=2, verbose=True)
# Best fit for 510.00 x 303.00 mm is 12U x 7U
# with 3.00 mm margin each side and 4.50 mm margin front and back
# Corner spacers : 4U wide x 2U deep
# Front/back spacers : 4U wide x 4.00 mm +0.50 mm tolerance
# Left/right spacers : 3U deep x 2.50 mm +0.50 mm tolerance
What your test case did also show is that there were two bugs in cq-gridfinity:
GridfinityDrawerSpacer
render methods should not attempt to generate spacer components if both front/back and left/right spacing falls belowmin_margin
. This has been fixed with a guard to check both before any render.- The fillet radius of spacer elements was hard coded to a fixed value. This value needs to be bounded so that it is also less than the minimum feature size.
These changes have been made and a new version v.0.5.6 has been released. Hopefully that works.
Thank you for you elaborate response, I did not now that we had a minimum radius, my goal was to draw everything in one go and output it to a script to it can be resulable. Now you fix in v0.5.6 the script does not fail.
This is what I wanted, thank you so much for the fix and the explanation.
@alfredopalhares Glad it worked! Thanks for catching the issue.