- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hi,
In a scenario like the one shown below, if a rule for the number of elements controls the pattern, ideally, you should adjust the quantity to avoid a situation where two holes overlap. is there a way to catch this by checking the geometry for overlapping features in API? nothing is constant here, the plate with, the position of the first element, quantity, and spacing are all dynamic, and this makes it very unpredictable to avoid mathematically, that's why I thought if we could check for the overlapping feature, then we can suppress those specific elements. any thoughts, or ideas are greatly appreciated.
Best
Ali
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
The first thing that comes to mind for this example is counting the quantity of edgeloops of the top face. If there are no overlapping holes, there should be one edgeloop for the contour of the plate and one edgeloop for each non-overlapping hole. So for a plate with five holes, the edgeloop count should be 6 (hole pattern quantity + 1).
As soon as you have less than 6 edgeloops, you have either overlapping holes, holes placed on the contour of the plate or holes located outside of the plate.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hi @3DAli. One of the first things that comes to mind when looking at that situation is checking either Mass or Volume of the 'remaining' solid body(s), both before and after the feature is created/updated, to see if they match what is expected. Volume would likely be simpler. If you know the size of the hole, and know that it goes through, and know the thickness of the part, then you can easily calculate the volume of that solid cylinder. Multiply that by the quantity, to get the total volume displacement. Get/record volume of part/body before creating/changing/updating the feature, then calculate expected displacement, then get volume again, and compare if it it different by the expected amount, within a tolerance. Just the first idea, but I'm sure there are multiple other ways.
Wesley Crihfield
(Not an Autodesk Employee)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
You can use the RangeBox property of a part feature, and then check if they are overlapping using "IsDisjoint". See code below. Be careful with this method though, as if the hole is COMPLETELY overlapped it will return "Nothing" for its rangebox and then you cant use .isDisjoint. I added in some checking for this, but its something to be aware of.
Dim oPart As PartDocument = ThisDoc.Document For Each oFeature As PartFeature In oPart.ComponentDefinition.Features.HoleFeatures If oFeature.RangeBox Is Nothing Then Continue For For Each oFeatureOther As PartFeature In oPart.ComponentDefinition.Features.HoleFeatures If oFeatureOther IsNot oFeature And oFeatureOther.RangeBox IsNot Nothing If Not oFeature.RangeBox.IsDisjoint(oFeatureOther.RangeBox) Then Logger.Info("OVERLAPPING: " & oFeature.Name) End If Next Next
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Add driven dimension on the 2 holes.
With diameter of both holes, you can calculate how many holes will fit.
A minimum distance can be set also.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Below is my attempt on trying to create a 'solution'.
There are probably some odd behaviors especially for very complicated model.
And if there are features after the "Test Pattern".
How one considers what "overlapping" features can be subjective so had used my own interpretation.
Say, if a resulting pattern cutout lie inside a pocket, is that considered overlapped or not.
Anyway, for the attached "Test Part", INV 2023, I considered that the resulting number of edges should be equal to the base feature cutout.
So, if a cutout falls inside the pocket, then it can be non-overlapping, but if the cutout falls on the border of the pocket, then it is overlapping.
I've added a check for minimum distance with other edges as it might be useful (actually, there is another related post with that requirement).
And since I used the Edges for comparison, the rule may take a while to evaluate the minimum distances.
Sub Main
Dim oDoc As PartDocument = ThisApplication.ActiveDocument
Dim oCompDef As PartComponentDefinition = oDoc.ComponentDefinition
Dim oFeats As PartFeatures = oCompDef.Features
Dim bCheckforMinDist As Boolean = True
Dim oUoM As UnitsOfMeasure = oDoc.UnitsOfMeasure
Dim MinDist As DoubleForEquals = 0.04 'a negative value will accept, not suppress if measure min distance = 0 mm
Dim MinDistUnit As String = "in"
'Define the base feature of the cutout pattern
Dim oPattBase As PartFeature
oPattBase = oFeats.Item("Test Feat2")
'Define the cutout pattern
Dim oPattern As RectangularPatternFeature
oPattern = oFeats.RectangularPatternFeatures.Item("Test Pattern2")
Dim oPattBaseEdgeDict As New Dictionary(Of Double, Edge)
Dim oBodyEdgeDict As New Dictionary(Of Double, Edge)
Dim oPattElemEdgeDict As New Dictionary(Of String, Edge)
'Use a dictionary to only consider unique edges
'as an edges can be shared between two faces
For Each oFace As Face In oPattBase.Faces
For Each oEdge As Edge In oFace.Edges
If Not oPattBaseEdgeDict.ContainsKey(oEdge.TransientKey) Then
oPattBaseEdgeDict.Add(oEdge.TransientKey,oEdge)
End If
Next
Next
'This needs to be set so that all features/edges after the oPattern are ignored
oPattern.SetEndOfPart(False) : oDoc.Update
Dim oElements As FeaturePatternElements
oElements = oPattern.PatternElements
'UnSuppress all Pattern Elements for now
For i = 2 To oElements.Count
oElements.Item(i).Suppressed = False
Next
Logger.Info("Pattern Base Feature Edge Count: " & oPattBaseEdgeDict.Keys.Count)
'Update Model to properly get the resulting edges of the Elements
oDoc.Update()
'Skip Index=1 as it is the Base Hole annd cannot suppress it
'Assumes that Base Hole is "ok", doesn't intersect with other cutouts
'Need more than 2 elements
If oElements.Count < 2 Then Exit Sub
For i = 2 To oElements.Count
Dim oElemKeyList As New List(Of String)
For Each oFace As Face In oElements(i).Faces
For Each oEdge As Edge In oFace.Edges
'Used a modified transient key so can get the Element index of the edge easier later
Dim sModKey As String = i & ":" & oEdge.TransientKey
If Not oPattElemEdgeDict.ContainsKey(sModKey) Then
oElemKeyList.Add(sModKey)
oPattElemEdgeDict.Add(sModKey, oEdge)
End If
Next
Next
'Assumption: the number of edges created of the Base Hole feature should equal to the resulting number of edges
'for the Pattern element to be considered not intersecting/overlapping with other cutouts
'there will be some limitations for this assumption depending on what is considered overlapping features.
If oElemKeyList.Count <> oPattBaseEdgeDict.Keys.Count Then
'Element Overlaps with other cutouts so remove those edges in the element Edge dictionary
For Each item In oElemKeyList
oPattElemEdgeDict.Remove(item)
Next
'Suppress the element considered overlapping
oElements(i).Suppressed = True
Logger.Info("Pattern Element " & i & " creates an overlap cutout")
End If
'Logger.Info("Pattern Element " & i & " Count: " & oElemKeyList.Count)
Next
If Not bCheckforMinDist Then GoTo FinalUpdate
oPattern.SetEndOfPart(True) : oDoc.Update
'Again, used a dictionary to get the unique edges before the pattern
Dim iEdgeCount As Integer = 0
For i = 1 To oCompDef.Features.Count
Dim oFeature As PartFeature = oCompDef.Features(i)
'Get only the edges before the Pattern
If oFeature.Name = oPattern.Name Then Exit For
For Each oFace As Face In oFeature.Faces
If oFace.CreatedByFeature.Name = oPattern.Name Then Continue For
For Each oEdge As Edge In oFace.Edges
If Not oBodyEdgeDict.ContainsKey(oEdge.TransientKey) Then
oBodyEdgeDict.Add(oEdge.TransientKey,oEdge)
End If
Next
Next
'Just for debugging/checking
'iEdgeCount = oBodyEdgeDict.Keys.Count - iEdgeCount
'Logger.Info(oFeature.Name & " " & iEdgeCount)
'iEdgeCount = oBodyEdgeDict.Keys.Count
Next
oPattern.SetEndOfPart(False) : oDoc.Update
Logger.Info("Base Body Edge Count: " & oBodyEdgeDict.Keys.Count)
'Evaluate Min Distaces based on Edges
Dim MinDistList As New List(Of DoubleForEquals)
Dim oSuppressIndexList As New List(Of Double)
Dim dPattIndex, dSuppressIndex As Double
Dim iCounter As Integer = 0
For Each EdgeKey In oPattElemEdgeDict.Keys
Dim oPattEdge As Edge = oPattElemEdgeDict.Item(EdgeKey)
dPattIndex = CDbl(Split(EdgeKey, ":")(0))
If oPattEdge.GeometryType = CurveTypeEnum.kUnknownCurve Then Continue For
'Logger.Info("Pattern Element: " & dPattIndex & vbLf & _
' "Suppress Element: " & dSuppressIndex)
'Check if Index is already for suppression, so just skip the Min Distance evaluation
If dPattIndex = dSuppressIndex Then Continue For
Dim dDist, dDist_Temp As DoubleForEquals
dDist = 1000 * Abs(MinDist) 'Just a large number greater than min distance as initial value
For Each oBodyEdge As Edge In oBodyEdgeDict.Values
If oBodyEdge.GeometryType = CurveTypeEnum.kUnknownCurve Then Continue For
'Check if both edges are line segments
'if they are parallel then we don't want to evaluate the min distance between them
If (TypeOf oPattEdge.Geometry Is LineSegment) AndAlso (TypeOf oBodyEdge.Geometry Is LineSegment) Then
Dim oPattEdgeVector As UnitVector = oPattEdge.Geometry.Direction
Dim oBodyEdgeVector As UnitVector = oBodyEdge.Geometry.Direction
If oPattEdgeVector.IsParallelTo(oBodyEdgeVector) Then Continue For
End If
'just for checking the iteration count
iCounter += 1
dDist_Temp = ThisApplication.MeasureTools.GetMinimumDistance(oPattEdge, oBodyEdge)
'Convert measured distance to input MinDisUnits
dDist_Temp = oUoM.ConvertUnits(dDist_Temp, UnitsTypeEnum.kDatabaseLengthUnits, oUoM.GetTypeFromString(MinDistUnit))
'Assumpption is that body thickness is larger than the minimum distace
If dDist >= dDist_Temp Then
dDist = dDist_Temp
End If
If dDist <= MinDist Then
'Logger.Info(Round(dDist,3) & " vs " & MinDist)
dSuppressIndex = dPattIndex
oSuppressIndexList.Add(dSuppressIndex)
'Logger.Info("Index :" & dSuppressIndex )
Logger.Info("Pattern Element " & dPattIndex & " Edge Pair Found (Distance = " & Round(dDist, 3) & " " & MinDistUnit & ")")
'Logger.Info(oPattEdge.GeometryType.ToString)
'Logger.Info(oBodyEdge.GeometryType.ToString)
'Found minimmum, so no need to evaluate distance to other edges
Exit For
End If
Next
Next
Logger.Info("Edge Pairs Evaluated: " & iCounter)
Logger.Info("Minimum Distance Criteria: " & MinDist & " " & MinDistUnit)
'Suppress the element index If it was found To result To lower than minimum Edge distance
For Each item In oSuppressIndexList
Logger.Info("Pattern Element " & item & " has resulting edge distance under minimum")
oElements(item).Suppressed = True
Next
FinalUpdate:
oCompDef.SetEndOfPartToTopOrBottom(False)
oDoc.Update
End Sub
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Just an idea for probably simpler/faster approach that potentially can be applied to more complex geometry (ex. engraved text etc) and even on models without Part Features (derived, imported etc):
1. Get the initial volume value
2. Calculate the volume of sure non-overlapped feature instance
2.1. Start the transaction
2.2. Create temporary Extrude-Add (New Solid) feature and get the non-overlapped volume change (new solid) value
2.3. Abort the transaction
3. Create the desired (Cut/Engrave) feature.
If resulting volume is > (initial volume - temporary solid volume) then there is some overlapping.
I wonder if step 2 can be done without making any change to the volume at all (by means of transient geometry)?
Please vote for Inventor-Idea Text Search within Option Names
