# functions.py import yaml from PIL import Image, ImageTk from tkinter import ttk, filedialog, messagebox import tkinter as tk import os import trimesh from mpl_toolkits.mplot3d.art3d import Poly3DCollection import numpy as np # Function to load object definitions from YAML # Load a specific parameter set from a YAML file for a group def load_yaml(group_name, param_name, folder_parsets): yml_file = os.path.join(folder_parsets, f"{group_name}.yml") if os.path.exists(yml_file): with open(yml_file, 'r') as file: data = yaml.safe_load(file) return data.get(param_name, {}) return {} # Save a parameter set to a YAML file for a group def save_yaml(group_name, param_name, param_data, folder_parsets): yml_file = os.path.join(folder_parsets, f"{group_name}.yml") all_data = load_existing_data(yml_file) all_data[param_name] = param_data os.makedirs(folder_parsets, exist_ok=True) with open(yml_file, 'w') as file: yaml.dump(all_data, file) # messagebox.showinfo("Success", f"Parameter set '{param_name}' saved to {group_name}.yml") def delete_yaml(group_name, param_name, folder_parsets): yml_file = os.path.join(folder_parsets, f"{group_name}.yml") if os.path.exists(yml_file): with open(yml_file, 'r') as file: data = yaml.safe_load(file) if param_name in data: del data[param_name] # Remove the specific parameter set with open(yml_file, 'w') as file: yaml.safe_dump(data, file) # Load existing data from a YAML file def load_existing_data(yml_file): if os.path.exists(yml_file): with open(yml_file, 'r') as file: return yaml.safe_load(file) or {} return {} # Fetch existing parameter sets from a group-specific YAML file def get_existing_parameters(group_name, folder_parsets): yml_file = os.path.join(folder_parsets, f"{group_name}.yml") data = load_existing_data(yml_file) return list(data.keys()) # Load the image for the UI def load_image(image_file, sizelimit=200): image = Image.open(image_file) w, h = image.size if w > h: new_w, new_h = sizelimit, int(sizelimit * h / w) else: new_h, new_w = sizelimit, int(sizelimit * w / h) return ImageTk.PhotoImage(image.resize((new_w, new_h), Image.Resampling.LANCZOS)) # Create a new parameter set and save it def create_new_parameter_set(group_name, param_name, input_vars, folder_parsets): if not param_name: messagebox.showerror("Error", "Parameter set name cannot be empty.") return param_data = {key: var.get() for key, var in input_vars[group_name].items()} save_yaml(group_name, param_name, param_data, folder_parsets) # Update the dropdown after saving new parameter set def update_dropdown(param_values, param_name, param_dropdown): param_values.insert(-1, param_name) param_dropdown['values'] = param_values # Create a popup window for creating a new parameter set def create_new_param_popup(root, group_name, input_vars, param_values, param_dropdown, folder_parsets): new_window = tk.Toplevel(root) new_window.title(f"Create New Parameter Set for {group_name}") tk.Label(new_window, text="Parameter Set Name:").pack(pady=10) param_name_entry = tk.Entry(new_window) param_name_entry.pack(pady=10) def create_param_set(): param_name = param_name_entry.get() create_new_parameter_set(group_name, param_name, input_vars, folder_parsets) update_dropdown(param_values, param_name, param_dropdown) new_window.destroy() tk.Button(new_window, text="Create", command=create_param_set).pack(pady=10) # ------------------------------------------------------------------------------------------------------- def plot_clamping(ax, x, y, z, dx, dy1, dy2, dz1, dz2, color='blue', alpha=0.5, linewidth=1, inverty=False): """Efficiently plots an L-shaped merged cube structure and draws only axis-aligned edges.""" # Compute Y offsets dyy1, dyy2 = (y - dy1 / 2, y - (dy1 - dy2) / 2) if not inverty else (y + dy1 / 2, y + (dy1 - dy2) / 2) # Create and position both cubes cubes = [ trimesh.creation.box(extents=[dx, dy1, dz1]).apply_translation([x + dx / 2, dyy1, z + dz1 / 2]), trimesh.creation.box(extents=[dx, dy1 + dy2, dz2]).apply_translation([x + dx / 2, dyy2, z - dz2 / 2]) ] try: # Perform boolean union on merged cubes merged = trimesh.boolean.union(cubes) # Extract vertices and edges vertices = np.array(merged.vertices) edges = merged.edges_unique # Add merged faces without visible edges ax.add_collection3d(Poly3DCollection( vertices[merged.faces], facecolors=color, alpha=alpha, edgecolors=None, linewidth=0 )) # Draw only axis-aligned edges for edge in edges: v1, v2 = vertices[edge] if np.isclose(v1, v2, atol=1e-6).sum() == 2: # Only one coordinate changes ax.plot(*zip(*[v1, v2]), color='black', linewidth=linewidth) except Exception as e: print(f"Trimesh union failed: {e}") def VarDescription(Name): #Workpiece if Name == "wp": return "Rohmaterial" elif Name == "WPR_X": return "Rohmass X" elif Name == "WPR_Y": return "Rohmass Y" elif Name == "WPR_Z": return "Rohmass Z" elif Name == "WPF_X": return "Griffversatz fertig X" elif Name == "WPF_Y": return "Griffversatz fertig Y" elif Name == "WPF_Z": return "Griffversatz fertig Z" elif Name == "WP_CLP_OFFSET_X": return "Einlegeposition X" elif Name == "WP_CLP_OFFSET_Y": return "Einlegeposition Y" elif Name == "WP_GRP_OFFSET_Z": return "Greiftiefe" #CLP elif Name == "clp": return "Schraubstock Backen" elif Name == "CLP_BACKENWEITE": return "Backenbreite" elif Name == "CLP_BACKENHOHE": return "Backenhöhe" elif Name == "CLP_SPANNHOHE": return "Backen Spanntiefe" elif Name == "CLP_AUFLAGETIEFE": return "Auflagebreite" elif Name == "MESSPOS_X": return "Messposition X" elif Name == "MESSPOS_Y": return "Messposition Y" elif Name == "MESSPOS_Z": return "Abstand Teil-Backe" elif Name == "MESSPOS_TOL": return "Toleranz Spannen" #PROBE elif Name == "probe": return "Messen" elif Name == "PRB_BOD_RE_X": return "Boden Rechts X" elif Name == "PRB_BOD_RE_Y": return "Boden Rechts Y" elif Name == "PRB_BOD_LI_X": return "Boden Links X" elif Name == "PRB_BOD_LI_Y": return "Boden Links Y" elif Name == "PRB_SEI_HI_X": return "Hinten X" elif Name == "PRB_SEI_HI_Z": return "Hinten Z" elif Name == "PRB_SEI_VO_X": return "Vorne X" elif Name == "PRB_SEI_VO_Z": return "Vorne Z" elif Name == "PRB_VERS_X_Y": return "X Mess Pos Y" elif Name == "PRB_VERS_X_Z": return "X Mess Pos Z" elif Name == "PRB_VERS_X_TOL": return "Pos Toleranz X" #INL elif Name == "inlay": return "Inlay" elif Name == "INL_X_NUM": return "Felder in X" elif Name == "INL_X_LENGTH": return "Feldlänge X" elif Name == "INL_X_OFFSET": return "Abstand Felder X" elif Name == "INL_Y_NUM": return "Felder in Y" elif Name == "INL_Y_LENGTH": return "Feldlänge in Y" elif Name == "INL_Y_OFFSET": return "Abstand Felder Y" elif Name == "PRT_NUM": return "Teile pro Feld" elif Name != "": return Name