Bir IFC dosyasının IfcOpenShell ile işlenip 3D Tiles olarak coğrafi konumuna oturtulması ve CesiumJS haritasında öznitelikleriyle yayınlanması. Şema, koordinat denetimi, Python ve SQLite kararları, internetten toplanan örnek envanteri.
Sol taraf üretim zamanı (bir kez, sunucuda), sağ uç çalışma zamanı (her ziyaretçide). Coğrafi konum geometriye yazılmaz; yalnızca tileset.json kök dönüşümünde durur. Böylece geometri küçük yerel koordinatlarda kalır ve float32 hassasiyeti korunur.
build.py models.yaml + models.samples.yaml'ı okur, dosyaları küçükten büyüğe sıralar.bim.sqlite'a: models / storeys / elements (psets_json, qtos_json, bbox_json)./api/models'i alır, her modelin tileset.json'ını yükler (küçük).getProperty("GlobalId") → /api/models/{id}/elements/{guid}.Üç bağımsız kontrol yapıldı. (1) Dosyadaki ham değerler, pipeline'ın ürettiği lon/lat ile IfcOpenShell'in kendi auto_xyz2enh dönüşümü ve elle yapılan EPSG dönüşümü üzerinden karşılaştırıldı. (2) tileset.json kök transformu ile tile köşeleri ECEF'e taşınıp pyproj ile harita koordinatlarından üretilen WGS84 konumlarla karşılaştırıldı. (3) Tarayıcıda, Cesium'un çizdiği kapı yüzeyine ışın kesişimi (scene.pickFromRay) atılıp konumu okundu.
| Model | Kaynak değer (dosyada) | Seviye | Boylam | Enlem | h (m) | θ (°) | Not |
|---|---|---|---|---|---|---|---|
| anka-ofis-ankara | IfcMapConversion E 481012.640 N 4417527.684 · EPSG:5255 · xaa/xao = cos/sin 12° | LoGeoRef 50 | 32.7780000 | 39.8917000 | 895.00 | +12.142 | γ = −0.142°; IfcSite ile 0.00 m |
| fzk-haus | IfcSite (49,6,1,566000) (8,26,11,540400) · TrueNorth (0.766, 0.643) | LoGeoRef 20 | 8.4365390 | 49.1004350 | 110.00 | +50.000 | KIT Campus Nord |
| kit-institute | IfcSite (49,9,0,0) (8,43,0,0) · "No real site" | LoGeoRef 20 | 8.7166667 | 49.1500000 | 0.00 | 0.000 | kaba, dosyadaki gibi |
| pcert-arch / str / hvac | E 729013348.83 N 9063992684.70 mm · EPSG:32760 · 60° | LoGeoRef 50 | 179.0801467 | −8.4621999 | 1.30 | +60.306 | MapUnit mm → m; Funafuti (Tuvalu) |
| pcert-bridge | E 729011225.88 N 9063960607.64 mm · 0° | LoGeoRef 50 | 179.0801290 | −8.4624900 | 0.00 | +0.306 | aynı sahne, 33 m güney |
| bsi-georef-utm | E 458657.30 N 5438232.25 · EPSG:25832 · Scale 1000 | LoGeoRef 50 | 8.4336798 | 49.0955510 | 113.70 | +74.728 | γ = −0.428° |
| bsi-georef-gk | E 3458715.92 N 5439966.65 · EPSG:31467 · Scale 1000 | LoGeoRef 50 | 8.4336778 | 49.0955387 | 113.70 | +74.728 | UTM ile 1.38 m (DHDN↔ETRS89 datum) |
| bsi-grid-placement | IfcSite (24,28,0) (54,25,0) → override | Manuel | 32.7787500 | 39.8916500 | 895.00 | +12.000 | models.yaml placement |
IfcProjectedCRS.MapUnit ile metreye çevrilir; PCERT sahnesinde bu mm'dir (729 013 348 mm = 729 013.35 m).get_factors) çıkarılır.scene.pickPosition derinlik tamponu yüzünden 1–5 m sapar; denetimde bu yüzden pickFromRay kullanıldı.IFC motoru Python'da yaşıyor. IfcOpenShell (LGPL-3.0) açık kaynak dünyasının referans IFC çekirdeğidir; C++ motorunun tam Python bağı vardır: geom.iterator (çok iş parçacıklı, OpenCASCADE boolean'ları), util.geolocation (IfcMapConversion, IFC2x3 ePSet, DMS), util.element.get_psets, api.* ile IFC yazma. Ankara örneğini üreten betik de aynı kütüphaneyle yazıldı.
Metadata için düşük seviye kontrol gerekti. Haritada tıklanabilirlik için GLB'ye _FEATURE_ID_0 ve EXT_structural_metadata property table'ı yazmak gerekiyor. IfcConvert CLI bunu üretmez; Python'da iterator çıktısından doğrudan GLB yazmak (numpy + struct, ~200 satır) en kısa yoldu.
Jeodezi ve geometri ekosistemi. pyproj (PROJ: EPSG, meridyen yakınsaması, datum dönüşümü), shapely (ayak izi birleşimi), numpy (ENU/ECEF matrisleri) aynı ortamda. Referans belgedeki üretim mimarisi (Bölüm 4.5) zaten Python işçisi + PostGIS öngörüyor.
Node yalnızca doğrulama için. 3d-tiles-validator ve 3d-tiles-tools npm paketleri npx ile çağrılır; çıktı 0 hata / 0 uyarı.
| Alternatif | Neden seçilmedi |
|---|---|
| web-ifc (JS/WASM) | Tarayıcı odaklı; IfcMapConversion/ePSet yardımcıları ve pset API'si daha zayıf, boolean geometri IfcOpenShell kadar sağlam değil. Sunucu tarafı ön üretim için doğal değil. |
| IfcConvert CLI → GLB | Aynı motor, ama feature ID / metadata eklentisi yazmaz; sonradan gltf-transform ile eklemek ikinci bir araç zinciri demek. |
| xBIM (.NET), IfcPlusPlus (C++) | Georeferans ve pset yardımcıları daha dar; ekip için ek çalışma zamanı. |
| Cesium ion Design Tiler | Tek adımda IFC → 3D Tiles + metadata verir, ama SaaS; ücretsiz plan ticari kullanıma kapalı. Kendi sunucusunda hat istendi. |
| FME | Ticari lisans; kod yazmadan CRS yönetimi için iyi ama demo hedefine göre ağır. |
Demo için SQLite seçildi: kurulum yok (Python standart kütüphanesi), tek dosya, WAL ile eşzamanlı okuma. Kolon adları referans belgedeki bim.* PostGIS şemasıyla aynı tutuldu; geçiş bir COPY ve ST_GeomFromGeoJSON meselesi. Aşağıdaki tablo, üretilen bim.sqlite üzerinde (10 model, 1 296 eleman) fiilen çalıştırılan testlerin sonucudur.
| Yetenek | PostGIS | SQLite (yerleşik) | Demo'daki test sonucu |
|---|---|---|---|
| GlobalId ile nokta sorgu | B-tree indeks | B-tree indeks | 5 000 arama 18 ms → 3.5 µs/sorgu (idx_elements_guid) |
| Pset içinde filtre / arama | JSONB, GIN indeksi, @> | JSON1: json_extract, json_each; JSON üzerine indeks yok (ifade indeksi mümkün) | IsExternal = 1 filtresi 0.7 ms; json_each ile 8 pset adı sayıldı |
| 3B kutu (bbox) kesişimi | GiST + &&, geometry(PolyhedralSurfaceZ) | R*Tree sanal tablo (ENABLE_RTREE), yalnızca kutu | 948 bbox; 6 m × 6 m × kat sorgusu 0.08 ms, 10 eleman |
| 2B poligon ilişkisi (ST_Contains, ST_Intersects) | Tam OGC işlev kümesi | geopoly modülü (düzlem 2B, sınırlı); SpatiaLite ile tam OGC | geopoly_contains_point → fzk-haus bulundu; mod_spatialite bu makinede yok |
| Koordinat dönüşümü (ST_Transform) | PROJ yerleşik | Yok — uygulama tarafında pyproj | Pipeline pyproj kullanıyor |
| 3B katı analizi (hacim, kesişim) | SFCGAL ile | Yok | — |
| OGC API Features / GeoServer / QGIS bağlantısı | Doğrudan | GeoJSON servisi API'den; QGIS SQLite/SpatiaLite okur | /api/models/{id}/footprint GeoJSON |
| Eşzamanlı yazma | MVCC, çok yazıcı | Tek yazıcı; WAL ile okuyucular engellenmez | Açık yazma sırasında okuma OK, ikinci yazıcı "database is locked" |
| Tam metin arama (eleman adı) | tsvector / pg_trgm | FTS5 | FTS5 derlenmiş (ENABLE_FTS5) |
| Bütünlük | — | integrity_check | ok · SQLite 3.53.1 · 3.5 MB |
Birden çok işçi aynı anda model yazacaksa, pset'ler üzerinde indeksli arama isteniyorsa, ayak izleri/hacimler üzerinde gerçek mekânsal analiz (kesişim, tampon, ST_Transform) veya QGIS/GeoServer entegrasyonu gerekiyorsa. Şema hazır: docs/ifc-teknik-referans.md Bölüm 4.5 DDL'i; db.py kolonları birebir eşleşir, footprint_geojson → geometry(Polygon, 4326).
pipeline/fetch_samples.py GitHub API ile beş depoyu listeler, raw/LFS'ten indirir (≤ 60 MB), .ifczip ve KIT zip'lerini açar, SHA-1 ile kopyaları eler ve dosyada IfcMapConversion / IfcSite koordinatı olup olmadığını tarar. Konumu olmayanlar ODTÜ batısındaki vitrin alanına satır satır dizilir; yerleşim DB'ye "auto (showcase grid)" olarak yazılır ve arayüzden düzeltilebilir.
| Kaynak | Model | LoGeoRef 50 | LoGeoRef 20 | Vitrin | Eleman | Üçgen | Şemalar |
|---|---|---|---|---|---|---|---|
| bSI Community-Sample-Test-Files | 66 | 3 | 28 | 35 | 45,550 | 7,908,039 | IFC2X3·62, IFC4X3·3, IFC4·1 |
| bSI IFC4.3 sample models | 37 | 0 | 0 | 37 | 103 | 137,920 | IFC4X3·37 |
| web-ifc public test files | 24 | 1 | 19 | 4 | 96,410 | 15,762,681 | IFC2X3·15, IFC4·6, IFC4X3·2, IFC4X2·1 |
| bSI Sample-Test-Files | 18 | 13 | 1 | 4 | 558 | 89,423 | IFC4·9, IFC4X3·9 |
| bSI InfraRoom unit tests | 18 | 3 | 0 | 15 | 201 | 613,438 | IFC4X3·18 |
| bSI örnek sahnesi | 4 | 4 | 0 | 0 | 81 | 16,961 | IFC4·4 |
| KIT IAI | 2 | 0 | 2 | 0 | 872 | 195,492 | IFC4X2·1, IFC4·1 |
| KIT | 2 | 0 | 2 | 0 | 785 | 64,614 | IFC4·2 |
| geographic-referencing-gk | 1 | 1 | 0 | 0 | 1 | 14 | IFC4X3·1 |
| Ankara | 1 | 1 | 0 | 0 | 70 | 840 | IFC4·1 |
| geographic-referencing-utm | 1 | 1 | 0 | 0 | 1 | 14 | IFC4X3·1 |
| grid-placement | 1 | 0 | 0 | 1 | 10 | 120 | IFC4X3·1 |
| Toplam | 175 | 27 | 52 | 96 | 144,642 | 24,789,556 | IFC2X3·77, IFC4X3·72, IFC4·24, IFC4X2·2 |
| Model | IFC MB | Eleman | Üçgen | Georef |
|---|---|---|---|---|
| cs-clinic-plumbing | 55.8 | 6,587 | 3,352,182 | LoGeoRef 20 |
| wi-viadotto-acerno | 33.0 | 6,538 | 3,004,265 | LoGeoRef 50 |
| issue-053-20181220holter-tower-10 | 177.5 | 60,284 | 2,580,030 | LoGeoRef 20 |
| ltu-a-house-redesign | 181.3 | 6,928 | 2,370,953 | LoGeoRef 20 |
| wi-issue-102-m3d-con-cd | 27.4 | 1,616 | 2,288,856 | vitrin / manuel |
| wi-issue-068-ark-nus-skolebygg | 57.3 | 4,459 | 1,416,713 | LoGeoRef 20 |
| wi-advanced-model | 35.3 | 6,401 | 1,325,648 | LoGeoRef 20 |
| wi-s-office-integrated-design-archi | 31.1 | 3,407 | 1,131,524 | LoGeoRef 20 |
| EPSG | Model | Örnek |
|---|---|---|
| EPSG:32760 | 17 | bsi-building-hvac-cb36a2, pcert-hvac, bsi-building-architecture-412277… |
| EPSG:3878 | 3 | cs-ut-spatialstructure-4, infra-spatialstructure-4, infra-drainagesystem-2 |
| EPSG:5834 | 2 | cs-ut-georef-1, infra-ut-georef-1 |
| EPSG:31467 | 1 | bsi-georef-gk |
| EPSG:5255 | 1 | anka-ofis-ankara |
| EPSG:32633 | 1 | wi-viadotto-acerno |
| EPSG:25832 | 1 | bsi-georef-utm |
| EPSG:28992 | 1 | cs-example-project-location |
cd demo
make venv # uv + Python 3.12 + ifcopenshell, pyproj, shapely, fastapi
make samples # KIT + bSI örnekleri + Ankara üretimi
.venv/bin/python -m pipeline.fetch_samples # internetteki tüm açık örnekler → samples/internet, models.samples.yaml
.venv/bin/python -m pipeline.build --sort-size
make serve # http://localhost:8000
make validate # 3d-tiles-validator
Dosyalar: pipeline/georef.py (koordinat çözümü), pipeline/glb_writer.py (GLB + metadata), pipeline/tileset.py (kök transform), server/app.py (API), web/app.js (CesiumJS), docs/ifc-teknik-referans.md (kaynak belge).