#include "fiko/cam/cam_sistemi.hpp" #include #include #include "fiko/cam/apt.hpp" #include "fiko/cam/cam_hesap.hpp" #include "fiko/cam/cam_op_hesap.hpp" #include "fiko/cam/cam_secim.hpp" #include "fiko/cam/gkod.hpp" #include "fiko/cekirdek/cekirdek.hpp" #include "fiko/sahne/sahne.hpp" namespace fiko::cam { namespace { // Dugumun dunya-uzayi AABB'si (yerel sinirin 8 kosesi donusumle tasinir). Aabbf dunyaSinir(const Dugum& d) { Aabbf s; const Vec3f a = d.yerelSinir.asgari, b = d.yerelSinir.azami; for (int i = 0; i < 8; ++i) { const Vec3d yerel{(f64)(i & 1 ? b.x : a.x), (f64)(i & 2 ? b.y : a.y), (f64)(i & 4 ? b.z : a.z)}; const Vec3d w = d.donusum.noktaUygula(yerel); s.genislet({(f32)w.x, (f32)w.y, (f32)w.z}); } return s; } } // namespace CamSistemi::CamSistemi(Cekirdek& cekirdek, Sahne& sahne) : cekirdek_(cekirdek), sahne_(sahne), takimlar_(varsayilanTakimlar()) { // Kaynak geometri degisince bagimli operasyonlar kirlenir (parametrik link). cekirdek_.olaylar().abone([this](const BrepDegisti& e) { for (CamIslem& op : islemler_) if (op.govde == e.varlik) op.kirli = true; for (CamOperasyon& op : operasyonlar_) if (op.geometri.kaynakGovde == e.varlik) op.bayat = true; }); cekirdek_.olaylar().abone([this](const DonusumDegisti& e) { for (CamIslem& op : islemler_) if (op.govde == e.varlik) op.kirli = true; for (CamOperasyon& op : operasyonlar_) if (op.geometri.kaynakGovde == e.varlik) op.bayat = true; }); cekirdek_.olaylar().abone([this](const VarlikSilindi& e) { for (CamIslem& op : islemler_) if (op.govde == e.varlik) { op.kirli = true; op.hata = "Kaynak gövde silindi — yeni geometri seçin"; } for (CamOperasyon& op : operasyonlar_) if (op.geometri.kaynakGovde == e.varlik) { op.bayat = true; op.hata = "Kaynak gövde silindi — yeni geometri seçin"; } }); // Hata/iptal ile biten gorevlerde "bitince" cagrilmaz → bayragi elle dusur. cekirdek_.olaylar().abone([this](const GorevBitti& e) { if (!e.hataliMi) return; for (CamIslem& op : islemler_) op.hesaplaniyor = false; for (CamOperasyon& op : operasyonlar_) op.hesaplaniyor = false; }); } CamSistemi::~CamSistemi() = default; // unique_ptr tam tip burada CamSecimSistemi& CamSistemi::secim() { if (!secim_) secim_ = std::make_unique(sahne_, *this, cekirdek_.olaylar()); return *secim_; } u32 CamSistemi::islemEkle(CamIslemTip tip) { CamIslem op; op.kimlik = ++sayac_; op.tip = tip; op.ad = std::string(islemTipAdi(tip)) + "." + std::to_string(op.kimlik); switch (tip) { case CamIslemTip::Delik: op.dongu = DelikDongu::Delme; op.takimNo = 6; // Matkap Ø5 break; case CamIslemTip::Kaba3D: op.zHatve = 2.0; op.ornekleme = 0.5; break; case CamIslemTip::Finis3D: op.takimNo = 3; // Küresel Ø6 op.yanalHatveOran = 0.15; op.ornekleme = 0.1; op.minOrnekleme = 0.01; break; case CamIslemTip::RestKaba: op.zHatve = 1.5; op.ornekleme = 0.4; op.oncekiTakimCap = 12.0; // onceki (buyuk) kaba takim capi break; case CamIslemTip::SweepFinis: op.takimNo = 3; // Küresel Ø6 op.ornekleme = 0.1; op.minOrnekleme = 0.01; break; case CamIslemTip::AdvancedFinis: op.takimNo = 3; op.scallop = 0.01; // scallop yuksekligi ile stepover op.dikEsikDerece = 45.0; op.ornekleme = 0.1; op.minOrnekleme = 0.01; break; case CamIslemTip::KonturGudumlu: op.takimNo = 3; op.konturPaso = 8; op.ornekleme = 0.1; op.minOrnekleme = 0.01; break; case CamIslemTip::ReworkFinis: op.takimNo = 2; // kucuk Parmak Ø6 (pencil) op.oncekiTakimCap = 6.0; op.ornekleme = 0.1; op.minOrnekleme = 0.01; break; default: break; } islemler_.push_back(std::move(op)); seciliKimlik = (int)sayac_; cekirdek_.olaylar().yayinla(CamIslemEklendi{sayac_}, islemler_.back().ad.c_str()); return sayac_; } bool CamSistemi::islemSil(u32 kimlik) { for (size_t i = 0; i < islemler_.size(); ++i) { if (islemler_[i].kimlik != kimlik) continue; if (islemler_[i].yolDugum) sahne_.sil(islemler_[i].yolDugum); islemler_.erase(islemler_.begin() + (std::ptrdiff_t)i); if (seciliKimlik == (int)kimlik) seciliKimlik = 0; pencereKapat(kimlik); cekirdek_.olaylar().yayinla(CamIslemSilindi{kimlik}, "CAM işlem silindi"); return true; } return false; } void CamSistemi::pencereAc(u32 kimlik) { if (!bul(kimlik)) return; for (u32 k : acikPencereler) if (k == kimlik) return; // zaten acik acikPencereler.push_back(kimlik); } void CamSistemi::pencereKapat(u32 kimlik) { for (size_t i = 0; i < acikPencereler.size(); ++i) if (acikPencereler[i] == kimlik) { acikPencereler.erase(acikPencereler.begin() + (std::ptrdiff_t)i); return; } } void CamSistemi::islemGeriYukle(const CamIslem& kopya) { CamIslem op = kopya; op.yolDugum = 0; // sahne dugumu silinmisti; yeniden hesapta kurulur op.hesaplaniyor = false; op.kirli = true; sayac_ = std::max(sayac_, op.kimlik); const char* ad = op.ad.c_str(); const u32 kimlik = op.kimlik; islemler_.push_back(std::move(op)); cekirdek_.olaylar().yayinla(CamIslemEklendi{kimlik}, ad); } CamIslem* CamSistemi::bul(u32 kimlik) { for (CamIslem& op : islemler_) if (op.kimlik == kimlik) return &op; return nullptr; } // ---- CATIA-tarzi operasyon CRUD (FAZ 1.1) -------------------------------- void CamSistemi::opVarsayilanlar(CamOperasyon& op) { // Tip'e gore mantikli strateji/hiz/makro varsayilanlari (web operasyonEkle). const bool axial = axialMi(op.tip); op.makrolar.clear(); // Her operasyon: guvenlik duzlemi + yaklasma + geri cekme. CamMakro clearance; clearance.tip = MakroTip::Clearance; op.makrolar.push_back(clearance); CamMakro yaklasma; yaklasma.tip = MakroTip::Approach; if (op.tip == CamIslemTipCatia::Pocketing) yaklasma.hareketTip = MakroHareket::Helis; else if (op.tip == CamIslemTipCatia::Contouring || op.tip == CamIslemTipCatia::CurveFollow) yaklasma.hareketTip = MakroHareket::Yay; else if (axial) yaklasma.hareketTip = MakroHareket::OnDelik; else yaklasma.hareketTip = MakroHareket::Rampa; op.makrolar.push_back(yaklasma); CamMakro cekme; cekme.tip = MakroTip::Retract; cekme.hareketTip = MakroHareket::Dikine; op.makrolar.push_back(cekme); switch (op.tip) { case CamIslemTipCatia::Facing: op.takimId = 1; // Parmak Ø10 (tarama yoksa yakin) op.strateji.yolStili = YolStili::Zigzag; break; case CamIslemTipCatia::Pocketing: op.strateji.finisMod = FinisMod::Tabanda; break; case CamIslemTipCatia::Drilling: case CamIslemTipCatia::SpotDrill: op.takimId = 6; // Matkap Ø5 op.strateji.dongu = AxialDongu::Standart; break; case CamIslemTipCatia::DeepHole: case CamIslemTipCatia::BreakChips: op.takimId = 6; op.strateji.dongu = AxialDongu::Gagali; break; case CamIslemTipCatia::Tapping: case CamIslemTipCatia::ReverseTap: op.takimId = 8; // Kılavuz M10 op.strateji.dwellMod = DwellMod::Devir; break; case CamIslemTipCatia::Reaming: op.takimId = 9; // Rayba Ø10 break; default: break; } } u32 CamSistemi::opEkle(CamIslemTipCatia tip) { CamOperasyon op; op.kimlik = ++opSayac_; op.tip = tip; op.ad = std::string(islemTipCatiaAdi(tip)) + "." + std::to_string(op.kimlik); opVarsayilanlar(op); operasyonlar_.push_back(std::move(op)); seciliOp = (int)opSayac_; cekirdek_.olaylar().yayinla(CamOpEklendi{opSayac_}, operasyonlar_.back().ad.c_str()); return opSayac_; } bool CamSistemi::opSil(u32 kimlik) { for (size_t i = 0; i < operasyonlar_.size(); ++i) { if (operasyonlar_[i].kimlik != kimlik) continue; if (operasyonlar_[i].yolDugum) sahne_.sil(operasyonlar_[i].yolDugum); operasyonlar_.erase(operasyonlar_.begin() + (std::ptrdiff_t)i); if (seciliOp == (int)kimlik) seciliOp = 0; cekirdek_.olaylar().yayinla(CamOpSilindi{kimlik}, "CAM operasyonu silindi"); return true; } return false; } CamOperasyon* CamSistemi::opBul(u32 kimlik) { for (CamOperasyon& op : operasyonlar_) if (op.kimlik == kimlik) return &op; return nullptr; } // ---- Parca operasyonu (Part Operation) CRUD ------------------------------ u32 CamSistemi::parcaOpEkle() { PartOperasyon pop; pop.kimlik = ++parcaOpSayac_; pop.ad = "Parça Operasyonu." + std::to_string(pop.kimlik); parcaOperasyonlari_.push_back(std::move(pop)); aktifParcaOp = (int)parcaOpSayac_; cekirdek_.olaylar().yayinla(CamParcaOpEklendi{parcaOpSayac_}, parcaOperasyonlari_.back().ad.c_str()); return parcaOpSayac_; } bool CamSistemi::parcaOpSil(u32 kimlik) { for (size_t i = 0; i < parcaOperasyonlari_.size(); ++i) { if (parcaOperasyonlari_[i].kimlik != kimlik) continue; parcaOperasyonlari_.erase(parcaOperasyonlari_.begin() + (std::ptrdiff_t)i); if (aktifParcaOp == (int)kimlik) aktifParcaOp = 0; cekirdek_.olaylar().yayinla(CamParcaOpSilindi{kimlik}, "Parça operasyonu silindi"); return true; } return false; } PartOperasyon* CamSistemi::parcaOpBul(u32 kimlik) { for (PartOperasyon& pop : parcaOperasyonlari_) if (pop.kimlik == kimlik) return &pop; return nullptr; } Takim* CamSistemi::takimBul(int numara) { for (Takim& t : takimlar_) if (t.numara == numara) return &t; // Bulunamadı → nullptr. SESSİZCE takimlar_[0]'a düşmek YANLIŞTI: (1) G-kod yanlış takımla // yazılır (yanlış kesim), (2) "boş numara bul" döngüsü (takimEkle) asla nullptr almaz → hang. return nullptr; } void CamSistemi::geometridenAta(CamIslem& op) { op.hata.clear(); const auto& secililer = sahne_.secililer(); if (secililer.empty()) { op.hata = "Önce 3D sahneden geometri seçin (yüz kipi: 1)"; return; } const SecimOge ilk = secililer[0]; Dugum* d = sahne_.bul(ilk.govde); if (!d || !d->brep || !d->brep->gecerliMi()) { op.hata = "Seçili gövdenin B-rep geometrisi yok"; return; } op.govde = ilk.govde; op.kirli = true; const Aabbf sinir = dunyaSinir(*d); switch (op.tip) { case CamIslemTip::Delik: { op.delikYuzleri.clear(); for (const SecimOge& oge : secililer) { if (oge.govde != op.govde || oge.alt == 0) continue; geometri::YuzBilgi yb; if (d->brep->yuzBilgi(oge.alt, yb) && yb.silindirMi) op.delikYuzleri.push_back(oge.alt); } if (op.delikYuzleri.empty()) { op.hata = "Silindirik delik yüzü seçilmedi (yüz kipinde delik duvarını seçin)"; return; } op.ustZ = sinir.azami.z; op.altZ = sinir.asgari.z - 1.0; // kirici cikis payi op.guvenliZ = op.ustZ + 15.0; op.geriCekmeZ = op.ustZ + 3.0; break; } case CamIslemTip::Profil: case CamIslemTip::Cep: { if (ilk.alt == 0) { op.hata = "Düz bir yüz seçin (yüz kipi: 1)"; return; } geometri::YuzBilgi yb; if (!d->brep->yuzBilgi(ilk.alt, yb) || !yb.duzlemMi) { op.hata = "Seçilen yüz düzlemsel değil"; return; } op.yuz = ilk.alt; const Vec3d merkezW = d->donusum.noktaUygula(yb.merkez); if (op.tip == CamIslemTip::Cep) { op.altZ = merkezW.z; // cep tabani = secilen yuz op.ustZ = sinir.azami.z; // malzeme ustu } else { op.ustZ = merkezW.z; // profil: yuzden asagi kes op.altZ = sinir.asgari.z - 0.5; // tam kesip cikarma } op.guvenliZ = sinir.azami.z + 15.0; op.geriCekmeZ = sinir.azami.z + 3.0; break; } case CamIslemTip::Kaba3D: case CamIslemTip::Finis3D: case CamIslemTip::RestKaba: case CamIslemTip::AdvancedFinis: case CamIslemTip::ReworkFinis: { op.yuz = 0; // tum govde mesh'i op.ustZ = sinir.azami.z; op.altZ = sinir.asgari.z; op.guvenliZ = sinir.azami.z + 15.0; op.geriCekmeZ = sinir.azami.z + 3.0; break; } case CamIslemTip::SweepFinis: case CamIslemTip::KonturGudumlu: { // Tum govde mesh + surus kenar/kontur ordinalleri (secili kenarlar). op.yuz = 0; op.surusKenarlari.clear(); for (const SecimOge& oge : secililer) if (oge.govde == op.govde && oge.alt != 0) op.surusKenarlari.push_back(oge.alt); op.ustZ = sinir.azami.z; op.altZ = sinir.asgari.z; op.guvenliZ = sinir.azami.z + 15.0; op.geriCekmeZ = sinir.azami.z + 3.0; if (op.surusKenarlari.empty()) op.hata = "Sürüş kenarı/konturu seçilmedi (kenar kipinde rehber kenar seçin)"; break; } } } bool CamSistemi::hesapla(u32 kimlik) { CamIslem* op = bul(kimlik); if (!op || op->hesaplaniyor) return false; const Takim* tkP = takimBul(op->takimNo); if (!tkP) { op->hata = takimlar_.empty() ? "Takım kütüphanesi boş" : "Takım bulunamadı (#" + std::to_string(op->takimNo) + ")"; return false; } Dugum* d = sahne_.bul(op->govde); if (!d || !d->brep || !d->brep->gecerliMi()) { op->hata = "Kaynak gövde geçersiz — Geometri sekmesinden seçim yapın"; return false; } op->hata.clear(); const CamIslem params = *op; // worker kopyasi (islemler_ worker'da OKUNMAZ) const Takim takim = *tkP; auto sonuc = std::make_shared(); auto hataMsg = std::make_shared(); std::function is; switch (op->tip) { case CamIslemTip::Profil: case CamIslemTip::Cep: { if (op->yuz == 0) { op->hata = "Yüz seçilmedi (Geometri sekmesi → Seçimden Al)"; return false; } const auto yerel = d->brep->yuzKonturlari(op->yuz, 0.02); if (yerel.empty()) { op->hata = "Yüz konturu çıkarılamadı"; return false; } std::vector konturlar; f64 zMin = 1e300, zMax = -1e300; for (const auto& halka : yerel) { Kontur k; k.reserve(halka.size()); for (const Vec3d& n : halka) { const Vec3d w = d->donusum.noktaUygula(n); zMin = std::min(zMin, w.z); zMax = std::max(zMax, w.z); k.push_back({w.x, w.y}); } konturlar.push_back(std::move(k)); } if (zMax - zMin > 0.5) { op->hata = "Yüz yatay (XY düzlemine paralel) değil — 2.5D operasyon için yatay yüz gerekli"; return false; } const bool cep = op->tip == CamIslemTip::Cep; is = [params, takim, konturlar = std::move(konturlar), sonuc, hataMsg, cep](GorevBaglam& b) { try { const HesapGeri geri{[&b](f32 o, const char* m) { b.ilerlet(o, m ? m : ""); }, [&b] { return b.iptalIstendi(); }}; *sonuc = cep ? cepYolu(params, takim, konturlar, geri) : profilYolu(params, takim, konturlar); if (sonuc->bosMu()) *hataMsg = "Takım yolu üretilemedi (takım bu geometriye sığmıyor olabilir)"; } catch (const std::exception& e) { *hataMsg = std::string("Hesap hatası: ") + e.what(); } catch (...) { *hataMsg = "Hesap hatası (bilinmeyen)"; } }; break; } case CamIslemTip::Delik: { std::vector merkezler; for (const u32 yuz : op->delikYuzleri) { geometri::YuzBilgi yb; if (d->brep->yuzBilgi(yuz, yb) && yb.silindirMi) merkezler.push_back(d->donusum.noktaUygula(yb.eksenNokta)); } if (merkezler.empty()) { op->hata = "Delik merkezi bulunamadı (silindirik yüz seçin)"; return false; } is = [params, merkezler = std::move(merkezler), sonuc, hataMsg](GorevBaglam&) { try { *sonuc = delikYolu(params, merkezler); } catch (const std::exception& e) { *hataMsg = std::string("Hesap hatası: ") + e.what(); } }; break; } case CamIslemTip::Kaba3D: case CamIslemTip::Finis3D: case CamIslemTip::RestKaba: case CamIslemTip::SweepFinis: case CamIslemTip::AdvancedFinis: case CamIslemTip::KonturGudumlu: case CamIslemTip::ReworkFinis: { if (d->cpuKonum.empty() || d->cpuIndeks.empty()) { op->hata = "Gövdenin üçgen mesh verisi yok"; return false; } MeshGirdi mesh; mesh.noktalar.reserve(d->cpuKonum.size()); for (const Vec3f& v : d->cpuKonum) mesh.noktalar.push_back(d->donusum.noktaUygula({(f64)v.x, (f64)v.y, (f64)v.z})); mesh.indeksler = d->cpuIndeks; // Surus egrileri: secili BREP kenarlarindan dunya-uzayi XY polyline (exact). std::vector> surus; const bool surusGerek = op->tip == CamIslemTip::SweepFinis || op->tip == CamIslemTip::KonturGudumlu; if (surusGerek) { for (const u32 kenar : op->surusKenarlari) { const std::vector yerel = d->brep->kenarNoktalari(kenar); if (yerel.size() < 2) continue; std::vector egri; egri.reserve(yerel.size()); for (const Vec3d& n : yerel) { const Vec3d w = d->donusum.noktaUygula(n); egri.push_back({w.x, w.y}); } surus.push_back(std::move(egri)); } if (surus.empty()) { op->hata = "Sürüş kenarı çıkarılamadı (Geometri → Seçimden Al ile kenar seçin)"; return false; } } const CamIslemTip tip = op->tip; is = [params, takim, mesh = std::move(mesh), surus = std::move(surus), sonuc, hataMsg, tip](GorevBaglam& b) { try { const HesapGeri geri{[&b](f32 o, const char* m) { b.ilerlet(o, m ? m : ""); }, [&b] { return b.iptalIstendi(); }}; switch (tip) { case CamIslemTip::Kaba3D: *sonuc = kaba3DYolu(params, takim, mesh, geri); break; case CamIslemTip::Finis3D: *sonuc = finis3DYolu(params, takim, mesh, geri); break; case CamIslemTip::RestKaba: *sonuc = restKabaYolu(params, takim, mesh, geri); break; case CamIslemTip::SweepFinis: *sonuc = sweepFinisYolu(params, takim, mesh, surus, geri); break; case CamIslemTip::AdvancedFinis: *sonuc = advancedFinisYolu(params, takim, mesh, geri); break; case CamIslemTip::KonturGudumlu: *sonuc = konturGudumluYolu(params, takim, mesh, surus, geri); break; case CamIslemTip::ReworkFinis: *sonuc = reworkFinisYolu(params, takim, mesh, geri); break; default: break; } if (sonuc->bosMu()) *hataMsg = "Takım yolu üretilemedi (OpenCAMLib boş sonuç)"; } catch (const std::exception& e) { *hataMsg = std::string("Hesap hatası: ") + e.what(); } catch (...) { *hataMsg = "Hesap hatası (bilinmeyen)"; } }; break; } } op->hesaplaniyor = true; const u32 opKimlik = op->kimlik; cekirdek_.gorevler().kuyrukla( "CAM: " + op->ad, std::move(is), [this, opKimlik, sonuc, hataMsg] { CamIslem* o = bul(opKimlik); if (!o) return; // islem bu arada silinmis o->hesaplaniyor = false; if (!hataMsg->empty()) { o->hata = *hataMsg; return; } o->yol = std::move(*sonuc); o->kirli = false; yolDugumuGuncelle(*o); cekirdek_.olaylar().yayinla( CamYoluHesaplandi{o->kimlik, (u32)o->yol.hamleler.size()}, o->ad.c_str()); }); return true; } void CamSistemi::kirlileriHesapla() { for (CamIslem& op : islemler_) if (op.etkin && op.kirli && !op.hesaplaniyor && op.govde) hesapla(op.kimlik); } // ---- CATIA operasyon takim yolu hesabi (FAZ 1.2) ------------------------- bool CamSistemi::opHesapla(u32 kimlik) { CamOperasyon* op = opBul(kimlik); if (!op || op->hesaplaniyor) return false; const Takim* tkP = takimBul(op->takimId); if (!tkP) { op->hata = takimlar_.empty() ? "Takım kütüphanesi boş" : "Takım bulunamadı (#" + std::to_string(op->takimId) + ")"; return false; } op->hata.clear(); // Geometri op'ta dünya-uzayı olarak saklı (cam_secim doldurur) → BREP erişimi // gerekmez, worker'a tam kopya geçilir (islemler_ okunmaz). const CamOperasyon params = *op; const Takim takim = *tkP; auto sonuc = std::make_shared(); auto hataMsg = std::make_shared(); std::function is = [params, takim, sonuc, hataMsg](GorevBaglam& b) { try { const HesapGeri geri{[&b](f32 o, const char* m) { b.ilerlet(o, m ? m : ""); }, [&b] { return b.iptalIstendi(); }}; *sonuc = opYoluHesapla(params, takim, geri, *hataMsg); } catch (const std::exception& e) { *hataMsg = std::string("Hesap hatası: ") + e.what(); } catch (...) { *hataMsg = "Hesap hatası (bilinmeyen)"; } }; op->hesaplaniyor = true; const u32 opKimlik = op->kimlik; cekirdek_.gorevler().kuyrukla( "CAM Op: " + op->ad, std::move(is), [this, opKimlik, sonuc, hataMsg] { CamOperasyon* o = opBul(opKimlik); if (!o) return; // op bu arada silinmis o->hesaplaniyor = false; if (!hataMsg->empty()) { o->hata = *hataMsg; o->hesaplandi = false; return; } o->yol = std::move(*sonuc); o->hesaplandi = true; o->bayat = false; opYolDugumuGuncelle(*o); cekirdek_.olaylar().yayinla( CamOpYoluHesaplandi{o->kimlik, (u32)o->yol.hamleler.size()}, o->ad.c_str()); }); return true; } Varlik CamSistemi::camGrupAl() { if (camGrup_ == VARLIK_YOK) camGrup_ = sahne_.grupEkle("CAM Programı", VARLIK_YOK); return camGrup_; } void CamSistemi::yolDugumuGuncelle(CamIslem& op) { // Kesme/dalma hamlelerini LINE_LIST'e cevir (hizli hareketler cizilmez — sade gorunum). std::vector kenarlar; kenarlar.reserve(op.yol.hamleler.size() * 2); for (size_t i = 1; i < op.yol.hamleler.size(); ++i) { const Hamle& h = op.yol.hamleler[i]; if (h.tip == HamleTip::Hizli) continue; const Vec3d& a = op.yol.hamleler[i - 1].nokta; kenarlar.push_back({{(f32)a.x, (f32)a.y, (f32)a.z}, 0}); kenarlar.push_back({{(f32)h.nokta.x, (f32)h.nokta.y, (f32)h.nokta.z}, 0}); } const Aabbf sinir = op.yol.sinir(); if (kenarlar.empty() || !sinir.gecerliMi()) { // Bos yol: dugumu kaldir (gecersiz AABB kamera fit'ini bozmasin). if (op.yolDugum) sahne_.sil(op.yolDugum); op.yolDugum = 0; return; } const Vec3f renk{0.10f, 0.85f, 1.0f}; // neon-cyan (web CAM temasi) if (op.yolDugum && sahne_.bul(op.yolDugum)) { sahne_.kenarNesneGuncelle(op.yolDugum, kenarlar, sinir); } else { op.yolDugum = sahne_.kenarNesneEkle(op.ad + " Yolu", camGrupAl(), renk, kenarlar, sinir); } } void CamSistemi::opYolDugumuGuncelle(CamOperasyon& op) { // Kesme/dalma hamlelerini LINE_LIST'e cevir (hizli hareketler cizilmez). std::vector kenarlar; kenarlar.reserve(op.yol.hamleler.size() * 2); for (size_t i = 1; i < op.yol.hamleler.size(); ++i) { const Hamle& h = op.yol.hamleler[i]; if (h.tip == HamleTip::Hizli) continue; const Vec3d& a = op.yol.hamleler[i - 1].nokta; kenarlar.push_back({{(f32)a.x, (f32)a.y, (f32)a.z}, 0}); kenarlar.push_back({{(f32)h.nokta.x, (f32)h.nokta.y, (f32)h.nokta.z}, 0}); } const Aabbf sinir = op.yol.sinir(); if (kenarlar.empty() || !sinir.gecerliMi()) { if (op.yolDugum) sahne_.sil(op.yolDugum); op.yolDugum = 0; return; } const Vec3f renk{0.10f, 0.85f, 1.0f}; // neon-cyan (web CAM temasi) if (op.yolDugum && sahne_.bul(op.yolDugum)) { sahne_.kenarNesneGuncelle(op.yolDugum, kenarlar, sinir); } else { op.yolDugum = sahne_.kenarNesneEkle(op.ad + " Yolu", camGrupAl(), renk, kenarlar, sinir); } } std::string CamSistemi::gkod() const { return gkodUret(islemler_, takimlar_); } bool CamSistemi::gkodYaz(const std::string& yol) const { std::ofstream f(yol, std::ios::binary); if (!f) return false; const std::string s = gkod(); f.write(s.data(), (std::streamsize)s.size()); return (bool)f; } u32 CamSistemi::aptIceAktar(const AptSonuc& sonuc, bool sahneyeCiz, bool aktiviteAyir) { if (!sonuc.basarili || sonuc.yol.bosMu()) return 0; // Ortak govde: bir operasyon uret. dilim=false → tum yol (eski davranis birebir, // delikler dahil); dilim=true → [bas, bas+adet) hamle araligi (aktivite). auto opUret = [&](const std::string& ad, const Takim& kaynakTakim, f64 devir, Vec3d eksen, bool dilim, std::size_t bas, std::size_t adet) -> u32 { CamOperasyon op; op.kimlik = ++opSayac_; op.tip = CamIslemTipCatia::Contouring; // notr varsayilan (yol zaten hazir) op.ad = !ad.empty() ? ad : !sonuc.programAdi.empty() ? sonuc.programAdi : ("APT." + std::to_string(op.kimlik)); op.yorum = "İçe aktarılan APT (.FikoApt)"; // Takim: parse edilen takimi kutuphaneye ekle (numara cakismasini onle). Takim takim = kaynakTakim; if (takim.numara <= 0) takim.numara = 1; while (takimBul(takim.numara)) ++takim.numara; // bos numara bul if (takim.ad.empty()) takim.ad = op.ad + " Takım"; takimlar_.push_back(takim); op.takimId = takim.numara; op.hizlar.devir = devir > 0 ? devir : op.hizlar.devir; // Tool-axis (5-eksen yonu) parse'dan. op.takimYonu.yon = eksen; op.takimYonu.kaynak = TakimYonu::Kaynak::Custom; op.takimYonu.origin = sonuc.eksenOrigin; // Yol zaten hesaplanmis: dogrudan yukle + hesaplandi isaretle (recompute yok). if (dilim) { op.yol.hamleler.assign(sonuc.yol.hamleler.begin() + (std::ptrdiff_t)bas, sonuc.yol.hamleler.begin() + (std::ptrdiff_t)(bas + adet)); op.yol.istatistikGuncelle(); // dilimin kendi uzunluk/sure istatistigi } else { op.yol = sonuc.yol; } op.hesaplandi = true; op.bayat = false; operasyonlar_.push_back(std::move(op)); CamOperasyon& eklenen = operasyonlar_.back(); if (sahneyeCiz) opYolDugumuGuncelle(eklenen); // sahnede neon-cyan yol dugumu (sim'de oynanir) const u32 hamle = (u32)eklenen.yol.hamleler.size(); cekirdek_.olaylar().yayinla(CamOpEklendi{opSayac_}, eklenen.ad.c_str()); cekirdek_.olaylar().yayinla(AptOkundu{opSayac_, hamle}, eklenen.ad.c_str()); return opSayac_; }; // Cok bloklu APT → aktivite basina ayri operasyon (web APTCAT gibi). Hamlesiz // blok atlanir (yalniz basli/metadata blogu operasyon uretmesin). if (aktiviteAyir && sonuc.aktiviteler.size() > 1) { u32 ilk = 0; for (const AptAktivite& a : sonuc.aktiviteler) { if (a.hamleAdet == 0) continue; const u32 k = opUret(a.ad, a.takim, a.devir, a.takimEkseni, true, a.hamleBas, a.hamleAdet); if (!ilk) ilk = k; } if (ilk) { seciliOp = (int)ilk; return ilk; } // Hicbir aktivitede hamle yok → tek-operasyon yoluna dus (guvenli). } const u32 k = opUret(sonuc.operasyonAdi, sonuc.takim, sonuc.devir, sonuc.takimEkseni, false, 0, 0); seciliOp = (int)k; return k; } bool CamSistemi::aptMetinUret(u32 kimlik, std::string& cikti, u32& hamleSayi) const { const TakimYolu* yol = nullptr; int takimNo = 1; f64 devir = 0.0; std::string ad; // Once CATIA operasyonu, sonra klasik islem (const_cast: opBul/bul const degil, // yalniz okunur). auto* self = const_cast(this); if (CamOperasyon* op = self->opBul(kimlik)) { if (op->yol.bosMu()) return false; yol = &op->yol; takimNo = op->takimId; devir = op->hizlar.devir; ad = op->ad; } else if (CamIslem* is = self->bul(kimlik)) { if (is->yol.bosMu()) return false; yol = &is->yol; takimNo = is->takimNo; devir = is->devir; ad = is->ad; } else { return false; } Takim takim; if (const Takim* t = self->takimBul(takimNo)) takim = *t; AptSecenek sec; sec.partNo = ad.empty() ? "FIKATIA" : ad; sec.programAdi = sec.partNo; sec.devir = devir; cikti = aptYaz(*yol, takim, sec); hamleSayi = (u32)yol->hamleler.size(); return true; } bool CamSistemi::aptDisariAktar(u32 kimlik, const std::string& dosya) { std::string metin; u32 hamleSayi = 0; if (!aptMetinUret(kimlik, metin, hamleSayi)) return false; std::ofstream f(dosya, std::ios::binary); if (!f) return false; f.write(metin.data(), (std::streamsize)metin.size()); if (!f) return false; cekirdek_.olaylar().yayinla(AptYazildi{kimlik, hamleSayi}, "APT"); return true; } f64 CamSistemi::toplamSureDk() const { f64 t = 0; for (const CamIslem& op : islemler_) if (op.etkin) t += op.yol.sureDk; return t; } } // namespace fiko::cam