mathanvd
(Mathan Van Driessche)
March 14, 2024, 4:52pm
1
Hi everybody,
I want to generate Wall Finish as walls based on room boundaries. But when I run the script, I receive the next message:
(‘An error occurred while creating the wall:’, Exception(‘Could not construct a proper face with the input curves to create a wall correctly.’,))
Something is wrong with my curves/lines, I think. Could somebody help me?
Thanks in advance!
# -*- coding: utf-8 -*-
# imports
# ===================================================
import clr
clr.AddReference('System')
from Autodesk.Revit.DB import *
from pyrevit import revit, DB, forms
from System.Collections.Generic import List
# Variables
# ===================================================
doc = revit.doc
uidoc = revit.uidoc
# definitions
# ===================================================
def afwerkingstype_mapping(wall, wandtypes):
# scheidingsmuur mappen aan afwerkingstype
wandtype = doc.GetElement(wall.GetTypeId())
afwerkingsnaam = wandtype.LookupParameter("Muurafwerkingstype").AsString()
for wt in wandtypes:
if wt.LookupParameter("Type Name").AsString() == afwerkingsnaam:
return wt.Id
def wand_eigenschappen_set(wall):
# hoogte van afwerking setten aan hoogte kamer
height_param = wall.get_Parameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM)
height_param.Set(room_height)
# room bounding van afwerking afzetten
room_bounding_param = wall.get_Parameter(BuiltInParameter.WALL_ATTR_ROOM_BOUNDING)
room_bounding_param.Set(False)
# Main
# ===================================================
rooms = DB.FilteredElementCollector(doc).OfCategory(DB.BuiltInCategory.OST_Rooms).ToElements()
wandtypes = DB.FilteredElementCollector(doc).OfCategory(DB.BuiltInCategory.OST_Walls).WhereElementIsElementType().ToElements()
# input wallfinish
wall_finish_input = forms.ask_for_string()
wall_finish_input = "Pleister" #weg te nemen wanneer script klaar is voor variablen
curve_list = List[Curve]()
t = Transaction(doc,'create wallfinishing')
t.Start()
# Loop door de kamers
for room in rooms:
# Controleren of de oppervlakte niet gelijk is aan 0
if room.Area != 0:
# Wall Finish opvragen + controle
wall_finish_rooms_value = room.LookupParameter("Wall Finish").AsString()
if wall_finish_rooms_value == wall_finish_input:
# Krijg naam van Base & Upper Limit
room_height = room.UnboundedHeight
room_base = room.Level.Name
# Room calculation settings
settings = DB.AreaVolumeSettings.GetAreaVolumeSettings(doc)
b_option = settings.GetSpatialElementBoundaryLocation(SpatialElementType.Room).Finish
options = DB.SpatialElementBoundaryOptions()
options.SpatialElementBoundaryLocation = b_option
# WallLoop
for boundlist in room.GetBoundarySegments(options):
for index, bound in enumerate(boundlist):
wall = doc.GetElement(bound.ElementId)
if wall is None:
try:
index_bound = index - 1
bound = boundlist[index_bound]
except IndexError:
index_bound = index + 1
bound = boundlist[index_bound]
room_boundrys_elements = bound.ElementId
wall = doc.GetElement(bound.ElementId)
# lijst van eigenschappen
curve = bound.GetCurve()
curve_list.Add(curve)
type_afwerkingId = afwerkingstype_mapping(wall,wandtypes)
# wall maken
try:
afwerkings_muur = Wall.Create(doc,curve_list, type_afwerkingId ,room.LevelId,False)
except Exception as e:
# Handle the exception here
print("An error occurred while creating the wall:", e)
#wand_eigenschappen_set(afwerkings_muur)
t.Commit()
@mathanvd ,
Can you explane your code a bit… what do you want to create as a finish? parts ? or an addional wall like tales…
# -*- coding: utf-8 -*-
__title__ = "wallSurface"
__doc__ = """Version = 1.0
Date = 29.10.2023Version = 1.0
Date = 29.10.2023
_____________________________________________________________________
Description:
This is a template file for pyRevit Scripts.
_____________________________________________________________________
How-to:
-> Click on the button
_____________________________________________________________________
Last update:
- [24.04.2022] - 1.0 RELEASE
_____________________________________________________________________
To-Do:
-
"""
# IMPORTS
# ==================================================
# Regular + Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.UI.Selection import ISelectionFilter, ObjectType, Selection
# pyRevit
from pyrevit import revit, forms
# .NET Imports
import clr
clr.AddReference("System")
from System.Collections.Generic import List
# VARIABLES
# ==================================================
doc = __revit__.ActiveUIDocument.Document
uidoc = __revit__.ActiveUIDocument
app = __revit__.Application
selection = uidoc.Selection # type: Selection
# MAIN
# ==================================================
from pyrevit import script
from Autodesk.Revit.DB import *
import time
start_time = time.time()
def afwerkingstype_mapping(wall, wandtypes):
# scheidingsmuur mappen aan afwerkingstype
wandtype = doc.GetElement(wall.GetTypeId())
afwerkingsnaam = wandtype.LookupParameter("Muurafwerkingstype").AsString()
for wt in wandtypes:
if wt.LookupParameter("Type Name").AsString() == afwerkingsnaam:
return wt.Id
def wand_eigenschappen_set(wall):
# hoogte van afwerking setten aan hoogte kamer
height_param = wall.get_Parameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM)
height_param.Set(room_height)
# room bounding van afwerking afzetten
room_bounding_param = wall.get_Parameter(BuiltInParameter.WALL_ATTR_ROOM_BOUNDING)
room_bounding_param.Set(False)
# Main
# ===================================================
rooms = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Rooms).ToElements()
wandtypes = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsElementType().ToElements()
wallfinish = input()
wall_finish_input = forms.ask_for_string()
wall_finish_input = "Pleister" # weg te nemen wanneer script klaar is voor variablen
curve_list = [] # ListCurve
t = Transaction(doc,"create wallfinishing")
t.Start()
# Loop door de kamers
for room in rooms:
# Controleren of de oppervlakte niet gelijk is aan 0
if room.Area != 0:
# Wall Finish opvragen + controle
wall_finish_rooms_value = room.LookupParameter("Wall Finish").AsString()
if wall_finish_rooms_value == wall_finish_input:
# Krijg naam van Base & Upper Limit
room_height = room.UnboundedHeight
room_base = room.Level.Name
# Room calculation settings
settings = AreaVolumeSettings.GetAreaVolumeSettings(doc)
b_option = settings.GetSpatialElementBoundaryLocation(SpatialElementType.Room).Finish
options = SpatialElementBoundaryOptions()
options.SpatialElementBoundaryLocation = b_option
# WallLoop
for boundlist in room.GetBoundarySegments(options):
for index, bound in enumerate(boundlist):
wall = doc.GetElement(bound.ElementId)
if wall is None:
try:
index_bound = index - 1
bound = boundlist[index_bound]
except IndexError:
index_bound = index + 1
bound = boundlist[index_bound]
room_boundrys_elements = bound.ElementId
wall = doc.GetElement(bound.ElementId)
# lijst van eigenschappen
curve = bound.GetCurve()
curve_list.Add(curve)
type_afwerkingId = afwerkingstype_mapping(wall,wandtypes)
# wall maken
try:
afwerkings_muur = Wall.Create(doc,curve_list, type_afwerkingId ,room.LevelId,False)
except Exception as e:
# Handle the exception here
print("An error occurred while creating the wall:", e)
# wand_eigenschappen_set(afwerkings_muur)
t.Commit()
Hi @mathanvd ,
I suppose the issues are related to how you pick the walls.
mathanvd:
for index, bound in enumerate(boundlist):
wall = doc.GetElement(bound.ElementId)
if wall is None:
try:
index_bound = index - 1
bound = boundlist[index_bound]
except IndexError:
index_bound = index + 1
bound = boundlist[index_bound]
room_boundrys_elements = bound.ElementId
wall = doc.GetElement(bound.ElementId)
With this code you risk to use the same wall twice, since you’re retrieving the one before or after the current bound if it’s none.
I suppose you can just skip the bound.
A style tip: you can reduce the code indentation by inverting the if condition and use continue
to go to the next item of a loop:
for room in rooms:
if room.Area == 0:
continue
wall_finish_rooms_value = room.LookupParameter("Wall Finish").AsString()
if wall_finish_rooms_value != wall_finish_input:
continue
# ...
for boundlist in room.GetBoundarySegments(options):
for index, bound in enumerate(boundlist):
wall = doc.GetElement(bound.ElementId)
if wall is None:
continue
room_boundrys_elements = bound.ElementId
# ...
1 Like
mathanvd
(Mathan Van Driessche)
April 2, 2024, 8:48am
4
Sorry for the late reply, I will explain my code a litle bit:
I would like to have wall finishes generated based on the room boundaries. Only the rooms that have a certain value in ‘Wall Finish’ (to be entered by the user in the window) may be used.
The walls must also have the correct height (‘Base Level’ from room = ‘Base Constraint’ wall, ‘Upper Limit’ from room = ‘Top Constraint’ wall).
In addition, the parameter ‘Muurafwerkingstype’ must be completed in the diviging walls. This way you can generate different wall finishing types for other walls at the same time (mapping). Sometimes I want a different finish for some walls.
Hopefully it’s clear now? I’m a beginner in Python, so any help is appreciated.
Thanks in advance!
mathanvd
(Mathan Van Driessche)
April 2, 2024, 9:00am
5
Thanks for the tip! I’ll try the Continue function.
I used that part of my script to ignore boundrys like on the picture. When I look to that boundry the ElementId is “-1”, you can see it on the other picture. Do you have a better alternative for this problem?
Thanks in advance!
Hi, thanks for the info, now I understand the problem better.
In your loop you didn’t “ignore” the boundary with the invalid elementid, you just exchanged it with the element before or after. But these elements are already taken care by their respective cycles, so you take the same element twice.
The continue statement (it is not a function, FYI ) just ignore it and moves to the next item in the list.
Anyway, I think I found your problem: you’re initiaziling the curve_list
outside or all the loops, so the list passed to the Wall.Create
method contains all the segments extracted so far!
You need to create the list just before the curve_list.Add(curve)
in order to only have the correct segment to draw the wall on.
1 Like