AVF Displays Intersections and Highlights Rooms

We held a DevLab in Gothenburg yesterday with lots of interesting things to discuss with our Scandinavian developer guests.
Today we are in Munich, Germany.
So is
Kean :-)

One of the topics that came up yesterday is a thing I have been wanting to write about for over a year now and never gotten around to, the use of the AVF or Analysis Visualisation Framework to display temporary geometry to the user.

I used it myself to display a

live webcam image on a building element
,
and Saikat used it in the AVF part of his

structural AVF and DMU sample
,
although I only documented the DMU or Dynamic Model Update aspect of it in detail.

This kind of use of the AVF is also demonstrated by the Revit SDK sample GeometryCreation_BooleanOperation.
It creates geometry solids using the GeometryCreationUtils and BooleanOperationUtils classes and displays them in a view using AVF.

FindColumns Using Geometry Creation and Booleans

Transient AVF visualisation was used very impressively in the presentation of new geometry functionality at the developer conferences last year.
<!–
385_devcamp_whats_new.htm:

  • FindColumns
    572_devdays_online.htm:
  • Updated version of the FindColumns SDK sample, using
    new geometry and AVF API features instead of FindReferencesByDirection to find a
    nd display all intersections between walls and columns.
    694_avf_hilite_rooms.htm:You may and should be aware of the FindColumns example
    of using the FindReferencesByDirection method to determine collisions between wa
    lls and columns.
    –>
    You may and should be aware of the
    FindColumns
    example of using the FindReferencesByDirection method to determine collisions between walls and columns in a situation like this:

    Wall and column intersections

    As I mentioned in the

    DevDays 2010 Online with Revit 2012 API news
    ,
    it was converted to use the exact wall and column geometry instead of the original approximate ray tracing approach, and the results are displayed exactly by hiding the wall and column categories in the view and displaying their intersection solids using AVF instead.

    It defines two commands:

    • HighlightIntersectionsCommand to determine and display the intersections, and
    • RestoreViewCommand to restore the view afterwards, i.e. reset the wall and column category visibility in the view.

    Here is the original 3D view of the situation:

    3D view of wall and column intersections

    Running HighlightIntersectionsCommand performs the following steps:

    • Hide the wall and column categories in the current view.
    • Set up an AVF view.
    • Collect all walls and column elements.
    • Query them for their solid geometry.
    • Calculate their intersections.
    • List and display the results.

    Here is the list of the resulting intersections:

    Wall and column intersection results

    This is what the intersection geometry looks like in AVF:

    Wall and column intersection solids in AVF

    As said, you can call RestoreViewCommand afterwards to restore the view by resetting the wall and column category visibility in the view.

    For your reference, here is
    Geometry2012.zip containing
    the C# sample code and Visual Studio solution together the suitable sample model to run it in.

    So all of that is really important stuff from last year that I have been dying to publish for such a long time and never gotten around to.
    Finally!

    Highlight Rooms Using AVF in VB

    I passed the geometry sample on to Betina Mette Zimmermann of

    NTI CAD Center A/S
    in
    Denmark, and she converted it to VB and modified it to highlight the room geometry returned by the Room.ClosedShell method instead of wall and column intersections within half an hour:

    
    #Region "Namespaces"
    Imports System
    Imports System.Collections.Generic
    Imports Autodesk.Revit.ApplicationServices
    Imports Autodesk.Revit.Attributes
    Imports Autodesk.Revit.DB
    Imports Autodesk.Revit.DB.Analysis
    Imports Autodesk.Revit.DB.Architecture
    Imports Autodesk.Revit.UI
    Imports Autodesk.Revit.UI.Selection
    #End Region
     
    <Transaction(TransactionMode.Manual)>
    Public Class Command
      Implements IExternalCommand
     
      Private schemaId As Integer = -1
     
      Public Function Execute(
        ByVal commandData As ExternalCommandData,
        ByRef message As String,
        ByVal elements As ElementSet) _
      As Result Implements IExternalCommand.Execute
     
        Dim uidoc As UIDocument = commandData.Application.ActiveUIDocument
        Dim doc As Document = uidoc.Document
     
        Dim transaction As Transaction = New Transaction(doc)
     
        Try
          Dim col As FilteredElementCollector _
            = New FilteredElementCollector(uidoc.Document)
     
          col.WhereElementIsNotElementType.ToElements()
          col.OfCategory(BuiltInCategory.OST_Rooms)
     
     
          Dim value As Double = 1.0
          For Each room As Room In col
            Dim geo As GeometryElement = room.ClosedShell()
            Dim solid As Solid = GetGeometry(geo)
            If Not solid Is Nothing Then
              PaintSolid(doc, solid, value)
            End If
            value = value + 1
          Next
     
          transaction.Start("Hide Walls")
     
          Dim categories As Categories _
            = uidoc.Document.Settings.Categories
     
          SetCategoryInvisible( _
            categories, BuiltInCategory.OST_Walls,
            uidoc.ActiveView)
     
          transaction.Commit()
     
          Return Result.Succeeded
     
        Catch ex As Exception
          message = ex.Message
          Return Result.Failed
        End Try
     
      End Function
     
      Public Shared Sub SetCategoryInvisible( _
        ByVal categories As Categories, _
        ByVal bic As BuiltInCategory, _
        ByVal view As View)
     
        SetCategoryVisibility(categories, bic, view, False)
     
      End Sub
     
      Private Shared Sub SetCategoryVisibility( _
        ByVal categories As Categories, _
        ByVal bic As BuiltInCategory, _
        ByVal view As View, _
        ByVal visible As Boolean)
     
        Dim category As Category = categories.Item(bic)
        category.Visible(view) = visible
     
      End Sub
     
      Public Function GetGeometry( _
        ByVal geomElem As GeometryElement) As Solid
     
        For Each geomObj As GeometryObject In geomElem.Objects
     
          ' Walls and some columns will have a solid 
          ' directly in its geometry
     
          If TypeOf geomObj Is Solid Then
            Dim solid As Solid = DirectCast(geomObj, Solid)
            If solid.Volume > 0 Then
              Return solid
            End If
          End If
     
          ' Some columns will have a instance 
          ' pointing to symbol geometry
     
          If TypeOf geomObj Is GeometryInstance Then
     
            Dim geomInst As GeometryInstance _
              = DirectCast(geomObj, GeometryInstance)
     
            ' Instance geometry is obtained so that the 
            ' intersection works as expected without 
            ' requiring transformation
     
            Dim instElem As GeometryElement _
              = geomInst.GetInstanceGeometry()
     
            For Each instObj As GeometryObject In instElem.Objects
              If TypeOf instObj Is Solid Then
                Dim solid As Solid = DirectCast(instObj, Solid)
                If solid.Volume > 0 Then
                  Return solid
                End If
              End If
            Next
          End If
        Next
        Return Nothing
      End Function
     
      Private Sub PaintSolid( _
        ByVal doc As Document, _
        ByVal s As Solid, _
        ByVal value As Double)
     
        Dim app As Application = doc.Application
     
        Dim view As View = doc.ActiveView
     
        If view.AnalysisDisplayStyleId _
          = ElementId.InvalidElementId Then
     
          CreateAVFDisplayStyle(doc, view)
        End If
     
        Dim sfm As SpatialFieldManager _
          = SpatialFieldManager.GetSpatialFieldManager(view)
     
        If sfm Is Nothing Then
          sfm = SpatialFieldManager _
            .CreateSpatialFieldManager(view, 1)
        End If
     
        If schemaId <> -1 Then
          Dim results As IList(Of Integer) _
            = sfm.GetRegisteredResults()
     
          If Not results.Contains(schemaId) Then
            schemaId = -1
          End If
        End If
     
        If schemaId = -1 Then
          Dim resultSchema1 As New AnalysisResultSchema( _
            "PaintedSolid", "Description")
     
          schemaId = sfm.RegisterResult(resultSchema1)
        End If
     
        Dim faces As FaceArray = s.Faces
        Dim trf As Transform = Transform.Identity
     
        For Each face As Face In faces
          Dim idx As Integer _
            = sfm.AddSpatialFieldPrimitive(face, trf)
     
          Dim uvPts As IList(Of UV) = New List(Of UV)()
          Dim doubleList As New List(Of Double)()
     
          Dim valList As IList(Of ValueAtPoint) _
            = New List(Of ValueAtPoint)()
     
          Dim bb As BoundingBoxUV = face.GetBoundingBox()
          uvPts.Add(bb.Min)
          doubleList.Add(value)
          valList.Add(New ValueAtPoint(doubleList))
          Dim pnts As New FieldDomainPointsByUV(uvPts)
          Dim vals As New FieldValues(valList)
     
          sfm.UpdateSpatialFieldPrimitive( _
            idx, pnts, vals, schemaId)
        Next
      End Sub
     
      Private Sub CreateAVFDisplayStyle( _
        ByVal doc As Document, _
        ByVal view As View)
     
        Dim t As New Transaction(doc)
        t.Start("Create AVF Style")
     
        Dim coloredSurfaceSettings As _
          New AnalysisDisplayColoredSurfaceSettings()
     
        coloredSurfaceSettings.ShowGridLines = True
     
        Dim colorSettings As _
          New AnalysisDisplayColorSettings()
     
        Dim legendSettings As _
          New AnalysisDisplayLegendSettings()
     
        legendSettings.ShowLegend = False
     
        Dim analysisDisplayStyle As AnalysisDisplayStyle _
          = analysisDisplayStyle.CreateAnalysisDisplayStyle( _
            doc, "Paint Solid", coloredSurfaceSettings, _
            colorSettings, legendSettings)
     
        view.AnalysisDisplayStyleId = analysisDisplayStyle.Id
     
        t.Commit()
      End Sub
     
    End Class
    

    To test this, I created the following Revit model of a cow hotel, implemented according to a design suggested by Jim Quanci in the Gothenburg airport:

    Jim's cow hotel

    Here are the resulting highlighted rooms using AVF:

    Cow hotel rooms highlighted

    Here is
    HighlightRooms.zip containing
    the VB code and complete Visual Studio solution for this command.

    Many thanks to Betina for implementing and sharing this!


  • Comments

    Leave a Reply

    Discover more from Autodesk Developer Blog

    Subscribe now to keep reading and get access to the full archive.

    Continue reading