// sureklilik.cpp — Dalga B: yuzey sureklilik G0/G1/G2 (sayisal rapor). // Iki komsu yuzun ORTAK KENARI boyunca ornekleyip pozisyon (G0) / normal-aci // (G1) / egrilik (G2) kopukluk olcer. Saf hesap (UI'siz, test edilebilir); // tumu OCCT tam B-Rep (yuzNoktaNormali analitik normal + yuzKurvatur). #include "fiko/analiz/analiz_hesap.hpp" #include #include #include #include "fiko/geometri/brep.hpp" namespace fiko::analiz { namespace { constexpr f64 PI = 3.14159265358979323846; constexpr f64 RAD2DEG = 180.0 / PI; f64 uzunluk(Vec3d v) { return std::sqrt(v.uzunlukKare()); } // Iki birim-normal arasi aci (derece). Normalize edilir; sifir uzunluk → 0. f64 normalAci(Vec3d a, Vec3d b) { const f64 la = uzunluk(a), lb = uzunluk(b); if (la < 1e-9 || lb < 1e-9) return 0.0; f64 d = (a.x * b.x + a.y * b.y + a.z * b.z) / (la * lb); d = std::clamp(d, -1.0, 1.0); return std::acos(d) * RAD2DEG; } } // namespace std::vector sureklilikRapor(const geometri::BrepGovde& g, f64 g1Esik, f64 g2Esik) { std::vector r; if (!g.gecerliMi()) return r; // Komsu yuzler TOPLU (tekil kenarKomsuYuzler kenar basina tam harita kuruyordu → // O(E²); tarakta 34.8 ms olculdu). Yuz merkez-kurvaturu de kenar basina degil yuz // basina BIR kez (ayni yuz ~4 kenarda tekrar) — sonuc birebir ayni. const std::vector> komsu = g.tumKenarKomsuYuzler(); std::unordered_map kurvaturOnbellek; const auto yuzKurvatur = [&](u32 yuz) -> const geometri::KurvaturBilgi& { auto it = kurvaturOnbellek.find(yuz); if (it == kurvaturOnbellek.end()) it = kurvaturOnbellek.emplace(yuz, geometri::yuzKurvaturMerkez(g, yuz)).first; return it->second; }; for (u32 ke = 1; ke <= komsu.size(); ++ke) { const std::vector& yuzler = komsu[ke - 1]; if (yuzler.size() < 2) continue; // sinir/serbest kenar → sureklilik yok const u32 fa = yuzler[0], fb = yuzler[1]; // Kenar noktalari (ornekleme); bos → olculemez kenar, atla. const std::vector noktalar = g.kenarNoktalari(ke); if (noktalar.empty()) continue; // Ic uc'lardan ornekle (uc noktalarda normal belirsiz olabilir). f64 g1Maks = 0.0, g2Maks = 0.0; u32 ornek = 0; const size_t n = noktalar.size(); for (size_t i = 1; i + 1 < n; i += std::max(1, (n / 8))) { Vec3d na, nb; if (!g.yuzNoktaNormali(fa, noktalar[i], na)) continue; if (!g.yuzNoktaNormali(fb, noktalar[i], nb)) continue; if (na.uzunlukKare() < 1e-12 || nb.uzunlukKare() < 1e-12) continue; g1Maks = std::max(g1Maks, normalAci(na, nb)); ++ornek; } if (ornek == 0) continue; // normal cozulemedi // G2: iki yuzun temsili ortalama-egrilik farki (yuz merkez kurvaturu, onbellekli). const geometri::KurvaturBilgi& ka = yuzKurvatur(fa); const geometri::KurvaturBilgi& kb = yuzKurvatur(fb); if (ka.gecerli && kb.gecerli) g2Maks = std::abs(ka.ortalama - kb.ortalama); SureklilikKenar sk; sk.kenarOrdinal = ke; sk.yuzA = fa; sk.yuzB = fb; sk.g0Poz = 0.0; // paylasilan kenar → pozisyon zaten surekli (saglam B-Rep) sk.g1AciDeg = g1Maks; sk.g2Egrilik = g2Maks; // Derece: pozisyon surekli (G0). Normal aci esik altiysa teget surekli (G1). // Ek olarak egrilik farki esik altiysa egrilik surekli (G2). if (g1Maks <= g1Esik) sk.derece = (g2Maks <= g2Esik) ? 2 : 1; else sk.derece = 0; r.push_back(sk); } return r; } } // namespace fiko::analiz