#include #include #include "fiko/dokum/porozite.hpp" #include "fiko_test.hpp" using namespace fiko; using namespace fiko::dokum; namespace { VoxelKafes kafesYap(u32 n) { VoxelKafes k; Aabbd s; s.genislet({-1, -1, -1}); s.genislet({1, 1, 1}); k.kur(s, n, 0.0, 1.0); for (auto& t : k.tip) t = HucreTip::Dis; return k; } KatilasmaSonuc katYap(const VoxelKafes& k, f64 ny) { KatilasmaSonuc kat; kat.niyama.assign(k.hucreSayi(), ny); kat.hazir = true; return kat; } } // namespace FIKO_TEST(porozite_niyama_monoton) { const Alasim al = alasimAlSi7Mg(); // Eğri monoton azalan: düşük Ny yüksek %, Ny*≥2 → 0. f64 once = 1e9; for (f64 ny : {0.0, 0.02, 0.05, 0.2, 0.35, 0.5, 0.8, 1.5, 5.0}) { const f64 p = cekmePorozitesi(ny, al, 1.0); FIKO_KONTROL(p <= once + 1e-12); FIKO_KONTROL(p >= 0.0 && p <= 100.0); once = p; } FIKO_KONTROL(cekmePorozitesi(0.005, al, 1.0) > 3.0); FIKO_KONTROL(cekmePorozitesi(5.0, al, 1.0) == 0.0); // Per-hücre alan: düşük-Niyama hücre > orta > yüksek (~0), kalıp hücresi 0. VoxelKafes k = kafesYap(4); const u32 dusuk = k.indeks(1, 1, 1), orta = k.indeks(2, 1, 1), yuksek = k.indeks(1, 2, 1); k.tip[dusuk] = k.tip[orta] = k.tip[yuksek] = HucreTip::Ic; KatilasmaSonuc kat = katYap(k, 5.0); kat.niyama[dusuk] = 0.02; kat.niyama[orta] = 0.25; kat.niyama[yuksek] = 3.0; const PoroziteSonuc s = poroziteHesapla(k, kat, nullptr, al, {}); FIKO_KONTROL(s.hazir); FIKO_KONTROL(s.porozite[dusuk] > s.porozite[orta]); FIKO_KONTROL(s.porozite[orta] > s.porozite[yuksek]); FIKO_KONTROL(s.porozite[yuksek] < 0.01f); FIKO_KONTROL(s.porozite[k.indeks(0, 0, 0)] == 0.0f); FIKO_KONTROL(s.maksPor > 3.0); FIKO_KONTROL(s.poroziteOrani > 0.0 && s.poroziteOrani < 100.0); FIKO_KONTROL(s.toplamPorHacimMm3 > 0.0 && s.toplamPorHacimMm3 < s.parcaHacimMm3); } FIKO_TEST(porozite_gaz_cebi) { // Çekme ~0 (yüksek Niyama); gaz yalnız hava alanlarından gelir. VoxelKafes k = kafesYap(4); const u32 cep = k.indeks(1, 1, 1), riskli = k.indeks(2, 1, 1); k.tip[cep] = k.tip[riskli] = HucreTip::Ic; const KatilasmaSonuc kat = katYap(k, 5.0); HavaAnalizSonuc hava; hava.lastAir.assign(k.hucreSayi(), 0.0f); hava.kabarcikRisk.assign(k.hucreSayi(), 0.0f); hava.lastAir[cep] = 1.0f; // dolmayan hücre = hapsolmuş hava hava.kabarcikRisk[riskli] = 0.8f; hava.hazir = true; const PoroziteSonuc s = poroziteHesapla(k, kat, &hava, alasimAlSi7Mg(), {}); FIKO_KONTROL(s.hazir); FIKO_KONTROL(s.gazPor[cep] > 4.9f); // kapaliCepPor tabanı FIKO_KONTROL(s.gazPor[riskli] > 1.5f); // 2.0 × 0.8 risk katkısı FIKO_KONTROL(s.cekmePor[cep] < 0.01f); FIKO_KONTROL(s.porozite[cep] > s.porozite[riskli]); FIKO_KONTROL(s.bolgeler.size() == 1); // bitişik iki gaz hücresi FIKO_KONTROL(s.bolgeler[0].tip == PoroziteTip::Gaz); FIKO_KONTROL(s.bolgeler[0].hucreSayi == 2); } FIKO_TEST(porozite_bolge_birlesme) { // Bitişik iki riskli hücre tek bölge; uzaktaki üçüncü ayrı bölge. VoxelKafes k = kafesYap(6); const u32 a = k.indeks(1, 1, 1), b = k.indeks(2, 1, 1), c = k.indeks(4, 4, 4); for (u32 idx : {a, b, c}) k.tip[idx] = HucreTip::Ic; KatilasmaSonuc kat = katYap(k, 5.0); kat.niyama[a] = kat.niyama[b] = kat.niyama[c] = 0.02; const PoroziteSonuc s = poroziteHesapla(k, kat, nullptr, alasimAlSi7Mg(), {}); FIKO_KONTROL(s.hazir); FIKO_KONTROL(s.bolgeler.size() == 2); u32 enBuyuk = 0; for (const auto& bg : s.bolgeler) { enBuyuk = std::max(enBuyuk, bg.hucreSayi); FIKO_KONTROL(bg.tip == PoroziteTip::Cekme); FIKO_KONTROL(bg.maksPor > 3.0 && bg.ortalamaPor > 3.0); FIKO_KONTROL(bg.hacimMm3 > 0.0); } FIKO_KONTROL(enBuyuk == 2); } FIKO_TEST(porozite_bos_giris_cokme_yok) { const Alasim al = alasimAlSi7Mg(); VoxelKafes bos; FIKO_KONTROL(!poroziteHesapla(bos, {}, nullptr, al, {}).hazir); VoxelKafes k = kafesYap(4); KatilasmaSonuc hazirDegil; hazirDegil.niyama.assign(k.hucreSayi(), 1.0); FIKO_KONTROL(!poroziteHesapla(k, hazirDegil, nullptr, al, {}).hazir); KatilasmaSonuc yanlisBoy; yanlisBoy.hazir = true; yanlisBoy.niyama.assign(3, 1.0); FIKO_KONTROL(!poroziteHesapla(k, yanlisBoy, nullptr, al, {}).hazir); // Hava boyutu uyumsuz → hava yok sayılır, çekme yine hesaplanır. k.tip[k.indeks(1, 1, 1)] = HucreTip::Ic; KatilasmaSonuc kat = katYap(k, 0.02); HavaAnalizSonuc bozukHava; bozukHava.hazir = true; bozukHava.lastAir.assign(2, 1.0f); const PoroziteSonuc s = poroziteHesapla(k, kat, &bozukHava, al, {}); FIKO_KONTROL(s.hazir); FIKO_KONTROL(s.gazPor[k.indeks(1, 1, 1)] == 0.0f); FIKO_KONTROL(s.porozite[k.indeks(1, 1, 1)] > 3.0f); } // ---- Oto izo-eşik: veriden yüzdelik (sabit %0.5 "her yer kırmızı"ydı) ------ // ÖLÇÜLDÜ (07-18 senaryo): 60mm küpte hücrelerin %58'i 0.5 üstü → izo-yüzey // parçayı kaplıyordu. Yüzdelik eşiği vurgulanan hücre oranını veriden seçer. FIKO_TEST(oto_esik_yuzdelik) { // 100 dolu hücre: 0.01..1.00 doğrusal → p90 ≈ 0.90. std::vector por; for (int i = 1; i <= 100; ++i) por.push_back(0.01f * i); const f64 e90 = poroziteOtoEsik(por, 0.90, 0.0, 100.0); FIKO_KONTROL(e90 > 0.85 && e90 < 0.95); // Eşik üstünde kalan hücre oranı ≈ %10 (vurgu yerelleşir, kaplamaz). int ustu = 0; for (f32 p : por) if (p > e90) ++ustu; FIKO_KONTROL(ustu >= 5 && ustu <= 15); // Sıfırlar yüzdeliğe girmez (parça dışı/temiz hücreler eşiği çekmesin). std::vector seyrek(1000, 0.0f); for (int i = 0; i < 10; ++i) seyrek[i] = 2.0f + 0.1f * i; const f64 eSeyrek = poroziteOtoEsik(seyrek, 0.90, 0.2, 20.0); FIKO_KONTROL(eSeyrek >= 2.0 && eSeyrek <= 3.0); // Boş / hep-sıfır → asgari (uydurma yok); bant kırpması çalışır. FIKO_KONTROL(poroziteOtoEsik({}, 0.9, 0.2, 20.0) == 0.2); FIKO_KONTROL(poroziteOtoEsik(std::vector(50, 0.0f), 0.9, 0.2, 20.0) == 0.2); FIKO_KONTROL(poroziteOtoEsik(std::vector(50, 99.0f), 0.9, 0.2, 20.0) == 20.0); } // ---- bolgeId haritası: baloncuk rengi = bölge TEPE değeri (MAGMA okuması) -- // İzo-yüzeyde alan ≈ eşik olduğundan alanın kendisiyle boyamak tüm baloncukları // dip renge ezer; bolgeId → maksPor alanı her baloncuğu şiddetiyle boyar. FIKO_TEST(bolge_id_haritasi) { VoxelKafes k = kafesYap(6); const u32 a = k.indeks(1, 1, 1), b = k.indeks(2, 1, 1), c = k.indeks(4, 4, 4); for (u32 idx : {a, b, c}) k.tip[idx] = HucreTip::Ic; KatilasmaSonuc kat = katYap(k, 5.0); kat.niyama[a] = kat.niyama[b] = kat.niyama[c] = 0.02; const PoroziteSonuc s = poroziteHesapla(k, kat, nullptr, alasimAlSi7Mg(), {}); FIKO_KONTROL(s.hazir && s.bolgeler.size() == 2); FIKO_KONTROL(s.bolgeId.size() == k.hucreSayi()); // Bitişik a-b aynı bölge, uzak c farklı bölge, kalan hücreler -1. FIKO_KONTROL(s.bolgeId[a] >= 0 && s.bolgeId[a] == s.bolgeId[b]); FIKO_KONTROL(s.bolgeId[c] >= 0 && s.bolgeId[c] != s.bolgeId[a]); std::vector say(s.bolgeler.size(), 0); for (u32 h = 0; h < k.hucreSayi(); ++h) { if (s.bolgeId[h] < 0) continue; FIKO_KONTROL((size_t)s.bolgeId[h] < s.bolgeler.size()); ++say[(size_t)s.bolgeId[h]]; } for (size_t bg = 0; bg < s.bolgeler.size(); ++bg) FIKO_KONTROL(say[bg] == s.bolgeler[bg].hucreSayi); }