Dukai Balázs @BalazsDukai, FOSS4G-HU 2019
Tweet #CityJSON
3D geoinformation research group, TU Delft, Netherlands
Az előadás anyagai megtalálhatóak itt: https://github.com/balazsdukai/foss4g2019
García-Sánchez, C., van Beeck, J., Gorlé, C., Predictive Large Eddy Simulations for Urban Flows: Challenges and Opportunities, Building and Environment, 139, 146-156, 2018.
számos modell elérhető, de ki használja ezeket? A vizualizáción kívül bármi másra?
kevés alkalmazás támogatja a 3D városmodelleket
ha igen, akkor általában zárt adatmodell és formátum (Esri, FME, Bentley ...)
kevés eszköz áll az egyéni felhasználó rendelkezésére
import json
import os
path = os.path.join('data', 'rotterdam_subset.json')
with open(path) as fin:
cm = json.loads(fin.read())
print(f"There are {len(cm['CityObjects'])} CityObjects")
# list all IDs
for id in cm['CityObjects']:
print(id, "\t")
There are 16 CityObjects {C9D4A5CF-094A-47DA-97E4-4A3BFD75D3AE} {71B60053-BC28-404D-BAB9-8A642AAC0CF4} {6271F75F-E8D8-4EE4-AC46-9DB02771A031} {DE77E78F-B110-43D2-A55C-8B61911192DE} {19935DFC-F7B3-4D6E-92DD-C48EE1D1519A} {953BC999-2F92-4B38-95CF-218F7E05AFA9} {8D716FDE-18DD-4FB5-AB06-9D207377240E} {C6AAF95B-8C09-4130-AB4D-6777A2A18A2E} {72390BDE-903C-4C8C-8A3F-2DF5647CD9B4} {8244B286-63E2-436E-9D4E-169B8ACFE9D0} {87316D28-7574-4763-B9CE-BF6A2DF8092C} {CD98680D-A8DD-4106-A18E-15EE2A908D75} {64A9018E-4F56-47CD-941F-43F6F0C4285B} {459F183A-D0C2-4F8A-8B5F-C498EFDE366D} {237D41CC-991E-4308-8986-42ABFB4F7431} {23D8CA22-0C82-4453-A11E-B3F2B3116DB4}
A CityJSON fájlok csak egyszerű JSON fájlok. Nem kell más mint a Standard Library
Viszont mindent meg kell írni az alapoktól kezdve
$ cjio city_model.json reproject 2056 export --format glb /out/model.glb
from cjio import cityjson
cm = cityjson.load('city_model.json')
cm.get_cityobjects(type='building')
pip install cjio
pip install git+https://github.com/tudelft3d/cjio@develop
cjio
's CLI¶! cjio --help
Usage: cjio [OPTIONS] INPUT COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]... Process and manipulate a CityJSON file, and allow different outputs. The different operators can be chained to perform several processing in one step, the CityJSON model goes through the different operators. To get help on specific command, eg for 'validate': cjio validate --help Usage examples: cjio example.json info validate cjio example.json assign_epsg 7145 remove_textures export output.obj cjio example.json subset --id house12 save out.json Options: --version Show the version and exit. --ignore_duplicate_keys Load a CityJSON file even if some City Objects have the same IDs (technically invalid file) --help Show this message and exit. Commands: assign_epsg Assign a (new) EPSG. clean Clean = remove_duplicate_vertices +... compress Compress a CityJSON file, ie stores its... decompress Decompress a CityJSON file, ie remove the... export Export the CityJSON to another format. extract_lod Extract only one LoD for a dataset. info Output info in simple JSON. locate_textures Output the location of the texture files. merge Merge the current CityJSON with others. partition Partition the city model into tiles. remove_duplicate_vertices Remove duplicate vertices a CityJSON file. remove_materials Remove all materials from a CityJSON file. remove_orphan_vertices Remove orphan vertices a CityJSON file. remove_textures Remove all textures from a CityJSON file. reproject Reproject the CityJSON to a new EPSG. save Save the city model to a CityJSON file. subset Create a subset of a CityJSON file. translate Translate the file by its (-minx, -miny,... update_bbox Update the bbox of a CityJSON file. update_textures Update the location of the texture files. upgrade_version Upgrade the CityJSON to the latest version. validate Validate the CityJSON file: (1) against its...
! cjio data/rotterdam_subset.json info
Parsing data/rotterdam_subset.json
{
"cityjson_version": "1.0",
"epsg": 7415,
"bbox": [
90454.18900000001,
435614.88,
0.0,
91002.41900000001,
436048.217,
18.29
],
"transform/compressed": true,
"cityobjects_total": 16,
"cityobjects_present": [
"Building"
],
"materials": false,
"textures": true
}
! cjio data/rotterdam_subset.json \
subset --exclude --id "{CD98680D-A8DD-4106-A18E-15EE2A908D75}" \
merge data/rotterdam_one.json \
reproject 2056 \
save data/test_rotterdam.json
Parsing data/rotterdam_subset.json Subset of CityJSON Merging files Reproject to EPSG:2056 [####################################] 100% Saving CityJSON to a file /home/balazs/Reports/talk_cjio_foss4g_2019/data/test_rotterdam.json
A CLI volt először, nem voltak tervek az API-ra
A városmodell egészén működik, nincs lehetőség az objektumokat külön feldolgozni
cjio
's API¶Cél hogy lehetővé tegye az olvas --> elemez --> módosít --> ír iterációt az adatelemzés folyamán
Az objektumokon (CityObject) és azok részein működik
Függvények a leggyakoribb lépésekre
Inspiráció: tidyverse az R programozási nyelvből
path = os.path.join('data', 'rotterdam_subset.json')
cm = cityjson.load(path)
print(type(cm))
<class 'cjio.cityjson.CityJSON'>
CityObject kiválasztása típus szerint vagy azonosító szerint.
Note that get_cityobjects()
== cm.cityobjects
buildings = cm.get_cityobjects(type='building')
# both Building and BuildingPart objects
buildings_parts = cm.get_cityobjects(type=['building', 'buildingpart'])
r_ids = ['{C9D4A5CF-094A-47DA-97E4-4A3BFD75D3AE}',
'{6271F75F-E8D8-4EE4-AC46-9DB02771A031}']
buildings_ids = cm.get_cityobjects(id=r_ids)
path = os.path.join('data', 'zurich.json')
zurich = cityjson.load(path, transform=True)
def compute_footprint_area(co):
"""Compute the area of the footprint"""
footprint_area = 0
for geom in co.geometry:
# only LoD2 (or higher) objects have semantic surfaces
if geom.lod >= 2.0:
footprints = geom.get_surfaces(type='groundsurface')
# there can be many surfaces with label 'groundsurface'
for i,f in footprints.items():
for multisurface in geom.get_surface_boundaries(f):
for surface in multisurface:
# cast to Shapely polygon
shapely_poly = Polygon(surface)
footprint_area += shapely_poly.area
return footprint_area
for co_id, co in zurich.cityobjects.items():
co.attributes['nr_vertices'] = len(co.get_vertices())
co.attributes['fp_area'] = compute_footprint_area(co)
zurich.cityobjects[co_id] = co
df = zurich.to_dataframe()
df.head()
creationDate | Geomtype | nr_vertices | fp_area | class | Herkunft | QualitaetStatus | FileCreationDate | Region | GebaeudeStatus | |
---|---|---|---|---|---|---|---|---|---|---|
UUID_93fc5bae-4446-4336-9ff8-6679ebfdfde3 | 2017-01-23 | 1.0 | 24 | 65.209763 | NaN | NaN | NaN | NaN | NaN | NaN |
UUID_c9884c4e-1cac-47f5-b88b-6fb074c0ae50 | 2017-01-23 | NaN | 0 | 0.000000 | BB01 | EE_LB_2007 | 1.0 | 2012-02-23 | 2.0 | 1.0 |
UUID_a4a09780-153f-4385-ad19-3a92a6c4eec4 | 2017-01-23 | 1.0 | 38 | 20.784309 | NaN | NaN | NaN | NaN | NaN | NaN |
UUID_ba0bb815-5276-4e35-b4c1-878cbf6ba934 | 2017-01-23 | NaN | 0 | 0.000000 | BB07 | EE_LB_2007 | 1.0 | 2012-02-23 | 2.0 | 1.0 |
UUID_bb1835bc-7437-453f-ac08-885de0503aaa | 2017-01-23 | 1.0 | 87 | 69.363823 | NaN | NaN | NaN | NaN | NaN | NaN |
%matplotlib notebook
model = cluster.DBSCAN(eps=0.2).fit(df_logtransform)
plot_model_results(model, df_logtransform)
for co_id, co in zurich.cityobjects.items():
if co_id in df_subset.index:
ml_results = dict(df_subset.loc[co_id])
else:
ml_results = {'nr_vertices': 'nan', 'fp_area': 'nan', 'dbscan': 'nan'}
new_attrs = {**co.attributes, **ml_results}
co.attributes = new_attrs
zurich.cityobjects[co_id] = co
path_out = os.path.join('data', 'zurich_output.json')
cityjson.save(zurich, path_out)
Dukai Balázs
b.dukai@tudelft.nl
@BalazsDukai
Az előadás anyagai: https://github.com/balazsdukai/foss4g2019
QGIS plugin: github.com/tudelft3d/cityjson-qgis-plugin
Azul – CityJSON megjelenítő Mac-en – keresd az AppStore-ban