diff --git a/MAIN.py b/MAIN.py index 5cb1103..1c0a954 100644 --- a/MAIN.py +++ b/MAIN.py @@ -1,5 +1,4 @@ # main.py - from functions import * from funct_inlay import * from funct_wp import * @@ -34,7 +33,7 @@ def setup_group(frame, group_name, data, input_vars, selected_params, group_widg param_var = selected_params[group_name] # Bind the dropdown to the corresponding selected_param entry param_dropdown = ttk.Combobox(frame, textvariable=param_var, values=param_values) group_widgets[group_name] = {"param_dropdown": param_dropdown} # Save for later reference - source_path = f"{folder_pictures}/{data['general']['initpic_name']}" + source_path = f"{folder_pictures}/{data['general']['notavailablepic_name']}" # Handle missing picture case if not os.path.exists(picture_path): @@ -273,7 +272,7 @@ def setup_evaluation(root, folder_pictures, data, folder_output, input_vars, sel frame.grid(row=2, column=0, columnspan=5, padx=10, pady=10, sticky="nsew") # Load and display the specific initial picture - picture_path = f"{folder_pictures}/{data['general']['initpic_name']}" + picture_path = f"{folder_pictures}/{data['general']['generatorpic_name']}" group_image_tk = load_image(picture_path, 200) # Assuming a function load_image exists and works as expected image_label = ttk.Label(frame, image=group_image_tk) image_label.image = group_image_tk # Keep a reference to avoid garbage collection @@ -290,7 +289,7 @@ def setup_evaluation(root, folder_pictures, data, folder_output, input_vars, sel # Place buttons in the vertical frame for operations button_frame = ttk.Frame(frame) button_frame.grid(row=0, column=1, padx=10, pady=10, sticky="n") - button1 = ttk.Button(button_frame, text="GENERATE DMUAUT_CFG.SPF FILE", width=45, command=btn_gen) + button1 = ttk.Button(button_frame, text="GEN CFG_DMUAUT.SPF FILE", width=45, command=btn_gen) button1.grid(row=0, column=0, padx=10, pady=5) button2 = ttk.Button(button_frame, text="GEN CFG_INLAY.SPF FILE", width=45, command=btn_gen_custom1) button2.grid(row=1, column=0, padx=5, pady=5) diff --git a/cfg_parsets/clp.yml b/cfg_parsets/clp.yml deleted file mode 100644 index 7d9d38f..0000000 --- a/cfg_parsets/clp.yml +++ /dev/null @@ -1,4 +0,0 @@ -clp1: - clp_offset: '0' -clp2: - clp_offset: '0' diff --git a/cfg_parsets/grp.yml b/cfg_parsets/grp.yml deleted file mode 100644 index e1bd8b1..0000000 --- a/cfg_parsets/grp.yml +++ /dev/null @@ -1,28 +0,0 @@ -grp1: - h_offset: '30' - h_step: '10' - hub: '50' - steps_num: '5' - w_offset: '40' - w_step: '45' -grp2: - h_offset: '30' - h_step: '5' - hub: '10' - steps_num: '6' - w_offset: '20' - w_step: '10' -grp3: - h_offset: '10' - h_step: '25' - hub: '10' - steps_num: '5' - w_offset: '25' - w_step: '45' -newset: - h_offset: '10' - h_step: '25' - hub: '10' - steps_num: '5' - w_offset: '25' - w_step: '45' diff --git a/cfg_parsets/inlay.yml b/cfg_parsets/inlay.yml index 2f37f19..b359223 100644 --- a/cfg_parsets/inlay.yml +++ b/cfg_parsets/inlay.yml @@ -5,6 +5,6 @@ INL_Y_OFFSET: '50' inlay1: INL_X_NUM: '10' - INL_X_OFFSET: '50' - INL_Y_NUM: '9' - INL_Y_OFFSET: '50' + INL_X_OFFSET: '10' + INL_Y_NUM: '10' + INL_Y_OFFSET: '10' diff --git a/cfg_parsets/wp.yml b/cfg_parsets/wp.yml index 323ddb4..3d0df58 100644 --- a/cfg_parsets/wp.yml +++ b/cfg_parsets/wp.yml @@ -1,9 +1,9 @@ wp1: - WPF_X: '20' + WPF_X: '15' WPF_Y: '20' - WPF_Z: '20' + WPF_Z: '15' WPR_X: '20' WPR_Y: '20' - WPR_Z: '33' - WP_CLP_OFFSET_X: '4' + WPR_Z: '20' + WP_CLP_OFFSET_X: '5' WP_GRP_OFFSET_Z: '5' diff --git a/cfg_picture/Thumbs.db b/cfg_picture/Thumbs.db deleted file mode 100644 index 1446612..0000000 Binary files a/cfg_picture/Thumbs.db and /dev/null differ diff --git a/cfg_picture/cat_wondering.png b/cfg_picture/cat_wondering.png new file mode 100644 index 0000000..f4cf402 Binary files /dev/null and b/cfg_picture/cat_wondering.png differ diff --git a/cfg_picture/dog_progr.png b/cfg_picture/dog_progr.png new file mode 100644 index 0000000..b67dbbc Binary files /dev/null and b/cfg_picture/dog_progr.png differ diff --git a/cfg_picture/img_clp.png b/cfg_picture/img_clp.png index 2882853..9075745 100644 Binary files a/cfg_picture/img_clp.png and b/cfg_picture/img_clp.png differ diff --git a/cfg_picture/img_inlay.png b/cfg_picture/img_inlay.png index a2c8c97..f5120d1 100644 Binary files a/cfg_picture/img_inlay.png and b/cfg_picture/img_inlay.png differ diff --git a/cfg_picture/img_wp.png b/cfg_picture/img_wp.png new file mode 100644 index 0000000..b4f5767 Binary files /dev/null and b/cfg_picture/img_wp.png differ diff --git a/cfg_picture/puppy - Kopie.png b/cfg_picture/puppy - Kopie.png deleted file mode 100644 index bf61fb7..0000000 Binary files a/cfg_picture/puppy - Kopie.png and /dev/null differ diff --git a/cfg_picture/puppy.png b/cfg_picture/puppy.png deleted file mode 100644 index bf61fb7..0000000 Binary files a/cfg_picture/puppy.png and /dev/null differ diff --git a/def.yml b/def.yml index 696a017..938637f 100644 --- a/def.yml +++ b/def.yml @@ -1,6 +1,7 @@ general: yolovar: int - initpic_name: puppy.png + notavailablepic_name: cat_wondering.png + generatorpic_name: dog_progr.png groups: inlay: @@ -25,8 +26,13 @@ groups: picture_name: img_wp.png clp: parameter: - clp_offset: double - - + CLP_BACKENWEITE: double + CLP_BACKENHOHE: double + CLP_SPANNHOHE: double + CLP_AUFLAGETIEFE: double + MESSPOS_X: double + MESSPOS_Y: double + MESSPOS_Z: double + MESSPOS_TOL: double cfg: picture_name: img_clp.png diff --git a/funct_clp.py b/funct_clp.py index 5110cd9..86588fa 100644 --- a/funct_clp.py +++ b/funct_clp.py @@ -1,130 +1,116 @@ import matplotlib.pyplot as plt -from mpl_toolkits.mplot3d.art3d import Poly3DCollection -import numpy as np +from functions import * def generate_picture_clp(all_group_vars, picture_path, DEBUG=False): - try: - # Get WPR_X, WPR_Y, and WPR_Z values - vars = all_group_vars['wp'] - x_wpraw = float(vars['WPR_X']) - y_wpraw = float(vars['WPR_Y']) - z_wpraw = float(vars['WPR_Z']) - x_cube = x_wpraw*2 - y_cube = y_wpraw*2 - z_cube = z_wpraw - clp_offset = float(all_group_vars['clp']['clp_offset']) + vars = all_group_vars['clp'] + CLP_BACKENWEITE, CLP_BACKENHOHE, CLP_SPANNHOHE, CLP_AUFLAGETIEFE = (float(vars[k]) for k in + ['CLP_BACKENWEITE', 'CLP_BACKENHOHE', + 'CLP_SPANNHOHE', 'CLP_AUFLAGETIEFE']) - # ERROR HANDLING - if x_cube <= 0 or y_cube <= 0 or z_cube <= 0: - raise ValueError("WPR_X, WPR_Y, and WPR_Z must be positive values.") + WPR_X = CLP_BACKENWEITE/2 + WPR_Y = CLP_BACKENWEITE/2 + WPR_Z = CLP_SPANNHOHE * 5 - # Define the vertices of the cube based on wpraw dimensions - vertices = (np.array([[0, 0, 0], [x_cube, 0, 0], [x_cube, y_cube, 0], [0, y_cube, 0], - [0, 0, z_cube], [x_cube, 0, z_cube], [x_cube, y_cube, z_cube], [0, y_cube, z_cube]]) - + np.array([0, -clp_offset, 0])) + if min(WPR_X, WPR_Y, WPR_Z) <= 0: + raise ValueError("Dimensions must be positive.") - # Define the 6 faces of the cube - faces = [[vertices[j] for j in [0, 1, 2, 3]], # Bottom face - [vertices[j] for j in [4, 5, 6, 7]], # Top face - [vertices[j] for j in [0, 3, 7, 4]], # Left face - [vertices[j] for j in [1, 2, 6, 5]], # Right face - [vertices[j] for j in [0, 1, 5, 4]], # Front face - [vertices[j] for j in [2, 3, 7, 6]]] # Back face + fig, ax = plt.subplots(subplot_kw={'projection': '3d'}) - # Plot the cube in 3D - fig = plt.figure() - ax = fig.add_subplot(111, projection='3d') + # Define raw workpiece dimensions + x_cube, y_cube, z_cube = 2 * WPR_X, 2 * WPR_Y, WPR_Z + vertices_raw = np.array([[0, 0, 0], [x_cube, 0, 0], [x_cube, y_cube, 0], [0, y_cube, 0], + [0, 0, WPR_Z], [x_cube, 0, WPR_Z], [x_cube, y_cube, WPR_Z], [0, y_cube, WPR_Z]]) + faces_raw = [vertices_raw[[0, 1, 2, 3]], vertices_raw[[4, 5, 6, 7]], vertices_raw[[0, 3, 7, 4]], + vertices_raw[[1, 2, 6, 5]], vertices_raw[[0, 1, 5, 4]], vertices_raw[[2, 3, 7, 6]]] - # Plot the cube with the specified faces - ax.add_collection3d(Poly3DCollection(faces, facecolors='k', linewidths=1, edgecolors='k', alpha=.15)) + # Set axis properties + ax.set_box_aspect([x_cube, y_cube, z_cube]) + ax.set(xticks=[], yticks=[], zticks=[]) - # Set the aspect ratio for each axis - ax.set_box_aspect([x_cube, y_cube, z_cube]) + # Draw WP coordinate system + axis_len = max(x_cube, y_cube, z_cube) * 0.2 + colors = ['r', 'g', 'b'] + origin_x = 0 + origin_y = 0 + origin_z = 0 + for i, vec in enumerate(np.eye(3)): + ax.quiver(origin_x, origin_y, origin_z, *(axis_len * vec), color=colors[i], linewidth=3) + ax.text(origin_x, origin_y, origin_z - axis_len * 0.3, 'WP', color='black', fontsize=9, weight='bold', ha='center', + va='top') - # Hide the axis ticks and labels - ax.set_xticks([]) # Hide X axis ticks - ax.set_yticks([]) # Hide Y axis ticks - ax.set_zticks([]) # Hide Z axis ticks + # Draw WP + ax.add_collection3d(Poly3DCollection(faces_raw, facecolors='k', linewidths=1, edgecolors='k', alpha=.15)) - # Add a ball (sphere) at the center of the cube - ball_radius = min(x_wpraw, y_wpraw, z_wpraw) * 0.1 # Size relative to cube dimensions + # Draw CLP coordinate system + axis_len = max(x_cube, y_cube, z_cube) * 0.15 + colors = ['r', 'g', 'b'] + origin_x = WPR_X + origin_y = WPR_Y + origin_z = 0 + for i, vec in enumerate(np.eye(3)): + ax.quiver(origin_x, origin_y, origin_z, *(axis_len * vec), color=colors[i], linewidth=3) + ax.text(origin_x, origin_y, origin_z - axis_len * 0.3, 'CLP', color='blue', fontsize=9, weight='bold', ha='center', + va='top') - u = np.linspace(0, 2 * np.pi, 20) - v = np.linspace(0, np.pi, 20) - x_sphere = x_wpraw + ball_radius * np.outer(np.cos(u), np.sin(v)) - y_sphere = y_wpraw - clp_offset + ball_radius * np.outer(np.sin(u), np.sin(v)) - z_sphere = z_wpraw + ball_radius * np.outer(np.ones(np.size(u)), np.cos(v)) - ax.plot_surface(x_sphere, y_sphere, z_sphere, color='red', alpha=1) + # Define clamping block dimensions + clp_deep = y_cube * 0.3 + base_x = WPR_X - CLP_BACKENWEITE / 2 + alpha = 0.35 + color = 'blue' + linewidth = 1 - # Add the origin sparrow (a small 3D marker at the origin) - max_size = max(x_cube, y_cube, z_cube) * 0.2 # Scale the arrows relative to the smallest dimension - ax.quiver(0, -clp_offset, 0, max_size, 0, 0, color='red', linewidth=2, label='X-axis') # Red arrow for X-axis - ax.quiver(0, -clp_offset, 0, 0, max_size, 0, color='green', linewidth=2, label='Y-axis') # Green arrow for Y-axis - ax.quiver(0, -clp_offset, 0, 0, 0, max_size, color='blue', linewidth=2, label='Z-axis') # Blue arrow for Z-axis + # Draw clamping blocks + x = base_x + dx = CLP_BACKENWEITE + y = 0 + dy1 = clp_deep + dy2 = CLP_AUFLAGETIEFE + z = 0 + dz1 = CLP_SPANNHOHE + dz2 = CLP_BACKENHOHE + plot_clamping(ax, x, y, z, dx, dy1, dy2, dz1, dz2, color=color, + alpha=alpha, linewidth=linewidth) + y = y_cube + plot_clamping(ax, x, y, z, dx, dy1, dy2, dz1, dz2, color=color, + alpha=alpha, linewidth=linewidth, inverty=True) - # Add two black blocks (greifer fingers) on the Y-faces in the middle of the cube height - max_size2 = max(x_cube, y_cube, z_cube) * 0.4 # Scale the arrows relative to the smallest dimension - ax.bar3d(-max_size2, -(2.0-1)/2 * y_cube, -z_wpraw * 0.0, - max_size2, 2.0 * y_cube, z_wpraw * 0.2, - color='black', alpha=.10) - ax.bar3d(-max_size2, -(2.0-1)/2 * y_cube, -z_wpraw * 0.0, - max_size2+3, 2.0 * y_cube, -z_wpraw * 0.2, - color='black', alpha=.10) + # Draw text for geometry values + ax.text(0, 2*WPR_Y+clp_deep, CLP_SPANNHOHE/2, f'{CLP_SPANNHOHE}mm', color='blue', fontsize=9, weight='bold', ha='right', va='center') + ax.text(0, 2*WPR_Y+clp_deep, -CLP_BACKENHOHE/2, f'{CLP_BACKENHOHE}mm', color='blue', fontsize=9, weight='bold', ha='right', va='center') + ax.text(WPR_X, 2*WPR_Y+clp_deep, CLP_SPANNHOHE, f'{CLP_BACKENWEITE}mm', color='blue', fontsize=9, weight='bold', ha='right', va='center') + ax.text(WPR_X*2, 2*WPR_Y-CLP_AUFLAGETIEFE/2, 0, f'{CLP_AUFLAGETIEFE}mm', color='blue', fontsize=9, weight='bold', ha='left', va='bottom') - ax.bar3d(x_cube, -(2-1)/2 * y_cube, -z_wpraw * 0.0, - max_size2, 2.0 * y_cube, z_wpraw * 0.2, - color='black', alpha=.10) - ax.bar3d(x_cube-3, -(2-1)/2 * y_cube, -z_wpraw * 0.0, - max_size2+3, 2.0 * y_cube, -z_wpraw * 0.2, - color='black', alpha=.10) + # Set view properties + z_trans = WPR_Z + zoom_factor = 1.5 # Adjust this factor to zoom out more or less + ax.view_init(elev=30, azim=-160) + ax.set_xlim([-x_cube * zoom_factor * 0.1, x_cube * zoom_factor]) + ax.set_ylim([-y_cube * zoom_factor * 0.1, y_cube * zoom_factor]) + ax.set_zlim([-WPR_Z * zoom_factor * 0.1 - z_trans, WPR_Z * zoom_factor - z_trans]) + ax.set_aspect('auto') + ax.grid(False) # Remove grid lines + ax.set_xticks([]) + ax.set_yticks([]) + ax.set_zticks([]) + for axis in [ax.xaxis, ax.yaxis, ax.zaxis]: + axis.set_pane_color((1, 1, 1, 0)) # Hide background panes + axis.line.set_color((1, 1, 1, 0)) # Hide axis lines - # Add the origin sparrow (a small 3D marker at the origin) - max_size3 = max(x_cube, y_cube, z_cube) * 0.3 # Scale the arrows relative to the smallest dimension - ax.quiver(x_wpraw, y_wpraw, 0, 0, max_size3, 0, color='red', linewidth=3, label='X-axis') # Red arrow for X-axis - ax.quiver(x_wpraw, y_wpraw, 0, -max_size3, 0, 0, color='green', linewidth=3, label='Y-axis') # Green arrow for Y-axis - ax.quiver(x_wpraw, y_wpraw, 0, 0, 0, max_size3, color='blue', linewidth=3, label='Z-axis') # Blue arrow for Z-axis - - # Set viewing angle - ax.view_init(elev=30, azim=-150) # Set elevation to 24° and azimuth to -151° - # ax.view_init(elev=90, azim=180) # Set elevation to 24° and azimuth to -151° - - # Set limits for the axes - # ax.set_xlim([0, x_cube]) - # ax.set_ylim([0, y_cube]) - # ax.set_zlim([0, z_cube]) - - # Set equal aspect ratio to make grid cells look square - ax.set_aspect('equal') - - if not DEBUG: - # Save the figure to the specified picture path - fig.savefig(picture_path, bbox_inches='tight', pad_inches=0.1, dpi=300, transparent=True) - else: - plt.show() - - # Close the figure to free memory - plt.close() - - except ValueError as ve: - # Handle value error (e.g., invalid input) - print(f"Invalid Input: Error: {ve}") - - except Exception as e: - # Catch any other exceptions and show a generic error message - print(f"An error occurred while generating the 3D cube: {e}") + # Save or display the plot + if not DEBUG: + fig.savefig(picture_path, bbox_inches='tight', dpi=300, transparent=True) + else: + plt.show() + plt.close() # Example use-case if __name__ == "__main__": all_group_vars = { - 'wp_raw': { - 'WPR_X': '10', # Example values for testing - 'WPR_Y': '15', - 'WPR_Z': '20' - }, - 'clp': { - 'clp_offset': '4' - } + 'CLP_BACKENWEITE': 25, + 'CLP_BACKENHOHE': 20, + 'CLP_SPANNHOHE': 3, + 'CLP_AUFLAGETIEFE': 3 } - generate_picture_clp(all_group_vars, 'output_image.png', DEBUG=True) + generate_picture_clp({'clp': all_group_vars}, "cfg_picture/TEST_wpraw.jpg", DEBUG=True) diff --git a/funct_gen.py b/funct_gen.py index ef085d0..a3d3777 100644 --- a/funct_gen.py +++ b/funct_gen.py @@ -7,7 +7,8 @@ import paramiko import yaml import shutil -# Function to generate the DMUAUT_CFG.SPF configuration file and save selected parameter sets + +# Function to generate the CFG_DMUAUT.SPF configuration file and save selected parameter sets def generate_config_spf(folder_output, input_vars, selected_params): # Get the current timestamp for folder name (format: YYMMDD_HHmmSS) timestamp = time.strftime("%y%m%d_%H%M%S") @@ -18,7 +19,7 @@ def generate_config_spf(folder_output, input_vars, selected_params): os.makedirs(folder_path) # Define the file path for the SPF configuration file - spf_file_path = os.path.join(folder_path, "DMUAUT_CFG.SPF") + spf_file_path = os.path.join(folder_path, "CFG_DMUAUT.SPF") # Generate the SPF file content with open(spf_file_path, "w") as spf_file: @@ -45,14 +46,13 @@ def generate_config_spf(folder_output, input_vars, selected_params): print(f"Configuration files saved in {folder_path}") - + os.startfile(folder_path) def generate_config_spf_custom1(folder_output, input_vars, selected_params, filetransfer=False): filename = "CFG_INL.SPF" filename2 = "_N_CFG_INL_SPF" - # Get the current timestamp for folder name (format: YYMMDD_HHmmSS) timestamp = time.strftime("%y%m%d_%H%M%S") folder_path = os.path.join(folder_output, f"{timestamp}") @@ -105,7 +105,7 @@ def generate_config_spf_custom1(folder_output, input_vars, selected_params, file spf_file_path2 = os.path.join(folder_path, filename2) shutil.copyfile(spf_file_path, spf_file_path2) - #try: + # try: # Transfer to Sinumerik url2 = "192.168.214.1" ssh_username = "manufact" @@ -114,7 +114,7 @@ def generate_config_spf_custom1(folder_output, input_vars, selected_params, file ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - ssh.connect(url2,username=ssh_username,password=ssh_password) + ssh.connect(url2, username=ssh_username, password=ssh_password) sftp = ssh.open_sftp() sftp.chdir(upload_folder_nc) if filename2 in sftp.listdir(): @@ -126,8 +126,7 @@ def generate_config_spf_custom1(folder_output, input_vars, selected_params, file os.remove(spf_file_path2) print(f"------->>>> FILE TRANSFERED TO SINUMERIK ------->>>> ") - #except Exception as e: + # except Exception as e: # print(f"ERROR IN FILETRANSFER {e}") else: os.startfile(folder_path) - diff --git a/funct_wp.py b/funct_wp.py index b93d8a0..0dee5d2 100644 --- a/funct_wp.py +++ b/funct_wp.py @@ -1,33 +1,31 @@ import matplotlib.pyplot as plt -from mpl_toolkits.mplot3d.art3d import Poly3DCollection -import numpy as np -import trimesh +from functions import * def generate_picture_wp(all_group_vars, picture_path, DEBUG=False): - # try: vars = all_group_vars['wp'] WPR_X, WPR_Y, WPR_Z, WPF_X, WPF_Y, WPF_Z, WP_CLP_OFFSET_X, WP_GRP_OFFSET_Z = (float(vars[k]) for k in - ['WPR_X', 'WPR_Y', 'WPR_Z', 'WPF_X', 'WPF_Y', 'WPF_Z', 'WP_CLP_OFFSET_X', 'WP_GRP_OFFSET_Z']) + ['WPR_X', 'WPR_Y', 'WPR_Z', 'WPF_X', + 'WPF_Y', 'WPF_Z', 'WP_CLP_OFFSET_X', + 'WP_GRP_OFFSET_Z']) if min(WPR_X, WPR_Y, WPR_Z, WPF_X, WPF_Y, WPF_Z) <= 0: raise ValueError("Dimensions must be positive.") - fig, ax = plt.subplots(subplot_kw={'projection': '3d'}) - # -------------------- wpraw ------------------------------------------------------------------------------------- + # Define raw workpiece dimensions x_cube, y_cube, z_cube = 2 * WPR_X, 2 * WPR_Y, WPR_Z vertices_raw = np.array([[0, 0, 0], [x_cube, 0, 0], [x_cube, y_cube, 0], [0, y_cube, 0], - [0, 0, WPR_Z], [x_cube, 0, WPR_Z], [x_cube, y_cube, WPR_Z], [0, y_cube, WPR_Z]]) + [0, 0, WPR_Z], [x_cube, 0, WPR_Z], [x_cube, y_cube, WPR_Z], [0, y_cube, WPR_Z]]) faces_raw = [vertices_raw[[0, 1, 2, 3]], vertices_raw[[4, 5, 6, 7]], vertices_raw[[0, 3, 7, 4]], - vertices_raw[[1, 2, 6, 5]], vertices_raw[[0, 1, 5, 4]], vertices_raw[[2, 3, 7, 6]]] + vertices_raw[[1, 2, 6, 5]], vertices_raw[[0, 1, 5, 4]], vertices_raw[[2, 3, 7, 6]]] - # Achsen-Einstellungen zusammenfassen + # Set axis properties ax.set_box_aspect([x_cube, y_cube, z_cube]) ax.set(xticks=[], yticks=[], zticks=[]) - # KOS WP zeichnen + # Draw WP coordinate system axis_len = max(x_cube, y_cube, z_cube) * 0.2 colors = ['r', 'g', 'b'] origin_x = 0 @@ -35,13 +33,13 @@ def generate_picture_wp(all_group_vars, picture_path, DEBUG=False): origin_z = 0 for i, vec in enumerate(np.eye(3)): ax.quiver(origin_x, origin_y, origin_z, *(axis_len * vec), color=colors[i], linewidth=3) - ax.text(origin_x, origin_y, origin_z-axis_len*0.3, 'WP', color='black', fontsize=9, weight='bold') + ax.text(origin_x, origin_y, origin_z - axis_len * 0.3, 'WP', color='black', fontsize=9, weight='bold', ha='center', + va='top') - - # WP + # Draw WP ax.add_collection3d(Poly3DCollection(faces_raw, facecolors='k', linewidths=1, edgecolors='k', alpha=.15)) - # GRIFFPUNKT + # Draw gripping point u, v = np.mgrid[0:2 * np.pi:20j, 0:np.pi:20j] ball_radius = min(WPR_X, WPR_Y, WPR_Z) * 0.1 ax.plot_surface( @@ -51,7 +49,7 @@ def generate_picture_wp(all_group_vars, picture_path, DEBUG=False): color='r' ) - # GREIFER + # Draw gripper gripper_thickness = max(x_cube, y_cube, z_cube) * 0.1 gripper_wide = WPR_X * 0.4 GRP_ALPHA = .40 @@ -66,10 +64,10 @@ def generate_picture_wp(all_group_vars, picture_path, DEBUG=False): color='r', alpha=GRP_ALPHA, edgecolor='k', linewidth=0.5 ) - # -------------------- wpfin--------------------------------------------------------------------------------- + # Define finished workpiece dimensions x_cube2, y_cube2, z_cube2 = 2 * WPF_X, 2 * WPF_Y, WPF_Z - # GRIFFPUNKT + # Draw gripping point for finished workpiece u, v = np.mgrid[0:2 * np.pi:20j, 0:np.pi:20j] ball_radius = min(WPF_X, WPF_Y, WPF_Z) * 0.08 ax.plot_surface( @@ -79,16 +77,14 @@ def generate_picture_wp(all_group_vars, picture_path, DEBUG=False): color='g' ) - - # GREIFER + # Draw gripper for finished workpiece gripper_thickness2 = max(x_cube, y_cube, z_cube) * 0.05 gripper_wide2 = WPR_X * 0.4 GRP_ALPHA2 = .25 - # wpf_y_offs = (np.sign(WPF_Y-WPR_Y)/2+.5) * (WPF_Y-WPR_Y) - yyy2 = [-gripper_thickness2, y_cube2] if WPF_Y < WPR_Y else [-gripper_thickness2+(WPF_Y-WPR_Y)*2, y_cube] + yyy2 = [-gripper_thickness2, y_cube2] if WPF_Y < WPR_Y else [-gripper_thickness2 + (WPF_Y - WPR_Y) * 2, y_cube] bars = [ - ((x_cube2 - gripper_wide2) * 0.5, yyy2[0], WPF_Z - WP_GRP_OFFSET_Z), - ((x_cube2 - gripper_wide2) * 0.5, yyy2[1], WPF_Z - WP_GRP_OFFSET_Z), + ((x_cube2 - gripper_wide2) * 0.5, yyy2[0], WPF_Z - WP_GRP_OFFSET_Z), + ((x_cube2 - gripper_wide2) * 0.5, yyy2[1], WPF_Z - WP_GRP_OFFSET_Z), ] for (x, y, z) in bars: ax.bar3d( @@ -97,9 +93,7 @@ def generate_picture_wp(all_group_vars, picture_path, DEBUG=False): color='g', alpha=GRP_ALPHA2, edgecolor='k', linewidth=0.5 ) - # -------------------- clp ------------------------------------------------------------------------------------- - - # KOS CLP zeichnen + # Draw CLP coordinate system axis_len = max(x_cube, y_cube, z_cube) * 0.15 colors = ['r', 'g', 'b'] origin_x = WPR_X - WP_CLP_OFFSET_X @@ -107,88 +101,65 @@ def generate_picture_wp(all_group_vars, picture_path, DEBUG=False): origin_z = 0 for i, vec in enumerate(np.eye(3)): ax.quiver(origin_x, origin_y, origin_z, *(axis_len * vec), color=colors[i], linewidth=3) - ax.text(origin_x, origin_y, origin_z-axis_len*0.3, 'CLP', color='blue', fontsize=9, weight='bold') - - # Add two black blocks on the Y-faces in the middle of the cube height + ax.text(origin_x, origin_y, origin_z - axis_len * 0.3, 'CLP', color='blue', fontsize=9, weight='bold', ha='center', + va='top') + # Define clamping block dimensions clp_height = z_cube * 0.2 clp_width = 0.6 * x_cube - clp_deep = y_cube * 0.3 # Scale the arrows relative to the smallest dimension - clp_supportdeep = 3 # Scale the arrows relative to the smallest dimension - base_x = WPR_X - clp_width/2 + clp_deep = y_cube * 0.3 + clp_supportdeep = 3 + base_x = WPR_X - clp_width / 2 alpha = 0.35 color = 'blue' - linewidth = 0 + linewidth = 1 - - # Replace the bar3d calls with plot_merged_cubes_trimesh + # Draw clamping blocks x = base_x - WP_CLP_OFFSET_X dx = clp_width y = 0 dy1 = clp_deep dy2 = clp_supportdeep z = 0 - dz = clp_height - plot_clamping(ax, x, y, z, dx, dy1, dy2, dz, color=color, - alpha=alpha, linewidth=linewidth) - + dz1 = z_cube * 0.2 + dz2 = z_cube * 0.6 + plot_clamping(ax, x, y, z, dx, dy1, dy2, dz1, dz2, color=color, + alpha=alpha, linewidth=linewidth) y = y_cube - plot_clamping(ax, x, y, z, dx, dy1, dy2, dz, color=color, - alpha=alpha, linewidth=linewidth, inverty=True) + plot_clamping(ax, x, y, z, dx, dy1, dy2, dz1, dz2, color=color, + alpha=alpha, linewidth=linewidth, inverty=True) - - - # -------------------- view ------------------------------------------------------------------------------------- - ax.view_init(elev=18, azim=-130) - # ax.view_init(elev=45, azim=-160) - ax.set_xlim([0, x_cube]); ax.set_ylim([0, y_cube]); ax.set_zlim([0, WPR_Z]) + # Set view properties + z_trans = WPR_Z*0.2 + zoom_factor = 1.1 # Adjust this factor to zoom out more or less + ax.view_init(elev=30, azim=-160) + ax.set_xlim([-x_cube * zoom_factor * 0.1, x_cube * zoom_factor]) + ax.set_ylim([-y_cube * zoom_factor * 0.1, y_cube * zoom_factor]) + ax.set_zlim([-WPR_Z * zoom_factor * 0.1 - z_trans, WPR_Z * zoom_factor - z_trans]) ax.set_aspect('auto') + ax.grid(False) # Remove grid lines + ax.set_xticks([]) + ax.set_yticks([]) + ax.set_zticks([]) + for axis in [ax.xaxis, ax.yaxis, ax.zaxis]: + axis.set_pane_color((1, 1, 1, 0)) # Hide background panes + axis.line.set_color((1, 1, 1, 0)) # Hide axis lines + # Save or display the plot if not DEBUG: fig.savefig(picture_path, bbox_inches='tight', dpi=300, transparent=True) else: plt.show() plt.close() - # except Exception as e: - # print(f"An error occurred: {e}") - - - - -def plot_clamping(ax, x, y, z, dx, dy1, dy2, dz, color='blue', alpha=0.5, - linewidth=1, inverty=False): - """Plots merged cubes using trimesh, hiding mesh edges and drawing specific edges manually.""" - dyy1 = y - dy1 / 2 if not inverty else y + dy1 / 2 - dyy2 = y - (dy1-dy2) / 2 if not inverty else y + (dy1-dy2)/2 - - - # Create and translate Cube 1 - cube1 = trimesh.creation.box(extents=[dx, dy1, dz]) - cube1.apply_translation([x + dx / 2, dyy1, z + dz / 2]) - - # Create and translate Cube 2 - cube2 = trimesh.creation.box(extents=[dx, dy2+dy1, dz]) - cube2.apply_translation([x + dx / 2, dyy2, z - dz / 2]) - - try: - # Perform boolean union - merged = trimesh.boolean.union([cube1, cube2]) - - # Create Poly3DCollection with NO edges - ax.add_collection3d(Poly3DCollection( - merged.vertices[merged.faces], - facecolors=color, alpha=alpha, edgecolors=color, linewidth=linewidth - )) - except Exception as e: - print(f"Trimesh union failed: {e}") - - - if __name__ == "__main__": - vars = {'WPR_X': 20, 'WPR_Y': 15, 'WPR_Z': 20, 'WPF_X': 10, 'WPF_Y': 18, 'WPF_Z': 10, 'WP_CLP_OFFSET_X': 3, 'WP_GRP_OFFSET_Z': 5} + vars = {'WPR_X': 20, + 'WPR_Y': 15, + 'WPR_Z': 20, + 'WPF_X': 10, + 'WPF_Y': 18, + 'WPF_Z': 15, + 'WP_CLP_OFFSET_X': 3, + 'WP_GRP_OFFSET_Z': 5} generate_picture_wp({'wp': vars}, "cfg_picture/TEST_wpraw.jpg", DEBUG=True) - - # vars = {'x_wpfin': 10, 'y_wpfin': 20, 'z_wpfin': 20, 'l_wpfin': 10} - # generate_picture_wpfin({'wp_fin': vars}, "cfg_picture/TEST_wpfin.jpg", DEBUG=True) diff --git a/functions.py b/functions.py index 2c53bb9..a9cc2eb 100644 --- a/functions.py +++ b/functions.py @@ -5,6 +5,9 @@ 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 @@ -87,3 +90,40 @@ def create_new_param_popup(root, group_name, input_vars, param_values, param_dro 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}") +