My Test model contains five rooms boundarized by most of the common conditions that exist in a real design model. Some are partially surrounded by room separation lines, one entirely surrounded by room separation lines, one with a curved wall, etc.
Text first thing we need is a complete list collection of the rooms in our model. The code below does this for us and puts the list of room elements into m_Rooms:
' Get the list of rooms Dim m_Collector As New FilteredElementCollector(m_Doc) m_Collector.OfCategory(BuiltInCategory.OST_Rooms) Dim m_Rooms As New List(Of Element) m_Rooms = m_Collector.ToElements
Now we can start iterating our collection of rooms in a For Each loop with the beginning of that shown here:
' Iterate the list and gather a list of boundaries For Each x As Architecture.Room In m_Rooms
This next group of code shows how we will avoid working on unplaced rooms by making sure the Area is larger than 1. The second portion shows how we start the stop watch object used to quantify the time that it takes to generate a mass from each room. Then the path to our specialty equipment family template and the saveas function is called to give the family a name. Make sure that the directory being called already exists for this sample to work.
' Avoid unplaced rooms If x.Area < 1 Then Continue For ' Stopwatcher - This comes FIRST Dim m_StopWatch As New Stopwatch m_StopWatch.Reset() m_StopWatch.Start() ' This is the path to our family template m_FamDoc = m_App.NewFamilyDocument("C:\Documents and Settings\All Users\Application Data\" & _ "Autodesk\RAC 2011\Imperial Templates\Specialty Equipment.rft") ' The "C:\My Families\" directory needs to exist first obviously m_FamDoc.SaveAs("C:\My Families\" & x.UniqueId.ToString & ".rfa")
The next snip shows where we create a transaction for both the main model as well as the family document
' Start a new Model Transaction Dim m_Trans As New Transaction(m_Doc, "My Rooms to Masses - By Boundary") m_Trans.Start() ' Start a new Family Transaction Dim m_TransFam As New Transaction(m_FamDoc, "Transaction in Family Document") m_TransFam.Start()
Now in this next portion, we will create a new subcategory named using the department of the room and material named equally that we will apply to the extrusion that we build the room with. This is handy to display the masses in color related to their department assignment.
' Get the department name Dim m_para As New clsPara(x.Parameter("Department")) Dim m_SubCatName As String = "My_Rooms" If m_para.Value <> "" Then m_SubCatName = "My_Rooms_" & m_para.Value ' Subcategory named by Department Dim m_Subcategory As Category = Nothing Try ' Try to create the subcategory if it does not exist m_Subcategory = m_FamDoc.Settings.Categories.NewSubcategory(m_SECategory, m_SubCatName) Catch ex As Exception ' Get the subcategory object since it exists already Dim m_NameMap As CategoryNameMap = m_SECategory.SubCategories For Each x1 As Category In m_NameMap If x1.Name = m_SubCatName Then m_Subcategory = x1 Exit For End If Next End Try ' Material named by Department Dim m_Material As Material = Nothing Try ' Try to create the material if it does not exist m_Material = m_FamDoc.Settings.Materials.AddWood(m_SubCatName) Catch ex As Exception ' Get the material object since it exists already m_Material = m_FamDoc.Settings.Materials.Item(m_SubCatName) End Try ' Apply the material to the subcategory m_Subcategory.Material = m_Material
Now for the part where we get the room boundary into a curve array that we will eventually use to extrude as a form representing a room element. The snip below iterates through the room boundary objects returning a CurveArray which just so happens to be the second to last process to get us to out required argument that we need to generate the 3D form, CurveArrArray!
' Get the room boundary Dim m_Boundary As Architecture.BoundarySegmentArrayArray = x.Boundary If m_Boundary Is Nothing Then Continue For ' The array of boundary curves Dim m_CurveArray As New CurveArray ' Iterate to gather the curve objects For i = 0 To m_Boundary.Size - 1 ' Boundary segments array Dim m_SegAray As Architecture.BoundarySegmentArray = m_Boundary.Item(i) ' Segments Array For ii = 0 To m_SegAray.Size - 1 Dim m_Seg As Architecture.BoundarySegment = m_SegAray.Item(ii) ' Add the segment curve to the array m_CurveArray.Append(m_Seg.Curve) Next Next
The snip below shows how we build up the workplane that is required to extrude the form from in our family template. We then append the CurveArray to the final argument required to extrude our form... CurveArrArray:
' Simple insertion point Dim pt1 As New XYZ(0, 0, 0) ' Our normal point that points the extrusion directly up Dim ptNormal As New XYZ(0, 0, 1) ' The plane to extrude the mass from Dim m_Plane As Plane = m_AppCreate.NewPlane(ptNormal, pt1) Dim m_SketchPlane As SketchPlane = m_FamDoc.FamilyCreate.NewSketchPlane(m_Plane) ' Need to add the CurveArray to the final requirement to generate the form Dim m_CurveArArray As New CurveArrArray m_CurveArArray.Append(m_CurveArray)
Now we can generate the form and add the extrusion to out subcategory representing the department:
' Extrude the form Dim m_Extrusion As Extrusion = m_FamDoc.FamilyCreate.NewExtrusion(True, m_CurveArArray, m_SketchPlane, 8) Try m_Extrusion.Subcategory = m_Subcategory Catch ex As Exception End Try
The next snip shows how we load the family into the project and place it into the model at 0,0,0 so our coordinates used to generate the form will line up right where the room needs to be:
' Commit the Family Transaction m_TransFam.Commit() ' Load the Family into the Model Dim m_NewFamily As Family = m_FamDoc.LoadFamily(m_Doc) ' Create a reference to the latest family (we just created it) Dim m_FamilySymbolSetIterator As FamilySymbolSetIterator = m_NewFamily.Symbols.ForwardIterator() m_FamilySymbolSetIterator.MoveNext() Dim m_FamSymbol As FamilySymbol = TryCast(m_FamilySymbolSetIterator.Current, FamilySymbol) ' Place the Family at 0,0,0 since we used the same coordinates as the rooms to generate Dim m_FamilyInstance As FamilyInstance = m_Doc.Create.NewFamilyInstance(New XYZ(0, 0, 0), m_FamSymbol, [Structure].StructuralType.NonStructural)
So that's about it.... now we just need to cleanup and close the stopwatch objects and report the timing to the user:
' Commit the Model Transaction m_Trans.Commit() ' Elapsed Time Per Element m_StopWatch.Stop() ' Report the elapsed time MsgBox(m_StopWatch.Elapsed.TotalSeconds.ToString & " Seconds!", MsgBoxStyle.Information, "Elapsed Time!")
Now check out the results....!!! A fully 3D schedulable room mass (as a specialty equipment form)...