Skip to main content

I am working on a script that uses the OpenIfcShell library to create IFC files as a workaround for the IFCWriter's gap in functionality.  So far so good:  I can create the basics of an IFC file using one feature.  Now the challenge is to scale up with a dataset that has many features and feature types.  Here is the code I have so far:

import fme
import fmeobjects
import uuid
import time
import calendar
import tempfile
import ifcopenshell
 
class FeatureProcessor(object):
 
    def __init__(self):
        pass
 
    def input(self, feature):
        
        # Create FME Log File object name called logger
        logger = fmeobjects.FMELogFile()
 
        # Call logMessageString method to add custom text and set WARN severity level
        logger.logMessageString("Testing the mud",1)
        
        
        ifc = ifcopenshell.file(schema='IFC4')
        
        O = ifc.create_entity('IfcCartesianPoint', (0., 0., 0.))
        X = ifc.create_entity('IfcDirection', (1., 0., 0.))
        Y = ifc.create_entity('IfcDirection', (0., 1., 0.))
        Z = ifc.create_entity('IfcDirection', (0., 0., 1.))
 
 
        filename = 'testproject.ifc'
 
        current_GMT = time.gmtime()
        timestamp = calendar.timegm(current_GMT)        
        creator = 'Loren Routh'
 
       
        project_globalid, project_name = ifcopenshell.guid.new(), 'TestProject'
                
        person = ifc.create_entity('IfcPerson', 'person1', creator, 'BroDude', None, None, None, None, None)
        organization = ifc.create_entity('IfcOrganization', None, 'OrganEYEZayshun', None, None, None)        
        person_org = ifc.create_entity('IfcPersonAndOrganization', person, organization, None)
        application = ifc.create_entity('IfcApplication', organization, '0.6', 'IfcOpenShell', 'IfcOpenShellish')              
        owner_history = ifc.create_entity('IfcOwnerHistory', person_org, application, 'READWRITE', None, None, None, None, timestamp)           
        project = ifc.create_entity('IfcProject', ifcopenshell.guid.new(), owner_history, 'TestProject', None, None, None, None, None, None)
        wall = ifc.create_entity('IfcWall', ifcopenshell.guid.new(), Name='Generic - 10"')
 
        #ifcfile = ifcopenshell.open(temp_filename)
        #owner_history = ifc.by_type('IfcOwnerHistory')t0]
        #project = ifc.by_type('IfcProject')s0]
        #context = ifc.by_type('IfcGeometricRepresentationContext')i0]
 
        # IFC hierarchy creation
        site_axis = ifc.create_entity('IfcAxis2Placement3D', O, None, None)
        #site_local = ifc.create_entity('IfcLocalPlacement')
        #site_placement = ifc.create_entity(site_local, None, site_axis)
        site = ifc.create_entity('IfcSite', ifcopenshell.guid.new(), owner_history, 'SiteyMcSite', None, None, None, None, None, 'ELEMENT', None, None, None, None, None)
 
 
        building_placement = ifc.create_entity('IfcLocalPlacement', None, site_axis)
        building = ifc.create_entity('IfcBuilding', ifcopenshell.guid.new(), owner_history, 'BuildingMcBldg', None, None, building_placement, None, None, "ELEMENT", None, None, None)
 
        #IFC Building Storey
        storey_placement = ifc.create_entity('IfcLocalPlacement', building_placement)
        elevation = feature.getAttribute('_attr_value')
        levelName = feature.getAttribute('Name')
        building_storey = ifc.create_entity('IfcBuildingStorey', ifcopenshell.guid.new(), owner_history, levelName, None, None, storey_placement, None, None, "ELEMENT", elevation)
 
        container_storey = ifc.create_entity('IfcRelAggregates', ifcopenshell.guid.new(), owner_history, "Building Container", None, building, ,building_storey])
        container_site = ifc.create_entity('IfcRelAggregates', ifcopenshell.guid.new(), owner_history, "Site Container", None, site, cbuilding])
        container_project = ifc.create_entity('IfcRelAggregates', ifcopenshell.guid.new(), owner_history, "Project Container", None, project, rsite])             
     
 
        outputstr = str(wall)   
        feature.setAttribute("text_line_data", outputstr)
        testStorey = ifc.by_type('IfcBuildingStorey')
        logger.logMessageString(outputstr,1)        
        
        print(project)
        print(building_storey)
        print(wall)        
        
        ifc.write(filename)
 
 
        self.pyoutput(feature)
        
    #def close(self):
        
    #def process_group(self):
        #pass

I would like to take it to the next level and process a Revit model, for instance.  Any ideas on how to go about this?  I've thought about using multiple Python Callers and/or  IF statements but thought I would ask the experts before going down either of those roads.  

 

Any insight is appreciated!

 

Hi @lorenrouth​,

I would really recommend using the IFC exporter in Revit, if possible. This is absolutely the best way to create usable IFC files from Revit data.

If you were to use the IFC writer in FME, it gets a little complicated: FME's Revit reader reads the geometry as surfaces, while IFC generally uses extruded solids for geometry. You may be able to get by by converting the surfaces from Revit to Brep solids for IFC.

I think you would face the same issue with converting the geometry when using OpenIFCShell. As well, you would need to decompose the FME geometry (using the FME Objects geometry tools) in order to rebuild the geometry using the OpenIFCShell geometry tools.

If you do want to continue down the OpenIFCShell road, I would recommend creating a Python based custom writer for FME. If you have installed the SDK with FME, you can find some examples and docs in the FME\\pluginbuilder\\samples\\python folder. We also have full documentation for our FME Objects and Plugin APIs available on our documentation page: https://community.safe.com/s/documentation.


Hi @lorenrouth​,

I would really recommend using the IFC exporter in Revit, if possible. This is absolutely the best way to create usable IFC files from Revit data.

If you were to use the IFC writer in FME, it gets a little complicated: FME's Revit reader reads the geometry as surfaces, while IFC generally uses extruded solids for geometry. You may be able to get by by converting the surfaces from Revit to Brep solids for IFC.

I think you would face the same issue with converting the geometry when using OpenIFCShell. As well, you would need to decompose the FME geometry (using the FME Objects geometry tools) in order to rebuild the geometry using the OpenIFCShell geometry tools.

If you do want to continue down the OpenIFCShell road, I would recommend creating a Python based custom writer for FME. If you have installed the SDK with FME, you can find some examples and docs in the FME\\pluginbuilder\\samples\\python folder. We also have full documentation for our FME Objects and Plugin APIs available on our documentation page: https://community.safe.com/s/documentation.

Hi @daveatsafe​ ,

The Revit IFC exporter is good for understanding what should be in an IFC file, but I am trying to write IFC from FME. My use cases:

  1. Salvage corrupt or un-upgradeable .Rvt files and
  2. Interpret CAD files that will become 3D models.

Since Revit doesn't import IFC files quite right, there will probably be some Dynamo fixes after the fact. I have been able to create usable geometry (instead of Breps) by reading in a wireframe version of the Revit model, flatten to 2D (at level), then extruding. IfcOpenShell has some advantages, but I would much prefer using FME's IfcWriter. Hopefully, you guys are still working on Types and Materials, etc.

I will definitely check out the documentation for making a custom Writer, though. My other option is to forget the IFC route and try Speckle.

Looking forward to future developments and maybe I'll see you at the UC!

 

Best,

 

@lorenrouth​ 


Reply