I am trying to create floor from Area Boundaries it works fine for rectangular area but when i select not rectangular area it does not work :
Code as
area_boundaries = area.GetBoundarySegments(SpatialElementBoundaryOptions())
with Transaction(doc, 'Create Floor') as t:
t.Start()
List_curve_loop = List[CurveLoop]()
for area_outline in area_boundaries:
curve_loop = CurveLoop()
for seg in area_outline:
curve_loop.Append(seg.GetCurve())
List_curve_loop.Add(curve_loop)
new_floor = Floor.Create(doc, List_curve_loop, selected_floor_type.Id, level.Id)
Jean-Marc
(Jean-Marc Couffin)
November 7, 2023, 10:16am
2
Hi,
The issue probably has to do with the order of creation of your curve loop.
The complete script would help
the error generated too
references:
Hi all, following on my previous post Sorting Contagious Loop - Autodesk Community I managed to get part of the code working, using example from Revit SDK however there are some cases where sorting curve array fail. Any ideas why?,...
https://thebuildingcoder.typepad.com/blog/2013/03/sort-and-orient-curves-to-form-a-contiguous-loop.html
1 Like
import traceback
from Autodesk.Revit.DB import *
from pyrevit import forms
# .NET IMPORTS
from Autodesk.Revit.DB import CurveLoop, Line, XYZ
import clr
clr.AddReference("System")
from System.Collections.Generic import List
from Autodesk.Revit.DB import XYZ, CurveLoop, CurveArray, SpatialElementBoundaryOptions, BuiltInParameter, Floor, Transaction, FilteredElementCollector
#Custom
from Snippets._context_manager import ef_Transaction, try_except
from Snippets._selection import get_selected_areas
from GUI.forms import select_from_dict
from GUI.Tools.AreaMapper import AreaMapper
import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitAPIUI')
uidoc = __revit__.ActiveUIDocument
app = __revit__.Application
doc = __revit__.ActiveUIDocument.Document
rvt_year = int(app.VersionNumber)
active_view_id = doc.ActiveView.Id
active_view = doc.GetElement(active_view_id)
active_view_level = active_view.GenLevel
class FloorsCreationWarningSwallower(IFailuresPreprocessor):
def PreprocessFailures(self, failuresAccessor):
failList = failuresAccessor.GetFailureMessages()
for failure in failList: #type: FailureMessage
failuresAccessor.DeleteWarning(failure)
# print(failure)
# fail_id = failure.GetFailureDefinitionId()
# if fail_id == BuiltInFailures.OverlapFailures.FloorsOverlap:
# failuresAccessor.DeleteWarning(failure)
# elif fail_id == BuiltInFailures.ExtrusionFailures.CannotDrawExtrusionsError:
# failuresAccessor.DeleteWarning(failure)
return FailureProcessingResult.Continue
def select_floor_type(area_type_value):
"""Function to select Floor Type based on Area Type value."""
if area_type_value == "Hotel":
floor_type_name = "CDA_Mass_Hotel"
elif area_type_value == "Office":
floor_type_name = "CDA_Mass_Office"
elif area_type_value == "Commercial":
floor_type_name = "CDA_Mass_Commercial"
elif area_type_value == "Market Rental":
floor_type_name = "CDA_Mass_MarketRental"
elif area_type_value == "Market Residential":
floor_type_name = "CDA_Mass_MarketResidential"
elif area_type_value == "Social Housing":
floor_type_name = "CDA_Mass_SocialHousing"
elif area_type_value == "Affordable Rental":
floor_type_name = "CDA_Mass_AffordableRental"
else:
floor_type_name = "CDA_Mass_Site"
floor_types = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Floors) \
.WhereElementIsElementType().ToElements()
selected_floor_type = None # Initialize the variable before the loop
for floor_type in floor_types:
type_comments = floor_type.get_Parameter(BuiltInParameter.ALL_MODEL_TYPE_COMMENTS).AsString()
if type_comments == floor_type_name: # Use the correct variable name for comparison
selected_floor_type = floor_type
break # Exit the loop once a matching floor type is found
return selected_floor_type # Return the selected floor type outside the loop
def SortCurves(originalLoop):
sortedLoop = CurveLoop()
if len(originalLoop) == 0:
return None
sortedLoop.Append(originalLoop[0])
sorted = [originalLoop[0]]
print sorted
for i in range(len(originalLoop)):
for oCurve in originalLoop:
if oCurve in sorted:
continue # Prevent curve duplication
# Case of curve is in correct position
if sortedLoop.Last().GetEndPoint(1).IsAlmostEqualTo(oCurve.GetEndPoint(0)):
sorted.append(oCurve)
sortedLoop.Append(oCurve)
break
# Case of curve is inverted
elif sortedLoop.Last().GetEndPoint(1).IsAlmostEqualTo(oCurve.GetEndPoint(1)):
sortedLoop.Append(oCurve.CreateReversed())
sorted.append(oCurve)
break
else:
continue
return sortedLoop
def area_to_floor(area, offset, level):
new_floor = None
try:
# Make sure that Area is bounding.
if not area.get_Parameter(BuiltInParameter.ROOM_AREA).AsDouble():
return None
# Check the shared parameter "Area Type" value
area_type_param = area.LookupParameter("Area Type")
if area_type_param:
area_type_value = area_type_param.AsString()
selected_floor_type = select_floor_type(area_type_value)
# AREA BOUNDARIES
area_boundaries = area.GetBoundarySegments(SpatialElementBoundaryOptions())
List_curve_loop = list[CurveLoop]()
for area_outline in area_boundaries:
print area_outline
curve_loop = SortCurves(area_outline) # Sort the curves using SortCurves function
print curve_loop
if curve_loop:
List_curve_loop.Add(curve_loop)
print List_curve_loop
floor_shape = area_boundaries[0]
openings = list(area_boundaries)[1:] if len(area_boundaries) > 1 else []
if rvt_year < 2022:
with Transaction(doc,'Create Floor') as t:
t.Start()
curve_array = CurveArray()
for seg in floor_shape:
curve_array.Append(seg.GetCurve())
new_floor = doc.Create.NewFloor(curve_array, selected_floor_type, level, False)
if new_floor:
# SET OFFSET
param = new_floor.get_Parameter(BuiltInParameter.FLOOR_HEIGHTABOVELEVEL_PARAM)
param.Set(offset)
failOpt = t.GetFailureHandlingOptions()
failOpt.SetFailuresPreprocessor(FloorsCreationWarningSwallower())
t.SetFailureHandlingOptions(failOpt)
t.Commit()
# CREATE FLOOR OPENINGS SEPERATELY BEFORE RVT 2022
if openings:
with Transaction(doc,'Create FloorOpening') as t2:
t2.Start()
# with ef_Transaction(doc, "Create Openings"):
for opening in openings:
with try_except():
opening_curve = CurveArray()
for seg in opening:
opening_curve.Append(seg.GetCurve())
floor_opening = doc.Create.NewOpening(new_floor, opening_curve, True)
t2.Commit()
if rvt_year >= 2022:
with Transaction(doc, 'Create Floor') as t:
t.Start()
new_floor = Floor.Create(doc, List_curve_loop, selected_floor_type.Id, level.Id) #FIXME
if new_floor:
# SET OFFSET
param = new_floor.get_Parameter(BuiltInParameter.FLOOR_HEIGHTABOVELEVEL_PARAM)
param.Set(offset)
failOpt = t.GetFailureHandlingOptions()
failOpt.SetFailuresPreprocessor(FloorsCreationWarningSwallower())
t.SetFailureHandlingOptions(failOpt)
t.Commit()
except:
# print(traceback.format_exc())
pass
if new_floor:
return new_floor
def create_floors(selected_areas, offset):
"""Function to loop through selected areas and create floors from them."""
new_floors = []
with TransactionGroup(doc, __title__) as tg:
tg.Start()
for r in selected_areas:
with try_except(debug=True):
new_floor = area_to_floor(area = r, offset = offset, level=r.Level)
if new_floor:
new_floors.append(new_floor)
tg.Assimilate()
return new_floors
def get_user_input():
all_ceil_types = FilteredElementCollector(doc).OfClass(FloorType).OfCategory(BuiltInCategory.OST_Floors).ToElements()
dict_ceil_types = {Element.Name.GetValue(fr): fr for fr in all_ceil_types}
GUI = AreaMapper(
title=__title__,
button_name='Create Floors',
version=__version__)
return GUI
if __name__ == '__main__':
selected_areas = get_selected_areas(uidoc, exitscript=True)
GUI = get_user_input()
selected_floor_type = GUI.selected_type
offset = GUI.offset
new_floors = create_floors(selected_areas, offset)
with try_except():
uidoc.Selection.SetElementIds(List[ElementId]([f.Id for f in new_floors if f.IsValidObject]))
I try using Sorted Curve (ps I am using EF tool )
lorhal
(lorhal)
November 10, 2023, 4:45pm
4
I’m glad this issue is being addressed. What I have found is that there are some geometries that Revit just doesn’t like. This will be something I will bring up next week at AU.
I have been working on a script that takes Area boundaries and makes Generic Models out of an extrusion. Anything more complex than your basic orthogonal boundaries would not work. I ended up generating model lines and manually creating the extrusions. Some of the more complex geometries would not let me create an extrusion no matter what I did! Constant warnings of either gaps, intersections, short lines.
My view is: If you can create an Area, you should be able to get those boundaries and use them in any closed loop operation with no issues.
If I get info from AutoDesk, I’ll post it.
Best,
Loren
lorhal
(lorhal)
November 12, 2023, 3:46pm
5
Update:
I had some good luck using GetRoomBoundaryAsCurveLoopArray() from the ExporterIFC module. Check out my post on the Revit API forum:
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...
it worked !! thanks Lorhal `def area_to_floor(area, offset, level):
new_floor = None
try:
# Make sure that Area is bounding.
if not area.get_Parameter(BuiltInParameter.ROOM_AREA).AsDouble():
return None
# Check the shared parameter "Area Type" value
area_type_param = area.LookupParameter("Area Type")
if area_type_param:
area_type_value = area_type_param.AsString()
selected_floor_type = select_floor_type(area_type_value)
# AREA BOUNDARIES
opt = DB.SpatialElementBoundaryOptions()
curve_loop_array = ExporterIFCUtils.GetRoomBoundaryAsCurveLoopArray(area, opt, True)
with Transaction(doc, 'Create Floor') as t:
t.Start()
curve_loop_list = List[CurveLoop]() # Create an empty list of CurveLoop
for curve_loop in curve_loop_array:
# Commenting out the print statement
# print(curve_loop)
curve_loop_list.Add(curve_loop) # Add each CurveLoop to the list
new_floor = Floor.Create(doc, curve_loop_list, selected_floor_type.Id, level.Id)
if new_floor:
# SET OFFSET
param = new_floor.get_Parameter(BuiltInParameter.FLOOR_HEIGHTABOVELEVEL_PARAM)
param.Set(offset)
failOpt = t.GetFailureHandlingOptions()
failOpt.SetFailuresPreprocessor(FloorsCreationWarningSwallower())
t.SetFailureHandlingOptions(failOpt)
t.Commit()
except:
# Print the exception for debugging purposes
print(traceback.format_exc())
return new_floor`