// fiko.sketch.* + fiko.parca.* Lua bağlama katmanı. // // AMAÇ: makro/MCP tarafının GERÇEK parametrik modelleme yapabilmesi. Önceden Lua'da // yalnız primitif (kutu/silindir/küre/koni) + boolean vardı; "kumpas çiz" gibi bir // istek ancak kutu yığınıyla karşılanabiliyordu. Artık sketch çizilip Part Design // feature'ı (pad/pocket/shaft/hole/fillet/pattern/…) uygulanabiliyor. // // TASARIM: feature kataloğu ZATEN veri-güdümlü (`featureTanimlari()`), bu yüzden // feature başına Lua fonksiyonu YAZILMADI — tek `fiko.parca.ekle(tip, ...)` tüm // tipleri (40+) açar ve yeni feature eklenince Lua tarafı kendiliğinden kazanır. // `fiko.parca.tipler()` katalogdan şemayı döndürür → yapay zeka parametreleri keşfeder. #include "fiko/betik/makro_motor.hpp" #include #include #include #include #include #include "fiko/cekirdek/cekirdek.hpp" #include "fiko/analiz/analiz_nesne.hpp" #include #include "fiko/geometri/brep.hpp" #include "fiko/cae/govde_kafes.hpp" #include "fiko/dokum/voxel_gorsel.hpp" #include "fiko/dokum/voxel_kafes.hpp" #include "fiko/montaj/mekanizma_sahne.hpp" // kesisim/donusumUygula — kesin girişim doğrulaması #include "fiko/kinematik/mekanizma.hpp" #include "fiko/montaj/mafsal_oneri.hpp" // mafsalOner (geometriden mafsal çıkarımı) #include "fiko/analiz/analiz_sistemi.hpp" #include "fiko/gsd/gsd_registry.hpp" #include "fiko/gsd/gsd_sistemi.hpp" #include "fiko/parca/feature_registry.hpp" #include "fiko/parca/part_design_sistemi.hpp" #include "fiko/sahne/sahne.hpp" #include "fiko/sahne/parametre_nesne.hpp" #include "fiko/sahne/sahne_islem.hpp" // SilIslem (parametre silme undo yolu) #include "fiko/sahne/sketch_nesne.hpp" #include "makro_ic.hpp" extern "C" { #include "lauxlib.h" #include "lua.h" } namespace fiko::betik { namespace { // Lua yığınındaki tablo → (anahtar, sayı) çiftleri. Bayrak (bool) da sayıya çevrilir // (feature parametreleri f64 haritasıdır — Bayrak 0/1, Secim indeks). std::vector> paramTablosu(lua_State* L, int indeks) { std::vector> out; if (!lua_istable(L, indeks)) return out; lua_pushnil(L); const int mutlak = lua_absindex(L, indeks); while (lua_next(L, mutlak) != 0) { if (lua_type(L, -2) == LUA_TSTRING) { const char* anahtar = lua_tostring(L, -2); f64 deger = 0.0; if (lua_isboolean(L, -1)) deger = lua_toboolean(L, -1) ? 1.0 : 0.0; else if (lua_isnumber(L, -1)) deger = (f64)lua_tonumber(L, -1); out.emplace_back(anahtar, deger); } lua_pop(L, 1); } return out; } SketchNesnesi* sketchBul(MakroMotor* m, Varlik v) { return dynamic_cast(m->cekirdekRef().nesne(v)); } } // namespace // ── fiko.sketch.* ─────────────────────────────────────────────────────────── // fiko.sketch.ekle("xy"|"yz"|"zx" veya duzlemVarlik) → sketch Varlik int MakroMotor::l_sketchEkle(lua_State* L) { MakroMotor* m = kendisi(L); Varlik duzlem = VARLIK_YOK; if (lua_type(L, 1) == LUA_TSTRING) { const std::string ad = lua_tostring(L, 1); const u32 alt = ad == "xy" ? eksensis::DUZLEM_XY : (ad == "yz" ? eksensis::DUZLEM_YZ : (ad == "zx" ? eksensis::DUZLEM_ZX : 0u)); if (!alt) { lua_pushnil(L); return 1; } duzlem = m->sahne_.eksenSistemiDuzlemi(alt); } else { duzlem = (Varlik)luaL_checkinteger(L, 1); } if (duzlem == VARLIK_YOK) { lua_pushnil(L); return 1; } const Varlik sk = m->sahne_.sketchEkle(duzlem); if (sk == VARLIK_YOK) lua_pushnil(L); else lua_pushinteger(L, (lua_Integer)sk); return 1; } // fiko.sketch.cizgi(sk, x1,y1, x2,y2) → geo kimlik int MakroMotor::l_sketchCizgi(lua_State* L) { MakroMotor* m = kendisi(L); SketchNesnesi* sk = sketchBul(m, (Varlik)luaL_checkinteger(L, 1)); if (!sk) { lua_pushnil(L); return 1; } const u32 g = sk->eskiz().cizgiEkle(luaL_checknumber(L, 2), luaL_checknumber(L, 3), luaL_checknumber(L, 4), luaL_checknumber(L, 5)); lua_pushinteger(L, (lua_Integer)g); return 1; } // fiko.sketch.daire(sk, cx, cy, r) → geo kimlik int MakroMotor::l_sketchDaire(lua_State* L) { MakroMotor* m = kendisi(L); SketchNesnesi* sk = sketchBul(m, (Varlik)luaL_checkinteger(L, 1)); if (!sk) { lua_pushnil(L); return 1; } const u32 g = sk->eskiz().daireEkle(luaL_checknumber(L, 2), luaL_checknumber(L, 3), luaL_checknumber(L, 4)); lua_pushinteger(L, (lua_Integer)g); return 1; } // fiko.sketch.yay(sk, cx, cy, r, baslangicAciDeg, bitisAciDeg) → geo kimlik int MakroMotor::l_sketchYay(lua_State* L) { MakroMotor* m = kendisi(L); SketchNesnesi* sk = sketchBul(m, (Varlik)luaL_checkinteger(L, 1)); if (!sk) { lua_pushnil(L); return 1; } const double d2r = 3.14159265358979323846 / 180.0; const u32 g = sk->eskiz().yayEkle(luaL_checknumber(L, 2), luaL_checknumber(L, 3), luaL_checknumber(L, 4), luaL_checknumber(L, 5) * d2r, luaL_checknumber(L, 6) * d2r); lua_pushinteger(L, (lua_Integer)g); return 1; } // fiko.sketch.dikdortgen(sk, x1,y1, x2,y2) → 4 çizgi kimliği (tablo). Kolaylık // sarmalayıcısı: kapalı profil en sık gereken şey; 4 ayrı cizgiEkle yazmak yerine. int MakroMotor::l_sketchDikdortgen(lua_State* L) { MakroMotor* m = kendisi(L); SketchNesnesi* sk = sketchBul(m, (Varlik)luaL_checkinteger(L, 1)); if (!sk) { lua_pushnil(L); return 1; } const double x1 = luaL_checknumber(L, 2), y1 = luaL_checknumber(L, 3); const double x2 = luaL_checknumber(L, 4), y2 = luaL_checknumber(L, 5); auto& ev = sk->eskiz(); const u32 g[4] = {ev.cizgiEkle(x1, y1, x2, y1), ev.cizgiEkle(x2, y1, x2, y2), ev.cizgiEkle(x2, y2, x1, y2), ev.cizgiEkle(x1, y2, x1, y1)}; lua_createtable(L, 4, 0); for (int i = 0; i < 4; ++i) { lua_pushinteger(L, (lua_Integer)g[i]); lua_rawseti(L, -2, i + 1); } return 1; } // fiko.sketch.yenile(sk) — eskiz geometrisini 3B kenarlara işle (görünür olsun). int MakroMotor::l_sketchYenile(lua_State* L) { MakroMotor* m = kendisi(L); const Varlik v = (Varlik)luaL_checkinteger(L, 1); m->sahne_.sketchKenarYenile(v); lua_pushboolean(L, 1); return 1; } namespace { // Feature kataloğunu Lua tablosuna dök — Part Design ve GSD AYNI `FeatureTanim` tipini // kullandığından tek yardımcı ikisine de hizmet eder (kod kopyası yok). void tanimlariYaz(lua_State* L, const std::vector& tanimlar) { lua_createtable(L, (int)tanimlar.size(), 0); int i = 1; for (const parca::FeatureTanim& t : tanimlar) { lua_createtable(L, 0, 4); lua_pushstring(L, t.id.c_str()); lua_setfield(L, -2, "tip"); lua_pushstring(L, t.ad.c_str()); lua_setfield(L, -2, "ad"); lua_pushboolean(L, t.malzemeEkler); lua_setfield(L, -2, "malzemeEkler"); lua_createtable(L, (int)t.parametreler.size(), 0); int j = 1; for (const parca::FeatureParam& p : t.parametreler) { lua_createtable(L, 0, 5); lua_pushstring(L, p.anahtar.c_str()); lua_setfield(L, -2, "anahtar"); lua_pushstring(L, p.etiket.c_str()); lua_setfield(L, -2, "etiket"); lua_pushinteger(L, (lua_Integer)p.tip); lua_setfield(L, -2, "tip"); lua_pushnumber(L, p.varsayilan); lua_setfield(L, -2, "varsayilan"); lua_pushstring(L, p.birim.c_str()); lua_setfield(L, -2, "birim"); lua_rawseti(L, -2, j++); } lua_setfield(L, -2, "parametreler"); lua_rawseti(L, -2, i++); } } } // namespace // ── fiko.gsd.* (Generative Shape Design — wireframe + yüzey) ──────────────── // GSD kataloğu da VERİ-GÜDÜMLÜ (`gsdTanimlari()`), Part Design ile aynı kalıp: // tek `ekle` 31 operasyonun tamamını açar (nokta/çizgi/spline/helix, extrude/revolve/ // fill/offset/thicken/extrapolate, süpürme/loft/köprüle/kırp/yama/onar/birleştir…). int MakroMotor::l_gsdTipler(lua_State* L) { tanimlariYaz(L, gsd::gsdTanimlari()); return 1; } // fiko.gsd.ekle(tip, sketchVarlik, kaynak, {param=deger}, kaynak2) → feature kimlik int MakroMotor::l_gsdEkle(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->gsd_) { lua_pushnil(L); return 1; } const std::string tip = luaL_checkstring(L, 1); const Varlik sk = (Varlik)luaL_optinteger(L, 2, 0); const Varlik kaynak = (Varlik)luaL_optinteger(L, 3, 0); const Varlik kaynak2 = (Varlik)luaL_optinteger(L, 5, 0); const u32 fk = m->gsd_->gsdBaslat(tip, sk, kaynak, kaynak2); if (!fk) { lua_pushnil(L); return 1; } const auto params = paramTablosu(L, 4); if (!params.empty()) m->gsd_->gsdGuncelleToplu(fk, params); lua_pushinteger(L, (lua_Integer)fk); return 1; } // fiko.gsd.guncelle(featureKimlik, {param=deger}) → TEK yeniden-inşa int MakroMotor::l_gsdGuncelle(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->gsd_) { lua_pushnil(L); return 1; } const u32 fk = (u32)luaL_checkinteger(L, 1); const auto params = paramTablosu(L, 2); if (params.empty()) { lua_pushnil(L); return 1; } m->gsd_->gsdGuncelleToplu(fk, params); lua_pushboolean(L, 1); return 1; } // fiko.gsd.featureler() → { {kimlik=, tip=, dugum=, hata=}, ... } int MakroMotor::l_gsdFeatureler(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->gsd_) { lua_pushnil(L); return 1; } const auto& sira = m->gsd_->featureler(); lua_createtable(L, (int)sira.size(), 0); int i = 1; for (u32 fk : sira) { lua_createtable(L, 0, 4); lua_pushinteger(L, (lua_Integer)fk); lua_setfield(L, -2, "kimlik"); if (gsd::GsdFeature* f = m->gsd_->bul(fk)) { lua_pushstring(L, f->tip().c_str()); lua_setfield(L, -2, "tip"); lua_pushinteger(L, (lua_Integer)f->sonucDugum()); lua_setfield(L, -2, "dugum"); lua_pushstring(L, f->hata().c_str()); lua_setfield(L, -2, "hata"); } lua_rawseti(L, -2, i++); } return 1; } // fiko.gsd.sil(featureKimlik) int MakroMotor::l_gsdSil(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->gsd_) { lua_pushnil(L); return 1; } m->gsd_->gsdIptal((u32)luaL_checkinteger(L, 1)); lua_pushboolean(L, 1); return 1; } // ── fiko.kinematik.* (mekanizma: uzuv + mafsal + ileri kinematik) ─────────── // Motor çekirdeği SAF (motor/kinematik); burada SAHNEYE bağlanır: her uzuv bir sahne // düğümüne bağlanır, `uygula()` ileri kinematik sonucunu düğüm dönüşümlerine yazar. // Mekanizma BELGE verisidir → makro motorunda yaşar (belge başına bir tane). namespace { bool mafsalTipCoz(const std::string& ad, kinematik::MafsalTip& t) { using M = kinematik::MafsalTip; if (ad == "sabit") t = M::Sabit; else if (ad == "doner") t = M::Doner; else if (ad == "kayar") t = M::Kayar; else if (ad == "silindirik") t = M::Silindirik; else if (ad == "vida") t = M::Vida; else if (ad == "kuresel") t = M::Kuresel; else if (ad == "duzlemsel") t = M::Duzlemsel; else if (ad == "serbest") t = M::Serbest; else return false; return true; } } // namespace // fiko.kinematik.sifirla() — mekanizmayı boşalt (gövde uzvu 0 otomatik kurulur) int MakroMotor::l_kinSifirla(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->mekanizma_) { lua_pushnil(L); return 1; } *m->mekanizma_ = kinematik::Mekanizma{}; m->kinSurulen_.clear(); m->mekanizma_->uzuvEkle("Gövde"); // uzuv 0 = ground (sabit) lua_pushboolean(L, 1); return 1; } // fiko.kinematik.uzuvEkle(ad, sahneDugum) → uzuv indeksi (düğümün MEVCUT dönüşümü taban) int MakroMotor::l_kinUzuvEkle(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->mekanizma_) { lua_pushnil(L); return 1; } if (m->mekanizma_->uzuvlar().empty()) m->mekanizma_->uzuvEkle("Gövde"); const std::string ad = luaL_checkstring(L, 1); const u32 dugum = (u32)luaL_optinteger(L, 2, 0); Donusumd taban; if (const Dugum* d = m->sahne_.bul(dugum)) taban = d->donusum; lua_pushinteger(L, (lua_Integer)m->mekanizma_->uzuvEkle(ad, dugum, taban)); return 1; } // fiko.kinematik.mafsalEkle(tip, ana, cocuk, {cx,cy,cz, q, q2, q3, vidaAdim, // altSinir, ustSinir}) → mafsal indeksi int MakroMotor::l_kinMafsalEkle(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->mekanizma_) { lua_pushnil(L); return 1; } kinematik::MafsalTip t{}; if (!mafsalTipCoz(luaL_checkstring(L, 1), t)) { lua_pushnil(L); return 1; } kinematik::Mafsal mf; mf.tip = t; mf.ana = (std::size_t)luaL_checkinteger(L, 2); mf.cocuk = (std::size_t)luaL_checkinteger(L, 3); for (const auto& [k, v] : paramTablosu(L, 4)) { if (k == "cx") mf.capa.konum.x = v; else if (k == "cy") mf.capa.konum.y = v; else if (k == "cz") mf.capa.konum.z = v; // ccx/ccy/ccz = ÇOCUK tarafı çapa (montaj mate) — kapalı zincirde şart. else if (k == "ccx") mf.capaCocuk.konum.x = v; else if (k == "ccy") mf.capaCocuk.konum.y = v; else if (k == "ccz") mf.capaCocuk.konum.z = v; else if (k == "q") mf.q = v; else if (k == "q2") mf.q2 = v; else if (k == "q3") mf.q3 = v; else if (k == "vidaAdim") mf.vidaAdim = v; else if (k == "altSinir") mf.altSinir = v; else if (k == "ustSinir") mf.ustSinir = v; } mf.ad = kinematik::mafsalTipAdi(t); lua_pushinteger(L, (lua_Integer)m->mekanizma_->mafsalEkle(std::move(mf))); return 1; } // fiko.kinematik.surus(mafsalIndeks, q, q2, q3) — değişkeni ayarla (sınıra kırpılır) int MakroMotor::l_kinSurus(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->mekanizma_) { lua_pushnil(L); return 1; } kinematik::Mafsal* mf = m->mekanizma_->mafsal((std::size_t)luaL_checkinteger(L, 1)); if (!mf) { lua_pushnil(L); return 1; } mf->q = luaL_checknumber(L, 2); mf->q2 = luaL_optnumber(L, 3, mf->q2); mf->q3 = luaL_optnumber(L, 4, mf->q3); // Elle sürülen mafsal SÜRÜLEN sayılır: kapalı zincir çözücüsü ona DOKUNMAZ // (kullanıcının verdiği değer korunur, bağımlı mafsallar ona göre çözülür). const std::size_t i = (std::size_t)luaL_checkinteger(L, 1); if (std::find(m->kinSurulen_.begin(), m->kinSurulen_.end(), i) == m->kinSurulen_.end()) m->kinSurulen_.push_back(i); lua_pushboolean(L, 1); return 1; } // Sürülen küme = elle sürülenler ∪ YASASI olan mafsallar (yasa değeri kilitlidir). static std::vector surulenKume(const kinematik::Mekanizma& mek, const std::vector& elle) { std::vector s = elle; for (const kinematik::MafsalYasa& y : mek.yasalar()) if (std::find(s.begin(), s.end(), y.mafsal) == s.end()) s.push_back(y.mafsal); return s; } // fiko.kinematik.coz() → {yakinsadi=, artik=, halka=} — kapalı zinciri AÇIKÇA çöz. int MakroMotor::l_kinCoz(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->mekanizma_) { lua_pushnil(L); return 1; } f64 artik = 0; const bool ok = m->mekanizma_->kapaliZincirCoz(surulenKume(*m->mekanizma_, m->kinSurulen_), (int)luaL_optinteger(L, 1, 200), luaL_optnumber(L, 2, 1e-6), &artik); lua_createtable(L, 0, 3); lua_pushboolean(L, ok); lua_setfield(L, -2, "yakinsadi"); lua_pushnumber(L, artik); lua_setfield(L, -2, "artik"); lua_pushinteger(L, (lua_Integer)m->mekanizma_->halkaKapatanlar().size()); lua_setfield(L, -2, "halka"); return 1; } // fiko.kinematik.uygula() → ileri kinematik sonucunu SAHNE düğümlerine yaz int MakroMotor::l_kinUygula(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->mekanizma_) { lua_pushnil(L); return 1; } // KAPALI ZİNCİR: ham ileri kinematik halkayı KAPATMAZ (bağımlı mafsallar çözülmeli). // Sahneye yazmadan ÖNCE çözücüyü koştur (ayar `kinematik.halka_oto_coz`; kapalıysa // eski davranış = ham FK). Ağaç mekanizmada çözücü anında döner (maliyetsiz). // TEK MERKEZ: aynı iş CAE panelinden de çağrılıyor (montaj::mekanizmaSahneyeYaz). const int yazilan = montaj::mekanizmaSahneyeYaz(m->sahne_, m->cekirdek_, *m->mekanizma_, surulenKume(*m->mekanizma_, m->kinSurulen_)); lua_pushinteger(L, yazilan); return 1; } // fiko.kinematik.yasa(mafsal, tip, {deger,hiz,genlik,periyot,faz,degisken}) → yasa indeksi // tip: "sabit" | "dogrusal" | "harmonik". Anahtar-kare için `yasaAnahtar` kullanın. int MakroMotor::l_kinYasa(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->mekanizma_) { lua_pushnil(L); return 1; } kinematik::MafsalYasa y; y.mafsal = (std::size_t)luaL_checkinteger(L, 1); const std::string tip = luaL_checkstring(L, 2); if (tip == "sabit") y.tip = kinematik::YasaTip::Sabit; else if (tip == "dogrusal") y.tip = kinematik::YasaTip::Dogrusal; else if (tip == "harmonik") y.tip = kinematik::YasaTip::Harmonik; else { lua_pushnil(L); return 1; } for (const auto& [k, v] : paramTablosu(L, 3)) { if (k == "deger") y.deger = v; else if (k == "hiz") y.hiz = v; else if (k == "genlik") y.genlik = v; else if (k == "periyot") y.periyot = v; else if (k == "faz") y.faz = v; else if (k == "degisken") y.degisken = (int)v; } lua_pushinteger(L, (lua_Integer)m->mekanizma_->yasaEkle(std::move(y))); return 1; } // fiko.kinematik.yasaAnahtar(mafsal, {{t1,q1},{t2,q2},...}, degisken) → yasa indeksi int MakroMotor::l_kinYasaAnahtar(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->mekanizma_) { lua_pushnil(L); return 1; } kinematik::MafsalYasa y; y.tip = kinematik::YasaTip::AnahtarKare; y.mafsal = (std::size_t)luaL_checkinteger(L, 1); y.degisken = (int)luaL_optinteger(L, 3, 0); luaL_checktype(L, 2, LUA_TTABLE); const int n = (int)lua_rawlen(L, 2); for (int i = 1; i <= n; ++i) { lua_rawgeti(L, 2, i); if (lua_istable(L, -1)) { lua_rawgeti(L, -1, 1); lua_rawgeti(L, -2, 2); y.anahtarlar.emplace_back((f64)lua_tonumber(L, -2), (f64)lua_tonumber(L, -1)); lua_pop(L, 2); } lua_pop(L, 1); } lua_pushinteger(L, (lua_Integer)m->mekanizma_->yasaEkle(std::move(y))); return 1; } // fiko.kinematik.zaman(t) — yasaları t anına uygula (sahneye yazmak için uygula() çağır) int MakroMotor::l_kinZaman(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->mekanizma_) { lua_pushnil(L); return 1; } m->mekanizma_->zamanaAyarla(luaL_checknumber(L, 1)); lua_pushboolean(L, 1); return 1; } // fiko.kinematik.carpismaTara(t0, t1, adim, komsuAtla) → { {a=,b=,adA=,adB=,zaman=,oran=}, ... } // DMU: mekanizma [t0,t1] boyunca süpürülür; uzuvların SAHNE düğümlerinin yerel sınır // kutuları kullanılır (düğümsüz uzuv atlanır). AABB ölçütü → yanlış-pozitif olabilir, // gerçek çarpışmayı ASLA kaçırmaz. Tarama mafsal değişkenlerini DEĞİŞTİRİR; sonrasında // istenen anı `zaman()`+`uygula()` ile geri kurun. int MakroMotor::l_kinCarpisma(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->mekanizma_) { lua_pushnil(L); return 1; } const auto& uzuvlar = m->mekanizma_->uzuvlar(); const std::vector kutular = montaj::uzuvYerelKutulari(m->sahne_, *m->mekanizma_); const f64 t0 = luaL_optnumber(L, 1, 0.0), t1 = luaL_optnumber(L, 2, 1.0); auto liste = kinematik::carpismaTara( *m->mekanizma_, kutular, t0, t1, (int)luaL_optinteger(L, 3, 24), lua_isnoneornil(L, 4) ? true : lua_toboolean(L, 4) != 0); // KESİN DOĞRULAMA (5. arg): AABB adayları yanlış-POZİTİF olabilir. İstenirse her aday // kendi anına geri kurulur, iki gövdenin DÜNYA B-Rep'leri kesiştirilir ve gerçek // girişim HACMİ (mm³) ölçülür; hacim ~0 ise aday ELENİR. Pahalı (OCCT boolean) → // yalnız aday sayısı kadar koşar, varsayılan KAPALI. std::vector girisimHacmi(liste.size(), -1.0); std::vector isaretDugum; const bool isaretle = !lua_isnoneornil(L, 6) && lua_toboolean(L, 6); if ((!lua_isnoneornil(L, 5) && lua_toboolean(L, 5)) || isaretle) { const auto& uz = m->mekanizma_->uzuvlar(); std::vector kalan; std::vector kalanHacim; for (const kinematik::Carpisma& c : liste) { m->mekanizma_->zamanaAyarla(c.zaman); if (!m->mekanizma_->halkaKapatanlar().empty()) { std::vector sur; for (const kinematik::MafsalYasa& y : m->mekanizma_->yasalar()) sur.push_back(y.mafsal); m->mekanizma_->kapaliZincirCoz(sur); } const auto dunya = m->mekanizma_->ileriKinematik(); const Dugum* da = c.uzuvA < uz.size() ? m->sahne_.bul(uz[c.uzuvA].sahne) : nullptr; const Dugum* db = c.uzuvB < uz.size() ? m->sahne_.bul(uz[c.uzuvB].sahne) : nullptr; if (!da || !db || !da->brep || !db->brep) continue; const geometri::BrepGovde ga = geometri::donusumUygula(*da->brep, dunya[c.uzuvA]); const geometri::BrepGovde gb = geometri::donusumUygula(*db->brep, dunya[c.uzuvB]); geometri::BrepGovde ortak = geometri::kesisim(ga, gb); // taşınabilir (kopyalanamaz) const f64 h = ortak.gecerliMi() ? ortak.hacim() : 0.0; if (h <= kinematik::girisimAsgariHacim()) continue; // AABB çakışmış, GERÇEK girişim yok kalan.push_back(c); kalanHacim.push_back(h); // 6. arg `isaretle`: girişim HACMİ sahnede gerçek gövde olur (CATIA DMU clash // volume). Gövde zaten hesaplandı — atmak yerine görünür kılınır. if (isaretle) { char ad[192]; std::snprintf(ad, sizeof ad, "Girişim: %s × %s (t=%.3f)", uz[c.uzuvA].ad.c_str(), uz[c.uzuvB].ad.c_str(), c.zaman); const u32 yeniDugum = m->sahne_.gsdDugumEkle(DugumTip::Yuzey, ad, VARLIK_YOK, kinematik::girisimRenk()); if (yeniDugum && m->sahne_.gsdDugumGuncelle(yeniDugum, std::make_shared(std::move(ortak)))) { if (Dugum* yd = m->sahne_.bul(yeniDugum)) yd->saydamlik = kinematik::girisimAlfa(); m->kinIsaretler_.push_back(yeniDugum); isaretDugum.push_back(yeniDugum); } else if (yeniDugum) { m->sahne_.sil(yeniDugum); // geçersiz gövde → boş düğüm bırakma } } } liste = std::move(kalan); girisimHacmi = std::move(kalanHacim); } lua_createtable(L, (int)liste.size(), 0); int i = 1; for (const kinematik::Carpisma& c : liste) { lua_createtable(L, 0, 6); lua_pushinteger(L, (lua_Integer)c.uzuvA); lua_setfield(L, -2, "a"); lua_pushinteger(L, (lua_Integer)c.uzuvB); lua_setfield(L, -2, "b"); lua_pushstring(L, c.uzuvA < uzuvlar.size() ? uzuvlar[c.uzuvA].ad.c_str() : ""); lua_setfield(L, -2, "adA"); lua_pushstring(L, c.uzuvB < uzuvlar.size() ? uzuvlar[c.uzuvB].ad.c_str() : ""); lua_setfield(L, -2, "adB"); lua_pushnumber(L, c.zaman); lua_setfield(L, -2, "zaman"); lua_pushnumber(L, c.hacimOran); lua_setfield(L, -2, "oran"); if ((std::size_t)(i - 1) < girisimHacmi.size() && girisimHacmi[i - 1] >= 0.0) { lua_pushnumber(L, girisimHacmi[i - 1]); lua_setfield(L, -2, "hacim"); // mm³ (kesin) } if ((std::size_t)(i - 1) < isaretDugum.size()) { lua_pushinteger(L, isaretDugum[i - 1]); lua_setfield(L, -2, "dugum"); // sahne işareti } lua_rawseti(L, -2, i++); } return 1; } // fiko.cae.kurulumKaydet(dugum, {cozunurluk,E,nu,sabitYuz,yukYuz,fx,fy,fz,simetri,konservatif}) // Analiz kurulumunu BELGEYE yazar (v1.19 CAEK → kaydet/aç korur). Aynı düğüm için varsa // üzerine yazar. Köprü yoksa (belge bağlı değil) nil döner. int MakroMotor::l_caeKurulumKaydet(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->caeKurulumlar_) { lua_pushnil(L); return 1; } io::FikoCaeKurulum c; c.dugum = (u32)luaL_checkinteger(L, 1); if (lua_istable(L, 2)) { const auto sayi = [&](const char* ad, f64 vars) { lua_getfield(L, 2, ad); const f64 v = lua_isnumber(L, -1) ? lua_tonumber(L, -1) : vars; lua_pop(L, 1); return v; }; const auto yuz = [&](const char* ad, u8 vars) { lua_getfield(L, 2, ad); u8 v = vars; if (lua_isstring(L, -1)) { const std::string s2 = lua_tostring(L, -1); if (s2 == "-x") v = 0; else if (s2 == "+x") v = 1; else if (s2 == "-y") v = 2; else if (s2 == "+y") v = 3; else if (s2 == "-z") v = 4; else if (s2 == "+z") v = 5; } lua_pop(L, 1); return v; }; c.cozunurluk = (u32)sayi("cozunurluk", 24.0); c.elastisite = sayi("E", 210000.0); c.poisson = sayi("nu", 0.3); c.kuvvet[0] = sayi("fx", 0.0); c.kuvvet[1] = sayi("fy", 0.0); c.kuvvet[2] = sayi("fz", 0.0); c.sabitYuz = yuz("sabitYuz", 0); c.yukYuz = yuz("yukYuz", 1); c.simetriKisit = (u8)(sayi("simetri", 0.0) != 0.0 ? 1 : 0); c.konservatif = (u8)(sayi("konservatif", 1.0) != 0.0 ? 1 : 0); } for (io::FikoCaeKurulum& v : *m->caeKurulumlar_) if (v.dugum == c.dugum) { v = c; lua_pushboolean(L, 1); return 1; } m->caeKurulumlar_->push_back(c); lua_pushboolean(L, 1); return 1; } // fiko.cae.kurulumlar() → { {dugum,cozunurluk,E,nu,sabitYuz,yukYuz,fx,fy,fz,...}, ... } int MakroMotor::l_caeKurulumlar(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->caeKurulumlar_) { lua_pushnil(L); return 1; } lua_createtable(L, (int)m->caeKurulumlar_->size(), 0); int i = 1; for (const io::FikoCaeKurulum& c : *m->caeKurulumlar_) { lua_createtable(L, 0, 10); lua_pushinteger(L, c.dugum); lua_setfield(L, -2, "dugum"); lua_pushinteger(L, c.cozunurluk); lua_setfield(L, -2, "cozunurluk"); lua_pushnumber(L, c.elastisite); lua_setfield(L, -2, "E"); lua_pushnumber(L, c.poisson); lua_setfield(L, -2, "nu"); lua_pushinteger(L, c.sabitYuz); lua_setfield(L, -2, "sabitYuz"); lua_pushinteger(L, c.yukYuz); lua_setfield(L, -2, "yukYuz"); lua_pushnumber(L, c.kuvvet[0]); lua_setfield(L, -2, "fx"); lua_pushnumber(L, c.kuvvet[1]); lua_setfield(L, -2, "fy"); lua_pushnumber(L, c.kuvvet[2]); lua_setfield(L, -2, "fz"); lua_pushinteger(L, c.konservatif); lua_setfield(L, -2, "konservatif"); lua_rawseti(L, -2, i++); } return 1; } // fiko.kinematik.isaretTemizle() → silinen işaret sayısı // carpismaTara(..., isaretle=true) ile sahneye konan girişim gövdelerini kaldırır. // Kullanıcı geometrisine DOKUNMAZ (yalnız bu API'nin ürettiği düğümler). int MakroMotor::l_kinIsaretTemizle(lua_State* L) { MakroMotor* m = kendisi(L); int silinen = 0; for (u32 k : m->kinIsaretler_) if (m->sahne_.bul(k)) { m->sahne_.sil(k); ++silinen; } m->kinIsaretler_.clear(); lua_pushinteger(L, silinen); return 1; } // fiko.cae.coz(dugum, {cozunurluk, E, nu, sabitYuz, yukYuz, fx, fy, fz}) // Gövdeyi voxelleyip lineer elastik FEM çözer (hex8). Yüz adları: "-x","+x","-y", // "+y","-z","+z" (KAFES yüzü — gövdenin AABB sınırı). Sonuç tablosu döner. int MakroMotor::l_caeCoz(lua_State* L) { MakroMotor* m = kendisi(L); const u32 kimlik = (u32)luaL_checkinteger(L, 1); const Dugum* d = m->sahne_.bul(kimlik); if (!d || !d->brep || !d->brep->gecerliMi()) { lua_pushnil(L); return 1; } const auto yuzCoz = [](const char* ad, cae::KafesYuz vars) { if (!ad) return vars; const std::string s = ad; if (s == "-x") return cae::KafesYuz::EksiX; if (s == "+x") return cae::KafesYuz::ArtiX; if (s == "-y") return cae::KafesYuz::EksiY; if (s == "+y") return cae::KafesYuz::ArtiY; if (s == "-z") return cae::KafesYuz::EksiZ; if (s == "+z") return cae::KafesYuz::ArtiZ; return vars; }; cae::KafesKurulum kur; kur.konservatif = cae::konservatifKafes(); // AyarSistemi: cae.konservatif_kafes cae::ElastikMalzeme mlz; cae::KafesYuz sabitYuz = cae::KafesYuz::EksiX, yukYuz = cae::KafesYuz::ArtiX; Vec3d kuvvet{0.0, 0.0, 0.0}; if (lua_istable(L, 2)) { const auto sayi = [&](const char* ad, f64 vars) { lua_getfield(L, 2, ad); const f64 v = lua_isnumber(L, -1) ? lua_tonumber(L, -1) : vars; lua_pop(L, 1); return v; }; const auto metin = [&](const char* ad, cae::KafesYuz vars) { lua_getfield(L, 2, ad); const cae::KafesYuz v = yuzCoz(lua_isstring(L, -1) ? lua_tostring(L, -1) : nullptr, vars); lua_pop(L, 1); return v; }; kur.enUzunHucre = (u32)sayi("cozunurluk", 24.0); lua_getfield(L, 2, "konservatif"); if (!lua_isnil(L, -1)) kur.konservatif = lua_toboolean(L, -1) != 0; lua_pop(L, 1); kur.kaliteOrani = sayi("kalite", 0.01); mlz.elastisite = sayi("E", 210000.0); mlz.poisson = sayi("nu", 0.3); kuvvet = {sayi("fx", 0.0), sayi("fy", 0.0), sayi("fz", 0.0)}; sabitYuz = metin("sabitYuz", sabitYuz); yukYuz = metin("yukYuz", yukYuz); } bool harita = false; if (lua_istable(L, 2)) { lua_getfield(L, 2, "harita"); harita = lua_toboolean(L, -1) != 0; lua_pop(L, 1); } dokum::VoxelKafes vk; const cae::HexKafes kf = cae::govdedenKafes(*d->brep, kur, harita ? &vk : nullptr); if (!kf.gecerliMi()) { lua_pushnil(L); return 1; } // sabitKip: "tam" (3 eksen ankastre, VARSAYILAN = eski davranış) | "simetri" // (yalnız yüzün normali tutulur → Poisson daralması serbest; ölçüldü 07-21: // eksenel uzama sapması %-0.80 → %0.00). bool simetri = false; if (lua_istable(L, 2)) { lua_getfield(L, 2, "sabitKip"); simetri = lua_isstring(L, -1) && std::string(lua_tostring(L, -1)) == "simetri"; lua_pop(L, 1); } std::vector kisitlar; if (simetri) { kisitlar = cae::yuzKisitlari(kf, sabitYuz, cae::yuzNormalMaske(sabitYuz)); // Rijit cisim hareketini kalan iki eksende de durdur: diğer iki yüzde // yalnız kendi normalleri tutulur (klasik simetri üçlüsü). for (const cae::KafesYuz y : {cae::KafesYuz::EksiY, cae::KafesYuz::EksiZ}) { if (cae::yuzNormalMaske(y) == cae::yuzNormalMaske(sabitYuz)) continue; const auto ek = cae::yuzKisitlari(kf, y, cae::yuzNormalMaske(y)); kisitlar.insert(kisitlar.end(), ek.begin(), ek.end()); } } else { for (u32 dg : cae::yuzDugumleri(kf, sabitYuz)) kisitlar.push_back({dg, 0x7}); } const cae::FemSonuc s = cae::femCoz(kf, mlz, kisitlar, cae::yuzeYayliKuvvet(kf, yukYuz, kuvvet)); u32 dolu = 0; for (u8 v : kf.dolu) dolu += v ? 1u : 0u; // Yük yüzünün ORTALAMA yer değiştirmesi: analitik uzamayla (FL/AE) doğrudan // kıyaslanabilir tek büyüklük. `enBuyukYer` uçtaki Poisson yanal hareketini de // içerir, `enBuyukGerilme` ise ankastre kökteki YIĞILMADIR — ölçüldü 07-21: // 100×20×20 kirişte max gerilme nominalin %60 üstü, max yer uzamanın %12 üstü. f64 yukYuzYer = 0.0; { const std::vector yy = cae::yuzDugumleri(kf, yukYuz); for (u32 dg : yy) if (dg < s.yer.size()) yukYuzYer += s.yer[dg].uzunluk(); if (!yy.empty()) yukYuzYer /= (f64)yy.size(); } // harita=true: von Mises alanı MEVCUT jenerik küp-mesh yoluyla (dokum::alanMeshKur) // sahneye renkli ısı-haritası düğümü olarak konur. Yeni render yolu YOK. u32 haritaDugum = 0; f32 haritaMin = 0.0f, haritaMaks = 0.0f; if (harita && s.yakinsadi && vk.gecerliMi() && s.vonMises.size() == vk.hucreSayi()) { std::vector alan(s.vonMises.size()); for (std::size_t i = 0; i < alan.size(); ++i) alan[i] = (f32)s.vonMises[i]; dokum::VoxelGorselAyar ga; ga.alan = dokum::VoxelAlan::Sicaklik; // alanMeshKur yalnız rampa/aralığı kullanır ga.rampa = dokum::VoxelRampa::Turbo; ga.kirpParcaya = true; dokum::VoxelGorselSonuc vg = dokum::alanMeshKur(vk, alan, ga); if (vg.gecerli) { // Renk skalasının SAYISAL karşılığı — lejant olmadan renk okunamaz. haritaMin = vg.alanMin; haritaMaks = vg.alanMax; haritaDugum = m->sahne_.hazirMeshEkle("FEM Gerilme Haritası", VARLIK_YOK, {0.6f, 0.6f, 0.6f}, std::move(vg.mesh)); if (Dugum* nd = m->sahne_.bul(haritaDugum)) nd->donusum = d->donusum; } } // KALİTE: en ince yönde kaç hücre var? Az ise sonuç sessizce anlamsız olur → hem // sonuca alan olarak koy hem de UYAR (kullanıcı/AI körlemesine güvenmesin). const u32 incede = cae::enIncedeHucre(kf); if (incede > 0 && incede < cae::asgariCidarHucre()) gunluk::uyari("[cae] KABA KAFES: en ince yonde {} hucre (asgari {}) — h={:.2f}; " "cozunurlugu artir, sonuc guvenilmez", incede, cae::asgariCidarHucre(), kf.h); lua_createtable(L, 0, 13); lua_pushinteger(L, incede); lua_setfield(L, -2, "enIncedeHucre"); lua_pushinteger(L, haritaDugum); lua_setfield(L, -2, "haritaDugum"); lua_pushnumber(L, haritaMin); lua_setfield(L, -2, "haritaMin"); lua_pushnumber(L, haritaMaks); lua_setfield(L, -2, "haritaMaks"); lua_pushnumber(L, yukYuzYer); lua_setfield(L, -2, "yukYuzYer"); lua_pushboolean(L, s.yakinsadi); lua_setfield(L, -2, "yakinsadi"); lua_pushinteger(L, s.adim); lua_setfield(L, -2, "adim"); lua_pushnumber(L, s.artik); lua_setfield(L, -2, "artik"); lua_pushnumber(L, s.enBuyukYer); lua_setfield(L, -2, "enBuyukYer"); lua_pushnumber(L, s.enBuyukVonMises); lua_setfield(L, -2, "enBuyukGerilme"); lua_pushinteger(L, (lua_Integer)kf.nx); lua_setfield(L, -2, "nx"); lua_pushinteger(L, (lua_Integer)kf.ny); lua_setfield(L, -2, "ny"); lua_pushinteger(L, (lua_Integer)kf.nz); lua_setfield(L, -2, "nz"); lua_pushnumber(L, kf.h); lua_setfield(L, -2, "h"); lua_pushinteger(L, (lua_Integer)dolu); lua_setfield(L, -2, "dolu"); return 1; } // fiko.kinematik.sabitle(uzuv) → mafsal indeksi // Uzvu GÖVDEYE, ŞU ANKİ YERİNDE sabitler (çapa = uzvun tabanı). Birim çapalı bir // "sabit" mafsal eklemek uzvu ORİJİNE IŞINLAR — ölçüldü 07-21: mil z=+1'de duruyordu, // birim çapalı gövde bağı onu z=0'a çekti ve zincirdeki her şey 1 mm kaydı. int MakroMotor::l_kinSabitle(lua_State* L) { MakroMotor* m = kendisi(L); const std::size_t i = (std::size_t)luaL_checkinteger(L, 1); const auto& uz = m->mekanizma_->uzuvlar(); if (i == 0 || i >= uz.size()) { lua_pushnil(L); return 1; } kinematik::Mafsal mf; mf.tip = kinematik::MafsalTip::Sabit; mf.ad = "Sabit"; mf.ana = 0; mf.cocuk = i; mf.capa = uz[i].taban; // gövde yereli = dünya → uzuv olduğu yerde kalır lua_pushinteger(L, (lua_Integer)m->mekanizma_->mafsalEkle(std::move(mf))); return 1; } // fiko.kinematik.oner(dugumA, dugumB, yaricapTol, mesafeTol) // → { {tip=, guven=, yaricap=, yuzA=, yuzB=, aciklama=}, ... } (güvene göre sıralı) // GEOMETRİDEN mafsal çıkarımı ("smart mate"): montaj kısıtı gerekmez. Sahneyi // DEĞİŞTİRMEZ — yalnız aday üretir; kabul için `onerEkle` kullanılır. int MakroMotor::l_kinOner(lua_State* L) { MakroMotor* m = kendisi(L); const Dugum* da = m->sahne_.bul((u32)luaL_checkinteger(L, 1)); const Dugum* db = m->sahne_.bul((u32)luaL_checkinteger(L, 2)); if (!da || !db || !da->brep || !db->brep) { lua_pushnil(L); return 1; } const geometri::BrepGovde ga = geometri::donusumUygula(*da->brep, da->donusum); const geometri::BrepGovde gb = geometri::donusumUygula(*db->brep, db->donusum); const auto liste = mafsalOner(ga, gb, luaL_optnumber(L, 3, 0.05), luaL_optnumber(L, 4, 0.05)); lua_createtable(L, (int)liste.size(), 0); int i = 1; for (const MafsalOneri& o : liste) { lua_createtable(L, 0, 6); lua_pushstring(L, kinematik::mafsalTipAdi(o.tip)); lua_setfield(L, -2, "tip"); lua_pushnumber(L, o.guven); lua_setfield(L, -2, "guven"); lua_pushnumber(L, o.yaricap); lua_setfield(L, -2, "yaricap"); lua_pushinteger(L, (lua_Integer)o.yuzA); lua_setfield(L, -2, "yuzA"); lua_pushinteger(L, (lua_Integer)o.yuzB); lua_setfield(L, -2, "yuzB"); lua_pushstring(L, o.aciklama.c_str()); lua_setfield(L, -2, "aciklama"); lua_rawseti(L, -2, i++); } return 1; } // fiko.kinematik.onerEkle(uzuvA, uzuvB, sira) → mafsal indeksi // `sira` (1-tabanlı, vars. 1) numaralı öneriyi GERÇEK mafsala çevirir. Öneri çapaları // DÜNYA uzayındadır; `capa` ana uzvun, `capaCocuk` çocuk uzvun YERELİNE çevrilir // (uzuv tabanının tersiyle) → mafsal eklendiği anda parçalar YERİNDEN OYNAMAZ. int MakroMotor::l_kinOnerEkle(lua_State* L) { MakroMotor* m = kendisi(L); const std::size_t ia = (std::size_t)luaL_checkinteger(L, 1); const std::size_t ib = (std::size_t)luaL_checkinteger(L, 2); const auto& uz = m->mekanizma_->uzuvlar(); if (ia >= uz.size() || ib >= uz.size()) { lua_pushnil(L); return 1; } const Dugum* da = m->sahne_.bul(uz[ia].sahne); const Dugum* db = m->sahne_.bul(uz[ib].sahne); if (!da || !db || !da->brep || !db->brep) { lua_pushnil(L); return 1; } const geometri::BrepGovde ga = geometri::donusumUygula(*da->brep, da->donusum); const geometri::BrepGovde gb = geometri::donusumUygula(*db->brep, db->donusum); const auto liste = mafsalOner(ga, gb); const std::size_t sira = (std::size_t)luaL_optinteger(L, 3, 1); if (sira == 0 || sira > liste.size()) { lua_pushnil(L); return 1; } const MafsalOneri& o = liste[sira - 1]; kinematik::Mafsal mf; mf.tip = o.tip; mf.ad = kinematik::mafsalTipAdi(o.tip); mf.ana = ia; mf.cocuk = ib; mf.capa = uz[ia].taban.ters() * o.capaA; // dünya → ANA uzuv yereli mf.capaCocuk = uz[ib].taban.ters() * o.capaB; // dünya → ÇOCUK uzuv yereli lua_pushinteger(L, (lua_Integer)m->mekanizma_->mafsalEkle(std::move(mf))); return 1; } // fiko.kinematik.durum() → {uzuv=, mafsal=, dof=, agac=} int MakroMotor::l_kinDurum(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->mekanizma_) { lua_pushnil(L); return 1; } lua_createtable(L, 0, 4); lua_pushinteger(L, (lua_Integer)m->mekanizma_->uzuvlar().size()); lua_setfield(L, -2, "uzuv"); lua_pushinteger(L, (lua_Integer)m->mekanizma_->mafsallar().size()); lua_setfield(L, -2, "mafsal"); lua_pushinteger(L, m->mekanizma_->serbestlikDerecesi()); lua_setfield(L, -2, "dof"); lua_pushboolean(L, m->mekanizma_->agacMi()); lua_setfield(L, -2, "agac"); lua_pushinteger(L, (lua_Integer)m->mekanizma_->yasalar().size()); lua_setfield(L, -2, "yasa"); return 1; } // ── fiko.analiz.* (kalıp/yüzey kalite analizleri) ─────────────────────────── // 10 tip: draft · undercut · kalinlik · radius · kurvatur · zebra · sureklilik · // reflect · fark · keskin. Motor tarafı vardı, yüzeyi yoktu → yapay zeka "bu parça kalıptan // çıkar mı, en ince cidar nerede, yüzey G2 sürekli mi" sorularını SAYIYLA yanıtlayabilsin. namespace { bool analizTipCoz(const std::string& ad, analiz::AnalizTip& t) { using A = analiz::AnalizTip; if (ad == "draft") t = A::Draft; else if (ad == "undercut") t = A::Undercut; else if (ad == "kalinlik") t = A::Kalinlik; else if (ad == "radius") t = A::Radius; else if (ad == "kurvatur") t = A::Kurvatur; else if (ad == "zebra") t = A::Zebra; else if (ad == "sureklilik") t = A::Sureklilik; else if (ad == "reflect") t = A::Reflect; else if (ad == "fark") t = A::Fark; else if (ad == "keskin") t = A::KeskinKenar; else return false; return true; } } // namespace // fiko.analiz.tipler() → { "draft", "undercut", ... } int MakroMotor::l_analizTipler(lua_State* L) { static const char* kTipler[] = {"draft", "undercut", "kalinlik", "radius", "kurvatur", "zebra", "sureklilik", "reflect", "fark", "keskin"}; lua_createtable(L, 10, 0); for (int i = 0; i < 10; ++i) { lua_pushstring(L, kTipler[i]); lua_rawseti(L, -2, i + 1); } return 1; } // fiko.analiz.ekle(tip, hedefDugum) → analiz kimlik (hesaplanmış) int MakroMotor::l_analizEkle(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->analiz_) { lua_pushnil(L); return 1; } analiz::AnalizTip t{}; if (!analizTipCoz(luaL_checkstring(L, 1), t)) { lua_pushnil(L); return 1; } const u32 k = m->analiz_->ekle(t, (u32)luaL_checkinteger(L, 2)); if (!k) { lua_pushnil(L); return 1; } m->analiz_->hesapla(k); lua_pushinteger(L, (lua_Integer)k); return 1; } // fiko.analiz.sonuc(kimlik) → {tip=, ozet=, min=, max=, birim=, kritik=, hazir=, // rapor={{ad=,deger=,kritik=,ordinal=}, ...}} int MakroMotor::l_analizSonuc(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->analiz_) { lua_pushnil(L); return 1; } analiz::AnalizNesnesi* a = m->analiz_->bul((u32)luaL_checkinteger(L, 1)); if (!a) { lua_pushnil(L); return 1; } lua_createtable(L, 0, 8); lua_pushstring(L, analiz::analizTipAdi(a->tip())); lua_setfield(L, -2, "tip"); lua_pushstring(L, a->ozet.c_str()); lua_setfield(L, -2, "ozet"); lua_pushnumber(L, a->sonuc.min); lua_setfield(L, -2, "min"); lua_pushnumber(L, a->sonuc.max); lua_setfield(L, -2, "max"); lua_pushstring(L, a->sonuc.birim.c_str()); lua_setfield(L, -2, "birim"); lua_pushinteger(L, (lua_Integer)a->sonuc.kritikSayi); lua_setfield(L, -2, "kritik"); lua_pushboolean(L, a->sonuc.hazir); lua_setfield(L, -2, "hazir"); lua_createtable(L, (int)a->rapor.size(), 0); int i = 1; for (const auto& r : a->rapor) { lua_createtable(L, 0, 4); lua_pushstring(L, r.ad.c_str()); lua_setfield(L, -2, "ad"); lua_pushnumber(L, r.deger); lua_setfield(L, -2, "deger"); lua_pushboolean(L, r.kritik); lua_setfield(L, -2, "kritik"); lua_pushinteger(L, (lua_Integer)r.ordinal); lua_setfield(L, -2, "ordinal"); lua_rawseti(L, -2, i++); } lua_setfield(L, -2, "rapor"); return 1; } // fiko.analiz.sil(kimlik) int MakroMotor::l_analizSil(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->analiz_) { lua_pushnil(L); return 1; } lua_pushboolean(L, m->analiz_->sil((u32)luaL_checkinteger(L, 1)) ? 1 : 0); return 1; } // ── fiko.parca.* (Part Design) ────────────────────────────────────────────── // fiko.parca.tipler() → { {tip=, ad=, malzemeEkler=, parametreler={{anahtar=,etiket=, // tip=,varsayilan=,birim=,secenekler={...}}, ...}}, ... } int MakroMotor::l_parcaTipler(lua_State* L) { tanimlariYaz(L, parca::featureTanimlari()); return 1; } // fiko.parca.ekle(tip, sketchVarlik, {param=deger}, hedefDugum) → feature kimlik int MakroMotor::l_parcaEkle(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->parca_) { lua_pushnil(L); return 1; } const std::string tip = luaL_checkstring(L, 1); const Varlik sk = (Varlik)luaL_optinteger(L, 2, (lua_Integer)VARLIK_YOK); const u32 hedef = (u32)luaL_optinteger(L, 4, 0); const u32 fk = m->parca_->featureBaslat(tip, sk, hedef); if (!fk) { lua_pushnil(L); return 1; } const auto params = paramTablosu(L, 3); if (!params.empty()) m->parca_->featureParamToplu(fk, params); lua_pushinteger(L, (lua_Integer)fk); return 1; } // fiko.parca.guncelle(featureKimlik, {param=deger}) → true/nil int MakroMotor::l_parcaGuncelle(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->parca_) { lua_pushnil(L); return 1; } const u32 fk = (u32)luaL_checkinteger(L, 1); const auto params = paramTablosu(L, 2); if (params.empty()) { lua_pushnil(L); return 1; } m->parca_->featureParamToplu(fk, params); lua_pushboolean(L, 1); return 1; } // fiko.parca.featureler() → { {kimlik=, tip=, dugum=}, ... } (recompute sırasında) int MakroMotor::l_parcaFeatureler(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->parca_) { lua_pushnil(L); return 1; } const auto& sira = m->parca_->featureSirasi(); lua_createtable(L, (int)sira.size(), 0); int i = 1; for (u32 fk : sira) { lua_createtable(L, 0, 3); lua_pushinteger(L, (lua_Integer)fk); lua_setfield(L, -2, "kimlik"); lua_pushstring(L, m->parca_->featureTip(fk).c_str()); lua_setfield(L, -2, "tip"); lua_pushinteger(L, (lua_Integer)m->parca_->featureSonucDugum(fk)); lua_setfield(L, -2, "dugum"); // Hata metni: feature hesaplanamadıysa NEDENİ burada (yapay zeka kendini düzeltebilsin). if (parca::Feature* f = m->parca_->bul(fk)) { lua_pushstring(L, f->hata().c_str()); lua_setfield(L, -2, "hata"); } lua_rawseti(L, -2, i++); } return 1; } // ── fiko.parametre.* (CATIA parametre tablosu + formül/DAG) ──────────────── // Motor tarafı (ParametreDeposu + ParametreNesnesi + Feature::formulAyarla) ZATEN // vardı ama HİÇBİR yüzeyi yoktu → sürülemiyor, ölçülemiyordu. Bu bağlama, parametrik // modellemeyi makro/MCP'den uçtan uca kullanılabilir yapar. // fiko.parametre.ekle(ad, ifadeVeyaSayi, birim) → parametre Varlik int MakroMotor::l_parametreEkle(lua_State* L) { MakroMotor* m = kendisi(L); const std::string ad = luaL_checkstring(L, 1); if (ad.empty()) { lua_pushnil(L); return 1; } const bool sayiMi = lua_isnumber(L, 2) != 0; const f64 baslangic = sayiMi ? (f64)lua_tonumber(L, 2) : 0.0; const std::string birim = luaL_optstring(L, 3, "mm"); const u32 v = m->sahne_.parametreEkle(ad, baslangic, birim); if (!v) { lua_pushnil(L); return 1; } if (!sayiMi) { // ifade verildi (ör. "genislik / 2") → düğüme yaz if (auto* pn = dynamic_cast(m->cekirdekRef().nesne(v))) pn->ifadeAyarla(luaL_checkstring(L, 2)); } m->sahne_.parametreleriCoz(); // DAG çöz + ParametreDegisti → bağımlı feature recompute lua_pushinteger(L, (lua_Integer)v); return 1; } // fiko.parametre.ayarla(ad, ifadeVeyaSayi) → true/nil (değiştir + yeniden çöz) int MakroMotor::l_parametreAyarla(lua_State* L) { MakroMotor* m = kendisi(L); const std::string ad = luaL_checkstring(L, 1); const u32 v = m->sahne_.parametreVarlik(ad); auto* pn = v ? dynamic_cast(m->cekirdekRef().nesne(v)) : nullptr; if (!pn) { lua_pushnil(L); return 1; } if (lua_isnumber(L, 2)) { char buf[64]; std::snprintf(buf, sizeof buf, "%g", (f64)lua_tonumber(L, 2)); pn->ifadeAyarla(buf); } else { pn->ifadeAyarla(luaL_checkstring(L, 2)); } m->sahne_.parametreleriCoz(); lua_pushboolean(L, 1); return 1; } // fiko.parametre.liste() → { {ad=, ifade=, birim=, deger=, hata=}, ... } int MakroMotor::l_parametreListe(lua_State* L) { MakroMotor* m = kendisi(L); const auto& hepsi = m->sahne_.paramDepo().hepsi(); lua_createtable(L, (int)hepsi.size(), 0); int i = 1; for (const parametre::Parametre& p : hepsi) { lua_createtable(L, 0, 5); lua_pushstring(L, p.ad.c_str()); lua_setfield(L, -2, "ad"); lua_pushstring(L, p.ifade.c_str()); lua_setfield(L, -2, "ifade"); lua_pushstring(L, p.birim.c_str()); lua_setfield(L, -2, "birim"); lua_pushnumber(L, p.deger); lua_setfield(L, -2, "deger"); lua_pushstring(L, p.hata.c_str()); lua_setfield(L, -2, "hata"); lua_rawseti(L, -2, i++); } return 1; } // fiko.parametre.sil(ad) int MakroMotor::l_parametreSil(lua_State* L) { MakroMotor* m = kendisi(L); const std::string ad = luaL_checkstring(L, 1); const u32 v = m->sahne_.parametreVarlik(ad); if (!v) { lua_pushnil(L); return 1; } m->cekirdek_.uygula(std::make_unique(m->sahne_, std::vector{v})); m->sahne_.parametreleriCoz(); lua_pushboolean(L, 1); return 1; } // fiko.parca.formul(featureKimlik, anahtar, ifade) — feature alanına f(x) BAĞLA. // ifade boş → bağı kaldır (sabit değere döner). Bağladıktan sonra parametre değişince // feature kendiliğinden yeniden hesaplanır (Feature::bagimliliklar DAG kenarı kurar). int MakroMotor::l_parcaFormul(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->parca_) { lua_pushnil(L); return 1; } const u32 fk = (u32)luaL_checkinteger(L, 1); parca::Feature* f = m->parca_->bul(fk); if (!f) { lua_pushnil(L); return 1; } const std::string anahtar = luaL_checkstring(L, 2); f->formulAyarla(anahtar, luaL_optstring(L, 3, "")); m->sahne_.parametreleriCoz(); // formül yeni bağımlılık kurar → zinciri tazele m->parca_->featureParamToplu(fk, {}); // TEK recompute (parametre yazımı yok, yalnız hesapla) lua_pushboolean(L, 1); return 1; } // fiko.sahne.olcu(dugumKimlik) → {hacim=, alan=, minX/minY/minZ, maksX/maksY/maksZ, boyX/boyY/boyZ} // SALT OKUMA. "Ne modelledim?" sorusunun cevabı — yapay zeka/makro sonucu DOĞRULAYABİLSİN // diye (ekran görüntüsü niteldir; bu niceldir). Parametrik zincirin gerçekten yeniden // hesaplandığını kanıtlamak için de gerekir (07-21: formül bağlandı ama katı ölçülmemişti). int MakroMotor::l_sahneOlcu(lua_State* L) { MakroMotor* m = kendisi(L); const Dugum* d = m->sahne_.bul((u32)luaL_checkinteger(L, 1)); if (!d) { lua_pushnil(L); return 1; } lua_createtable(L, 0, 11); const bool brepVar = d->brep && d->brep->gecerliMi(); lua_pushnumber(L, brepVar ? d->brep->hacim() : 0.0); lua_setfield(L, -2, "hacim"); lua_pushnumber(L, brepVar ? d->brep->alan() : 0.0); lua_setfield(L, -2, "alan"); const auto& s = d->yerelSinir; const auto alan3 = [&](const char* ad, f64 v) { lua_pushnumber(L, v); lua_setfield(L, -2, ad); }; alan3("minX", s.asgari.x); alan3("minY", s.asgari.y); alan3("minZ", s.asgari.z); alan3("maksX", s.azami.x); alan3("maksY", s.azami.y); alan3("maksZ", s.azami.z); alan3("boyX", (f64)s.azami.x - s.asgari.x); alan3("boyY", (f64)s.azami.y - s.asgari.y); alan3("boyZ", (f64)s.azami.z - s.asgari.z); // DÜNYA sınırları: yerelSinir düğüm DÖNÜŞÜMÜNÜ İÇERMEZ — yalnız yerel ölçüyü // okuyan doğrulama, parça taşınsa/döndürülse de aynı sayıyı görür ve YANILTIR // (07-21: kinematik sürüşü "çalışmıyor" sanılmasına yol açtı). 8 köşe dönüştürülüp // eksen-hizalı kutu yeniden kurulur; ayrıca dünya merkezi verilir. const Vec3f yk[8] = {{s.asgari.x, s.asgari.y, s.asgari.z}, {s.azami.x, s.asgari.y, s.asgari.z}, {s.asgari.x, s.azami.y, s.asgari.z}, {s.azami.x, s.azami.y, s.asgari.z}, {s.asgari.x, s.asgari.y, s.azami.z}, {s.azami.x, s.asgari.y, s.azami.z}, {s.asgari.x, s.azami.y, s.azami.z}, {s.azami.x, s.azami.y, s.azami.z}}; Vec3d dMin{1e300, 1e300, 1e300}, dMaks{-1e300, -1e300, -1e300}; for (const Vec3f& p : yk) { const Vec3d w = d->donusum.noktaUygula({(f64)p.x, (f64)p.y, (f64)p.z}); dMin = {std::min(dMin.x, w.x), std::min(dMin.y, w.y), std::min(dMin.z, w.z)}; dMaks = {std::max(dMaks.x, w.x), std::max(dMaks.y, w.y), std::max(dMaks.z, w.z)}; } alan3("dunyaMinX", dMin.x); alan3("dunyaMinY", dMin.y); alan3("dunyaMinZ", dMin.z); alan3("dunyaMaksX", dMaks.x); alan3("dunyaMaksY", dMaks.y); alan3("dunyaMaksZ", dMaks.z); alan3("merkezX", (dMin.x + dMaks.x) * 0.5); alan3("merkezY", (dMin.y + dMaks.y) * 0.5); alan3("merkezZ", (dMin.z + dMaks.z) * 0.5); return 1; } // fiko.parca.sil(featureKimlik) int MakroMotor::l_parcaSil(lua_State* L) { MakroMotor* m = kendisi(L); if (!m->parca_) { lua_pushnil(L); return 1; } m->parca_->featureSilKalici((u32)luaL_checkinteger(L, 1)); lua_pushboolean(L, 1); return 1; } } // namespace fiko::betik