#include "fiko/cam/nesting.hpp" #include #include #include namespace fiko::cam { namespace { constexpr double EPS = 1e-9; // Parçayı oryantasyona göre çözer: levhaya sığan + raf paketleme için yatık // (küçük-boy) tercih edilen (en, boy, döndü?) döndürür. Sığmıyorsa sigar=false. struct Yon { double en, boy; bool dondu; bool sigar; }; Yon oryantasyonSec(const NestParca& p, const NestLevha& levha) { const bool duz = p.en <= levha.en + EPS && p.boy <= levha.boy + EPS; const bool don = p.dondurulebilir && p.boy <= levha.en + EPS && p.en <= levha.boy + EPS; if (!duz && !don) return {0, 0, false, false}; // Döndürülebilir + döndürünce yatar (boy küçülür) VEYA düz hiç sığmıyorsa çevir. if (p.dondurulebilir && don && (!duz || p.en < p.boy)) { return {p.boy, p.en, true, true}; // 90° çevrik } return {p.en, p.boy, false, true}; } } // namespace NestSonuc nestingYerlestir(const std::vector& parcalar, const NestLevha& levha, double kerf) { struct Oge { std::string kimlik; double en, boy; bool dondu; }; std::vector ogeler; NestSonuc sonuc; // 1. adet genişlet + oryantasyon seç (sığmayanları ayır). for (const NestParca& p : parcalar) { const Yon y = oryantasyonSec(p, levha); const int adet = std::max(1, p.adet); if (!y.sigar) { for (int c = 0; c < adet; ++c) sonuc.yerlesmeyen.push_back(p.kimlik); continue; } for (int c = 0; c < adet; ++c) ogeler.push_back({p.kimlik, y.en, y.boy, y.dondu}); } // 2. Boy azalan sırala (FFDH — yüksek parçalar önce, raf yüksekliğini belirler). std::stable_sort(ogeler.begin(), ogeler.end(), [](const Oge& a, const Oge& b) { return a.boy > b.boy; }); // 3. Raf paketleme + çok-levha taşma. struct Raf { int levha; double y; // rafın alt kenarı double yuk; // raf yüksekliği (= ilk/en yüksek parça) double xImlec; // sonraki parça X'i }; std::vector raflar; int sonLevha = 0; for (const Oge& o : ogeler) { // First-fit: mevcut rafları sırayla dene (önceki levhalar dahil). bool yerlesti = false; for (Raf& r : raflar) { if (o.boy <= r.yuk + EPS && r.xImlec + o.en <= levha.en + EPS) { sonuc.yerlesimler.push_back({o.kimlik, r.xImlec, r.y, o.en, o.boy, o.dondu, r.levha}); r.xImlec += o.en + kerf; yerlesti = true; break; } } if (yerlesti) continue; // Yeni raf: son levhada kullanılan yüksekliğin üstüne. double kullanilanY = 0; for (const Raf& r : raflar) if (r.levha == sonLevha) kullanilanY = std::max(kullanilanY, r.y + r.yuk + kerf); if (kullanilanY + o.boy <= levha.boy + EPS) { raflar.push_back({sonLevha, kullanilanY, o.boy, o.en + kerf}); sonuc.yerlesimler.push_back({o.kimlik, 0, kullanilanY, o.en, o.boy, o.dondu, sonLevha}); } else { // Yeni levha aç. ++sonLevha; raflar.push_back({sonLevha, 0, o.boy, o.en + kerf}); sonuc.yerlesimler.push_back({o.kimlik, 0, 0, o.en, o.boy, o.dondu, sonLevha}); } } sonuc.levhaSayisi = sonuc.yerlesimler.empty() ? 0 : (sonLevha + 1); // 4. Doluluk oranı. const double levhaAlan = levha.en * levha.boy; if (sonuc.levhaSayisi > 0 && levhaAlan > EPS) { double yerlesenAlan = 0; for (const NestYerlesim& y : sonuc.yerlesimler) yerlesenAlan += y.en * y.boy; sonuc.kullanim = yerlesenAlan / (sonuc.levhaSayisi * levhaAlan); } return sonuc; } namespace { // DXF LINE entity ekler (Z=0). void dxfCizgi(std::string& o, const char* katman, double x1, double y1, double x2, double y2) { char b[256]; std::snprintf(b, sizeof(b), "0\nLINE\n8\n%s\n10\n%.4f\n20\n%.4f\n30\n0\n11\n%.4f\n21\n%.4f\n31\n0\n", katman, x1, y1, x2, y2); o += b; } // Dikdörtgen = 4 LINE (sol-alt (x,y), en×boy). void dxfDikdortgen(std::string& o, const char* katman, double x, double y, double en, double boy) { dxfCizgi(o, katman, x, y, x + en, y); // alt dxfCizgi(o, katman, x + en, y, x + en, y + boy); // sağ dxfCizgi(o, katman, x + en, y + boy, x, y + boy); // üst dxfCizgi(o, katman, x, y + boy, x, y); // sol } } // namespace std::string nestingDxfMetin(const NestSonuc& sonuc, const NestLevha& levha, double aralik) { std::string o = "0\nSECTION\n2\nENTITIES\n"; const double adim = levha.en + aralik; // levhalar arası X ötelemesi // Levha sınırları. for (int s = 0; s < sonuc.levhaSayisi; ++s) dxfDikdortgen(o, "LEVHA", s * adim, 0, levha.en, levha.boy); // Parçalar (kendi levhasının ötelemesiyle). for (const NestYerlesim& y : sonuc.yerlesimler) dxfDikdortgen(o, "PARCA", y.levha * adim + y.x, y.y, y.en, y.boy); o += "0\nENDSEC\n0\nEOF\n"; return o; } bool nestingDxfKaydet(const NestSonuc& sonuc, const NestLevha& levha, const std::string& yol, double aralik) { std::ofstream f(yol, std::ios::binary); if (!f) return false; f << nestingDxfMetin(sonuc, levha, aralik); return f.good(); } } // namespace fiko::cam