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

Strange To Room and From Room Data on Elements

If you have relied on the "To Room" or "From Room" data on an element and didn't always get what you were expecting, I'd be willing to bet that it is due to one of two things. No room elements in the newest phase of your model or refer* to the first reason.

* recursion humor

Room data for the "To Room" and "From Room" parameters on FamilyInstance elements can only read from rooms in the youngest phase in time. This means that any room you place in a previous phase in your model will be ignored in terms of "To Room" and "From Room" no matter what. Confused yet?

Let's say that your model has three phases:

  • Existing
  • Main Construction
  • Future
If you perform most of your modeling and place your rooms in the "Main Construction" phase none of your elements will return a "To Room" or "From Room" element at all unless these rooms are placed in the "Future" phase. Something even a bit more confusing is that your existing doors will report the "To Room" and "From Room" data for the room that exists in the same location in the newest phase.

The image below shows the room data that results from a door selected in a view that is set to the existing phase. There are rooms on either side both places in the existing phase yet the data reported by the door is showing from the future. If the rooms placed in the future phase were deleted, this door would not display any room data even though there are clearly two existing rooms on either side of the door.



The two phases are shown below to help you understand how this door data is coming through the element.



The "To Room" and "From Room" data comes from the rooms placed in the newest phase of your model only so be careful when developing tools that rely on these room settings. You can see below what happens when an element is not adjacent to any rooms in the last phase of your model... you get nothing:


Thursday, December 15, 2011

How To Uninstall or Remove a Revit Add-In

I've been getting this question quite a bit recently:
"How do I remove an Add-In from Revit?"



This post will not focus on what an Add-In is nor what an Add-In manifest is... hopefully you already have an idea or can find out about those things here.

The uninstall solution depends on the version of Revit that you are running. The method that I will discuss in this post is suitable for Revit 2011 and newer. If you are using Revit 2010 then you just need to go ahead and upgrade your shiz.

There are two locations that Add-In manifests can be placed to load into Revit. The paths shown below are for Windows7. If you are still running Windows XP than it may be time to update your other shiz.

Machine Wide Location
The first is available to all users that log into the machine and requires administrative privileges to add files to.

  • C:\ProgramData\Autodesk\Revit\Addins\
User Profile Location
The user profile location will only load for the current user. This location does not require administrative privileges and therefor anyone can install Revit Add-Ins into their environment if they use this location.
  • %USERPROFILE%\AppData\Roaming\Autodesk\Revit\Addins\

Preventing the Add-In from Loading
There's a bunch of ways to prevent an Add-In from loading into Revit.

  • Removing the associated .addin file from either of the locations mentioned above will prevent the Add-In from loading into Revit. You can leave the .dll and all other files there if you want and they will not load without the associated .addin file instructing Revit to do so.
  • Another trick is to simply rename the extension of the .addin file to something like .addin.notloaded or something to keep it from loading.
  • Revit 2011 and 2012 do not load .addin files that are placed in sub-directories of these Add-In manifest directories either, so you could just simply create a sub-directory for the Add-Ins that you don't want to be loaded and place them in that sub directory.

Sunday, December 4, 2011

Free Revit Add-Ins from Your Friends @ Case Design, Inc.


It has been a while since I've posted anything so I’d like this to be one for the users out there. We’ve been working on lots of cool stuff recently including the beginnings of what we will be offering as a suite of free tools for Revit 2012 and beyond.

For those of you that made it out to Autodesk University 2011 in Las Vegas and attended our first annual AU Tweetup (free beers for our twitter friends), you may have heard about a few of these tools. We released three fully functional tools that you can install from our apps site by registering your valid email address. Once you’ve registered for the tools, the links to install will be revealed in the page.

The first three tools of the Case Free Tool Suite include:


Once installed, the tools will be accessible from a new Tab on your Revit Ribbon named "Case Design, Inc." These are are intended to be simple to use everyday use tools to help out. If you ever have a need for anything more complicated or heavily customized give me a shout and I'd be happy to work with you on a solution.

We are planning to add others in the future to our free suite of tools, so stay tuned to announcements from this blog as well as twitter from any of the following accounts:
@case_inc
@AYBABTM
@davidfano
@fedenegro