From 15029486d41640f6bb316c761bed0eda0d1b2624 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 10 Oct 2024 01:28:15 +0200 Subject: [PATCH] ADD: w_solver, wip w_dataset_closest_lines_insertion --- src/rhino/plugin/commands/w_dataset.py | 4 +- .../w_dataset_closest_lines_insertion.py | 175 ++++++++++++++++++ .../w_dataset_closest_points_joints.py | 10 + .../commands/w_dataset_folded_plates.py | 57 +++--- src/rhino/plugin/commands/w_parameters.py | 161 +++++++++------- src/rhino/plugin/commands/w_solver.py | 114 ++++++++++++ src/rhino/plugin/compas_wood.rhproj | 96 +++++++++- .../plugin/libraries/wood_rui/globals.py | 22 ++- src/rhino/plugin/libraries/wood_rui/object.py | 9 +- 9 files changed, 531 insertions(+), 117 deletions(-) diff --git a/src/rhino/plugin/commands/w_dataset.py b/src/rhino/plugin/commands/w_dataset.py index b2fba9189..c0eb8d6fc 100644 --- a/src/rhino/plugin/commands/w_dataset.py +++ b/src/rhino/plugin/commands/w_dataset.py @@ -2,7 +2,6 @@ import Rhino import System import System.IO -import compas_wood from compas_wood.binding import read_xml_polylines import os from wood_rui import add_polylines, wood_rui_globals, BooleanForm @@ -59,7 +58,7 @@ def load_data_set(path: str = "C://brg//2_code//compas_wood//src//rhino//plugin/ """ # Get filenames from the path: - module_path: str = path#os.path.dirname(compas_wood.__file__) + module_path: str = path # os.path.dirname(compas_wood.__file__) print("Data-sets are located in the shared folder:\n" + module_path) foldername: str = module_path + os.sep files: List[str] = os.listdir(foldername) @@ -78,6 +77,7 @@ def load_data_set(path: str = "C://brg//2_code//compas_wood//src//rhino//plugin/ polylines = read_xml_polylines(foldername, value[0]) wood_rui_globals[value[0]]["polylines"] = polylines add_polylines(polylines, value[0]) + Rhino.RhinoDoc.ActiveDoc.Views.ActiveView.Redraw() # 0 ms return file_names_without_extensions diff --git a/src/rhino/plugin/commands/w_dataset_closest_lines_insertion.py b/src/rhino/plugin/commands/w_dataset_closest_lines_insertion.py index e69de29bb..ee717ef9a 100644 --- a/src/rhino/plugin/commands/w_dataset_closest_lines_insertion.py +++ b/src/rhino/plugin/commands/w_dataset_closest_lines_insertion.py @@ -0,0 +1,175 @@ +import Rhino +import Rhino.Input +import Rhino.DocObjects +from typing import * +from wood_rui import wood_rui_globals + +def find_insertion_lines(): + ############################################################################### + # Run the closest point search + ############################################################################### + + # convert element polylines to a flattened dictionary: + segments_dictionary = {} + # stores ids e.g. int , [element_int,bottom_or_top_polyline_int,edge,int, bounding_box, hit_count, point_id] + vectors = [] + count = 0 + for i in range(len(polylines)): + vectors.append([Vector3d.Zero] * (polylines[i][0].SegmentCount + 2)) + for j in range(len(polylines[i])): + for k in range(polylines[i][j].SegmentCount): + bbox = polylines[i][j].SegmentAt(k).BoundingBox + bbox.Inflate(0.02) + segments_dictionary[count] = [i, j, k, bbox, polylines[i][j].SegmentAt(k)] + + count = count + 1 + + # create a tree + rtree = Rhino.Geometry.RTree() + + # fill the tree + for i in segments_dictionary: + rtree.Insert(segments_dictionary[i][3], i) + + # call_backs of rtree search + def search_callback(sender, rtree_event_args): + data_by_reference.append(rtree_event_args.Id) + + # perform search, two times first for start points of a polyline, second for the end point + for i in range(len(lines)): + data_by_reference = [] + if rtree.Search(Sphere(lines[i].From, 0), search_callback, data_by_reference): + for j in data_by_reference: + if ( + lines[i].From.DistanceToSquared(segments_dictionary[j][4].ClosestPoint(lines[i].From, True)) + < 0.001 + ): + vectors[segments_dictionary[j][0]][segments_dictionary[j][2] + 2] = lines[i].Direction + # vectors[segments_dictionary[j][0]][segments_dictionary[j][2]+2].Unitize() + + for i in range(len(lines)): + data_by_reference = [] + if rtree.Search(Sphere(lines[i].To, 0), search_callback, data_by_reference): + for j in data_by_reference: + if lines[i].To.DistanceToSquared(segments_dictionary[j][4].ClosestPoint(lines[i].To, True)) < 0.001: + vectors[segments_dictionary[j][0]][segments_dictionary[j][2] + 2] = -lines[i].Direction + # vectors[segments_dictionary[j][0]][segments_dictionary[j][2]+2].Unitize() + + ############################################################################### + # Output + ############################################################################### + _polylines_out = polylines_out + _vectors = th.list_to_tree(vectors) + + # return outputs if you have them; here I try it for you: + return (_polylines_out, _vectors) + + +def command_line_input() -> Tuple[str, List[Rhino.Geometry.Line]]: + + # Create an instance of GetOption to define options in one line + get_options: Rhino.Input.Custom.GetOption = Rhino.Input.Custom.GetOption() + + # Populate options from wood_rui_globals.datasets.keys() + + case_names = list(wood_rui_globals.dataset.keys()) + + # Check if case_names is empty + if not case_names: + Rhino.RhinoApp.WriteLine("\nATTENTION: First create geometry, set joint parameters, and then run the solver.\n") + return Rhino.Commands.Result.Cancel # Exit if no datasets are found + + # Add an option to select lines + get_options.AddOption("select_lines") + + # Add case names as options + for case_name in case_names: + get_options.AddOption(case_name) + + Rhino.RhinoApp.WriteLine("\nā”€ Select a case and lines. Hit 'Enter' when done. ā”€") + get_options.SetCommandPrompt("Select a case or lines.") + + # Initialize storage for the case name and selected lines + selected_case_name = None + selected_lines = [] + + # Run the option selection loop + while True: + res = get_options.Get() + + # Check if the operation was cancelled or Enter was pressed (GetResult.Nothing) + if res == Rhino.Input.GetResult.Nothing or res == Rhino.Input.GetResult.Cancel: + if not selected_case_name: + selected_case_name = case_names[0] # Default to the first case if none was selected + Rhino.RhinoApp.WriteLine("Selection completed.") + break + + # If an option is selected + if res == Rhino.Input.GetResult.Option: + option_name = get_options.Option().EnglishName + + # If user selects the option to choose lines + if option_name == "select_lines": + Rhino.RhinoApp.WriteLine("\nā”€ Select the lines. Press Enter when done. ā”€") + + # Create an instance of GetObject to select curves (lines) + go = Rhino.Input.Custom.GetObject() + go.SetCommandPrompt("Select lines") + go.GeometryFilter = Rhino.DocObjects.ObjectType.Curve # Filter only curves (includes lines) + go.SubObjectSelect = False # Don't allow subobject selection + go.EnablePreSelect(True, True) # Allow pre-selection of objects + go.GetMultiple(1, 0) # Allow selecting multiple lines, 1 as the minimum + + # Check the result of the line selection + if go.CommandResult() != Rhino.Commands.Result.Success: + Rhino.RhinoApp.WriteLine("Failed to select lines.") + continue # Continue to let user select more lines + + # Process the selected lines + for i in range(go.ObjectCount): + obj_ref = go.Object(i) + curve = obj_ref.Curve() + if curve: + selected_lines.append(curve) + + Rhino.RhinoApp.WriteLine(f"Total lines selected: {len(selected_lines)}") + + # If the user selects a case + elif option_name in case_names: + selected_case_name = option_name + Rhino.RhinoApp.WriteLine(f"Case selected: {selected_case_name}") + + # Handle the datasets based on user input + print(selected_case_name, selected_lines) + return selected_case_name, selected_lines + +if __name__ == "__main__": + + Rhino.RhinoDoc.ActiveDoc.Views.ActiveView.Redraw() # 0 ms + + command_line_input() + + + + case_name = "your_case_name" # Replace with the actual case name + # polylines_guid_list = wood_rui_globals[case_name]["polylines_guid"] + + # # Iterate through the list two items at a time + # for i in range(0, len(polylines_guid_list), 2): + # # Get the current GUIDs for both first and second items + # first_guid = polylines_guid_list[i] # Current index + # second_guid = polylines_guid_list[i + 1] # Next index (always exists) + + # # Process the first object + # rhino_object_first = Rhino.RhinoDoc.ActiveDoc.Objects.Find(first_guid) + # for idx, v in enumerate(vectors[int(i * 0.5)]): + # name = f"insertion_vector_{idx}" # Use the same index for both + # value = f"{v.X} {v.Y} {v.Z}" # Ensure you are referencing the correct coordinates + # rhino_object_first.Attributes.SetUserString(name, value) + + # # Process the second object + # rhino_object_second = Rhino.RhinoDoc.ActiveDoc.Objects.Find(second_guid) + # for idx, v in enumerate(vectors[int(i * 0.5)]): + # name = f"insertion_vector_{idx}" # Same name pattern + # value = f"{v.X} {v.Y} {v.Z}" # Ensure you are referencing the correct coordinates + # rhino_object_second.Attributes.SetUserString(name, value) diff --git a/src/rhino/plugin/commands/w_dataset_closest_points_joints.py b/src/rhino/plugin/commands/w_dataset_closest_points_joints.py index e69de29bb..a364bf6ec 100644 --- a/src/rhino/plugin/commands/w_dataset_closest_points_joints.py +++ b/src/rhino/plugin/commands/w_dataset_closest_points_joints.py @@ -0,0 +1,10 @@ +import Rhino +import Rhino.Input +import Rhino.DocObjects +from typing import * +from wood_rui import wood_rui_globals + + +if __name__ == "__main__": + + Rhino.RhinoDoc.ActiveDoc.Views.ActiveView.Redraw() # 0 ms diff --git a/src/rhino/plugin/commands/w_dataset_folded_plates.py b/src/rhino/plugin/commands/w_dataset_folded_plates.py index f5968b060..84ef1377b 100644 --- a/src/rhino/plugin/commands/w_dataset_folded_plates.py +++ b/src/rhino/plugin/commands/w_dataset_folded_plates.py @@ -12,18 +12,18 @@ class dataset_folded_plates: def __init__( self, - dataset_name : str, + dataset_name: str, surface: Rhino.Geometry.Surface, u_divisions: int, v_divisions: int, base_planes: System.Collections.Generic.List[Rhino.Geometry.Plane], thickness: float, chamfer: float, - face_positions: System.Collections.Generic.List[float] + face_positions: System.Collections.Generic.List[float], ): # Diamond Subdivision - self._dataset_name = dataset_name # type str + self._dataset_name = dataset_name # type str self._mesh = Rhino.Geometry.Mesh() # type Mesh self._flags = [] # List @@ -585,28 +585,25 @@ def get_insertion_vectors(self): for i in range(self._f): for j in range(2): self._f_polylines[i][j] = self.chamfer_polyline(self._f_polylines[i][j], -self._chamfer) - def create_dataset(self): - add_mesh(self._mesh, self._dataset_name) flat_list_of_polylines = [] for i in range(0, len(self._f_polylines)): for j in range(0, len(self._f_polylines[i])): flat_list_of_polylines.append(self._f_polylines[i][j]) - add_polylines(flat_list_of_polylines , self._dataset_name) + add_polylines(flat_list_of_polylines, self._dataset_name) add_insertion_lines(self._insertion_lines, self._dataset_name) add_adjacency(self._adjacency, self._dataset_name) add_flags(self._flags, self._dataset_name) - Rhino.RhinoDoc.ActiveDoc.Views.Redraw() # 10-12ms - Rhino.RhinoDoc.ActiveDoc.Views.ActiveView.Redraw() # 0 ms - + # Rhino.RhinoDoc.ActiveDoc.Views.Redraw() # 10-12ms + Rhino.RhinoDoc.ActiveDoc.Views.ActiveView.Redraw() # 0 ms def get_base_planes() -> Tuple[Optional[List[rg.Plane]], rc.Result]: base_planes: List[rg.Plane] = [] - + # Create a GetObject instance to select multiple curves go: ric.GetObject = ric.GetObject() go.SetCommandPrompt("Select multiple rectangle curves") @@ -637,9 +634,10 @@ def get_base_planes() -> Tuple[Optional[List[rg.Plane]], rc.Result]: if not base_planes: return None, rc.Result.Failure - + return base_planes, rc.Result.Success + def command_line_input(dataset_name) -> rc.Result: # Create an instance of GetOption to define options in one line get_options: ric.GetOption = ric.GetOption() @@ -649,11 +647,11 @@ def command_line_input(dataset_name) -> rc.Result: surface: Optional[rg.Surface] = None u_divisions: ric.OptionInteger = ric.OptionInteger(5) # Default value 5 v_divisions: ric.OptionInteger = ric.OptionInteger(2) # Default value 2 - thickness: ric.OptionDouble = ric.OptionDouble(4) # Default value 1.4 - chamfer: ric.OptionDouble = ric.OptionDouble(3) # Default value 0.0 + thickness: ric.OptionDouble = ric.OptionDouble(1.4) # Default value 1.4 + chamfer: ric.OptionDouble = ric.OptionDouble(6) # Default value 0.0 face_positions: List[float] = [0.0] # Default list with a single value 0.0 base_planes: List[Rhino.Geometry.Plane] = [] - + # Add options to the GetOption instance with custom names get_options.AddOption("select_surface") # New option to select surface get_options.AddOptionInteger("u_divisions", u_divisions) @@ -671,15 +669,15 @@ def command_line_input(dataset_name) -> rc.Result: def update(): dataset_folded_plates( dataset_name, - surface, - u_divisions.CurrentValue, - v_divisions.CurrentValue, + surface, + u_divisions.CurrentValue, + v_divisions.CurrentValue, base_planes, - thickness.CurrentValue, - chamfer.CurrentValue, - face_positions # Pass face_positions to the UI + thickness.CurrentValue, + chamfer.CurrentValue, + face_positions, # Pass face_positions to the UI ) - + update() # Run once to see the code input while True: @@ -690,7 +688,7 @@ def update(): return rc.Result.Cancel # Exit the loop if res == Rhino.Input.GetResult.Option: - + if get_options.OptionIndex() == 1: # 'select_surface' # Step A: Select a surface go: ric.GetObject = ric.GetObject() @@ -699,13 +697,13 @@ def update(): go.EnablePreSelect(True, True) go.DeselectAllBeforePostSelect = False go.SubObjectSelect = False - + if go.Get() != Rhino.Input.GetResult.Object: return go.CommandResult() - + surface_ref = go.Object(0) surface: Optional[rg.Surface] = surface_ref.Surface() - + if not surface: print("No surface selected.") return rc.Result.Failure @@ -717,10 +715,10 @@ def update(): print("You have chosen to get base planes.") # Call get_base_planes() immediately when option is selected base_planes, result = get_base_planes() - + if result != rc.Result.Success: return result - + print("Base planes selected:", len(base_planes) if base_planes else 0) update() continue @@ -732,12 +730,12 @@ def update(): if gp.Get() != Rhino.Input.GetResult.String: print("No input provided for face positions.") return rc.Result.Failure - + input_str = gp.StringResult() try: # Convert the input string to a list of floats - face_positions = [float(val.strip()) for val in input_str.split(',')] + face_positions = [float(val.strip()) for val in input_str.split(",")] print("Face positions:", face_positions) except ValueError: print("Invalid input. Please enter valid numbers separated by commas.") @@ -761,7 +759,6 @@ def update(): else: update() - # Do something with the inputs (you can apply further operations here) return rc.Result.Success diff --git a/src/rhino/plugin/commands/w_parameters.py b/src/rhino/plugin/commands/w_parameters.py index f6ef3ae0d..43ef69322 100644 --- a/src/rhino/plugin/commands/w_parameters.py +++ b/src/rhino/plugin/commands/w_parameters.py @@ -4,83 +4,98 @@ from compas_wood.binding import wood_globals if __name__ == "__main__": - + + # Define the parameters parameters: Tuple[str, Any] = [ - - ("SEARCH TYPE", " "), # 0 - ("(0 - side-to-side, 1 - cross, 2 - both)", 0), # 1 - (" ", " "), # 2 - ("OUTPUT TYPE", " "), # 3 - ("(0 - outlines, 1 - lines, 2 - areas, 3 - volumes, 4 - merged joints) ", wood_globals.output_geometry_type), # 4 - (" ", " "), # 5 - ("SCALE", " "), # 6 - ("x-axis", 1), # 7 - ("y-axis", 1), # 8 - ("z-axis", 1), # 9 - (" ", " "), # 10 - ("EXTENSION", " "), # 11 - ("x-axis", wood_globals.joint_volume_extension[0]), # 12 - ("y-axis", wood_globals.joint_volume_extension[1]), # 13 - ("z-axis", wood_globals.joint_volume_extension[2]), # 14 - (" ", " "), # 15 - ("SIDE-TO-SIDE EDGE IN-PLANE", " "), # 16 - ("division length (0-n)", wood_globals.joints_parameters_and_types[0]), # 17 - ("parameter (0-1)", wood_globals.joints_parameters_and_types[1]), # 18 - ("type (1-9)", wood_globals.joints_parameters_and_types[2]), # 19 - (" ", " "), # 20 - ("SIDE-TO-SIDE EDGE OUT-OF-PLANE", " "), # 21 - ("division length (10-n)", wood_globals.joints_parameters_and_types[3]), # 22 - ("parameter (0-1)", wood_globals.joints_parameters_and_types[4]), # 23 - ("type (10-19)", wood_globals.joints_parameters_and_types[5]), # 24 - (" ", " "), # 25 - ("TOP-TO-SIDE EDGE PLANE", " "), # 26 - ("division length (20-n)", wood_globals.joints_parameters_and_types[6]), # 27 - ("parameter (0-1)", wood_globals.joints_parameters_and_types[7]), # 28 - ("type (20-29)", wood_globals.joints_parameters_and_types[8]), # 29 - (" ", " "), # 30 - ("CROSS CUTTING IN-PLANE", " "), # 31 - ("division length (30-n)", wood_globals.joints_parameters_and_types[9]), # 32 - ("parameter (0-1)", wood_globals.joints_parameters_and_types[10]), # 33 - ("type (30-39)", wood_globals.joints_parameters_and_types[11]), # 34 - (" ", " "), # 35 - ("TOP-TO-TOP EDGE PLANE", " "), # 36 - ("division length (40-n)", wood_globals.joints_parameters_and_types[12]), # 37 - ("parameter (0-1)", wood_globals.joints_parameters_and_types[13]), # 38 - ("type (40-49)", wood_globals.joints_parameters_and_types[14]), # 39 - (" ", " "), # 40 - ("SIDE-TO-SIDE EDGE ROTATED", " "), # 41 - ("division length (50-n)", wood_globals.joints_parameters_and_types[15]), # 42 - ("parameter (0-1)", wood_globals.joints_parameters_and_types[16]), # 43 - ("type (50-59)", wood_globals.joints_parameters_and_types[17]), # 44 - (" ", " "), # 45 - ("BOUNDARY", " "), # 46 - ("division length (60-n)", wood_globals.joints_parameters_and_types[18]), # 47 - ("parameter (0-1)", wood_globals.joints_parameters_and_types[19]), # 48 - ("type (60-69)", wood_globals.joints_parameters_and_types[20]), # 49 - (" ", " "), # 50 - ("DEBUG PARAMETERS", " "), # 51 - ("clipper_scale", wood_globals.clipper_scale), # 52 - ("clipper_area", wood_globals.clipper_area), # 53 - ("distance", wood_globals.distance), # 54 - ("distance_squared", wood_globals.distance_squared), # 55 - ("angle", wood_globals.angle), # 56 - ("path_and_file_for_joints", wood_globals.path_and_file_for_joints), # 57 - ("data_set_input_folder", wood_globals.data_set_input_folder), # 58 - ("data_set_output_file", wood_globals.data_set_output_file), # 59 - ("data_set_output_database", wood_globals.data_set_output_database), # 60 - ("face_to_face_side_to_side_joints_all_treated_as_rotated", wood_globals.face_to_face_side_to_side_joints_all_treated_as_rotated), # 61 - ("face_to_face_side_to_side_joints_rotated_joint_as_average", wood_globals.face_to_face_side_to_side_joints_rotated_joint_as_average), # 62 - ("face_to_face_side_to_side_joints_dihedral_angle", wood_globals.face_to_face_side_to_side_joints_dihedral_angle), # 63 - ("limit_min_joint_length", wood_globals.limit_min_joint_length), # 64 + ("SEARCH TYPE", " "), # 0 + ("(0 - side-to-side, 1 - cross, 2 - both)", wood_rui_globals.search_type), # temporary parameter that must go from compas_wood.binding import wood_globals + (" ", " "), # 2 + ("OUTPUT TYPE", " "), # 3 + ( + "(0 - areas, 1 - lines, 2 - volumes, 3 - joints, 4 - merged joints) ", + wood_globals.output_geometry_type, + ), # 4 + (" ", " "), # 5 + ("SCALE", " "), # 6 + ("x-axis", wood_rui_globals.scale[0]), # 7 temporary parameter that must go from compas_wood.binding import wood_globals + ("y-axis", wood_rui_globals.scale[1]), # 8 temporary parameter that must go from compas_wood.binding import wood_globals + ("z-axis", wood_rui_globals.scale[2]), # 9 temporary parameter that must go from compas_wood.binding import wood_globals + (" ", " "), # 10 + ("EXTENSION", " "), # 11 + ("x-axis", wood_rui_globals.joint_volume_extension[0]), # 12 temporary parameter that must go from compas_wood.binding import wood_globals + ("y-axis", wood_rui_globals.joint_volume_extension[1]), # 13 temporary parameter that must go from compas_wood.binding import wood_globals + ("z-axis", wood_rui_globals.joint_volume_extension[2]), # 14 temporary parameter that must go from compas_wood.binding import wood_globals + (" ", " "), # 15 + ("SIDE-TO-SIDE EDGE IN-PLANE", " "), # 16 + ("division length (0-n)", wood_globals.joints_parameters_and_types[0]), # 17 + ("parameter (0-1)", wood_globals.joints_parameters_and_types[1]), # 18 + ("type (1-9)", wood_globals.joints_parameters_and_types[2]), # 19 + (" ", " "), # 20 + ("SIDE-TO-SIDE EDGE OUT-OF-PLANE", " "), # 21 + ("division length (10-n)", wood_globals.joints_parameters_and_types[3]), # 22 + ("parameter (0-1)", wood_globals.joints_parameters_and_types[4]), # 23 + ("type (10-19)", wood_globals.joints_parameters_and_types[5]), # 24 + (" ", " "), # 25 + ("TOP-TO-SIDE EDGE PLANE", " "), # 26 + ("division length (20-n)", wood_globals.joints_parameters_and_types[6]), # 27 + ("parameter (0-1)", wood_globals.joints_parameters_and_types[7]), # 28 + ("type (20-29)", wood_globals.joints_parameters_and_types[8]), # 29 + (" ", " "), # 30 + ("CROSS CUTTING IN-PLANE", " "), # 31 + ("division length (30-n)", wood_globals.joints_parameters_and_types[9]), # 32 + ("parameter (0-1)", wood_globals.joints_parameters_and_types[10]), # 33 + ("type (30-39)", wood_globals.joints_parameters_and_types[11]), # 34 + (" ", " "), # 35 + ("TOP-TO-TOP EDGE PLANE", " "), # 36 + ("division length (40-n)", wood_globals.joints_parameters_and_types[12]), # 37 + ("parameter (0-1)", wood_globals.joints_parameters_and_types[13]), # 38 + ("type (40-49)", wood_globals.joints_parameters_and_types[14]), # 39 + (" ", " "), # 40 + ("SIDE-TO-SIDE EDGE ROTATED", " "), # 41 + ("division length (50-n)", wood_globals.joints_parameters_and_types[15]), # 42 + ("parameter (0-1)", wood_globals.joints_parameters_and_types[16]), # 43 + ("type (50-59)", wood_globals.joints_parameters_and_types[17]), # 44 + (" ", " "), # 45 + ("BOUNDARY", " "), # 46 + ("division length (60-n)", wood_globals.joints_parameters_and_types[18]), # 47 + ("parameter (0-1)", wood_globals.joints_parameters_and_types[19]), # 48 + ("type (60-69)", wood_globals.joints_parameters_and_types[20]), # 49 + (" ", " "), # 50 + ("DEBUG PARAMETERS", " "), # 51 + ("clipper_scale", wood_globals.clipper_scale), # 52 + ("clipper_area", wood_globals.clipper_area), # 53 + ("distance", wood_globals.distance), # 54 + ("distance_squared", wood_globals.distance_squared), # 55 + ("angle", wood_globals.angle), # 56 + ("path_and_file_for_joints", wood_globals.path_and_file_for_joints), # 57 + ("data_set_input_folder", wood_globals.data_set_input_folder), # 58 + ("data_set_output_file", wood_globals.data_set_output_file), # 59 + ("data_set_output_database", wood_globals.data_set_output_database), # 60 + ( + "face_to_face_side_to_side_joints_all_treated_as_rotated", + wood_globals.face_to_face_side_to_side_joints_all_treated_as_rotated, + ), # 61 + ( + "face_to_face_side_to_side_joints_rotated_joint_as_average", + wood_globals.face_to_face_side_to_side_joints_rotated_joint_as_average, + ), # 62 + ( + "face_to_face_side_to_side_joints_dihedral_angle", + wood_globals.face_to_face_side_to_side_joints_dihedral_angle, + ), # 63 + ("limit_min_joint_length", wood_globals.limit_min_joint_length), # 64 ] - # Extract names and values separately - names : list[str] = [item[0] for item in parameters] # First row: keys (names) - values : list[str, float, int, tuple, list, dict, set, bool, None] = [item[1] for item in parameters] # Second row: values + names: list[str] = [item[0] for item in parameters] # First row: keys (names) + values: list[str, float, int, tuple, list, dict, set, bool, None] = [ + item[1] for item in parameters + ] # Second row: values # Pass the my_method as the run_method parameter - form : NamedValuesForm = NamedValuesForm(names=names, values=values, title="Joinery Parameters", width = 408, height = 600) + form: NamedValuesForm = NamedValuesForm( + names=names, values=values, title="Joinery Parameters", width=408, height=600 + ) if form.show(): joint_parameters = [ @@ -123,3 +138,7 @@ wood_globals.face_to_face_side_to_side_joints_rotated_joint_as_average = form.attributes[62][1] wood_globals.face_to_face_side_to_side_joints_dihedral_angle = form.attributes[63][1] wood_globals.limit_min_joint_length = form.attributes[64][1] + + wood_rui_globals.scale = [form.attributes[7][1], form.attributes[8][1], form.attributes[9][1]] # temporary parameter that must go from compas_wood.binding import wood_globals + wood_rui_globals.search_type = form.attributes[1][1] # temporary parameter that must go from compas_wood.binding import wood_globals + wood_rui_globals.joint_volume_extension = [form.attributes[12][1], form.attributes[13][1], form.attributes[14][1]] # temporary parameter that must go from compas_wood.binding import wood_globals diff --git a/src/rhino/plugin/commands/w_solver.py b/src/rhino/plugin/commands/w_solver.py index e69de29bb..0caf6b7fe 100644 --- a/src/rhino/plugin/commands/w_solver.py +++ b/src/rhino/plugin/commands/w_solver.py @@ -0,0 +1,114 @@ +#! python3 +import Rhino +import Rhino.Input.Custom as ric +from wood_rui import wood_rui_globals, add_joinery +from wood_nano import get_connection_zones as wood_nano_get_connection_zones +from wood_nano import cut_type2 as wood_nano_cut_type2 +from wood_nano import point3 as wood_nano_point3 +from wood_nano.conversions_python import to_int2 +from wood_nano.conversions_python import to_int1 +from wood_nano.conversions_python import to_double1 +from wood_nano.conversions_python import from_cut_type2 +from compas_wood.conversions_rhino import to_point2 +from compas_wood.conversions_rhino import to_vector2 +from compas_wood.conversions_rhino import from_point3 +from compas_wood.binding import wood_globals +from compas_wood.datastructures import WoodData +from typing import List, Dict, Any + + +def command_line_input() -> str: + """ + Gets user input for selecting a dataset from wood_rui_globals. + + Returns: + str: The name of the selected dataset, or an empty string if cancelled. + """ + # All datasets as a list of strings. + datasets: List[str] = list(wood_rui_globals.dataset.keys()) + + # Create an instance of GetOption to allow user to choose a dataset + get_options: ric.GetOption = ric.GetOption() + + # Add each dataset as an option + for i, dataset in enumerate(datasets): + get_options.AddOption(dataset) + + get_options.SetCommandPrompt("Select a dataset from wood_rui_globals:") + + while True: + res: Rhino.Input.GetResult = get_options.Get() + + if res == Rhino.Input.GetResult.Option: + selected_index: int = get_options.OptionIndex() - 1 # Adjusting for 1-based index + selected_dataset: str = datasets[selected_index] + print(f"Selected dataset: {selected_dataset}") + return selected_dataset + + elif res == Rhino.Input.GetResult.Cancel: + print("Selection cancelled.") + return "" + + +def solver(dataset_name: str) -> None: + """ + Run the solver with the selected dataset, using properties from global parameters. + + Args: + dataset_name (str): Name of the dataset to solve. + """ + + w_output_plines: wood_nano_point3 = wood_nano_point3() + w_output_types: wood_nano_cut_type2 = wood_nano_cut_type2() + + adjacency_flat_list: List[int] = [] + adjacency_data: List[List[int]] = wood_rui_globals[dataset_name]["adjacency"] + + for sublist in adjacency_data: + for item in sublist: + adjacency_flat_list.append(item) + + wood_nano_get_connection_zones( + to_point2(wood_rui_globals[dataset_name]["polylines"]), + to_vector2(wood_rui_globals[dataset_name]["insertion_vectors"]), + to_int2(wood_rui_globals[dataset_name]["joints_dots"]), + to_int2(wood_rui_globals[dataset_name]["three_valence_element_indices_and_instruction"]), + to_int1(adjacency_flat_list), + to_double1(wood_globals.joints_parameters_and_types), + int(wood_rui_globals.search_type), + to_double1(wood_rui_globals.scale), + int(wood_globals.output_geometry_type), + w_output_plines, + w_output_types, + to_double1(wood_rui_globals.joint_volume_extension), + ) + + add_joinery(from_point3(w_output_plines), dataset_name) + + # Add joint types if the output type is 3 + is_output_type_3: bool = int(wood_globals.output_geometry_type) == 3 + + if is_output_type_3: + joint_types: List[List[int]] = from_cut_type2(w_output_types) + + counter: int = 0 + for i, output_type in enumerate(w_output_types): + for j in range(len(wood_rui_globals[dataset_name]["joinery"][i])): + guid: str = wood_rui_globals[dataset_name]["joinery_guid"][counter] + rhino_object: Rhino.DocObjects.RhinoObject = Rhino.RhinoDoc.ActiveDoc.Objects.Find(guid) + + if is_output_type_3: + joint_type: int = joint_types[i][int(j * 0.5)] + rhino_object.Attributes.SetUserString("joint_type", str(joint_type)) + + rhino_object.Attributes.SetUserString("element_id", str(i)) + rhino_object.Attributes.SetUserString("face_id", str(j)) + counter += 1 + + Rhino.RhinoDoc.ActiveDoc.Views.ActiveView.Redraw() # 0 ms + + +if __name__ == "__main__": + dataset_name: str = command_line_input() + if dataset_name: + solver(dataset_name) diff --git a/src/rhino/plugin/compas_wood.rhproj b/src/rhino/plugin/compas_wood.rhproj index 76db85c15..71abfcad8 100644 --- a/src/rhino/plugin/compas_wood.rhproj +++ b/src/rhino/plugin/compas_wood.rhproj @@ -8,7 +8,7 @@ "id": "d0647ba8-eee5-4c18-ab3e-03a95f119654", "identity": { "name": "compas_wood", - "version": "2.0.6", + "version": "2.0.10", "publisher": { "email": "petrasvestartas@gmail.com", "name": "Petras Vestartas", @@ -147,7 +147,25 @@ "version": "3.9.10" }, "title": "w_dataset_folded_plates", - "uri": "commands/w_dataset_folded_plates.py" + "uri": "commands/w_dataset_folded_plates.py", + "image": { + "light": { + "type": "svg", + "data": "PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmlld0JveD0iMHB0IDBwdCA0OHB0IDQ4cHQiIGZpbGwtZGFyaz0iI0ZGRiIgc3Ryb2tlLWRhcms9Im5vbmUiPg0KICA8c3ZnIGlkPSJMYXllcl8yIiBkYXRhLW5hbWU9IkxheWVyIDIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI0IDI0Ij4NCiAgICA8ZGVmcyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KICAgICAgPHN0eWxlPgogICAgICAuY2xzLTEgewogICAgICAgIGZpbGw6ICNkYmRiZGI7CiAgICAgICAgc3Ryb2tlOiAjMDAwOwogICAgICAgIHN0cm9rZS1saW5lY2FwOiByb3VuZDsKICAgICAgICBzdHJva2UtbGluZWpvaW46IHJvdW5kOwogICAgICB9CiAgICA8L3N0eWxlPg0KICAgIDwvZGVmcz4NCiAgICA8cG9seWdvbiBjbGFzcz0iY2xzLTEiIHBvaW50cz0iMTEuOTUgMTEuMjggMy4yMiAyMC4wMiAzLjIyIDIuNTQgMTEuOTUgMTEuMjggMTEuOTUgMTEuMjgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgLz4NCiAgICA8cG9seWdvbiBjbGFzcz0iY2xzLTEiIHBvaW50cz0iMTIuMDIgMTEuMjggMjAuNzUgMi41NCAyMC43NSAyMC4wMiAxMi4wMiAxMS4yOCAxMi4wMiAxMS4yOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAvPg0KICAgIDxwb2x5Z29uIGNsYXNzPSJjbHMtMSIgcG9pbnRzPSIxMi4wMiAxMS4zMiAxMi4wMiAyMi4zMSAzLjI5IDIwLjA1IDEyLjAyIDExLjMyIDEyLjAyIDExLjMyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIC8\u002BDQogICAgPHBvbHlnb24gY2xhc3M9ImNscy0xIiBwb2ludHM9IjEyLjAyIDExLjI0IDMuMjkgMi41MSAxMS45NSA0Ljc3IDEyLjAyIDExLjI0IDEyLjAyIDExLjI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIC8\u002BDQogICAgPHBvbHlnb24gY2xhc3M9ImNscy0xIiBwb2ludHM9IjEyLjAyIDExLjMyIDEyLjAyIDIyLjMxIDIwLjc1IDIwLjA1IDEyLjAyIDExLjMyIDEyLjAyIDExLjMyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIC8\u002BDQogICAgPHBvbHlnb24gY2xhc3M9ImNscy0xIiBwb2ludHM9IjEyLjAyIDExLjI0IDIwLjc1IDIuNTEgMTIuMDkgNC43NyAxMi4wMiAxMS4yNCAxMi4wMiAxMS4yNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAvPg0KICA8L3N2Zz4NCjwvc3ZnPg==" + }, + "rendered": { + "light": { + "bytes": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAAjVJREFUSEvdlT2PElEUhgkNEL4h4SMK2CAWhIQSaKzYAKEgKKExEhKIYgGBUNHREQId/AqNP8BYAZXxF9BY2GhcF3cMu6uD1/POOmR2MrPOTGLjSZ7kzr1n3ocQLsf0X9Vji8XyxefzvaX1C\u002BKBsKut7hPP/X7/G4fDsaP1I2FXViehUOg8EAj8qNfrl8FgcGez2b56PJ5XdPaUuCt0Xdcd4gmdvaSeU3pnV61Wv8ViMT4ajXJ09lDoktVJOp0\u002BHQwGe2q82m63bL1es\u002Bl0yorFIud2u78TH10u1wesC4UCN5lM2Gq1YuhNpVL8cDjcJ5PJM8pSF6C53\u002B8fJVLonFUqlRt7QAzHWpMAKEkymQxrNBrHZyANB5oFoNfr3ZBA0Gw2j\u002BfycKBLAKSSbDbLWq2WsK8UDnQLQLfbFSQQtNtt1XBgSAAgsVqtB/pJ/lILB4YFwGw2H\u002BgiHpTORAwL6JNfxeNxPp/P83QJeaUeYEiA8Pl8vs/lcqzT6bDlcrmnW68o0S0Qw7EWBVirSXQJpOFAKgBKEs0CeTiQC8AfyU/xWZNAKRwoCYBU8leBWjhQE4DFYnEBya0Cu93Oj0YjxXBwmwCMx\u002BMLyjhQlqLAQX8HY6fT\u002Bcnr9XKlUonDLMBMEAPkgs1mw2azGSuXyxxdQI7CP0cikQll2a8j1StKNDDNMNXoa9vVarXLRCLBaNAwTLxwOHxOZ2c0gF5Tb5O4hxeNFmbuM5pk70j6ntYdQs/M/ldlMv0Gh8N580c/fxwAAAAASUVORK5CYII=", + "width": 24, + "height": 24 + }, + "dark": { + "bytes": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAAjVJREFUSEvdlT2PElEUhgkNEL4h4SMK2CAWhIQSaKzYAKEgKKExEhKIYgGBUNHREQId/AqNP8BYAZXxF9BY2GhcF3cMu6uD1/POOmR2MrPOTGLjSZ7kzr1n3ocQLsf0X9Vji8XyxefzvaX1C\u002BKBsKut7hPP/X7/G4fDsaP1I2FXViehUOg8EAj8qNfrl8FgcGez2b56PJ5XdPaUuCt0Xdcd4gmdvaSeU3pnV61Wv8ViMT4ajXJ09lDoktVJOp0\u002BHQwGe2q82m63bL1es\u002Bl0yorFIud2u78TH10u1wesC4UCN5lM2Gq1YuhNpVL8cDjcJ5PJM8pSF6C53\u002B8fJVLonFUqlRt7QAzHWpMAKEkymQxrNBrHZyANB5oFoNfr3ZBA0Gw2j\u002BfycKBLAKSSbDbLWq2WsK8UDnQLQLfbFSQQtNtt1XBgSAAgsVqtB/pJ/lILB4YFwGw2H\u002BgiHpTORAwL6JNfxeNxPp/P83QJeaUeYEiA8Pl8vs/lcqzT6bDlcrmnW68o0S0Qw7EWBVirSXQJpOFAKgBKEs0CeTiQC8AfyU/xWZNAKRwoCYBU8leBWjhQE4DFYnEBya0Cu93Oj0YjxXBwmwCMx\u002BMLyjhQlqLAQX8HY6fT\u002Bcnr9XKlUonDLMBMEAPkgs1mw2azGSuXyxxdQI7CP0cikQll2a8j1StKNDDNMNXoa9vVarXLRCLBaNAwTLxwOHxOZ2c0gF5Tb5O4hxeNFmbuM5pk70j6ntYdQs/M/ldlMv0Gh8N580c/fxwAAAAASUVORK5CYII=", + "width": 24, + "height": 24 + } + } + } }, { "id": "96a8383f-a861-4e0b-8983-116601b8c75d", @@ -156,7 +174,79 @@ "version": "3.9.10" }, "title": "w_parameters", - "uri": "commands/w_parameters.py" + "uri": "commands/w_parameters.py", + "image": { + "light": { + "type": "svg", + "data": "PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmlld0JveD0iMHB0IDBwdCA0OHB0IDQ4cHQiIGZpbGwtZGFyaz0iI0ZGRiIgc3Ryb2tlLWRhcms9Im5vbmUiPg0KICA8c3ZnIGlkPSJMYXllcl8yIiBkYXRhLW5hbWU9IkxheWVyIDIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI0IDI0Ij4NCiAgICA8ZGVmcyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KICAgICAgPHN0eWxlPgogICAgICAuY2xzLTEgewogICAgICAgIGZpbGw6ICMwMDA7CiAgICAgICAgc3Ryb2tlOiAjMDAwOwogICAgICAgIHN0cm9rZS1saW5lY2FwOiByb3VuZDsKICAgICAgICBzdHJva2UtbGluZWpvaW46IHJvdW5kOwogICAgICB9CiAgICA8L3N0eWxlPg0KICAgIDwvZGVmcz4NCiAgICA8cG9seWdvbiBjbGFzcz0iY2xzLTEiIHBvaW50cz0iMS42OSAxMi41NCA2Ljg1IDE3LjY4IDEyLjA2IDEyLjU4IDE3LjE2IDE3LjY3IDIyLjMxIDEyLjUzIDIyLjMxIDIyLjIxIDEuNjkgMjIuMjEgMS42OSAxMi41NCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAvPg0KICA8L3N2Zz4NCjwvc3ZnPg==" + }, + "rendered": { + "light": { + "bytes": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAAMxJREFUSEvt0MsJwkAYReEs7MEG3PgAi7ECwaUrF64ERdFSbEUsQBAEFyL4fmADem4yIzIkMRLdSA58JBmH\u002BRO9rKysrOTlzTVJOXP9qBVqwW1sTXSD29gqGAe3QQvcUPSfwmvhiA36Woioiivm/pNJA\u002B64oKQFpzYO0B7ZYgA3HX6C9oQOsEPKsHWwh/3d0pcMYXs9XCIHyBkF9LAza2E0ZAT3cIkdIGvor3DXXXqBmbMmbwek9WcDlgjblIZe\u002BlkDU0y\u002BRGfV8es87wGQ3bHUFEUY6gAAAABJRU5ErkJggg==", + "width": 24, + "height": 24 + }, + "dark": { + "bytes": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAAMxJREFUSEvt0MsJwkAYReEs7MEG3PgAi7ECwaUrF64ERdFSbEUsQBAEFyL4fmADem4yIzIkMRLdSA58JBmH\u002BRO9rKysrOTlzTVJOXP9qBVqwW1sTXSD29gqGAe3QQvcUPSfwmvhiA36Woioiivm/pNJA\u002B64oKQFpzYO0B7ZYgA3HX6C9oQOsEPKsHWwh/3d0pcMYXs9XCIHyBkF9LAza2E0ZAT3cIkdIGvor3DXXXqBmbMmbwek9WcDlgjblIZe\u002BlkDU0y\u002BRGfV8es87wGQ3bHUFEUY6gAAAABJRU5ErkJggg==", + "width": 24, + "height": 24 + } + } + } + }, + { + "id": "c3fa9ccf-ee62-45b7-92e6-b30473390737", + "language": { + "id": "mcneel.pythonnet.python", + "version": "3.9.10" + }, + "title": "w_solver", + "uri": "commands/w_solver.py", + "image": { + "light": { + "type": "svg", + "data": "PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmlld0JveD0iMHB0IDBwdCA0OHB0IDQ4cHQiIGZpbGwtZGFyaz0iI0ZGRiIgc3Ryb2tlLWRhcms9Im5vbmUiPg0KICA8c3ZnIGlkPSJMYXllcl8yIiBkYXRhLW5hbWU9IkxheWVyIDIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI0IDI0Ij4NCiAgICA8ZGVmcyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KICAgICAgPHN0eWxlPgogICAgICAuY2xzLTEgewogICAgICAgIGZpbGw6ICMwMDA7CiAgICAgICAgc3Ryb2tlLXdpZHRoOiAwcHg7CiAgICAgIH0KICAgIDwvc3R5bGU\u002BDQogICAgPC9kZWZzPg0KICAgIDxwb2x5Z29uIGNsYXNzPSJjbHMtMSIgcG9pbnRzPSIwIDYuNjMgNi4wMSAxMi43MyAxMS45NCA2Ljc3IDE4LjAxIDEyLjczIDI0IDYuNjEgMjQgMCAwIDAgMCA2LjYzIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIC8\u002BDQogICAgPHBvbHlnb24gY2xhc3M9ImNscy0xIiBwb2ludHM9IjAgMTIuNzQgNiAxOC43MiAxMi4wNyAxMi43OCAxOCAxOC43MSAyNCAxMi43MyAyNCAyNCAwIDI0IDAgMTIuNzQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgLz4NCiAgPC9zdmc\u002BDQo8L3N2Zz4=" + }, + "rendered": { + "light": { + "bytes": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAAMRJREFUSEu1kIEJwzAMBD1CR\u002BkIHaWbdZSOkFW6QaoXESjqW3JAfTjiPGcJPCT7n6FlJ7TshJad0LITWnYyPqHIuOIC\u002BON\u002BHJjggQP36boM8zXVkpMsqZZEXzNbQmXJbMnM18QlqSyJSypfY0uWZMlDSP3b8fWBOBt\u002BxVd3s8NCXsKqDweuvt3KJQy3t658Gw536ZIfXvl\u002BOCgvseFG9ONwcPoBdgm8jy7D\u002B3E4\u002BCkARCbPyHxadkLLTmjZCS07oWUTY/8CcCGuc1pNI2kAAAAASUVORK5CYII=", + "width": 24, + "height": 24 + }, + "dark": { + "bytes": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAAMRJREFUSEu1kIEJwzAMBD1CR\u002BkIHaWbdZSOkFW6QaoXESjqW3JAfTjiPGcJPCT7n6FlJ7TshJad0LITWnYyPqHIuOIC\u002BON\u002BHJjggQP36boM8zXVkpMsqZZEXzNbQmXJbMnM18QlqSyJSypfY0uWZMlDSP3b8fWBOBt\u002BxVd3s8NCXsKqDweuvt3KJQy3t658Gw536ZIfXvl\u002BOCgvseFG9ONwcPoBdgm8jy7D\u002B3E4\u002BCkARCbPyHxadkLLTmjZCS07oWUTY/8CcCGuc1pNI2kAAAAASUVORK5CYII=", + "width": 24, + "height": 24 + } + } + } + }, + { + "id": "60c6091b-3dcb-410d-9006-b445ae46e291", + "language": { + "id": "mcneel.pythonnet.python", + "version": "3.9.10" + }, + "title": "w_dataset_closest_lines_insertion", + "uri": "commands/w_dataset_closest_lines_insertion.py", + "image": { + "light": { + "type": "svg", + "data": "PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmlld0JveD0iMHB0IDBwdCA0OHB0IDQ4cHQiIGZpbGwtZGFyaz0iI0ZGRiIgc3Ryb2tlLWRhcms9Im5vbmUiPg0KICA8c3ZnIGlkPSJMYXllcl8yIiBkYXRhLW5hbWU9IkxheWVyIDIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI0IDI0Ij4NCiAgICA8ZGVmcyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KICAgICAgPHN0eWxlPgogICAgICAuY2xzLTEgewogICAgICAgIGZpbGw6ICMwMDA7CiAgICAgICAgc3Ryb2tlLXdpZHRoOiAwcHg7CiAgICAgIH0KCiAgICAgIC5jbHMtMiB7CiAgICAgICAgZmlsbDogI2RiZGJkYjsKICAgICAgfQoKICAgICAgLmNscy0yLCAuY2xzLTMgewogICAgICAgIHN0cm9rZTogIzAwMDsKICAgICAgICBzdHJva2UtbGluZWNhcDogcm91bmQ7CiAgICAgICAgc3Ryb2tlLWxpbmVqb2luOiByb3VuZDsKICAgICAgfQoKICAgICAgLmNscy0zIHsKICAgICAgICBmaWxsOiBub25lOwogICAgICAgIHN0cm9rZS13aWR0aDogMnB4OwogICAgICB9CiAgICA8L3N0eWxlPg0KICAgIDwvZGVmcz4NCiAgICA8bGluZSBjbGFzcz0iY2xzLTMiIHgxPSIyMS4yMyIgeTE9IjcuNDIiIHgyPSIxNi4yMyIgeTI9IjcuNDIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgLz4NCiAgICA8bGluZSBjbGFzcz0iY2xzLTMiIHgxPSI3LjczIiB5MT0iMTYuODYiIHgyPSIyLjczIiB5Mj0iMTYuODYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgLz4NCiAgICA8cmVjdCBjbGFzcz0iY2xzLTIiIHg9IjUuOTEiIHk9IjUuODkiIHdpZHRoPSIxMi4zOSIgaGVpZ2h0PSIxMi4zOSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTIuMDkgLTUuMDIpIHJvdGF0ZSg0NSkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgLz4NCiAgICA8Y2lyY2xlIGNsYXNzPSJjbHMtMSIgY3g9IjE1LjY0IiBjeT0iNy40MiIgcj0iMi4xOSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAvPg0KICAgIDxjaXJjbGUgY2xhc3M9ImNscy0xIiBjeD0iOC4xMSIgY3k9IjE2Ljg2IiByPSIyLjE5IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIC8\u002BDQogIDwvc3ZnPg0KPC9zdmc\u002B" + }, + "rendered": { + "light": { + "bytes": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAASFJREFUSEvlk00KgkAYhl0oqKvwBB2hncsOEEgXkY5QGyEv4An0Ap4gaNEVAlctgxYRREQL\u002B15zxJ\u002BZmgbd1AsPhtrz6nyj9ncZlQySkWVZe8dxDvj9OtVfCrnnefcwDPO\u002BSyp5lmU5QIlt2ye6tiWWuAc3qqQjB1EU5XStzo5AEWNBfAxXDnzfbxfwmBDCCOUgjuOGzDTNGx3XxKpkTgjzVs5ACd4E8/hm8FJyHlIlqnLGp5Li6YMguPL\u002BLAMKDMO4kmv8UnajXFKTv909SFWSpmmeJAlXWEdWjnWblsx0Xb/QsdiGrutyxUBWjjVr7O022JaqcgRPv2nxIKoCLJeqXBR8jWcComN98H3I26kGP4ScpSgZSs6CWQk/ol\u002BMpj0BI2D8J1UU1HoAAAAASUVORK5CYII=", + "width": 24, + "height": 24 + }, + "dark": { + "bytes": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAASFJREFUSEvlk00KgkAYhl0oqKvwBB2hncsOEEgXkY5QGyEv4An0Ap4gaNEVAlctgxYRREQL\u002B15zxJ\u002BZmgbd1AsPhtrz6nyj9ncZlQySkWVZe8dxDvj9OtVfCrnnefcwDPO\u002BSyp5lmU5QIlt2ye6tiWWuAc3qqQjB1EU5XStzo5AEWNBfAxXDnzfbxfwmBDCCOUgjuOGzDTNGx3XxKpkTgjzVs5ACd4E8/hm8FJyHlIlqnLGp5Li6YMguPL\u002BLAMKDMO4kmv8UnajXFKTv909SFWSpmmeJAlXWEdWjnWblsx0Xb/QsdiGrutyxUBWjjVr7O022JaqcgRPv2nxIKoCLJeqXBR8jWcComN98H3I26kGP4ScpSgZSs6CWQk/ol\u002BMpj0BI2D8J1UU1HoAAAAASUVORK5CYII=", + "width": 24, + "height": 24 + } + } + } } ], "libraries": [ diff --git a/src/rhino/plugin/libraries/wood_rui/globals.py b/src/rhino/plugin/libraries/wood_rui/globals.py index 90cfa6738..22f213a88 100644 --- a/src/rhino/plugin/libraries/wood_rui/globals.py +++ b/src/rhino/plugin/libraries/wood_rui/globals.py @@ -5,22 +5,23 @@ class Globals(object): _instances = {} scale = [1.0, 1.0, 1.0] # temporary parameter that must go from compas_wood.binding import wood_globals search_type = 0 # temporary parameter that must go from compas_wood.binding import wood_globals - extension = [0.0, 0.0, 0.0] # temporary parameter that must go from compas_wood.binding import wood_globals + joint_volume_extension = [0.0, 0.0, 0.0] # temporary parameter that must go from compas_wood.binding import wood_globals def __new__(cls, plugin_name="compas_wood"): """Ensure that only one instance per plugin exists.""" if plugin_name not in cls._instances: print("Creating new instance for plugin: {}".format(plugin_name)) - instance = super(Globals, cls).__new__(cls) - # Initialize the plugin-specific globals storage - instance.plugin_name = plugin_name - instance.dataset = {} - instance.init_data("default") # Call init_data on the instance - - cls._instances[plugin_name] = instance - + cls._instances[plugin_name] = super(Globals, cls).__new__(cls) return cls._instances[plugin_name] + def __init__(self, plugin_name="compas_wood"): + """Initialize the plugin-specific globals storage.""" + if not hasattr(self, 'initialized'): # Ensure initialization happens only once + self.plugin_name = plugin_name + self.dataset = {} + self.initialized = True + self.reset() + def init_data(self, name): self.dataset[name] = { @@ -39,6 +40,7 @@ def init_data(self, name): "three_valence": [], # INPUT special dataset for annen and vidy "three_valence_guid": [], "adjacency": [], # INPUT only filled for special dataset like annen, where computation time is important + "three_valence_element_indices_and_instruction": [], # INPUT special dataset for annen and vidy "planes": [], "planes_guid": [], "flags": [], @@ -70,7 +72,7 @@ def reset(self): self.init_data("default") self.scale = [1.0, 1.0, 1.0] # temporary parameter that must go from compas_wood.binding import wood_globals self.search_type = 0 # temporary parameter that must go from compas_wood.binding import wood_globals - self.extension = [ + self.joint_volume_extension = [ 0.0, 0.0, 0.0, diff --git a/src/rhino/plugin/libraries/wood_rui/object.py b/src/rhino/plugin/libraries/wood_rui/object.py index 8875e7f9b..7f258e612 100644 --- a/src/rhino/plugin/libraries/wood_rui/object.py +++ b/src/rhino/plugin/libraries/wood_rui/object.py @@ -31,7 +31,7 @@ def add_polylines(polylines: List[Rhino.Geometry.Polyline], data_name: str): layer_index = ensure_layer_exists(data_name, "polylines", Color.Red) polyline_guids = [] - for polyline in polylines: + for idx, polyline in enumerate(polylines): if polyline: obj_guid = Rhino.RhinoDoc.ActiveDoc.Objects.AddCurve(polyline.ToNurbsCurve()) if obj_guid: @@ -40,6 +40,9 @@ def add_polylines(polylines: List[Rhino.Geometry.Polyline], data_name: str): obj.Attributes.LayerIndex = layer_index obj.CommitChanges() polyline_guids.append(obj_guid) + obj.Attributes.SetUserString("element_id", str(int(idx*0.5))) + obj.Attributes.SetUserString("dataset", data_name) + obj.Attributes.SetUserString("type", "polylines") else: print(obj_guid, obj) else: @@ -63,6 +66,8 @@ def add_insertion_lines(lines, data_name): obj.Attributes.LayerIndex = layer_index obj.CommitChanges() line_guids.append(obj_guid) + obj.Attributes.SetUserString("dataset", data_name) + obj.Attributes.SetUserString("type", "insertion") if "insertion_guid" in wood_rui_globals[data_name]: delete_objects(wood_rui_globals[data_name]["insertion_guid"]) @@ -129,6 +134,8 @@ def add_joinery(joinery: List[List[Rhino.Geometry.Polyline]], data_name: str) -> obj.Attributes.LayerIndex = layer_index # Assign to the specified layer obj.CommitChanges() # Commit the changes to the object's attributes group_guids.append(obj_guid) # Collect the GUID for this polyline + obj.Attributes.SetUserString("dataset", data_name) + obj.Attributes.SetUserString("type", "joinery") # If the group contains polylines, group them together in Rhino if group_guids: