#include "fiko_test.hpp" #include #include #include #include "fiko/analiz/analiz_hesap.hpp" #include "fiko/analiz/analiz_nesne.hpp" // radiusSerbestKurvatur bayragi #include "fiko/geometri/brep.hpp" using namespace fiko; using namespace fiko::analiz; // ---- Draft acisi: bilinen normal · yon ------------------------------------ FIKO_TEST(draft_acisi_analitik) { // Cekim yonu +Z. Ust yuz normali +Z → draft +90° (aciliyor). FIKO_YAKIN(draftAcisi({0, 0, 1}, {0, 0, 1}), 90.0, 1e-6); // Alt yuz normali -Z → draft -90° (ters/kilit). FIKO_YAKIN(draftAcisi({0, 0, -1}, {0, 0, 1}), -90.0, 1e-6); // Yan yuz normali +X → dik duvar → draft 0°. FIKO_YAKIN(draftAcisi({1, 0, 0}, {0, 0, 1}), 0.0, 1e-6); // 45° egimli normal → draft 45°. const f64 s = 1.0 / std::sqrt(2.0); FIKO_YAKIN(draftAcisi({s, 0, s}, {0, 0, 1}), 45.0, 1e-6); } // ---- Draft rapor: kup 6 yuz, cekim +Z → 1 ust(+90), 1 alt(-90), 4 yan(0) --- FIKO_TEST(draft_rapor_kup) { const geometri::BrepGovde kup = geometri::kutu(10, 10, 10); FIKO_KONTROL(kup.gecerliMi()); Donusumd birim; // kimlik donusum f64 minDraft = 90.0; const auto yuzler = draftRapor(kup, birim, {0, 0, 1}, -0.3, minDraft); FIKO_KONTROL(yuzler.size() == 6); // En kritik draft = -90° (alt yuz, ters). FIKO_YAKIN(minDraft, -90.0, 1e-3); int ters = 0, dik = 0, iyi = 0; for (auto& y : yuzler) { if (y.draftDeg < -0.3) ++ters; else if (std::abs(y.draftDeg) <= 0.3) ++dik; else ++iyi; } FIKO_KONTROL(ters == 1); // yalniz alt yuz FIKO_KONTROL(dik == 4); // 4 yan duvar FIKO_KONTROL(iyi == 1); // ust yuz } // ---- GPU signed-rampa sozlesmesi: draft° → isaretli s = draft/90 ∈ [-1,1] ---- // analiz.frag rampaSigned(s, dikBant) girdisi. Isaret ve dik-bant sinifi analitik // draftAcisi ile TUTARLI olmali (shader ile CPU rapor ayni renk sinifini uretsin). FIKO_TEST(gpu_signed_rampa_sozlesme) { const Vec3d yon{0, 0, 1}; auto s = [&](Vec3d n) { return draftAcisi(n, yon) / 90.0; }; // Ters (kilit): normal -Z → s = -1 (kirmizi bolge). FIKO_YAKIN(s({0, 0, -1}), -1.0, 1e-6); // Dik duvar: normal +X → s = 0 (sari bant merkezi). FIKO_YAKIN(s({1, 0, 0}), 0.0, 1e-6); // Iyi aci: normal +Z → s = +1 (yesil bolge). FIKO_YAKIN(s({0, 0, 1}), 1.0, 1e-6); // Isaret dogru: ters<0 7 → silindir yan yuzu (R=7) kritik olmali. const auto yuzler = radiusRapor(sil, 8.0, kritik); FIKO_KONTROL(!yuzler.empty()); bool silindirBulundu = false; for (auto& y : yuzler) if (y.yaricap > 0) { FIKO_YAKIN(y.yaricap, 7.0, 1e-3); silindirBulundu = true; } FIKO_KONTROL(silindirBulundu); FIKO_KONTROL(kritik >= 1); // Esik 5 < 7 → kritik yok. u32 kritik2 = 0; radiusRapor(sil, 5.0, kritik2); FIKO_KONTROL(kritik2 == 0); } // ---- Radius rapor: TORUS (fillet) → boru/minor yaricap ---------------------- // Regresyon: torus yuzler radiusRapor'da sessizce notr (-1) doner, yani fillet'ler // -radius analizinin ASIL vakasi- hic olculmezdi. Basliktaki yorum torus destegi // vaat ediyordu ama YuzBilgi'de torusMu YOKTU. FIKO_TEST(radius_torus_fillet) { // R7 silindirin UST cember kenarina r=3 fillet → torus (minor=3, major=7−3=4). // NOT: silindir() govdeyi ORIJINDE ORTALAR (z: −10..+10) → "en buyuk merkez.z'li // cember" diye ara; sabit z varsayma (fabrika degisirse test sessizce kaymasin). const geometri::BrepGovde sil = geometri::silindir(7.0, 20.0); FIKO_KONTROL(sil.gecerliMi()); u32 ustCember = 0; f64 enUstZ = -1e9; for (u32 o = 1;; ++o) { geometri::KenarBilgi kb{}; if (!sil.kenarBilgi(o, kb)) break; if (kb.cemberMi && std::abs(kb.yaricap - 7.0) < 1e-3 && kb.merkez.z > enUstZ) { enUstZ = kb.merkez.z; ustCember = o; } } FIKO_KONTROL(ustCember != 0); const geometri::BrepGovde y = geometri::yuvarlat(sil, {ustCember}, 3.0); FIKO_KONTROL(y.gecerliMi()); // Esik 4: torus (R3) kritik, silindir yan yuzu (R7) degil → tam 1 kritik. u32 kritik = 0; const auto yuzler = radiusRapor(y, 4.0, kritik); bool torusBulundu = false; for (auto& f : yuzler) if (f.yaricap > 0 && std::abs(f.yaricap - 3.0) < 1e-3) torusBulundu = true; FIKO_KONTROL(torusBulundu); // minor (3) okundu — major (4) DEGIL FIKO_KONTROL(kritik == 1); } // ---- Radius rapor: serbest (B-spline) yuz + ayar bayragi -------------------- FIKO_TEST(radius_serbest_kurvatur_bayragi) { // Degisken-yaricapli fillet → tasiyici yuzey B-spline (analitik yaricap YOK). const geometri::BrepGovde g = geometri::kutu(10, 10, 10); const geometri::BrepGovde y = geometri::yuvarlatDegisken(g, /*kenar*/ 1, 0.2, 0.5); FIKO_KONTROL(y.gecerliMi()); const bool eski = radiusSerbestKurvatur(); // KAPALI = eski davranis: kup duzlemleri + serbest fillet → hicbiri olculmez. radiusSerbestKurvaturAyarla(false); u32 k0 = 0; const auto kapali = radiusRapor(y, 1.0, k0); for (auto& f : kapali) FIKO_KONTROL(f.yaricap < 0); FIKO_KONTROL(k0 == 0); // ACIK: fillet yuzu asal egrilikten olculur (r1=0.2..r2=0.5 araliginda). radiusSerbestKurvaturAyarla(true); u32 k1 = 0; const auto acik = radiusRapor(y, 1.0, k1); bool serbestOlculdu = false; for (auto& f : acik) if (f.yaricap > 0.15 && f.yaricap < 0.6) serbestOlculdu = true; FIKO_KONTROL(serbestOlculdu); FIKO_KONTROL(k1 >= 1); // esik 1.0 > fillet R → kritik radiusSerbestKurvaturAyarla(eski); // global ayar: sonraki testlere sizmasin } // ---- K-1 regresyon: silindir draft, cekim EKSENE DIK → degisken (karisik) ---- // Silindir ekseni +Z. Cekim +X. Yan yuz radyal normalleri +X'e bakan (+90°) ile // -X'e bakan (-90°) arasinda tarar → draft NOKTADAN NOKTAYA degisir. Eski kod tek // "ortalama" radyal (≈0) verip yanlis raporlardi; artik per-nokta min/maks. FIKO_TEST(draft_silindir_degisken) { const geometri::BrepGovde sil = geometri::silindir(7.0, 20.0); FIKO_KONTROL(sil.gecerliMi()); sil.ucgenle({0.7f, 0.7f, 0.7f}); // yuz ornek noktalari icin ucgenleme Donusumd birim; f64 minDraft = 90.0; const auto yuzler = draftRapor(sil, birim, {1, 0, 0}, -0.3, minDraft); FIKO_KONTROL(!yuzler.empty()); // Yan silindir yuzu bulunmali ve KARISIK (degisken draft) isaretli olmali. bool karisikBulundu = false; for (auto& y : yuzler) if (y.karisikMi) { karisikBulundu = true; // Aralik genis: yaklasik [-90, +90] taramali (radyal normal tum yonlere). FIKO_KONTROL(y.draftMax - y.draftMin > 90.0); FIKO_KONTROL(y.draftMin < -60.0); // -X'e bakan yer ters FIKO_KONTROL(y.draftMax > 60.0); // +X'e bakan yer aciliyor FIKO_KONTROL(y.draftDeg == y.draftMin); // temsili = en kritik FIKO_KONTROL(y.tersMi); // araligin bir yeri ters esik altinda } FIKO_KONTROL(karisikBulundu); } // ---- K-1 regresyon: silindir draft, cekim EKSEN BOYUNCA → sabit ~0° dik duvar -- // Cekim +Z (eksenle ayni). Yan yuz radyal normalleri hep eksene dik → draft ~0° // her yerde (sabit, karisik degil). Per-nokta hesap bunu dogru vermeli. FIKO_TEST(draft_silindir_eksen_boyunca) { const geometri::BrepGovde sil = geometri::silindir(7.0, 20.0); sil.ucgenle({0.7f, 0.7f, 0.7f}); Donusumd birim; f64 minDraft = 90.0; const auto yuzler = draftRapor(sil, birim, {0, 0, 1}, -0.3, minDraft); for (auto& y : yuzler) if (y.draftMax - y.draftMin < 5.0 && std::abs(y.draftMin) < 5.0) { // Yan yuz: dik duvar, sabit ~0°, karisik degil. FIKO_KONTROL(!y.karisikMi); FIKO_YAKIN(y.draftDeg, 0.0, 2.0); } } // ---- K-2 regresyon: kure draft → her yerde degisken (tam [-90,+90] tarar) ----- FIKO_TEST(draft_kure_degisken) { const geometri::BrepGovde kr = geometri::kure(8.0); FIKO_KONTROL(kr.gecerliMi()); kr.ucgenle({0.7f, 0.7f, 0.7f}); Donusumd birim; f64 minDraft = 90.0; const auto yuzler = draftRapor(kr, birim, {0, 0, 1}, -0.3, minDraft); FIKO_KONTROL(!yuzler.empty()); bool karisik = false; for (auto& y : yuzler) if (y.karisikMi) { karisik = true; FIKO_KONTROL(y.draftMax - y.draftMin > 90.0); // genis yayilim } FIKO_KONTROL(karisik); // En kritik draft belirgin negatif (ters) olmali (alt yarikure). FIKO_KONTROL(minDraft < -30.0); } // ---- K-4 regresyon: borulu (halka) cidar → egri yuzden sabit ~2mm kalinlik ----- // Dis R=10, ic R=8 silindir farki → 2mm cidarli boru. Dis silindir yuzunden ic // isin → ic silindir duvarina 2mm. Eski kod silindiri ATLIYORDU (hic olcmuyordu). FIKO_TEST(kalinlik_boru_egri_cidar) { const geometri::BrepGovde dis = geometri::silindir(10.0, 30.0); const geometri::BrepGovde ic = geometri::silindir(8.0, 40.0); const geometri::BrepGovde boru = geometri::cikarma(dis, ic); FIKO_KONTROL(boru.gecerliMi()); boru.ucgenle({0.7f, 0.7f, 0.7f}); f64 mn = 1e6, mx = 0; const auto noktalar = kalinlikRapor(boru, 1e5, mn, mx); FIKO_KONTROL(!noktalar.empty()); // egri cidar artik olculuyor (eski: bos olabilir) // Silindirik cidar sabit ~2mm. Ust/alt halka duz yuzler daha buyuk deger verir; // en kucuk (cidar) ~2mm olmali. FIKO_YAKIN(mn, 2.0, 0.5); } // ---- Kesit egrisi: 20x20x20 kup, XY duzlemi (z=0) → kapali kare kontur ------- FIKO_TEST(kesit_kup_kare) { const geometri::BrepGovde kup = geometri::kutu(20, 20, 20); FIKO_KONTROL(kup.gecerliMi()); const auto egriler = geometri::brepKesit(kup, {0, 0, 0}, {0, 0, 1}, 0.1); FIKO_KONTROL(!egriler.empty()); // Kesit noktalarinin bbox'i ~ [-10,10] x [-10,10], z ~ 0. f64 minx = 1e9, maxx = -1e9, miny = 1e9, maxy = -1e9, maxz = 0; size_t nokta = 0; for (auto& p : egriler) for (auto& q : p) { minx = std::min(minx, q.x); maxx = std::max(maxx, q.x); miny = std::min(miny, q.y); maxy = std::max(maxy, q.y); maxz = std::max(maxz, std::abs(q.z)); ++nokta; } FIKO_KONTROL(nokta >= 4); FIKO_YAKIN(minx, -10.0, 0.5); FIKO_YAKIN(maxx, 10.0, 0.5); FIKO_YAKIN(miny, -10.0, 0.5); FIKO_YAKIN(maxy, 10.0, 0.5); FIKO_KONTROL(maxz < 0.5); // kesit z~0 duzleminde } // ---- Et kalinligi: 4mm kalin plaka → ust yuzden alt yuze ~4mm ---------------- FIKO_TEST(kalinlik_plaka) { // Ince plaka: 40 x 40 x 4 (z = kalinlik). const geometri::BrepGovde plaka = geometri::kutu(40, 40, 4); FIKO_KONTROL(plaka.gecerliMi()); f64 mn = 1e6, mx = 0; const auto noktalar = kalinlikRapor(plaka, 1e5, mn, mx); FIKO_KONTROL(!noktalar.empty()); // Ust/alt duz yuzlerinden atilan ic isin → karsi duvara ~4mm. FIKO_YAKIN(mn, 4.0, 0.5); } // ---- noktaKalinlik dogrudan: kup ic isin -------------------------------------- FIKO_TEST(nokta_kalinlik_kup) { const geometri::BrepGovde kup = geometri::kutu(10, 10, 10); // Ust yuz merkezi (0,0,5), disa normal +Z → ic isin -Z → karsi (alt) yuze 10mm. const f64 k = geometri::noktaKalinlik(kup, {0, 0, 5}, {0, 0, 1}); FIKO_YAKIN(k, 10.0, 0.2); } // ============================================================================ // DALGA B — Geometrik yuzey kalite (Kurvatur / Sureklilik) // ============================================================================ // ---- Kurvatur analitik: kure Gauss = 1/R² ----------------------------------- // Yaricap R kure → Gauss egriligi K = 1/R², |ortalama| = 1/R (BRepLProp analitik, // mesh-yogunluga duyarsiz). R=8 → K = 1/64 = 0.015625. FIKO_TEST(kurvatur_kure_gauss) { const f64 R = 8.0; const geometri::BrepGovde kr = geometri::kure(R); FIKO_KONTROL(kr.gecerliMi()); const geometri::KurvaturBilgi kb = geometri::yuzKurvaturMerkez(kr, 1); FIKO_KONTROL(kb.gecerli); FIKO_YAKIN(std::abs(kb.gauss), 1.0 / (R * R), 1e-4); // K = 1/R² FIKO_YAKIN(std::abs(kb.ortalama), 1.0 / R, 1e-3); // |H| = 1/R FIKO_YAKIN(std::abs(kb.kMin), 1.0 / R, 1e-3); // asal egrilik = 1/R FIKO_YAKIN(std::abs(kb.kMaks), 1.0 / R, 1e-3); } // ---- Kurvatur analitik: silindir Gauss = 0 ---------------------------------- // Silindir developable → Gauss = 0 (bir asal egrilik 1/R, digeri 0). FIKO_TEST(kurvatur_silindir_gauss_sifir) { const f64 R = 7.0; const geometri::BrepGovde sil = geometri::silindir(R, 20.0); FIKO_KONTROL(sil.gecerliMi()); // Yan silindir yuzunu bul (Gauss ~ 0, |ortalama| ~ 1/(2R)). bool silBulundu = false; for (u32 ord = 1;; ++ord) { geometri::YuzBilgi yb; if (!sil.yuzBilgi(ord, yb)) break; if (!yb.silindirMi) continue; const geometri::KurvaturBilgi kb = geometri::yuzKurvaturMerkez(sil, ord); FIKO_KONTROL(kb.gecerli); FIKO_YAKIN(kb.gauss, 0.0, 1e-5); // developable → K = 0 FIKO_YAKIN(std::abs(kb.ortalama), 1.0 / (2 * R), 1e-3); // |H| = 1/(2R) silBulundu = true; } FIKO_KONTROL(silBulundu); } // ---- Kurvatur analitik: duzlem (kup yuzu) Gauss = 0, ortalama = 0 ------------ FIKO_TEST(kurvatur_duzlem_sifir) { const geometri::BrepGovde kup = geometri::kutu(10, 10, 10); const geometri::KurvaturBilgi kb = geometri::yuzKurvaturMerkez(kup, 1); FIKO_KONTROL(kb.gecerli); FIKO_YAKIN(kb.gauss, 0.0, 1e-6); FIKO_YAKIN(kb.ortalama, 0.0, 1e-6); } // ---- Kurvatur rapor: kup 6 yuz, hepsi duzlem → tum degerler 0 --------------- FIKO_TEST(kurvatur_rapor_kup) { const geometri::BrepGovde kup = geometri::kutu(10, 10, 10); f64 mn = 0, mx = 0; const auto yuzler = kurvaturRapor(kup, KurvaturOlcu::Gauss, mn, mx); FIKO_KONTROL(yuzler.size() == 6); for (auto& y : yuzler) FIKO_YAKIN(y.deger, 0.0, 1e-6); FIKO_YAKIN(mn, 0.0, 1e-6); FIKO_YAKIN(mx, 0.0, 1e-6); } // ---- Sureklilik: kup komsu yuzler DIK (G1 aci ~90°, kirik/G0) --------------- // Kupun her ic kenari 2 dik yuzu paylasir → normaller arasi aci ~90° → keskin // (G1 saglanmaz, derece 0). 12 kenar. FIKO_TEST(sureklilik_kup_keskin) { const geometri::BrepGovde kup = geometri::kutu(10, 10, 10); FIKO_KONTROL(kup.gecerliMi()); const auto kenarlar = sureklilikRapor(kup, 5.0); // g1Esik 5° → 90° kirik // OCCT kutu topolojisi: her fiziksel kenar 2 yuz-cifti girisi → paylasilan // kenar sayisi topolojiye bagli; onemli olan HEPSININ dik (90°/keskin) olmasi. FIKO_KONTROL(!kenarlar.empty()); int keskin = 0; for (auto& k : kenarlar) { FIKO_YAKIN(k.g1AciDeg, 90.0, 2.0); // dik yuzler → ~90° if (k.derece == 0) ++keskin; } FIKO_KONTROL(keskin == (int)kenarlar.size()); // hepsi keskin (G1 degil) } // ---- Sureklilik: kure seam (dikis) kenari TEGET → G1 aci ~0° ----------------- // Kure = tek periyodik yuz; meridyen seam kenarinin iki tarafi da AYNI yuzun // devami → normaller cakisir → G1 aci ~0 (teget surekli, derece >= 1). Iki-teget // yuz G1≈0 sozlesmesi (analitik pürüzsüz yüzey → keskin degil). FIKO_TEST(sureklilik_kure_seam_teget) { const geometri::BrepGovde kr = geometri::kure(8.0); FIKO_KONTROL(kr.gecerliMi()); const auto kenarlar = sureklilikRapor(kr, 5.0); // Paylasilan (2-yuz komsulu) her kenar teget olmali (pürüzsüz kure). bool tegetVar = false; for (auto& k : kenarlar) { FIKO_YAKIN(k.g1AciDeg, 0.0, 5.0); // teget surekli (keskin degil) FIKO_KONTROL(k.derece >= 1); tegetVar = true; } FIKO_KONTROL(tegetVar); // en az bir ic/seam kenar olculdu } // ---- Keskin kenar: kup → 12 dik (~90°) disbukey kenar ------------------------ // Dihedral aci dogrudan B-Rep'ten (kenarDihedral); esik 30° altinda kalan // hicbir kenar yok, kupun 12 kenari da keskin ve DISBUKEY olmali. FIKO_TEST(keskin_kenar_kup) { const geometri::BrepGovde kup = geometri::kutu(10, 10, 10); FIKO_KONTROL(kup.gecerliMi()); const auto kenarlar = keskinKenarRapor(kup, 30.0); FIKO_KONTROL(kenarlar.size() == 12); for (auto& k : kenarlar) { FIKO_YAKIN(k.aciDeg, 90.0, 2.0); // dik yuzler → ~90° FIKO_KONTROL(k.disbukey); FIKO_KONTROL(k.yuzA != 0 && k.yuzB != 0 && k.yuzA != k.yuzB); // Orta nokta kupun uzerinde (kutu orijinde ortali → |koordinat| <= 5). FIKO_KONTROL(std::abs(k.orta.x) <= 5.001 && std::abs(k.orta.y) <= 5.001 && std::abs(k.orta.z) <= 5.001); } } // ---- Keskin kenar: esik 95° > 90° → kupte keskin kenar yok -------------------- FIKO_TEST(keskin_kenar_kup_esik_ustu) { const geometri::BrepGovde kup = geometri::kutu(10, 10, 10); FIKO_KONTROL(kup.gecerliMi()); const auto kenarlar = keskinKenarRapor(kup, 95.0); FIKO_KONTROL(kenarlar.empty()); } // ---- Keskin kenar: kure seam TEGET (~0°) → keskin kenar yok ------------------- // Seam kenarinin iki tarafi ayni periyodik yuzun devami → dihedral ~0. FIKO_TEST(keskin_kenar_kure_teget) { const geometri::BrepGovde kr = geometri::kure(8.0); FIKO_KONTROL(kr.gecerliMi()); const auto kenarlar = keskinKenarRapor(kr, 30.0); FIKO_KONTROL(kenarlar.empty()); } // ---- Keskin kenar → pah onerisi deger zinciri (uçtan uca motor) -------------- // Panel onerisinin motor karsiligi: keskin kenarlari bul → hepsine pahla → // yeniden analiz. 90° kenarlar C1 pahla 45°'lik iki kenara boluner: 50° esikte // temiz (0 keskin), 30° esikte pah kenarlari gorunur (>0) — esik semantigi dogru. FIKO_TEST(keskin_kenar_pah_sonrasi_temiz) { const geometri::BrepGovde kup = geometri::kutu(10, 10, 10); const auto once = keskinKenarRapor(kup, 50.0); FIKO_KONTROL(once.size() == 12); std::vector kenarlar; for (const auto& k : once) if (k.disbukey) kenarlar.push_back(k.kenarOrdinal); FIKO_KONTROL(kenarlar.size() == 12); const geometri::BrepGovde pahli = geometri::pahla(kup, kenarlar, 1.0); FIKO_KONTROL(pahli.gecerliMi()); FIKO_KONTROL(keskinKenarRapor(pahli, 50.0).empty()); // 90°'lar gitti FIKO_KONTROL(!keskinKenarRapor(pahli, 30.0).empty()); // 45° pah kenarlari duruyor } // ---- Pah onerisi: SIGMAYAN boy → kose-clamp (kademeli kucultme) KILIDI ------- // pahla 0.72 kademeli kucultme + zaman kutusu tasir (fillet ile ayni — anayasada // OZELLIK). Ince plakada (kalinlik 2) C=5 sigmaz; beklenen: TAM BASARISIZLIK DEGIL, // kucultulmus boyla gecerli sonuc (5→3.6→2.59→1.87 sigar). Oneri cipinin "buyuk boy // verdim diye hicbir sey olmadi" durumuna dusmedigini kilitler. FIKO_TEST(keskin_kenar_pah_clamp_ince_plaka) { const geometri::BrepGovde plaka = geometri::kutu(10, 10, 2); const auto keskin = keskinKenarRapor(plaka, 50.0); FIKO_KONTROL(keskin.size() == 12); std::vector kenarlar; for (const auto& k : keskin) kenarlar.push_back(k.kenarOrdinal); const geometri::BrepGovde pahli = geometri::pahla(plaka, kenarlar, 5.0); FIKO_KONTROL(pahli.gecerliMi()); // clamp devrede: bos DEGIL // Malzeme kirildi (hacim kucluldu) ama govde yasiyor. const f64 v0 = plaka.hacim(), v1 = pahli.hacim(); FIKO_KONTROL(v1 > 0.0 && v1 < v0); } // ---- Tum analiz tipleri: PERF olcumu (tarak — hangi tip pahali?) ------------- FIKO_TEST(analiz_perf_tum_tipler) { geometri::BrepGovde g = geometri::kutu(100, 20, 6); for (int i = 0; i < 10; ++i) { Donusumd t; t.konum = {-45.0 + i * 10.0, 0.0, 6.0}; g = geometri::birlesim(g, geometri::donusumUygula(geometri::kutu(4, 20, 6), t)); } FIKO_KONTROL(g.gecerliMi()); const auto olc = [](const char* ad, auto&& fn) { const auto t0 = std::chrono::steady_clock::now(); const size_t n = fn(); const f64 ms = std::chrono::duration( std::chrono::steady_clock::now() - t0).count(); std::printf("[perf-tipler] %-10s %5zu oge %7.1f ms\n", ad, n, ms); return n; }; f64 minD = 0, mn = 0, mx = 0; u32 kritik = 0; Donusumd birim; FIKO_KONTROL(olc("draft", [&] { return draftRapor(g, birim, {0, 0, 1}, 0.0, minD).size(); }) > 0); FIKO_KONTROL(olc("radius", [&] { return radiusRapor(g, 3.0, kritik).size(); }) > 0); FIKO_KONTROL(olc("kurvatur", [&] { return kurvaturRapor(g, KurvaturOlcu::Ortalama, mn, mx).size(); }) > 0); FIKO_KONTROL(olc("kalinlik", [&] { return kalinlikRapor(g, 100.0, mn, mx).size(); }) > 0); } // ---- Derin kopya ordinal kararliligi (async hesap temeli) -------------------- // Async yol worker'a govdeDerinKopya verir; rapor ordinalleri CANLI govdeye // uygulanir. Kopyanin TopExp sirasi kaynagla birebir olmali — degilse async // sonuc yanlis kenari isaret eder. (BRepBuilderAPI_Copy yapi sirasini korur; // bu test o varsayimi KILITLER.) // ---- govdeKalinlikOrnekle: TEK Load, tum yuzler, sirali ordinal ciktisi ------ // Bu API yuz basina Load yapan yolun toplu ikizi: ayni ornem SAYISI, tek kurulum. // Kutu 6 yuz; izgara n → 6 * n * n ornek beklenir (kirpma yok → hepsi gecerli). FIKO_TEST(kalinlik_govde_toplu_izgara_kapsam) { const geometri::BrepGovde g = geometri::kutu(20, 30, 40); FIKO_KONTROL(g.gecerliMi()); for (const u32 iz : {2u, 4u, 8u}) { std::vector np; std::vector nk; std::vector nord; const u32 n = geometri::govdeKalinlikOrnekle(g, iz, 1e5, np, nk, nord); FIKO_KONTROL(n == np.size()); FIKO_KONTROL(n == nk.size()); FIKO_KONTROL(n == nord.size()); // Kutu tam kutu → kirpma YOK → her hucre iceride → 6 yuz * iz^2 ornek. FIKO_KONTROL(n == 6u * iz * iz); // Ordinal SIRALI (tek gecisle toplama buna dayanir) ve 1..6 araliginda. bool sirali = nord.size() > 1; for (size_t i = 1; i < nord.size(); ++i) if (nord[i] < nord[i - 1]) { sirali = false; break; } FIKO_KONTROL(sirali); if (!nord.empty()) { FIKO_KONTROL(nord.front() >= 1u); FIKO_KONTROL(nord.back() <= 6u); } } } // ---- govdeKalinlikOrnekle == yuzKalinlikOrnekle (yuz yuz ayni sonuc) --------- // Toplu API davranis degistirmemeli: ayni yuzu iki yolla ornekle, KARSILASTIR. FIKO_TEST(kalinlik_govde_toplu_yuz_yuz_ayni) { const geometri::BrepGovde g = geometri::kutu(20, 30, 40); std::vector bp; std::vector bk; std::vector bo; geometri::govdeKalinlikOrnekle(g, 4, 1e5, bp, bk, bo); FIKO_KONTROL(!bk.empty()); // Ordinal 1..6 için tek tek; her biri toplu çıktıyla AYNI ızgarada örneklenmiş olmalı. for (u32 ord = 1; ord <= 6; ++ord) { std::vector p; std::vector k; const u32 n = geometri::yuzKalinlikOrnekle(g, ord, 4, 1e5, p, k); f64 yMinToplu = 1e30, yMinTek = 1e30; for (size_t i = 0; i < bo.size(); ++i) if (bo[i] == ord) yMinToplu = std::min(yMinToplu, bk[i]); for (const f64 v : k) yMinTek = std::min(yMinTek, v); if (n == 0) { FIKO_KONTROL(yMinToplu > 1e29); continue; } FIKO_KONTROL(yMinToplu < 1e29); FIKO_YAKIN(yMinToplu, yMinTek, 1e-9); // aynı örnekler, aynı min } } // ---- Geçersiz govde → toplu API bos doner (cokme YOK) ----------------------- FIKO_TEST(kalinlik_govde_toplu_gecersiz_bos) { const geometri::BrepGovde bos; std::vector np; std::vector nk; std::vector nord; FIKO_KONTROL(geometri::govdeKalinlikOrnekle(bos, 4, 1e5, np, nk, nord) == 0); FIKO_KONTROL(np.empty() && nk.empty() && nord.empty()); } // ---- PERF: maliyet ornek sayisiyla LINEER olmali (karesel degil) ----------- // Eski yol her hucrede BRepClass_FaceClassifier::Perform agac gezintisi yapiyordu // (kutu yuzunde hepsi bos sonuc = saf israf). Kirpma kisayolu sonrasi hucre basina // maliyet isin-kesisime dustu. Amac regresyon kilidi: izgara 8→16 (4x ornek) sure // ~4x'ten CAT uygun olmali (asiri sabit olmamali) VE asiri hizli olmamali. FIKO_TEST(kalinlik_perf_izgara_dogrusal) { const geometri::BrepGovde g = geometri::kutu(200, 200, 200); const auto olc = [&](u32 iz) { const auto t0 = std::chrono::steady_clock::now(); std::vector np; std::vector nk; std::vector nord; const u32 n = geometri::govdeKalinlikOrnekle(g, iz, 1e5, np, nk, nord); return std::pair{std::chrono::duration( std::chrono::steady_clock::now() - t0).count(), n}; }; const auto [ms4, n4] = olc(4); const auto [ms16, n16] = olc(16); std::printf("[perf] govdeKalinlikOrnekle iz4=%u orn %.1fms | iz16=%u orn %.1fms\n", n4, ms4, n16, ms16); FIKO_KONTROL(n4 > 0 && n16 > 0); // Izgara 4 -> 16 eksen basina 4x; ornek sayisi KARESEL olur (6 yuz × iz^2): // 4x4=16/yuz → 16x16=256/yuz = 16x. Onceki test 4x bekliyordu (yanlis). FIKO_KONTROL(n16 == 16u * n4); // Zaman orani ornkle kuyrugunda kalsin: 16x ornek → en fazla ~24x sure (kaba tavan). // Ortulama maliyet/ornek buyurse (asiri sabit = veri hazirligi isabeti) kirilir. FIKO_KONTROL(ms16 <= ms4 * 24.0 + 5.0); // Ayrica: maliyet/ornek IKINCI calistirmada artmamali (cache/yerellik etkisi). const auto [ms4b, n4b] = olc(4); FIKO_KONTROL(n4b == n4); FIKO_KONTROL(ms4b <= ms4 * 3.0 + 5.0); } // ---- "En ince 6 / en kalin 3" rapor listesi cakismaz ----------------------- // Eski dongu `for (i = size; i-- > 0 && i+3 >= size;)` idi: yuz sayisi 9'dan // kucukken en ince 6 ile en kalin 3 AYNI yuzleri iki kez raporlardi ve en kalin // yerine ortadakileri yaziyordu. Bu test indirgeme mantigini kilitler. FIKO_TEST(kalinlik_rapor_ince_kalin_ayri) { const geometri::BrepGovde g = geometri::kutu(20, 30, 40); // 6 yuz (< 9) f64 mn = 0, mx = 0; const auto noktalar = kalinlikRapor(g, 1e5, mn, mx); FIKO_KONTROL(!noktalar.empty()); // Kutu: her yuzun kalinligi karsi boyuta esit → 6 yuz = 6 nokta grubu. // 20, 30, 40 boyutlarindan biri min, biri max olarak gorunmeli. FIKO_YAKIN(mn, 20.0, 1e-2); FIKO_YAKIN(mx, 40.0, 1e-2); // Eski 1.5x filtresi olmadan ham ortalama da ayni (duz yuz, tek deger). FIKO_KONTROL(mn > 0.0 && mx >= mn); } FIKO_TEST(keskin_kenar_derin_kopya_ordinal) { geometri::BrepGovde g = geometri::kutu(60, 20, 6); for (int i = 0; i < 4; ++i) { Donusumd t; t.konum = {-24.0 + i * 15.0, 0.0, 6.0}; g = geometri::birlesim(g, geometri::donusumUygula(geometri::kutu(4, 20, 6), t)); } FIKO_KONTROL(g.gecerliMi()); const geometri::BrepGovde kopya = geometri::govdeDerinKopya(g); FIKO_KONTROL(kopya.gecerliMi()); const auto orijinal = keskinKenarRapor(g, 30.0); const auto kopyadan = keskinKenarRapor(kopya, 30.0); FIKO_KONTROL(!orijinal.empty()); FIKO_KONTROL(orijinal.size() == kopyadan.size()); for (size_t i = 0; i < orijinal.size() && i < kopyadan.size(); ++i) { FIKO_KONTROL(orijinal[i].kenarOrdinal == kopyadan[i].kenarOrdinal); FIKO_KONTROL(orijinal[i].disbukey == kopyadan[i].disbukey); FIKO_YAKIN(orijinal[i].aciDeg, kopyadan[i].aciDeg, 1e-6); FIKO_YAKIN(orijinal[i].orta.x, kopyadan[i].orta.x, 1e-9); } } // ---- Olcek dogrulamasi: 30 disli tarak (~4x kenar) — lineerlik kontrolu ------ // Toplu harita sonrasi keskin/sureklilik ~O(E) olmali; kuadratik kalsaydi 4x // kenar ~16x sure verirdi. Sureler stdout'a (async karari icin veri). FIKO_TEST(analiz_perf_olcek_30dis) { const auto tb0 = std::chrono::steady_clock::now(); geometri::BrepGovde g = geometri::kutu(300, 20, 6); for (int i = 0; i < 30; ++i) { Donusumd t; t.konum = {-145.0 + i * 10.0, 0.0, 6.0}; g = geometri::birlesim(g, geometri::donusumUygula(geometri::kutu(4, 20, 6), t)); } FIKO_KONTROL(g.gecerliMi()); const f64 insaMs = std::chrono::duration( std::chrono::steady_clock::now() - tb0).count(); u32 kenarSayi = 0; for (u32 o = 1;; ++o) { if (g.kenarNoktalari(o).empty()) break; ++kenarSayi; } const auto t0 = std::chrono::steady_clock::now(); const auto keskin = keskinKenarRapor(g, 30.0); const auto t1 = std::chrono::steady_clock::now(); const auto surek = sureklilikRapor(g, 5.0, 0.1); const auto t2 = std::chrono::steady_clock::now(); std::printf("[perf-olcek] insa %.0f ms | %u kenar | keskin %zu adet %.1f ms | " "sureklilik %zu kenar %.1f ms\n", insaMs, (unsigned)kenarSayi, keskin.size(), std::chrono::duration(t1 - t0).count(), surek.size(), std::chrono::duration(t2 - t1).count()); FIKO_KONTROL(kenarSayi >= 300); FIKO_KONTROL(keskin.size() >= 60); FIKO_KONTROL(surek.size() >= 300); } // ---- Sureklilik: PERF olcumu (tarak govde — keskin perf ile ayni geometri) --- FIKO_TEST(sureklilik_perf_tarak) { geometri::BrepGovde g = geometri::kutu(100, 20, 6); for (int i = 0; i < 10; ++i) { Donusumd t; t.konum = {-45.0 + i * 10.0, 0.0, 6.0}; g = geometri::birlesim(g, geometri::donusumUygula(geometri::kutu(4, 20, 6), t)); } FIKO_KONTROL(g.gecerliMi()); const auto t0 = std::chrono::steady_clock::now(); const auto kenarlar = sureklilikRapor(g, 5.0, 0.1); const f64 ms = std::chrono::duration( std::chrono::steady_clock::now() - t0).count(); std::printf("[perf] sureklilikRapor: %zu kenar, %.1f ms\n", kenarlar.size(), ms); FIKO_KONTROL(kenarlar.size() >= 100); // ic kenarlarin tumu olculur for (auto& k : kenarlar) FIKO_KONTROL(k.yuzA != 0 && k.yuzB != 0); } // ---- Keskin kenar: PERF olcumu (tarak govde, cok kenar) ---------------------- // Sure assert edilmez (makine bagimli) — stdout'a yazilir; dogruluk + bos-olmama // kontrol edilir. Optimizasyon oncesi/sonrasi kiyas icin sabit geometri. FIKO_TEST(keskin_kenar_perf_tarak) { geometri::BrepGovde g = geometri::kutu(100, 20, 6); for (int i = 0; i < 10; ++i) { Donusumd t; t.konum = {-45.0 + i * 10.0, 0.0, 6.0}; g = geometri::birlesim(g, geometri::donusumUygula(geometri::kutu(4, 20, 6), t)); } FIKO_KONTROL(g.gecerliMi()); u32 kenarSayi = 0; for (u32 o = 1;; ++o) { if (g.kenarNoktalari(o).empty()) break; ++kenarSayi; } const auto t0 = std::chrono::steady_clock::now(); const auto kenarlar = keskinKenarRapor(g, 30.0); const f64 ms = std::chrono::duration( std::chrono::steady_clock::now() - t0).count(); std::printf("[perf] keskinKenarRapor: %u kenar ordinali, %zu keskin, %.1f ms\n", (unsigned)kenarSayi, kenarlar.size(), ms); FIKO_KONTROL(kenarSayi >= 100); // tarak yeterince zengin (olcum anlamli) FIKO_KONTROL(kenarlar.size() >= 20); // dislerin dik kenarlari keskin for (auto& k : kenarlar) FIKO_KONTROL(k.aciDeg > 30.0); } // ---- Kama (degisken cidar): UV ornekleme + yuz-MIN indirgeme --------------- // 40x40 taban, kalinligi 1mm'den 10mm'ye giden kama. GERCEK en ince cidar = 1mm. // ESKI DAVRANIS (olculdu): ornek noktalari ucgen dugumleri (= yuz koseleri) idi → // egik yuzde 6 ornegin 4'u komsu yuzu siyirip iskaladi, alt yuz ortalamasi 5.5mm // cikti (gercek min 1.0mm maskelendi). Yeni: yuz UV izgarasi + yuz basina MIN. FIKO_TEST(kalinlik_kama_degisken_cidar) { std::vector> kont{{{0, 0, 0}, {40, 0, 0}, {40, 0, 10}, {0, 0, 1}}}; const geometri::BrepGovde kama = geometri::prizma(kont, {0, 1, 0}, 40.0); FIKO_KONTROL(kama.gecerliMi()); f64 mn = 1e6, mx = 0; const auto np = kalinlikRapor(kama, 1e5, mn, mx); FIKO_KONTROL(!np.empty()); // UV hucre MERKEZI ornekler → tam kenara (x=0, t=1mm) hic dokunmaz: n=8'de ilk // merkez x=40*(0.5/8)=2.5 → t = 1 + 9*2.5/40 = 1.5625mm. Cozunurluk (analiz. // kalinlik_izgara) buyudukce gercek minimuma yakinsar; ESKI kod bu yuzu hic // olcemiyordu. Bu YAKIN, ornekleme modelinin de dogrulamasidir. FIKO_YAKIN(mn, 1.5625, 0.15); // Alt yuz (ordinal 1): UV izgarasi ic noktalari ornekler → hem 1'e hem 10'a // yakin degerler cikmali (kose-iskasi bitti), MIN indirgemesi 1mm'yi gorur. std::vector p; std::vector k; const u32 say = geometri::yuzKalinlikOrnekle(kama, 1, kalinlikIzgara(), 1e5, p, k); FIKO_KONTROL(say >= 16); // 8x8 izgara → yuz ici gercekten orneklendi f64 yMin = 1e9, yMax = 0, top = 0; for (f64 v : k) { yMin = std::min(yMin, v); yMax = std::max(yMax, v); top += v; } FIKO_YAKIN(yMin, 1.5625, 0.15); // ince uca en yakin hucre merkezi FIKO_KONTROL(yMax > 9.0); // kalin uc da olculdu (eski kod iskaliyordu) FIKO_KONTROL(top / (f64)say > 4.0); // ortalama ~5.5 → MIN ile ORTALAMA farki gercek } // ---- Uzayda KEYFI konum/yonelim → ayni kalinlik (olcum) --------------------- // Kalinlik yuzey normali boyunca ic isindir; hem nokta hem normal AYNI (yerel) // uzayda oldugundan doteleme/dondurme sonucu DEGISTIRMEMELI. Bunu iddia degil // OLCUM olarak kilitle: 8mm plaka, keyfi eksende 37° dondurulup 123mm otelenmis. FIKO_TEST(kalinlik_konum_yonelim_bagimsiz) { const geometri::BrepGovde plaka = geometri::kutu(40, 30, 8); f64 mn0 = 1e6, mx0 = 0; kalinlikRapor(plaka, 1e5, mn0, mx0); Donusumd don; don.yonelim = Quatd::eksenAci(Vec3d{0.3, -0.7, 0.65}.birim(), 37.0 * 3.14159265358979 / 180.0); don.konum = {123.4, -56.7, 89.1}; const geometri::BrepGovde tasinmis = geometri::donusumUygula(plaka, don); FIKO_KONTROL(tasinmis.gecerliMi()); f64 mn1 = 1e6, mx1 = 0; kalinlikRapor(tasinmis, 1e5, mn1, mx1); FIKO_YAKIN(mn1, mn0, 1e-6); // konum/yonelim kalinligi DEGISTIRMEZ FIKO_YAKIN(mx1, mx0, 1e-6); FIKO_YAKIN(mn0, 8.0, 0.2); // gercek cidar 8mm } // ---- IC BOSLUK (kapali kavite): kutu icinde kutu → 5mm cidar ---------------- // 40³ kutudan icerideki 30³ kutu cikarilir → disa hic acilmayan kapali kavite. // Hem DIS yuzlerden ic isin (5mm'de kavite duvarina), hem KAVITE yuzlerinden // (normali bosluga bakar → ic isin MALZEMEYE gider) 5mm okunmali. FIKO_TEST(kalinlik_ic_bosluk_kavite) { const geometri::BrepGovde dis = geometri::kutu(40, 40, 40); const geometri::BrepGovde ic = geometri::kutu(30, 30, 30); const geometri::BrepGovde kovuk = geometri::cikarma(dis, ic); FIKO_KONTROL(kovuk.gecerliMi()); // 6 dis + 6 kavite = 12 yuz olmali (kavite gercekten kapali). u32 yuzSay = 0; for (u32 o = 1;; ++o) { geometri::YuzBilgi yb; if (!kovuk.yuzBilgi(o, yb)) break; ++yuzSay; } FIKO_KONTROL(yuzSay == 12); f64 mn = 1e6, mx = 0; const auto np = kalinlikRapor(kovuk, 1e5, mn, mx); FIKO_KONTROL(!np.empty()); FIKO_YAKIN(mn, 5.0, 0.2); // cidar 5mm — ic bosluk dogru bulundu // DIS yuzun ORTASINDAN: tam kavitenin uzerinde → 5mm (isin kaviteye girer durur). FIKO_YAKIN(geometri::noktaKalinlik(kovuk, {0, 0, 20}, {0, 0, 1}), 5.0, 1e-3); // KAVITE yuzunden: normali bosluga bakar → ic isin MALZEMEYE gider → yine 5mm. FIKO_YAKIN(geometri::noktaKalinlik(kovuk, {0, 0, 15}, {0, 0, -1}), 5.0, 1e-3); // Kenar/pervaz bolgesi (kavitenin YANINDAN gecen isin) 40mm'ye kadar cikar — // orada malzeme gercekten 40mm; bu DOGRU davranis, kavite kacagi degil. FIKO_YAKIN(mx, 40.0, 0.5); } // ---- Rampa CPU ikizi (lejant) renkRampa.glsl ile ayni mi ------------------- // Lejant eskiden kaba kirmizi→yesil cizerken shader jet/turbo boyuyordu → lejant // 3B'yi YANLIS tarif ediyordu. Ikiz artik tek kaynak; bu test onu kilitler. FIKO_TEST(rampa_cpu_ikizi) { // Jet: t=0 mavi, t=0.5 yesil, t=1 kirmizi (GLSL formulunun birebir ayni cikti). const Vec3f j0 = rampaRenk(0, 0.0f), j5 = rampaRenk(0, 0.5f), j1 = rampaRenk(0, 1.0f); // Klasik jet uclarda YARIM yogunlukta baslar: t=0 → (0,0,0.5) koyu mavi, // t=1 → (0.5,0,0) koyu kirmizi (1.5-|4t-k| formulunun dogal sonucu). FIKO_YAKIN(j0.z, 0.5f, 1e-4f); FIKO_KONTROL(j0.x < 0.01f && j0.y < 0.01f); FIKO_KONTROL(j5.y > 0.9f); // orta yesil FIKO_YAKIN(j1.x, 0.5f, 1e-4f); FIKO_KONTROL(j1.z < 0.01f && j1.y < 0.01f); // Turbo: koyu mavi → kirmizi; ucta kirmizi bilesen baskin. const Vec3f t0 = rampaRenk(1, 0.0f), t1 = rampaRenk(1, 1.0f); FIKO_KONTROL(t0.z > t0.x); FIKO_KONTROL(t1.x > t1.z); // Tolerans: merkez yesil, uclar kirmizi (sapma bandi semantigi). const Vec3f m = rampaRenk(3, 0.5f), u = rampaRenk(3, 1.0f); FIKO_KONTROL(m.y > m.x); FIKO_KONTROL(u.x > u.y); // Sinir disi t kenetlenir (NaN/tasma renk uretmez). const Vec3f alt = rampaRenk(0, -5.0f), ust = rampaRenk(0, 7.0f); FIKO_KONTROL(alt.x >= 0.f && alt.y >= 0.f && alt.z >= 0.f); FIKO_KONTROL(ust.x <= 1.f && ust.y <= 1.f && ust.z <= 1.f); }