Skip to content

Commit 387183a

Browse files
Big overhaul
1 parent 46ff643 commit 387183a

File tree

6 files changed

+460
-101
lines changed

6 files changed

+460
-101
lines changed

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,20 @@
11
# IFC2JSON_python
22
Python converter from IFC SPF to JSON
3+
4+
# Getting Started
5+
6+
## Requirements
7+
- ifcopenshell (using packagemanager or in folder ./ifcopenshell)
8+
- IfcConvert placed in ./ifcopenshell
9+
10+
## Usage
11+
```
12+
python -i model.ifc -o model_-_ifcjson4.json -v 4
13+
```
14+
```
15+
optional arguments:
16+
-h, --help show this help message and exit
17+
-i I input ifc file path
18+
-o O output json file path
19+
-v V IFC.JSON version, options: "4"(default), "5a"
20+
```

ifc2json.py

Lines changed: 48 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,50 @@
1-
import ifcopenshell
2-
import json
3-
4-
ifc_file = ifcopenshell.open('./samples/7m900_tue_hello_wall_with_door.ifc')
5-
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(ifc_file.schema)
6-
id_objects = {}
7-
8-
def entityToDict(entity):
9-
ref = {
10-
"Type": entity.is_a()
11-
}
12-
attr_dict = entity.__dict__
13-
14-
# check for globalid
15-
if "GlobalId" in attr_dict:
16-
ref["ref"] = attr_dict["GlobalId"]
17-
if not attr_dict["GlobalId"] in id_objects:
18-
d = {
19-
"Type": entity.is_a()
20-
}
21-
22-
for i in range(0,len(entity)):
23-
attr = entity.attribute_name(i)
24-
if attr in attr_dict:
25-
if not attr == "OwnerHistory":
26-
jsonValue = getEntityValue(attr_dict[attr])
27-
if jsonValue:
28-
d[attr] = jsonValue
29-
if attr_dict[attr] == None:
30-
continue
31-
elif isinstance(attr_dict[attr], ifcopenshell.entity_instance):
32-
d[attr] = entityToDict(attr_dict[attr])
33-
elif isinstance(attr_dict[attr], tuple):
34-
subEnts = []
35-
for subEntity in attr_dict[attr]:
36-
if isinstance(subEntity, ifcopenshell.entity_instance):
37-
subEntJson = entityToDict(subEntity)
38-
if subEntJson:
39-
subEnts.append(subEntJson)
40-
else:
41-
subEnts.append(subEntity)
42-
if len(subEnts) > 0:
43-
d[attr] = subEnts
44-
else:
45-
d[attr] = attr_dict[attr]
46-
id_objects[attr_dict["GlobalId"]] = d
47-
return ref
1+
# IFCJSON_python - ifc2json.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 ifcjson.ifc2json4 as ifc2json4
23+
import ifcjson.ifc2json5a as ifc2json5a
24+
25+
if __name__ == '__main__':
26+
parser = argparse.ArgumentParser(description='Convert IFC SPF file to IFC.JSON')
27+
parser.add_argument('-i', type=str, help='input ifc file path')
28+
parser.add_argument('-o', type=str, help='output json file path')
29+
parser.add_argument('-v', type=str, help='IFC.JSON version, options: "4"(default), "5a"')
30+
args = parser.parse_args()
31+
if args.i:
32+
ifcFilePath = args.i
4833
else:
49-
d = {
50-
"Type": entity.is_a()
51-
}
52-
53-
for i in range(0,len(entity)):
54-
attr = entity.attribute_name(i)
55-
if attr in attr_dict:
56-
if not attr == "OwnerHistory":
57-
jsonValue = getEntityValue(attr_dict[attr])
58-
if jsonValue:
59-
d[attr] = jsonValue
60-
if attr_dict[attr] == None:
61-
continue
62-
elif isinstance(attr_dict[attr], ifcopenshell.entity_instance):
63-
d[attr] = entityToDict(attr_dict[attr])
64-
elif isinstance(attr_dict[attr], tuple):
65-
subEnts = []
66-
for subEntity in attr_dict[attr]:
67-
if isinstance(subEntity, ifcopenshell.entity_instance):
68-
# subEnts.append(None)
69-
subEntJson = entityToDict(subEntity)
70-
if subEntJson:
71-
subEnts.append(subEntJson)
72-
else:
73-
subEnts.append(subEntity)
74-
if len(subEnts) > 0:
75-
d[attr] = subEnts
76-
else:
77-
d[attr] = attr_dict[attr]
78-
return d
79-
80-
def getEntityValue(value):
81-
if value == None:
82-
jsonValue = None
83-
elif isinstance(value, ifcopenshell.entity_instance):
84-
jsonValue = entityToDict(value)
85-
elif isinstance(value, tuple):
86-
jsonValue = None
87-
subEnts = []
88-
for subEntity in value:
89-
subEnts.append(getEntityValue(subEntity))
90-
jsonValue = subEnts
34+
ifcFilePath = './samples/7m900_tue_hello_wall_with_door.ifc'
35+
if os.path.isfile(ifcFilePath):
36+
if args.o:
37+
jsonFilePath = args.o
38+
else:
39+
jsonFilePath = os.path.splitext(ifcFilePath)[0] + '.json'
40+
if args.v:
41+
if args.v == "4":
42+
ifc2json4.spf2Json(ifcFilePath, jsonFilePath)
43+
elif args.v == "5a":
44+
ifc2json5a.spf2Json(ifcFilePath, jsonFilePath)
45+
else:
46+
print('Version ' + args.v + ' is not supported')
47+
else:
48+
ifc2json4.spf2Json(ifcFilePath, jsonFilePath)
9149
else:
92-
jsonValue = value
93-
return jsonValue
94-
95-
96-
jsonObjects= []
97-
entityIter = iter(ifc_file)
98-
for entity in entityIter:
99-
entityToDict(entity)
100-
for key in id_objects:
101-
jsonObjects.append(id_objects[key])
102-
with open('7m900_tue_hello_wall_with_door.json', 'w') as outfile:
103-
json.dump(jsonObjects, outfile, indent=4)
50+
print(args.i + ' is not a valid file')

ifcjson/__init__.py

Whitespace-only changes.

ifcjson/common.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
def toLowerCamelcase(string):
2+
"""Convert string from upper to lower camelCase"""
3+
4+
return string[0].lower() + string[1:]

ifcjson/ifc2json4.py

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
# IFCJSON_python - ifc2json4.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-4
18+
# https://github.com/IFCJSON-Team
19+
20+
import os
21+
import argparse
22+
import json
23+
import uuid
24+
import ifcopenshell
25+
import ifcopenshell.guid as guid
26+
import ifcjson.common as common
27+
28+
# ifc_file = ifcopenshell.open('../samples/7m900_tue_hello_wall_with_door.ifc')
29+
# schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(ifc_file.schema)
30+
id_objects = {}
31+
32+
# Create dictionary of OwnerHistory objects
33+
ownerHistories = {}
34+
35+
# Create dictionary of IfcGeometricRepresentationContext objects
36+
representationContexts = {}
37+
38+
def entityToDict(entity):
39+
attr_dict = entity.__dict__
40+
41+
ref = {
42+
"type": entity.is_a()
43+
}
44+
45+
# Add missing GlobalId to OwnerHistory
46+
if entity.is_a() == 'IfcOwnerHistory':
47+
if not entity.id() in ownerHistories:
48+
ownerHistories[entity.id()] = guid.new()
49+
attr_dict["GlobalId"] = ownerHistories[entity.id()]
50+
51+
# Add missing GlobalId to IfcGeometricRepresentationContext
52+
if entity.is_a() == 'IfcGeometricRepresentationContext':
53+
if not entity.id() in representationContexts:
54+
representationContexts[entity.id()] = guid.new()
55+
attr_dict["GlobalId"] = representationContexts[entity.id()]
56+
57+
# check for globalid
58+
if "GlobalId" in attr_dict:
59+
uuid = guid.split(guid.expand(attr_dict["GlobalId"]))[1:-1]
60+
ref["ref"] = uuid
61+
if not attr_dict["GlobalId"] in id_objects:
62+
d = {
63+
"type": entity.is_a()
64+
}
65+
66+
# Add missing GlobalId to OwnerHistory
67+
if entity.is_a() == 'IfcOwnerHistory':
68+
d["GlobalId"] = guid.split(guid.expand(ownerHistories[entity.id()]))[1:-1]
69+
70+
# Add missing GlobalId to IfcGeometricRepresentationContext
71+
if entity.is_a() == 'IfcGeometricRepresentationContext':
72+
d["GlobalId"] = guid.split(guid.expand(representationContexts[entity.id()]))[1:-1]
73+
74+
for i in range(0,len(entity)):
75+
attr = entity.attribute_name(i)
76+
attrKey = common.toLowerCamelcase(attr)
77+
if attr == "GlobalId":
78+
d[attrKey] = uuid
79+
else:
80+
if attr in attr_dict:
81+
jsonValue = getEntityValue(attr_dict[attr])
82+
if jsonValue:
83+
if ((entity.is_a() == 'IfcOwnerHistory') and (attr == "GlobalId")):
84+
pass
85+
else:
86+
d[attrKey] = jsonValue
87+
if attr_dict[attr] == None:
88+
continue
89+
elif isinstance(attr_dict[attr], ifcopenshell.entity_instance):
90+
d[attrKey] = entityToDict(attr_dict[attr])
91+
elif isinstance(attr_dict[attr], tuple):
92+
subEnts = []
93+
for subEntity in attr_dict[attr]:
94+
if isinstance(subEntity, ifcopenshell.entity_instance):
95+
subEntJson = entityToDict(subEntity)
96+
if subEntJson:
97+
subEnts.append(subEntJson)
98+
else:
99+
subEnts.append(subEntity)
100+
if len(subEnts) > 0:
101+
d[attrKey] = subEnts
102+
else:
103+
d[attrKey] = attr_dict[attr]
104+
id_objects[attr_dict["GlobalId"]] = d
105+
return ref
106+
else:
107+
d = {
108+
"type": entity.is_a()
109+
}
110+
111+
for i in range(0,len(entity)):
112+
attr = entity.attribute_name(i)
113+
attrKey = common.toLowerCamelcase(attr)
114+
if attr in attr_dict:
115+
if not attr == "OwnerHistory":
116+
jsonValue = getEntityValue(attr_dict[attr])
117+
if jsonValue:
118+
d[attrKey] = jsonValue
119+
if attr_dict[attr] == None:
120+
continue
121+
elif isinstance(attr_dict[attr], ifcopenshell.entity_instance):
122+
d[attrKey] = entityToDict(attr_dict[attr])
123+
elif isinstance(attr_dict[attr], tuple):
124+
subEnts = []
125+
for subEntity in attr_dict[attr]:
126+
if isinstance(subEntity, ifcopenshell.entity_instance):
127+
# subEnts.append(None)
128+
subEntJson = entityToDict(subEntity)
129+
if subEntJson:
130+
subEnts.append(subEntJson)
131+
else:
132+
subEnts.append(subEntity)
133+
if len(subEnts) > 0:
134+
d[attrKey] = subEnts
135+
else:
136+
d[attrKey] = attr_dict[attr]
137+
return d
138+
139+
def getEntityValue(value):
140+
if value == None:
141+
jsonValue = None
142+
elif isinstance(value, ifcopenshell.entity_instance):
143+
jsonValue = entityToDict(value)
144+
elif isinstance(value, tuple):
145+
jsonValue = None
146+
subEnts = []
147+
for subEntity in value:
148+
subEnts.append(getEntityValue(subEntity))
149+
jsonValue = subEnts
150+
else:
151+
jsonValue = value
152+
return jsonValue
153+
154+
155+
# jsonObjects= []
156+
# entityIter = iter(ifc_file)
157+
# for entity in entityIter:
158+
# entityToDict(entity)
159+
# for key in id_objects:
160+
# jsonObjects.append(id_objects[key])
161+
# with open('../7m900_tue_hello_wall_with_door.json', 'w') as outfile:
162+
# json.dump(jsonObjects, outfile, indent=4)
163+
164+
def spf2Json(ifcFilePath, jsonFilePath):
165+
ifc_file = ifcopenshell.open(ifcFilePath)
166+
167+
jsonObjects= []
168+
entityIter = iter(ifc_file)
169+
for entity in entityIter:
170+
entityToDict(entity)
171+
for key in id_objects:
172+
jsonObjects.append(id_objects[key])
173+
with open(jsonFilePath, 'w') as outfile:
174+
json.dump(jsonObjects, outfile, indent=4)

0 commit comments

Comments
 (0)