Skip to content

Commit adfcc86

Browse files
Removed relationship objects
1 parent d37697f commit adfcc86

File tree

4 files changed

+44814
-430
lines changed

4 files changed

+44814
-430
lines changed

ifcjson/ifc2json5a.py

Lines changed: 182 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,21 @@
2626

2727
import os
2828
import uuid
29+
from tempfile import NamedTemporaryFile
2930
import subprocess
3031
import ifcopenshell
3132
import ifcopenshell.guid as guid
3233
import ifcjson.common as common
3334

35+
36+
explicitInverseAttributes = {
37+
'IsDecomposedBy',
38+
'HasAssociations',
39+
'IsDefinedBy',
40+
'HasOpenings',
41+
'ContainsElements'
42+
}
43+
3444
class IFC2JSON5a:
3545
def __init__(self, ifcFilePath):
3646
self.ifcFilePath = ifcFilePath
@@ -45,53 +55,178 @@ def __init__(self, ifcFilePath):
4555
def spf2Json(self):
4656
objData = self.getObjData(self.ifcFilePath)
4757
jsonObjects= []
48-
entityIter = iter(self.ifcModel)
49-
for entity in entityIter:
58+
# entityIter = iter(self.ifcModel)
59+
# for entity in entityIter:
60+
# # print(dir(entity))
61+
# # print("test")
62+
# # print(getitem(entity))
63+
# self.entityToDict(entity, objData)
64+
for entity in self.ifcModel.by_type('IfcProject'):
5065
self.entityToDict(entity, objData)
5166
for key in self.id_objects:
5267
jsonObjects.append(self.id_objects[key])
5368
for key in self.representations:
5469
jsonObjects.append(self.representations[key])
55-
return jsonObjects
70+
return {'file_schema': 'IFC.JSON5a','data': jsonObjects}
71+
72+
def entityToDict(self, entity, objData, parent=None):
73+
entityAttributes = entity.__dict__
74+
# inverseAttributes = explicitInverseAttributes.intersection(entity.wrapped_data.get_inverse_attribute_names())
75+
entityType = entity.is_a()
5676

57-
def entityToDict(self, entity, objData):
5877
ref = {
59-
'type': entity.is_a()
78+
'type': entityType
6079
}
61-
attr_dict = entity.__dict__
6280

63-
# check for globalid
64-
if 'GlobalId' in attr_dict:
65-
uuid = guid.split(guid.expand(attr_dict["GlobalId"]))[1:-1]
81+
82+
# determine if object needs to be nested or referenced
83+
reference = False
84+
if 'GlobalId' in entityAttributes:
85+
reference = True
86+
if entity.is_a == 'IfcRelAggregates':
87+
# print('relaggregates!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
88+
reference = False
89+
90+
d = {
91+
'type': entityType
92+
}
93+
94+
95+
# for inverseAttribute in inverseAttributes:
96+
# invAtt = {}
97+
# attributeObject = getattr(entity, inverseAttribute)
98+
# attr = inverseAttribute
99+
# attrKey = common.toLowerCamelcase(attr)
100+
# print(attributeObject)
101+
102+
# print("yeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeees")
103+
# if isinstance(attributeObject, ifcopenshell.entity_instance):
104+
# print("dsicnkjcnkdjvnskjcnkvjnfjkn")
105+
# # if attributeObject.is_a == 'IfcRelAggregates':
106+
# # d[inverseAttribute] = attributeObject.RelatedObjects
107+
# # jsonValue = self.getEntityValue(attributeObject, objData)
108+
# # if jsonValue:
109+
# # invAtt[attrKey] = jsonValue
110+
# # if attributeObject == None:
111+
# # continue
112+
# # elif isinstance(attributeObject, ifcopenshell.entity_instance):
113+
# # invAtt[attrKey] = self.entityToDict(attributeObject, objData)
114+
# # elif isinstance(attributeObject, tuple):
115+
# # subEnts = []
116+
# # for subEntity in attributeObject:
117+
# # if isinstance(subEntity, ifcopenshell.entity_instance):
118+
# # subEntJson = self.entityToDict(subEntity, objData)
119+
# # if subEntJson:
120+
# # subEnts.append(subEntJson)
121+
# # else:
122+
# # subEnts.append(subEntity)
123+
# # if len(subEnts) > 0:
124+
# # invAtt[attrKey] = subEnts
125+
# # else:
126+
# # invAtt[attrKey] = attributeObject
127+
# if invAtt:
128+
# # print(inverseAttribute)
129+
# d[inverseAttribute] = invAtt
130+
131+
132+
# if hasattr(entity, 'IsDefinedBy'):
133+
# decomposedBy = entity.IsDefinedBy
134+
# invAtt = []
135+
# for rel in decomposedBy:
136+
# print(rel)
137+
# relatedObjects = rel.RelatingPropertyDefinition.HasProperties
138+
# print(relatedObjects)
139+
# for relatedObject in relatedObjects:
140+
# relatedEntity = self.entityToDict(relatedObject, objData, parent=entity)
141+
# if parent != relatedEntity:
142+
# invAtt.append(relatedEntity)
143+
# # print(relatedObject)
144+
# # invAtt = invAtt + list(self.entityToDict(subEntity, objData))
145+
# print(invAtt)
146+
# if invAtt:
147+
# d['IsDefinedBy'] = invAtt
148+
149+
150+
if hasattr(entity, 'IsDefinedBy'):
151+
relations = entity.IsDefinedBy
152+
# p = {}
153+
for rel in relations:
154+
if rel.is_a() == 'IfcRelDefinesByProperties':
155+
definition = rel.RelatingPropertyDefinition
156+
if definition.is_a() == 'IfcPropertySet':
157+
relatedObjects = definition.HasProperties
158+
for relatedObject in relatedObjects:
159+
value = relatedObject.NominalValue.wrappedValue
160+
if value and value != '':
161+
d[common.toLowerCamelcase(relatedObject.Name)] = value
162+
elif definition.is_a() == 'IfcElementQuantity':
163+
relatedObjects = definition.Quantities
164+
for relatedObject in relatedObjects:
165+
value = relatedObject.AreaValue
166+
if value and value != '':
167+
d[common.toLowerCamelcase(relatedObject.Name)] = value
168+
else:
169+
print('Skipped: ' + str(definition))
170+
else:
171+
print('Skipped: ' + str(rel))
172+
# if p:
173+
# d['properties'] = p
174+
175+
176+
if hasattr(entity, 'IsDecomposedBy'):
177+
decomposedBy = entity.IsDecomposedBy
178+
invAtt = []
179+
for rel in decomposedBy:
180+
relatedObjects = rel.RelatedObjects
181+
for relatedObject in relatedObjects:
182+
relatedEntity = self.entityToDict(relatedObject, objData, parent=entity)
183+
if parent != relatedEntity:
184+
invAtt.append(relatedEntity)
185+
if invAtt:
186+
d['IsDecomposedBy'] = invAtt
187+
188+
189+
if hasattr(entity, 'ContainsElements'):
190+
decomposedBy = entity.ContainsElements
191+
invAtt = []
192+
for rel in decomposedBy:
193+
relatedObjects = rel.RelatedElements
194+
for relatedObject in relatedObjects:
195+
relatedEntity = self.entityToDict(relatedObject, objData, parent=entity)
196+
if parent != relatedEntity:
197+
invAtt.append(relatedEntity)
198+
if invAtt:
199+
d['ContainsElements'] = invAtt
200+
201+
202+
if reference:
203+
uuid = guid.split(guid.expand(entityAttributes["GlobalId"]))[1:-1]
66204
ref['ref'] = uuid
67-
if not attr_dict['GlobalId'] in self.id_objects:
68-
d = {
69-
'type': entity.is_a()
70-
}
205+
if not entityAttributes['GlobalId'] in self.id_objects:
71206

72207
for i in range(0,len(entity)):
73208
attr = entity.attribute_name(i)
74209
attrKey = common.toLowerCamelcase(attr)
75210
if attr == "GlobalId":
76211
d[attrKey] = uuid
77212
else:
78-
if attr in attr_dict:
213+
if attr in entityAttributes:
79214

80215
# Skip all IFC entities that are not part of IFC.JSON5a
81-
if type(attr_dict[attr]) == ifcopenshell.entity_instance:
216+
if type(entityAttributes[attr]) == ifcopenshell.entity_instance:
82217

83218
# Skip IfcOwnerHistory
84-
if attr_dict[attr].is_a() == 'IfcOwnerHistory':
219+
if entityAttributes[attr].is_a() == 'IfcOwnerHistory':
85220
continue
86221

87222
# Skip IfcGeometricRepresentationContext
88-
if attr_dict[attr].is_a() == 'IfcGeometricRepresentationContext':
223+
if entityAttributes[attr].is_a() == 'IfcGeometricRepresentationContext':
89224
continue
90225

91226
# Use representation from OBJ list if present
92227
if attr == 'Representation':
93228
if objData:
94-
if attr_dict['GlobalId'] in objData:
229+
if entityAttributes['GlobalId'] in objData:
95230
id = guid.split(guid.expand(guid.new()))[1:-1]
96231
d['representations'] = [
97232
{
@@ -105,7 +240,7 @@ def entityToDict(self, entity, objData):
105240
"representationIdentifier": "Body",
106241
"representationType": "OBJ",
107242
"items": [
108-
objData[attr_dict['GlobalId']]
243+
objData[entityAttributes['GlobalId']]
109244
]
110245
}
111246
continue
@@ -117,16 +252,16 @@ def entityToDict(self, entity, objData):
117252
if attr == 'ObjectPlacement':
118253
continue
119254

120-
jsonValue = self.getEntityValue(attr_dict[attr], objData)
255+
jsonValue = self.getEntityValue(entityAttributes[attr], objData)
121256
if jsonValue:
122257
d[attrKey] = jsonValue
123-
if attr_dict[attr] == None:
258+
if entityAttributes[attr] == None:
124259
continue
125-
elif isinstance(attr_dict[attr], ifcopenshell.entity_instance):
126-
d[attrKey] = self.entityToDict(attr_dict[attr], objData)
127-
elif isinstance(attr_dict[attr], tuple):
260+
elif isinstance(entityAttributes[attr], ifcopenshell.entity_instance):
261+
d[attrKey] = self.entityToDict(entityAttributes[attr], objData)
262+
elif isinstance(entityAttributes[attr], tuple):
128263
subEnts = []
129-
for subEntity in attr_dict[attr]:
264+
for subEntity in entityAttributes[attr]:
130265
if isinstance(subEntity, ifcopenshell.entity_instance):
131266
subEntJson = self.entityToDict(subEntity, objData)
132267
if subEntJson:
@@ -136,29 +271,26 @@ def entityToDict(self, entity, objData):
136271
if len(subEnts) > 0:
137272
d[attrKey] = subEnts
138273
else:
139-
d[attrKey] = attr_dict[attr]
140-
self.id_objects[attr_dict['GlobalId']] = d
274+
d[attrKey] = entityAttributes[attr]
275+
self.id_objects[entityAttributes['GlobalId']] = d
141276
return ref
142277
else:
143-
d = {
144-
'type': entity.is_a()
145-
}
146278

147279
for i in range(0,len(entity)):
148280
attr = entity.attribute_name(i)
149281
attrKey = common.toLowerCamelcase(attr)
150-
if attr in attr_dict:
282+
if attr in entityAttributes:
151283
if not attr == 'OwnerHistory':
152-
jsonValue = self.getEntityValue(attr_dict[attr], objData)
284+
jsonValue = self.getEntityValue(entityAttributes[attr], objData)
153285
if jsonValue:
154286
d[attrKey] = jsonValue
155-
if attr_dict[attr] == None:
287+
if entityAttributes[attr] == None:
156288
continue
157-
elif isinstance(attr_dict[attr], ifcopenshell.entity_instance):
158-
d[attrKey] = self.entityToDict(attr_dict[attr], objData)
159-
elif isinstance(attr_dict[attr], tuple):
289+
elif isinstance(entityAttributes[attr], ifcopenshell.entity_instance):
290+
d[attrKey] = self.entityToDict(entityAttributes[attr], objData)
291+
elif isinstance(entityAttributes[attr], tuple):
160292
subEnts = []
161-
for subEntity in attr_dict[attr]:
293+
for subEntity in entityAttributes[attr]:
162294
if isinstance(subEntity, ifcopenshell.entity_instance):
163295
subEntJson = self.entityToDict(subEntity, objData)
164296
if subEntJson:
@@ -168,7 +300,9 @@ def entityToDict(self, entity, objData):
168300
if len(subEnts) > 0:
169301
d[attrKey] = subEnts
170302
else:
171-
d[attrKey] = attr_dict[attr]
303+
d[attrKey] = entityAttributes[attr]
304+
305+
172306
return d
173307

174308
def getEntityValue(self, value, objData):
@@ -188,15 +322,15 @@ def getEntityValue(self, value, objData):
188322

189323
# convert IFC SPF file into OBJ using IfcConvert and extract OBJ objects
190324
def getObjData(self, ifcFilePath):
191-
objFilePath = os.path.splitext(ifcFilePath)[0] + '.obj'
325+
objFilePath = NamedTemporaryFile(suffix='.obj', delete=True).name
192326

193327
# Convert IFC to OBJ using IfcConvert (could also be done for glTF or Collada)
194-
# subprocess.run([
195-
# './ifcopenshell/IfcConvert',
196-
# ifcFilePath,
197-
# objFilePath,
198-
# '--use-element-guids'
199-
# ])
328+
subprocess.run([
329+
'./ifcopenshell/IfcConvert',
330+
ifcFilePath,
331+
objFilePath,
332+
'--use-element-guids'
333+
])
200334
if os.path.isfile(objFilePath):
201335
objData = {}
202336
header = True
@@ -208,14 +342,15 @@ def getObjData(self, ifcFilePath):
208342
# find group
209343
if line[0] == 'g':
210344
header = False
211-
objData[groupId] = '\n'.join(groupData)
345+
objData[groupId] = ''.join(groupData)
212346
groupId = line.split()[1]
213347
groupData = []
214348
else:
215349
if header:
216350
pass
217351
else:
218-
groupData.append(line)
352+
if line[0] == 'v' or line[0] == 'f':
353+
groupData.append(line)
219354
return objData
220355
else:
221356
print('Creating intermediate OBJ failed')

0 commit comments

Comments
 (0)