AnkaGeo · IFC → 3D Tiles → CesiumJS demo · teknik özet

IFC Web Harita Hattı

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.

2026-09-02demo/ · IfcOpenShell 0.8.5 · CesiumJS 1.145 · 3D Tiles 1.1240 IFC dosyası → 175 tileset · 157 881 eleman · 24.8 M üçgen3d-tiles-validator: 0 hata
01 · Uçtan uca akış

Altı adım: dosyadan haritadaki tıklanabilir elemana

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.

ADIM 1

IFC dosyası

ifcopenshell.open()
  • IFC2x3 / IFC4 / IFC4X3_ADD2 STEP (.ifc, .ifczip)
  • Proje uzunluk birimi okunur (mm → 0.001)
  • Pset/Qto değerleri m / m² / m³'e çevrilir, birim ayrı saklanır
  • Kat listesi: IfcBuildingStorey, yükseklik sırasıyla
girdi samples/*.ifc
ADIM 2

Coğrafi referans

pipeline/georef.py · pyproj
  • LoGeoRef 50: IfcMapConversion + IfcProjectedCRS → EPSG → WGS84
  • LoGeoRef 20: IfcSite RefLatitude/Longitude (DMS) + TrueNorth
  • Manuel / vitrin: models.yaml, veri olarak saklanır
çıktı lon, lat, h, θ, anchor
ADIM 3

Geometri

ifcopenshell.geom.iterator
  • use-world-coords: yerleşim zinciri çözülmüş, metre
  • Boolean'lar (açıklıklar) OpenCASCADE ile kesilir
  • IfcSurfaceStyle rengi + saydamlık, kat ataması
çıktı eleman başına üçgen ağı
ADIM 4

GLB + metadata

pipeline/glb_writer.py
  • (x, y, z) → (x, z, −y): +Z yukarı → glTF +Y yukarı
  • COLOR_0, düz normal, _FEATURE_ID_0
  • EXT_mesh_features + EXT_structural_metadata: GlobalId, ifc_class, Name, storey
çıktı storey_00.glb … other.glb
ADIM 5

3D Tiles

pipeline/tileset.py
  • Kök transform = ENU(lon, lat, h) · Rz(θ)
  • Kat başına bir çocuk tile, refine ADD
  • Boş kök, geometricError ≈ 2 × çap: uzaktan indirilmez
çıktı tileset.json (3D Tiles 1.1)
ADIM 6

Yayın

FastAPI + SQLite · CesiumJS
  • /tiles statik, /api/models, /api/…/elements/{guid}
  • Pset/Qto veritabanında, tile'da değil
  • Tıkla → GlobalId → psets; stil; kat filtresi; yerleşim düzelt
çıktı http://localhost:8000

Üretim zamanı (make build)

  1. build.py models.yaml + models.samples.yaml'ı okur, dosyaları küçükten büyüğe sıralar.
  2. Her model: geometri → georef → kat başına GLB → tileset.json → 2B ayak izi.
  3. Öznitelikler bim.sqlite'a: models / storeys / elements (psets_json, qtos_json, bbox_json).
  4. Georeferansı olmayan dosya vitrin alanına (ODTÜ batısı) satır satır dizilir; slot DB'ye yazılır.

Çalışma zamanı (tarayıcı)

  1. Görüntüleyici /api/models'i alır, her modelin tileset.json'ını yükler (küçük).
  2. Kamera yaklaşınca Cesium kat tile'larını (GLB) ister; uzaktayken yalnızca etiket görünür.
  3. Tıklama → Cesium3DTileFeature → getProperty("GlobalId")/api/models/{id}/elements/{guid}.
  4. Yerleşim paneli modelMatrix ile canlı düzeltir; Kaydet → tileset.json kök transformu + DB güncellenir.
02 · Koordinat denetimi

Koordinatlar doğru alındı mı?

Üç 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.

Ham IFC ↔ pipeline
0.00 cm
10 modelin tamamında; IfcOpenShell ve elle hesap aynı noktayı verdi
Kök transform ↔ pyproj
≤ 0.3 cm
Ankara modeli, 4 köşe (24 m × 14 m × 10.8 m); meridyen yakınsaması −0.142° dahil
Cesium'da çizilen kapı ↔ beklenen
32.7781121, 39.8917183
her iki yöntem 7. ondalıkta aynı (≈1 cm); glTF Y-up dönüşümü ve ENU·Rz doğru
ModelKaynak değer (dosyada)SeviyeBoylamEnlemh (m)θ (°)Not
anka-ofis-ankaraIfcMapConversion E 481012.640 N 4417527.684 · EPSG:5255 · xaa/xao = cos/sin 12°LoGeoRef 5032.778000039.8917000895.00+12.142γ = −0.142°; IfcSite ile 0.00 m
fzk-hausIfcSite (49,6,1,566000) (8,26,11,540400) · TrueNorth (0.766, 0.643)LoGeoRef 208.436539049.1004350110.00+50.000KIT Campus Nord
kit-instituteIfcSite (49,9,0,0) (8,43,0,0) · "No real site"LoGeoRef 208.716666749.15000000.000.000kaba, dosyadaki gibi
pcert-arch / str / hvacE 729013348.83 N 9063992684.70 mm · EPSG:32760 · 60°LoGeoRef 50179.0801467−8.46219991.30+60.306MapUnit mm → m; Funafuti (Tuvalu)
pcert-bridgeE 729011225.88 N 9063960607.64 mm · 0°LoGeoRef 50179.0801290−8.46249000.00+0.306aynı sahne, 33 m güney
bsi-georef-utmE 458657.30 N 5438232.25 · EPSG:25832 · Scale 1000LoGeoRef 508.433679849.0955510113.70+74.728γ = −0.428°
bsi-georef-gkE 3458715.92 N 5439966.65 · EPSG:31467 · Scale 1000LoGeoRef 508.433677849.0955387113.70+74.728UTM ile 1.38 m (DHDN↔ETRS89 datum)
bsi-grid-placementIfcSite (24,28,0) (54,25,0) → overrideManuel32.778750039.8916500895.00+12.000models.yaml placement
Doğru yapılan dört ayrıntı
  • Birim: Eastings/Northings IfcProjectedCRS.MapUnit ile metreye çevrilir; PCERT sahnesinde bu mm'dir (729 013 348 mm = 729 013.35 m).
  • Dönüş: θgrid = atan2(XAxisOrdinate, XAxisAbscissa); Cesium'un ENU çerçevesi gerçek kuzeye göre olduğundan meridyen yakınsaması γ (pyproj get_factors) çıkarılır.
  • Scale: geometri IfcOpenShell'den metre olarak geldiği ve Cesium ECEF metrelerinde çizdiği için ölçek uygulanmaz; 0.001 / 1000 birim dönüşümü olarak raporlanır.
  • Eksen: IFC +Z → glTF +Y için (x, z, −y); 3D Tiles çalışma zamanı y-up→z-up uygular, tile çerçevesi x=doğu, y=kuzey, z=yukarı olur.
Bilinçli sınırlar
  • LoGeoRef 20 konum ~10 m mertebesinde kabadır; yön yalnızca TrueNorth'tan gelir, yoksa +Y = kuzey.
  • OrthogonalHeight ortometriktir, Cesium elipsoidal ister; teren yokken "Zemine oturt" h = 0 kullanır, gerçek değer DB'de kalır.
  • Ayak izi ENU teğet düzleminden üretilir; km ölçeğinde projeksiyon ölçeği (0.9996) ihmal edilmiştir.
  • scene.pickPosition derinlik tamponu yüzünden 1–5 m sapar; denetimde bu yüzden pickFromRay kullanıldı.
03 · Karar

Neden Python?

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ı.

AlternatifNeden 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 → GLBAynı 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 TilerTek adımda IFC → 3D Tiles + metadata verir, ama SaaS; ücretsiz plan ticari kullanıma kapalı. Kendi sunucusunda hat istendi.
FMETicari lisans; kod yazmadan CRS yönetimi için iyi ama demo hedefine göre ağır.
04 · Karar

Neden SQLite? PostGIS ile fark ne?

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.

YetenekPostGISSQLite (yerleşik)Demo'daki test sonucu
GlobalId ile nokta sorguB-tree indeksB-tree indeks5 000 arama 18 ms → 3.5 µs/sorgu (idx_elements_guid)
Pset içinde filtre / aramaJSONB, 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şimiGiST + &&, geometry(PolyhedralSurfaceZ)R*Tree sanal tablo (ENABLE_RTREE), yalnızca kutu948 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ümesigeopoly modülü (düzlem 2B, sınırlı); SpatiaLite ile tam OGCgeopoly_contains_point → fzk-haus bulundu; mod_spatialite bu makinede yok
Koordinat dönüşümü (ST_Transform)PROJ yerleşikYok — uygulama tarafında pyprojPipeline pyproj kullanıyor
3B katı analizi (hacim, kesişim)SFCGAL ileYok
OGC API Features / GeoServer / QGIS bağlantısıDoğrudanGeoJSON servisi API'den; QGIS SQLite/SpatiaLite okur/api/models/{id}/footprint GeoJSON
Eşzamanlı yazmaMVCC, çok yazıcıTek yazıcı; WAL ile okuyucular engellenmezAçık yazma sırasında okuma OK, ikinci yazıcı "database is locked"
Tam metin arama (eleman adı)tsvector / pg_trgmFTS5FTS5 derlenmiş (ENABLE_FTS5)
Bütünlükintegrity_checkok · SQLite 3.53.1 · 3.5 MB
Ne zaman PostGIS'e geçmeli

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_geojsongeometry(Polygon, 4326).

05 · Envanter

İnternetten toplanan örnek IFC dosyaları

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.

İşlenen model
175
65 dosya başarısız (aşağıda)
Eleman / üçgen
144,642 / 24,789,556
SQLite elements satırı: 157,881
Coğrafi referans
27 · 52 · 96
LoGeoRef 50 · LoGeoRef 20 · vitrin/manuel
KaynakModelLoGeoRef 50LoGeoRef 20VitrinElemanÜçgenŞemalar
bSI Community-Sample-Test-Files663283545,5507,908,039IFC2X3·62, IFC4X3·3, IFC4·1
bSI IFC4.3 sample models370037103137,920IFC4X3·37
web-ifc public test files24119496,41015,762,681IFC2X3·15, IFC4·6, IFC4X3·2, IFC4X2·1
bSI Sample-Test-Files18131455889,423IFC4·9, IFC4X3·9
bSI InfraRoom unit tests183015201613,438IFC4X3·18
bSI örnek sahnesi44008116,961IFC4·4
KIT IAI2020872195,492IFC4X2·1, IFC4·1
KIT202078564,614IFC4·2
geographic-referencing-gk1100114IFC4X3·1
Ankara110070840IFC4·1
geographic-referencing-utm1100114IFC4X3·1
grid-placement100110120IFC4X3·1
Toplam175275296144,64224,789,556IFC2X3·77, IFC4X3·72, IFC4·24, IFC4X2·2

En büyük modeller (üçgen)

ModelIFC MBElemanÜçgenGeoref
cs-clinic-plumbing55.86,5873,352,182LoGeoRef 20
wi-viadotto-acerno33.06,5383,004,265LoGeoRef 50
issue-053-20181220holter-tower-10177.560,2842,580,030LoGeoRef 20
ltu-a-house-redesign181.36,9282,370,953LoGeoRef 20
wi-issue-102-m3d-con-cd27.41,6162,288,856vitrin / manuel
wi-issue-068-ark-nus-skolebygg57.34,4591,416,713LoGeoRef 20
wi-advanced-model35.36,4011,325,648LoGeoRef 20
wi-s-office-integrated-design-archi31.13,4071,131,524LoGeoRef 20

Gerçek dünyaya oturanlar (LoGeoRef 50, EPSG)

EPSGModelÖrnek
EPSG:3276017bsi-building-hvac-cb36a2, pcert-hvac, bsi-building-architecture-412277…
EPSG:38783cs-ut-spatialstructure-4, infra-spatialstructure-4, infra-drainagesystem-2
EPSG:58342cs-ut-georef-1, infra-ut-georef-1
EPSG:314671bsi-georef-gk
EPSG:52551anka-ofis-ankara
EPSG:326331wi-viadotto-acerno
EPSG:258321bsi-georef-utm
EPSG:289921cs-example-project-location
Başarısız dosyalar (65)
  • RuntimeError — 64: bsi43-segmented-reference-curve, bsi43-structural-curve-member, bsi43-tessellation-with-blob-texture, bsi43-tessellation-with-image-texture, bsi43-tessellation-with-pixel-texture, cs-linearplacement-2, cs-linearplacement-2-4x1, cs-spatialstructure-2…
  • TimeoutError — 1: infra-fixedreferencesweptareasolid-1
06 · Çalıştırma

Komutlar

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).