- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
I work with models that contain Gross Building AreaPlans with their respective Areas and AreaBoundary lines. The goal is to use the AreaBoundaries to extrude a solid, into a GenericModel per Level. This can be achieved in Dynamo, but is not reliable and has difficulty with more complicated geometry. Trying with a Python node gives me an 'internal exception' where the NewExtrusion is called.
Trying with pyRevit, it gives a 'managed exception' where the NewExtrusion is called. Here is my script:
#Create Extrusions from Gross Boundaries
import clr
import sys
import pyrevit
from pyrevit import revit, DB, script, forms, api
doc = revit.doc
doc_create = doc.Create
with DB.Transaction(doc, "Create Family Doc") as tx:
tx.Start()
m_familyDocument = doc.Application.NewFamilyDocument("C:/ProgramData/Autodesk/RVT 2023/Family Templates/English-Imperial/Generic Model.rft")
m_creationFamily = m_familyDocument.FamilyCreate
print(m_creationFamily)
tx.Commit()
all_views = DB.FilteredElementCollector(doc).OfCategory(DB.BuiltInCategory.OST_Views).WhereElementIsNotElementType()
viewsGross = []
viewsGrossNames = []
for v in all_views:
if not v.IsTemplate:
if (doc.GetElement(v.GetTypeId())).get_Parameter(DB.BuiltInParameter.ALL_MODEL_TYPE_NAME).AsString() == "Gross Building":
if not v.GenLevel.Name == "R001":
if not v.GenLevel.Name == "S001":
viewsGross.append(v)
viewsGrossNames.append(v.GenLevel.Name)
#print(viewsGross)
print(viewsGrossNames)
gross_areas = []
#for view in viewsGross:
gross_view_areas = DB.FilteredElementCollector(doc, viewsGross[0].Id).OfCategory(DB.BuiltInCategory.OST_Areas).WhereElementIsNotElementType()
for view_areas in gross_view_areas:
gross_areas.append(view_areas)
print(gross_view_areas)
print("Gross Areas")
print(len(gross_areas))
with DB.Transaction(doc, "Get Segments and Sketchplanes") as tx:
tx.Start()
area_segments = []
sketch_planes = []
for area in gross_areas:
sketch_plane = DB.SketchPlane.Create(doc,area.LevelId)
sketch_planes.append(sketch_plane)
opt = DB.SpatialElementBoundaryOptions()
segments = area.GetBoundarySegments(opt)
area_segments.append(segments)
segments_sketchplanes = zip(area_segments,sketch_planes)
tx.Commit()
#print(sketch_planes)
#print(segments_sketchplanes)
#print("Area Segments")
#print(area_segments)
#print(len(area_segments))
one_loop = segments_sketchplanes[0]
#print(one_loop)
area_curves = []
for segmentz in one_loop[0]:
curveArrArray = DB.CurveArrArray()
for seg in segmentz:
curveArray = DB.CurveArray()
curve = seg.GetCurve()
area_curves.append(curve)
# Sorting and grouping the curves into contiguous loops
def find_contiguous_loop(start_curve, remaining_curves):
loop = [start_curve]
next_point = start_curve.GetEndPoint(1)
while loop[0].GetEndPoint(0) != loop[-1].GetEndPoint(1):
found = False
for curve in remaining_curves:
if next_point.IsAlmostEqualTo(curve.GetEndPoint(0)):
loop.append(curve)
next_point = curve.GetEndPoint(1)
remaining_curves.remove(curve)
found = True
break
elif next_point.IsAlmostEqualTo(curve.GetEndPoint(1)):
curve.CreateReversed()
loop.append(curve)
next_point = curve.GetEndPoint(0)
remaining_curves.remove(curve)
found = True
break
if not found:
break
return loop
# Sorting and grouping the curves into contiguous loops
sorted_loops = []
#while area_curves:
remaining_curves = area_curves[:]
loop = find_contiguous_loop(area_curves[0], remaining_curves)
# Check if the loop is valid (more than one curve)
if len(loop) > 1:
sorted_loops.append(loop)
print("Sorted Loops")
print(sorted_loops)
print(len(sorted_loops))
# Now, sorted_loops contains the contiguous loops of curves
for loop in sorted_loops:
curveArrArray = DB.CurveArrArray()
for curve in loop:
curveArray = DB.CurveArray()
curveArray.Append(curve)
curveArrArray.Append(curveArray)
print(curveArrArray)
if curveArrArray.Size > 0:
# Create extrusion for each loop
with DB.Transaction(doc, "Create Extrusion") as tx:
tx.Start()
area_extrusion = m_creationFamily.NewExtrusion(True, curveArrArray, one_loop[1], 20.0)
tx.Commit()
#print(m_familyDocument)
#print(m_creationFamily)
#print(normal)
#print(origin)
#print(plane)
#print(sketchplane)
#print(curveArrArray)
#print(area_curves)
#print(len(area_curves))
#print(startcurve)
#print(startP)
#print(endP)
#print(curve)
#print(curveArray.Size)
#print(curveArrArray.Size)
This script is only meant to process a single Area. Hopefully I can scale up later.
Since I established that the GetBoundarySegments method is the one to use, are the Segments returned contiguous or need to be sorted?
I have tried with and without the 'find_continuous_loop' function , same error. See the attached Revit file containing a Gross Building AreaPlan with a relatively simple Area for testing.
Any help is appreciated.
Thanks,
-Loren
Solved! Go to Solution.