// keskin_kenar.cpp — dihedral aci esigi ustundeki kenarlar (sayisal rapor). // Sureklilik'in kardesi: o kopuklugu normal ORNEKLEYEREK olcer; bu, kenarin // dihedral acisini + disbukeyligini dogrudan B-Rep'ten (kenarDihedral) alir. // Saf hesap (UI'siz, test edilebilir); hicbir asamada mesh kullanilmaz. #include "fiko/analiz/analiz_hesap.hpp" #include #include #include #include "fiko/geometri/brep.hpp" namespace fiko::analiz { std::vector keskinKenarRapor(const geometri::BrepGovde& g, f64 esikDeg) { std::vector r; if (!g.gecerliMi()) return r; // Ordinal uzayi TopExp_Explorer sirasi → paylasilan kenar IKI kez gezilir // (depo degismezi, degistirilemez). Ayni fiziksel kenari rapor/gorselde bir // kez saymak icin yuz-cifti + kuantalanmis orta nokta anahtar yapilir. std::set> gorulen; // Komsu yuzler TOPLU alinir: tekil kenarKomsuYuzler kenar basina tum modelin // ata haritasini kuruyordu → tarama O(E²) buyuyordu (304 kenarli tarakta 52.7 ms // olculdu; toplu haritayla ~O(E)). Dihedral da hazir yuz ciftiyle cagrilir. const std::vector> komsu = g.tumKenarKomsuYuzler(); for (u32 ke = 1; ke <= komsu.size(); ++ke) { const std::vector& yuzler = komsu[ke - 1]; if (yuzler.size() < 2) continue; // sinir/serbest kenar → dihedral yok const geometri::KenarDihedralBilgi d = g.kenarDihedral(ke, yuzler[0], yuzler[1]); if (!d.gecerli || d.aciDeg <= esikDeg) continue; const std::vector noktalar = g.kenarNoktalari(ke); if (noktalar.empty()) continue; const Vec3d o = noktalar[noktalar.size() / 2]; const auto q = [](f64 v) { return (i64)std::llround(v * 1e4); }; // 0.1 µm if (!gorulen.insert({std::min(yuzler[0], yuzler[1]), std::max(yuzler[0], yuzler[1]), q(o.x), q(o.y), q(o.z)}).second) continue; // ayni kenarin ikinci occurrence'i KeskinKenarBilgi kk; kk.kenarOrdinal = ke; kk.yuzA = yuzler[0]; kk.yuzB = yuzler[1]; kk.aciDeg = d.aciDeg; kk.disbukey = d.disbukey; kk.orta = o; r.push_back(kk); } return r; } } // namespace fiko::analiz