Wednesday, December 28, 2011

To and From Room Query Tool

I posted earlier on the weird behavior of FamilyInstance "To Room" and "From Room" data. I just thought I'd go ahead and share the simple tool that I used to query the elements.

The sample project consists of a command entry class, a selection manager class and one form.

The first class shown below is used to manage the selection of elements or faces in a model. This class is taken from the SDK with some minor adjustments.

Imports Autodesk.Revit.DB
Imports Autodesk.Revit.UI
Imports Autodesk.Revit.UI.Selection

''' <summary>
''' Selection type.
''' </summary>
Public Enum SelectionType
    Element
    Face
    Edge
    Point
End Enum

''' <summary>
''' A class for object selection and storage.
''' </summary>
Public Class clsSelectionManager

    Private m_commandData As ExternalCommandData
    Private m_application As UIApplication
    Private m_document As UIDocument
    Private m_CreationBase As Autodesk.Revit.Creation.ItemFactoryBase
    Private m_elemPickedPoint As XYZ
    Private m_selectionType As SelectionType = SelectionType.Element
    Private m_selectedPoint As XYZ
    Private m_selectedElement As Element

    ''' <summary>
    ''' constructor of SelectionManager
    ''' </summary>
    ''' <param name="commandData"></param>
    Public Sub New(commandData As ExternalCommandData)

        ' Widen Scope
        m_commandData = commandData
        m_application = m_commandData.Application
        m_document = m_application.ActiveUIDocument

        ' Support for Family and Project Environment
        If m_document.Document.IsFamilyDocument Then
            m_CreationBase = m_document.Document.FamilyCreate
        Else
            m_CreationBase = m_document.Document.Create
        End If

    End Sub

    ''' <summary>
    ''' For specific selection type.
    ''' </summary>
    Public Property SelectionType() As SelectionType
        Get
            Return m_selectionType
        End Get
        Set(value As SelectionType)
            m_selectionType = value
        End Set
    End Property

    ''' <summary>
    ''' Store the selected element.
    ''' </summary>
    Public Property SelectedElement() As Element
        Get
            Return m_selectedElement
        End Get
        Set(value As Element)
            m_selectedElement = value
        End Set
    End Property

    ''' <summary>
    ''' Store the selected point. 
    ''' When the point is picked, move the element to the point.
    ''' </summary>
    Public Property SelectedPoint() As XYZ
        Get
            Return m_selectedPoint
        End Get
        Set(value As XYZ)
            m_selectedPoint = value
            If m_selectedElement IsNot Nothing AndAlso m_selectedPoint IsNot Nothing Then
                MoveElement(m_selectedElement, m_selectedPoint)
            End If
        End Set
    End Property

    ''' <summary>
    ''' Select objects according to the selection type.
    ''' </summary>
    Public Sub SelectObjects()
        Select Case m_selectionType
            Case SelectionType.Element
                PickElement()
                ' pick element
                Exit Select
            Case SelectionType.Face
                Exit Select
            Case SelectionType.Edge
                Exit Select
            Case SelectionType.Point
                PickPoint()
                ' pick point
                Exit Select
        End Select
    End Sub

    ''' <summary>
    ''' Pick the element from UI.
    ''' </summary>
    Friend Sub PickElement()
        Try
            ' Pick an element.
            Dim eRef As Reference = m_document.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, "Please pick an element.")
            If eRef IsNot Nothing AndAlso eRef.ElementId <> ElementId.InvalidElementId Then
                SelectedElement = m_document.Document.GetElement(eRef)
                m_elemPickedPoint = eRef.GlobalPoint
            End If
        Catch generatedExceptionName As Autodesk.Revit.Exceptions.OperationCanceledException
            ' Element selection cancelled.
            SelectedElement = Nothing
        End Try
    End Sub

    ''' <summary>
    ''' Pick the point from UI.
    ''' </summary>
    Friend Sub PickPoint()
        Try
            ' Pick a point.
            Dim targetPoint As XYZ = m_document.Selection.PickPoint("Please pick a point.")
            SelectedPoint = targetPoint
        Catch generatedExceptionName As Autodesk.Revit.Exceptions.OperationCanceledException
            ' Point selection cancelled.
            SelectedPoint = Nothing
        End Try
    End Sub

    ''' <summary>
    ''' Move an element to the point.
    ''' </summary>
    ''' <param name="elem">The element to be moved.</param>
    ''' <param name="targetPoint">The location element to be moved.</param>
    Friend Sub MoveElement(elem As Element, targetPoint As XYZ)
        Dim vecToMove As XYZ = targetPoint - m_elemPickedPoint
        m_elemPickedPoint = targetPoint
        ElementTransformUtils.MoveElement(m_document.Document, elem.Id, vecToMove)
    End Sub

End Class

The code for the form used to display the to and from data is shown here as well after the image showing the basic layout of the controls:


Public Class Form_ToFrom

    ''' <summary>
    ''' Constructor
    ''' </summary>
    ''' <param name="p_e"></param>
    ''' <remarks></remarks>
    Public Sub New(p_e As FamilyInstance)
        InitializeComponent()

        Try ' To Room
            If Not p_e.ToRoom Is Nothing Then
                Me.LabelToName.Text = p_e.ToRoom.Name
                Me.LabelToNumber.Text = p_e.ToRoom.Number
            Else
                Me.LabelToName.Text = "n/a"
                Me.LabelToNumber.Text = "n/a"
            End If
        Catch ex As Exception
            Me.LabelToName.Text = "n/a"
            Me.LabelToNumber.Text = "n/a"
        End Try
        Try ' From Room
            If Not p_e.FromRoom Is Nothing Then
                Me.LabelFromName.Text = p_e.FromRoom.Name
                Me.LabelFromNumber.Text = p_e.FromRoom.Number
            Else
                Me.LabelFromName.Text = "n/a"
                Me.LabelFromNumber.Text = "n/a"
            End If
        Catch ex As Exception
            Me.LabelFromName.Text = "n/a"
            Me.LabelFromNumber.Text = "n/a"
        End Try
    End Sub

    ''' <summary>
    ''' Close the Form
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub ButtonOk_Click(sender As System.Object, e As System.EventArgs) Handles ButtonOk.Click
        Me.Close()
    End Sub

End Class

Finally, here's the basic command entry and execution class used to launch the Add-In:


Imports Autodesk.Revit.ApplicationServices
Imports Autodesk.Revit.Attributes
Imports Autodesk.Revit.DB
Imports Autodesk.Revit.UI
Imports Autodesk.Revit.UI.Selection

<Transaction(TransactionMode.Automatic)>
Public Class Commands
    Implements IExternalCommand

    ''' <summary>
    ''' Entry
    ''' </summary>
    ''' <param name="commandData"></param>
    ''' <param name="message"></param>
    ''' <param name="elements"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Execute(ByVal commandData As ExternalCommandData,
                            ByRef message As String,
                            ByVal elements As ElementSet) As Result Implements IExternalCommand.Execute
        Try
            ' Selection Manager
            Dim m_mgr As New clsSelectionManager(commandData)

            ' Select an Element
            m_mgr.SelectionType = SelectionType.Element

            ' Pick an Element
            m_mgr.PickElement()

            ' Is it a FamilyInstance?
            If TypeOf m_mgr.SelectedElement Is FamilyInstance Then

                ' Analyze It in the Form
                Using m_d As New Form_ToFrom(m_mgr.SelectedElement)

                    ' Display the Results
                    m_d.ShowDialog()

                End Using

            End If

            ' Return Success
            Return Result.Succeeded

        Catch ex As Exception

            ' Failure
            Return Result.Failed

        End Try

    End Function
End Class

Text