#include "fiko/sahne/olcum_sistemi.hpp" #include #include #include #include "fiko/core/birim_bicim.hpp" // global küsürat: uzunluk/açı/alan/koordinat hanesi namespace fiko { namespace { constexpr f64 PI = 3.14159265358979323846; Vec3f f32e(const Vec3d& v) { return {(f32)v.x, (f32)v.y, (f32)v.z}; } // Olcu cizgisi ofset yonu: olculen dogruya DIK + EKRAN duzleminde yukari tercihli // (kameraya bakar, teknik resim gibi okunur). Kamera bazisi (sag/yukari) yoksa // dunya-Z'ye duser. Boylece ilk cizgi modelin icine/arkasina kacmaz. Vec3f ofsetYonSec(const Vec3f& a, const Vec3f& b, const Vec3f& sag, const Vec3f& yukari) { Vec3f ab = b - a; const bool bazVar = yukari.uzunlukKare() > 0.1f; if (ab.uzunlukKare() < 1e-12f) return bazVar ? yukari.birim() : Vec3f{0, 0, 1}; ab = ab.birim(); Vec3f n{}; if (bazVar) { // Ekran-yukari'yi ab'ye dik bilesene indir (Gram-Schmidt) n = yukari - ab * yukari.nokta(ab); if (n.uzunlukKare() < 1e-6f) n = sag - ab * sag.nokta(ab); // ab ekranda dikey → saga } if (n.uzunlukKare() < 1e-6f) { // baz yok/dejenere → dunya-Z n = ab.capraz({0, 0, 1}); if (n.uzunlukKare() < 1e-10f) n = ab.capraz({1, 0, 0}); if (n.uzunlukKare() < 1e-10f) return {0, 0, 1}; } n = n.birim(); // Ekranda yukari dogru gorunsun (kamera-yukari ile ayni yari-kure); baz yoksa +Z'ye if (bazVar) { if (n.nokta(yukari) < 0) n = n * -1.0f; } else if (n.z < 0) n = n * -1.0f; return n; } // Deger metni — küsürat GLOBAL birim ayarindan (fiko::birim) okunur; türüne göre // uzunluk/açı/alan hanesi seçilir. "Nerede gösterirse aynı hassasiyet" tek kaynagi. void degerMetin(Olcum& o) { using birim::Birim; const Birim bir = o.tur == OlcumTur::Aci ? Birim::Aci : o.tur == OlcumTur::Alan ? Birim::Alan : Birim::Uzunluk; const int d = birim::hane(bir); char fmt[24], m[64]; const char* onek = o.tur == OlcumTur::Cap ? "⌀ " : o.tur == OlcumTur::Yaricap ? "R " : ""; const char* sonek = o.tur == OlcumTur::Aci ? "°" : o.tur == OlcumTur::Alan ? " mm²" : " mm"; std::snprintf(fmt, sizeof(fmt), "%s%%.%df%s", onek, d, sonek); std::snprintf(m, sizeof(m), fmt, o.deger); o.metin = m; } // Akilli mod → geometriye gore en anlamli sabit modu sec (CATIA sezgisi). MesafeModu akilliCoz(const OlcumRef& r) { if (r.silindir || r.kure || r.cember) return MesafeModu::Merkez; // eksen/merkez olcumu if (r.duzlem) return MesafeModu::KisaDuz; // dik mesafe return MesafeModu::EnKisa; } // Bir secimin temsil noktasini moda gore sec (hedef: digerinin referans noktasi). Vec3f secimNoktasi(const OlcumRef& r, MesafeModu m, const Vec3f& hedef) { if (m == MesafeModu::Merkez || r.noktalar.empty()) return r.merkez; const bool uzak = (m == MesafeModu::EnUzak || m == MesafeModu::UzakDuz); Vec3f best = r.noktalar.front(); f32 bestD = uzak ? -1.0e30f : 1.0e30f; for (const Vec3f& p : r.noktalar) { const f32 d = (p - hedef).uzunlukKare(); if (uzak ? (d > bestD) : (d < bestD)) { bestD = d; best = p; } } return best; } // Noktayi duzleme (r.merkez + r.normal) dik projekte et — temiz dik olcu. Vec3f duzlemeProjekte(const OlcumRef& r, const Vec3f& p) { const Vec3f n = r.normal.birim(); return p - n * (p - r.merkez).nokta(n); } // Per-secim modlu mesafe: her secim KENDI moduyla endpoint turetir; duzlem+dik modda // dik projeksiyon uygulanir. Iki gecisli (her biri digerinin cozumune gore). void mesafeHesapPer(const OlcumRef& A, const OlcumRef& B, MesafeModu m1, MesafeModu m2, Vec3f& outA, Vec3f& outB, f64& deger) { Vec3f pA = secimNoktasi(A, m1, B.merkez); Vec3f pB = secimNoktasi(B, m2, pA); pA = secimNoktasi(A, m1, pB); const bool dik1 = (m1 == MesafeModu::KisaDuz || m1 == MesafeModu::UzakDuz); const bool dik2 = (m2 == MesafeModu::KisaDuz || m2 == MesafeModu::UzakDuz); if (A.duzlem && dik1) pA = duzlemeProjekte(A, pB); if (B.duzlem && dik2) pB = duzlemeProjekte(B, pA); outA = pA; outB = pB; deger = (f64)(pB - pA).uzunluk(); } } // namespace OlcumSistemi::OlcumSistemi(Sahne& sahne, OlayGunlugu& olaylar) : sahne_(sahne), olaylar_(olaylar) { // Parametrik-linkli: kaynak geometri degisince ilgili olcumler otomatik yenilenir. olaylar_.abone([this](const DonusumDegisti& e) { guncelle(e.varlik); }); olaylar_.abone([this](const BrepDegisti& e) { guncelle(e.varlik); }); olaylar_.abone([this](const VarlikSilindi& e) { guncelle(e.varlik); }); } const char* OlcumSistemi::modAd(MesafeModu m) const { switch (m) { case MesafeModu::Akilli: return "Akıllı"; case MesafeModu::KisaDuz: return "Kısa Düz"; case MesafeModu::EnKisa: return "En Kısa"; case MesafeModu::Merkez: return "Merkez"; case MesafeModu::EnUzak: return "En Uzak"; case MesafeModu::UzakDuz: return "Uzak Düz"; } return ""; } const char* OlcumSistemi::modSimge(MesafeModu m) const { switch (m) { case MesafeModu::Akilli: return "✦"; case MesafeModu::KisaDuz: return "⊥"; case MesafeModu::EnKisa: return "↔"; case MesafeModu::Merkez: return "⊙"; case MesafeModu::EnUzak: return "⤢"; case MesafeModu::UzakDuz: return "⇕"; } return ""; } void OlcumSistemi::metinleriYenile() { // Koordinat türü XYZ metnini degerMetin üretmez (yenidenHesapla'da kurulur) → // yalnız skaler ölçüleri yeniden biçimle; koordinat için canli'yi yeniden hesapla. if (canliVar && canli.tur != OlcumTur::Koordinat) degerMetin(canli); for (Olcum& o : olcumler_) if (o.tur != OlcumTur::Koordinat) degerMetin(o); for (OlcumZincir& z : zincirler_) zincirCoz(z); // yeni ondalikla metinler if (zincirVar) zincirCoz(canliZincir); yenidenHesapla(); // koordinat/XYZ ve canli için tam yeniden hesap } SecimFiltre OlcumSistemi::aktifFiltre() const { if (kip == OlcumKip::Kumpas || kip == OlcumKip::Zincir) return filtre1; return (!ref1.var || (ref1.var && ref2.var)) ? filtre1 : filtre2; } bool OlcumSistemi::refCoz(const OlcumBaglanti& link, OlcumRef& r) const { r = OlcumRef{}; if (!link.var) return false; Dugum* d = sahne_.bul(link.govde); if (!d) return false; // Serbest yuzey noktasi: topoloji gerekmez, govde-yerel konum donusumle dunyaya. if (link.serbest) { r.link = link; r.var = true; r.tipAd = "Nokta"; r.altTipAd = "Serbest"; r.merkez = f32e(d->donusum.noktaUygula({(f64)link.yerel.x, (f64)link.yerel.y, (f64)link.yerel.z})); r.noktalar = {r.merkez}; return true; } if (!d->brep) return false; const auto W = [&](const Vec3d& p) { return f32e(d->donusum.noktaUygula(p)); }; const auto WY = [&](const Vec3d& v) { return f32e(d->donusum.yonelim.dondur(v)).birim(); }; const f64 k = d->donusum.olcek.x; r.link = link; r.var = true; // KYA: kalıcı kimlik varsa GÜNCEL brep'ten ordinali yeniden çöz → edit sonrası ordinal kayınca // link doğru öğeyi bulur (kaybolmaz). KID yok/çözülmezse eski ordinal (birebir fallback davranış). u32 alt = link.alt; if (link.kid && geometri::kaliciKimlikAcikMi()) { const u32 yeni = link.kip == SecimKip::Yuz ? d->brep->yuzKimlikOrd(link.kid) : link.kip == SecimKip::Kenar ? d->brep->kenarKimlikOrd(link.kid) : link.kip == SecimKip::Nokta ? d->brep->noktaKimlikOrd(link.kid) : 0; if (yeni) alt = yeni; } if (link.kip == SecimKip::Nokta) { Vec3d p; if (!d->brep->noktaKonum(alt, p)) return false; r.tipAd = "Nokta"; r.merkez = W(p); r.noktalar = {r.merkez}; } else if (link.kip == SecimKip::Kenar) { geometri::KenarBilgi kb; if (!d->brep->kenarBilgi(alt, kb)) return false; r.tipAd = "Çizgi"; r.uzunluk = kb.uzunluk * k; r.merkez = W(kb.orta); for (const Vec3d& p : d->brep->kenarNoktalari(alt)) r.noktalar.push_back(W(p)); if (kb.cemberMi) { r.cember = true; r.altTipAd = "Çember"; r.yaricap = (f32)(kb.yaricap * k); r.merkez = W(kb.merkez); r.normal = WY(kb.normal); } else if (kb.dogruMu) { r.dogru = true; r.altTipAd = "Doğru"; r.yon = WY(kb.yon); } else { r.altTipAd = "Eğri"; } if (r.noktalar.empty()) r.noktalar = {W(kb.bas), W(kb.son)}; r.hlKontur = {r.noktalar}; // kenar polyline → highlight } else if (link.kip == SecimKip::Yuz) { geometri::YuzBilgi yb; if (!d->brep->yuzBilgi(alt, yb)) return false; r.tipAd = "Yüzey"; r.alan = yb.alan * k * k; r.merkez = W(yb.merkez); for (const auto& kontur : d->brep->yuzKonturlari(alt)) { // yüz sınırı → highlight std::vector w; w.reserve(kontur.size() + 1); for (const Vec3d& p : kontur) w.push_back(W(p)); if (w.size() >= 2) { w.push_back(w.front()); r.hlKontur.push_back(std::move(w)); } } for (const Vec3d& p : d->brep->yuzNoktalari(alt)) r.noktalar.push_back(W(p)); if (yb.duzlemMi) { r.duzlem = true; r.altTipAd = "Düzlem"; r.normal = WY(yb.normal); } else if (yb.silindirMi) { r.silindir = true; r.altTipAd = "Silindir"; r.yaricap = (f32)(yb.yaricap * k); r.normal = WY(yb.eksen); } else if (yb.kureMi) { r.kure = true; r.altTipAd = "Küre"; r.yaricap = (f32)(yb.yaricap * k); } else { r.altTipAd = "Eğri"; } if (r.noktalar.empty()) r.noktalar = {r.merkez}; } else { r.tipAd = "Gövde"; r.merkez = d->dunyaMerkez(); r.noktalar = {r.merkez}; } return true; } void OlcumSistemi::olcumHesapla(Olcum& o, bool ilk) const { OlcumRef A, B; const bool aVar = refCoz(o.k1, A); const bool bVar = o.k2.var ? refCoz(o.k2, B) : false; if (!aVar || (o.k2.var && !bVar)) { o.gecerli = false; return; } o.gecerli = true; char buf[128]; // ---- Kumpas / tekli: oge ozellikleri ---- if (!o.k2.var) { if (A.link.kip == SecimKip::Nokta) { o.tur = OlcumTur::Koordinat; o.a = o.b = o.c = A.merkez; { const Vec3f kc = eksenKoord(A.merkez); char xf[40]; const int dd = birim::hane(birim::Birim::Koordinat); std::snprintf(xf, sizeof(xf), "X %%.%df\nY %%.%df\nZ %%.%df", dd, dd, dd); std::snprintf(buf, sizeof(buf), xf, kc.x, kc.y, kc.z); } o.metin = buf; o.aciklama = eksenRef.var ? ("Nokta · eksen: " + eksenAdi()) : std::string("Nokta"); } else if (A.link.kip == SecimKip::Kenar) { if (A.cember) { o.tur = OlcumTur::Yaricap; o.deger = A.yaricap; o.c = A.merkez; o.a = A.merkez; o.b = A.noktalar.empty() ? A.merkez : A.noktalar.front(); o.aciklama = "Yarıçap"; } else { o.tur = OlcumTur::Uzunluk; o.deger = A.uzunluk; o.a = A.noktalar.front(); o.b = A.noktalar.back(); o.aciklama = A.dogru ? "Doğru Uzunluk" : "Eğri Uzunluk"; } degerMetin(o); } else if (A.link.kip == SecimKip::Yuz) { if (A.silindir) { o.tur = OlcumTur::Cap; o.deger = 2.0 * A.yaricap; o.c = A.merkez; Vec3f dik = A.normal.capraz({0, 0, 1}); if (dik.uzunlukKare() < 1e-8f) dik = A.normal.capraz({1, 0, 0}); dik = dik.birim() * A.yaricap; o.a = A.merkez - dik; o.b = A.merkez + dik; o.aciklama = "Çap"; } else if (A.kure) { o.tur = OlcumTur::Yaricap; o.deger = A.yaricap; o.c = A.merkez; o.a = A.merkez; o.b = A.merkez + Vec3f{A.yaricap, 0, 0}; o.aciklama = "Küre Yarıçapı"; } else { o.tur = OlcumTur::Alan; o.deger = A.alan; o.a = o.b = o.c = A.merkez; o.aciklama = "Yüzey Alanı"; } degerMetin(o); } else { o.tur = OlcumTur::Koordinat; o.a = o.b = o.c = A.merkez; { const Vec3f kc = eksenKoord(A.merkez); char xf[40]; const int dd = birim::hane(birim::Birim::Koordinat); std::snprintf(xf, sizeof(xf), "X %%.%df\nY %%.%df\nZ %%.%df", dd, dd, dd); std::snprintf(buf, sizeof(buf), xf, kc.x, kc.y, kc.z); } o.metin = buf; o.aciklama = eksenRef.var ? ("Gövde Merkezi · eksen: " + eksenAdi()) : std::string("Gövde Merkezi"); } if (ilk && (o.tur == OlcumTur::Uzunluk)) { o.ofsetYon = ofsetYonSec(o.a, o.b, kameraSag, kameraYukari); o.ofset = std::max((o.b - o.a).uzunluk() * 0.18f, 0.02f); } else if (o.tur == OlcumTur::Uzunluk) { o.ofsetYon = ofsetYonSec(o.a, o.b, kameraSag, kameraYukari); } return; } // Per-secim modlar: Akilli → geometriye gore otomatik cozulur. const MesafeModu m1 = (o.mod1 == MesafeModu::Akilli) ? akilliCoz(A) : o.mod1; const MesafeModu m2 = (o.mod2 == MesafeModu::Akilli) ? akilliCoz(B) : o.mod2; // ---- Cetvel / ikili: iki duzlem arasi aci mi mesafe mi? ---- // Iki duzlem, paralel degil ve HER IKI mod da Akilli → aci (kullanici mod secerse mesafe). if (A.duzlem && B.duzlem && o.mod1 == MesafeModu::Akilli && o.mod2 == MesafeModu::Akilli) { const f32 d = std::abs(A.normal.nokta(B.normal)); if (d < 0.9998f) { const f32 aci = std::acos(std::clamp(d, -1.0f, 1.0f)) * 180.0f / (f32)PI; o.tur = OlcumTur::Aci; o.deger = aci; o.a = A.merkez; o.b = B.merkez; o.c = (A.merkez + B.merkez) * 0.5f; std::snprintf(buf, sizeof(buf), "%.1f° Açılı Yüzeyler Arası Mesafe", aci); o.aciklama = buf; degerMetin(o); return; } } o.tur = OlcumTur::Mesafe; mesafeHesapPer(A, B, m1, m2, o.a, o.b, o.deger); // Aciklama (tip etiketi) — moda ve geometri ciftine gore const SecimKip ka = A.link.kip, kb = B.link.kip; const auto ciftMi = [&](SecimKip x, SecimKip y) { return (ka == x && kb == y) || (ka == y && kb == x); }; if (m1 == MesafeModu::Merkez && m2 == MesafeModu::Merkez) o.aciklama = "Merkez-Merkez Mesafesi"; else if (A.duzlem && B.duzlem) o.aciklama = "Paralel Yüzeyler Arası Mesafe"; else if (ciftMi(SecimKip::Yuz, SecimKip::Nokta)) o.aciklama = "Yüzey-Nokta Mesafesi"; else if (ciftMi(SecimKip::Nokta, SecimKip::Nokta)) o.aciklama = "Nokta-Nokta Mesafesi"; else if (ciftMi(SecimKip::Kenar, SecimKip::Nokta)) o.aciklama = "Çizgi-Nokta Mesafesi"; else if (ciftMi(SecimKip::Kenar, SecimKip::Kenar)) o.aciklama = "Çizgi-Çizgi Mesafesi"; else if (ciftMi(SecimKip::Yuz, SecimKip::Kenar)) o.aciklama = "Yüzey-Çizgi Mesafesi"; else if (ciftMi(SecimKip::Yuz, SecimKip::Yuz)) o.aciklama = "Yüzeyler Arası Mesafe"; else o.aciklama = "Mesafe"; degerMetin(o); o.ofsetYon = ofsetYonSec(o.a, o.b, kameraSag, kameraYukari); if (ilk) o.ofset = std::max((o.b - o.a).uzunluk() * 0.18f, 0.02f); } void OlcumSistemi::linkAl(const OlcumBaglanti& link) { if (kip == OlcumKip::Kumpas) { canli.k1 = link; canli.k2 = OlcumBaglanti{}; } else { // Cetvel: bos/tamamlanmis ise Secim1'e, aksi halde Secim2'ye if (!canli.k1.var || (canli.k1.var && canli.k2.var)) { canli.k1 = link; canli.k2 = OlcumBaglanti{}; } else { canli.k2 = link; } } refCoz(canli.k1, ref1); canli.k2.var ? (void)refCoz(canli.k2, ref2) : (void)(ref2 = OlcumRef{}); const bool hazir = canli.k1.var && (kip == OlcumKip::Kumpas || canli.k2.var); if (hazir) { canli.aci = 0; canli.ofset = 0; canli.mod1 = mod1; canli.mod2 = mod2; // aktif per-secim modlari uygula olcumHesapla(canli, true); canliVar = canli.gecerli; if (canliVar && kaliciVarsayilan) kalicilastir(); } else { canliVar = false; } } void OlcumSistemi::secimAl(u32 govde, u32 alt, int vurguTur) { const SecimKip sk = vurguTur == 1 ? SecimKip::Yuz : vurguTur == 2 ? SecimKip::Kenar : vurguTur == 3 ? SecimKip::Nokta : SecimKip::Govde; OlcumBaglanti link{true, govde, alt, sk}; // KYA: ölçüm anında öğenin kalıcı kimliğini yakala → geometri edit'lense de link KID ile bulunur. if (geometri::kaliciKimlikAcikMi() && sk != SecimKip::Govde) { if (Dugum* d = sahne_.bul(govde); d && d->brep) { if (!d->brep->kimlikliMi()) d->brep->kimlikleriBaslat(); // ölçülen gövde henüz etiketsizse etiketle link.kid = sk == SecimKip::Yuz ? d->brep->yuzKimlik(alt) : sk == SecimKip::Kenar ? d->brep->kenarKimlik(alt) : d->brep->noktaKimlik(alt); } } if (kip == OlcumKip::Zincir) zincirNoktaEkle(link); else linkAl(link); } void OlcumSistemi::serbestNoktaAl(u32 govde, const Vec3f& dunyaNokta) { Dugum* d = sahne_.bul(govde); if (!d) return; const Vec3d y = d->donusum.ters().noktaUygula( {(f64)dunyaNokta.x, (f64)dunyaNokta.y, (f64)dunyaNokta.z}); OlcumBaglanti link{}; link.var = true; link.govde = govde; link.alt = 0; link.kip = SecimKip::Nokta; link.serbest = true; link.yerel = {(f32)y.x, (f32)y.y, (f32)y.z}; if (kip == OlcumKip::Zincir) zincirNoktaEkle(link); else linkAl(link); } void OlcumSistemi::secimSifirla() { ref1 = OlcumRef{}; ref2 = OlcumRef{}; canli = Olcum{}; canliVar = false; canliZincir = OlcumZincir{}; zincirVar = false; eksenSecModu = false; // transient "sahneden seç" modu kapanır (eksenRef ise KORUNUR) } // ---- Kumpas referans ekseni ---- void OlcumSistemi::eksenAl(u32 govde, u32 alt, int vurguTur) { const SecimKip sk = vurguTur == 1 ? SecimKip::Yuz : vurguTur == 2 ? SecimKip::Kenar : vurguTur == 3 ? SecimKip::Nokta : SecimKip::Govde; eksenRef = OlcumBaglanti{true, govde, alt, sk}; eksenSecModu = false; yenidenHesapla(); // canlı koordinat ölçümü yeni çerçeveyle güncellensin } void OlcumSistemi::eksenTemizle() { eksenRef = OlcumBaglanti{}; yenidenHesapla(); } std::string OlcumSistemi::eksenAdi() const { if (!eksenRef.var) return "Global (0,0,0)"; Dugum* d = sahne_.bul(eksenRef.govde); return d ? (d->ad.empty() ? std::string("Gövde") : d->ad) : std::string("(silinmiş)"); } Vec3f OlcumSistemi::eksenKoord(const Vec3f& dunya) const { if (!eksenRef.var) return dunya; Dugum* d = sahne_.bul(eksenRef.govde); if (!d) return dunya; const Vec3d l = d->donusum.ters().noktaUygula({(f64)dunya.x, (f64)dunya.y, (f64)dunya.z}); return {(f32)l.x, (f32)l.y, (f32)l.z}; } // ---- Zincir kipi ---- bool OlcumSistemi::zincirNoktaKonum(const OlcumBaglanti& link, Vec3f& out) const { OlcumRef r; if (!refCoz(link, r)) return false; out = r.merkez; return true; } void OlcumSistemi::zincirCoz(OlcumZincir& z) const { z.dunya.clear(); z.segment.clear(); z.toplam = 0; z.gecerli = true; for (const OlcumBaglanti& l : z.noktalar) { Vec3f p; if (!zincirNoktaKonum(l, p)) { z.gecerli = false; continue; } z.dunya.push_back(p); } const int n = (int)z.dunya.size(); const int lim = z.kapali ? n : n - 1; for (int i = 0; i < lim && n >= 2; ++i) { const f64 d = (f64)(z.dunya[(i + 1) % n] - z.dunya[i]).uzunluk(); z.segment.push_back(d); z.toplam += d; } const int dd = birim::hane(birim::Birim::Uzunluk); char fmt[40], m[80]; std::snprintf(fmt, sizeof(fmt), "Σ %%.%df mm · %%d nokta", dd); std::snprintf(m, sizeof(m), fmt, z.toplam, (int)z.dunya.size()); z.metin = m; } void OlcumSistemi::zincirNoktaEkle(const OlcumBaglanti& link) { canliZincir.noktalar.push_back(link); zincirCoz(canliZincir); zincirVar = !canliZincir.noktalar.empty(); refCoz(link, ref1); // son eklenen nokta highlight'i } void OlcumSistemi::zincirGeriAl() { if (canliZincir.noktalar.empty()) return; canliZincir.noktalar.pop_back(); zincirCoz(canliZincir); zincirVar = !canliZincir.noktalar.empty(); if (!zincirVar) ref1 = OlcumRef{}; } void OlcumSistemi::zincirKapatToggle() { canliZincir.kapali = !canliZincir.kapali; zincirCoz(canliZincir); } bool OlcumSistemi::zincirKalicilastir() { if (canliZincir.noktalar.size() < 2) return false; zincirCoz(canliZincir); if (!canliZincir.gecerli) return false; OlcumZincir z = canliZincir; z.kimlik = ++sayac_; zincirler_.push_back(std::move(z)); olaylar_.yayinla(OlcumEklendi{zincirler_.back().kimlik}, zincirler_.back().metin.c_str()); canliZincir = OlcumZincir{}; zincirVar = false; ref1 = OlcumRef{}; return true; } void OlcumSistemi::zincirSifirla() { canliZincir = OlcumZincir{}; zincirVar = false; ref1 = OlcumRef{}; } void OlcumSistemi::zincirSil(u32 kimlik) { const auto it = std::find_if(zincirler_.begin(), zincirler_.end(), [&](const OlcumZincir& z) { return z.kimlik == kimlik; }); if (it == zincirler_.end()) return; zincirler_.erase(it); olaylar_.yayinla(OlcumSilindi{kimlik}); } void OlcumSistemi::zincirTemizle() { for (const OlcumZincir& z : zincirler_) olaylar_.yayinla(OlcumSilindi{z.kimlik}); zincirler_.clear(); } void OlcumSistemi::yenidenHesapla() { if (!canliVar) return; canli.mod1 = mod1; canli.mod2 = mod2; olcumHesapla(canli, false); canliVar = canli.gecerli; } bool OlcumSistemi::kalicilastir() { if (!canliVar || !canli.gecerli) return false; Olcum o = canli; o.kimlik = ++sayac_; olcumler_.push_back(std::move(o)); olaylar_.yayinla(OlcumEklendi{olcumler_.back().kimlik}, olcumler_.back().metin.c_str()); return true; } void OlcumSistemi::olcumEkle(const Olcum& o) { // dosya yükleme: link + cache türet Olcum m = o; olcumHesapla(m, false); // ofset/açı/mod korunur; deger/metin/a/b/c/yay yeniden türetilir if (m.kimlik > sayac_) sayac_ = m.kimlik; // kimlik çakışması önle olcumler_.push_back(std::move(m)); } void OlcumSistemi::zincirEkle(const OlcumZincir& z) { // dosya yükleme: link + cache türet OlcumZincir m = z; zincirCoz(m); if (m.kimlik > sayac_) sayac_ = m.kimlik; zincirler_.push_back(std::move(m)); } void OlcumSistemi::guncelle(u32 govde) { for (Olcum& o : olcumler_) if (o.k1.govde == govde || (o.k2.var && o.k2.govde == govde)) olcumHesapla(o, false); if (canliVar && (canli.k1.govde == govde || (canli.k2.var && canli.k2.govde == govde))) { olcumHesapla(canli, false); canliVar = canli.gecerli; refCoz(canli.k1, ref1); canli.k2.var ? (void)refCoz(canli.k2, ref2) : (void)(ref2 = OlcumRef{}); } // Zincirler: govdeyi referans alan varsa yeniden coz (parametrik link) const auto ilgiliZincir = [&](const OlcumZincir& z) { for (const OlcumBaglanti& l : z.noktalar) if (l.govde == govde) return true; return false; }; for (OlcumZincir& z : zincirler_) if (ilgiliZincir(z)) zincirCoz(z); if (zincirVar && ilgiliZincir(canliZincir)) zincirCoz(canliZincir); } void OlcumSistemi::sil(u32 kimlik) { const auto it = std::find_if(olcumler_.begin(), olcumler_.end(), [&](const Olcum& o) { return o.kimlik == kimlik; }); if (it == olcumler_.end()) return; olcumler_.erase(it); olaylar_.yayinla(OlcumSilindi{kimlik}); } void OlcumSistemi::temizle() { for (const Olcum& o : olcumler_) olaylar_.yayinla(OlcumSilindi{o.kimlik}); olcumler_.clear(); } }