2020-07-14 21:40:23 +02:00
import json
import ifcopenshell
import os
class CA2IFC :
def __init__ ( self , inputFilename , outputFilename ) :
self . inputFilename = inputFilename
self . outputFilename = outputFilename
self . data = None
self . f = None
self . reps = { }
self . origin = None
self . xAxis = None
self . yAxis = None
self . zAxis = None
def convert ( self ) :
# load json file
with open ( self . inputFilename ) as dataFile :
self . data = json . load ( dataFile )
# initiate ifc file
self . f = ifcopenshell . file ( )
# create header
self . create_header ( )
# create global axes
globalAxes = self . create_global_axes ( )
localPlacement = self . f . createIfcLocalPlacement ( None , globalAxes )
# TODO: create units
2020-08-17 17:05:31 +02:00
lengthUnit = self . f . createIfcSIUnit ( None , ' LENGTHUNIT ' , None , ' METRE ' )
unitAssignment = self . f . createIfcUnitAssignment ( ( lengthUnit , ) )
2020-07-14 21:40:23 +02:00
# create owner history
ownerHistory = self . create_owner_history ( )
# create representations and subrepresentations
self . reps = self . create_reference_subrep ( globalAxes )
# create project and model
project = self . f . createIfcProject ( self . guid ( ) , ownerHistory , ' A Project ' , None , None , None , None , ( self . reps [ ' model ' ] , ) , unitAssignment )
model = self . f . createIfcStructuralAnalysisModel ( self . guid ( ) , ownerHistory , self . data [ ' name ' ] , None , None , ' NOTDEFINED ' , globalAxes , None , None , localPlacement )
self . f . createIfcRelDeclares ( self . guid ( ) , ownerHistory , None , None , project , ( model , ) )
# create materials
ifcMaterials = [ None for _ in range ( len ( self . data [ ' db ' ] [ ' materials ' ] ) ) ]
for i , material in enumerate ( self . data [ ' db ' ] [ ' materials ' ] ) :
ifcMaterials [ i ] = self . create_material ( material )
# create profiles
ifcProfiles = [ None for _ in range ( len ( self . data [ ' db ' ] [ ' profiles ' ] ) ) ]
for i , profile in enumerate ( self . data [ ' db ' ] [ ' profiles ' ] ) :
ifcProfiles [ i ] = self . create_profile ( profile )
# create material-profile sets
mpSets = list ( set ( [ el [ ' material ' ] + ' - ' + el [ ' profile ' ] for el in self . data [ ' elements ' ] if el [ ' geometryType ' ] == ' line ' ] ) )
ifcMaterialProfileSets = [ None for _ in range ( len ( mpSets ) ) ]
for i , mpSet in enumerate ( mpSets ) :
materialIndex = [ mat [ ' ifcName ' ] for mat in self . data [ ' db ' ] [ ' materials ' ] ] . index ( mpSet . split ( ' - ' ) [ 0 ] )
profileIndex = [ prof [ ' ifcName ' ] for prof in self . data [ ' db ' ] [ ' profiles ' ] ] . index ( mpSet . split ( ' - ' ) [ 1 ] )
material = ifcMaterials [ materialIndex ]
2020-08-17 17:05:31 +02:00
profile = ifcProfiles [ profileIndex ]
2020-07-14 21:40:23 +02:00
matProf = self . f . createIfcMaterialProfile ( self . data [ ' db ' ] [ ' materials ' ] [ materialIndex ] [ ' name ' ] + ' | ' + self . data [ ' db ' ] [ ' profiles ' ] [ profileIndex ] [ ' profileName ' ] , None , material , profile )
ifcMaterialProfileSets [ i ] = self . f . createIfcMaterialProfileSet ( None , None , ( matProf , ) )
# create structural elements
ifcElements = [ None for _ in range ( len ( self . data [ ' elements ' ] ) ) ]
for i , el in enumerate ( self . data [ ' elements ' ] ) :
# geometry - product definition shape
prodDefShape = self . create_geometry ( el )
if el [ ' geometryType ' ] == ' line ' :
# z axis TODO: group by elements
localZAxis = self . f . createIfcDirection ( tuple ( el [ ' orientation ' ] [ 2 ] ) )
# element
ifcElements [ i ] = self . f . createIfcStructuralCurveMember ( self . guid ( ) , ownerHistory , el [ ' name ' ] , None , None , localPlacement , prodDefShape , el [ ' predefinedType ' ] , localZAxis )
if el [ ' geometryType ' ] == ' surface ' :
ifcElements [ i ] = self . f . createIfcStructuralSurfaceMember ( self . guid ( ) , ownerHistory , el [ ' name ' ] , None , None , localPlacement , prodDefShape , el [ ' predefinedType ' ] , el [ ' thickness ' ] )
# create structural point connections
ifcConnections = [ None for _ in range ( len ( self . data [ ' connections ' ] ) ) ]
for i , conn in enumerate ( self . data [ ' connections ' ] ) :
# geometry - product definition shape
prodDefShape = self . create_geometry ( conn )
2020-10-14 11:13:23 +02:00
2020-07-14 21:40:23 +02:00
# boundary conditions
if conn [ ' appliedCondition ' ] :
2020-10-14 11:13:23 +02:00
bc = self . create_applied_conditions ( conn [ ' appliedCondition ' ] , conn [ ' geometryType ' ] )
if conn [ ' geometryType ' ] == ' point ' :
appliedCondition = self . f . createIfcBoundaryNodeCondition ( None , bc [ ' dx ' ] , bc [ ' dy ' ] , bc [ ' dz ' ] , bc [ ' drx ' ] , bc [ ' dry ' ] , bc [ ' drz ' ] )
if conn [ ' geometryType ' ] == ' line ' :
appliedCondition = self . f . createIfcBoundaryEdgeCondition ( None , bc [ ' dx ' ] , bc [ ' dy ' ] , bc [ ' dz ' ] , bc [ ' drx ' ] , bc [ ' dry ' ] , bc [ ' drz ' ] )
if conn [ ' geometryType ' ] == ' surface ' :
appliedCondition = self . f . createIfcBoundaryFaceCondition ( None , bc [ ' dx ' ] , bc [ ' dy ' ] , bc [ ' dz ' ] )
2020-07-14 21:40:23 +02:00
else :
appliedCondition = None
if conn [ ' geometryType ' ] == ' point ' :
2020-10-14 11:13:23 +02:00
# local axes
localAxes = self . create_orientation ( conn [ ' orientation ' ] )
# connection
2020-07-14 21:40:23 +02:00
ifcConnections [ i ] = self . f . createIfcStructuralPointConnection ( self . guid ( ) , ownerHistory , conn [ ' name ' ] , None , None , localPlacement , prodDefShape , appliedCondition , localAxes )
2020-10-14 11:13:23 +02:00
if conn [ ' geometryType ' ] == ' line ' :
# z axis TODO: group by elements
localZAxis = self . f . createIfcDirection ( tuple ( conn [ ' orientation ' ] [ 2 ] ) )
# connection
ifcConnections [ i ] = self . f . createIfcStructuralCurveConnection ( self . guid ( ) , ownerHistory , conn [ ' name ' ] , None , None , localPlacement , prodDefShape , appliedCondition , localZAxis )
if conn [ ' geometryType ' ] == ' surface ' :
ifcConnections [ i ] = self . f . createIfcStructuralSurfaceConnection ( self . guid ( ) , ownerHistory , conn [ ' name ' ] , None , None , localPlacement , prodDefShape , appliedCondition )
2020-07-14 21:40:23 +02:00
# assign material-profile-sets
for i , mpSet in enumerate ( mpSets ) :
groupOfElements = [ ]
for j , el in enumerate ( self . data [ ' elements ' ] ) :
if el [ ' geometryType ' ] == ' line ' and el [ ' material ' ] + ' - ' + el [ ' profile ' ] == mpSet :
groupOfElements . append ( ifcElements [ j ] )
if groupOfElements :
self . f . createIfcRelAssociatesMaterial ( self . guid ( ) , ownerHistory , None , None , tuple ( groupOfElements ) , ifcMaterialProfileSets [ i ] )
# assign materials
for i , mat in enumerate ( self . data [ ' db ' ] [ ' materials ' ] ) :
groupOfElements = [ ]
for j , el in enumerate ( self . data [ ' elements ' ] ) :
if el [ ' geometryType ' ] == ' surface ' and el [ ' material ' ] == mat [ ' ifcName ' ] :
groupOfElements . append ( ifcElements [ j ] )
if groupOfElements :
self . f . createIfcRelAssociatesMaterial ( self . guid ( ) , ownerHistory , None , None , tuple ( groupOfElements ) , ifcMaterials [ i ] )
# create connections with elements
for i , el in enumerate ( self . data [ ' elements ' ] ) :
for conn in el [ ' connections ' ] :
2020-10-14 11:13:23 +02:00
j = [ c [ ' ifcName ' ] for c in self . data [ ' connections ' ] ] . index ( conn [ ' relatedConnection ' ] )
geometryType = self . data [ ' connections ' ] [ j ] [ ' geometryType ' ]
2020-07-14 21:40:23 +02:00
if conn [ ' appliedCondition ' ] :
2020-10-14 11:13:23 +02:00
bc = self . create_applied_conditions ( conn [ ' appliedCondition ' ] , geometryType )
if geometryType == ' point ' :
appliedCondition = self . f . createIfcBoundaryNodeCondition ( None , bc [ ' dx ' ] , bc [ ' dy ' ] , bc [ ' dz ' ] , bc [ ' drx ' ] , bc [ ' dry ' ] , bc [ ' drz ' ] )
if geometryType == ' line ' :
appliedCondition = self . f . createIfcBoundaryEdgeCondition ( None , bc [ ' dx ' ] , bc [ ' dy ' ] , bc [ ' dz ' ] , bc [ ' drx ' ] , bc [ ' dry ' ] , bc [ ' drz ' ] )
if geometryType == ' surface ' :
appliedCondition = self . f . createIfcBoundaryFaceCondition ( None , bc [ ' dx ' ] , bc [ ' dy ' ] , bc [ ' dz ' ] )
2020-07-14 21:40:23 +02:00
else :
appliedCondition = None
2020-10-14 11:13:23 +02:00
# local axes
localAxes = self . create_orientation ( conn [ ' orientation ' ] )
if geometryType == ' point ' :
if not conn [ ' eccentricity ' ] :
self . f . createIfcRelConnectsStructuralMember ( self . guid ( ) , ownerHistory , None , None , ifcElements [ i ] , ifcConnections [ j ] , appliedCondition , None , None , localAxes )
else :
pointOnElement = self . f . createIfcCartesianPoint ( tuple ( conn [ ' eccentricity ' ] [ ' pointOnElement ' ] ) )
vector = conn [ ' eccentricity ' ] [ ' vector ' ]
connPointEcc = self . f . createIfcConnectionPointEccentricity ( pointOnElement , None , vector [ 0 ] , vector [ 1 ] , vector [ 2 ] )
self . f . createIfcRelConnectsWithEccentricity ( self . guid ( ) , ownerHistory , None , None , ifcElements [ i ] , ifcConnections [ j ] , appliedCondition , None , None , localAxes , connPointEcc )
if geometryType in [ ' line ' , ' surface ' ] :
2020-07-14 21:40:23 +02:00
self . f . createIfcRelConnectsStructuralMember ( self . guid ( ) , ownerHistory , None , None , ifcElements [ i ] , ifcConnections [ j ] , appliedCondition , None , None , localAxes )
# assign elements and connections to group
self . f . createIfcRelAssignsToGroup ( self . guid ( ) , ownerHistory , None , None , tuple ( ifcElements + ifcConnections ) , None , model )
# finalize ifc file
self . f . write ( self . outputFilename )
def guid ( self ) :
return ifcopenshell . guid . new ( )
def create_header ( self ) :
self . f . wrapped_data . header . file_name . name = os . path . basename ( self . outputFilename )
def create_global_axes ( self ) :
self . xAxis = self . f . createIfcDirection ( ( 1. , 0. , 0. ) )
self . yAxis = self . f . createIfcDirection ( ( 0. , 1. , 0. ) )
self . zAxis = self . f . createIfcDirection ( ( 0. , 0. , 1. ) )
self . origin = self . f . createIfcCartesianPoint ( ( 0. , 0. , 0. ) )
axes = self . f . createIfcAxis2Placement3D ( self . origin , self . zAxis , self . xAxis )
return axes
def create_orientation ( self , orientation ) :
xAxis = self . f . createIfcDirection ( tuple ( orientation [ 0 ] ) )
zAxis = self . f . createIfcDirection ( tuple ( orientation [ 2 ] ) )
axes = self . f . createIfcAxis2Placement3D ( self . origin , zAxis , xAxis )
return axes
def create_owner_history ( self ) :
actor = self . f . createIfcActorRole ( ' ENGINEER ' , None , None )
person = self . f . createIfcPerson ( ' Christovasilis ' , None , ' Ioannis ' , None , None , None , ( actor , ) )
organization = self . f . createIfcOrganization ( None , ' IfcOpenShell ' , ' IfcOpenShell, an open source (LGPL) software library that helps users and software developers to work with the IFC file format. ' )
p_o = self . f . createIfcPersonAndOrganization ( person , organization )
application = self . f . createIfcApplication ( organization , ' v0.0.x ' , ' IFC2CA ' , ' IFC2CA ' )
ownerHistory = self . f . createIfcOwnerHistory ( p_o , application , ' READWRITE ' , None , None , p_o , application )
return ownerHistory
def create_reference_subrep ( self , globalAxes ) :
modelRep = self . f . createIfcGeometricRepresentationContext ( None , ' Model ' , 3 , 1.E-05 , globalAxes , None )
bodySubRep = self . f . createIfcGeometricRepresentationSubContext ( ' Body ' , ' Model ' , None , None , None , None , modelRep , None , ' MODEL_VIEW ' , None )
refSubRep = self . f . createIfcGeometricRepresentationSubContext ( ' Reference ' , ' Model ' , None , None , None , None , modelRep , None , ' GRAPH_VIEW ' , None )
return {
' model ' : modelRep ,
' body ' : bodySubRep ,
' reference ' : refSubRep
}
def create_material ( self , material ) :
ifcMaterial = self . f . createIfcMaterial ( material [ ' name ' ] , None , material [ ' category ' ] )
mechProps = [ ]
if ' youngModulus ' in material [ ' mechProps ' ] :
youngModulus = self . f . createIfcPropertySingleValue ( ' YoungModulus ' , None , self . f . createIfcModulusOfElasticityMeasure ( material [ ' mechProps ' ] [ ' youngModulus ' ] ) )
mechProps . append ( youngModulus )
if ' shearModulus ' in material [ ' mechProps ' ] :
shearModulus = self . f . createIfcPropertySingleValue ( ' ShearModulus ' , None , self . f . createIfcModulusOfElasticityMeasure ( material [ ' mechProps ' ] [ ' shearModulus ' ] ) )
mechProps . append ( shearModulus )
if ' poissonRatio ' in material [ ' mechProps ' ] :
poissonRatio = self . f . createIfcPropertySingleValue ( ' PoissonRatio ' , None , self . f . createIfcPositiveRatioMeasure ( material [ ' mechProps ' ] [ ' poissonRatio ' ] ) )
mechProps . append ( poissonRatio )
if mechProps :
self . f . createIfcMaterialProperties ( ' Pset_MaterialMechanical ' , material [ ' name ' ] , tuple ( mechProps ) , ifcMaterial )
commonProps = [ ]
if ' massDensity ' in material [ ' commonProps ' ] :
massDensity = self . f . createIfcPropertySingleValue ( ' MassDensity ' , None , self . f . createIfcMassDensityMeasure ( material [ ' commonProps ' ] [ ' massDensity ' ] ) )
commonProps . append ( massDensity )
if commonProps :
self . f . createIfcMaterialProperties ( ' Pset_MaterialCommon ' , material [ ' name ' ] , tuple ( commonProps ) , ifcMaterial )
return ifcMaterial
def create_profile ( self , profile ) :
if profile [ ' profileShape ' ] == ' rectangular ' :
ifcProfile = self . f . createIfcRectangleProfileDef ( profile [ ' profileType ' ] , profile [ ' profileName ' ] , None , profile [ ' xDim ' ] , profile [ ' yDim ' ] )
if profile [ ' profileShape ' ] == ' iSymmetrical ' :
ifcProfile = self . f . createIfcIShapeProfileDef (
profile [ ' profileType ' ] , profile [ ' profileName ' ] , None ,
profile [ ' commonProps ' ] [ ' overallWidth ' ] ,
profile [ ' commonProps ' ] [ ' overallDepth ' ] ,
profile [ ' commonProps ' ] [ ' webThickness ' ] ,
profile [ ' commonProps ' ] [ ' flangeThickness ' ] ,
profile [ ' commonProps ' ] [ ' filletRadius ' ]
)
mechProps = [ ]
if ' massPerLength ' in profile [ ' mechProps ' ] :
massPerLength = self . f . createIfcPropertySingleValue ( ' MassPerLength ' , None , self . f . createIfcMassPerLengthMeasure ( profile [ ' mechProps ' ] [ ' massPerLength ' ] ) )
mechProps . append ( massPerLength )
if ' crossSectionArea ' in profile [ ' mechProps ' ] :
crossSectionArea = self . f . createIfcPropertySingleValue ( ' CrossSectionArea ' , None , self . f . createIfcAreaMeasure ( profile [ ' mechProps ' ] [ ' crossSectionArea ' ] ) )
mechProps . append ( crossSectionArea )
if ' momentOfInertiaY ' in profile [ ' mechProps ' ] :
momentOfInertiaY = self . f . createIfcPropertySingleValue ( ' MomentOfInertiaY ' , None , self . f . createIfcMomentOfInertiaMeasure ( profile [ ' mechProps ' ] [ ' momentOfInertiaY ' ] ) )
mechProps . append ( momentOfInertiaY )
if ' momentOfInertiaZ ' in profile [ ' mechProps ' ] :
momentOfInertiaZ = self . f . createIfcPropertySingleValue ( ' MomentOfInertiaZ ' , None , self . f . createIfcMomentOfInertiaMeasure ( profile [ ' mechProps ' ] [ ' momentOfInertiaZ ' ] ) )
mechProps . append ( momentOfInertiaZ )
if ' torsionalConstantX ' in profile [ ' mechProps ' ] :
torsionalConstantX = self . f . createIfcPropertySingleValue ( ' TorsionalConstantX ' , None , self . f . createIfcMomentOfInertiaMeasure ( profile [ ' mechProps ' ] [ ' torsionalConstantX ' ] ) )
mechProps . append ( torsionalConstantX )
if mechProps :
self . f . createIfcProfileProperties ( ' Pset_ProfileMechanical ' , profile [ ' profileName ' ] , tuple ( mechProps ) , ifcProfile )
return ifcProfile
def create_geometry ( self , object ) :
if object [ ' geometryType ' ] == ' point ' :
point = self . f . createIfcCartesianPoint ( tuple ( object [ ' geometry ' ] ) )
vertex = self . f . createIfcVertexPoint ( point )
vertexTopologyRep = self . f . createIfcTopologyRepresentation ( self . reps [ ' reference ' ] , ' Reference ' , ' Vertex ' , ( vertex , ) )
vertexProdDefShape = self . f . createIfcProductDefinitionShape ( None , None , ( vertexTopologyRep , ) )
return vertexProdDefShape
if object [ ' geometryType ' ] == ' line ' :
startPoint = self . f . createIfcCartesianPoint ( tuple ( object [ ' geometry ' ] [ 0 ] ) )
startVertex = self . f . createIfcVertexPoint ( startPoint )
endPoint = self . f . createIfcCartesianPoint ( tuple ( object [ ' geometry ' ] [ 1 ] ) )
endVertex = self . f . createIfcVertexPoint ( endPoint )
edge = self . f . createIfcEdge ( startVertex , endVertex )
edgeTopologyRep = self . f . createIfcTopologyRepresentation ( self . reps [ ' reference ' ] , ' Reference ' , ' Edge ' , ( edge , ) )
edgeProdDefShape = self . f . createIfcProductDefinitionShape ( None , None , ( edgeTopologyRep , ) )
return edgeProdDefShape
if object [ ' geometryType ' ] == ' surface ' :
verts = [ None for _ in range ( len ( object [ ' geometry ' ] ) ) ]
for i , p in enumerate ( object [ ' geometry ' ] ) :
point = self . f . createIfcCartesianPoint ( tuple ( p ) )
verts [ i ] = self . f . createIfcVertexPoint ( point )
orientedEdges = [ None for _ in range ( len ( object [ ' geometry ' ] ) ) ]
for i , v in enumerate ( verts ) :
v2Index = ( i + 1 ) if i < len ( verts ) - 1 else 0
edge = self . f . createIfcEdge ( v , verts [ v2Index ] )
orientedEdges [ i ] = self . f . createIfcOrientedEdge ( None , None , edge , True )
edgeLoop = self . f . createIfcEdgeLoop ( tuple ( orientedEdges ) )
localAxes = self . create_orientation ( object [ ' orientation ' ] )
plane = self . f . createIfcPlane ( localAxes )
faceBound = self . f . createIfcFaceBound ( edgeLoop , True )
face = self . f . createIfcFaceSurface ( ( faceBound , ) , plane , True )
faceTopologyRep = self . f . createIfcTopologyRepresentation ( self . reps [ ' reference ' ] , ' Reference ' , ' Face ' , ( face , ) )
faceProdDefShape = self . f . createIfcProductDefinitionShape ( None , None , ( faceTopologyRep , ) )
return faceProdDefShape
2020-10-14 11:13:23 +02:00
def create_applied_conditions ( self , bc , geometryType ) :
2020-08-17 17:05:31 +02:00
for dof in [ ' dx ' , ' dy ' , ' dz ' ] :
if isinstance ( bc [ dof ] , bool ) :
bc [ dof ] = self . f . createIfcBoolean ( bc [ dof ] )
else :
2020-10-14 11:13:23 +02:00
if geometryType == ' point ' :
bc [ dof ] = self . f . createIfcLinearStiffnessMeasure ( bc [ dof ] )
if geometryType == ' line ' :
bc [ dof ] = self . f . createIfcModulusOfLinearSubgradeReactionMeasure ( bc [ dof ] )
if geometryType == ' surface ' :
bc [ dof ] = self . f . createIfcModulusOfSubgradeReactionMeasure ( bc [ dof ] )
2020-08-17 17:05:31 +02:00
for dof in [ ' drx ' , ' dry ' , ' drz ' ] :
if isinstance ( bc [ dof ] , bool ) :
bc [ dof ] = self . f . createIfcBoolean ( bc [ dof ] )
else :
2020-10-14 11:13:23 +02:00
if geometryType == ' point ' :
bc [ dof ] = self . f . createIfcRotationalStiffnessMeasure ( bc [ dof ] )
if geometryType == ' line ' :
bc [ dof ] = self . f . createIfcModulusOfRotationalSubgradeReactionMeasure ( bc [ dof ] )
2020-08-17 17:05:31 +02:00
return bc
2020-07-14 21:40:23 +02:00
if __name__ == ' __main__ ' :
2020-10-14 11:13:23 +02:00
inputFilename = ' structure_01.json '
outputFilename = ' structure_01.ifc '
2020-07-14 21:40:23 +02:00
ca2ifc = CA2IFC ( inputFilename , outputFilename )
ca2ifc . convert ( )