Autodesk / revit-ifc

IFC for Revit and Navisworks (2019+)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

INQ: IFCopenshell - Revit

avinash-218 opened this issue · comments

Inquiry description

... I create a wall in ifcopenshell in the IFC schema IFC2X3. When i open the ifc file in revit, it is identified as wall but it is not being identified as native revit family wall.

import ifcopenshell
from ifcopenshell.api import run
import ifcopenshell.util.element

# Create a blank model
model = ifcopenshell.file(schema="IFC2X3")

# Create a user and application directly using ifcopenshell
person = model.create_entity("IfcPerson", FamilyName="Doe", GivenName="John")
organization = model.create_entity("IfcOrganization", Name="My Organization")
person_and_organization = model.create_entity("IfcPersonAndOrganization", ThePerson=person, TheOrganization=organization)
application = model.create_entity("IfcApplication", ApplicationDeveloper=organization, Version="1.0", ApplicationFullName="My Application", ApplicationIdentifier="APP-001")
owner_history = model.create_entity("IfcOwnerHistory", OwningUser=person, OwningApplication=application, ChangeAction="ADDED")

# Create IFC Project element
project = model.create_entity("IfcProject", Name="My Project")
project.OwnerHistory = owner_history

# units - mm and square meters
length = ifcopenshell.api.run("unit.add_si_unit", model, unit_type="LENGTHUNIT", prefix="MILLI")
area = ifcopenshell.api.run("unit.add_si_unit", model, unit_type="AREAUNIT")

# assign default unit
ifcopenshell.api.run("unit.assign_unit", model, units=[length, area])

# create modeling geometry context to store 3D geometry
context = run("context.add_context", model, context_type="Model")
body = run("context.add_context", model, context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent=context)

# Create site, building, storey
site = model.create_entity("IfcSite", Name="My Site")
site.OwnerHistory = owner_history

building = model.create_entity("IfcBuilding", Name="Building A")
building.OwnerHistory = owner_history

storey = model.create_entity("IfcBuildingStorey", Name="Ground Floor")
storey.OwnerHistory = owner_history

# Create modeling geometry context to store 3D geometry
context = run("context.add_context", model, context_type="Model")
body = run("context.add_context", model, context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent=context)

# Create site, building, storey
site = model.create_entity("IfcSite", Name="My Site", OwnerHistory=owner_history)
building = model.create_entity("IfcBuilding", Name="Building A", OwnerHistory=owner_history)
storey = model.create_entity("IfcBuildingStorey", Name="Ground Floor", OwnerHistory=owner_history)

# Assign spatial structure using IfcRelAggregates
model.create_entity("IfcRelAggregates", OwnerHistory=owner_history, RelatingObject=project, RelatedObjects=[site])
model.create_entity("IfcRelAggregates", OwnerHistory=owner_history, RelatingObject=site, RelatedObjects=[building])
model.create_entity("IfcRelAggregates", OwnerHistory=owner_history, RelatingObject=building, RelatedObjects=[storey])

# Create a new wall
wall = model.create_entity("IfcWallStandardCase", OwnerHistory=owner_history)
wall.Name = "Basic Wall:Wall-Ext_102Bwk-75Ins-100LBlk-12P:323443"
wall.GlobalId = "123456789"
wall.ObjectType = "Basic Wall:Wall-Ext_102Bwk-75Ins-100LBlk-12P"
wall.Tag = "323443"

print(wall.get_info())
# print(dir(wall))

pset = ifcopenshell.api.run("pset.add_pset", model, product=wall, name="Pset_WallCommon")
prop = {"Reference": "Wall-Ext_102Bwk-75Ins-100LBlk-12P", "IsExternal": True, "ExtendToStructure": False,"LoadBearing":False}
ifcopenshell.api.run("pset.edit_pset", model, pset=pset, properties=prop)

pset = ifcopenshell.api.run("pset.add_pset", model, product=wall, name="Pset_ReinforcementBarPitchOfWall")
prop = {"Reference": "Wall-Ext_102Bwk-75Ins-100LBlk-12P"}
ifcopenshell.api.run("pset.edit_pset", model, pset=pset, properties=prop)

pset = ifcopenshell.api.run("pset.add_pset", model, product=wall, name="Pset_QuantityTakeOff")
prop = {"Reference": "Wall-Ext_102Bwk-75Ins-100LBlk-12P"}
ifcopenshell.api.run("pset.edit_pset", model, pset=pset, properties=prop)

# Add a new wall-like body geometry, 5000mm long, 3000 meters high, and 200mm thick
representation = run("geometry.add_wall_representation", model, context=body, length=5, height=8, thickness=0.29)

# Assign our new body geometry back to our wall
run("geometry.assign_representation", model, product=wall, representation=representation)

# Place our wall in the ground floor
run("spatial.assign_container", model, relating_structure=storey, products=[wall])

# Save the IFC model to a file
model.write('ifc2x3_wall.ifc')

Here is the script to create an ifc file with wall.

But when i import an IFC file that is created from revit, the wall is identified as revit native family. Can anyone please help?

Revit Version

2024.0.x

IFC for Revit Addon Version

24.x.x

Windows Version

11 22H2

There's no material layer set associated with it. Also, what is the representation created for the wall? Is it a simple vertical extrusion? These are the things that would increase the chances of it importing as native.

@AngelVelezSosa

Thanks. You are a life saver. Revit can identify the wall after adding the material.
But the wall is thin as a plane, any idea why is this happening??

Also, yes the wall is a simple vertical extrusion

Below is the updated script

import ifcopenshell
from ifcopenshell.api import run
import ifcopenshell.util.element

# Create a blank model
model = ifcopenshell.file(schema="IFC2X3")

# Create a user and application directly using ifcopenshell
person = model.create_entity("IfcPerson", FamilyName="Doe", GivenName="John")
organization = model.create_entity("IfcOrganization", Name="My Organization")
person_and_organization = model.create_entity("IfcPersonAndOrganization", ThePerson=person, TheOrganization=organization)
application = model.create_entity("IfcApplication", ApplicationDeveloper=organization, Version="1.0", ApplicationFullName="My Application", ApplicationIdentifier="APP-001")
owner_history = model.create_entity("IfcOwnerHistory", OwningUser=person, OwningApplication=application, ChangeAction="ADDED")

# Create IFC Project element
project = model.create_entity("IfcProject", Name="My Project")
project.OwnerHistory = owner_history

# units - mm and square meters
length = ifcopenshell.api.run("unit.add_si_unit", model, unit_type="LENGTHUNIT", prefix="MILLI")
area = ifcopenshell.api.run("unit.add_si_unit", model, unit_type="AREAUNIT")

# assign default unit
ifcopenshell.api.run("unit.assign_unit", model, units=[length, area])

# create modeling geometry context to store 3D geometry
context = run("context.add_context", model, context_type="Model")
body = run("context.add_context", model, context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent=context)

# Create site, building, storey
site = model.create_entity("IfcSite", Name="My Site")
site.OwnerHistory = owner_history

building = model.create_entity("IfcBuilding", Name="Building A")
building.OwnerHistory = owner_history

storey = model.create_entity("IfcBuildingStorey", Name="Ground Floor")
storey.OwnerHistory = owner_history

# Create modeling geometry context to store 3D geometry
context = run("context.add_context", model, context_type="Model")
body = run("context.add_context", model, context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent=context)

# Create site, building, storey
site = model.create_entity("IfcSite", Name="My Site", OwnerHistory=owner_history)
building = model.create_entity("IfcBuilding", Name="Building A", OwnerHistory=owner_history)
storey = model.create_entity("IfcBuildingStorey", Name="Ground Floor", OwnerHistory=owner_history)

# Assign spatial structure using IfcRelAggregates
model.create_entity("IfcRelAggregates", OwnerHistory=owner_history, RelatingObject=project, RelatedObjects=[site])
model.create_entity("IfcRelAggregates", OwnerHistory=owner_history, RelatingObject=site, RelatedObjects=[building])
model.create_entity("IfcRelAggregates", OwnerHistory=owner_history, RelatingObject=building, RelatedObjects=[storey])

# Create a new wall
wall = model.create_entity("IfcWallStandardCase", OwnerHistory=owner_history)
wall.Name = "Basic Wall:Wall-Ext_102Bwk-75Ins-100LBlk-12P:323443"
wall.GlobalId = "123456789"
wall.ObjectType = "Basic Wall:Wall-Ext_102Bwk-75Ins-100LBlk-12P"
wall.Tag = "323434"

print(wall.get_info())
# print(dir(wall))

pset = ifcopenshell.api.run("pset.add_pset", model, product=wall, name="Pset_WallCommon")
prop = {"Reference": "Wall-Ext_102Bwk-75Ins-100LBlk-12P", "IsExternal": True, "ExtendToStructure": False,"LoadBearing":False}
ifcopenshell.api.run("pset.edit_pset", model, pset=pset, properties=prop)

pset = ifcopenshell.api.run("pset.add_pset", model, product=wall, name="Pset_ReinforcementBarPitchOfWall")
prop = {"Reference": "Wall-Ext_102Bwk-75Ins-100LBlk-12P"}
ifcopenshell.api.run("pset.edit_pset", model, pset=pset, properties=prop)

pset = ifcopenshell.api.run("pset.add_pset", model, product=wall, name="Pset_QuantityTakeOff")
prop = {"Reference": "Wall-Ext_102Bwk-75Ins-100LBlk-12P"}
ifcopenshell.api.run("pset.edit_pset", model, pset=pset, properties=prop)


# Define material layers
material = model.create_entity("IfcMaterial", Name="Brick")
material_layer = model.create_entity("IfcMaterialLayer", Material=material, LayerThickness=0.29)
material_layer_set = model.create_entity("IfcMaterialLayerSet", MaterialLayers=[material_layer], LayerSetName="Basic Wall Layers")
material_layer_set_usage = model.create_entity("IfcMaterialLayerSetUsage", ForLayerSet=material_layer_set, LayerSetDirection="AXIS2", DirectionSense="POSITIVE", OffsetFromReferenceLine=0.0)

# Create the relationship between the wall and its material layer set usage
model.create_entity("IfcRelAssociatesMaterial", GlobalId=ifcopenshell.guid.new(), OwnerHistory=owner_history, RelatedObjects=[wall], RelatingMaterial=material_layer_set_usage)

# Add a new wall-like body geometry, 5000mm long, 3000 meters high, and 200mm thick
representation = run("geometry.add_wall_representation", model, context=body, length=5, height=8, thickness=5)

# Assign our new body geometry back to our wall
run("geometry.assign_representation", model, product=wall, representation=representation)

# Place our wall in the ground floor
run("spatial.assign_container", model, relating_structure=storey, products=[wall])

# Save the IFC model to a file
model.write('ifc2x3_wall.ifc')

Also is there any resource that behaves as a mapper so that all IFC objects are linked to Revit native family??

LayerThickness=0.29 ==> if there is a discrepancy between the geometry and the material layer set description (which there is), it will take the parametric representation over the geometric one.

And alas, no. It isn't trivial to make everything work...

Material layer thickness and geometry is made same. It still did not fix the issue.

Actually, as i said Revit can identify the wall as the native revit family type but the wall is thin as a plane. But the wall when viewed in two ifc viewers, looks like a wall rather than thin plane.

Surprisingly, when i export a wall in an ifc file from revit (IFC4) and open the file back in revit, revit identifies it as native wall family but it is thin as a plane.

is this a bug ??

I doubt it is a bug. If you go to the wall, click on the type, and look at the wall structure, what is the thickness of the material layer?

Original thickness:
image

Thickness of the same wall when opened as IFC file
image

Figured out. it is because i did not export the material layer as well, so only the structure is being exported which is why it looked thin. When exporting along with materials, the walls looked as expected.

this fixed


# Define material layers
material = model.create_entity("IfcMaterial", Name="Brick")
material_layer = model.create_entity("IfcMaterialLayer", Material=material, LayerThickness=290)
material_layer_set = model.create_entity("IfcMaterialLayerSet", MaterialLayers=[material_layer], LayerSetName="Basic Wall Layers")
material_layer_set_usage = model.create_entity("IfcMaterialLayerSetUsage", ForLayerSet=material_layer_set, LayerSetDirection="AXIS2", DirectionSense="POSITIVE", OffsetFromReferenceLine=0.0)

# Create the relationship between the wall and its material layer set usage
model.create_entity("IfcRelAssociatesMaterial", GlobalId=ifcopenshell.guid.new(), OwnerHistory=owner_history, RelatedObjects=[wall], RelatingMaterial=material_layer_set_usage)

# Add a new wall-like body geometry, 5000mm long, 3000 meters high, and 200mm thick
representation = run("geometry.add_wall_representation", model, context=body, length=5, height=8, thickness=0.2)```

the issue with thickness was due to the confusion of the input units scale in the below statements
1) material_layer = model.create_entity("IfcMaterialLayer", Material=material, LayerThickness=290)
2) representation = run("geometry.add_wall_representation", model, context=body, length=5, height=8, thickness=0.2)```

in my case statement 1 considers 290mm (milli-metre)while statement 2 considers 0.2m (metre). 


Thank you so much @AngelVelezSosa