|
|
import gradio as gr |
|
|
import pandas as pd |
|
|
from rectpack import newPacker |
|
|
import matplotlib.pyplot as plt |
|
|
import matplotlib.patches as patches |
|
|
import random |
|
|
|
|
|
|
|
|
|
|
|
def calculate_single_cabinet_parts(dolap_no, h, w, d, kalinlik, raf_sayisi, kapak_var, kapak_sayisi, arkalik_var): |
|
|
"""Tek bir dolabın parçalarını hesaplar.""" |
|
|
parts = [] |
|
|
|
|
|
|
|
|
ic_genislik = w - (2 * kalinlik) |
|
|
parts.append({'dolap_no': dolap_no, 'parca_adi': 'Yan Tabla', 'adet': 2, 'uzunluk': h, 'genislik': d, 'malzeme': 'Sunta'}) |
|
|
parts.append({'dolap_no': dolap_no, 'parca_adi': 'Alt/Üst Tabla', 'adet': 2, 'uzunluk': ic_genislik, 'genislik': d, 'malzeme': 'Sunta'}) |
|
|
|
|
|
|
|
|
if raf_sayisi > 0: |
|
|
raf_derinlik = d - 1 |
|
|
parts.append({'dolap_no': dolap_no, 'parca_adi': 'Raf', 'adet': raf_sayisi, 'uzunluk': ic_genislik, 'genislik': raf_derinlik, 'malzeme': 'Sunta'}) |
|
|
|
|
|
|
|
|
if kapak_var and kapak_sayisi > 0: |
|
|
calisma_boslugu = 3 |
|
|
bant_payi = 1 |
|
|
kapak_yukseklik = h - calisma_boslugu |
|
|
toplam_kullanilabilir_genislik = w - calisma_boslugu |
|
|
bitmis_kapak_genisligi = toplam_kullanilabilir_genislik / kapak_sayisi |
|
|
net_kesim_genisligi = bitmis_kapak_genisligi - (2 * bant_payi) |
|
|
parts.append({'dolap_no': dolap_no, 'parca_adi': 'Kapak', 'adet': kapak_sayisi, 'uzunluk': kapak_yukseklik, 'genislik': round(net_kesim_genisligi, 2), 'malzeme': 'Sunta'}) |
|
|
|
|
|
|
|
|
if arkalik_var: |
|
|
parts.append({'dolap_no': dolap_no, 'parca_adi': 'Arkalık', 'adet': 1, 'uzunluk': h, 'genislik': w, 'malzeme': 'HDF/Duralit'}) |
|
|
|
|
|
return parts |
|
|
|
|
|
def add_cabinet_to_list(all_parts_state, cabinet_number_state, h, w, d, kalinlik, raf_sayisi, kapak_var, kapak_sayisi, arkalik_var): |
|
|
"""Hesaplanan dolap parçalarını ana listeye ekler.""" |
|
|
if not all([h, w, d, kalinlik]): |
|
|
raise gr.Error("Lütfen temel dolap ölçülerini ve malzeme kalınlığını girin!") |
|
|
new_parts = calculate_single_cabinet_parts(cabinet_number_state, h, w, d, kalinlik, raf_sayisi, kapak_var, kapak_sayisi, arkalik_var) |
|
|
updated_parts = all_parts_state + new_parts |
|
|
df = pd.DataFrame(updated_parts) |
|
|
return updated_parts, cabinet_number_state + 1, df, f"Başarılı! {cabinet_number_state}. Dolap listeye eklendi." |
|
|
|
|
|
def clear_list(): |
|
|
"""Tüm listeyi temizler.""" |
|
|
return [], 1, pd.DataFrame(), "Liste temizlendi. Yeni dolap ekleyebilirsiniz." |
|
|
|
|
|
def create_layout_plot(packer, plaka_uzunluk, plaka_genislik): |
|
|
"""Matplotlib kullanarak plaka yerleşimini çizer.""" |
|
|
images = [] |
|
|
plaka_alani = plaka_uzunluk * plaka_genislik |
|
|
|
|
|
for i, b in enumerate(packer): |
|
|
fig, ax = plt.subplots(1, figsize=(10, 7)) |
|
|
ax.set_xlim(0, plaka_uzunluk) |
|
|
ax.set_ylim(0, plaka_genislik) |
|
|
|
|
|
|
|
|
ax.add_patch(patches.Rectangle((0, 0), plaka_uzunluk, plaka_genislik, fill=False, edgecolor='black', lw=2)) |
|
|
|
|
|
toplam_kullanilan_alan = 0 |
|
|
for r in b: |
|
|
|
|
|
color = "#{:06x}".format(random.randint(0, 0xFFFFFF)) |
|
|
ax.add_patch(patches.Rectangle((r.x, r.y), r.width, r.height, facecolor=color, edgecolor='black', lw=1, alpha=0.7)) |
|
|
|
|
|
ax.text(r.x + r.width/2, r.y + r.height/2, f"{int(r.width)}x{int(r.height)}", ha='center', va='center', fontsize=8) |
|
|
toplam_kullanilan_alan += r.width * r.height |
|
|
|
|
|
kullanim_orani = (toplam_kullanilan_alan / plaka_alani) * 100 |
|
|
ax.set_title(f"Plaka {i+1} - Kullanım: {kullanim_orani:.2f}%") |
|
|
plt.gca().set_aspect('equal', adjustable='box') |
|
|
|
|
|
filepath = f"/tmp/plaka_{i+1}.png" |
|
|
plt.savefig(filepath) |
|
|
plt.close(fig) |
|
|
images.append(filepath) |
|
|
|
|
|
return images |
|
|
|
|
|
def run_optimization_and_visualize(all_parts, plaka_uzunluk, plaka_genislik): |
|
|
"""Parçaları plakalara yerleştirir ve görselleştirir.""" |
|
|
if not all_parts: |
|
|
raise gr.Error("Liste boş! Lütfen önce dolap ekleyin.") |
|
|
if not all([plaka_uzunluk, plaka_genislik]): |
|
|
raise gr.Error("Lütfen sunta plakası ölçülerini girin!") |
|
|
|
|
|
sunta_parcalari = [] |
|
|
for part in all_parts: |
|
|
if part['malzeme'] == 'Sunta': |
|
|
for _ in range(part['adet']): |
|
|
sunta_parcalari.append((part['uzunluk'], part['genislik'])) |
|
|
|
|
|
if not sunta_parcalari: |
|
|
return "Optimize edilecek 'Sunta' malzemesi bulunamadı.", None |
|
|
|
|
|
packer = newPacker(rotation=True) |
|
|
for r in sunta_parcalari: |
|
|
packer.add_rect(r[0], r[1]) |
|
|
|
|
|
packer.add_bin(plaka_uzunluk, plaka_genislik, count=100) |
|
|
packer.pack() |
|
|
|
|
|
plaka_sayisi = len(packer) |
|
|
optimization_result = f"**Optimizasyon Sonucu:**\nToplam **{plaka_sayisi}** adet {plaka_uzunluk}x{plaka_genislik}mm sunta plakasına ihtiyaç var." |
|
|
|
|
|
|
|
|
image_paths = create_layout_plot(packer, plaka_uzunluk, plaka_genislik) |
|
|
|
|
|
return optimization_result, image_paths |
|
|
|
|
|
|
|
|
|
|
|
with gr.Blocks(theme=gr.themes.Soft(), title="Dolap Kesim Hesaplayıcı") as demo: |
|
|
all_parts_state = gr.State([]) |
|
|
cabinet_number_state = gr.State(1) |
|
|
|
|
|
gr.Markdown("# Akıllı Dolap Kesim Hesaplayıcı ve Görselleştirici") |
|
|
gr.Markdown("Bu uygulama, dolap ölçülerinize göre kesim listesi oluşturur ve parçaların plaka üzerindeki yerleşimini görselleştirir.") |
|
|
|
|
|
with gr.Row(): |
|
|
with gr.Column(scale=1): |
|
|
gr.Markdown("### 1. Dolap Bilgilerini Girin") |
|
|
with gr.Accordion(f"Yeni Dolap Ekle (No: 1)", open=True) as accordion: |
|
|
with gr.Row(): |
|
|
h_input = gr.Number(label="Yükseklik (mm)", value=1800) |
|
|
w_input = gr.Number(label="Genişlik (mm)", value=800) |
|
|
d_input = gr.Number(label="Derinlik (mm)", value=500) |
|
|
kalinlik_input = gr.Number(label="Malzeme Kalınlığı (mm)", value=18) |
|
|
raf_input = gr.Slider(minimum=0, maximum=10, step=1, label="Raf Sayısı", value=3) |
|
|
with gr.Row(): |
|
|
kapak_var_input = gr.Checkbox(label="Kapak Olsun mu?", value=True) |
|
|
kapak_sayisi_input = gr.Radio([1, 2, 3, 4], label="Kapak Sayısı", value=2, interactive=True) |
|
|
arkalik_var_input = gr.Checkbox(label="Arkalık Olsun mu?", value=True) |
|
|
add_button = gr.Button("Hesapla ve Listeye Ekle", variant="primary") |
|
|
clear_button = gr.Button("Tüm Listeyi Temizle", variant="stop") |
|
|
status_text = gr.Textbox(label="Durum", interactive=False) |
|
|
|
|
|
with gr.Column(scale=2): |
|
|
gr.Markdown("### 2. Toplam Parça Kesim Listesi") |
|
|
parts_df_output = gr.DataFrame( |
|
|
headers=["dolap_no", "parca_adi", "adet", "uzunluk", "genislik", "malzeme"], |
|
|
interactive=False |
|
|
) |
|
|
|
|
|
gr.Markdown("---") |
|
|
gr.Markdown("### 3. Optimizasyon ve Görselleştirme") |
|
|
with gr.Row(): |
|
|
plaka_uzunluk_input = gr.Number(label="Plaka Uzunluğu (mm)", value=2800) |
|
|
plaka_genislik_input = gr.Number(label="Plaka Genişliği (mm)", value=2100) |
|
|
|
|
|
visualize_button = gr.Button("Optimizasyonu Çalıştır ve Görselleştir", variant="primary") |
|
|
optimization_output = gr.Markdown() |
|
|
layout_gallery = gr.Gallery(label="Plaka Yerleşim Planları", elem_id="gallery", columns=[2], object_fit="contain", height="auto") |
|
|
|
|
|
|
|
|
kapak_var_input.change(lambda x: gr.update(interactive=x), kapak_var_input, kapak_sayisi_input) |
|
|
add_button.click( |
|
|
fn=add_cabinet_to_list, |
|
|
inputs=[all_parts_state, cabinet_number_state, h_input, w_input, d_input, kalinlik_input, raf_input, kapak_var_input, kapak_sayisi_input, arkalik_var_input], |
|
|
outputs=[all_parts_state, cabinet_number_state, parts_df_output, status_text] |
|
|
).then(lambda cabinet_no: gr.update(label=f"Yeni Dolap Ekle (No: {cabinet_no})"), cabinet_number_state, accordion) |
|
|
clear_button.click(fn=clear_list, outputs=[all_parts_state, cabinet_number_state, parts_df_output, status_text]).then(lambda cabinet_no: gr.update(label=f"Yeni Dolap Ekle (No: {cabinet_no})"), cabinet_number_state, accordion) |
|
|
visualize_button.click( |
|
|
fn=run_optimization_and_visualize, |
|
|
inputs=[all_parts_state, plaka_uzunluk_input, plaka_genislik_input], |
|
|
outputs=[optimization_output, layout_gallery] |
|
|
) |
|
|
|
|
|
demo.launch() |
|
|
|