#pragma once // brep_ic.hpp — brep.cpp bolunmus TU'lari arasi ic paylasim (PUBLIC DEGIL). // BrepGovde::Icerik tanimi + sar()/sekil() + ortak OCCT yardimcilari. #include "fiko/geometri/brep.hpp" #include #include #include #include #include #include #include #include class BRepBuilderAPI_MakeShape; // OCCT MakeShape kok (Modified/Generated/IsDeleted) namespace fiko::geometri { struct BrepGovde::Icerik { TopoDS_Shape sekil; // Yuz-basi renk (STEP XCAF ColorSurf). Bos → tekduze govde rengi kullanilir. // Indeks = yuz ordinali-1 (ucgenle ile ayni TopExp_Explorer sirasi). std::vector yuzRenkleri; // Ordinal→shape O(1) cache. sekil SABIT olduğundan (BrepGovde her işlemde yeni // Icerik üretir) lazy kurulur, geçerli kalır. TopExp_Explorer sırasıyla BİREBİR // (IndexedMap DEĞİL — o paylaşılan kenarı dedup edip seçim ordinalini bozar). mutable std::vector yuzOrd, kenarOrd, vertexOrd; // Kenar polyline önbelleği (kenarMesh doldurur): kenar-başı [başlangıç,noktaSayı] aralığı + // düz nokta havuzu + kullanılan sapma. Feature sonrası YENİ gövde, değişmeyen kenarları // (IsSame: TShape+Location) eski gövdenin havuzundan kopyalar → devasa modelde kenar // örnekleme yalnız DEĞİŞEN birkaç kenara iner (E0c kenar ayağı). mutable f64 kenarOnbSapma = 0.0; mutable std::vector> kenarOnbAralik; // ordinal-1 → {baş, nokta sayısı} mutable std::vector kenarOnbNokta; // ---- Kalıcı Yüz Adı (KYA): topoloji-değişmez kimlik (CATIA CGM / Parasolid tag ruhu) ---- // Her yüz/kenar/nokta DOĞDUĞUNDA GLOBAL sayaçtan (kaliciKimlikSonraki) BELGE-GENELİNDE benzersiz // u64 etiket alır (indeks = ordinal-1; 0 = atanmamış). Global benzersizlik → referans niteleyici // gerektirmez ("F7" tek başına tek yüz). Etiket işlemlerde GEOMETRİDEN yeniden hesaplanmaz — // history/geometrik eşleme ile TAŞINIR (propagasyon: Faz 2). Ordinal kaysa da "aynı yüz" izlenir. std::vector yuzKid, kenarKid, vertexKid; // ordinal-1 → kalıcı etiket (0 = atanmamış) // Yüz sınıflandırma önbelleği (yuzBilgi sonucu): akıllı seçim (benzerYuzler/paralelYuzler) // her seçimde 10ms+ O(yüz) tarama yapıyordu → cache ile O(yüz) UCUZ karşılaştırma (<1ms). // Import worker'ında (off-main-thread) VEYA ilk benzerYuzler'de bir kez dolar; BrepGovde her // işlemde yeni Icerik ürettiğinden ordinal-kayması riski YOK (cache gövdeyle tutarlı). // alanHazir: non-düzlem yüzün PAHALI alan/merkezi (BRepGProp) bir kez hesaplanıp buraya // yazıldı → sonraki sorgular OCCT'ye gitmez (dev B-spline yüzde çağrı başına ~1.1 s idi). struct YuzOnbGiris { bool ok = false; bool dolu = false; bool alanHazir = false; YuzBilgi bilgi; }; mutable std::vector yuzBilgiOnb; mutable bool yuzBilgiOnbHazir = false; // Kenar önbelleği (yüzle aynı kalıp): kenarBilgi bir kez hesaplar, sonrası kilitli okuma. // LinearProperties+BRepAdaptor genelde ucuz ama dev B-spline kenarında değil; hover/bağlam // bloklamasın diye kenarBilgiHizli yalnız bu tabloyu okur. struct KenarOnbGiris { bool ok = false; bool dolu = false; KenarBilgi bilgi; }; mutable std::vector kenarBilgiOnb; // Tembel doldurma import worker'ı ile main-thread'i AYNI ANDA yakalayabilir (prewarm // worker'da koşuyor) → tablo boyutlama/yazma kilitli. Kilit YALNIZ tablo erişiminde; // pahalı OCCT hesabı kilit DIŞINDA kalır. mutable std::mutex yuzOnbKilit; // Gövde geneli BRepGProp memo (şekil değişmez → bayatlamaz; yeni işlem yeni Icerik üretir). mutable f64 hacimMemo = 0, alanMemo = 0; mutable bool hacimHazir = false, alanHazir = false; // Arka plan alan hesabı sonucunu DOĞRU gövdeye bağlamak için süreç-ömrü benzersiz kimlik // (ham pointer yeniden kullanılabilir → yanlış gövdeye yazma riski olurdu). u64 onbKimlik = 0; }; // Kaba (LOD) tessellation önbelleği (ucgenleKaba): kaynak şekil + mesh'lenmiş bağımsız // kopyası + sapma. Bir SONRAKİ gövdenin kaba çağrısı, değişmeyen yüz üçgenlemelerini bu // kopyadan transfer eder → kaba LOD da yalnız değişen yüzleri üçgenler. Oluşturulduktan // sonra SALT-OKUNUR (worker'lar arası shared_ptr ile güvenle paylaşılır). struct KabaOnbellek { TopoDS_Shape kaynak; // üretildiği gövdenin şekli (yüz eşleme referansı) TopoDS_Shape kopya; // kaba üçgenlemeleri taşıyan bağımsız kopya f64 sapma = 0.0; }; namespace ic { inline BrepGovde sar(const TopoDS_Shape& s) { auto icerik = std::make_unique(); icerik->sekil = s; return BrepGovde(std::move(icerik)); } inline const TopoDS_Shape& sekil(const BrepGovde& g) { return g.icerik()->sekil; } // Ortak koordinat cevirileri (gp_Pnt/gp_Dir → Vec3d, Vec3d → gp_Pnt/gp_Dir). inline Vec3d ceviri(const gp_Pnt& p) { return {p.X(), p.Y(), p.Z()}; } inline Vec3d ceviri(const gp_Dir& d) { return {d.X(), d.Y(), d.Z()}; } inline gp_Pnt pnt(const Vec3d& v) { return gp_Pnt(v.x, v.y, v.z); } inline gp_Dir dir(const Vec3d& v) { return gp_Dir(v.x, v.y, v.z); } inline f64 uzunlukVec(const Vec3d& v) { return std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z); } // Renk propagasyonu: kaynak (renkli) govdenin per-yuz renklerini, bir OCCT // MakeShape algoritmasiyla (pah/yuvarlat/boolean) uretilen yeni govdeye tasir. // algo.Modified/IsDeleted + IsSame ile eski-yuz→yeni-yuz eslesir; yeni uretilen // yuzler kenar-komsu atanmis yuz renginden turer. `yeni` govdeye yuzRenkleriAta // eder (ucgenle ONCESI cagrilmali). Birden fazla kaynak icin ard arda cagrilir // (atanmis yuzler korunur; boolean a+b). Kaynak renksizse hicbir sey yapmaz. void renkPropagasyonu(const BrepGovde& eski, BRepBuilderAPI_MakeShape& algo, BrepGovde& yeni); // ---- Sonuc onbellek (boolean / fillet memoization) ---------------------- // Ayni girdi(ler) + skaler parametre imzasiyla tekrar cagrilan pahali OCCT islemleri // (fuse/cut/common, pah/yuvarlat) yeniden hesaplanmaz. Girdi TopoDS_Shape'leri // SAKLANIR (TShape refcount canli → pointer ABA yok) ve isabet adayinda IsEqual ile // (TShape + Location + Orientation) DOGRULANIR → yanlis isabet imkansiz. thread_local // kullanilmali (worker/main ayri onbellek; kilit yok). Bounded (eski girdi atilir). struct SonucGiris { u64 imza = 0; std::vector girdi; // dogrulama + ABA korumasi icin canli tutulur TopoDS_Shape sonuc; std::vector renkler; bool renkli = false; std::vector yuzRemap; // sonuc yuz ordinali → girdi ordinali (0=yeni) — provenance }; class SonucOnbellek { public: // Girdiler tam eslesir (IsEqual) + imza aynysa saklanan sonucu doner (yoksa nullptr). const SonucGiris* bul(const std::vector& girdi, u64 imza) const { for (const auto& g : giris_) { if (g.imza != imza || g.girdi.size() != girdi.size()) continue; bool esit = true; for (size_t i = 0; i < girdi.size(); ++i) if (!g.girdi[i].IsEqual(girdi[i])) { esit = false; break; } if (esit) return &g; } return nullptr; } void ekle(std::vector girdi, u64 imza, const TopoDS_Shape& sonuc, std::vector renkler, bool renkli, std::vector yuzRemap = {}) { if (giris_.size() >= kMaks) giris_.erase(giris_.begin()); giris_.push_back({imza, std::move(girdi), sonuc, std::move(renkler), renkli, std::move(yuzRemap)}); } private: static constexpr size_t kMaks = 12; std::vector giris_; }; // f64 parametreyi imzaya kar (bit-kesin). inline u64 imzaKat(u64 h, f64 v) { const u64 b = std::bit_cast(v); h ^= b + 0x9e3779b97f4a7c15ull + (h << 6) + (h >> 2); return h; } inline u64 imzaKat(u64 h, u64 v) { h ^= v + 0x9e3779b97f4a7c15ull + (h << 6) + (h >> 2); return h; } } // namespace ic } // namespace fiko::geometri