Python Forum
[split] How to ask Smart Questions (thread title expansion)
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[split] How to ask Smart Questions (thread title expansion)
#1
import tkinter as tk
from tkinter import ttk, messagebox
from reportlab.pdfgen import canvas

class GuillotineCuttingOptimizer:
    def __init__(self, stock_width, stock_length, stock_quantity, cut_sizes):
        self.stock_width = stock_width
        self.stock_length = stock_length
        self.stock_quantity = stock_quantity
        self.cut_sizes = cut_sizes
        self.sheets_needed = 0
        self.remaining_stock_area = 0
        self.cut_plan = []

    def optimize_cutting_plan(self):
        self.cut_sizes.sort(key=lambda x: x[0] * x[1], reverse=True)

        stock_area = self.stock_width * self.stock_length * self.stock_quantity
        remaining_stock_area = stock_area
        sheets_needed = 0
        cut_plan = []

        while self.cut_sizes:
            sheet_area = stock_area
            current_cut_plan = []

            while self.cut_sizes:
                cut_width, cut_length, cut_quantity = self.cut_sizes.pop(0)

                if cut_width <= self.stock_width and cut_length <= self.stock_length:
                    current_cut_plan.append((cut_width, cut_length, cut_quantity))
                    sheet_area -= cut_width * cut_length * cut_quantity

            if sheet_area < stock_area:
                sheets_needed += 1
                remaining_stock_area -= sheet_area
                cut_plan.extend(current_cut_plan)

        self.sheets_needed = sheets_needed
        self.remaining_stock_area = remaining_stock_area
        self.cut_plan = cut_plan

class GuillotineApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Guillotine Cutting Planner")

        # Variables
        self.stock_width_var = tk.DoubleVar()
        self.stock_length_var = tk.DoubleVar()
        self.stock_quantity_var = tk.IntVar()
        self.cut_width_var = tk.DoubleVar()
        self.cut_length_var = tk.DoubleVar()
        self.cut_quantity_var = tk.IntVar()
        self.cut_sizes = []

        # Create and place widgets
        self.create_widgets()

    def create_widgets(self):
        # Stock Sheet Entry
        stock_frame = ttk.LabelFrame(self.root, text="Stock Sheet")
        stock_frame.grid(row=0, column=0, padx=10, pady=10, sticky="ew")

        self.create_label_entry(stock_frame, "Width:", self.stock_width_var, 0)
        self.create_label_entry(stock_frame, "Length:", self.stock_length_var, 1)
        self.create_label_entry(stock_frame, "Quantity:", self.stock_quantity_var, 2)

        # Cut Sizes Entry
        cuts_frame = ttk.LabelFrame(self.root, text="Cut Sizes")
        cuts_frame.grid(row=1, column=0, padx=10, pady=10, sticky="ew")

        self.create_label_entry(cuts_frame, "Width:", self.cut_width_var, 0)
        self.create_label_entry(cuts_frame, "Length:", self.cut_length_var, 1)
        self.create_label_entry(cuts_frame, "Quantity:", self.cut_quantity_var, 2)

        ttk.Button(self.root, text="Optimize", command=self.optimize_and_display).grid(row=2, column=0, pady=20)
        ttk.Button(self.root, text="Export to PDF", command=self.export_to_pdf).grid(row=3, column=0, pady=10)

        # Canvas for Drawing
        self.canvas = tk.Canvas(self.root, bg="white", width=800, height=600)
        self.canvas.grid(row=0, column=1, rowspan=4, padx=10, pady=10, sticky="nsew")

        # Make canvas resizable
        self.root.grid_rowconfigure(0, weight=1)
        self.root.grid_columnconfigure(1, weight=1)

        # Bind canvas resize event
        self.canvas.bind("<Configure>", self.on_canvas_resize)

    def create_label_entry(self, frame, label_text, variable, row):
        ttk.Label(frame, text=label_text).grid(row=row, column=0, padx=5, pady=5, sticky="e")
        ttk.Entry(frame, textvariable=variable).grid(row=row, column=1, padx=5, pady=5, sticky="w")

    def on_canvas_resize(self, event):
        # Redraw the cut sizes when the canvas is resized
        self.display_cut_sizes(self.cut_sizes)

    def optimize_and_display(self):
        try:
            stock_width = float(self.stock_width_var.get())
            stock_length = float(self.stock_length_var.get())
            stock_quantity = int(self.stock_quantity_var.get())

            cut_width = float(self.cut_width_var.get())
            cut_length = float(self.cut_length_var.get())
            cut_quantity = int(self.cut_quantity_var.get())

            if cut_width > 0 and cut_length > 0 and cut_quantity > 0:
                self.cut_sizes.append((cut_width, cut_length, cut_quantity))
            else:
                messagebox.showerror("Error", "Please enter valid positive values for Cut Width, Length, and Quantity.")

            optimizer = GuillotineCuttingOptimizer(stock_width, stock_length, stock_quantity, self.cut_sizes)
            optimizer.optimize_cutting_plan()

            self.display_stock_size(stock_width, stock_length, stock_quantity)
            self.display_optimization_results(optimizer)
            self.display_cut_sizes(optimizer.cut_plan)
            messagebox.showinfo("Optimized Calculation",
                                f"Optimized Cutting Plan:\nTotal sheets needed: {optimizer.sheets_needed}\nRemaining stock area: {optimizer.remaining_stock_area:.2f} mm²")

        except ValueError:
            messagebox.showerror("Error", "Please enter valid numeric values.")

    def display_stock_size(self, stock_width, stock_length, stock_quantity):
        # Clear previous drawings on the canvas
        self.canvas.delete("stock_size")

        # Calculate total dimensions of stock sheet
        total_width = stock_width * stock_quantity
        total_length = stock_length

        # Draw the stock sheet rectangle
        self.canvas.create_rectangle(10, 10, total_width + 10, total_length + 10,
                                     outline="black", fill="lightgreen", tags="stock_size")

        # Display stock size dimensions
        self.canvas.create_text(total_width / 2 + 10, total_length / 2 + 10,
                                text=f"Stock Size\n{stock_width} mm x {stock_length} mm x {stock_quantity}",
                                fill="black", anchor="center", tags="stock_size")

    def display_cut_sizes(self, cut_plan):
        # Clear previous drawings on the canvas
        self.canvas.delete("cut_sizes")

        # Calculate total dimensions of stock sheet and cut sizes
        total_width = max(self.stock_width_var.get(), *map(lambda x: x[0], cut_plan))
        total_length = max(self.stock_length_var.get(), *map(lambda x: x[1], cut_plan))

        # Calculate scale factor based on canvas size and total dimensions
        scale_factor = min(self.canvas.winfo_width() / total_width, self.canvas.winfo_height() / total_length)

        current_x = 10
        current_y = 10

        for cut_width, cut_length, cut_quantity in cut_plan:
            # Scale dimensions for better visibility
            scaled_width = cut_width * scale_factor
            scaled_length = cut_length * scale_factor

            # Draw the cut size rectangle
            for _ in range(cut_quantity):
                self.canvas.create_rectangle(current_x, current_y, current_x + scaled_width, current_y + scaled_length,
                                             outline="black", fill="lightblue", tags="cut_sizes")

                # Display cut size dimensions
                self.canvas.create_text(current_x + scaled_width / 2, current_y - 5,
                                        text=f"{cut_width} mm", fill="black", anchor="s", tags="cut_sizes")

                self.canvas.create_text(current_x - 5, current_y + scaled_length / 2,
                                        text=f"{cut_length} mm", fill="black", anchor="e", tags="cut_sizes")

                # Display cut size quantity
                self.canvas.create_text(current_x + scaled_width / 2, current_y + scaled_length + 5,
                                        text=f"Qty: {cut_quantity}", fill="black", anchor="n", tags="cut_sizes")

                current_y += scaled_length  # Remove the gap between cut sizes

        # Adjust the canvas scroll region based on the actual drawing dimensions
        self.canvas.config(scrollregion=self.canvas.bbox("all"))

    def display_optimization_results(self, optimizer):
        # Display optimization results on the canvas
        result_text = f"Optimization Results:\nTotal sheets needed: {optimizer.sheets_needed}\nRemaining stock area: {optimizer.remaining_stock_area:.2f} mm²"
        self.canvas.create_text(400, 500, text=result_text, fill="black", anchor="center", tags="optimization_results")

    def export_to_pdf(self):
        try:
            pdf_filename = "cutting_plan.pdf"
            pdf = canvas.Canvas(pdf_filename, pagesize=(800, 600))
            self.display_stock_size_to_pdf(pdf, float(self.stock_width_var.get()), float(self.stock_length_var.get()), int(self.stock_quantity_var.get()))
            self.display_cut_sizes_to_pdf(pdf, self.cut_sizes)
            self.display_optimization_results_to_pdf(pdf)  # Pass optimizer object here
            pdf.save()
            messagebox.showinfo("PDF Export", f"The cutting plan has been exported to {pdf_filename}")

        except Exception as e:
            messagebox.showerror("Error", f"An error occurred while exporting to PDF: {str(e)}")

    def display_stock_size_to_pdf(self, pdf, stock_width, stock_length, stock_quantity):
        # Calculate total dimensions of stock sheet
        total_width = stock_width * stock_quantity
        total_length = stock_length

        # Draw the stock sheet rectangle on PDF
        pdf.rect(10, 10, total_width + 10, total_length + 10, fill=1)

        # Display stock size dimensions on PDF
        pdf.drawCentredString(total_width / 2 + 10, total_length / 2 + 10,
                              f"Stock Size\n{stock_width} mm x {stock_length} mm x {stock_quantity}")

    def display_cut_sizes_to_pdf(self, pdf, cut_plan):
        current_x = 10
        current_y = 10

        for cut_width, cut_length, cut_quantity in cut_plan:
            # Scale dimensions for better visibility
            scale_factor = 10
            scaled_width = cut_width * scale_factor
            scaled_length = cut_length * scale_factor

            # Draw the cut size rectangle on PDF
            for _ in range(cut_quantity):
                pdf.rect(current_x, current_y, scaled_width, scaled_length, fill=1)

                # Display cut size dimensions on PDF
                pdf.drawCentredString(current_x + scaled_width / 2, current_y - 5, f"{cut_width} mm")
                pdf.drawRightString(current_x - 5, current_y + scaled_length / 2, f"{cut_length} mm")

                # Display cut size quantity on PDF
                pdf.drawCentredString(current_x + scaled_width / 2, current_y + scaled_length + 5, f"Qty: {cut_quantity}")

                current_y += scaled_length + 10

    def display_optimization_results_to_pdf(self, pdf):
        # Display optimization results on PDF
        result_text = f"Optimization Results:\nTotal sheets needed: {self.sheets_needed}\nRemaining stock area: {self.remaining_stock_area:.2f} mm²"
        pdf.drawCentredString(400, 500, result_text)

if __name__ == "__main__":
    root = tk.Tk()
    app = GuillotineApp(root)
    root.mainloop()
I need help to finding best 2d cutting optimization cutting plan on cutting layout.
It is not working to display well calculated and quality results for the same.
buran write Feb-17-2024, 12:24 PM:
Please post all code, output and errors (it it's entirety) between their respective tags. Refer to BBCode help topic on how to post. Use the "Preview Post" button to make sure the code is presented as you expect before hitting the "Post Reply/Thread" button.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  While loop - series expansion StillAnotherDave 3 4,851 Dec-19-2019, 01:50 AM
Last Post: scidam

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020