Reply

Find Unconstrained Geometry

Hello everyone Smiley Happy

 

I'm sure we've all struggled to work through a sketch to try and find an underconstrained element that is causing the sketch to show as underconstrained.

 

Quite often for me when I'm look at other peoples work it is either a very small element left over after a number of trim operations or two lines sat directly on top of each other.

 

There isn't a function in SE to find the underconstrained elements so I have been tring to develop a little macro that will loop through the sketches in a part document and zoom onto each element so you can find the "very tiny" or the "hidden behind" elements.

 

So far I've only worked with lines and I can zoom onto each line, highlight it and ask the user if they want to move on to the next line.

 

It would be so much easier if I could identify which lines are underconstrained but this can't be done, I can't even start the macro in the sketch definition and use the SE colours for constrained/not-constrained as they don't show in any properties.

 

I also can't collect the user input in any other manner than a messagebox which is fine for two screens but with only one screen the messagebox sits directly over the line being viewed.

 

I wonder if anyone can offer any advice on those two points, I've included my code below and I'll post the final result so others can use it in the future.

 

Imports SolidEdgeFramework
Imports System.Runtime.InteropServices

Public Class FindUnderConstrainedSketchElement


    <STAThread()> _
    Public Sub FindUnderConstrainedSketchElement()

        'Declare the required SolidEdge objects
        Dim objApplication As SolidEdgeFramework.Application = Nothing
        Dim objWindow As SolidEdgeFramework.Window = Nothing
        Dim objView As SolidEdgeFramework.View = Nothing
        Dim objPart As SolidEdgePart.PartDocument = Nothing
        Dim objSketches As SolidEdgePart.Sketchs = Nothing
        Dim objSketch As SolidEdgePart.Sketch = Nothing
        Dim objProfiles As SolidEdgePart.Profiles = Nothing
        Dim objProfile As SolidEdgePart.Profile = Nothing
        Dim objLines2D As SolidEdgeFrameworkSupport.Lines2d = Nothing
        Dim objLine2D As SolidEdgeFrameworkSupport.Line2d = Nothing

        Dim arNormal(2) As Double
        Dim objPlane As SolidEdgePart.RefPlane = Nothing

        Dim dblOriginPoint(1) As Double
        Dim dblOriginAxis(1) As Double

        Dim lngKeyPointType As SolidEdgeConstants.KeyPointType
        Dim lngHandleType As SolidEdgeConstants.HandleType
        Dim objStart(2) As Double
        Dim objEnd(2) As Double

        Dim intBaseWidth As Integer
        Dim low(2) As Double
        Dim high(2) As Double
        Dim maxLength As Double

        Dim objCamera As New CameraSettings

        Try
            'Register the message filter to filter COM exception messages
            MessageFilter.Register()

            ' Connect to a running instance of Solid Edge
            objApplication = Marshal.GetActiveObject("SolidEdge.Application")

            'Check the current document is a part document
            If objApplication.ActiveDocumentType = DocumentTypeConstants.igPartDocument Then

                'Collect the part document
                objPart = objApplication.ActiveDocument

                'Collect the sketches
                objSketches = objPart.Sketches

                For Each objSketch In objSketches

                    'Look at the profiles in undefined sketches
                    If objSketch.IsUnderDefined Then

                        'Collect the planar details of the sketch
                        objSketch.GetLocalXAxis(dblOriginPoint(0), dblOriginPoint(1), _
                                                dblOriginAxis(0), dblOriginAxis(1))

                        'Get the current camera settings
                        objWindow = objApplication.ActiveWindow
                        objView = objWindow.View
                        objView.GetCamera( _
                                objCamera.EyeX, objCamera.EyeY, objCamera.EyeZ, _
                                objCamera.TargetX, objCamera.TargetY, objCamera.TargetZ, _
                                objCamera.UpX, objCamera.UpY, objCamera.UpZ, _
                                objCamera.Perspective, objCamera.Scale)

                        'Clear the select set
                        objWindow.SelectSet.RemoveAll()

                        'Loop through each profile
                        objProfiles = objSketch.Profiles
                        For Each objProfile In objProfiles

                            'Collect the normal unit vector for the sketch plane
                            objPlane = objProfile.Plane
                            objPlane.GetNormal(arNormal)

                            'Loop through the lines in the profile
                            objLines2D = objProfile.Lines2d
                            For Each objLine2D In objLines2D

                                'Select the current line only
                                objLine2D.Select()

                                objWindow.SelectSet.RefreshDisplay()

                                'Collect the mid point of the line and set the camera to focus on it
                                objLine2D.GetKeyPoint(0, objStart(0), objStart(1), objStart(2), _
                                                            lngKeyPointType, lngHandleType)

                                objLine2D.GetKeyPoint(1, objEnd(0), objEnd(1), objEnd(2), _
                                                      lngKeyPointType, lngHandleType)

                                objProfile.Convert2DCoordinate( _
                                    objStart(0) + (0.5 * (objEnd(0) - objStart(0))), _
                                    objStart(1) + (0.5 * (objEnd(1) - objStart(1))), _
                                    objCamera.TargetX, objCamera.TargetY, objCamera.TargetZ)

                                'It is important to move the camera eye so that it is normal to the 
                                'sketch plane
                                objCamera.EyeX = objCamera.TargetX * (1 + arNormal(0))
                                objCamera.EyeY = objCamera.TargetY * (1 + arNormal(1))
                                objCamera.EyeZ = objCamera.TargetZ * (1 + arNormal(2))

                                'Calculate the scale to fit the line into the screen
                                intBaseWidth = objWindow.Width
                                objView.GetModelRange(low(0), low(1), low(2), high(0), high(1), high(2))

                                maxLength = Math.Max( _
                                    Math.Max(high(0) - low(0), high(1) - low(1)), high(2) - low(2))

                                objCamera.Scale = (maxLength / objLine2D.Length) * 1000

                                objView.SetCamera( _
                                        objCamera.EyeX, objCamera.EyeY, objCamera.EyeZ, _
                                        objCamera.TargetX, objCamera.TargetY, objCamera.TargetZ, _
                                        objCamera.UpX, objCamera.UpY, objCamera.UpZ, objCamera.Perspective, _
                                        objCamera.Scale)

                                'Update the view
                                objView.Update()
                                objApplication.DoIdle()

                                'Present the user with a message and the opportunity to cancel or continue
                                If MessageBox.Show("Press Cancel to stop, press OK for the next line", _
                                    "Line " & objLine2D.Name, MessageBoxButtons.OKCancel) = _
                                        DialogResult.Cancel Then
                                    Exit For
                                Else
                                    'Clear the select set
                                    objWindow.SelectSet.RemoveAll()
                                End If

                            Next

                        Next

                    End If

                Next

            End If

        Catch ex As Exception
            Console.WriteLine(ex.Message)
            MessageBox.Show(ex.Message)
        Finally

            If Not (objPlane Is Nothing) Then
                Marshal.ReleaseComObject(objPlane)
                objPlane = Nothing
            End If

            If Not (objLine2D Is Nothing) Then
                Marshal.ReleaseComObject(objLine2D)
                objLine2D = Nothing
            End If

            If Not (objLines2D Is Nothing) Then
                Marshal.ReleaseComObject(objLines2D)
                objLines2D = Nothing
            End If

            If Not (objProfile Is Nothing) Then
                Marshal.ReleaseComObject(objProfile)
                objProfile = Nothing
            End If

            If Not (objProfiles Is Nothing) Then
                Marshal.ReleaseComObject(objProfiles)
                objProfiles = Nothing
            End If

            If Not (objSketch Is Nothing) Then
                Marshal.ReleaseComObject(objSketch)
                objSketch = Nothing
            End If

            If Not (objSketches Is Nothing) Then
                Marshal.ReleaseComObject(objSketches)
                objSketches = Nothing
            End If

            If Not (objPart Is Nothing) Then
                Marshal.ReleaseComObject(objPart)
                objPart = Nothing
            End If

            If Not (objView Is Nothing) Then
                Marshal.ReleaseComObject(objView)
                objView = Nothing
            End If

            If Not (objWindow Is Nothing) Then
                Marshal.ReleaseComObject(objWindow)
                objWindow = Nothing
            End If

            If Not (objApplication Is Nothing) Then
                Marshal.ReleaseComObject(objApplication)
                objApplication = Nothing
            End If

            'Revoke the message filter
            MessageFilter.Revoke()

        End Try

        MessageBox.Show("Completed")

    End Sub

    ''' <summary>
    ''' Class to hold and update the camera settings after the Get and Set methods are called
    ''' </summary>
    ''' <remarks></remarks>
    Private Class CameraSettings

        Dim m_eyex As Double
        Dim m_eyey As Double
        Dim m_eyez As Double
        Dim m_targetx As Double
        Dim m_targety As Double
        Dim m_targetz As Double
        Dim m_upx As Double
        Dim m_upy As Double
        Dim m_upz As Double
        Dim m_perspective As Double
        Dim m_scale As Double

        Public Property EyeX As Double
            Get
                Return Me.m_eyex
            End Get
            Set(ByVal value As Double)
                Me.m_eyex = value
            End Set
        End Property

        Public Property EyeY As Double
            Get
                Return Me.m_eyey
            End Get
            Set(ByVal value As Double)
                Me.m_eyey = value
            End Set
        End Property

        Public Property EyeZ As Double
            Get
                Return Me.m_eyez
            End Get
            Set(ByVal value As Double)
                Me.m_eyez = value
            End Set
        End Property

        Public Property TargetX As Double
            Get
                Return Me.m_targetx
            End Get
            Set(ByVal value As Double)
                Me.m_targetx = value
            End Set
        End Property

        Public Property TargetY As Double
            Get
                Return Me.m_targety
            End Get
            Set(ByVal value As Double)
                Me.m_targety = value
            End Set
        End Property

        Public Property TargetZ As Double
            Get
                Return Me.m_targetz
            End Get
            Set(ByVal value As Double)
                Me.m_targetz = value
            End Set
        End Property

        Public Property UpX As Double
            Get
                Return Me.m_upx
            End Get
            Set(ByVal value As Double)
                Me.m_upx = value
            End Set
        End Property

        Public Property UpY As Double
            Get
                Return Me.m_upy
            End Get
            Set(ByVal value As Double)
                Me.m_upy = value
            End Set
        End Property

        Public Property UpZ As Double
            Get
                Return Me.m_upz
            End Get
            Set(ByVal value As Double)
                Me.m_upz = value
            End Set
        End Property

        Public Property Perspective As Double
            Get
                Return Me.m_perspective
            End Get
            Set(ByVal value As Double)
                Me.m_perspective = value
            End Set
        End Property

        Public Property Scale As Double
            Get
                Return Me.m_scale
            End Get
            Set(ByVal value As Double)
                Me.m_scale = value
            End Set
        End Property

    End Class

End Class