#include "fiko/analiz/analiz_hesap.hpp" #include #include #include "fiko/analiz/analiz_nesne.hpp" // radiusSerbestKurvatur() ayari #include "fiko/geometri/brep.hpp" namespace fiko::analiz { namespace { constexpr f64 PI = 3.14159265358979323846; constexpr f64 RAD2DEG = 180.0 / PI; // Yuz normalini dunyaya tasi (yalniz donusum yonelimi; olcek isaret bozmaz varsayimi). Vec3d dunyaNormal(const Donusumd& d, Vec3d yerel) { return d.yonelim.dondur(yerel); } } // namespace f64 draftAcisi(Vec3d yuzNormal, Vec3d cekimYonu) { const f64 nl = std::sqrt(yuzNormal.uzunlukKare()); const f64 cl = std::sqrt(cekimYonu.uzunlukKare()); if (nl < 1e-9 || cl < 1e-9) return 0.0; const Vec3d n{yuzNormal.x / nl, yuzNormal.y / nl, yuzNormal.z / nl}; const Vec3d c{cekimYonu.x / cl, cekimYonu.y / cl, cekimYonu.z / cl}; f64 d = n.nokta(c); d = std::clamp(d, -1.0, 1.0); // Draft acisi: 90° − aci(normal, cekim). n·c > 0 → aciliyor (+); < 0 → ters (−). // asin(d) tam bunu verir: d=+1 (paralel) → +90°; d=−1 → −90°; d=0 (dik) → 0°. return std::asin(d) * RAD2DEG; } std::vector draftRapor(const geometri::BrepGovde& g, const Donusumd& donusum, Vec3d cekimYonu, f64 tersEsik, f64& minDraftCikti) { std::vector r; minDraftCikti = 90.0; if (!g.gecerliMi()) return r; for (u32 ord = 1;; ++ord) { geometri::YuzBilgi yb; if (!g.yuzBilgi(ord, yb)) break; // ordinal bitti if (yb.duzlemMi) { // Duz yuz: tek sabit normal → tek draft acisi. if (yb.normal.uzunlukKare() < 1e-12) continue; const Vec3d dn = dunyaNormal(donusum, yb.normal); DraftYuz dy; dy.ordinal = ord; dy.draftDeg = dy.draftMin = dy.draftMax = draftAcisi(dn, cekimYonu); dy.tersMi = dy.draftDeg < tersEsik; minDraftCikti = std::min(minDraftCikti, dy.draftDeg); r.push_back(dy); continue; } // Egri yuz (silindir/kure/torus): draft NOKTADAN NOKTAYA DEGISIR. Yuzey // ornek noktalarindan PER-NOKTA gercek normal (BRepLProp) ile min/maks draft. // Tek "ortalama" yon yanlis olurdu (K-1/K-2) — degisken/karisik isaretlenir. const std::vector noktalar = g.yuzNoktalari(ord); if (noktalar.empty()) continue; const int adim = std::max(1, (int)(noktalar.size() / 24)); // ~24 ornek/yuz f64 dMin = 90.0, dMax = -90.0; bool bulundu = false; for (size_t i = 0; i < noktalar.size(); i += (size_t)adim) { Vec3d yerelN; if (!g.yuzNoktaNormali(ord, noktalar[i], yerelN)) continue; if (yerelN.uzunlukKare() < 1e-12) continue; const Vec3d dn = dunyaNormal(donusum, yerelN); const f64 d = draftAcisi(dn, cekimYonu); dMin = std::min(dMin, d); dMax = std::max(dMax, d); bulundu = true; } if (!bulundu) continue; // normal cozulemedi (serbest yuzey) — atla DraftYuz dy; dy.ordinal = ord; dy.draftMin = dMin; dy.draftMax = dMax; dy.draftDeg = dMin; // temsili = en kritik (en kucuk draft) dy.karisikMi = (dMax - dMin) > 0.5; // >0.5° yayilim → degisken dy.tersMi = dMin < tersEsik; // araligin herhangi yeri ters → ters minDraftCikti = std::min(minDraftCikti, dMin); r.push_back(dy); } if (r.empty()) minDraftCikti = 0.0; return r; } std::vector radiusRapor(const geometri::BrepGovde& g, f64 esikAlti, u32& kritikSayiCikti) { std::vector r; kritikSayiCikti = 0; if (!g.gecerliMi()) return r; for (u32 ord = 1;; ++ord) { geometri::YuzBilgi yb; if (!g.yuzBilgi(ord, yb)) break; RadiusYuz ry; ry.ordinal = ord; if (yb.silindirMi || yb.kureMi) { ry.yaricap = yb.yaricap; } else if (yb.torusMu) { // Torusun asal egrilik yaricaplari: boru yonunde DAIMA kucukYaricap, cember // yonunde >= major−minor. Takimin girmesi gereken = kucuk olan → fillet R. ry.yaricap = yb.kucukYaricap; } else if (!yb.duzlemMi && radiusSerbestKurvatur()) { // Serbest (B-spline) + koni: analitik yaricap yok → yuz param merkezinde // asal egrilik. R = 1/max(|kMin|,|kMaks|) = en kritik (en sikisik) yon. // Duzlem hep notr kalir (egrilik 0 → R sonsuz; zaten esigin ustunde). const geometri::KurvaturBilgi kb = geometri::yuzKurvaturMerkez(g, ord); const f64 kEnBuyuk = std::max(std::abs(kb.kMin), std::abs(kb.kMaks)); if (kb.gecerli && kEnBuyuk > 1e-9) ry.yaricap = 1.0 / kEnBuyuk; } // yaricap<0 = notr (duzlem/serbest-basarisiz) — kritik sayilmaz. ry.kritik = ry.yaricap > 0 && ry.yaricap < esikAlti; if (ry.kritik) ++kritikSayiCikti; r.push_back(ry); } return r; } std::vector kalinlikRapor(const geometri::BrepGovde& g, f64 enBuyuk, f64& minCikti, f64& maxCikti) { std::vector r; minCikti = enBuyuk; maxCikti = 0.0; if (!g.gecerliMi()) return r; // Ornekleme: yuz UV izgarasi (hucre merkezleri) — ucgen dugumu DEGIL. Dugumler // yuzun KOSELERIdir: duz yuzde tessellation 4 kose verir (yuz ici hic olculmez) // ve kose isini komsu yuzu siyirip iskalar (olculdu: kama testinde 6 ornegin // 4'u iska). K-4 korunur: egri yuzlerde nokta-basi gercek normal kullanilir // (yuzKalinlikOrnekle icinde). const u32 izgara = kalinlikIzgara(); // TEK gecis: govde basina tek BRepIntCurveSurface_Inter Load. Onceki yol her yuz icin // Load ediyordu (N kurulum) — hesabin buyuk payi. YuzOrdinalleri sirali oldugu icin // tek taramakla yuz basina indirgeme yapilir (aradaki onbellege gerek yok). std::vector np; std::vector nk; std::vector nord; geometri::govdeKalinlikOrnekle(g, izgara, enBuyuk, np, nk, nord); // Yuz basi ORTALAMA, geometri::kalinlikRapor ile ayni 1.5x filtresinden gecer: // koseye yakin ornekler komsu yan duvara capraz vurup o noktanin yerel cidarini // temsil etmez; ham ortalama kirilma degeri uretir (olculmus: ort=7.5mm, gercek 2). size_t i = 0; while (i < nord.size()) { const size_t jStart = i; while (i < nord.size() && nord[i] == nord[jStart]) ++i; const size_t j = i; f64 yMin = nk[jStart]; for (size_t q = jStart; q < j; ++q) yMin = std::min(yMin, nk[q]); f64 yOrt = 0; u32 fSay = 0; const f64 esik = yMin * 1.5; for (size_t q = jStart; q < j; ++q) if (nk[q] <= esik) { yOrt += nk[q]; ++fSay; } if (!fSay) { for (size_t q = jStart; q < j; ++q) yOrt += nk[q]; fSay = (u32)(j - jStart); } yOrt /= (f64)fSay; for (size_t q = jStart; q < j; ++q) { KalinlikNokta kn; kn.yerel = np[q]; kn.kalinlik = nk[q]; minCikti = std::min(minCikti, nk[q]); maxCikti = std::max(maxCikti, nk[q]); r.push_back(kn); } minCikti = std::min(minCikti, yOrt); maxCikti = std::max(maxCikti, yOrt); } if (r.empty()) { minCikti = 0; maxCikti = 0; } return r; } } // namespace fiko::analiz