diff --git a/commands/commandCreateBin/entry.py b/commands/commandCreateBin/entry.py index 927f5e2..d813680 100644 --- a/commands/commandCreateBin/entry.py +++ b/commands/commandCreateBin/entry.py @@ -92,9 +92,11 @@ BIN_HAS_SCOOP_INPUT_ID = 'bin_has_scoop' BIN_SCOOP_MAX_RADIUS_INPUT_ID = 'bin_scoop_max_radius' BIN_HAS_TAB_INPUT_ID = 'bin_has_tab' +BIN_TAB_IS_HOLLOW_INPUT_ID = 'tab_is_hollow' BIN_TAB_LENGTH_INPUT_ID = 'bin_tab_length' BIN_TAB_WIDTH_INPUT_ID = 'bin_tab_width' BIN_TAB_POSITION_INPUT_ID = 'bin_tab_position' +BIN_TAB_LABEL_ANGLE_INPUT_ID = 'bin_tab_label_angle' BIN_TAB_ANGLE_INPUT_ID = 'bin_tab_angle' BIN_WITH_LIP_INPUT_ID = 'with_lip' BIN_WITH_LIP_NOTCHES_INPUT_ID = 'with_lip_notches' @@ -177,10 +179,12 @@ def initDefaultUiState(): commandUIState.initValue(BIN_SCOOP_MAX_RADIUS_INPUT_ID, const.BIN_SCOOP_MAX_RADIUS, adsk.core.ValueCommandInput.classType()) commandUIState.initValue(BIN_HAS_TAB_INPUT_ID, False, adsk.core.BoolValueCommandInput.classType()) + commandUIState.initValue(BIN_TAB_IS_HOLLOW_INPUT_ID, False, adsk.core.BoolValueCommandInput.classType()) commandUIState.initValue(BIN_TAB_LENGTH_INPUT_ID, 1, adsk.core.ValueCommandInput.classType()) commandUIState.initValue(BIN_TAB_WIDTH_INPUT_ID, const.BIN_TAB_WIDTH, adsk.core.ValueCommandInput.classType()) commandUIState.initValue(BIN_TAB_POSITION_INPUT_ID, 0, adsk.core.ValueCommandInput.classType()) - commandUIState.initValue(BIN_TAB_ANGLE_INPUT_ID, '45 deg', adsk.core.ValueCommandInput.classType()) + commandUIState.initValue(BIN_TAB_LABEL_ANGLE_INPUT_ID, f'{const.BIN_TAB_LABEL_ANGLE} DEG', adsk.core.ValueCommandInput.classType()) + commandUIState.initValue(BIN_TAB_ANGLE_INPUT_ID, f'{const.BIN_TAB_OVERHANG_ANGLE} DEG', adsk.core.ValueCommandInput.classType()) commandUIState.initValue(BIN_GENERATE_BASE_INPUT_ID, True, adsk.core.BoolValueCommandInput.classType()) commandUIState.initValue(BIN_SCREW_HOLES_INPUT_ID, False, adsk.core.BoolValueCommandInput.classType()) @@ -449,6 +453,7 @@ def is_all_input_valid(inputs: adsk.core.CommandInputs): binTabLength: adsk.core.ValueCommandInput = inputs.itemById(BIN_TAB_LENGTH_INPUT_ID) binTabWidth: adsk.core.ValueCommandInput = inputs.itemById(BIN_TAB_WIDTH_INPUT_ID) binTabPosition: adsk.core.ValueCommandInput = inputs.itemById(BIN_TAB_POSITION_INPUT_ID) + binTabLabelAngle: adsk.core.ValueCommandInput = inputs.itemById(BIN_TAB_LABEL_ANGLE_INPUT_ID) binTabAngle: adsk.core.ValueCommandInput = inputs.itemById(BIN_TAB_ANGLE_INPUT_ID) binTypeDropdownInput: adsk.core.DropDownCommandInput = inputs.itemById(BIN_TYPE_DROPDOWN_ID) binCompartmentGridTypeDropdownInput: adsk.core.DropDownCommandInput = inputs.itemById(BIN_COMPARTMENTS_GRID_TYPE_ID) @@ -603,12 +608,20 @@ def command_created(args: adsk.core.CommandCreatedEventArgs): commandUIState.registerCommandInput(binTabFeaturesGroup) generateTabCheckboxinput = binTabFeaturesGroup.children.addBoolValueInput(BIN_HAS_TAB_INPUT_ID, 'Add label tab (along bin width)', True, '', commandUIState.getState(BIN_HAS_TAB_INPUT_ID)) commandUIState.registerCommandInput(generateTabCheckboxinput) + binTabIsHollowInput = binTabFeaturesGroup.children.addBoolValueInput(BIN_TAB_IS_HOLLOW_INPUT_ID, 'Hollow tab', True, '', commandUIState.getState(BIN_TAB_IS_HOLLOW_INPUT_ID)) + commandUIState.registerCommandInput(binTabIsHollowInput) binTabLengthInput = binTabFeaturesGroup.children.addValueInput(BIN_TAB_LENGTH_INPUT_ID, 'Tab length (u)', '', adsk.core.ValueInput.createByReal(commandUIState.getState(BIN_TAB_LENGTH_INPUT_ID))) commandUIState.registerCommandInput(binTabLengthInput) binTabWidthInput = binTabFeaturesGroup.children.addValueInput(BIN_TAB_WIDTH_INPUT_ID, 'Tab width (mm)', defaultLengthUnits, adsk.core.ValueInput.createByReal(commandUIState.getState(BIN_TAB_WIDTH_INPUT_ID))) commandUIState.registerCommandInput(binTabWidthInput) binTabPostionInput = binTabFeaturesGroup.children.addValueInput(BIN_TAB_POSITION_INPUT_ID, 'Tab offset (u)', '', adsk.core.ValueInput.createByReal(commandUIState.getState(BIN_TAB_POSITION_INPUT_ID))) commandUIState.registerCommandInput(binTabPostionInput) + binTabLabelAngleInput = binTabFeaturesGroup.children.addValueInput(BIN_TAB_LABEL_ANGLE_INPUT_ID, 'Tab label angle', 'deg', adsk.core.ValueInput.createByString(str(commandUIState.getState(BIN_TAB_LABEL_ANGLE_INPUT_ID)))) + binTabLabelAngleInput.minimumValue = math.radians(0) + binTabLabelAngleInput.isMinimumInclusive = True + binTabLabelAngleInput.maximumValue = math.radians(90) + binTabLabelAngleInput.isMaximumInclusive = True + commandUIState.registerCommandInput(binTabLabelAngleInput) tabObverhangAngleInput = binTabFeaturesGroup.children.addValueInput(BIN_TAB_ANGLE_INPUT_ID, 'Tab overhang angle', 'deg', adsk.core.ValueInput.createByString(str(commandUIState.getState(BIN_TAB_ANGLE_INPUT_ID)))) tabObverhangAngleInput.minimumValue = math.radians(30) tabObverhangAngleInput.isMinimumInclusive = True @@ -821,8 +834,10 @@ def onChangeValidate(): commandUIState.getInput(BIN_SCOOP_MAX_RADIUS_INPUT_ID).isEnabled = generateScoop generateTab: bool = commandUIState.getState(BIN_HAS_TAB_INPUT_ID) + commandUIState.getInput(BIN_TAB_IS_HOLLOW_INPUT_ID).isEnabled = generateTab commandUIState.getInput(BIN_TAB_LENGTH_INPUT_ID).isEnabled = generateTab commandUIState.getInput(BIN_TAB_WIDTH_INPUT_ID).isEnabled = generateTab + commandUIState.getInput(BIN_TAB_LABEL_ANGLE_INPUT_ID).isEnabled = generateTab commandUIState.getInput(BIN_TAB_ANGLE_INPUT_ID).isEnabled = generateTab commandUIState.getInput(BIN_TAB_POSITION_INPUT_ID).isEnabled = generateTab @@ -866,9 +881,11 @@ def generateBin(args: adsk.core.CommandEventArgs): has_scoop: adsk.core.BoolValueCommandInput = inputs.itemById(BIN_HAS_SCOOP_INPUT_ID) binScoopMaxRadius: adsk.core.ValueCommandInput = inputs.itemById(BIN_SCOOP_MAX_RADIUS_INPUT_ID) hasTabInput: adsk.core.BoolValueCommandInput = inputs.itemById(BIN_HAS_TAB_INPUT_ID) + binTabIsHollow: adsk.core.BoolValueCommandInput = inputs.itemById(BIN_TAB_IS_HOLLOW_INPUT_ID) binTabLength: adsk.core.ValueCommandInput = inputs.itemById(BIN_TAB_LENGTH_INPUT_ID) binTabWidth: adsk.core.ValueCommandInput = inputs.itemById(BIN_TAB_WIDTH_INPUT_ID) binTabPosition: adsk.core.ValueCommandInput = inputs.itemById(BIN_TAB_POSITION_INPUT_ID) + binTabLabelAngle: adsk.core.ValueCommandInput = inputs.itemById(BIN_TAB_LABEL_ANGLE_INPUT_ID) binTabAngle: adsk.core.ValueCommandInput = inputs.itemById(BIN_TAB_ANGLE_INPUT_ID) binTypeDropdownInput: adsk.core.DropDownCommandInput = inputs.itemById(BIN_TYPE_DROPDOWN_ID) binCompartmentGridTypeDropdownInput: adsk.core.DropDownCommandInput = inputs.itemById(BIN_COMPARTMENTS_GRID_TYPE_ID) @@ -938,9 +955,11 @@ def generateBin(args: adsk.core.CommandEventArgs): binBodyInput.hasScoop = has_scoop.value and isHollow binBodyInput.scoopMaxRadius = binScoopMaxRadius.value binBodyInput.hasTab = hasTabInput.value and isHollow + binBodyInput.isTabHollow = binTabIsHollow.value binBodyInput.tabLength = binTabLength.value binBodyInput.tabWidth = binTabWidth.value binBodyInput.tabPosition = binTabPosition.value + binBodyInput.tabLabelAngle = binTabLabelAngle.value binBodyInput.tabOverhangAngle = binTabAngle.value binBodyInput.compartmentsByX = compartmentsX.value binBodyInput.compartmentsByY = compartmentsY.value @@ -1017,9 +1036,11 @@ def generateBin(args: adsk.core.CommandEventArgs): compartmentTabInput.origin = tabOriginPoint compartmentTabInput.length = max(0, min(binBodyInput.tabLength, binBodyInput.binWidth)) * binBodyInput.baseWidth - binBodyInput.wallThickness * 2 - binBodyInput.xyClearance * 2 compartmentTabInput.width = binBodyInput.tabWidth + compartmentTabInput.isTabHollow = binBodyInput.isTabHollow + compartmentTabInput.labelAngle = binBodyInput.tabLabelAngle compartmentTabInput.overhangAngle = binBodyInput.tabOverhangAngle compartmentTabInput.topClearance = const.BIN_TAB_TOP_CLEARANCE - tabBody = createGridfinityBinBodyTab(compartmentTabInput, gridfinityBinComponent) + tabBody, tabBodiesToSubtract = createGridfinityBinBodyTab(compartmentTabInput, gridfinityBinComponent) combineInput = combineFeatures.createInput(tabBody, commonUtils.objectCollectionFromList([binBody])) combineInput.operation = adsk.fusion.FeatureOperations.CutFeatureOperation combineInput.isKeepToolBodies = True diff --git a/lib/gridfinityUtils/binBodyGenerator.py b/lib/gridfinityUtils/binBodyGenerator.py index fa13ecc..82775be 100644 --- a/lib/gridfinityUtils/binBodyGenerator.py +++ b/lib/gridfinityUtils/binBodyGenerator.py @@ -142,6 +142,8 @@ def createGridfinityBinBody( compartmentTabInput.origin = tabOriginPoint compartmentTabInput.length = max(0, min(input.tabLength, input.binWidth)) * input.baseWidth compartmentTabInput.width = input.tabWidth + compartmentTabInput.isTabHollow = input.isTabHollow + compartmentTabInput.labelAngle = input.tabLabelAngle compartmentTabInput.overhangAngle = input.tabOverhangAngle compartmentTabInput.topClearance = const.BIN_TAB_TOP_CLEARANCE @@ -255,14 +257,16 @@ def createCompartment( # label tab if hasTab: - tabBody = createGridfinityBinBodyTab(tabInput, targetComponent) - - intersectTabInput = targetComponent.features.combineFeatures.createInput( - tabBody, - commonUtils.objectCollectionFromList([innerCutoutBody]), - ) - intersectTabInput.operation = adsk.fusion.FeatureOperations.IntersectFeatureOperation - intersectTabInput.isKeepToolBodies = True - intersectTabFeature = targetComponent.features.combineFeatures.add(intersectTabInput) - bodiesToMerge = bodiesToMerge + [body for body in list(intersectTabFeature.bodies) if not body.revisionId == innerCutoutBody.revisionId] + tabBody, tabBodiesToSubtract = createGridfinityBinBodyTab(tabInput, targetComponent) + if tabBody: + intersectTabInput = targetComponent.features.combineFeatures.createInput( + tabBody, + commonUtils.objectCollectionFromList([innerCutoutBody]), + ) + intersectTabInput.operation = adsk.fusion.FeatureOperations.IntersectFeatureOperation + intersectTabInput.isKeepToolBodies = True + intersectTabFeature = targetComponent.features.combineFeatures.add(intersectTabInput) + bodiesToMerge = bodiesToMerge + [body for body in list(intersectTabFeature.bodies) if not body.revisionId == innerCutoutBody.revisionId] + + bodiesToSubtract = bodiesToSubtract + tabBodiesToSubtract return (bodiesToMerge, bodiesToSubtract) \ No newline at end of file diff --git a/lib/gridfinityUtils/binBodyGeneratorInput.py b/lib/gridfinityUtils/binBodyGeneratorInput.py index 40eed7c..96b993d 100644 --- a/lib/gridfinityUtils/binBodyGeneratorInput.py +++ b/lib/gridfinityUtils/binBodyGeneratorInput.py @@ -188,6 +188,14 @@ def hasTab(self) -> bool: def hasTab(self, value: bool): self._hasTab = value + @property + def isTabHollow(self) -> bool: + return self._isTabHollow + + @isTabHollow.setter + def isTabHollow(self, value: bool): + self._isTabHollow = value + @property def tabWidth(self) -> float: return self._tabWidth @@ -212,6 +220,14 @@ def tabPosition(self) -> float: def tabPosition(self, value: float): self._tabPosition = value + @property + def tabLabelAngle(self) -> float: + return self._tabLabelAngle + + @tabLabelAngle.setter + def tabLabelAngle(self, value: float): + self._tabLabelAngle = value + @property def tabOverhangAngle(self) -> float: return self._tabOverhangAngle diff --git a/lib/gridfinityUtils/binBodyTabGenerator.py b/lib/gridfinityUtils/binBodyTabGenerator.py index 14a8b80..9210514 100644 --- a/lib/gridfinityUtils/binBodyTabGenerator.py +++ b/lib/gridfinityUtils/binBodyTabGenerator.py @@ -1,10 +1,11 @@ +import logging import adsk.core, adsk.fusion, traceback import os import math -from .const import BIN_TAB_EDGE_FILLET_RADIUS +from .const import BIN_TAB_EDGE_FILLET_RADIUS, BIN_WALL_THICKNESS, BIN_XY_CLEARANCE from ...lib.gridfinityUtils import geometryUtils from ...lib import fusion360utils as futil from ...lib.gridfinityUtils import filletUtils @@ -27,78 +28,133 @@ def getInnerCutoutScoopFace( def createGridfinityBinBodyTab( input: BinBodyTabGeneratorInput, targetComponent: adsk.fusion.Component, -): - +): + x_position = input.origin.x - BIN_WALL_THICKNESS tabProfilePlaneInput: adsk.fusion.ConstructionPlaneInput = targetComponent.constructionPlanes.createInput() tabProfilePlaneInput.setByOffset( targetComponent.yZConstructionPlane, - adsk.core.ValueInput.createByReal(input.origin.x) + adsk.core.ValueInput.createByReal(x_position) ) tabProfilePlane = targetComponent.constructionPlanes.add(tabProfilePlaneInput) tabSketch: adsk.fusion.Sketch = targetComponent.sketches.add(tabProfilePlane) tabSketch.name = "label tab sketch" tabSketchLine = tabSketch.sketchCurves.sketchLines tabTopEdgeHeight = input.origin.z - input.topClearance - actualTabWidth = input.width + BIN_TAB_EDGE_FILLET_RADIUS / math.tan((math.radians(90) - input.overhangAngle) / 2) - actualTabHeight = actualTabWidth / math.tan(input.overhangAngle) + + h1 = input.width * math.sin(input.labelAngle) + hr1 = BIN_TAB_EDGE_FILLET_RADIUS * math.cos(input.labelAngle) + wr1 = BIN_TAB_EDGE_FILLET_RADIUS*(1 - math.sin(input.labelAngle)) + hr2 = BIN_TAB_EDGE_FILLET_RADIUS * math.sin(input.overhangAngle) + wr2 = BIN_TAB_EDGE_FILLET_RADIUS*(1 - math.cos(input.overhangAngle)) + w = input.width * math.cos(input.labelAngle) + h2 = (w+wr1-wr2) / math.tan(input.overhangAngle) + h = h1 + h2 + hr1 + hr2 + + originPoint = adsk.core.Point3D.create( + x=x_position, + y=input.origin.y, + z=tabTopEdgeHeight + ) + + pt1 = adsk.core.Point3D.create( + x=x_position, + y=input.origin.y + BIN_WALL_THICKNESS, + z=tabTopEdgeHeight + BIN_WALL_THICKNESS*math.tan(input.labelAngle) + ) + pt2 = adsk.core.Point3D.create( + x=x_position, + y=input.origin.y + BIN_WALL_THICKNESS, + z=tabTopEdgeHeight - h - BIN_WALL_THICKNESS*math.tan(input.overhangAngle) + ) + pt3 = adsk.core.Point3D.create( + x=x_position, + y=input.origin.y - w, + z=tabTopEdgeHeight - h1 + ) + pt4 = adsk.core.Point3D.create( + x=x_position, + y=input.origin.y - w - wr1 + wr2, + z=tabTopEdgeHeight - h1 - hr1 - hr2 + ) + + fillet_center_pt = adsk.core.Point3D.create( + x=x_position, + y=input.origin.y - w - wr1 + const.BIN_TAB_EDGE_FILLET_RADIUS, + z=tabTopEdgeHeight - h1 - hr1 + ) + line1 = tabSketchLine.addByTwoPoints( - tabSketch.modelToSketchSpace(adsk.core.Point3D.create(input.origin.x, input.origin.y, tabTopEdgeHeight)), - tabSketch.modelToSketchSpace(adsk.core.Point3D.create(input.origin.x, input.origin.y, tabTopEdgeHeight - actualTabHeight)), + tabSketch.modelToSketchSpace(pt1), + tabSketch.modelToSketchSpace(pt2), ) line2 = tabSketchLine.addByTwoPoints( - tabSketch.modelToSketchSpace(adsk.core.Point3D.create(input.origin.x, input.origin.y, tabTopEdgeHeight)), - tabSketch.modelToSketchSpace(adsk.core.Point3D.create(input.origin.x, input.origin.y - actualTabWidth, tabTopEdgeHeight)), + tabSketch.modelToSketchSpace(pt1), + tabSketch.modelToSketchSpace(pt3), ) line3 = tabSketchLine.addByTwoPoints( - tabSketch.modelToSketchSpace(adsk.core.Point3D.create(input.origin.x, input.origin.y, tabTopEdgeHeight - actualTabHeight)), - tabSketch.modelToSketchSpace(adsk.core.Point3D.create(input.origin.x, input.origin.y - actualTabWidth, tabTopEdgeHeight)), + tabSketch.modelToSketchSpace(pt2), + tabSketch.modelToSketchSpace(pt4), ) + tabOriginSketchPoint = tabSketch.sketchPoints.add(tabSketch.modelToSketchSpace(originPoint)) + arc1 = tabSketch.sketchCurves.sketchArcs.addByCenterStartEnd( + tabSketch.modelToSketchSpace(fillet_center_pt), + line2.endSketchPoint, + line3.endSketchPoint + ) + constraints: adsk.fusion.GeometricConstraints = tabSketch.geometricConstraints dimensions: adsk.fusion.SketchDimensions = tabSketch.sketchDimensions - # horizontal/vertical relative to local sketch XY coordinates - constraints.addHorizontal(line1) - constraints.addVertical(line2) - constraints.addCoincident(line1.startSketchPoint, line2.startSketchPoint) - constraints.addCoincident(line2.endSketchPoint, line3.endSketchPoint) - constraints.addCoincident(line1.endSketchPoint, line3.startSketchPoint) + tabOriginSketchPoint.isFixed = True + constraints.addCoincident(tabOriginSketchPoint, line2) dimensions.addDistanceDimension( - tabSketch.originPoint, - line1.startSketchPoint, - adsk.fusion.DimensionOrientations.VerticalDimensionOrientation, - line1.startSketchPoint.geometry, + tabOriginSketchPoint, + line2.endSketchPoint, + adsk.fusion.DimensionOrientations.AlignedDimensionOrientation, + line2.endSketchPoint.geometry, True ) - dimensions.addDistanceDimension( - tabSketch.originPoint, + tabOriginSketchPoint, line1.startSketchPoint, - adsk.fusion.DimensionOrientations.HorizontalDimensionOrientation, + adsk.fusion.DimensionOrientations.VerticalDimensionOrientation, line1.startSketchPoint.geometry, True - ) + ) + # horizontal/vertical relative to local sketch XY coordinates + constraints.addHorizontal(line1) + constraints.addCoincident(line1.startSketchPoint, line2.startSketchPoint) + constraints.addCoincident(line1.endSketchPoint, line3.startSketchPoint) - dimensions.addDistanceDimension( - line2.startSketchPoint, - line2.endSketchPoint, - adsk.fusion.DimensionOrientations.VerticalDimensionOrientation, - line2.endSketchPoint.geometry, - True - ) dimensions.addAngularDimension( line1, + line2, + adsk.core.Point3D.create(x_position, (pt2.y + pt3.y) / 2, (pt2.z + pt3.z) / 2), + True, + ) + + dimensions.addAngularDimension( line3, - line1.endSketchPoint.geometry, + line1, + adsk.core.Point3D.create(x_position, (pt1.y + pt3.y) / 2, (pt1.z + pt3.z) / 2), True, ) + + + constraints.addTangent(arc1, line2) + constraints.addTangent(arc1, line3) + dimensions.addRadialDimension( + arc1, arc1.endSketchPoint.geometry, True + ) + tabExtrudeFeature = extrudeUtils.simpleDistanceExtrude( tabSketch.profiles.item(0), adsk.fusion.FeatureOperations.NewBodyFeatureOperation, - input.length, + input.length - BIN_XY_CLEARANCE * 2, adsk.fusion.ExtentDirections.PositiveExtentDirection, [], targetComponent, @@ -106,14 +162,65 @@ def createGridfinityBinBodyTab( tabBody = tabExtrudeFeature.bodies.item(0) tabBody.name = 'label tab' - tabTopFace = faceUtils.getTopFace(tabBody) - roundedEdge = min([edge for edge in tabTopFace.edges if geometryUtils.isCollinearToX(edge)], key=lambda x: x.boundingBox.minPoint.y) - fillet = filletUtils.createFillet( - [roundedEdge], - BIN_TAB_EDGE_FILLET_RADIUS, - False, - targetComponent - ) - fillet.name = 'label tab fillet' + if input.isTabHollow: + binBody = targetComponent.bRepBodies.itemByName("Bin body") + tabBodySubtract = targetComponent.features.copyPasteBodies.add(tabBody).bodies.item(0) + tabBodyShell = targetComponent.features.copyPasteBodies.add(tabBody).bodies.item(0) + + intersectCollection = adsk.core.ObjectCollection.create() + intersectCollection.add(binBody) + combineUtils.intersectBody( + tabBodyShell, + intersectCollection, + targetComponent, + True + ) + + combineUtils.intersectBody( + tabBodySubtract, + intersectCollection, + targetComponent, + True + ) + + shellFeatureEntities = adsk.core.ObjectCollection.create() + + for face in tabBodyShell.faces: + if face.geometry.surfaceType == adsk.core.SurfaceTypes.PlaneSurfaceType and face.evaluator.getNormalAtPoint(pt1)[1].isPerpendicularTo( + adsk.core.Vector3D.create(pt2.x - pt1.x , pt2.y - pt1.y, pt2.z - pt1.z) + ) and not face.evaluator.getNormalAtPoint(pt1)[1].isParallelTo( + adsk.core.Vector3D.create(pt2.x - pt1.x , pt2.y - pt1.y, pt2.z - pt1.z).crossProduct( + adsk.core.Vector3D.create(pt3.x - pt1.x , pt3.y - pt1.y, pt3.z - pt1.z) + ) + ): + shellFeatureEntities.add(face) + + shellFeats = targetComponent.features.shellFeatures + + shellFeatureInput = shellFeats.createInput(shellFeatureEntities, False) + shellFeatureInput.insideThickness = adsk.core.ValueInput.createByReal(BIN_WALL_THICKNESS) + shellFeatureInput.shellType = adsk.fusion.ShellTypes.RoundedOffsetShellType + shellFeats.add(shellFeatureInput) + + subtractCollection = adsk.core.ObjectCollection.create() + subtractCollection.add(tabBodyShell) + + combineUtils.cutBody( + tabBodySubtract, + subtractCollection, + targetComponent + ) + + subtractCollection = adsk.core.ObjectCollection.create() + subtractCollection.add(tabBodySubtract) + + combineUtils.cutBody( + tabBody, + subtractCollection, + targetComponent, + True + ) - return tabBody + return tabBody, [tabBodySubtract] + else: + return tabBody, [] diff --git a/lib/gridfinityUtils/binBodyTabGeneratorInput.py b/lib/gridfinityUtils/binBodyTabGeneratorInput.py index d523108..73b1b0a 100644 --- a/lib/gridfinityUtils/binBodyTabGeneratorInput.py +++ b/lib/gridfinityUtils/binBodyTabGeneratorInput.py @@ -1,11 +1,12 @@ +import math import adsk.core, adsk.fusion, traceback from . import const class BinBodyTabGeneratorInput(): def __init__(self): - self.overhangAngle = const.BIN_TAB_OVERHANG_ANGLE - self.labelAngle = const.BIN_TAB_LABEL_ANGLE + self.overhangAngle = math.radians(const.BIN_TAB_OVERHANG_ANGLE) + self.labelAngle = math.radians(const.BIN_TAB_LABEL_ANGLE) self.position = 0 @property @@ -56,4 +57,10 @@ def labelAngle(self) -> float: def labelAngle(self, value: float): self._tablabelAngle = value - \ No newline at end of file + @property + def isTabHollow(self) -> bool: + return self._isTabHollow + + @isTabHollow.setter + def isTabHollow(self, value: bool): + self._isTabHollow = value \ No newline at end of file diff --git a/lib/gridfinityUtils/combineUtils.py b/lib/gridfinityUtils/combineUtils.py index 16badfc..9469522 100644 --- a/lib/gridfinityUtils/combineUtils.py +++ b/lib/gridfinityUtils/combineUtils.py @@ -10,9 +10,11 @@ def cutBody( targetBody: adsk.fusion.BRepBodies, toolBodies: adsk.core.ObjectCollection, targetComponent: adsk.fusion.Component, + keepToolBodies: bool = False ): combineInput = targetComponent.features.combineFeatures.createInput(targetBody, toolBodies) combineInput.operation = adsk.fusion.FeatureOperations.CutFeatureOperation + combineInput.isKeepToolBodies = keepToolBodies combineFeature = targetComponent.features.combineFeatures.add(combineInput) return combineFeature @@ -20,9 +22,11 @@ def intersectBody( targetBody: adsk.fusion.BRepBody, toolBodies: adsk.core.ObjectCollection, targetComponent: adsk.fusion.Component, + keepToolBodies: bool = False, ): combineInput = targetComponent.features.combineFeatures.createInput(targetBody, toolBodies) combineInput.operation = adsk.fusion.FeatureOperations.IntersectFeatureOperation + combineInput.isKeepToolBodies = keepToolBodies combineFeature = targetComponent.features.combineFeatures.add(combineInput) return combineFeature @@ -30,8 +34,10 @@ def joinBodies( targetBody: adsk.fusion.BRepBodies, toolBodies: adsk.core.ObjectCollection, targetComponent: adsk.fusion.Component, + keepToolBodies: bool = False, ): combineInput = targetComponent.features.combineFeatures.createInput(targetBody, toolBodies) combineInput.operation = adsk.fusion.FeatureOperations.JoinFeatureOperation + combineInput.isKeepToolBodies = keepToolBodies combineFeature = targetComponent.features.combineFeatures.add(combineInput) return combineFeature