Automatic Sheet Metal Thickness Detection
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
I've been struggling to find an easy way to automatically detect whether the geometry in a part qualifies as a sheet metal part, and if so, what the sheet metal thickness is. I couldn't find anything satisfactory so I wrote the following rule which in our situation seems to work 100% of the time for 2 years now. I hope this can be useful to someone now that it seemed to have proved itself.
What the rule does is:
-Check if a part is a standard or sheet metal part, and convert if neccesary.
-Determine the sheet metal thickness within the accepted thickness values
-Else, it will be regarded it as a standard part regardsless
Those willing to use it will undoubtedly have to modify the rule to work for their use-case, but I hope this may prove as a good starting point. I'm very eager to recieve improvements on the rule to make it even more robust.
Sub Main() Dim oPartDoc As PartDocument = ThisDoc.Document ' <-- fixed Dim oCompDef As PartComponentDefinition = oPartDoc.ComponentDefinition 'Declaring Public Variables Dim acceptableValues() As Double = {0.5, 1, 1.25, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10 } Dim largestFace As Face = Nothing Dim largestFlatFace As Face = Nothing Dim largestArea As Double = 0 Dim outerLoopPoints As New List(Of Point) Dim outerLoopEdge As Edge = Nothing Dim planeDistance As Double = 0 If oCompDef.SurfaceBodies(1).Faces.Count < 2 Then oPartDoc.SubType = "{4D29B490-49B2-11D0-93C3-7E0706000000}" Return End If 'Get the largest face For Each oFace As Face In oCompDef.SurfaceBodies(1).Faces Dim area As Double = oFace.Evaluator.Area If area > largestArea Then largestArea = area largestFace = oFace End If Next If Not largestFace Is Nothing Then 'Store Outer Loop Vertex Points For Each oEdgeLoop As EdgeLoop In largestFace.EdgeLoops If oEdgeLoop.IsOuterEdgeLoop Then outerLoopEdge = oEdgeLoop.Edges.Item(1) For Each oEdge As Edge In oEdgeLoop.Edges outerLoopPoints.Add(oEdge.StartVertex.Point) outerLoopPoints.Add(oEdge.StopVertex.Point) Next End If Next 'Check if there's a straight edge connected to the outer edge and aligned with the largestFace normal For Each oEdge As Edge In oCompDef.SurfaceBodies(1).Edges If oEdge.GeometryType = kLineSegmentCurve Then Dim sharedVertex As Point = OnlyPointConnectingEdgeToLoop(oEdge, outerLoopPoints) If Not sharedVertex Is Nothing Then If AlignedEdgeAndFaceNormalAtPoint(oEdge, largestFace, sharedVertex) Then Dim edgeLength As Double = Math.Round(EgdeLength(oEdge) * 10, 4) If acceptableValues.Contains(edgeLength) Then SetThickness(edgeLength, oPartDoc) ' <-- pass oPartDoc Return End If End If End If End If Next largestArea = 0 For Each oFace As Face In oCompDef.SurfaceBodies.Item(1).Faces If oFace.SurfaceType = SurfaceTypeEnum.kPlaneSurface Then Dim area As Double = oFace.Evaluator.Area If area > largestArea Then largestArea = area largestFlatFace = oFace End If End If Next For Each oFace As Face In oCompDef.SurfaceBodies.Item(1).Faces If oFace IsNot largestFlatFace And oFace.SurfaceType = SurfaceTypeEnum.kPlaneSurface Then Dim oPlane As Plane = oFace.Geometry Dim largestPlane As Plane = largestFlatFace.Geometry Dim Distance As Double = Double.MinValue If largestPlane.IsParallelTo(oPlane) Then Distance = Math.Abs(Math.Round(largestPlane.DistanceTo(oPlane.RootPoint) * 10, 4)) End If If Distance > 0 And Distance > planeDistance Then planeDistance = Distance End If End If Next If acceptableValues.Contains(planeDistance) Then SetThickness(planeDistance, oPartDoc) ' <-- pass oPartDoc Return Else For Each oFace As Face In oCompDef.SurfaceBodies.Item(1).Faces If oFace IsNot largestFlatFace And oFace.SurfaceType = SurfaceTypeEnum.kPlaneSurface Then Dim oPlane As Plane = oFace.Geometry Dim largestPlane As Plane = largestFlatFace.Geometry Dim Distance As Double = Double.MaxValue If largestPlane.IsParallelTo(oPlane) Then Distance = Math.Abs(Math.Round(largestPlane.DistanceTo(oPlane.RootPoint) * 10, 4)) End If If Distance > 0 And Distance < planeDistance Then planeDistance = Distance End If End If Next If acceptableValues.Contains(planeDistance) Then SetThickness(planeDistance, oPartDoc) ' <-- pass oPartDoc Return Else Dim connectedFaces As Faces = outerLoopEdge.Faces Dim otherFace As Face = Nothing For Each oFace As Face In connectedFaces If oFace IsNot largestFace Then otherFace = oFace Exit For End If Next Dim otherFaceArea As Double = otherFace.Evaluator.Area Dim totalLoopLenght As Double = 0 For Each oEdge In otherFace.Edges totalLoopLenght += EgdeLength(oEdge) Next Dim ratio As Double = Math.Abs(Math.Round(otherFaceArea / (totalLoopLenght / 2) * 10, 4)) If acceptableValues.Contains(ratio) Then SetThickness(ratio, oPartDoc) ' <-- pass oPartDoc Return Else oPartDoc.SubType = "{4D29B490-49B2-11D0-93C3-7E0706000000}" End If End If End If End If End Sub Function OnlyPointConnectingEdgeToLoop(E As Edge, VA As List(Of Point)) As Point Dim startVertex As Point = E.StartVertex.Point Dim stopVertex As Point = E.StopVertex.Point For Each oLoopVertex As Point In VA If startVertex.IsEqualTo(oLoopVertex) Xor stopVertex.IsEqualTo(oLoopVertex) Then Return oLoopVertex End If Next End Function Function AlignedEdgeAndFaceNormalAtPoint(E As Edge, F As Face, P As Point) As Boolean Dim oPoint As Double() = {P.X, P.Y, P.Z } Dim oNormal As Double() = New Double(2) {} F.Evaluator.GetNormalAtPoint(oPoint, oNormal) Dim oParam As Double() = {0, 0, 0 } Dim oTangent As Double() = New Double(2) {} E.Evaluator.GetTangent(oParam, oTangent) Dim DotProduct As Double = oNormal(0) * oTangent(0) + oNormal(1) * oTangent(1) + oNormal(2) * oTangent(2) Dim Tolerance As Double = 0.001 If Math.Abs(DotProduct) >= (1 - Tolerance) Then Return True End If End Function Function EgdeLength(oEdge As Edge) As Double Dim curveEval As CurveEvaluator = oEdge.Evaluator Dim MinParam As Double Dim MaxParam As Double Dim Length As Double curveEval.GetParamExtents(MinParam, MaxParam) curveEval.GetLengthAtParam(MinParam, MaxParam, Length) Return Length End Function Function SetThickness(T As Double, oPartDoc As PartDocument) ' <-- accepts oPartDoc as argument Dim new_smcd As SheetMetalComponentDefinition = oPartDoc.ComponentDefinition ' <-- fixed new_smcd.ActiveSheetMetalStyle.Thickness = T new_smcd.UseSheetMetalStyleThickness = True End Function