ifcopenshell i python

Dodaj właściwości do IFC używając ifcOpenShell

Często zdarza się, że plik IFC po eksporcie zawiera niezamierzone błędy, takie jak brak atrybutów na obiektach, nieodpowiednia liczba właściwości czy brak wyeksportowanych wartości. W takich przypadkach zazwyczaj musimy otworzyć model w natywnym oprogramowaniu, aby wprowadzić poprawki.

Istnieją również programy umożliwiające edycję danych zawartych w pliku IFC, jednak większość z nich jest płatna.

W tym artykule chciałbym przedstawić darmową metodę, która pozwala na manipulację plikami IFC.

Będzie to pierwszy wpis z serii poświęconej tematyce analizy oraz edycji plików IFC.

Jaka to metoda?

Zapraszam do lektury.

Jeśli interesuje Cię temat IFC 4.3, nie zapomnij sprawdzić innych artykułów poświęconych temu tematowi na naszym blogu.

ifcOpenShell

Bohaterem tego artykułu jest IfcOpenShell – otwarto źródłowa biblioteka stworzona do pracy z plikami IFC (Industry Foundation Classes), które są standardem wymiany danych w branży architektonicznej i budowlanej.

IfcOpenShell pozwala na przeglądanie, edytowanie i analizowanie informacji zawartych w plikach IFC, bez konieczności korzystania z komercyjnego oprogramowania. Dzięki tej bibliotece możesz manipulować strukturą modelu, dodawać lub usuwać atrybuty, a nawet tworzyć nowe pliki IFC. IfcOpenShell działa w języku programowania Python, więc podstawowa znajomość tego języka jest konieczna do efektywnego korzystania z narzędzia.

Więcej na temat IfcOpenShell znajdziesz tutaj: LINK

Rozumiem jednak, że nauka Pythona może wydawać się wyzwaniem, dlatego poniżej znajdziesz prosty kod, który możesz po prostu wkleić do swojego środowiska programistycznego.

Podzieliłem go na poszczególne części, aby krok po kroku wyjaśnić, co robi każdy fragment.

Google Colab

Zanim jednak przejdziemy do omawianego przykładu, chciałbym przedstawić narzędzie, z którego będę korzystał – Google Colab. Wybrałem to środowisko programistyczne z prostego powodu: umożliwia łatwy dostęp, jest darmowe, nie wymaga instalacji żadnego oprogramowania na komputerze, działa w chmurze i umożliwia pisanie oraz uruchamianie kodu Python bezpośrednio w przeglądarce. To idealne rozwiązanie dla tych, którzy nie chcą lub nie mogą instalować Pythona lokalnie.

Dodatkowo, Google Colab ułatwia współpracę – możesz łatwo udostępniać swoje notatniki innym osobom, tak jak w przypadku dokumentów Google Docs. Dzięki temu możesz wspólnie pracować nad kodem w czasie rzeczywistym, co czyni Colab świetnym narzędziem zarówno do nauki, jak i realizacji projektów w zespole.

Więcej o Google Colab znajdziesz tutaj: LINK

Dodawanie właściwości do modelu IFC przy użyciu IfcOpenShell

Często występują sytuacje, gdy plik IFC nie zawiera wszystkich wymaganych właściwości lub nie mamy dostępu do oryginalnych plików, co może stwarzać trudności.

Ręczna edycja pliku IFC poprzez modyfikację kodu STEP w edytorze tekstu jest pracochłonna i obciążona ryzykiem błędów.

Zdecydowanie prostszym rozwiązaniem jest wykorzystanie Ifcopenshell. W dalszej części artykułu pokażę, jak w prosty sposób dodać właściwości do modelu mostu przy użyciu tego narzędzia.

Więcej na temat właściwości w IFC znajdziesz w tym artykule: LINK

Zaczynamy!

Aby rozpocząć pracę, zaloguj się na stronie Google Colab i stwórz nowy notatnik. Następnie załaduj plik, który chcesz edytować klikając ikonę umożliwiającą przesłanie pliku na serwer.

Uwaga: Pliki przesyłane do sesji Colab są usuwane po jej zamknięciu. Aby kontynuować pracę z plikiem w przyszłości, będziesz musiał ponownie przesłać go na serwer.

Gdy plik będzie już dostępny w sesji, dodaj linię kodu w notatniku.

Skopiuj i wklej kod, który znajdziesz poniżej.

Twój kod jest już gotowy do użycia!

Uwaga: Przykład oparty jest na moim konkretnym scenariuszu. Aby dostosować go do własnych potrzeb, dokładnie przeanalizuj kod i sprawdź, jakie zmienne możesz zmienić zgodnie z wymaganiami Twojego projektu

Kod gotowy do użycia

				
					# Instalacja ifcopenshell 
!pip install ifcopenshell

# Importowanie niezbędnych bibliotek
import ifcopenshell
import ifcopenshell.util.element

# Ładowanie pliku IFC
ifc_file = ifcopenshell.open('Bridge 1.ifc')

# Wyszukiwanie obiektów docelowych
bridge_parts = ifc_file.by_type('IfcBridgePart')

# Tworzenie nowej wartości właściwości MMI
property_single_value_mmi = ifc_file.create_entity(
    "IfcPropertySingleValue",
    "MMI",
    None,  # Opis jest opcjonalny
    ifc_file.create_entity("IfcLabel", "300"),  # Wartość nominalna
    None  # Jednostka jest opcjonalna
)

# Tworzenie nowej wartości właściwości Status
property_single_value_status = ifc_file.create_entity(
    "IfcPropertySingleValue",
    "Status",
    None,  # Opis jest opcjonalny
    ifc_file.create_entity("IfcText", "InProgress"),  # Wartość nominalna
    None  # Jednostka jest opcjonalna
)

# Tworzenie nowego zestawu właściwości
property_set = ifc_file.create_entity(
    "IfcPropertySet",
    ifcopenshell.guid.new(),
    ifc_file.by_type("IfcOwnerHistory")[0],
    "BIMCorner",
    None,  # Opis jest opcjonalny
    [property_single_value_mmi, property_single_value_status]
)

# Iteracja przez obiekty i dodanie zestawu właściwości
for bridge_part in bridge_parts:
    rel_defines = ifc_file.create_entity(
        "IfcRelDefinesByProperties",
        ifcopenshell.guid.new(),
        ifc_file.by_type("IfcOwnerHistory")[0],
        None,  # Opis jest opcjonalny
        None,  # Opis jest opcjonalny
        [bridge_part],  # Powiązane obiekty
        property_set  # Powiązane definicje właściwości
    )

# Zapisanie zmodyfikowanego pliku IFC
ifc_file.write('Modified_Bridge.ifc')


				
			

Objaśnienie kodu

1. Instalowanie biblioteki ifcopenshell

				
					!pip install ifcopenshell
				
			
  • Co robisz: Instalujesz bibliotekę ifcopenshell.
  • Dlaczego tak: ifcopenshell umożliwia manipulację danymi w plikach IFC, które są standardem wymiany danych w branży budowlanej.
  • O czym warto pamiętać: Upewnij się, że masz zainstalowaną bibliotekę pip w swoim środowisku. Możesz to zrobić za pomocą pip install pip.
  • Częste błędy: Brak uprawnień do instalacji pakietów, brak zainstalowanej biblioteki pip.

2. Importowanie niezbędnych bibliotek:

				
					import ifcopenshell
import ifcopenshell.util.element
				
			
  • Co robisz: Importujesz biblioteki ifcopenshell oraz ifcopenshell.util.element.
  • Dlaczego tak: Te biblioteki są niezbędne do manipulacji danymi w plikach IFC.
  • O czym warto pamiętać: Upewnij się, że biblioteki są poprawnie zainstalowane przed ich importem.
  • Częste błędy: Niezainstalowane biblioteki, literówki w nazwach bibliotek.

3. Ładowanie pliku IFC:

				
					ifc_file = ifcopenshell.open('Bridge 1.ifc')
				
			
  • Co robisz: Ładujesz plik IFC do zmiennej ifc_file.
  • Dlaczego tak: Aby móc manipulować danymi w pliku IFC, musisz go najpierw załadować.
  • O czym warto pamiętać: Ścieżka  do pliku musi być poprawna. Upewnij się, że plik istnieje w podanej lokalizacji.
  • Częste błędy: Błędna ścieżka do pliku, brak pliku w podanej lokalizacji.

4. Wyszukiwanie obiektów docelowych na podstawie typu:

  • Znajdowanie jednostek IfcBridgePart
				
					bridge_parts = ifc_file.by_type('IfcBridgePart')
				
			
  • Co robisz: Wyszukujesz obiekty typu IfcBridgePart w załadowanym pliku IFC.
  • Dlaczego tak: Aby dodać właściwości do konkretnych obiektów, musisz je najpierw znaleźć.
  • O czym warto pamiętać: Sprawdź, czy obiekty tego typu istnieją w pliku IFC.
  • Częste błędy: Brak obiektów danego typu w pliku, literówki w nazwie typu obiektu.

4.1. Wyszukiwanie różnych obiektów docelowych

  • Znajdowanie jednostek IfcWall:
				
					walls = ifc_file.by_type('IfcWall')
				
			
  • Znajdowanie jednostek IfcColumn:
				
					columns = ifc_file.by_type('IfcColumn')
				
			
  • Znajdowanie jednostek IfcBeam
				
					beams = ifc_file.by_type('IfcBeam')
				
			
  • Znajdowanie jednostek IfcSlab
				
					slabs = ifc_file.by_type('IfcSlab')
				
			
  • Znajdowanie jednostek IfcDoor
				
					doors = ifc_file.by_type('IfcDoor')
				
			

4.2. Wyszukiwanie innych obiektów docelowych, posiadających atrubut 'PredefinedType' o wartości 'USERDEFEINED'

Poniżej znajdziesz przykład kodu, który umożliwia znalezienie obiektu na podstawie konkretnego atrybutu.

				
					attribute_target_objects = []
for entity in ifc_file:
    if hasattr(entity, 'PredefinedType') and entity.PredefinedType == 'USERDEFINED':
        attribute_target_objects.append(entity)
				
			

4.3. Wyszukiwanie obiektów docelowych, posiadających właściwość 'IfcPropertySingleValue' 'Domain' o wartości 'Bridge'

Poniżej znajdziesz przykład kodu, który umożliwia znalezienie obiektu na podstawie konkretnej właściwości oraz określonej wartości 

				
					property_target_objects = []
for entity in ifc_file:
    # Sprawdzamy, czy obiekt ma przypisane zestawy właściwości
    if hasattr(entity, 'IsDefinedBy'):
        for rel in entity.IsDefinedBy:
            if rel.is_a('IfcRelDefinesByProperties'):
                property_set = rel.RelatingPropertyDefinition
                if property_set.is_a('IfcPropertySet'):
                    for prop in property_set.HasProperties:
                        if prop.is_a('IfcPropertySingleValue') and prop.Name == 'Domain' and prop.NominalValue.wrappedValue == 'Bridge':
                            property_target_objects.append(entity)
                            break
				
			

***W kodzie Python, funkcja hasattr() jest używana do sprawdzenia, czy określony obiekt ma atrybut o danej nazwie. Jest to przydatne, gdy nie jesteśmy pewni, czy dany obiekt posiada określony atrybut, i chcemy uniknąć potencjalnych błędów wynikających z próby dostępu do nieistniejącego atrybutu.

5. Tworzenie nowych wartości właściwości

				
					# Tworzenie nowej wartości właściwości MMI
property_single_value_mmi = ifc_file.create_entity(
    "IfcPropertySingleValue",
    "MMI",
    None,  # Opis jest opcjonalny
    ifc_file.create_entity("IfcLabel", "300"),  # Wartość nominalna
    None  # Jednostka jest opcjonalna
)

# Tworzenie nowej wartości właściwości Status
property_single_value_status = ifc_file.create_entity(
    "IfcPropertySingleValue",
    "Status",
    None,  # Opis jest opcjonalny
    ifc_file.create_entity("IfcText", "InProgress"),  # Wartość nominalna
    None  # Jednostka jest opcjonalna
				
			
  • Co robisz: Tworzysz nową wartość właściwości IfcPropertySingleValue.
  • Dlaczego tak: Aby dodać konkretne właściwości do zestawu właściwości.
  • O czym warto pamiętać: Upewnij się, że typ i wartość właściwości są poprawne.
  • Częste błędy: Błędne typy danych, brak wymaganych parametrów.

6. Tworzenie nowego zestawu właściwości:

  • Co robisz: Tworzysz nowy zestaw właściwości IfcPropertySet.
  • Dlaczego tak: Aby grupować właściwości i przypisywać je do obiektów.
  • O czym warto pamiętać: Upewnij się, że zestaw właściwości ma unikalny identyfikator GUID.
  • Częste błędy: Duplikaty GUID, brak wymaganych parametrów.
				
					property_set = ifc_file.create_entity(
    "IfcPropertySet",
    ifcopenshell.guid.new(),
    ifc_file.by_type("IfcOwnerHistory")[0],
    "BIMCorner",
    None,  # Opis jest opcjonalny
    [property_single_value_mmi, property_single_value_status]
)
				
			

7. Iteracja przez obiekty i dodanie zestawu właściwości:

				
					for bridge_part in bridge_parts:
    rel_defines = ifc_file.create_entity(
        "IfcRelDefinesByProperties",
        ifcopenshell.guid.new(),
        ifc_file.by_type("IfcOwnerHistory")[0],
        None,  # Opis jest opcjonalny
        None,  # Opis jest opcjonalny
        [bridge_part],  # Powiązane obiekty
        property_set  # Powiązane definicje właściwości
    )
				
			
  • Co robisz: Iterujesz przez wszystkie jednostki IfcBridgePart i tworzysz relację IfcRelDefinesByProperties, która wiąże te jednostki z zestawem właściwości.
  • Dlaczego tak: IfcRelDefinesByProperties tworzy relację między obiektami a ich właściwościami, co pozwala na przypisanie zestawu właściwości property_set do każdej części mostu.
  • O czym warto pamiętać: Upewnij się, że każda jednostka IfcBridgePart ma poprawnie przypisaną relację. Możesz dodać dodatkowe opisy, jeśli są potrzebne, aby zwiększyć czytelność.

7.1. Iteracja przez inne typy obiektów (Patrz punkt 4.1)

				
					for element in bridge_parts + walls + columns + beams + slabs + doors:
    rel_defines = ifc_file.create_entity(
        "IfcRelDefinesByProperties",
        ifcopenshell.guid.new(),
        ifc_file.by_type("IfcOwnerHistory")[0],
        None,  # Opis jest opcjonalny
        None,  # Opis jest opcjonalny
        [element],  # Powiązane obiekty
        property_set  # Powiązane definicje właściwości
    )
				
			
  • Co robisz: Iterujesz przez wszystkie jednostki różnych typów (IfcBridgePart, IfcWall, IfcColumn, IfcBeam, IfcSlab, IfcDoor) i tworzysz relację IfcRelDefinesByProperties, która wiąże te jednostki z zestawem właściwości.
  • Dlaczego tak: Umożliwia to przypisanie zestawu właściwości property_set do różnych elementów modelu.
  • O czym warto pamiętać: Upewnij się, że każda jednostka różnych typów ma poprawnie przypisaną relację. Możesz dostosować listę typów obiektów według potrzeb projektu.
    Częste błędy: Niepoprawne iterowanie przez obiekty, błędy w tworzeniu relacji IfcRelDefinesByProperties.

7.2. Iteracja przez obiekty mające atrybut PredefinedType = USERDEFINED (Patrz punkt 4.2)

				
					for attribute_target_object in attribute_target_objects:
    rel_defines = ifc_file.create_entity(
        "IfcRelDefinesByProperties",
        ifcopenshell.guid.new(),
        ifc_file.by_type("IfcOwnerHistory")[0],
        None,  # Opis jest opcjonalny
        None,  # Opis jest opcjonalny
        [attribute_target_object],  # Powiązane obiekty
        property_set  # Powiązane definicje właściwości
    )
				
			

7.3. Iteracja przez obiekty posiadające właściwość 'IfcPropertySingleValue' 'Domain' o wartości 'Bridge' (Patrz punkt 4.3)

				
					for property_target_object in property_target_objects:
    rel_defines = ifc_file.create_entity(
        "IfcRelDefinesByProperties",
        ifcopenshell.guid.new(),
        ifc_file.by_type("IfcOwnerHistory")[0],
        None,  # Opis jest opcjonalny
        None,  # Opis jest opcjonalny
        [property_target_object],  # Powiązane obiekty
        property_set  # Powiązane definicje właściwości
    )
				
			

Podsumowanie

Jak mogłeś zauważyć, korzystanie z Python i ifcopenshell daje nam niesamowite możliwości prostego i efektywnego modyfikowania plików IFC. Ten przykład to jedynie wstęp do olbrzymiego potencjału, jaki kryje się za tymi narzędziami. Co więcej, gdy opanujesz podstawy programowania, otworzą się przed Tobą drzwi do tworzenia własnych, unikalnych aplikacji, które usprawnią Twoją pracę.

W kolejnych artykułach pokażę Ci, jak krok po kroku stworzyć taką aplikację. Mam nadzieję, że ten temat jest dla Ciebie fascynujący i że spotkamy się ponownie, aby wspólnie zgłębiać tajniki programowania w świecie BIM.

Do zobaczenia w kolejnych odsłonach!

Pozdrawiam serdecznie,
Marcin Pszczolka

Spodobał Ci się ten artykuł? Podziel się nim !

Dużo czasu i wysiłku poświęcamy na tworzenie wszystkich naszych artykułów i poradników. Byłoby świetnie, gdybyś poświęcił chwilę na udostępnienie tego wpisu!

Udostępnij:

Komentarze:

Subscribe
Powiadom o
guest
0 Comments
najstarszy
najnowszy
Inline Feedbacks
View all comments

Autor:

Pobierz przewodnik po projektach BIM:

Po przeczytaniu tego poradnika dowiesz się:

  1. Jak BIM jest wykorzystywany przy największych projektach w Norwegii
  2. Jakie były wyzwania dla zespołu projektowego i jak zostały rozwiązane
  3. Jakie były wyzwania na budowie i jakie było nasze podejście do nich

Najnowsze wpisy: