Skip to content

Commit 46ff643

Browse files
version added with OBJ geometry using ifcconvert
1 parent 1364ada commit 46ff643

File tree

3 files changed

+2014
-0
lines changed

3 files changed

+2014
-0
lines changed

ifc2json5a.py

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
# IFCJSON_python - ifc2json5.py
2+
# Copyright (C) 2020 Jan Brouwer <jan@brewsky.nl>
3+
4+
# This program is free software: you can redistribute it and/or modify
5+
# it under the terms of the GNU General Public License as published by
6+
# the Free Software Foundation, either version 3 of the License, or
7+
# (at your option) any later version.
8+
9+
# This program is distributed in the hope that it will be useful,
10+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
# GNU General Public License for more details.
13+
14+
# You should have received a copy of the GNU General Public License
15+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
# Convert IFC SPF file to IFC.JSON-5Alpha
18+
# https://github.com/IFCJSON-Team
19+
20+
import os
21+
import argparse
22+
import json
23+
import uuid
24+
import subprocess
25+
import ifcopenshell
26+
27+
id_objects = {}
28+
29+
def entityToDict(entity, objData):
30+
ref = {
31+
'type': entity.is_a()
32+
}
33+
attr_dict = entity.__dict__
34+
35+
# check for globalid
36+
if 'GlobalId' in attr_dict:
37+
ref['ref'] = attr_dict['GlobalId']
38+
if not attr_dict['GlobalId'] in id_objects:
39+
d = {
40+
'type': entity.is_a()
41+
}
42+
43+
for i in range(0,len(entity)):
44+
attr = entity.attribute_name(i)
45+
46+
# Create camelCase key for attributes
47+
attrKey = attr[0].lower() + attr[1:]
48+
49+
if attr in attr_dict:
50+
51+
# Skip OwnerHistory
52+
if attr == 'OwnerHistory':
53+
continue
54+
55+
# Use representation from OBJ list if present
56+
if attr == 'Representation':
57+
if objData:
58+
if attr_dict['GlobalId'] in objData:
59+
id = str(uuid.uuid4())
60+
d['representations'] = [
61+
{
62+
"class": "ShapeRepresentation",
63+
"ref": id
64+
}
65+
]
66+
id_objects[id] = {
67+
"class": "ShapeRepresentation",
68+
"globalId": id,
69+
"representationIdentifier": "Body",
70+
"representationType": "OBJ",
71+
"items": [
72+
objData[attr_dict['GlobalId']]
73+
]
74+
}
75+
continue
76+
else:
77+
continue
78+
79+
80+
# Skip ObjectPlacement: all placements are in world coordinates
81+
if attr == 'ObjectPlacement':
82+
continue
83+
# # Skip relative placement if representation present in OBJ list
84+
# if attr == 'ObjectPlacement':
85+
# if objData:
86+
# if attr_dict['GlobalId'] in objData:
87+
# continue
88+
89+
jsonValue = getEntityValue(attr_dict[attr], objData)
90+
if jsonValue:
91+
d[attrKey] = jsonValue
92+
if attr_dict[attr] == None:
93+
continue
94+
elif isinstance(attr_dict[attr], ifcopenshell.entity_instance):
95+
d[attrKey] = entityToDict(attr_dict[attr], objData)
96+
elif isinstance(attr_dict[attr], tuple):
97+
subEnts = []
98+
for subEntity in attr_dict[attr]:
99+
if isinstance(subEntity, ifcopenshell.entity_instance):
100+
subEntJson = entityToDict(subEntity, objData)
101+
if subEntJson:
102+
subEnts.append(subEntJson)
103+
else:
104+
subEnts.append(subEntity)
105+
if len(subEnts) > 0:
106+
d[attrKey] = subEnts
107+
else:
108+
d[attrKey] = attr_dict[attr]
109+
id_objects[attr_dict['GlobalId']] = d
110+
return ref
111+
else:
112+
d = {
113+
'type': entity.is_a()
114+
}
115+
116+
for i in range(0,len(entity)):
117+
attr = entity.attribute_name(i)
118+
119+
# Create camelCase key for attributes
120+
attrKey = attr[0].lower() + attr[1:]
121+
122+
if attr in attr_dict:
123+
if not attr == 'OwnerHistory':
124+
jsonValue = getEntityValue(attr_dict[attr], objData)
125+
if jsonValue:
126+
d[attrKey] = jsonValue
127+
if attr_dict[attr] == None:
128+
continue
129+
elif isinstance(attr_dict[attr], ifcopenshell.entity_instance):
130+
d[attrKey] = entityToDict(attr_dict[attr], objData)
131+
elif isinstance(attr_dict[attr], tuple):
132+
subEnts = []
133+
for subEntity in attr_dict[attr]:
134+
if isinstance(subEntity, ifcopenshell.entity_instance):
135+
# subEnts.append(None)
136+
subEntJson = entityToDict(subEntity, objData)
137+
if subEntJson:
138+
subEnts.append(subEntJson)
139+
else:
140+
subEnts.append(subEntity)
141+
if len(subEnts) > 0:
142+
d[attrKey] = subEnts
143+
else:
144+
d[attrKey] = attr_dict[attr]
145+
return d
146+
147+
def getEntityValue(value, objData):
148+
if value == None:
149+
jsonValue = None
150+
elif isinstance(value, ifcopenshell.entity_instance):
151+
jsonValue = entityToDict(value, objData)
152+
elif isinstance(value, tuple):
153+
jsonValue = None
154+
subEnts = []
155+
for subEntity in value:
156+
subEnts.append(getEntityValue(subEntity, objData))
157+
jsonValue = subEnts
158+
else:
159+
jsonValue = value
160+
return jsonValue
161+
162+
# convert IFC SPF file into OBJ using IfcConvert and extract OBJ objects
163+
def getObjData(ifcFilePath):
164+
objFilePath = os.path.splitext(jsonFilePath)[0] + '.obj'
165+
166+
# Convert IFC to OBJ using IfcConvert (could also be done for glTF or Collada)
167+
# subprocess.run([
168+
# './ifcopenshell/IfcConvert',
169+
# ifcFilePath,
170+
# objFilePath,
171+
# '--use-element-guids'
172+
# ])
173+
if os.path.isfile(objFilePath):
174+
objData = {}
175+
header = True
176+
groupId = ''
177+
groupData = []
178+
f = open(objFilePath, 'r')
179+
for line in f:
180+
181+
# find group
182+
if line[0] == 'g':
183+
header = False
184+
objData[groupId] = '\n'.join(groupData)
185+
groupId = line.split()[1]
186+
groupData = []
187+
else:
188+
if header:
189+
pass
190+
else:
191+
groupData.append(line)
192+
return objData
193+
else:
194+
print('Creating intermediate OBJ failed')
195+
return None
196+
197+
def spf2Json(ifcFilePath, jsonFilePath):
198+
ifc_file = ifcopenshell.open(ifcFilePath)
199+
objData = getObjData(ifcFilePath)
200+
print(objData)
201+
202+
jsonObjects= []
203+
entityIter = iter(ifc_file)
204+
for entity in entityIter:
205+
entityToDict(entity, objData)
206+
for key in id_objects:
207+
jsonObjects.append(id_objects[key])
208+
with open(jsonFilePath, 'w') as outfile:
209+
json.dump(jsonObjects, outfile, indent=4)
210+
211+
if __name__ == '__main__':
212+
parser = argparse.ArgumentParser(description='Convert IFC SPF file to IFC.JSON-5Alpha')
213+
parser.add_argument('-i', type=str, help='input ifc file path')
214+
args = parser.parse_args()
215+
if args.i:
216+
ifcFilePath = args.i
217+
else:
218+
ifcFilePath = './samples/7m900_tue_hello_wall_with_door.ifc'
219+
if os.path.isfile(ifcFilePath):
220+
basePath = os.path.splitext(ifcFilePath)[0]
221+
jsonFilePath = basePath + '.json'
222+
spf2Json(ifcFilePath, jsonFilePath)
223+
else:
224+
print(args.i + ' is not a valid file')

0 commit comments

Comments
 (0)