Sub CATMain()
' Choose one of two ways to generate vectors.
' Comment out unused method with " ' " sign
'Call CreateHoleVectorsWithoutEdges ' this will generate vectors and points without linking them to hole geometry
Call CreateHoleVectorsWithEdges ' this generates vectors, linked to geometry of hole's "end" faces
End Sub
'======================================================================================================
' Sets layer for choosen geometrical feature with respect to Hole Diameter.
'======================================================================================================
Private Sub SetHoleGeometryLayer(ByVal objHoleGeometry As HybridShape, ByVal dblHoleDiameter As Double)
' quickly check inputs
If (objHoleGeometry Is Nothing) Then
Exit Sub
End If
' get selection object
Dim objSelection As Selection
Set objSelection = CATIA.ActiveDocument.Selection
' get access to graphic properties of object
Dim objVisProp As VisPropertySet
Call objSelection.Clear
Call objSelection.Add(objHoleGeometry)
Set objVisProp = objSelection.VisProperties
' choose proper layer for geometry using hole diameter as a criteria
Dim iLayer As Integer
Select Case dblHoleDiameter
' ENLIST ALL POSSIBLE DIAMETERS AND CORRESPONDING LAYER NUMBERS HERE
Case 10: iLayer = 1
Case 20: iLayer = 2
Case 30: iLayer = 3
Case 40: iLayer = 4
' if no suitable diameter was found, geometry will be sent to "None" layer
Case Else: iLayer = -1
End Select
If (iLayer < 0) Then
Call objVisProp.SetLayer(catVisLayerNone, 0)
Else
Call objVisProp.SetLayer(catVisLayerBasic, iLayer)
End If
' clear selection
Call objSelection.Clear
End Sub
'========================================================================================================
' Translates reference string (retrieved with DisplayName) of Edge, Face or Vertex object, making it usable in construction
'========================================================================================================
Private Function TranslateReferenceStr(ByVal strReference As String) As String
' set default value
TranslateReferenceStr = strReference
' quickly check inputs
If (TranslateReferenceStr = "") Then
Exit Function
End If
' analyze string
Dim posSelection As Integer
Dim posCf As Integer
' check if it is string from reference retrieved from selection
posSelection = InStr(1, strReference, "Selection_")
If (posSelection = 0) Then
Exit Function
End If
' remove "Selection" from string
strReference = Right(strReference, Len(strReference) - Len("Selection_"))
' cut bad ending
posCf = InStrRev(strReference, "Cf11));")
strReference = Left(strReference, posCf + Len("Cf11));") - 1)
' insert new ending
strReference = strReference & "WithPermanentBody;WithoutBuildError;WithSelectingFeatureSupport;MFBRepVersion_CXR15)"
' return translated string
TranslateReferenceStr = strReference
End Function
'========================================================================================================
' Creates vectors and points on hole ends basing solely on their coordinates
'========================================================================================================
Private Sub CreateHoleVectorsWithoutEdges()
' part infrastructure
Dim RootPart As Part
Set RootPart = CATIA.ActiveDocument.Part
Dim PartBody As Body
Set PartBody = RootPart.MainBody
Dim SPAWbench As SPAWorkbench
Set SPAWbench = CATIA.ActiveDocument.GetWorkbench("SPAWorkbench")
' find and create (if necessary) "Points and Vectors" geometrical set
Dim PnVGeoSet As HybridBody
On Error Resume Next
Set PnVGeoSet = RootPart.HybridBodies.Item("Points and Vectors")
If (Err.Number 0) Then
' geometrical set not found, create new one
Set PnVGeoSet = RootPart.HybridBodies.Add()
PnVGeoSet.name = "Points and Vectors"
Call Err.Clear
End If
On Error GoTo 0
' find all Holes inside PartBody and form collection of them
Dim objSelection As Selection
Set objSelection = CATIA.ActiveDocument.Selection
Call objSelection.Clear
Call objSelection.Add(PartBody)
objSelection.Search "'Part Design'.Hole,sel" '.Search "'Part Design'.Hole,sel"
Dim colHoles As Collection
Set colHoles = New Collection
Dim iHole As Integer
For iHole = 1 To objSelection.Count2
Call colHoles.Add(objSelection.Item2(iHole).Value)
Next
Call objSelection.Clear
' for each hole create "axis" lines and points
Dim objHSF As HybridShapeFactory
Set objHSF = RootPart.HybridShapeFactory
Dim hlHole As Hole
Dim objHole As AnyObject
Dim refHole As Reference
Dim iHoleType As CatHoleType
Dim lntDepth As Length
Dim lmtDepth As Limit
Dim dblDepth As Double
Dim dblDiameter As Double
Dim ArrOriginPoint(2) As Variant
Dim ArrDirection(2) As Variant
Dim objOriginPoint As HybridShapePointCoord
Dim refOriginPoint As Reference
Dim objEndPoint As HybridShape
Dim refEndPoint As Reference
Dim objHoleDirection As HybridShapeDirection
Dim refHoleDirection As Reference
Dim blOrientation As Boolean
Dim objHoleAxis As HybridShape
Dim refHoleAxis As Reference
For iHole = 1 To colHoles.Count
' get hole object
Set hlHole = colHoles(iHole)
Set objHole = hlHole
Set refHole = RootPart.CreateReferenceFromObject(objHole)
'----------------
' BASIC HOLE INFO
'----------------
' retrieve hole type
iHoleType = hlHole.Type
' determine depth of the hole
If (iHoleType = catSimpleHole) Or (iHoleType = catTaperedHole) Then
Set lmtDepth = hlHole.BottomLimit
Set lntDepth = lmtDepth.Dimension
Else
Set lntDepth = hlHole.HeadDepth
End If
dblDepth = lntDepth.Value
' !!!!! IMPORTANT!!!!!!
' Determine hole direction orientation
' Seems like hole is always created opposingly to it's direction vector (retrieved below)
blOrientation = False
' get hole diameter
dblDiameter = hlHole.Diameter.Value
'---------------------------
' POINTS AND VECTOR CREATION
'---------------------------
' retrieve hole origin and direction
Call objHole.GetOrigin(ArrOriginPoint)
Call objHole.GetDirection(ArrDirection)
' create explicit origin point and compute it's geometry
Set objOriginPoint = objHSF.AddNewPointCoord(ArrOriginPoint(0), ArrOriginPoint(1), ArrOriginPoint(2))
Set refOriginPoint = RootPart.CreateReferenceFromObject(objOriginPoint)
Call objOriginPoint.Compute
' place origin point in "Points and Vectors" geometrical set
Call PnVGeoSet.AppendHybridShape(objOriginPoint)
' create explicit direction
Set objHoleDirection = objHSF.AddNewDirectionByCoord(ArrDirection(0), ArrDirection(1), ArrDirection(2))
' Set refHoleDirection = RootPart.CreateReferenceFromObject(objHoleDirection)
Call objHoleDirection.Compute
' create axis line along hole direction
Set objHoleAxis = objHSF.AddNewLinePtDir(refOriginPoint, objHoleDirection, 0, dblDepth, blOrientation)
Set refHoleAxis = RootPart.CreateReferenceFromObject(objHoleAxis)
Call objHoleAxis.Compute
' place line in "Points and Vectors" geometrical set
Call PnVGeoSet.AppendHybridShape(objHoleAxis)
' create point at the end of axis line
Set objEndPoint = objHSF.AddNewPointOnCurveFromPercent(refHoleAxis, 1, blOrientation)
Set refEndPoint = RootPart.CreateReferenceFromObject(objEndPoint)
Call objEndPoint.Compute
' place end point in "Points and Vectors" geometrical set
Call PnVGeoSet.AppendHybridShape(objEndPoint)
'--------------------------------------------
' ASSIGNING PROPER LAYER TO POINTS AND VECTOR
'--------------------------------------------
Call SetHoleGeometryLayer(objOriginPoint, dblDiameter)
Call SetHoleGeometryLayer(objEndPoint, dblDiameter)
Call SetHoleGeometryLayer(objHoleAxis, dblDiameter)
Next
' update geometrical set
Call RootPart.UpdateObject(PnVGeoSet)
End Sub
'========================================================================================================
' Creates required vectors and points by retrieving edges from holes
' This allows vectors to be linked with their corresponding holes
' and (theoretically) be properly updated when hole geometry changes
'========================================================================================================
Private Sub CreateHoleVectorsWithEdges()
' part infrastructure
Dim RootPart As Part
Set RootPart = CATIA.ActiveDocument.Part
Dim PartBody As Body
Set PartBody = RootPart.MainBody
Dim SPAWbench As SPAWorkbench
Set SPAWbench = CATIA.ActiveDocument.GetWorkbench("SPAWorkbench")
' find and create (if necessary) "Points and Vectors" geometrical set
Dim PnVGeoSet As HybridBody
On Error Resume Next
Set PnVGeoSet = RootPart.HybridBodies.Item("Points and Vectors")
If (Err.Number 0) Then
' geometrical set not found, create new one
Set PnVGeoSet = RootPart.HybridBodies.Add()
PnVGeoSet.name = "Points and Vectors"
Call Err.Clear
End If
On Error GoTo 0
' find all Holes inside PartBody and form collection of them
Dim objSelection As Selection
Set objSelection = CATIA.ActiveDocument.Selection
Call objSelection.Clear
Call objSelection.Add(PartBody)
Call objSelection.Search("'Part Design'.Hole,sel")
Dim colHoles As Collection
Set colHoles = New Collection
Dim iHole As Integer
For iHole = 1 To objSelection.Count2
Call colHoles.Add(objSelection.Item2(iHole).Value)
Next
Call objSelection.Clear
' for each hole create "axis" lines and points
Dim objHSF As HybridShapeFactory
Set objHSF = RootPart.HybridShapeFactory
Dim hlHole As Hole
Dim objHole As AnyObject
Dim refHole As Reference
Dim iHoleType As CatHoleType
Dim lntDepth As Length
Dim lmtDepth As Limit
Dim dblDepth As Double
Dim dblDiameter As Double
Dim ArrOriginPoint(2) As Variant
Dim ArrDirection(2) As Variant
Dim objOriginPoint As Point
Dim refOriginPoint As Reference
Dim objEndPoint As Point
Dim refEndPoint As Reference
Dim blOrientation As Boolean
Dim objHoleAxis As HybridShape
Dim refHoleAxis As Reference
Dim ArrEdges() 'As Collection
ReDim ArrEdges(colHoles.Count) 'As Collection
Dim colEdges As Collection
Dim iEdge As Integer
Dim refEdge As Reference
Dim strEdge As String
Dim colCenterPoints As Collection
Set colCenterPoints = New Collection
Dim iCenterPoint As Integer
Dim objCenterPoint As HybridShapePointCenter
Dim varCenterPoint As AnyObject
Dim refCenterPoint As Reference
Dim ArrCenterPoint(2) As Variant
Dim objMeas As Measurable
Dim dblDistance As Double
For iHole = 1 To colHoles.Count
' get hole object
Set hlHole = colHoles(iHole)
Set objHole = hlHole
Set refHole = RootPart.CreateReferenceFromObject(objHole)
'---------------------------------
' ENLIST ALL EDGES OF CURRENT HOLE
'---------------------------------
Call objSelection.Clear
Call objSelection.Add(hlHole)
Call objSelection.Search("Topology.Edge,sel")
Set colEdges = New Collection
For iEdge = 1 To objSelection.Count
strEdge = TranslateReferenceStr(objSelection.Item(iEdge).Value.DisplayName)
Set refEdge = RootPart.CreateReferenceFromBRepName(strEdge, objSelection.Item(iEdge).Value.Parent)
Call colEdges.Add(refEdge)
Next
Call objSelection.Clear
'--------------------------------------------
' CREATE CENTERS OF ALL EDGES OF CURRENT HOLE
'--------------------------------------------
Set objOriginPoint = Nothing
Set objEndPoint = Nothing
' retrieve hole origin and direction
Call objHole.GetOrigin(ArrOriginPoint)
Call objHole.GetDirection(ArrDirection)
For iEdge = 1 To colEdges.Count
' retrieve edge
Set refEdge = colEdges.Item(iEdge)
' try to create center point of it
On Error Resume Next
Set objCenterPoint = objHSF.AddNewPointCenter(refEdge)
If (Err.Number = 0) Then
On Error Resume Next
Call objCenterPoint.Compute
If (Err.Number 0) Then
Set objCenterPoint = Nothing
End If
Else
Set objCenterPoint = Nothing
End If
If Not (objCenterPoint Is Nothing) Then
' sucessfully created point in the center of edge
Set refCenterPoint = RootPart.CreateReferenceFromObject(objCenterPoint)
' add it to center points collection
Call colCenterPoints.Add(objCenterPoint)
' check if it is the same point as hole origin point
Set varCenterPoint = objCenterPoint
Call varCenterPoint.GetCoordinates(ArrCenterPoint)
If ((ArrCenterPoint(0) = ArrOriginPoint(0)) And _
(ArrCenterPoint(1) = ArrOriginPoint(1)) And _
(ArrCenterPoint(2) = ArrOriginPoint(2))) Then
Set objOriginPoint = objCenterPoint
Set refOriginPoint = refCenterPoint
End If
End If
Next
' if we've found origin point of hole we look for another center point lying on other edge at the distance equal to hole depth
If Not (objOriginPoint Is Nothing) Then
' determine depth of the hole
iHoleType = hlHole.Type
If (iHoleType = catSimpleHole) Or (iHoleType = catTaperedHole) Then
Set lmtDepth = hlHole.BottomLimit
Set lntDepth = lmtDepth.Dimension
Else
Set lntDepth = hlHole.HeadDepth
End If
dblDepth = lntDepth.Value
' get Measurable object on retrieved origin point
Set objMeas = SPAWbench.GetMeasurable(refOriginPoint)
For iCenterPoint = 1 To colCenterPoints.Count
' retrieve another center point
Set objCenterPoint = colCenterPoints.Item(iCenterPoint)
Set refCenterPoint = RootPart.CreateReferenceFromObject(objCenterPoint)
' calculate distance between origin and center points
dblDistance = objMeas.GetMinimumDistance(refCenterPoint)
' check if it equals to hole depth
If (dblDistance = dblDepth) Then
Set objEndPoint = objCenterPoint
Set refEndPoint = refCenterPoint
Exit For
End If
Next
End If
' get hole diameter
dblDiameter = hlHole.Diameter.Value
'---------------------------
' POINTS AND VECTOR CREATION
'---------------------------
If (Not (objOriginPoint Is Nothing) And Not (objCenterPoint Is Nothing)) Then
' create line between origin and end points
Set objHoleAxis = objHSF.AddNewLinePtPt(refOriginPoint, refEndPoint)
Call objHoleAxis.Compute
' add both points and created line to "Points and Vectors" geometrical set
Call PnVGeoSet.AppendHybridShape(objOriginPoint)
Call PnVGeoSet.AppendHybridShape(objEndPoint)
Call PnVGeoSet.AppendHybridShape(objHoleAxis)
End If
'--------------------------------------------
' ASSIGNING PROPER LAYER TO POINTS AND VECTOR
'--------------------------------------------
Call SetHoleGeometryLayer(objOriginPoint, dblDiameter)
Call SetHoleGeometryLayer(objEndPoint, dblDiameter)
Call SetHoleGeometryLayer(objHoleAxis, dblDiameter)
Next
' update geometrical set
Call RootPart.UpdateObject(PnVGeoSet)
End Sub