#include "fiko/geometri/brep.hpp" #include "fiko/zeka/dedektorler.hpp" #include "fiko/zeka/zeka_motoru.hpp" #include "fiko_test.hpp" using namespace fiko; using namespace fiko::zeka; FIKO_TEST(topoloji_kutu) { ZekaMotoru m; auto b = geometri::kutu(20, 30, 40); u64 kok = m.govdeCoz(b, 1); FIKO_KONTROL(kok != 0); FIKO_KONTROL(m.govdeKok(1) == kok); FIKO_KONTROL(!m.bayatMi(1)); auto yuzler = m.sorgu().tip("Yuz").govdede(1).bul(); auto kenarlar = m.sorgu().tip("Kenar").govdede(1).bul(); FIKO_KONTROL(yuzler.size() == 6); FIKO_KONTROL(kenarlar.size() == 12); FIKO_KONTROL(m.sorgu().tip("Yuz").ozEsit("yuzey_tip", std::string("duzlem")).bul().size() == 6); // Kübün tüm iç kenarları dışbükey ~90° auto dik = m.sorgu().tip("Kenar").ozEsit("disbukey", true) .ozAralik("dihedral_aci", 89, 91).bul(); FIKO_KONTROL(dik.size() == 12); // Her kenar tam 2 yüze sınır for (u64 k : kenarlar) FIKO_KONTROL(m.graf.komsular(k, "sinir", +1).size() == 2); // Her yüz 4 komşu yüz ilişkisi taşır (yön bağımsız) for (u64 y : yuzler) FIKO_KONTROL(m.graf.komsular(y, "komsu", 0).size() == 4); // BREP referansı: KYA kid → düğüm geri bulunur const ZDugum* yd = m.graf.dugum(yuzler[0]); FIKO_KONTROL(yd->brep.kid != 0 && m.graf.brepDugum(1, 1, yd->brep.kid) == yuzler[0]); } FIKO_TEST(topoloji_silindir_ve_yeniden_cozum) { ZekaMotoru m; auto b = geometri::silindir(5, 20); m.govdeCoz(b, 7); auto silindirYuz = m.sorgu().tip("Yuz").ozEsit("yuzey_tip", std::string("silindir")).bul(); FIKO_KONTROL(silindirYuz.size() == 1); FIKO_KONTROL(m.graf.ozSayi(silindirYuz[0], "yaricap") == 5.0); auto duz = m.sorgu().tip("Yuz").ozEsit("yuzey_tip", std::string("duzlem")).bul(); FIKO_KONTROL(duz.size() == 2); auto cember = m.sorgu().tip("Kenar").ozEsit("kenar_tip", std::string("cember")).bul(); FIKO_KONTROL(!cember.empty()); // Bayatla + yeniden çöz: eski alt-graf düşer, canlı sayılar sabit kalır u32 onceDugum = m.graf.dugumSayisi(); m.govdeBayatla(7); FIKO_KONTROL(m.bayatMi(7)); m.govdeCoz(b, 7); FIKO_KONTROL(m.graf.dugumSayisi() == onceDugum); FIKO_KONTROL(!m.bayatMi(7)); // Gövde silme: alt-graf tamamen düşer m.govdeSil(7); FIKO_KONTROL(m.graf.dugumSayisi() == 0); FIKO_KONTROL(m.govdeKok(7) == 0); } FIKO_TEST(topoloji_delik_ve_icbukey) { // Delikli plaka: silindir duvarı yüz olarak tanınır ve kenara sınırdır auto delikli = geometri::cikarma(geometri::kutu(30, 30, 10), geometri::silindir(4, 30)); ZekaMotoru m; m.govdeCoz(delikli, 3); auto sil = m.sorgu().tip("Yuz").ozEsit("yuzey_tip", std::string("silindir")) .iliskili("sinir", "Kenar", -1).bul(); FIKO_KONTROL(sil.size() == 1); // Kare kanal: cep duvar-duvar köşe kenarları İÇBÜKEY (4 dikey kenar) auto kanal = geometri::cikarma(geometri::kutu(30, 30, 10), geometri::kutu(10, 10, 30)); m.govdeCoz(kanal, 4); auto icbukey = m.sorgu().tip("Kenar").govdede(4).ozEsit("disbukey", false).bul(); FIKO_KONTROL(icbukey.size() == 4); } namespace { // Genişleme sözleşmesi kanıtı: "yeni analiz = yeni dedektör, çekirdek değişmez". // Basit delik dedektörü — içbükey ağızlı silindir yüzünü Delik düğümü yapar. struct TestDelikDedektor : Dedektor { const char* ad() const override { return "test_delik"; } void calistir(DedektorBaglam& b) override { for (u64 y : Sorgu(b.graf).tip("Yuz").govdede(b.govdeVarlik) .ozEsit("yuzey_tip", std::string("silindir")).bul()) { u64 delik = b.graf.dugumEkle("Delik"); b.graf.ozAyarla(delik, "cap", b.graf.ozSayi(y, "yaricap") * 2); b.graf.ozAyarla(delik, "uretim_tipi", std::string("delme")); b.graf.iliskiEkle("icerir", b.govdeDugum, delik); b.graf.iliskiEkle("bagli", delik, y); } } }; } // namespace FIKO_TEST(topoloji_dedektor_katmani) { auto kutu = geometri::kutu(30, 30, 10); auto delikCap8 = geometri::silindir(4, 30); auto b = geometri::cikarma(kutu, delikCap8); ZekaMotoru m; m.dedektorEkle(std::make_unique()); FIKO_KONTROL(m.dedektor("test_delik") != nullptr); u64 govdeBildirim = 0; m.grafGuncellendi = [&](u64 g) { govdeBildirim = g; }; m.govdeCoz(b, 9); FIKO_KONTROL(govdeBildirim == 9); auto delikler = m.sorgu().tip("Delik").bul(); FIKO_KONTROL(delikler.size() == 1); FIKO_KONTROL(m.graf.ozSayi(delikler[0], "cap") == 8.0); // Feature'lar BREP-bağsız: govdede() onları görmez, govdeFeatureleri görmeli // (özet/sayım sözleşmesi — yaşandı: sağ-tık özeti hep "bulunamadı" diyordu) FIKO_KONTROL(m.sorgu().tip("Delik").govdede(9).bul().empty()); auto fl = m.govdeFeatureleri(9); FIKO_KONTROL(fl.size() == 1 && m.graf.dugum(fl[0])->tip == m.graf.adBul("Delik")); // Delik → yüz ilişkisi gezilebilir FIKO_KONTROL(m.graf.komsular(delikler[0], "bagli", +1).size() == 1); // Yeniden çözümde dedektör düğümleri de tazelenir (birikme yok) m.govdeCoz(b, 9); FIKO_KONTROL(m.sorgu().tip("Delik").bul().size() == 1); // Dedektör kapatılabilir m.dedektor("test_delik")->aktif = false; m.govdeCoz(b, 9); FIKO_KONTROL(m.sorgu().tip("Delik").bul().empty()); } FIKO_TEST(topoloji_onveri_esdegerlik) { // Async akış kanıtı: DERİN KOPYADAN çıkarılan onVeri ile kurulan graf, senkron // yolla birebir aynı düğüm/ilişki/özellik + delik dedektörü aynı sonucu üretmeli. auto b = geometri::cikarma(geometri::kutu(40, 40, 12), geometri::silindir(4, 40)); (void)b.ucgenle({0.5f, 0.5f, 0.5f}); // mesh → silindir örnek/normal yolu da sınansın b.kimlikleriBaslat(); auto kopya = geometri::govdeDerinKopya(b); FIKO_KONTROL(kopya.gecerliMi()); kopya.kimlikleriBaslat(); // ordinal sayıları etiket dizilerinden okunur const TopolojiOnVeri onVeri = ZekaMotoru::onVeriCikar(kopya); FIKO_KONTROL(!onVeri.yuzler.empty() && !onVeri.kenarlar.empty()); FIKO_KONTROL(!onVeri.silindirOrnekleri.empty()); // mesh örnek+normal çiftleri toplandı ZekaMotoru ms, ma; ms.dedektorEkle(delikDedektoru()); ma.dedektorEkle(delikDedektoru()); ms.govdeCoz(b, 1); // senkron yol ma.govdeCoz(b, 1, &onVeri); // onVeri yolu FIKO_KONTROL(ms.graf.dugumSayisi() == ma.graf.dugumSayisi()); FIKO_KONTROL(ms.graf.iliskiSayisi() == ma.graf.iliskiSayisi()); const auto say = [](ZekaMotoru& m, const char* tip) { return m.sorgu().tip(tip).bul().size(); }; FIKO_KONTROL(say(ms, "Yuz") == say(ma, "Yuz")); FIKO_KONTROL(say(ms, "Kenar") == say(ma, "Kenar")); FIKO_KONTROL(ms.graf.ozSayi(ms.govdeKok(1), "kenar_sayi") == ma.graf.ozSayi(ma.govdeKok(1), "kenar_sayi")); FIKO_KONTROL(ms.sorgu().tip("Kenar").ozEsit("disbukey", false).bul().size() == ma.sorgu().tip("Kenar").ozEsit("disbukey", false).bul().size()); auto ds = ms.sorgu().tip("Delik").bul(); auto da = ma.sorgu().tip("Delik").bul(); FIKO_KONTROL(ds.size() == 1 && da.size() == 1); FIKO_YAKIN(ms.graf.ozSayi(ds[0], "cap"), ma.graf.ozSayi(da[0], "cap"), 1e-9); FIKO_YAKIN(ms.graf.ozSayi(ds[0], "derinlik"), ma.graf.ozSayi(da[0], "derinlik"), 1e-9); const Deger* ts = ms.graf.oz(ds[0], "tip"); const Deger* ta = ma.graf.oz(da[0], "tip"); FIKO_KONTROL(ts && ta && std::holds_alternative(*ts) && std::get(*ts) == std::get(*ta)); }