Couldn't create wall (finish)

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.

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

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!

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!


image

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 :wink: ) 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