handleman
Automotive
- Jan 7, 2005
- 3,411
I posted some quickie mate macros some time back for coincident, concentric, and parallel mates in thread559-175155. I'd been wanting to do a distance mate, but I liked the SW functionality that uses the current distance between the chosen components as the default distance. Calculating this distance turned out to be pretty involved, especially calculating normal distances (which was what the default SW mate function does) rather than just the shortest distance.
This macro, like the other macros, is faster than the standard way of adding mates (especially for larger assemblies) because it doesn't use the mate property manager and doesn't do a rebuild after adding each mate. It also saves mouse clicks by allowing you to enter a negative value for the dimension rather than having to check a box or click a button.
Hope it can be a help to others...
This macro, like the other macros, is faster than the standard way of adding mates (especially for larger assemblies) because it doesn't use the mate property manager and doesn't do a rebuild after adding each mate. It also saves mouse clicks by allowing you to enter a negative value for the dimension rather than having to check a box or click a button.
Hope it can be a help to others...
Code:
Const SF As Double = 1000 'scale factor.
'Change the scale factor value above based on your
'standard unit system. Use:
'1000 for mm
'100/2.54 for inches
Sub main()
Dim CurDist As Double
Dim NewDist As Double
Dim CurFlip As Boolean
Dim NewFlip As Boolean
Dim cnt As Long
Dim myMateDim As SldWorks.Dimension
Dim InPutStr As String
Dim swApp As SldWorks.SldWorks
Dim swDoc As SldWorks.ModelDoc2
Dim swAssy As SldWorks.AssemblyDoc
Dim swSelMgr As SldWorks.SelectionMgr
Dim swMate As SldWorks.Mate2
Dim ErrorLong As Long
Dim MsgReply As Integer
Dim NewAlign As Long
Dim sMsg As String
Dim sMateName As String
sMsg = "Enter desired mate distance" & vbCrLf & _
"Enter a negative number to flip the dimension and change value." & vbCrLf & _
"Enter ""-"" alone to flip current value shown" & _
"To accept the current value, Cancel or press Enter"
Set swApp = Application.SldWorks
Set swDoc = swApp.ActiveDoc
Set swAssy = swDoc
Set swSelMgr = swDoc.SelectionManager
Const IBX As Integer = 2
Const IBY As Integer = 2
If swDoc.GetType <> swDocASSEMBLY Then
MsgBox "Use this macro in Assembly documents only.", vbCritical
Exit Sub
End If
If swSelMgr.GetSelectedObjectCount <> 2 Then
MsgBox swSelMgr.GetSelectedObjectCount & " items selected. Req'd number is 2.", vbCritical
Exit Sub
End If
CurDist = GetInitialDist
If CurDist = -1 Then
CurDist = 0
Else
CurDist = CurDist
End If
Set swMate = swAssy.AddMate3(swMateDISTANCE, swMateAlignCLOSEST, True, CurDist, CurDist, CurDist, 0, 0, 0, 0, 0, False, ErrorLong)
sMateName = swMate.Name
If Nothing Is swMate Then
MsgBox "Mating Error #" & ErrorLong & " Mate not added.", vbCritical
Exit Sub
End If
'GoTo BYPASS
If swAddMateError_OverDefinedAssembly = ErrorLong Then
MsgReply = MsgBox("Overdefining mate. Keep anyway?", vbYesNo + vbQuestion)
If vbNo = MsgReply Then
swDoc.ClearSelection2 True
swMate.Select True
swDoc.Extension.DeleteSelection2 0
Else
'swDoc.EditRebuild3
End If
ElseIf swMate.Alignment <> swMateAlignCLOSEST Then
'''Verify alignment
MsgReply = MsgBox("Keep current alignment?", vbYesNo, "Mate Alignment")
If vbNo = MsgReply Then
If swMate.Alignment = swMateAlignALIGNED Then
NewAlign = swMateAlignANTI_ALIGNED
Else
NewAlign = swMateAlignALIGNED
End If
swMate.Select True
swAssy.EditMate2 swMateDISTANCE, NewAlign, False, CurDist, CurDist, CurDist, 0, 0, 0, 0, 0, ErrorLong
If swAddMateError_OverDefinedAssembly = ErrorLong Then
MsgReply = MsgBox("Flip caused errors. Undo?", vbYesNo + vbQuestion)
If vbYes = MsgReply Then
swDoc.EditUndo2 1
End If
End If
'swDoc.EditRebuild3
End If
ElseIf swAddMateError_NoError <> ErrorLong Then
MsgBox "Mate error #" & ErrorLong & vbCrLf & "Mate not added"
If Not swMate Is Nothing Then
swDoc.ClearSelection2 True
swMate.Select True
swDoc.Extension.DeleteSelection2 0
End If
ElseIf swMate.GetErrorCode <> swFeatureErrorNone Then
Select Case swMate.GetErrorCode
Case swFeatureErrorMateInvalidEdge
MsgBox "Invalid edge"
Case swFeatureErrorMateInvalidFace
MsgBox "Invalid Face"
Case swFeatureErrorMateFailedCreatingSurface
MsgBox "Mate surface type not supported"
Case swFeatureErrorMateInvalidEntity
MsgBox "Supressed, Invalid, or Missing Entity"
Case swFeatureErrorMateDanglingGeometry
MsgBox "Mate geometry is dangling"
Case swFeatureErrorMateEntityNotLinear
MsgBox "Non-linear edges cannot be used for mating"
Case swFeatureErrorMateOverdefined
MsgBox "Mate is overdefining"
Case swFeatureErrorMateIlldefined
MsgBox "Mate cannot be solved (Ill-Defined)"
Case swFeatureErrorMateBroken
MsgBox "One or more entities suppressed or invalid for this mate"
End Select
swDoc.ClearSelection2 True
swMate.Select True
swDoc.Extension.DeleteSelection2 0
End If
''''''''Verify/Enter Distance
'get the mate dimension - if it is nonexistent then don't mess with it.
Dim genobj As SldWorks.Feature
Set genobj = swAssy.FeatureByName(sMateName)
Set swMate = genobj.GetSpecificFeature2
Set myMateDim = swMate.DisplayDimension.GetDimension
If Not myMateDim Is Nothing Then
NewDist = Empty
CurDist = CurDist * SF
CurFlip = swMate.Flipped
InPutStr = InputBox(sMsg, "Mate Distance", CurDist, 1, 1, Empty, Empty)
If InPutStr = "" Then
NewDist = CurDist
ElseIf InPutStr = "-" Then
NewDist = -CurDist
Else
NewDist = CDbl(InPutStr)
End If
If NewDist < 0 Then
NewDist = 0 - NewDist
If False = CurFlip Then
NewFlip = True
Else
NewFlip = False
End If
Else
NewFlip = CurFlip
End If
CurDist = CDbl(CurDist)
cnt = 1
While (Abs(NewDist - CurDist) > 0.00000001) Or CurFlip <> NewFlip
'Debug.Print cnt, CurDist, CurFlip, NewDist, NewFlip
If swSelMgr.GetSelectedObjectCount <> 3 Then
'Debug.Print "select again", swSelMgr.GetSelectedObjectCount
swMate.Select True
End If
swAssy.EditMate2 swMateDISTANCE, swMate.Alignment, NewFlip, NewDist / SF, NewDist / SF, NewDist / SF, 0, 0, 0, 0, 0, ErrorLong
Set genobj = swAssy.FeatureByName(sMateName)
Set swMate = genobj.GetSpecificFeature2
Set myMateDim = swMate.DisplayDimension.GetDimension
'myMateDim.SetValue3 NewDist, swSetValue_InAllConfigurations, Empty
'swMate.Flipped = NewFlip
'swDoc.EditRebuild3
'If swAddMateError_OverDefinedAssembly = ErrorLong Then
' MsgReply = MsgBox("Distance change caused errors. Undo?", vbYesNo + vbQuestion)
' If vbYes = MsgReply Then
' swDoc.EditUndo2 1
' End If
'End If
'swDoc.EditRebuild3
CurDist = NewDist
CurFlip = swMate.Flipped
InPutStr = InputBox(sMsg, "Mate Distance", CurDist, 1, 1, Empty, Empty)
If InPutStr = "" Then
NewDist = CurDist
ElseIf InPutStr = "-" Then
NewDist = -CurDist
Else
NewDist = CDbl(InPutStr)
End If
If NewDist < 0 Then
NewDist = 0 - NewDist
If False = CurFlip Then
NewFlip = True
Else
NewFlip = False
End If
Else
NewFlip = CurFlip
End If
cnt = cnt + 1
Wend
End If
swDoc.ClearSelection2 True
Set myMateDim = Nothing
Set swApp = Nothing
Set swDoc = Nothing
Set swAssy = Nothing
Set swSelMgr = Nothing
Set swMate = Nothing
End Sub
Private Function GetInitialDist()
Dim swApp As SldWorks.SldWorks
Dim swDoc As SldWorks.ModelDoc2
Dim swSelMgr As SldWorks.SelectionMgr
Dim swMathUtil As SldWorks.MathUtility
Dim myFace As SldWorks.Face2
Dim myFirstNormVect As SldWorks.MathVector
Dim mySecondNormVect As SldWorks.MathVector
Dim myFirstXform As SldWorks.MathTransform
Dim mySecondXform As SldWorks.MathTransform
Dim myDistVect As SldWorks.MathVector
Dim myDist As Double
Dim FirstDistPoint As Variant
Dim SecondDistPoint As Variant
Dim FirstDistVect As SldWorks.MathVector
Dim myModeler As SldWorks.Modeler
Dim mySel1 As Object
Dim mySel2 As Object
Dim myCross As SldWorks.MathVector
Dim FirstSelPlanar As Boolean
Dim SecondSelPlanar As Boolean
Dim tmpArrayData(2) As Double
Dim tmpPt As SldWorks.MathPoint
Set swApp = Application.SldWorks
Set swDoc = swApp.ActiveDoc
Set swSelMgr = swDoc.SelectionManager
Set swMathUtil = swApp.GetMathUtility
''''''Check the first selection
If swSelMgr.GetSelectedObjectType3(1, -1) = 4 Then 'refplanes
Set mySel1 = swSelMgr.GetSelectedObject6(1, -1).GetSpecificFeature
FirstSelPlanar = True
tmpArrayData(0) = 0
tmpArrayData(1) = 0
tmpArrayData(2) = 1
Set tmpPt = swMathUtil.CreatePoint(tmpArrayData)
Set myFirstXform = mySel1.Transform 'This gets the xfrom inside the component (not assy)
Set tmpPt = tmpPt.MultiplyTransform(myFirstXform)
Set myFirstNormVect = swMathUtil.CreateVector(tmpPt.ArrayData)
'myFirstNormVect now contains the normal vector in part coords of the selected plane
ElseIf swSelMgr.GetSelectedObjectType3(1, -1) = 2 Then 'faces
Set mySel1 = swSelMgr.GetSelectedObject6(1, -1)
Set myFirstNormVect = swMathUtil.CreateVector(mySel1.Normal)
If myFirstNormVect.GetLength <> 0 Then
FirstSelPlanar = True
Else
FirstSelPlanar = False
End If
Else
FirstSelPlanar = False
Set myFirstNormVect = Nothing
Set mySel1 = swSelMgr.GetSelectedObject6(1, -1)
End If
'''''Check the second selection
If swSelMgr.GetSelectedObjectType3(2, -1) = 4 Then 'refplanes
Set mySel2 = swSelMgr.GetSelectedObject6(2, -1).GetSpecificFeature
SecondSelPlanar = True
tmpArrayData(0) = 0
tmpArrayData(1) = 0
tmpArrayData(2) = 1
Set tmpPt = swMathUtil.CreatePoint(tmpArrayData)
Set mySecondXform = mySel2.Transform 'This gets the xfrom inside the component (not assy)
Set tmpPt = tmpPt.MultiplyTransform(mySecondXform)
Set mySecondNormVect = swMathUtil.CreateVector(tmpPt.ArrayData)
'mysecondNormVect now contains the normal vector in part coords of the selected plane
ElseIf swSelMgr.GetSelectedObjectType3(2, -1) = 2 Then 'faces
Set mySel2 = swSelMgr.GetSelectedObject6(2, -1)
Set mySecondNormVect = swMathUtil.CreateVector(mySel2.Normal)
If mySecondNormVect.GetLength <> 0 Then
SecondSelPlanar = True
Else
SecondSelPlanar = False
End If
Else
SecondSelPlanar = False
Set mySecondNormVect = Nothing
Set mySel2 = swSelMgr.GetSelectedObject6(2, -1)
End If
'get the distance value and distance vector
myDist = swDoc.ClosestDistance(mySel1, mySel2, FirstDistPoint, SecondDistPoint)
Set FirstDistVect = swMathUtil.CreateVector(FirstDistPoint)
Set myDistVect = FirstDistVect.Subtract(swMathUtil.CreateVector(SecondDistPoint))
''''''Now get the in-assembly transforms for each component
Set myFirstXform = swSelMgr.GetSelectedObjectsComponent3(1, -1).GetTotalTransform(True)
Set mySecondXform = swSelMgr.GetSelectedObjectsComponent3(2, -1).GetTotalTransform(True)
If FirstSelPlanar And SecondSelPlanar Then
Set myFirstNormVect = myFirstNormVect.MultiplyTransform(myFirstXform)
Set mySecondNormVect = mySecondNormVect.MultiplyTransform(mySecondXform)
Set myCross = myFirstNormVect.Cross(mySecondNormVect)
If myCross.GetLength < 0.000000001 Then 'assume planes are parallel. Use par. dist
myDist = Abs(myDistVect.Dot(myFirstNormVect.Normalise))
Else
'Leave myDist as-is
End If
ElseIf FirstSelPlanar Then
'Debug.Print "first planar"
myDist = Abs(myDistVect.Dot(myFirstNormVect.Normalise))
ElseIf SecondSelPlanar Then
'Debug.Print "second planar"
myDist = Abs(myDistVect.Dot(mySecondNormVect.Normalise))
End If
'MsgBox myDist * SF
GetInitialDist = myDist
Set swApp = Nothing
Set swDoc = Nothing
Set swSelMgr = Nothing
Set swMathUtil = Nothing
Set myFace = Nothing
Set myFirstNormVect = Nothing
Set mySecondNormVect = Nothing
Set myFirstXform = Nothing
Set mySecondXform = Nothing
Set myDistVect = Nothing
Set FirstDistVect = Nothing
Set mySel1 = Nothing
Set mySel2 = Nothing
Set myCross = Nothing
Set tmpPt = Nothing
End Function