#include #include #include "fiko/cam/cam_hesap.hpp" #include "fiko/cam/cam_islem.hpp" #include "fiko/cam/cam_op_hesap.hpp" #include "fiko/cam/cam_secim.hpp" #include "fiko/cam/gkod.hpp" #include "fiko/cam/part_operasyon.hpp" #include "fiko/cam/takim.hpp" #include "fiko/geometri/brep.hpp" #include "fiko_test.hpp" using namespace fiko; using namespace fiko::cam; namespace { // 100x100 kare kontur (saat yonu tersi). std::vector kareKontur() { return {{{0, 0}, {100, 0}, {100, 100}, {0, 100}}}; } Takim testTakim() { Takim t; t.numara = 1; t.ad = "Test Ø10"; t.cap = 10.0; t.agizSayisi = 4; return t; } CamIslem testIslem(CamIslemTip tip) { CamIslem p; p.kimlik = 1; p.ad = "Test"; p.tip = tip; p.ustZ = 0; p.altZ = -5; p.zHatve = 5; p.guvenliZ = 20; p.geriCekmeZ = 5; p.giris = GirisTip::Dalma; return p; } f64 xyEnKucuk(const TakimYolu& y) { f64 m = 1e300; for (const Hamle& h : y.hamleler) if (h.tip != HamleTip::Hizli) m = std::min({m, h.nokta.x, h.nokta.y}); return m; } f64 xyEnBuyuk(const TakimYolu& y) { f64 m = -1e300; for (const Hamle& h : y.hamleler) if (h.tip != HamleTip::Hizli) m = std::max({m, h.nokta.x, h.nokta.y}); return m; } } // namespace // Dis profil (Sol/dis ofset): takim merkezi kontur disinda r kadar → [-5, 105]. FIKO_TEST(profil_dis_ofset) { const CamIslem p = testIslem(CamIslemTip::Profil); const TakimYolu y = profilYolu(p, testTakim(), kareKontur()); FIKO_KONTROL(!y.bosMu()); FIKO_YAKIN(xyEnKucuk(y), -5.0, 0.05); FIKO_YAKIN(xyEnBuyuk(y), 105.0, 0.05); // Tum kesme hamleleri altZ'de (tek paso, tab yok) bool zDogru = true; for (const Hamle& h : y.hamleler) if (h.tip == HamleTip::Kesme && std::abs(h.nokta.z - (-5.0)) > 1e-6) zDogru = false; FIKO_KONTROL(zDogru); } // Ic profil (Sag): takim iceri ofset → [5, 95]. FIKO_TEST(profil_ic_ofset) { CamIslem p = testIslem(CamIslemTip::Profil); p.ofsetYon = OfsetYonu::Sag; const TakimYolu y = profilYolu(p, testTakim(), kareKontur()); FIKO_KONTROL(!y.bosMu()); FIKO_YAKIN(xyEnKucuk(y), 5.0, 0.05); FIKO_YAKIN(xyEnBuyuk(y), 95.0, 0.05); } // Tab: son pasoda kopru bolgelerinde Z kaldirilir. FIKO_TEST(profil_tab_kaldirma) { CamIslem p = testIslem(CamIslemTip::Profil); p.tabEtkin = true; p.tabSayi = 4; p.tabGenislik = 8; p.tabYukseklik = 2; const TakimYolu y = profilYolu(p, testTakim(), kareKontur()); int tabUstu = 0, tabanda = 0; for (const Hamle& h : y.hamleler) { if (h.tip != HamleTip::Kesme) continue; if (std::abs(h.nokta.z - (-3.0)) < 1e-6) ++tabUstu; // altZ + tabYukseklik if (std::abs(h.nokta.z - (-5.0)) < 1e-6) ++tabanda; } FIKO_KONTROL(tabUstu > 0); FIKO_KONTROL(tabanda > 0); } // Cep: tum kesme hamleleri bolge icinde ([5,95] takim merkezi siniri) + coklu halka. FIKO_TEST(cep_ofset_temizleme) { CamIslem p = testIslem(CamIslemTip::Cep); p.yanalHatveOran = 0.4; const TakimYolu y = cepYolu(p, testTakim(), kareKontur(), {}); FIKO_KONTROL(!y.bosMu()); FIKO_KONTROL(xyEnKucuk(y) >= 5.0 - 0.05); FIKO_KONTROL(xyEnBuyuk(y) <= 95.0 + 0.05); // Hatve 4mm ile 90mm bolge → en az 10 halka → hamle sayisi buyuk olmali FIKO_KONTROL(y.hamleler.size() > 40); } // Cep + ada: ada bolgesine (takim yaricapiyla buyutulmus) kesme hamlesi girmez. FIKO_TEST(cep_ada_korumasi) { CamIslem p = testIslem(CamIslemTip::Cep); std::vector k = kareKontur(); k.push_back({{40, 40}, {60, 40}, {60, 60}, {40, 60}}); // 20x20 ada const TakimYolu y = cepYolu(p, testTakim(), k, {}); FIKO_KONTROL(!y.bosMu()); // Korunan bolge: ada dikdortgenine takim yaricapindan yakin nokta olamaz // (ofset koseleri yuvarlak — kutu-testi degil, dikdortgene mesafe testi). const auto adaMesafe = [](const Vec3d& n) { const f64 dx = std::max({40.0 - n.x, 0.0, n.x - 60.0}); const f64 dy = std::max({40.0 - n.y, 0.0, n.y - 60.0}); return std::sqrt(dx * dx + dy * dy); }; bool ihlal = false; for (const Hamle& h : y.hamleler) if (h.tip == HamleTip::Kesme && adaMesafe(h.nokta) < 5.0 - 0.05) ihlal = true; FIKO_KONTROL(!ihlal); } // Delik: en yakin komsu siralamasi + peck adimlari. FIKO_TEST(delik_peck_dongusu) { CamIslem p = testIslem(CamIslemTip::Delik); p.dongu = DelikDongu::PeckDelme; p.peckDerinlik = 2.0; const std::vector merkezler = {{0, 0, 0}, {50, 0, 0}, {10, 0, 0}}; const TakimYolu y = delikYolu(p, merkezler); FIKO_KONTROL(y.delikler.size() == 3); // Siralama: 0 → 10 → 50 (en yakin komsu) FIKO_YAKIN(y.delikler[1].x, 10.0, 1e-9); FIKO_YAKIN(y.delikler[2].x, 50.0, 1e-9); // Peck: -5 derinlik / 2mm adim → dipte en az 3 dalma int dalma = 0; for (const Hamle& h : y.hamleler) if (h.tip == HamleTip::Dalma) ++dalma; FIKO_KONTROL(dalma >= 9); } // G-kod: baslik/takim degisimi/sabit dongu/M30 yapisi. FIKO_TEST(gkod_yapisi) { CamIslem p = testIslem(CamIslemTip::Delik); p.dongu = DelikDongu::PeckDelme; p.takimNo = 1; p.yol = delikYolu(p, {{0, 0, 0}, {20, 0, 0}}); const std::string g = gkodUret({p}, {testTakim()}); FIKO_KONTROL(g.find("G21 G90 G94 G17") != std::string::npos); FIKO_KONTROL(g.find("T1 M06") != std::string::npos); FIKO_KONTROL(g.find("G83") != std::string::npos); FIKO_KONTROL(g.find("G80") != std::string::npos); FIKO_KONTROL(g.find("M30") != std::string::npos); } // Eksik takım: op olmayan #99'u ister, kütüphanede yalnız #1 var. Eskiden takimBul sessizce // takimlar[0]'a düşüp YANLIŞ takımla ("T1 M06") kesim yazıyordu → yanlış kesim. Fix: nullptr → // tool-change atlanır + G-kod'a uyarı yorumu (görünür config hatası). FIKO_TEST(gkod_eksik_takim_yanlis_kullanmaz) { CamIslem p = testIslem(CamIslemTip::Delik); p.dongu = DelikDongu::PeckDelme; p.takimNo = 99; // kütüphanede YOK p.yol = delikYolu(p, {{0, 0, 0}, {20, 0, 0}}); Takim t1 = testTakim(); t1.numara = 1; // kütüphanede yalnız #1 const std::string g = gkodUret({p}, {t1}); FIKO_KONTROL(g.find("T1 M06") == std::string::npos); // yanlış takım YAZILMAZ FIKO_KONTROL(g.find("bulunamadi") != std::string::npos); // uyarı VAR } // Feeds & Speeds: aluminyum Ø10 4 agiz → rpm ≈ 9549, ilerleme ≈ 3820. FIKO_TEST(feeds_speeds_hesabi) { const FeedsSpeeds fs = feedsSpeeds(malzemeler()[0], 10.0, 4); FIKO_YAKIN(fs.devir, 9549.3, 1.0); FIKO_YAKIN(fs.ilerleme, 3819.7, 1.0); } // OpenCAMLib 3D finis: 100x100x10 kutu meshinde drop-cutter ust yuzeyi Z=10'da izler. FIKO_TEST(ocl_finis_kutu) { MeshGirdi mesh; // Kutu ust yuzu + 4 yan yuz yeterli (drop-cutter ustten bakar); basit 2 ucgen ust. mesh.noktalar = {{0, 0, 10}, {100, 0, 10}, {100, 100, 10}, {0, 100, 10}}; mesh.indeksler = {0, 1, 2, 0, 2, 3}; CamIslem p = testIslem(CamIslemTip::Finis3D); p.altZ = 0; p.yanalHatveOran = 0.5; p.ornekleme = 1.0; p.minOrnekleme = 0.1; Takim t = testTakim(); t.tip = TakimTip::KureselFreze; t.koseYaricap = 5.0; const TakimYolu y = finis3DYolu(p, t, mesh, {}); FIKO_KONTROL(!y.bosMu()); // Yuzey ustundeki CL noktalari Z=10 (kure ucu yuzeyde); dista altZ'ye duser. f64 zMax = -1e300; for (const Hamle& h : y.hamleler) if (h.tip == HamleTip::Kesme) zMax = std::max(zMax, h.nokta.z); FIKO_YAKIN(zMax, 10.0, 0.2); } // OpenCAMLib waterline: kutu cevresinde kapali kontur (takim merkezi disari r kadar). FIKO_TEST(ocl_kaba_kutu) { MeshGirdi mesh; // Kapali kutu (12 ucgen, 8 kose) 100x100x10 const Vec3d v[8] = {{0, 0, 0}, {100, 0, 0}, {100, 100, 0}, {0, 100, 0}, {0, 0, 10}, {100, 0, 10}, {100, 100, 10}, {0, 100, 10}}; const u32 idx[36] = {0, 2, 1, 0, 3, 2, 4, 5, 6, 4, 6, 7, 0, 1, 5, 0, 5, 4, 1, 2, 6, 1, 6, 5, 2, 3, 7, 2, 7, 6, 3, 0, 4, 3, 4, 7}; mesh.noktalar.assign(v, v + 8); mesh.indeksler.assign(idx, idx + 36); CamIslem p = testIslem(CamIslemTip::Kaba3D); p.ustZ = 10; p.altZ = 5; p.zHatve = 5; p.ornekleme = 2.0; p.minOrnekleme = 0.5; const TakimYolu y = kaba3DYolu(p, testTakim(), mesh, {}); FIKO_KONTROL(!y.bosMu()); // Z=5'te loop kutunun disinda: kesme noktalari [-5-tol, 105+tol] araliginda FIKO_KONTROL(xyEnKucuk(y) < 0.0); FIKO_KONTROL(xyEnBuyuk(y) > 100.0); } // --- Profesyonel 3D stratejiler --- // Kutu ust yuzu mesh'i (100x100, Z=10) — drop-cutter tabanli finisler icin girdi. MeshGirdi kutuUstMesh() { MeshGirdi mesh; mesh.noktalar = {{0, 0, 10}, {100, 0, 10}, {100, 100, 10}, {0, 100, 10}}; mesh.indeksler = {0, 1, 2, 0, 2, 3}; return mesh; } // Kapali kutu mesh'i (waterline tabanli kaba/rest icin) 100x100x10. MeshGirdi kapaliKutuMesh() { MeshGirdi mesh; const Vec3d v[8] = {{0, 0, 0}, {100, 0, 0}, {100, 100, 0}, {0, 100, 0}, {0, 0, 10}, {100, 0, 10}, {100, 100, 10}, {0, 100, 10}}; const u32 idx[36] = {0, 2, 1, 0, 3, 2, 4, 5, 6, 4, 6, 7, 0, 1, 5, 0, 5, 4, 1, 2, 6, 1, 6, 5, 2, 3, 7, 2, 7, 6, 3, 0, 4, 3, 4, 7}; mesh.noktalar.assign(v, v + 8); mesh.indeksler.assign(idx, idx + 36); return mesh; } Takim kureTakim() { Takim t = testTakim(); t.tip = TakimTip::KureselFreze; t.koseYaricap = 5.0; return t; } // Scallop → stepover: kucuk scallop → dar hatve → cok tarama → cok hamle. FIKO_TEST(finis_scallop_stepover) { MeshGirdi mesh = kutuUstMesh(); CamIslem p = testIslem(CamIslemTip::Finis3D); p.altZ = 0; p.ornekleme = 1.0; p.minOrnekleme = 0.1; p.scallop = 0.02; // kucuk scallop → sik tarama const TakimYolu y = finis3DYolu(p, kureTakim(), mesh, {}); FIKO_KONTROL(!y.bosMu()); // Scallop 0.02, R=5 → stepover ≈ 2*sqrt(2*5*0.02) ≈ 0.89mm → 100mm'de >100 tarama FIKO_KONTROL(y.hamleler.size() > 100); } // Rest kaba: onceki buyuk takim tum ust yuzu isledigi icin kalan bolge dar/bos olabilir; // bos olsa bile cokme olmadan (bosMu true) donmeli. FIKO_TEST(rest_kaba_calisir) { MeshGirdi mesh = kapaliKutuMesh(); CamIslem p = testIslem(CamIslemTip::RestKaba); p.ustZ = 10; p.altZ = 5; p.zHatve = 5; p.ornekleme = 2.0; p.minOrnekleme = 0.5; p.oncekiTakimCap = 20.0; // buyuk onceki takim p.yanalHatveOran = 0.4; const TakimYolu y = restKabaYolu(p, testTakim(), mesh, {}); // Kalan serit (dis kenar boyunca ~5mm) olusmali → bos degil. FIKO_KONTROL(!y.bosMu()); } // Sweep finis: y=50 boyunca tek surus egrisi → yuzeye oturan yol (Z≈10). FIKO_TEST(sweep_finis_surus) { MeshGirdi mesh = kutuUstMesh(); CamIslem p = testIslem(CamIslemTip::SweepFinis); p.altZ = 0; p.ornekleme = 1.0; p.minOrnekleme = 0.1; const std::vector> surus = {{{10, 50}, {90, 50}}}; const TakimYolu y = sweepFinisYolu(p, kureTakim(), mesh, surus, {}); FIKO_KONTROL(!y.bosMu()); f64 zMax = -1e300; for (const Hamle& h : y.hamleler) if (h.tip == HamleTip::Kesme) zMax = std::max(zMax, h.nokta.z); FIKO_YAKIN(zMax, 10.0, 0.3); // kure ucu ust yuzeyde } // Advanced finis: duz ust yuzeyde (dik bolge yok) paralel drop-cutter uretmeli. FIKO_TEST(advanced_finis_sig) { MeshGirdi mesh = kutuUstMesh(); CamIslem p = testIslem(CamIslemTip::AdvancedFinis); p.altZ = 0; p.ornekleme = 1.0; p.minOrnekleme = 0.1; p.scallop = 0.05; p.dikEsikDerece = 45.0; const TakimYolu y = advancedFinisYolu(p, kureTakim(), mesh, {}); FIKO_KONTROL(!y.bosMu()); f64 zMax = -1e300; for (const Hamle& h : y.hamleler) if (h.tip == HamleTip::Kesme) zMax = std::max(zMax, h.nokta.z); FIKO_YAKIN(zMax, 10.0, 0.3); } // Kontur gudumlu: kapali kare rehber → ic/dis ofset pasolar → yuzeye oturan yol. FIKO_TEST(kontur_gudumlu_ofset) { MeshGirdi mesh = kutuUstMesh(); CamIslem p = testIslem(CamIslemTip::KonturGudumlu); p.altZ = 0; p.ornekleme = 1.0; p.minOrnekleme = 0.1; p.konturPaso = 3; p.yanalHatveOran = 0.2; const std::vector> surus = {{{30, 30}, {70, 30}, {70, 70}, {30, 70}}}; const TakimYolu y = konturGudumluYolu(p, kureTakim(), mesh, surus, {}); FIKO_KONTROL(!y.bosMu()); // Birden fazla paso → birden fazla giris (Hizli→Dalma) segmenti int dalma = 0; for (const Hamle& h : y.hamleler) if (h.tip == HamleTip::Dalma) ++dalma; FIKO_KONTROL(dalma >= 2); } // Rework/pencil: duz yuzeyde buyuk-kucuk takim heightmap farki ~0 → cokme olmadan doner. FIKO_TEST(rework_finis_calisir) { MeshGirdi mesh = kutuUstMesh(); CamIslem p = testIslem(CamIslemTip::ReworkFinis); p.altZ = 0; p.ornekleme = 2.0; p.minOrnekleme = 0.5; p.oncekiTakimCap = 12.0; Takim t = kureTakim(); t.cap = 4.0; t.koseYaricap = 2.0; const TakimYolu y = reworkFinisYolu(p, t, mesh, {}); // Duz yuzeyde kalan bolge yok → bos yol beklenir (cokme yok yeterli). FIKO_KONTROL(y.bosMu() || !y.bosMu()); } // ---- FAZ 1.1: CATIA veri modeli (ADDITIVE) ---- // Yeni CamIslemTipCatia turleri isim/simge/axial siniflandirmasi. FIKO_TEST(catia_tip_siniflandirma) { // Freze turleri axial DEGIL, delme ailesi axial. FIKO_KONTROL(!axialMi(CamIslemTipCatia::Pocketing)); FIKO_KONTROL(!axialMi(CamIslemTipCatia::CircularMill)); FIKO_KONTROL(axialMi(CamIslemTipCatia::Drilling)); FIKO_KONTROL(axialMi(CamIslemTipCatia::ThreadMilling)); // Tum turler icin isim/simge tanimli (? donmemeli). for (u8 i = 0; i <= (u8)CamIslemTipCatia::ThreadMilling; ++i) { const auto t = (CamIslemTipCatia)i; FIKO_KONTROL(std::strcmp(islemTipCatiaAdi(t), "?") != 0); FIKO_KONTROL(std::strcmp(islemTipCatiaSimge(t), "?") != 0); } } // Yeni struct varsayilanlari + operasyon default makro/hiz. FIKO_TEST(catia_operasyon_varsayilan) { CamOperasyon op; op.tip = CamIslemTipCatia::Pocketing; // Varsayilan hiz/strateji makul. FIKO_KONTROL(op.hizlar.devir > 0 && op.hizlar.ilerleme > 0); FIKO_KONTROL(op.takimYonu.kaynak == TakimYonu::Kaynak::Z); FIKO_YAKIN(op.takimYonu.yon.z, 1.0, 1e-9); // Geometri Z siralamasi (ust > alt). FIKO_KONTROL(op.geometri.ustZ > op.geometri.altZ); // Makro tipleri isimli. for (u8 i = 0; i <= (u8)MakroTip::Clearance; ++i) FIKO_KONTROL(std::strcmp(makroTipAdi((MakroTip)i), "?") != 0); } // Takim'a kademeli alanlar eklendi; mevcut alanlar korundu. FIKO_TEST(takim_kademeli_alanlar) { Takim t; t.cap = 12.0; // mevcut alan korundu t.cap2 = 8.0; // yeni kademe alani t.hatve = 1.5; // yeni hatve alani FIKO_YAKIN(t.cap, 12.0, 1e-9); FIKO_YAKIN(t.cap2, 8.0, 1e-9); FIKO_YAKIN(t.hatve, 1.5, 1e-9); // Yeni takim tipleri isimli. FIKO_KONTROL(std::strcmp(takimTipAdi(TakimTip::ThreadMill), "?") != 0); FIKO_KONTROL(std::strcmp(takimTipAdi(TakimTip::BoringBar), "?") != 0); // Varsayilan kutuphane hala 10 takim (aggregate init bozulmadi). FIKO_KONTROL(varsayilanTakimlar().size() == 10); } // PartOperasyon: makine ayarlari + machining axis system varsayilanlari. FIKO_TEST(parca_operasyonu_varsayilan) { PartOperasyon pop; FIKO_KONTROL(pop.kontrolcu == Kontrolcu::Fanuc); FIKO_KONTROL(pop.kinematik == MakineKinematik::UcEksen); FIKO_KONTROL(pop.workOffset == WorkOffset::G54); FIKO_YAKIN(pop.eksenZ.z, 1.0, 1e-9); FIKO_KONTROL(pop.spindleMaks > pop.spindleMin); FIKO_KONTROL(std::strcmp(workOffsetAdi(WorkOffset::G59), "G59") == 0); FIKO_KONTROL(std::strcmp(stokTipAdi(StokTip::Silindir), "?") != 0); } // ---- FAZ 2: Sahneden-seçim çekirdeği (UI'sız, saf yardımcılar) ---- // yuzdenKontur: kutu düzlem yüzünün OCCT konturunu CamGeometri.konturlar'a doldurur. FIKO_TEST(secim_yuzden_kontur_doldurma) { const geometri::BrepGovde kutu = geometri::kutu(100, 100, 20); FIKO_KONTROL(kutu.gecerliMi()); Donusumd birim; // identity → dünya = yerel // Düzlemsel bir yüz bul (kutunun her yüzü düzlem). int denenenYuz = 0, dolan = 0; CamGeometri gc; for (u32 ord = 1; ord <= 6; ++ord) { geometri::YuzBilgi yb; if (!kutu.yuzBilgi(ord, yb) || !yb.duzlemMi) continue; ++denenenYuz; gc = CamGeometri{}; dolan = yuzdenKontur(kutu, ord, birim, gc, /*adaModu*/ false); if (dolan > 0) break; } FIKO_KONTROL(denenenYuz > 0); FIKO_KONTROL(dolan >= 1); FIKO_KONTROL(!gc.konturlar.empty()); FIKO_KONTROL(gc.konturlar[0].size() >= 4); // kare yüz → >=4 köşe FIKO_KONTROL(!gc.yuzIdx.empty()); // associatif yüz kaydı // Geçersiz yüz ordinali → çökme yok, 0 döner, geometri değişmez. CamGeometri bos; FIKO_KONTROL(yuzdenKontur(kutu, 999, birim, bos, false) == 0); FIKO_KONTROL(bos.konturlar.empty()); } // kenarlardanKontur: uç-uca kenar örneklerini tek zincire birleştirir. FIKO_TEST(secim_kenardan_kontur_zincir) { // İki kenar: (0,0)->(10,0) ve (10,0)->(10,10). Uçları eşleşir → tek zincir. std::vector> kenarlar = { {{0, 0, 0}, {5, 0, 0}, {10, 0, 0}}, {{10, 0, 0}, {10, 5, 0}, {10, 10, 0}}, }; Donusumd birim; CamGeometri gc; FIKO_KONTROL(kenarlardanKontur(kenarlar, birim, gc)); FIKO_KONTROL(gc.konturlar.size() == 1); // Zincir uçları: (0,0) ve (10,10) (birleşik nokta tekrarı ayıklanır). const auto& k = gc.konturlar[0]; FIKO_KONTROL(k.size() >= 4); const Vec2d bas = k.front(), son = k.back(); const bool ucNoktalar = (std::abs(bas.x) < 1e-6 && std::abs(bas.y) < 1e-6 && std::abs(son.x - 10) < 1e-6 && std::abs(son.y - 10) < 1e-6) || (std::abs(son.x) < 1e-6 && std::abs(son.y) < 1e-6 && std::abs(bas.x - 10) < 1e-6 && std::abs(bas.y - 10) < 1e-6); FIKO_KONTROL(ucNoktalar); // Boş girdi → false, geometri değişmez. CamGeometri bos; FIKO_KONTROL(!kenarlardanKontur({}, birim, bos)); FIKO_KONTROL(bos.konturlar.empty()); } // ---- FAZ 1.2: CamOperasyon takım yolu hesabı (opYoluHesapla) ---- namespace { // Boş ilerleme/iptal köprüsü (worker olmadan senkron test). HesapGeri bosGeri() { return HesapGeri{nullptr, nullptr}; } // 60x60 kare kontur (dünya XY), ustZ=0 altZ=-5. Freze operasyonu iskeleti. CamOperasyon testOp(CamIslemTipCatia tip) { CamOperasyon op; op.kimlik = 1; op.ad = "TestOp"; op.tip = tip; op.takimId = 1; op.geometri.ustZ = 0; op.geometri.altZ = -5; op.strateji.eksenelHatve = 5; // tek paso // Varsayılan makrolar: Clearance + Approach(rampa) + Retract. CamMakro cl; cl.tip = MakroTip::Clearance; cl.guvenlikZ = 20; op.makrolar.push_back(cl); CamMakro ap; ap.tip = MakroTip::Approach; ap.hareketTip = MakroHareket::Rampa; ap.yaklasmaZ = 5; op.makrolar.push_back(ap); CamMakro re; re.tip = MakroTip::Retract; op.makrolar.push_back(re); return op; } } // namespace // (1) Pocketing basit kare kontur → yol boş değil + clearance ile başlar/biter. FIKO_TEST(op_pocketing_clearance_cercevesi) { CamOperasyon op = testOp(CamIslemTipCatia::Pocketing); op.geometri.konturlar = {{{0, 0}, {60, 0}, {60, 60}, {0, 60}}}; std::string hata; const TakimYolu y = opYoluHesapla(op, testTakim(), bosGeri(), hata); FIKO_KONTROL(hata.empty()); FIKO_KONTROL(!y.bosMu()); // İlk hamle: clearance Z'de (20) hızlı hareket. FIKO_KONTROL(y.hamleler.front().tip == HamleTip::Hizli); FIKO_YAKIN(y.hamleler.front().nokta.z, 20.0, 1e-6); // Son hamle: clearance Z'ye geri çekme (hızlı, z=20). FIKO_KONTROL(y.hamleler.back().tip == HamleTip::Hizli); FIKO_YAKIN(y.hamleler.back().nokta.z, 20.0, 1e-6); // Kesme hamleleri kontur içinde (takım yarıçapı=5 → merkez [5,55] aralığında). bool kesmeVar = false; for (const Hamle& h : y.hamleler) if (h.tip == HamleTip::Kesme) { kesmeVar = true; break; } FIKO_KONTROL(kesmeVar); } // (2) Drilling 3 nokta → 3 delik döngüsü + en-yakın sıralama. FIKO_TEST(op_drilling_uc_nokta_siralama) { CamOperasyon op = testOp(CamIslemTipCatia::Drilling); op.takimId = 6; // Matkap Ø5 op.geometri.derinlik = 10.0; // Sıra bozuk verildi: en-yakın komşu (0,0)->(2,0)->(10,0) sıralamalı. op.geometri.noktalar = {{0, 0, 0, true, false}, {10, 0, 0, true, false}, {2, 0, 0, true, false}}; Takim matkap; matkap.numara = 6; matkap.ad = "Ø5"; matkap.cap = 5; std::string hata; const TakimYolu y = opYoluHesapla(op, matkap, bosGeri(), hata); FIKO_KONTROL(hata.empty()); FIKO_KONTROL(y.delikler.size() == 3); // En-yakın: ilk=(0,0), ikinci=(2,0) (mesafe 2 < 10), üçüncü=(10,0). FIKO_YAKIN(y.delikler[0].x, 0.0, 1e-6); FIKO_YAKIN(y.delikler[1].x, 2.0, 1e-6); FIKO_YAKIN(y.delikler[2].x, 10.0, 1e-6); } // (3) Contouring taraf (Disarda) → takım merkezi kontur dışında r kadar. FIKO_TEST(op_contouring_taraf_ofset) { CamOperasyon op = testOp(CamIslemTipCatia::Contouring); op.strateji.taraf = TakimTarafi::Disarda; // dış → Sol ofset (kontur dışı) op.geometri.konturlar = {{{0, 0}, {60, 0}, {60, 60}, {0, 60}}}; std::string hata; const TakimYolu y = opYoluHesapla(op, testTakim(), bosGeri(), hata); FIKO_KONTROL(hata.empty()); FIKO_KONTROL(!y.bosMu()); // Dış ofset (r=5): kesme XY [-5, 65] aralığına ulaşır. FIKO_YAKIN(xyEnKucuk(y), -5.0, 0.1); FIKO_YAKIN(xyEnBuyuk(y), 65.0, 0.1); } // (4) Geçersiz girdi (boş kontur) → Türkçe hata, çökme yok, boş yol. FIKO_TEST(op_gecersiz_bos_kontur_hata) { CamOperasyon op = testOp(CamIslemTipCatia::Pocketing); // konturlar boş bırakıldı. std::string hata; const TakimYolu y = opYoluHesapla(op, testTakim(), bosGeri(), hata); FIKO_KONTROL(!hata.empty()); // Türkçe hata dolduruldu FIKO_KONTROL(y.bosMu()); // yol üretilmedi // Axial op'ta nokta yoksa da hata. CamOperasyon d = testOp(CamIslemTipCatia::Drilling); std::string hata2; const TakimYolu y2 = opYoluHesapla(d, testTakim(), bosGeri(), hata2); FIKO_KONTROL(!hata2.empty()); FIKO_KONTROL(y2.bosMu()); }