#include "fiko/pafta/pafta_uretim.hpp" #include #include #include namespace fiko::pafta { namespace { u64 karistir(u64 h, u64 v) { h ^= v + 0x9e3779b97f4a7c15ull + (h << 6) + (h >> 2); return h; } } // namespace u64 cizimImzasi(const geometri::BrepGovde* govde, geometri::Gorunum yon, Olcek olcek) { u64 h = 1469598103934665603ull; h = karistir(h, (u64)(std::uintptr_t)govde); h = karistir(h, (u64)yon); h = karistir(h, ((u64)(u32)olcek.pay << 32) | (u32)olcek.payda); return h; } u64 kesitImzasi(u64 taban, Vec2d a, Vec2d b) { u64 h = taban; const f64 d[4] = {a.x, a.y, b.x, b.y}; for (f64 v : d) { u64 bit = 0; std::memcpy(&bit, &v, sizeof bit); h = karistir(h, bit); } return h; } GorunumCizim gorunumUret(const geometri::BrepGovde& govde, geometri::Gorunum yon, Olcek olcek) { GorunumCizim c; c.imza = cizimImzasi(&govde, yon, olcek); const geometri::Izdusum2D iz = geometri::ortoIzdusum(govde, yon); if (!iz.gecerli) return c; // Sınır kutusu (ham izdüşüm uzayı) → merkez + ölçekli boyut. f64 minX = 1e300, minY = 1e300, maksX = -1e300, maksY = -1e300; const auto tara = [&](const std::vector>& gruplar) { for (const auto& pl : gruplar) for (const Vec2d& p : pl) { minX = std::min(minX, p.x); maksX = std::max(maksX, p.x); minY = std::min(minY, p.y); maksY = std::max(maksY, p.y); } }; tara(iz.gorunur); tara(iz.gizli); if (minX > maksX || minY > maksY) return c; // tamamen boş izdüşüm const f64 o = olcek.oran(); const Vec2d merkez{(minX + maksX) * 0.5, (minY + maksY) * 0.5}; const auto donustur = [&](const std::vector>& kaynak, std::vector>& hedef) { hedef.reserve(kaynak.size()); for (const auto& pl : kaynak) { std::vector y; y.reserve(pl.size()); for (const Vec2d& p : pl) y.push_back({(p.x - merkez.x) * o, (p.y - merkez.y) * o}); hedef.push_back(std::move(y)); } }; donustur(iz.gorunur, c.gorunur); donustur(iz.gizli, c.gizli); c.boyut = {(maksX - minX) * o, (maksY - minY) * o}; c.hamMerkez = merkez; c.gecerli = true; return c; } GorunumCizim kesitGorunumUret(const geometri::BrepGovde& govde, geometri::Gorunum yon, Olcek olcek, Vec3d duzlemNokta, Vec3d duzlemNormal) { const geometri::BrepGovde kesik = geometri::duzlemleBol(govde, duzlemNokta, duzlemNormal); const geometri::BrepGovde& kaynak = kesik.gecerliMi() ? kesik : govde; GorunumCizim c = gorunumUret(kaynak, yon, olcek); if (!c.gecerli || !kesik.gecerliMi()) return c; const f64 o = olcek.oran(); for (auto& kontur : geometri::kesitYuzKonturlari(kesik, yon, duzlemNokta, duzlemNormal)) { std::vector yerel; yerel.reserve(kontur.size()); for (const Vec2d& q : kontur) yerel.push_back({(q.x - c.hamMerkez.x) * o, (q.y - c.hamMerkez.y) * o}); c.kesitKonturlari.push_back(std::move(yerel)); } return c; } Vec2d hamdanYerele(const GorunumCizim& c, Vec2d ham, Olcek olcek) { const f64 o = olcek.oran(); return {(ham.x - c.hamMerkez.x) * o, (ham.y - c.hamMerkez.y) * o}; } Vec2d nokta3dYerele(const GorunumCizim& c, geometri::Gorunum yon, Vec3d nokta, Olcek olcek) { const geometri::GorunumEksen e = geometri::gorunumEksenleri(yon); const Vec3d v{nokta.x - e.kok.x, nokta.y - e.kok.y, nokta.z - e.kok.z}; const Vec2d ham{v.x * e.xEks.x + v.y * e.xEks.y + v.z * e.xEks.z, v.x * e.yEks.x + v.y * e.yEks.y + v.z * e.yEks.z}; return hamdanYerele(c, ham, olcek); } std::vector tutunmaAdaylari(const geometri::BrepGovde& govde, geometri::Gorunum yon, const GorunumCizim& cizim, Olcek olcek) { std::vector sonuc; if (!cizim.gecerli) return sonuc; // çıpa (hamMerkez) yoksa yerel uzay tanımsız const std::vector ham = geometri::izdusumNoktalari(govde, yon); sonuc.reserve(ham.size()); for (const geometri::IzdusumNokta& n : ham) { const Vec2d y = hamdanYerele(cizim, n.p, olcek); // İzdüşümde ÜST ÜSTE düşen köşeler tek adaya iner (kutuda 8 köşe → 4 nokta). bool var = false; for (const Vec2d& e : sonuc) if (std::abs(e.x - y.x) < 1e-7 && std::abs(e.y - y.y) < 1e-7) { var = true; break; } if (!var) sonuc.push_back(y); } return sonuc; } bool tutunmaYakala(const std::vector& adaylar, Vec2d hedef, f64 toleransMm, Vec2d& cikti) { f64 enIyi = toleransMm * toleransMm; bool bulundu = false; for (const Vec2d& a : adaylar) { const f64 dx = a.x - hedef.x, dy = a.y - hedef.y; const f64 d2 = dx * dx + dy * dy; if (d2 <= enIyi) { enIyi = d2; cikti = a; bulundu = true; } } return bulundu; } const GorunumCizim* CizimOnbellek::bul(u32 gorunumKimlik, u64 imza) const { const auto it = harita_.find(gorunumKimlik); if (it == harita_.end() || it->second.imza != imza) return nullptr; return &it->second; } const GorunumCizim* CizimOnbellek::bulHamm(u32 gorunumKimlik) const { const auto it = harita_.find(gorunumKimlik); return it == harita_.end() ? nullptr : &it->second; } void CizimOnbellek::ata(u32 gorunumKimlik, GorunumCizim c) { harita_[gorunumKimlik] = std::move(c); } void CizimOnbellek::sil(u32 gorunumKimlik) { harita_.erase(gorunumKimlik); } SayfaDonusum sayfaDonusum(SayfaOlcu s, f64 ekranG, f64 ekranY, Vec2d pan, f64 zoom, f64 kenarPx) { SayfaDonusum d; if (s.en <= 0 || s.boy <= 0 || ekranG <= 0 || ekranY <= 0) return d; const f64 kullanG = std::max(1.0, ekranG - 2 * kenarPx); const f64 kullanY = std::max(1.0, ekranY - 2 * kenarPx); d.olcek = std::min(kullanG / s.en, kullanY / s.boy) * (zoom > 0 ? zoom : 1.0); // Sayfa ekrana ortalanır; pan px cinsinden kaydırır. Sayfa (0,0) SOL-ALT olduğundan // ofset sol-alt köşenin ekran karşılığıdır (ekrana() y'yi çevirir). const f64 genislikPx = s.en * d.olcek, yukseklikPx = s.boy * d.olcek; d.ofset = {(ekranG - genislikPx) * 0.5 + pan.x, (ekranY + yukseklikPx) * 0.5 + pan.y}; return d; } u32 gorunumVur(const Pafta& p, Vec2d sayfaNoktasi, f64 toleransMm) { const auto& liste = p.gorunumler(); for (auto it = liste.rbegin(); it != liste.rend(); ++it) { if (!it->goster) continue; const f64 yariEn = it->boyut.x * 0.5 + toleransMm; const f64 yariBoy = it->boyut.y * 0.5 + toleransMm; if (std::abs(sayfaNoktasi.x - it->konum.x) <= yariEn && std::abs(sayfaNoktasi.y - it->konum.y) <= yariBoy) return it->kimlik; } return 0; } } // namespace fiko::pafta