-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbatch_converter.py
147 lines (119 loc) · 5.32 KB
/
batch_converter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import sys
import warnings
import gc
import os
import glob
import click
import zipfile
from cjio import errors, cityjson
from cityjson2ifc import Cityjson2ifc
def load_cityjson(infile, ignore_duplicate_keys=False):
"""
Loads a CityJSON file using cjio's cityjson.reader with optional duplicate key ignoring.
Returns a CityJSON object.
"""
try:
cm = cityjson.reader(file=infile, ignore_duplicate_keys=ignore_duplicate_keys)
except ValueError as e:
raise click.ClickException(f'{e}: "{infile.name}".')
except IOError as e:
raise click.ClickException(f'Invalid file: "{infile.name}".\n{e}')
# Check version and capture warnings
try:
with warnings.catch_warnings(record=True) as w:
cm.check_version()
if w: # If any warnings were captured
for warn in w:
# Print or log the warning messages if needed
click.echo(f"Warning: {warn.message}")
except errors.CJInvalidVersion as e:
raise click.ClickException(e.msg)
# If the purpose is to clear out cityobjects for memory reasons, do it explicitly
cm.cityobjects = {}
cm.load_from_j(transform=False)
# The next line also clears the "CityObjects" in cm.j explicitly
cm.j["CityObjects"] = {}
# Force garbage collection to free memory
gc.collect()
return cm
@click.command()
@click.option('--input_dir', default="/data/amir/decompressed", show_default=True,
help="Directory containing .city.json files.")
@click.option('--ignore_duplicate', is_flag=True, default=False,
help="Ignore duplicate JSON keys in CityJSON files.")
def main(input_dir, ignore_duplicate):
"""
Finds all .city.json files in the input directory, converts each to IFC for multiple LoDs,
and then zips the results in ~/IFC3DBAG/ZIP/.
"""
# 1. Identify all .city.json files
input_dir = os.path.abspath(os.path.expanduser(input_dir))
cityjson_files = glob.glob(os.path.join(input_dir, "*.city.json"))
if not cityjson_files:
click.echo("No .city.json files found in the specified directory.")
sys.exit(1)
# Define your output locations
ifc_output_dir = os.path.abspath(os.path.expanduser("~/IFC3DBAG/output"))
zip_output_dir = os.path.abspath(os.path.expanduser("~/IFC3DBAG/ZIP"))
# Ensure both directories exist
os.makedirs(ifc_output_dir, exist_ok=True)
os.makedirs(zip_output_dir, exist_ok=True)
# Define which LODs to export
lods = ["0", "1.2", "1.3", "2.2"]
for cityjson_file in cityjson_files:
# Build the zip file name in ~/IFC3DBAG/ZIP
zip_filename = os.path.join(
zip_output_dir,
os.path.basename(cityjson_file).replace(".city.json", "-ifc.zip")
)
# If that ZIP already exists, skip processing
if os.path.isfile(zip_filename):
click.echo(f"Zip file {zip_filename} found. Skipping {cityjson_file}.")
continue
# Otherwise, process the city.json file
with open(cityjson_file, "r") as infile:
click.echo(f"Parsing {infile.name} ...")
# 2. Load the CityJSON
cm = load_cityjson(infile, ignore_duplicate_keys=ignore_duplicate)
output_ifc_files = []
# 3. Convert for each LOD
for lod in lods:
converter = Cityjson2ifc()
# Create the IFC output path
base_name = os.path.basename(cityjson_file).replace(".city.json", f"-{lod}.ifc")
output_ifc_path = os.path.join(ifc_output_dir, base_name)
# 4. Configure the converter
converter.configuration(
name_project="3DBAG Project",
name_site="3DBAG Site",
name_person_family="3Dgeoinfo",
name_person_given="3DGI/",
lod=lod,
file_destination=output_ifc_path
)
# 5. Run conversion
try:
converter.convert(cm)
click.echo(f"Conversion completed for {cityjson_file} at LoD {lod}.")
except Exception as ex:
click.echo(f"Failed to convert {cityjson_file} at LoD {lod}.\nError: {ex}")
continue
output_ifc_files.append(output_ifc_path)
# 6. After generating all IFC files, zip them together
if output_ifc_files: # Only try to zip if we actually have IFC files
with zipfile.ZipFile(zip_filename, 'w') as zf:
for ifc_file in output_ifc_files:
# Write the IFC file into the ZIP,
# but store it under its base name inside the ZIP
zf.write(ifc_file, os.path.basename(ifc_file))
click.echo(f"Zipped IFC files into {zip_filename}.")
# Delete the IFC files after zipping
for ifc_file in output_ifc_files:
try:
os.remove(ifc_file)
click.echo(f"Deleted IFC file: {ifc_file}")
except OSError as e:
click.echo(f"Error deleting {ifc_file}: {e}")
click.echo("All CityJSON files have been processed.")
if __name__ == "__main__":
main()