#include #include #include "fiko/sketch/eskiz_veri.hpp" // CATIA parametrik kompozit entity araclari. Her araç mevcut ekleme desenleri // (cizgiEkle/daireEkle/yayEkle/kisitEkle) ile KOMPOZE eder + otomatik geometrik // kisitlar kurar. coz() CAGRILMAZ (cagiran katman — main.cpp — sonrasi cozer). namespace fiko::eskiz { namespace { constexpr Skalar kPi = 3.14159265358979323846; } // namespace std::vector EskizVeri::slotEkle(Skalar x1, Skalar y1, Skalar x2, Skalar y2, Skalar r) { // Slot ekseni yonu + dik birim vektor (tegel cizgi ofseti icin). Skalar dx = x2 - x1, dy = y2 - y1; Skalar len = std::sqrt(dx * dx + dy * dy); if (len < 1e-9) { dx = 1.0; dy = 0.0; len = 1.0; } const Skalar ux = dx / len, uy = dy / len; // eksen birim const Skalar nx = -uy, ny = ux; // dik birim const Skalar ox = nx * r, oy = ny * r; // Iki tegel cizgi (eksen boyunca, +n ve -n tarafinda). u32 cizgiUst = cizgiEkle(x1 + ox, y1 + oy, x2 + ox, y2 + oy); u32 cizgiAlt = cizgiEkle(x1 - ox, y1 - oy, x2 - ox, y2 - oy); // Iki uc yay (yarim daire) DIŞ taraftan (sol uç -u, sağ uç +u üzerinden). Yay a0→a1 // ARTAN yonde ornekleir; sol yay a0..a0+π (orta = aciEksen+π = -u dış), sağ yay // aciEksen-π/2..+π/2 (orta = aciEksen = +u dış). Eski sol yay azalan→iç taraftan (hata). Skalar aciEksen = std::atan2(uy, ux); u32 yaySol = yayEkle(x1, y1, r, aciEksen + kPi * 0.5, aciEksen + kPi * 1.5); u32 yaySag = yayEkle(x2, y2, r, aciEksen - kPi * 0.5, aciEksen + kPi * 0.5); // Kisitlar: iki cizgi paralel + iki yay esit yaricap + cizgiler yaylara tegel. kisitEkle(KisitTip::Paralel, {cizgiUst, cizgiAlt}); kisitEkle(KisitTip::Esit, {yaySol, yaySag}); kisitEkle(KisitTip::Tegel, {cizgiUst, yaySol}); kisitEkle(KisitTip::Tegel, {cizgiUst, yaySag}); kisitEkle(KisitTip::Tegel, {cizgiAlt, yaySol}); kisitEkle(KisitTip::Tegel, {cizgiAlt, yaySag}); return {yaySol, cizgiUst, yaySag, cizgiAlt}; } std::vector EskizVeri::cokgenEkle(Skalar cx, Skalar cy, Skalar r, int kenarSayisi) { if (kenarSayisi < 3) kenarSayisi = 3; const int n = kenarSayisi; const Skalar adim = 2.0 * kPi / (Skalar)n; // Kose noktalari (cevrel cember uzerinde). std::vector kx((std::size_t)n), ky((std::size_t)n); for (int i = 0; i < n; ++i) { Skalar aci = (Skalar)i * adim - kPi * 0.5; // ilk kose ustte kx[(std::size_t)i] = cx + r * std::cos(aci); ky[(std::size_t)i] = cy + r * std::sin(aci); } // N kenar cizgisi (kose[i] -> kose[i+1]). std::vector cizgiler; cizgiler.reserve((std::size_t)n); for (int i = 0; i < n; ++i) { int j = (i + 1) % n; cizgiler.push_back(cizgiEkle(kx[(std::size_t)i], ky[(std::size_t)i], kx[(std::size_t)j], ky[(std::size_t)j])); } // Koseler cakisik (zincir kapali). for (int i = 0; i < n; ++i) { int j = (i + 1) % n; kisitEkle(KisitTip::Cakisik, {cizgiler[(std::size_t)i], cizgiler[(std::size_t)j]}, {1, 0}, 0); } // Tum kenarlar esit uzunluk (ilk kenara gore). for (int i = 1; i < n; ++i) kisitEkle(KisitTip::Esit, {cizgiler[0], cizgiler[(std::size_t)i]}); // Yapi cevrel cemberi + her kose cember uzerinde (duzgun cokgeni sabitler). u32 cember = daireEkle(cx, cy, r); yapiAyarla(cember, true); for (int i = 0; i < n; ++i) kisitEkle(KisitTip::NoktaUzerinde, {cizgiler[(std::size_t)i], cember}, {0, 0}, 0); std::vector sonuc = cizgiler; sonuc.push_back(cember); return sonuc; } std::vector EskizVeri::merkezliDikdortgenEkle(Skalar cx, Skalar cy, Skalar yariEn, Skalar yariBoy) { // Koseler: (-en,-boy),(+en,-boy),(+en,+boy),(-en,+boy) merkez etrafinda. const Skalar x0 = cx - yariEn, x1 = cx + yariEn; const Skalar y0 = cy - yariBoy, y1 = cy + yariBoy; u32 alt = cizgiEkle(x0, y0, x1, y0); u32 sag = cizgiEkle(x1, y0, x1, y1); u32 ust = cizgiEkle(x1, y1, x0, y1); u32 sol = cizgiEkle(x0, y1, x0, y0); // Koseler cakisik. kisitEkle(KisitTip::Cakisik, {alt, sag}, {1, 0}, 0); kisitEkle(KisitTip::Cakisik, {sag, ust}, {1, 0}, 0); kisitEkle(KisitTip::Cakisik, {ust, sol}, {1, 0}, 0); kisitEkle(KisitTip::Cakisik, {sol, alt}, {1, 0}, 0); // Dikdortgen sekli: alt/ust yatay, sol/sag dikey. kisitEkle(KisitTip::Yatay, {alt}); kisitEkle(KisitTip::Yatay, {ust}); kisitEkle(KisitTip::Dikey, {sol}); kisitEkle(KisitTip::Dikey, {sag}); // Merkez simetrisi: merkez noktasi (yapi) + karsit koseler ona simetrik. u32 mrk = noktaEkle(cx, cy); yapiAyarla(mrk, true); // alt-a (sol-alt kose) ile ust-a (sag-ust kose) merkeze gore simetrik → // Simetrik kisiti bir CIZGI ekseni ister; bunun yerine merkez orta-nokta // esitligini YatayMesafe/DikeyMesafe ile kur: kose - merkez = -(karsit - merkez). // Basitce: sol kenar x merkeze uzak = sag kenar (Dikey mesafe simetrisi). // Simetrik(kose_a, kose_c, merkezNoktasi_uzerinden) icin bir eksen cizgisine // ihtiyac var; MVP olarak yatay/dikey mesafe simetrisi ile merkezle. // alt.a = sol-alt kose (cx-yariEn, cy-yariBoy) → merkezden isaretli delta. kisitEkle(KisitTip::YatayMesafe, {mrk, alt}, {0, 0}, -yariEn); // merkez->sol-alt x kisitEkle(KisitTip::DikeyMesafe, {mrk, alt}, {0, 0}, -yariBoy); // merkez->sol-alt y std::vector sonuc{alt, sag, ust, sol, mrk}; return sonuc; } std::vector EskizVeri::yonluDikdortgenEkle(Skalar x0, Skalar y0, Skalar x1, Skalar y1, Skalar yukseklik) { // Taban kenar (x0,y0)->(x1,y1); yukseklik dik yonde. Skalar dx = x1 - x0, dy = y1 - y0; Skalar len = std::sqrt(dx * dx + dy * dy); if (len < 1e-9) { dx = 1.0; dy = 0.0; len = 1.0; } const Skalar nx = -dy / len, ny = dx / len; // dik birim const Skalar hx = nx * yukseklik, hy = ny * yukseklik; // Koseler: taban iki uc + ust iki uc (taban + yukseklik ofseti). u32 taban = cizgiEkle(x0, y0, x1, y1); u32 sag = cizgiEkle(x1, y1, x1 + hx, y1 + hy); u32 ust = cizgiEkle(x1 + hx, y1 + hy, x0 + hx, y0 + hy); u32 sol = cizgiEkle(x0 + hx, y0 + hy, x0, y0); kisitEkle(KisitTip::Cakisik, {taban, sag}, {1, 0}, 0); kisitEkle(KisitTip::Cakisik, {sag, ust}, {1, 0}, 0); kisitEkle(KisitTip::Cakisik, {ust, sol}, {1, 0}, 0); kisitEkle(KisitTip::Cakisik, {sol, taban}, {1, 0}, 0); // Egik dikdortgen: taban serbest yonlu; kenarlar dik + karsit paralel. kisitEkle(KisitTip::Dik, {taban, sag}); kisitEkle(KisitTip::Dik, {sag, ust}); kisitEkle(KisitTip::Paralel, {taban, ust}); kisitEkle(KisitTip::Paralel, {sol, sag}); return {taban, sag, ust, sol}; } std::vector EskizVeri::paralelkenarEkle(Skalar x0, Skalar y0, Skalar v1x, Skalar v1y, Skalar v2x, Skalar v2y) { // Koseler: p0, p0+v1, p0+v1+v2, p0+v2. const Skalar ax = x0, ay = y0; const Skalar bx = x0 + v1x, by = y0 + v1y; const Skalar cx = x0 + v1x + v2x, cy = y0 + v1y + v2y; const Skalar ddx = x0 + v2x, ddy = y0 + v2y; u32 k1 = cizgiEkle(ax, ay, bx, by); // p0 -> p0+v1 u32 k2 = cizgiEkle(bx, by, cx, cy); // p0+v1 -> p0+v1+v2 u32 k3 = cizgiEkle(cx, cy, ddx, ddy); // p0+v1+v2 -> p0+v2 u32 k4 = cizgiEkle(ddx, ddy, ax, ay); // p0+v2 -> p0 kisitEkle(KisitTip::Cakisik, {k1, k2}, {1, 0}, 0); kisitEkle(KisitTip::Cakisik, {k2, k3}, {1, 0}, 0); kisitEkle(KisitTip::Cakisik, {k3, k4}, {1, 0}, 0); kisitEkle(KisitTip::Cakisik, {k4, k1}, {1, 0}, 0); // Karsit kenar ciftleri paralel (paralelkenar tanimi). kisitEkle(KisitTip::Paralel, {k1, k3}); kisitEkle(KisitTip::Paralel, {k2, k4}); // Karsit kenarlar esit uzunluk. kisitEkle(KisitTip::Esit, {k1, k3}); kisitEkle(KisitTip::Esit, {k2, k4}); return {k1, k2, k3, k4}; } std::vector EskizVeri::egriselSlotEkle(Skalar cx, Skalar cy, Skalar r, Skalar a0, Skalar a1, Skalar genislikR) { // CATIA Cylindrical Elongated Hole: eksen YAYI (merkez cx,cy; yaricap r; // a0..a1 CCW) + genislik yaricapi g. Kontur: dis yay (r+g) + ic yay (r-g) // ayni merkezli + uclarda g yaricapli yarim yaylar (eksen ucu merkezli, // eksen tegetine dik acilir → dis/ic yaya uc-uca kapanir). const Skalar g = std::abs(genislikR); if (g < 1e-9 || g >= std::abs(r)) return {}; // ic yay yaricapi <= 0 olur while (a1 <= a0) a1 += 2.0 * kPi; // CCW supurme garanti // Eksen yayi uc noktalari (uc yarim-yay merkezleri). const Skalar p0x = cx + r * std::cos(a0), p0y = cy + r * std::sin(a0); const Skalar p1x = cx + r * std::cos(a1), p1y = cy + r * std::sin(a1); // Es merkezli dis/ic yaylar (ayni aci araligi). u32 dis = yayEkle(cx, cy, r + g, a0, a1); u32 ic = yayEkle(cx, cy, r - g, a0, a1); // Uc yarim-yaylar: acilar eksen tegetine dik → radyal a0/a1 etrafinda ±π. // a0 ucu: ic noktadan (a0-π) DIŞA dogru (a0-π/2 = -teget) dis noktaya (a0). // a1 ucu: dis noktadan (a1) DIŞA dogru (a1+π/2 = +teget) ic noktaya (a1+π). u32 uc0 = yayEkle(p0x, p0y, g, a0 - kPi, a0); u32 uc1 = yayEkle(p1x, p1y, g, a1, a1 + kPi); // Kisitlar: uclar cakisik (kapali kontur) + dis/ic es merkez + uc yaylar // esit + uc yaylar ic yaya DIŞ teget (cozucu daire-daire tegeti dis teget // olarak tanimlar; dis yaya baglanti Cakisik uclarla saglanir). kisitEkle(KisitTip::Cakisik, {uc0, ic}, {0, 0}, 0); kisitEkle(KisitTip::Cakisik, {uc0, dis}, {1, 0}, 0); kisitEkle(KisitTip::Cakisik, {uc1, dis}, {0, 1}, 0); kisitEkle(KisitTip::Cakisik, {uc1, ic}, {1, 1}, 0); kisitEkle(KisitTip::Cakisik, {dis, ic}, {2, 2}, 0); // es merkez kisitEkle(KisitTip::Esit, {uc0, uc1}); kisitEkle(KisitTip::Tegel, {uc0, ic}); kisitEkle(KisitTip::Tegel, {uc1, ic}); return {dis, uc1, ic, uc0}; // kontur sirali: dis → a1 ucu → ic → a0 ucu } std::vector EskizVeri::anahtarDeligiEkle(Skalar bx, Skalar by, Skalar kx, Skalar ky, Skalar kucukR, Skalar buyukR) { // CATIA Keyhole Profile: buyuk cember (B, R) + kucuk cember (K, r) + iki // ortak DIŞ teget cizgi. Kontur: buyuk yayin K'dan uzak buyuk parcasi + // teget cizgiler + kucuk yayin B'den uzak parcasi. const Skalar dx = kx - bx, dy = ky - by; const Skalar d = std::sqrt(dx * dx + dy * dy); if (kucukR < 1e-9 || buyukR < 1e-9) return {}; if (d < 1e-9 || d <= std::abs(buyukR - kucukR)) return {}; // ic ice → dis teget yok // Dis teget geometrisi (main.cpp "tegetcizgi" matematigi): teget noktalari // her iki cemberde AYNI normal acida (alfa ± beta). const Skalar alfa = std::atan2(dy, dx); const Skalar co = (buyukR - kucukR) / d; const Skalar beta = std::acos(co > 1.0 ? 1.0 : (co < -1.0 ? -1.0 : co)); // Teget noktalari: + tarafi (alfa+beta) ve - tarafi (alfa-beta). const Skalar aP = alfa + beta, aM = alfa - beta; const Skalar bPx = bx + buyukR * std::cos(aP), bPy = by + buyukR * std::sin(aP); const Skalar bMx = bx + buyukR * std::cos(aM), bMy = by + buyukR * std::sin(aM); const Skalar kPx = kx + kucukR * std::cos(aP), kPy = ky + kucukR * std::sin(aP); const Skalar kMx = kx + kucukR * std::cos(aM), kMy = ky + kucukR * std::sin(aM); // Buyuk yay: aP'den CCW (K'dan uzak, alfa+π uzerinden) aM'ye (supurme 2π-2β). u32 buyukYay = yayEkle(bx, by, buyukR, aP, aM + 2.0 * kPi); // Kucuk yay: aM'den CCW (B'den uzak, alfa uzerinden) aP'ye (supurme 2β). u32 kucukYay = yayEkle(kx, ky, kucukR, aM, aP); // Iki teget cizgi (buyuk teget noktasi → kucuk teget noktasi). u32 cizgiP = cizgiEkle(bPx, bPy, kPx, kPy); u32 cizgiM = cizgiEkle(bMx, bMy, kMx, kMy); // Kisitlar: uclar cakisik (kapali kontur) + cizgiler iki yaya tegel // (slotEkle deseni — surukleyince teget/kapali kalir). kisitEkle(KisitTip::Cakisik, {cizgiP, buyukYay}, {0, 0}, 0); kisitEkle(KisitTip::Cakisik, {cizgiP, kucukYay}, {1, 1}, 0); kisitEkle(KisitTip::Cakisik, {cizgiM, buyukYay}, {0, 1}, 0); kisitEkle(KisitTip::Cakisik, {cizgiM, kucukYay}, {1, 0}, 0); kisitEkle(KisitTip::Tegel, {cizgiP, buyukYay}); kisitEkle(KisitTip::Tegel, {cizgiP, kucukYay}); kisitEkle(KisitTip::Tegel, {cizgiM, buyukYay}); kisitEkle(KisitTip::Tegel, {cizgiM, kucukYay}); return {buyukYay, cizgiP, kucukYay, cizgiM}; // kontur sirali } // NURBS Spline: control point + auto uniform clamped knot/weight. u32 EskizVeri::splineNurbsEkle(const std::vector>& noktalar) { if (noktalar.size() < 2) return 0; Geometri g; g.tip = GeoTip::Spline; int n = (int)noktalar.size(); // Uclar parametre olarak g.a = Nokta{paramEkle(noktalar.front().first), paramEkle(noktalar.front().second)}; g.b = Nokta{paramEkle(noktalar.back().first), paramEkle(noktalar.back().second)}; // Ic noktalar ekNoktalar g.ekNoktalar.reserve(n - 2); for (int i = 1; i < n - 1; ++i) g.ekNoktalar.push_back(Nokta{paramEkle(noktalar[i].first), paramEkle(noktalar[i].second)}); // Knot: uniform clamped, derece min(3, n-1) int p = std::min(3, n - 1); g.knot.resize((size_t)(n + p + 1)); for (int i = 0; i <= p; ++i) g.knot[(size_t)i] = 0.0; for (int i = n; i < n + p + 1; ++i) g.knot[(size_t)i] = 1.0; int icAdet = n - p - 1; if (icAdet > 0) { for (int i = 0; i < icAdet; ++i) g.knot[(size_t)(p + 1 + i)] = (f64)(i + 1) / ((f64)icAdet + 1); } // Weight: hepsi 1.0 g.weight.assign((size_t)n, 1.0); g.kimlik = sonrakiGeoKimlik_++; geo_.push_back(g); return g.kimlik; } } // namespace fiko::eskiz