diff --git a/docs/examples/binding_beam_volumes_cross.png b/docs/examples/binding_beam_volumes_cross.png new file mode 100644 index 000000000..3d4ce04ed Binary files /dev/null and b/docs/examples/binding_beam_volumes_cross.png differ diff --git a/docs/examples/binding_beam_volumes_cross.py b/docs/examples/binding_beam_volumes_cross.py new file mode 100644 index 000000000..9cec63dec --- /dev/null +++ b/docs/examples/binding_beam_volumes_cross.py @@ -0,0 +1,77 @@ +from compas.geometry import Polyline +from compas_wood.binding import beam_volumes + + +input_polylines = [ + Polyline([ + [-5, 0, 0], + [5, 0, 0] + ]), + Polyline([ + [0, -5, 1], + [0, 5, 1] + ]), +] +input_polylines_segment_radii = [] + +for i in range(len(input_polylines)): + input_polyline_segment_radii = [] + for j in range(len(input_polylines[i].points)): + input_polyline_segment_radii.append(1) + input_polylines_segment_radii.append(input_polyline_segment_radii) + +input_polylines_segment_direction = [] + + +index_polylines, index_polylines_segment, distance, point_pairs, volume_pairs, joints_areas, joints_types = beam_volumes( + input_polylines, + input_polylines_segment_radii, + input_polylines_segment_direction, + input_min_distance=2, + input_volume_length=5 +) + +try: + from compas_viewer import Viewer + from compas.geometry import Scale + from compas.geometry import Polygon + + colors = { + 10: (255, 0, 0), # Side-to-side rotated + 11: (0, 255, 0), # Side-to-side out-of-plane + 12: (0, 0, 255), # Side-to-side in-plane + 13: (100, 100, 100), # Side-to-side in-plane + 20: (255, 0, 150), # Top-to-side + 30: (0, 200, 255) # Cross + } + + viewer = Viewer(show_grid=False, rendermode='lighted') + scale = 1e-0 + + for polyline in input_polylines: + polyline.transform(Scale.from_factors([scale, scale, scale])) + viewer.scene.add(polyline, show_points=False, lineswidth=1, linecolor=(150, 150, 150)) + + for id, p in enumerate(point_pairs): + for point in p: + point.transform(Scale.from_factors([scale, scale, scale])) + viewer.scene.add(point, size=10, pointcolor=colors[joints_types[id]]) + + for volume in volume_pairs: + for polyline in volume: + polyline.transform(Scale.from_factors([scale, scale, scale])) + + viewer.scene.add(polyline, show_points=False, lineswidth=2, linecolor=(150, 150, 150)) + + for id, joint_area in enumerate(joints_areas): + joint_area.transform(Scale.from_factors([scale, scale, scale])) + + viewer.scene.add(Polygon(joint_area.points[:-1]).to_mesh(), + show_points=False, + show_lines=False, + facecolor=colors[joints_types[id]]) + + viewer.show() + +except ImportError: + print("compas_viewer is not installed.") diff --git a/docs/examples/binding_beam_volumes_cross.rst b/docs/examples/binding_beam_volumes_cross.rst new file mode 100644 index 000000000..0c15bfcb3 --- /dev/null +++ b/docs/examples/binding_beam_volumes_cross.rst @@ -0,0 +1,13 @@ +******************************************************************************** +binding_beam_volumes_cross +******************************************************************************** + + +.. figure:: ./binding_beam_volumes_cross.png + :figclass: figure + :class: figure-img img-fluid + + +.. literalinclude:: ./binding_beam_volumes_cross.py + :language: python + diff --git a/docs/examples/binding_beam_volumes_frame.png b/docs/examples/binding_beam_volumes_frame.png new file mode 100644 index 000000000..2d59217e6 Binary files /dev/null and b/docs/examples/binding_beam_volumes_frame.png differ diff --git a/docs/examples/binding_beam_volumes_frame.py b/docs/examples/binding_beam_volumes_frame.py new file mode 100644 index 000000000..ec292ec44 --- /dev/null +++ b/docs/examples/binding_beam_volumes_frame.py @@ -0,0 +1,96 @@ +from compas.geometry import Polyline +from compas_wood.binding import beam_volumes + + +input_polylines = [ + Polyline([ + [-5, -5, 0], + [-5, 5, 0] + ]), + Polyline([ + [-5, 5, 0], + [5, 5, 0] + ]), + Polyline([ + [5, 5, 0], + [5, -5, 0] + ]), + Polyline([ + [5, -5, 0], + [-5, -5, 0] + ]), +] + + +input_polylines_segment_radii = [] + +for i in range(len(input_polylines)): + input_polyline_segment_radii = [] + for j in range(len(input_polylines[i].points)): + input_polyline_segment_radii.append(0.2) + input_polylines_segment_radii.append(input_polyline_segment_radii) + +input_polylines_segment_direction = [] +for i in range(len(input_polylines)): + input_polyline_segment_direction = [] + for j in range(len(input_polylines[i].points)-1): + input_polyline_segment_direction.append([0, 0, 1]) + input_polylines_segment_direction.append(input_polyline_segment_direction) + + +index_polylines, index_polylines_segment, distance, point_pairs, volume_pairs, joints_areas, joints_types = beam_volumes( + input_polylines, + input_polylines_segment_radii, + input_polylines_segment_direction, + input_allowed_types_per_polyline=[0], + input_min_distance=1, + input_volume_length=5, + input_cross_or_side_to_end=2.01, +) + + + +try: + from compas_viewer import Viewer + from compas.geometry import Scale + from compas.geometry import Polygon + + colors = { + 10: (255, 0, 0), # Side-to-side rotated + 11: (0, 255, 0), # Side-to-side out-of-plane + 12: (0, 0, 255), # Side-to-side in-plane + 13: (100, 100, 100), # Side-to-side in-plane + 20: (255, 0, 150), # Top-to-side + 30: (0, 200, 255) # Cross + } + + viewer = Viewer(show_grid=False, rendermode='lighted') + scale = 1e-0 + + for polyline in input_polylines: + polyline.transform(Scale.from_factors([scale, scale, scale])) + viewer.scene.add(polyline, show_points=False, lineswidth=1, linecolor=(150, 150, 150)) + + for id, p in enumerate(point_pairs): + for point in p: + point.transform(Scale.from_factors([scale, scale, scale])) + viewer.scene.add(point, size=10, pointcolor=colors[joints_types[id]]) + + for volume in volume_pairs: + for polyline in volume: + polyline.transform(Scale.from_factors([scale, scale, scale])) + + viewer.scene.add(polyline, show_points=False, lineswidth=2, linecolor=(150, 150, 150)) + + for id, joint_area in enumerate(joints_areas): + joint_area.transform(Scale.from_factors([scale, scale, scale])) + + viewer.scene.add(Polygon(joint_area.points[:-1]).to_mesh(), + show_points=False, + show_lines=False, + facecolor=colors[joints_types[id]]) + + viewer.show() + +except ImportError: + print("compas_viewer is not installed.") diff --git a/docs/examples/binding_beam_volumes_frame.rst b/docs/examples/binding_beam_volumes_frame.rst new file mode 100644 index 000000000..0dfcbb632 --- /dev/null +++ b/docs/examples/binding_beam_volumes_frame.rst @@ -0,0 +1,13 @@ +******************************************************************************** +binding_beam_volumes_frame +******************************************************************************** + + +.. figure:: ./binding_beam_volumes_frame.png + :figclass: figure + :class: figure-img img-fluid + + +.. literalinclude:: ./binding_beam_volumes_frame.py + :language: python + diff --git a/docs/examples/binding_beam_volumes_multiple.png b/docs/examples/binding_beam_volumes_multiple.png new file mode 100644 index 000000000..e5e03f373 Binary files /dev/null and b/docs/examples/binding_beam_volumes_multiple.png differ diff --git a/docs/examples/binding_beam_volumes_multiple.py b/docs/examples/binding_beam_volumes_multiple.py new file mode 100644 index 000000000..468c195ae --- /dev/null +++ b/docs/examples/binding_beam_volumes_multiple.py @@ -0,0 +1,183 @@ +from compas.geometry import Polyline +from compas_wood.binding import beam_volumes + + +input_polylines = [ + Polyline([ + [297.037012066934, 126.422271499885, -178.188030913779], + [321.489409568039, 169.111942318764, -186.869036108803], + [345.941807069144, 211.801613137642, -195.550041303827], + [370.394204570249, 254.491283956521, -204.231046498851] + ]), + Polyline([ + [182.634858082301, 98.7137182074149, -78.306080246581], + [211.235396578459, 105.640856530532, -103.27656791338], + [239.835935074617, 112.56799485365, -128.24705558018], + [268.436473570776, 119.495133176767, -153.217543246979], + [297.037012066934, 126.422271499885, -178.188030913779] + ]), + Polyline([ + [-125.19241232501, 107.875422065027, -39.2649958323028], + [-75.705277009549, 107.25372412331, -42.5192301219386], + [-26.8203151230943, 105.243836458838, -50.6895979092208], + [21.1131439030443, 102.043760643015, -63.0656900444498], + [67.9151143837992, 97.8400491497485, -78.9813305497922], + [113.521085871532, 92.7952640964856, -97.8579657684805], + [157.936920791687, 87.0452505103035, -119.213391744547], + [201.207350715535, 80.7012045875338, -142.653744283013] + ]), + Polyline([ + [-10.3599318150342, 38.7282123158674, -287.206518566188], + [-31.7764187502288, 49.1160173176098, -249.870793280387], + [-46.147480668278, 60.3975803199585, -209.510751764339], + [-54.662795188934, 72.1419219251921, -167.63145233557], + [-58.5361339307107, 84.0926783823342, -125.117457662038], + [-58.7606503977529, 96.1110401814458, -82.4406121991002], + [-56.0905042124202, 108.124674519414, -39.8417855305585], + [-51.0879024066377, 120.096820292103, 2.56039219002248], + [-44.1738209609492, 132.009588674272, 44.7113106559208], + ]), + + Polyline([ + [-188.240159298455, 75.8808592794907, -151.530383786316], + [-145.963074583616, 73.7325840014969, -160.05232439351], + [-103.685989868776, 71.5843087235031, -168.574265000704], + [-61.4089051539373, 69.4360334455093, -177.096205607898], + [-19.1318204390981, 67.2877581675155, -185.618146215092], + [23.1452642757411, 65.1394828895218, -194.140086822286], + ]), + + Polyline([ + [-96.6199846476256, 90.1021988025274, -110.227043500606], + [-48.9174102895825, 87.3983183807673, -111.648442107134], + [-1.21483593153943, 84.6944379590072, -113.069840713663], + [46.4877384265037, 81.9905575372471, -114.491239320191], + [94.1903127845467, 79.286677115487, -115.91263792672], + ]), + + Polyline([ + [132.972124919423, 138.449055887252, 86.074977722597], + [167.267793637183, 134.152861891673, 62.679797641331], + [201.563462354943, 129.856667896093, 39.2846175600651], + [235.859131072703, 125.560473900514, 15.8894374787991], + ]), + + Polyline([ + [129.410585091899, 71.8669625143157, -172.501597971961], + [151.870897769568, 83.1961266976715, -132.75167444875], + [174.331210447238, 94.5252908810273, -93.0017509255386], + [196.791523124907, 105.854455064383, -53.2518274023273], + [219.251835802577, 117.183619247739, -13.5019038791161], + [241.712148480247, 128.512783431095, 26.2480196440951], + [264.172461157916, 139.84194761445, 65.9979431673064], + ]), + + Polyline([ + [164.938767042065, 160.473718227021, 163.598974047964], + [147.837376054901, 149.074854470926, 123.488214523064], + [131.218069322568, 137.625923389656, 83.1894892076615], + [115.06311204992, 126.130413515365, 42.715559558341], + [99.3556294473208, 114.591526704951, 2.07815097714067], + [84.0795669982659, 103.012205524298, -38.7119491181474], + [69.2196466793098, 91.3951546375981, -79.6448144234582], + [54.7613339074588, 79.7428674496858, -120.71128445365], + [40.6907906778078, 68.0576389813056, -161.902917836579], + [26.9948513423117, 56.3415940716198, -203.2118916656], + ]), + + Polyline([ + [114.821035246594, 198.058111884719, 106.829580839264], + [139.879901144329, 179.26591505587, 135.214277443614], + [164.938767042065, 160.473718227021, 163.598974047964], + [189.9976329398, 141.681521398171, 191.983670652314], + [215.056498837535, 122.889324569322, 220.368367256664], + ]), + + Polyline([ + [264.172461157916, 139.84194761445, 65.9979431673064], + [312.86620413861, 146.859577749078, 57.3169379722823], + [361.559947119303, 153.877207883706, 48.6359327772582], + [410.253690099997, 160.894838018334, 39.954927582234], + ]), + + Polyline([ + [13.7562673016774, 164.804159616155, 178.132387775678], + [31.0555420852146, 160.035948344655, 140.217407062733], + [42.5288946455757, 155.666866376768, 100.123423196389], + [46.7750711952287, 151.895205966801, 58.5935066719183], + [42.9566247038049, 148.911475312983, 16.9636577178732], + [31.3140030201931, 146.81417226681, -23.2519859176756], + ]), +] + + +input_polylines_segment_radii = [] + +for i in range(len(input_polylines)): + input_polyline_segment_radii = [] + for j in range(len(input_polylines[i].points)): + input_polyline_segment_radii.append(10) + input_polylines_segment_radii.append(input_polyline_segment_radii) + +input_polylines_segment_direction = [] +for i in range(len(input_polylines)): + input_polyline_segment_direction = [] + for j in range(len(input_polylines[i].points)-1): + input_polyline_segment_direction.append([0, 1, 0]) + input_polylines_segment_direction.append(input_polyline_segment_direction) + + +index_polylines, index_polylines_segment, distance, point_pairs, volume_pairs, joints_areas, joints_types = beam_volumes( + input_polylines, + input_polylines_segment_radii, + input_polylines_segment_direction, + input_allowed_types_per_polyline=[-1], + input_min_distance=20, + input_volume_length=75, + input_cross_or_side_to_end=0.91, +) + +try: + from compas_viewer import Viewer + from compas.geometry import Scale + from compas.geometry import Polygon + + colors = { + 10: (255, 0, 0), # Side-to-side rotated + 11: (0, 255, 0), # Side-to-side out-of-plane + 12: (0, 0, 255), # Side-to-side in-plane + 13: (100, 100, 100), # Side-to-side in-plane + 20: (255, 0, 150), # Top-to-side + 30: (0, 200, 255) # Cross + } + + viewer = Viewer(show_grid=False, rendermode='lighted') + scale = 1e-2 + + for polyline in input_polylines: + polyline.transform(Scale.from_factors([scale, scale, scale])) + viewer.scene.add(polyline, show_points=False, lineswidth=1, linecolor=(150, 150, 150)) + + for id, p in enumerate(point_pairs): + for point in p: + point.transform(Scale.from_factors([scale, scale, scale])) + viewer.scene.add(point, size=10, pointcolor=colors[joints_types[id]]) + + for volume in volume_pairs: + for polyline in volume: + polyline.transform(Scale.from_factors([scale, scale, scale])) + + viewer.scene.add(polyline, show_points=False, lineswidth=2, linecolor=(150, 150, 150)) + + for id, joint_area in enumerate(joints_areas): + joint_area.transform(Scale.from_factors([scale, scale, scale])) + + viewer.scene.add(Polygon(joint_area.points[:-1]).to_mesh(), + show_points=False, + show_lines=False, + facecolor=colors[joints_types[id]]) + + viewer.show() + +except ImportError: + print("compas_viewer is not installed.") \ No newline at end of file diff --git a/docs/examples/binding_beam_volumes_multiple.rst b/docs/examples/binding_beam_volumes_multiple.rst new file mode 100644 index 000000000..c8e376cba --- /dev/null +++ b/docs/examples/binding_beam_volumes_multiple.rst @@ -0,0 +1,13 @@ +******************************************************************************** +binding_beam_volumes_multiple +******************************************************************************** + + +.. figure:: ./binding_beam_volumes_multiple.png + :figclass: figure + :class: figure-img img-fluid + + +.. literalinclude:: ./binding_beam_volumes_multiple.py + :language: python + diff --git a/docs/examples/binding_beam_volumes_side.png b/docs/examples/binding_beam_volumes_side.png new file mode 100644 index 000000000..7fec5de68 Binary files /dev/null and b/docs/examples/binding_beam_volumes_side.png differ diff --git a/docs/examples/binding_beam_volumes_side.py b/docs/examples/binding_beam_volumes_side.py new file mode 100644 index 000000000..6d4b7eb20 --- /dev/null +++ b/docs/examples/binding_beam_volumes_side.py @@ -0,0 +1,79 @@ +from compas.geometry import Polyline +from compas_wood.binding import beam_volumes + + +input_polylines = [ + Polyline([ + [-5, 0, 0], + [5, 0, 0] + ]), + Polyline([ + [0, -5, 1], + [0, 5, 1] + ]), +] +input_polylines_segment_radii = [] + +for i in range(len(input_polylines)): + input_polyline_segment_radii = [] + for j in range(len(input_polylines[i].points)): + input_polyline_segment_radii.append(1) + input_polylines_segment_radii.append(input_polyline_segment_radii) + +input_polylines_segment_direction = [] + + +index_polylines, index_polylines_segment, distance, point_pairs, volume_pairs, joints_areas, joints_types = beam_volumes( + input_polylines, + input_polylines_segment_radii, + input_polylines_segment_direction, + input_allowed_types_per_polyline=[-1], + input_min_distance=2, + input_volume_length=5, + input_cross_or_side_to_end=1.01, +) + +try: + from compas_viewer import Viewer + from compas.geometry import Scale + from compas.geometry import Polygon + + colors = { + 10: (255, 0, 0), # Side-to-side rotated + 11: (0, 255, 0), # Side-to-side out-of-plane + 12: (0, 0, 255), # Side-to-side in-plane + 13: (100, 100, 100), # Side-to-side in-plane + 20: (255, 0, 150), # Top-to-side + 30: (0, 200, 255) # Cross + } + + viewer = Viewer(show_grid=False, rendermode='lighted') + scale = 1e-0 + + for polyline in input_polylines: + polyline.transform(Scale.from_factors([scale, scale, scale])) + viewer.scene.add(polyline, show_points=False, lineswidth=1, linecolor=(150, 150, 150)) + + for id, p in enumerate(point_pairs): + for point in p: + point.transform(Scale.from_factors([scale, scale, scale])) + viewer.scene.add(point, size=10, pointcolor=colors[joints_types[id]]) + + for volume in volume_pairs: + for polyline in volume: + polyline.transform(Scale.from_factors([scale, scale, scale])) + + viewer.scene.add(polyline, show_points=False, lineswidth=2, linecolor=(150, 150, 150)) + + for id, joint_area in enumerate(joints_areas): + joint_area.transform(Scale.from_factors([scale, scale, scale])) + + viewer.scene.add(Polygon(joint_area.points[:-1]).to_mesh(), + show_points=False, + show_lines=False, + facecolor=colors[joints_types[id]]) + + viewer.show() + +except ImportError: + print("compas_viewer is not installed.") diff --git a/docs/examples/binding_beam_volumes_side.rst b/docs/examples/binding_beam_volumes_side.rst new file mode 100644 index 000000000..451a49b00 --- /dev/null +++ b/docs/examples/binding_beam_volumes_side.rst @@ -0,0 +1,13 @@ +******************************************************************************** +binding_beam_volumes_side +******************************************************************************** + + +.. figure:: ./binding_beam_volumes_side.png + :figclass: figure + :class: figure-img img-fluid + + +.. literalinclude:: ./binding_beam_volumes_side.py + :language: python + diff --git a/docs/examples/binding_read_xml_polylines.py b/docs/examples/binding_read_xml_polylines.py index 2a7ff8b60..91a02f87e 100644 --- a/docs/examples/binding_read_xml_polylines.py +++ b/docs/examples/binding_read_xml_polylines.py @@ -1,17 +1,31 @@ from compas_wood.binding import read_xml_polylines +import compas_wood +import os +dataset_index = 3 +module_path = os.path.dirname(compas_wood.__file__) +foldername = os.path.join(module_path, "datasets") +foldername = os.path.join(module_path, "datasets") + os.sep +files = os.listdir(foldername) +file_names_without_extensions = [os.path.splitext(file)[0] for file in files] +filename = file_names_without_extensions[dataset_index % len(file_names_without_extensions)] -polylines = read_xml_polylines() +polylines = read_xml_polylines(foldername, filename) try: - + from compas_viewer import Viewer + from compas.geometry import Scale + + scale = 1e-2 + xform = Scale.from_factors([scale, scale, scale]) viewer = Viewer() for polyline in polylines: + polyline.transform(xform) viewer.scene.add(polyline, show_points=False) viewer.show() diff --git a/docs/examples/binding_read_xml_polylines_and_properties.py b/docs/examples/binding_read_xml_polylines_and_properties.py index 860bc8f76..640f92e8d 100644 --- a/docs/examples/binding_read_xml_polylines_and_properties.py +++ b/docs/examples/binding_read_xml_polylines_and_properties.py @@ -1,5 +1,17 @@ from compas_wood.binding import read_xml_polylines_and_properties from compas.geometry import Line +import compas_wood +import os + +dataset_index = 0 +module_path = os.path.dirname(compas_wood.__file__) +foldername = os.path.join(module_path, "datasets") +foldername = os.path.join(module_path, "datasets") + os.sep +files = os.listdir(foldername) + +file_names_without_extensions = [os.path.splitext(file)[0] for file in files] +filename = file_names_without_extensions[dataset_index % len(file_names_without_extensions)] +filename = "type_plates_name_top_to_side_and_side_to_side_outofplane_annen_grid_small" ( @@ -8,9 +20,10 @@ input_joints_types, input_three_valence_element_indices_and_instruction, input_adjacency, -) = read_xml_polylines_and_properties() - +) = read_xml_polylines_and_properties(foldername, filename) +print("vectors_lists:", vectors_lists) +print(filename) try: diff --git a/src/compas_wood/binding/__init__.py b/src/compas_wood/binding/__init__.py index d5458e046..ef62b9aee 100644 --- a/src/compas_wood/binding/__init__.py +++ b/src/compas_wood/binding/__init__.py @@ -7,6 +7,7 @@ from .binding_closed_mesh_from_polylines import closed_mesh_from_polylines from .binding_joints import joints from .binding_mesh_boolean_difference_from_polylines import mesh_boolean_difference_from_polylines +from .binding_beam_volumes import beam_volumes __all__ = [ "wood_globals", @@ -19,4 +20,5 @@ "closed_mesh_from_polylines", "joints", "mesh_boolean_difference_from_polylines", + "beam_volumes", ] diff --git a/src/compas_wood/binding/binding_beam_volumes.py b/src/compas_wood/binding/binding_beam_volumes.py new file mode 100644 index 000000000..ace4fd486 --- /dev/null +++ b/src/compas_wood/binding/binding_beam_volumes.py @@ -0,0 +1,80 @@ +from wood_nano import beam_volumes as wood_nano_beam_volumes +from compas_wood.conversions_compas import to_point2 +from compas_wood.conversions_compas import to_vector2 +from compas_wood.conversions_compas import from_point2 +from compas_wood.conversions_compas import from_point3 +from wood_nano.conversions_python import to_double2 +from wood_nano.conversions_python import to_int1 +from wood_nano.conversions_python import from_int1 +from wood_nano.conversions_python import from_int2 +from wood_nano.conversions_python import from_double2 +from wood_nano import int1 +from wood_nano import int2 +from wood_nano import double2 +from wood_nano import point2 +from wood_nano import point3 +from wood_nano import cut_type2 + +# from wood_nano.conversions_python import from_cut_type2 + + +def beam_volumes( + input_polyline_axes, + input_polylines_segment_radii, + input_polylines_segment_direction, + input_allowed_types_per_polyline=[1], + input_min_distance=50, + input_volume_length=500, + input_cross_or_side_to_end=0.91, + input_flip_male=1, + input_compute_joints=False, + input_division_distance=150, + input_shift=0.5, + input_output_geometry_type=0, + input_use_eccentricities_to_scale_joints=True, +): + + index_polylines = int2() + index_polylines_segment = int2() + distance = double2() + point_pairs = point2() + volume_pairs = point3() + joints_areas = point2() + joints_types = int1() + w_output_plines = point3() + w_output_types = cut_type2() + + wood_nano_beam_volumes( + to_point2(input_polyline_axes), + to_double2(input_polylines_segment_radii), + to_vector2(input_polylines_segment_direction), + to_int1(input_allowed_types_per_polyline), + float(input_min_distance), + float(input_volume_length), + float(input_cross_or_side_to_end), + int(input_flip_male), + index_polylines, # out + index_polylines_segment, # out + distance, # out + point_pairs, # out + volume_pairs, # out + joints_areas, # out + joints_types, # out + w_output_plines, # from_point3(w_output_plines) + w_output_types, # from_cut_type2(w_output_types)) + input_compute_joints, + input_division_distance, + input_shift, + input_output_geometry_type, + input_use_eccentricities_to_scale_joints, + ) + + return ( + from_int2(index_polylines), + from_int2(index_polylines_segment), + from_double2(distance), + from_point2(point_pairs), + from_point3(volume_pairs), + from_point2(joints_areas), + from_int1(joints_types), + ) diff --git a/src/compas_wood/binding/binding_get_connection_zones.py b/src/compas_wood/binding/binding_get_connection_zones.py index c9042f507..b34219127 100644 --- a/src/compas_wood/binding/binding_get_connection_zones.py +++ b/src/compas_wood/binding/binding_get_connection_zones.py @@ -90,8 +90,6 @@ def get_connection_zones( w_output_plines, w_output_types, to_double1(input_joint_volume_parameters), - to_point2(input_custom_joints), - to_int1(input_custom_joints_types), ) return from_point3(w_output_plines), from_cut_type2(w_output_types) diff --git a/src/compas_wood/binding/binding_globals.py b/src/compas_wood/binding/binding_globals.py index c119048f0..2f027f23d 100644 --- a/src/compas_wood/binding/binding_globals.py +++ b/src/compas_wood/binding/binding_globals.py @@ -1,7 +1,7 @@ from wood_nano import GLOBALS -class Globals: +class Globals(object): """Class to access global variables of the wood_nano library using class instance wood_globals: >>> from compas_wood.binding import wood_globals @@ -90,6 +90,13 @@ class Globals: """ + def __new__(cls): + + if not hasattr(cls, "instance"): + cls.instance = super(Globals, cls).__new__(cls) + + return cls.instance + @property def clipper_scale(cls): return GLOBALS.CLIPPER_SCALE diff --git a/src/compas_wood/binding/binding_read_xml_polylines_and_properties.py b/src/compas_wood/binding/binding_read_xml_polylines_and_properties.py index a621e111d..944f9e6c3 100644 --- a/src/compas_wood/binding/binding_read_xml_polylines_and_properties.py +++ b/src/compas_wood/binding/binding_read_xml_polylines_and_properties.py @@ -12,7 +12,7 @@ def read_xml_polylines_and_properties( foldername="/home/petras/brg/2_code/wood_nano/src/wood/cmake/src/wood/dataset/", - filename_of_dataset="type_plates_name_cross_vda_hexshell_reciprocal", + filename_of_dataset="type_plates_name_top_to_side_and_side_to_side_outofplane_annen_grid_small", scale=1e-2, ): """Read polylines from XML file with attributes: @@ -56,8 +56,8 @@ def read_xml_polylines_and_properties( input_adjacency = int1() wood_nano_read_xml_polylines_and_properties( - "/home/petras/brg/2_code/wood_nano/src/wood/cmake/src/wood/dataset/", - "type_plates_name_top_to_side_and_side_to_side_outofplane_annen_grid_small", + foldername, + filename_of_dataset, input_polyline_pairs_coord, input_insertion_vectors_coord, input_joints_types, diff --git a/src/rhino/gh/componentize_cpy.py b/src/rhino/gh/componentize_cpy.py index 54874469b..5cdde3b91 100644 --- a/src/rhino/gh/componentize_cpy.py +++ b/src/rhino/gh/componentize_cpy.py @@ -5,7 +5,9 @@ import re import sys import tempfile -import urllib.request, urllib.parse, urllib.error +import urllib.request +import urllib.parse +import urllib.error import zipfile from io import BytesIO @@ -119,7 +121,7 @@ def validate_source_bundle(source): if data["exposure"] not in EXPOSURE["valid"]: raise ValueError("Invalid exposure value. Accepted values are {}".format(sorted(EXPOSURE["valid"]))) - ghpython = data.get("ghpython") + ghpython = data.get("ghpython") # noqa: F841 if r'"""' not in python_code: python_code = r'"""{}"""{}{}'.format( diff --git a/src/rhino/gh/cpy/assembly/code.py b/src/rhino/gh/cpy/assembly/code.py index 145e7fbd5..c0287abd2 100644 --- a/src/rhino/gh/cpy/assembly/code.py +++ b/src/rhino/gh/cpy/assembly/code.py @@ -1,4 +1,5 @@ """display assembly sequence""" + __author__ = "petras" __version__ = "2023.04.02" diff --git a/src/rhino/gh/cpy/assembly_solids/code.py b/src/rhino/gh/cpy/assembly_solids/code.py index 7e94c65f2..7d1862947 100644 --- a/src/rhino/gh/cpy/assembly_solids/code.py +++ b/src/rhino/gh/cpy/assembly_solids/code.py @@ -1,23 +1,14 @@ """display assembly sequence""" + __author__ = "petras" __version__ = "2023.04.13" from ghpythonlib.componentbase import executingcomponent as component -import Grasshopper, GhPython import System import Rhino -import rhinoscriptsyntax as rs - - -import rhinoscriptsyntax as rs -import Rhino.Geometry as rg from Rhino.Geometry import BoundingBox from Rhino.Geometry import Point3d -from Rhino.Geometry import Plane -from Rhino.Geometry import Polyline -from Rhino.Geometry import Vector3d from Rhino.Geometry import Line -from Rhino.Geometry import TextEntity from Rhino.Geometry import Transform from System.Drawing import Color import math @@ -48,9 +39,6 @@ def get_ClippingBox(self): def display_insersion_sequence(self, _geos, _lines, _t): - text_size = 50 - line_scale = 300 - ############################################################################### # input ############################################################################### diff --git a/src/rhino/gh/cpy/beam_volume/code.py b/src/rhino/gh/cpy/beam_volume/code.py index b162402bb..e09a64510 100644 --- a/src/rhino/gh/cpy/beam_volume/code.py +++ b/src/rhino/gh/cpy/beam_volume/code.py @@ -1,1748 +1,61 @@ -from ghpythonlib.componentbase import executingcomponent as component -import Grasshopper, GhPython -import System -import rhinoscriptsyntax as rs - -import Rhino -from Rhino.Geometry import ( - Point3d, - Vector3d, - Polyline, - Curve, - Line, - Plane, - Brep, - BoundingBox, - Interval, - RTree, - Transform, - Rectangle3d, -) -from collections import OrderedDict -from Grasshopper import DataTree -from Grasshopper.Kernel.Data import GH_Path -import math -from System.Collections.Generic import SortedDictionary - - -class MyComponent(component): - def RunScript( - self, - _circles: Grasshopper.DataTree[Rhino.Geometry.Circle], - _length_of_box: float, - _distance_tolerance: float, - _parallel_tolerance: float, - _cross_or_toptoside: bool, - _create_pipes: bool, - ): - class Cut: - pass - - class OutlineType: - Top = 1 - Side = 2 - Center = 9 - Unset = 777 - - class Outline: - def __init__(self, pline=None, name=None, outline=None): - - self.plines = [] - self.plane = Plane.Unset - self.name = OutlineType.Unset - self.bbox = BoundingBox.Unset - self.tileNames = None - - if pline is not None and name is not None: - - if self.is_list_of_polylines(pline): - for current_pline in pline: - self.plines.append(Polyline(current_pline)) - else: - self.plines = [Polyline(pline)] - - self.plane = self.GetPlane(self.plines[0]) - self.name = name - self.bbox = self.plines[0].BoundingBox - self.bbox.Inflate(0.02) - - elif outline is not None and name is not None: - - self.plines = outline.Duplicate() - self.plane = self.GetPlane(outline[0]) - self.name = name - self.bbox = BoundingBox() - for polyline in outline: - self.bbox.Union(polyline.BoundingBox) - self.bbox.Inflate(0.02) - - def is_list_of_polylines(self, obj): - if isinstance(obj, list): - if all(isinstance(item, Polyline) for item in obj): - return True - - def AverageNormal(self, p): - - count = p.Count - 1 - vector3d = Vector3d(0, 0, 0) - num = count - 1 - - for i in range(num + 1): - num1 = (i - 1 + count) % count - num2 = (i + 1 + count) % count - item = p[num1] - point3d = p[num2] - item1 = p[i] - vector3d += Vector3d.CrossProduct(Vector3d(item1 - item), Vector3d(point3d - item1)) - - if vector3d.X == 0 and vector3d.Y == 0 and vector3d.Z == 0: - vector3d.Unitize() - - return vector3d - - def GetPlane(self, polyline, AveragePlane=True): - plane = Plane.Unset - if not AveragePlane: - Plane.FitPlaneToPoints(polyline, plane) - plane.Origin = polyline.CenterPoint() - return plane - - line = polyline.SegmentAt(0) - vector3d = line.Direction - vector3d.Unitize() - vector3d1 = self.AverageNormal(polyline) - vector3d1.Unitize() - vector3d2 = Vector3d.CrossProduct(vector3d, vector3d1) - return Plane(polyline.CenterPoint(), vector3d, vector3d2) - - def FlipAndRotate(self, p): - plane = Plane(p) - plane.Flip() - plane.Rotate(1.5707963267949, plane.ZAxis) - return plane - - def IsClockwiseClosedPolyline(self, p, plane): - polyline = Polyline(p) - world_xy = Rhino.Geometry.Plane.WorldXY - plane_to_world_xy = Rhino.Geometry.Transform.PlaneToPlane(plane, world_xy) - polyline.Transform(plane_to_world_xy) - y = 0 - for i in range(len(polyline) - 1): - item = polyline[i + 1] - x = item.X - item = polyline[i] - num = x - item.X - item = polyline[i + 1] - y1 = item.Y - item = polyline[i] - y += num * (y1 + item.Y) - return y > 0 - - def CheckPolygonOrientation(self, optionalOutline): - for i in range(len(self.plines)): - if i == 0: - if self.IsClockwiseClosedPolyline(self.plines[i], self.plane): - self.plines[i].Reverse() - optionalOutline.plines[i].Reverse() - else: - if not self.IsClockwiseClosedPolyline(self.plines[i], self.plane): - self.plines[i].Reverse() - optionalOutline.plines[i].Reverse() - - def Duplicate(self): - outline = Outline() - outline.bbox = self.bbox - outline.plines = [] - for i in self.plines: - outline.plines.append(i.Duplicate()) - outline.plane = Plane(self.plane) - outline.name = self.name - if self.tileNames is None: - outline.tileNames = None - else: - outline.tileNames = [name for name in self.tileNames] - return outline - - def FlipPlane(self, optionalOutline): - self.plane = self.FlipAndRotate(self.plane) - optionalOutline.plane = self.FlipAndRotate(optionalOutline.plane) - - def Transform(self, xform): - for i in range(len(self.plines)): - self.plines[i].Transform(xform) - self.plane.Transform(xform) - self.bbox.Transform(xform) - - class Beam: - - id = None - id2 = -1 - centreCurve = None - centrePline = None - frames = [] - radii = [] - samples = 5 - circles = [] - polygons = [] - cuts = [] - jointsID = [] - endCuts = True - debug = [] - - @property - def GetMidPt(self): - t0 = curve.Domain.T0 - domain = curve.Domain - return self.centreCurve.PointAt((t0 + domain.T1) * 0.5) - - def __getitem__(self, index): - if index == 0: - return self.centreCurve.PointAtStart - return self.centreCurve.PointAtEnd - - def __init__(self, id, centrePline, radii, adjustDirection_, planes=None, samples_=20, rebuild=False): - plane = Plane.Unset - num = 0 - point3dArray = None - self.id = id - self.centreCurve = Curve.CreateInterpolatedCurve( - centrePline, 3, Rhino.Geometry.CurveKnotStyle.ChordPeriodic - ) - self.centrePline = centrePline - self.radii = [] - self.frames = [] - if planes is not None and len(planes) != 0: - for i in range(len(planes)): - self.centreCurve.ClosestPoint(planes[i].Origin, num) - self.frames.append((num, planes[i])) - self.radii = list(radii) - elif not self.centreCurve.IsPlanar(): - curve = self.centreCurve - domain = self.centreCurve.Domain - plane1 = curve.GetPlane(domain.T0, False) - planes = [plane1] - self.frames.append((self.centreCurve.Domain.T0, plane1)) - self.radii = list(radii) - else: - self.centreCurve.TryGetPlane(plane) - plane2 = Plane( - self.centreCurve.PointAtStart(), - plane.ZAxis, - Vector3d.CrossProduct(self.centreCurve.TangentAtStart, plane.ZAxis), - ) - plane3 = Plane( - self.centreCurve.PointAtEnd(), - plane.ZAxis, - Vector3d.CrossProduct(self.centreCurve.TangentAtEnd, plane.ZAxis), - ) - self.frames.append((self.centreCurve.Domain.T0, plane2)) - self.frames.append((self.centreCurve.Domain.T1, plane3)) - self.radii = list(radii) - if len(radii) == len(centrePline): - self.radii.clear() - self.centreCurve.DivideByCount(self.samples - 1, True, point3dArray) - for j in range(len(point3dArray)): - num1 = centrePline.ClosestParameter(point3dArray[j]) - num2 = MathUtil.RemapNumbers( - num1 % 1, 0, 1, radii[int(Math.Floor(num1))], radii[int(Math.Ceiling(num1))] - ) - self.radii.append(num2) - self.SortFrames() - self.frames = self.RecalculateFrames(self.centreCurve, self.frames) - self.circles = [] - self.polygons = [] - self.cuts = [] - self.jointsID = [] - if adjustDirection_ != Line.Unset: - plane4 = self.centreCurve.GetPlane(self.frames, adjustDirection_.get_From()) - num3 = Vector3d.VectorAngle(plane4.get_XAxis(), adjustDirection_.get_Direction(), plane4) - for k in range(len(self.frames)): - item2 = self.frames[k][1] - item2.Rotate(num3, plane4.get_ZAxis()) - self.frames[k] = (self.frames[k][0], item2) - - def RecalculateFrames(self, centreCurve, frames): - frames_updated = [] - for i in range(len(frames)): - point3d = centreCurve.PointAt(frames[i][0]) - vector3d = centreCurve.TangentAt(frames[i][0]) - item2 = frames[i][1] - vector3d1 = Vector3d.CrossProduct(item2.YAxis, vector3d) - vector3d2 = Vector3d.CrossProduct(vector3d, vector3d1) - frames_updated.append((frames[i][0], Plane(point3d, vector3d1, vector3d2))) - return frames_updated - - def AdjustPlanes(self, l): - plane = self.GetPlane(l.From) - num = rg.Vector3d.VectorAngle(plane.XAxis, l.Direction, plane) - for i in range(len(self.frames)): - item2 = self.frames[i].Item2 - item2.Rotate(num, plane.ZAxis) - self.frames[i] = rg.Tuple(self.frames[i].Item1, item2) - - def CreateBeamCircles(self, rebuild=False): - return self.centreCurve.CreateBeamCircles( - self.radii, self.frames, self.samples, rebuild, self.samples, 1, 1 - ) - - def CreateBeamLoft(self): - return rg.Brep.CreatePipe(self.centreCurve, self.frames, self.radii) - - def Duplicate(self): - beam = Beam() - beam.id = self.id - beam.id2 = self.id2 - beam.centreCurve = self.centreCurve.DuplicateCurve() - beam.centrePline = self.centrePline.Duplicate() - beam.frames = [rg.Tuple(frame.Item1, rg.Plane(frame.Item2)) for frame in self.frames] - beam.radii = self.radii[:] - beam.samples = self.samples - beam.circles = [rg.Circle(rg.Plane(circle.Plane), circle.Radius) for circle in self.circles] - beam.polygons = [rg.Polyline(polygon) for polygon in self.polygons] - beam.cuts = [cut.Duplicate() for cut in self.cuts] - beam.jointsID = self.jointsID[:] - beam.endCuts = self.endCuts - return beam - - def BoundingBox(self, crvs, inflate=0.001): - boundingBox = crvs[0].GetBoundingBox(False) - for crv in crvs: - boundingBox.Union(crv.GetBoundingBox(True)) - boundingBox.Inflate(inflate) - return boundingBox - - def GetBoundingBox(self, inflate=0.001): - return self.BoundingBox(self.OffsetCurve4(False), inflate) - - def GetCP(self, p): - return self.centreCurve.TCP(p) - - def GetEndPlanes(self): - domain = self.centreCurve.Domain - plane1 = self.GetPlane(domain.T0) - domain = self.centreCurve.Domain - plane2 = self.GetPlane(domain.T1) - return rg.Tuple(plane1, plane2) - - def TCP(self, curve, p): - result, num = curve.ClosestPoint(p) - return num - - def TXAB(self, curve, valueFromAToB): - min = curve.Domain.Min - domain = curve.Domain - return self.RemapNumbers(valueFromAToB, min, domain.Max, 0, 1) - - def GetInterpolatedRadius_by_parameter(self, t): - return self.Interpolate(self.radii, self.TXAB(self.centreCurve, t)) - - def GetInterpolatedRadius_by_point(self, p): - - return self.Interpolate(self.radii, self.TCP(self.centreCurve, p)) - - def GetMidPlane(self): - domain = self.centreCurve.Domain - return self.GetPlane(domain.Mid) - - def GetP(self, t): - return self.centreCurve.PointAt(t) - - def GetParameters(self): - nums = [] - for frame in self.frames: - nums.append(frame.Item1) - return nums - - def GetPlane_by_point(self, centerCurve, frames, p): - - result, num = centerCurve.ClosestPoint(p) - tuple = self.FramesAround(centerCurve, frames, num) - plane = self.InterpolatePlanes(tuple[0], tuple[1], tuple[2]) - plane.Origin = centerCurve.PointAt(num) - plane.Transform(Transform.Rotation(plane.ZAxis, centerCurve.TangentAt(num), plane.Origin)) - return plane - - def GetPlane_by_parameter(self, centerCurve, frames, t): - tuple = self.FramesAround(centerCurve, frames, t) - plane = self.InterpolatePlanes(tuple[0], tuple[1], tuple[2]) - plane.Origin = centerCurve.PointAt(t) - plane.Transform(Transform.Rotation(plane.ZAxis, centerCurve.TangentAt(t), plane.Origin)) - return plane - - def GetPlane_by_p(self, p): - return self.GetPlane_by_point(self.centreCurve, self.frames, p) - - def GetPlane_by_t(self, t): - return self.GetPlane_by_parameter(self.centreCurve, self.frames, t) - - def OrientPlaneTowardsCurveShorterEnd(self, curve, plane, t): - - # print(message) - plane1 = Plane(plane) - - # which side is shorter - p = curve.PointAt(t) - copy_curve = curve.Duplicate() - copy_curve = copy_curve.Extend( - Rhino.Geometry.CurveEnd.Both, - copy_curve.GetLength(0.01) * 0.1, - Rhino.Geometry.CurveExtensionStyle.Smooth, - ) - copy_curve.Domain = Interval(0, 1) - - result, cpt = copy_curve.ClosestPoint(p) - - domain0 = Interval(copy_curve.Domain.T0, cpt) - domain1 = Interval(cpt, copy_curve.Domain.T1) - - # get middle point of that side - orientation_point = copy_curve.PointAt(domain0.Mid) - if domain1.Length > domain0.Length: - orientation_point = copy_curve.PointAt(domain1.Mid) - - # orient the plane based on the distance search - distance = plane.DistanceTo(orientation_point) - # print(distance) - - # Rhino.RhinoDoc.ActiveDoc.Objects.AddPoint(orientation_point) - if distance > 0: - plane1 = self.FlipAndRotate(plane1) - - return plane1 - - def GetPlaneOrientedToShorterSide_by_t(self, t): - plane = self.GetPlane_by_parameter(self.centreCurve, self.frames, t) - return self.OrientPlaneTowardsCurveShorterEnd(self.centreCurve, plane, t) - - def GetPlaneOrientedToShorterSide_by_p(self, p): - plane = self.GetPlane_by_point(self.centreCurve, self.frames, p) - cp = self.GetCP(p) - return self.OrientPlaneTowardsCurveShorterEnd(self.centreCurve, plane, cp) - - def GetPlanes(self): - planes = [] - for frame in self.frames: - planes.append(frame.Item2) - return planes - - def GetSidePlanes(self, t, XZ_YZ=True): - return self.centreCurve.GetSidePlanes(self.frames, self.radii, t, XZ_YZ) - - def GetXAxis(self, p): - plane = self.GetPlane_by_point(self.centreCurve, self.frames, p) - return plane.XAxis - - def GetXAxis(self, t): - plane = self.GetPlane_by_parameter(self.centreCurve, self.frames, t) - return plane.XAxis - - def GetYAxis(self, p): - plane = self.GetPlane_by_point(self.centreCurve, self.frames, p) - return plane.YAxis - - def GetYAxis(self, t): - plane = self.GetPlane_by_parameter(self.centreCurve, self.frames, t) - return plane.YAxis - - def GetZAxis(self, p): - plane = self.GetPlane_by_point(self.centreCurve, self.frames, p) - return plane.ZAxis - - def GetZAxis(self, t): - plane = self.GetPlane_by_parameter(self.centreCurve, self.frames, t) - return plane.ZAxis - - def RemapNumbers(self, speed=50, low1=0, high1=2000, low2=0, high2=1): - return low2 + (speed - low1) * (high2 - low2) / (high1 - low1) - - def Interpolate(self, values, parameter): - def SampleLinear(v0, v1, t): - return v0 * (1 - t) + v1 * t - - count = len(values) - 1 - num2 = parameter * count - num3 = int(math.floor(num2)) - if num3 < 0: - item = values[0] - elif num3 >= count: - item = values[count] - else: - item3 = values[num3] - item4 = values[num3 + 1] - item = SampleLinear(item3, item4, num2 - num3) - return item - - def FramesAround(self, centerCurve, frames, t): - if len(frames) < 1: - return None - num = 0 - num1 = 1 - count = len(frames) - 1 - if t <= frames[0][0]: - return (frames[0][1], frames[0][1], 0) - if t > frames[count][0]: - return (frames[count][1], frames[count][1], 1) - num2 = 1 - while num2 < len(frames): - if frames[num2][0] < t: - num2 += 1 - else: - num1 = num2 - break - num = (t - frames[num1 - 1][0]) / (frames[num1][0] - frames[num1 - 1][0]) - return (frames[num1 - 1][1], frames[num1][1], num) - - def InterpolatePlanes(self, A, B, t): - origin = self.Lerp(A.Origin, B.Origin, t) - xAxis = self.Lerp(A.XAxis, B.XAxis, t) - yAxis = self.Lerp(A.YAxis, B.YAxis, t) - return Plane(origin, xAxis, yAxis) - - def Lerp(self, vA, vB, t): - return vA + (t * (vB - vA)) - - def GetPlane_CreateOffsetCurve(self, centerCurve, frames, t): - tuple = self.FramesAround(centerCurve, frames, t) - plane = self.InterpolatePlanes(tuple[0], tuple[1], tuple[2]) - plane.Origin = centerCurve.PointAt(t) - plane.Transform(Transform.Rotation(plane.ZAxis, centerCurve.TangentAt(t), plane.Origin)) - return plane - - def FlipAndRotate(self, p): - plane = Plane(p) - plane.Flip() - plane.Rotate(1.5707963267949, plane.ZAxis) - return plane - - def CreateOffsetCurve( - self, centreCurve, radii, frames, samples, rebuild=False, rebuild_pts=20, signX=1, signY=1 - ): - point3ds = [] - numArray = centreCurve.DivideByCount(samples, True) - for i in range(len(numArray)): - num = self.RemapNumbers(numArray[i], 0, numArray[-1], 0, 1) - num1 = self.Interpolate(radii, num) - plane = self.GetPlane_CreateOffsetCurve(centreCurve, frames, numArray[i]) - point3ds.append( - (plane.Origin + (plane.XAxis * float(signX) * num1)) + (plane.YAxis * float(signY) * num1) - ) - - curve = Rhino.Geometry.Curve.CreateInterpolatedCurve( - point3ds, - 3, - Rhino.Geometry.CurveKnotStyle.Uniform, - centreCurve.TangentAtStart, - centreCurve.TangentAtEnd, - ) - if curve is None: - raise Exception("FreeformGlulam::CreateOffsetCurve:: Failed to create interpolated curve!") - curve.Domain = Interval(0, curve.GetLength()) - if rebuild: - curve = curve.Rebuild(rebuild_pts, curve.Degree, True) - return curve - - """ - def CreateOffsetCurve(self, centreCurve, frames, samples, x, y, rebuild=False, rebuild_pts=20): - point3ds = [] - numArray = centreCurve.DivideByCount(samples, True) - for i in range(len(numArray)): - plane = centreCurve.GetPlane(frames, numArray[i]) - point3ds.append((plane.Origin + (plane.XAxis * x)) + (plane.YAxis * y)) - curve = rg.Curve.CreateInterpolatedCurve(point3ds, 3, 0, centreCurve.TangentAtStart, centreCurve.TangentAtEnd) - if curve is None: - raise Exception("FreeformGlulam::CreateOffsetCurve:: Failed to create interpolated curve!") - curve.Domain = rg.Interval(0, curve.GetLength()) - if rebuild: - curve = curve.Rebuild(rebuild_pts, curve.Degree, True) - return curve - """ - - def CreateOffsetCurve4(self, centreCurve, radii, frames, samples, rebuild=False, rebuild_pts=20): - curve1 = self.CreateOffsetCurve(self.centreCurve, radii, frames, samples, rebuild, rebuild_pts, 1, 1) - curve2 = self.CreateOffsetCurve(self.centreCurve, radii, frames, samples, rebuild, rebuild_pts, -1, 1) - curve3 = self.CreateOffsetCurve(self.centreCurve, radii, frames, samples, rebuild, rebuild_pts, -1, -1) - curve4 = self.CreateOffsetCurve(self.centreCurve, radii, frames, samples, rebuild, rebuild_pts, 1, -1) - return [curve1, curve2, curve3, curve4] - - def OffsetCurve(self, x, y, rebuild=False): - return self.CreateOffsetCurve(self.centreCurve, self.frames, self.samples, x, y, rebuild, self.samples) - - def OffsetCurve(self, rebuild=False): - return self.CreateOffsetCurve( - self.centreCurve, self.radii, self.frames, self.samples, rebuild, self.samples, 1, 1 - ) - - def OffsetCurve4(self, rebuild=False): - return self.CreateOffsetCurve4( - self.centreCurve, self.radii, self.frames, self.samples, rebuild, self.samples - ) - - def SortFrames(self): - self.frames.sort(key=lambda x: x[0]) - - def ToString(self): - length = round(self.centreCurve.GetLength(), 3) - num_cuts = len(self.cuts) - return "Beam ID: {self.id} Length: {length} Cuts: {num_cuts}" - - def Transform(self, xform): - self.centreCurve.Transform(xform) - self.centrePline.Transform(xform) - for i in range(len(self.frames)): - plane = rg.Plane(self.frames[i].Item2) - plane.Transform(xform) - self.frames[i] = (self.frames[i].Item1, rg.Plane(plane)) - for circle in self.circles: - circle.Transform(xform) - for polygon in self.polygons: - polygon.Transform(xform) - for cut in self.cuts: - cut.Transform(xform) - - class Element: - - key = None - fID = None - eID = [] - cuts = [] - outlinesCenter = Outline() - outlines = [] - outlinesBackUp = [] - plGroup = Plane.Unset - bbox = BoundingBox() - bboxAligned = None - mesh = None - d = Line.Unset - ev = [] - beamOrPlate = False - w = 0 - - def __init__(self, fID, v, p0_, p1_, plGroup, eID=None, key=""): - self.key = None - self.fID = None - self.eID = [] - self.cuts = [] - self.outlinesCenter = Outline() - self.outlines = [] - self.outlinesBackUp = [] - self.plGroup = Plane.Unset - self.bbox = BoundingBox() - self.bboxAligned = None - self.mesh = None - self.d = Line.Unset - self.ev = [] - self.beamOrPlate = False - self.w = 0 - - if isinstance(p0_, Polyline): - p0 = [p0_] - p1 = [p1_] - - self.beamOrPlate = True if v.IsValid and v != Line.Unset else False - self.beamOrPlate = False # Overriding previous assignment - self.fID = fID - self.key = str(fID) if key == "" else key - segmentCount = sum(len(polyline) for polyline in p0) - self.eID = eID if eID is not None else [-1] * segmentCount - self.d = Line(v.From, v.To) - outline = Outline(p0, OutlineType.Top) - outline1 = Outline(p1, OutlineType.Top) - outline1.plane = self.FlipAndRotate(outline1.plane) - - plane = self.Translation(outline.plane, outline.plane.ZAxis * 0.01) - plane1 = self.Translation(outline1.plane, outline1.plane.ZAxis * 0.01) - if plane.Origin.DistanceToSquared(plane1.Origin) < outline.plane.Origin.DistanceToSquared( - outline1.plane.Origin - ): - outline.FlipPlane(outline1) - outline.CheckPolygonOrientation(outline1) - self.outlines.append(outline) - self.outlines.append(outline1) - polylines = [] - - for j in range(len(p0)): - polylines.append(self.tweenPolylines(outline.plines[j], outline1.plines[j], 0.5)) - self.outlinesCenter = Outline(polylines, OutlineType.Center) - self.outlinesCenter.plane = Plane( - (outline.plane.Origin + outline1.plane.Origin) * 0.5, outline.plane.XAxis, outline.plane.YAxis - ) - - for k in range(len(p0)): - numArray = [0] * (len(p0[k]) - 1) - array = list(range(len(p0[k]) - 1)) - for l in range(len(p0[k]) - 1): - polyline = Polyline() - polyline.Add(outline.plines[k][l + 1]) - polyline.Add(outline.plines[k][l]) - polyline.Add(outline1.plines[k][l]) - polyline.Add(outline1.plines[k][l + 1]) - polyline.Add(outline.plines[k][l + 1]) - outline2 = Outline(polyline, OutlineType.Side) - outline2.plane = Plane( - outline2.plane.Origin, - outline.plines[k][l + 1] - outline.plines[k][l], - outline.plines[k][l] - outline1.plines[k][l], - ) - self.outlines.append(outline2) - self.ev.append(Vector3d.Unset) - if self.beamOrPlate: - numArray[l] = 999999 - num = 0 - if Intersection.LinePlane(self.d, outline2.plane, num) and -0.001 < num < 1.0001: - numArray[l] = 0 - - if self.beamOrPlate: - Array.Sort(numArray, array) - for m in range(len(p0[k]) - 1): - if m >= 2: - self.outlines[array[m] + 2].name = OutlineType.Top - else: - self.outlines[array[m] + 2].name = OutlineType.Side - - point3ds = [] - for polyline1 in p0: - point3ds.extend(polyline1) - - for polyline2 in p1: - point3ds.extend(polyline2) - - self.bbox = BoundingBox(point3ds) - self.bbox.Inflate(0.01) - self.bboxAligned = self.GetBoundingBoxAligned(point3ds, self.outlines[0].plane, 0.01) - - for outline3 in self.outlines: - self.outlinesBackUp.append(outline3.Duplicate()) - - self.plGroup = self.outlines[0].plane if plGroup == Plane.Unset else Plane(plGroup) - - if self.d != Line.Unset: - self.plGroup = self.ToPlane(self.d, False) - self.plGroup = Plane(self.d.PointAt(0.5), self.plGroup.XAxis, self.plGroup.YAxis) - self.plGroup = self.AlignPlane(self.plGroup, Vector3d.ZAxis) - - if self.d == Line.Unset: - origin = self.outlines[0].plane.Origin - self.w = origin.DistanceTo(self.outlines[1].plane.Origin) - return - - origin = self.outlines[0].plane.ClosestPoint(self.d.From) - num1 = origin.DistanceTo(self.outlines[1].plane.ClosestPoint(self.d.From)) - num2 = num1 - self.w = num1 - num3 = num2 - origin = self.outlines[0].plane.ClosestPoint(self.d.To) - num4 = origin.DistanceTo(self.outlines[1].plane.ClosestPoint(self.d.To)) - num2 = num4 - self.w = num4 - self.w = max(num3, num2) - - def ToPlane(self, line, start_or_end): - if start_or_end: - return Plane(line.From, line.Direction) - return Plane(line.To, line.Direction) - - def AlignPlane(self, plane, v): - plane1 = Plane(plane) - num = 0.0 - num1 = 0.0 - result, num, num1 = plane1.ClosestParameter(plane1.Origin + v) - num2 = math.atan2(num, num1) - plane1.Rotate(-num2 + 1.5707963267949, plane1.ZAxis, plane1.Origin) - return plane1 - - def GetBoundingBoxAligned(self, pts, plane, inflate=0): - transform = Rhino.Geometry.Transform.ChangeBasis(Rhino.Geometry.Plane.WorldXY, plane) - boundingBox = Rhino.Geometry.BoundingBox(pts, transform) - if inflate > 0: - boundingBox.Inflate(inflate) - min_point = boundingBox.Min - x = min_point.X - max_point = boundingBox.Max - x_interval = Rhino.Geometry.Interval(x, max_point.X) - y = min_point.Y - y_interval = Rhino.Geometry.Interval(y, max_point.Y) - z = min_point.Z - z_interval = Rhino.Geometry.Interval(z, max_point.Z) - return Rhino.Geometry.Box(plane, x_interval, y_interval, z_interval) - - def tweenPolylines(self, l0, l1, t=0.5): - def Lerp(start, end, t): - return (1 - t) * start + t * end - - polyline = Polyline(l0) - for i in range(l0.Count): - polyline[i] = Lerp(l0[i], l1[i], t) - return polyline - - def FlipAndRotate(self, p): - plane = Plane(p) - plane.Flip() - plane.Rotate(1.5707963267949, plane.ZAxis) - return plane - - def Translation(self, plane, v): - plane1 = Plane(plane) - plane1.Translate(v) - return plane1 - - def Orient(self, targetPlane): - self.Transform(Rhino.Geometry.Transform.PlaneToPlane(self.plGroup, targetPlane)) - - def Transform(self, x): - self.d.Transform(x) - for i in range(len(self.outlines)): - self.outlines[i].Transform(x) - for j in range(len(self.outlinesBackUp)): - self.outlinesBackUp[j].Transform(x) - self.outlinesCenter.Transform(x) - for k in range(len(self.cuts)): - self.cuts[k].Transform(x) - for l in range(len(self.ev)): - if self.ev[l] != Rhino.Geometry.Vector3d.Unset: - self.ev[l].Transform(x) - self.plGroup.Transform(x) - self.bbox.Transform(x) - self.bboxAligned.Transform(x) - for m in range(len(self.ev)): - self.ev[m].Transform(x) - if self.mesh is not None: - self.mesh.Transform(x) - - def KeyToIntArray(self): - strArrays = self.key.split(";") - numArray = [int(num) for num in strArrays] - return numArray - - class Elements: - - eSL = OrderedDict() - r = [] - - def __init__(self, listElements=None): - - if listElements is not None: - for listElement in listElements: - self.Add(listElement) - - def __getitem__(self, index): - return list(self.eSL.values())[index] - - def __setitem__(self, index, value): - self.eSL.values()[index] = value - - def Add(self, item): - key = item.key - self.eSL[key] = item - - def Duplicate(self): - elements = Elements() - for key, value in self.eSL.items(): - elements.Add(value.Duplicate()) - for geometryBase in self.r: - elements.r.append(geometryBase.Duplicate()) - return elements - - def GetEdgeDirections(self, lines): - num = 0 - for direction in self.eSL.values(): - value = direction.bbox - for i in range(len(lines)): - if value.Contains(lines[i].get_From()) or not value.Contains(lines[i].get_To()): - for j in range(2, len(direction.outlines)): - item = lines[i] - if not direction.outlines[j].bbox.Contains(item.get_From()): - item = lines[i] - if not direction.outlines[j].bbox.Contains(item.get_To()): - continue - item = lines[i] - if abs(direction.outlines[j].plane.DistanceTo(item.get_From())) >= 0.0001: - item = lines[i] - if abs(direction.outlines[j].plane.DistanceTo(item.get_To())) >= 0.0001: - continue - if ( - direction.outlines[0] - .plines[0] - .ClosestPoint(lines[i].get_From()) - .DistanceTo(lines[i].get_From()) - < 0.001 - or direction.outlines[1] - .plines[0] - .ClosestPoint(lines[i].get_From()) - .DistanceTo(lines[i].get_From()) - < 0.001 - ): - line = lines[i] - direction.ev[j - 2] = line.get_Direction() - num += 1 - - def GetElementDirections(self, lines): - try: - num = 0 - for keyValuePair in self.eSL.items(): - value = keyValuePair.Value.bbox - for i in range(len(lines)): - if value.Contains(lines[i].get_From()) or not value.Contains(lines[i].get_To()): - num1 = 0 - while True: - if num1 >= 2: - break - item = lines[i] - if not keyValuePair.Value.outlines[num1].bbox.Contains(item.get_From()): - item = lines[i] - if not keyValuePair.Value.outlines[num1].bbox.Contains(item.get_To()): - continue - item = lines[i] - if abs(keyValuePair.Value.outlines[num1].plane.DistanceTo(item.get_From())) < 0.01: - break - item = lines[i] - if abs(keyValuePair.Value.outlines[num1].plane.DistanceTo(item.get_To())) < 0.01: - break - num1 += 1 - line = lines[i] - line.Transform(Transform.PlanarProjection(keyValuePair.Value.outlines[0].plane)) - for j in range(2, len(keyValuePair.Value.outlines)): - direction = line.get_Direction() - origin = keyValuePair.Value.outlines[j].plane.get_Origin() - if keyValuePair.Value.outlinesCenter.plane.get_Origin().DistanceToSquared( - origin + (direction * 1) - ) < keyValuePair.Value.outlinesCenter.plane.get_Origin().DistanceToSquared( - origin - (direction * 1) - ): - direction.Reverse() - keyValuePair.Value.ev[j - 2] = direction - num += 1 - except Exception as exception: - Debug.Log(str(exception), True) - - def GetEnumerator(self): - return self.eSL.GetEnumerator() - - def GetList(self): - return list(self.eSL.values()) - - def GetOutlinePlane(self, f, e): - return self.eSL[f].outlines[e].plane - - def GetOutlinePlaneX(self, f, e): - return self.eSL[f].outlines[e].plane.get_XAxis() - - def GetOutlinePlaneY(self, f, e): - return self.eSL[f].outlines[e].plane.get_YAxis() - - def GetOutlinePlaneZ(self, f, e): - return self.eSL[f].outlines[e].plane.get_ZAxis() - - def GetOutlinePlines(self, f, e): - return self.eSL[f].outlines[e].plines - - def GetOutlineType(self, f, e): - return self.eSL[f].outlines[e].name - - def Partition(self, level=0, addRefGeometry=True): - elements = [] - if len(self.eSL) == 0: - return elements - elements1 = Elements() - num = -10 - flag = True - for key, value in self.eSL.items(): - intArray = value.KeyToIntArray() - if num != intArray and not flag: - elements.append(elements1) - elements1 = Elements() - elements1.Add(value) - if len(self.r) > intArray and addRefGeometry: - elements1.r.append(self.r[intArray]) - num = intArray - flag = False - elements.append(elements1) - return elements - - def GetEnumerator(self): - return self.Partition() - - def ToString(self): - str = str(len(self.eSL)) - count = len(self.r) - return "Elements " + str + " Ref " + str(count) - - def Transform(self, xform): - for keyValuePair in self.eSL: - keyValuePair.Value.Transform(xform) - for geometryBase in self.r: - geometryBase.Transform(xform) - - class ElementsFromCCX: - - adjacency = [] - elements = Elements() # class for storage - beams = None - JointsPts = [] - CollisionPairs = set() - id = [] - idParams = [] - closestDistanceTol = 400.0 - parallelTol = 0.2 - lengthOfBoxes = 300.0 - elementCount = 0 - halfLap = False - - def __init__( - self, - axis_, - C_, - rebuild, - indices, - componentPlanes, - adjustLines, - closestDistanceTol, - parallelTol, - lengthOfBoxes, - jointsPoints, - halfLap, - ): - polyline = None - count = len(axis_) - self.beams = [None] * count - self.closestDistanceTol = closestDistanceTol - self.parallelTol = parallelTol - self.lengthOfBoxes = lengthOfBoxes - self.elementCount = 0 - self.JointsPts = jointsPoints - self.elements = Elements() # class for storage - self.halfLap = halfLap - - for i in range(count): - result, polyline = axis_[i].TryGetPolyline() - if polyline[0].DistanceToSquared(C_[i][0].Center) > polyline[0].DistanceToSquared(C_[i][-1].Center): - C_[i].Reverse() - - line = adjustLines[i] if count == len(adjustLines) else Line.Unset - num = indices[i] if len(indices) == count else i - - nums = [] - planes = [] - for j in range(len(C_[i]) - 1): - item = C_[i][j] - nums.append(item.Radius) - item = C_[i][j] - planes.append(item.Plane) - - self.beams[i] = Beam(num, polyline, nums, line, planes, rebuild, rebuild > 0) - - self.GetNeighbours() - - num1 = 0 - num2 = -1 - for element in self.elements: - intArray = element.KeyToIntArray()[0] - if num2 == intArray: - continue - num1 += 1 - num2 = intArray - - if len(indices) != len(componentPlanes) or len(indices) + len(componentPlanes) <= 0: - if num1 == len(componentPlanes): - for keyValuePair in self.elements: - intArray1 = keyValuePair.KeyToIntArray()[0] - keyValuePair.Value.plGroup = componentPlanes[intArray1] - return - - nums1 = set() - nums2 = {} - for k in range(len(indices)): - if indices[k] not in nums1: - nums1.add(indices[k]) - nums2[indices[k]] = componentPlanes[k] - - for l in range(len(self.elements)): - numArray = self.elements[l].KeyToIntArray() - self.elements[l].plGroup = nums2[numArray[0]] - - def MovePlanebyAxis(self, plane, dist, axis=2): - plane1 = Plane(plane) - if axis == 0: - plane1.Translate(plane1.XAxis * dist) - elif axis == 1: - plane1.Translate(plane1.YAxis * dist) - else: - plane1.Translate(plane1.Normal * dist) - return plane1 - - def OrientPlaneTowardsCurveShorterEnd(self, curve, plane, t, message): - - plane1 = Plane(plane) - - # which side is shorter - p = curve.PointAt(t) - copy_curve = curve.Duplicate() - copy_curve = copy_curve.Extend( - Rhino.Geometry.CurveEnd.Both, - copy_curve.GetLength(0.01) * 0.1, - Rhino.Geometry.CurveExtensionStyle.Smooth, - ) - copy_curve.Domain = Interval(0, 1) - - result, cpt = copy_curve.ClosestPoint(p) - - domain0 = Interval(copy_curve.Domain.T0, cpt) - domain1 = Interval(cpt, copy_curve.Domain.T1) - - # get middle point of that side - orientation_point = copy_curve.PointAt(domain0.Mid) - if domain1.Length > domain0.Length: - orientation_point = copy_curve.PointAt(domain1.Mid) - - # orient the plane based on the distance search - distance = plane.DistanceTo(orientation_point) - # print(distance) - # Rhino.RhinoDoc.ActiveDoc.Objects.AddPoint(orientation_point) - if distance < 0: - plane1 = self.FlipAndRotate(plane1) - - # Rhino.RhinoDoc.ActiveDoc.Objects.AddPolyline(Rectangle3d(plane1,10,10).ToPolyline()) - return plane1 - """ - num = 0 - plane1 = Plane(plane) - interval = [None] * 2 - domain = curve.Domain - interval[0] = Interval(domain.T0 - 1000, t) - domain = curve.Domain - interval[1] = Interval(t, domain.T1 + 1000) - intervalArray = interval - num1 = 0 if intervalArray[0].Length < intervalArray[1].Length else 1 - curve.ClosestPoint(plane.Origin + plane.ZAxis, num) - if not intervalArray[num1].IncludesParameter(num): - plane1 = self.FlipAndRotate(plane1) - return plane1 - """ - - def AlignPlane(self, A, B): - origin = B.Origin - xAxis = B.XAxis - yAxis = B.YAxis - zAxis = B.ZAxis - - switch_value = A.ZAxis.IsParallelTo(B.ZAxis, 1.539380400259) - if switch_value == -1: - point3d = B.ClosestPoint(origin + A.XAxis) - xAxis = origin - point3d - xAxis.Unitize() - elif switch_value == 0: - transform = Rhino.Geometry.Transform.Rotation(A.ZAxis, B.ZAxis, B.Origin) - xAxis = A.XAxis - xAxis.Transform(transform) - elif switch_value == 1: - xAxis = B.ClosestPoint(origin + A.XAxis) - origin - xAxis.Unitize() - - return Plane(origin, xAxis, Vector3d.CrossProduct(zAxis, xAxis)) - - """ - def AlignPlane(self, plane, v): - plane1 = Plane(plane) - num = 0.0 - num1 = 0.0 - result, num, num1 = plane1.ClosestParameter(plane1.Origin + v) - num2 = math.atan2(num, num1) - plane1.Rotate(-num2 + 1.5707963267949, plane1.ZAxis, plane1.Origin) - return plane1 - """ - - def GetMale(self, C0, C1, T0=-1, T1=-1): - t0 = None - t1 = None - - if T0 != -1 or T1 != -1: - t0 = T0 - t1 = T1 - else: - curveIntersection = Intersection.CurveCurve(C0, C1, 1000, 0.01) - t0 = curveIntersection[0].ParameterA - t1 = curveIntersection[0].ParameterB - - domain = C0.Domain - domain = Rhino.Geometry.Interval(domain.T0, t0) - length = domain.Length - domain = C0.Domain - domain = Rhino.Geometry.Interval(t0, domain.T1) - num = domain.Length - - domain = C1.Domain - domain = Rhino.Geometry.Interval(domain.T0, t1) - length1 = domain.Length - domain = C1.Domain - domain = Rhino.Geometry.Interval(t1, domain.T1) - num1 = domain.Length - - if abs(length - num) / C0.Domain.Length <= abs(length1 - num1) / C1.Domain.Length: - return 1 - return 0 - - def MovePlanebyAxis(self, plane, dist, axis=2): - plane1 = Plane(plane) - if axis == 0: - plane1.Translate(plane1.XAxis * dist) - elif axis == 1: - plane1.Translate(plane1.YAxis * dist) - else: - plane1.Translate(plane1.Normal * dist) - return plane1 - - def AverageNormal(self, p): - count = p.Count - 1 - vector3d = Vector3d(0, 0, 0) - num = count - 1 - for i in range(num + 1): - num1 = (i - 1 + count) % count - num2 = (i + 1 + count) % count - item = p[num1] - point3d = p[num2] - item1 = p[i] - vector3d += Vector3d.CrossProduct(Vector3d(item1 - item), Vector3d(point3d - item1)) - - if vector3d.X == 0 and vector3d.Y == 0 and vector3d.Z == 0: - vector3d.Unitize() - - return vector3d - - def GetPlane(self, polyline, AveragePlane=True): - plane = Plane.Unset - if not AveragePlane: - Plane.FitPlaneToPoints(polyline, plane) - plane.Origin = polyline.CenterPoint() - return plane - - line = polyline.SegmentAt(0) - vector3d = line.Direction - vector3d.Unitize() - vector3d1 = self.AverageNormal(polyline) - vector3d1.Unitize() - vector3d2 = Vector3d.CrossProduct(vector3d, vector3d1) - return Plane(polyline.CenterPoint(), vector3d, vector3d2) - - def FlipAndRotate(self, p): - plane = Plane(p) - plane.Flip() - plane.Rotate(1.5707963267949, plane.ZAxis) - return plane - - def ShiftPline(self, a, n=1): - def Wrap(index, n): - if n == 0: - return 0 - return (index % n + n) % n - - polyline = Rhino.Geometry.Polyline(a) - polyline.RemoveAt(polyline.Count - 1) - num = Wrap(n, polyline.Count) - for i in range(num): - count = polyline.Count - item = polyline[count - 1] - for j in range(count - 1, 0, -1): - polyline[j] = polyline[j - 1] - polyline[0] = item - polyline.Add(polyline[0]) - return polyline - - def SplitCurvesByPlane(self, pline, plane): - num = 0 - polyline = None - polyline1 = Polyline(pline) - nurbsCurve = polyline1.ToNurbsCurve() - nums = [] - - for i in range(polyline1.SegmentCount): - result, num = Rhino.Geometry.Intersect.Intersection.LinePlane(polyline1.SegmentAt(i), plane) - if result: - if num > -0.999999999 and num < 1.0000001: - nums.append(float(i) + num) - - array = sorted(nums) - nurbsCurve = polyline1.ToNurbsCurve() - curveArray = None - if len(array) != 2: - curveArray = nurbsCurve.Split(array) - else: - curveArray = [nurbsCurve.Trim(array[0], array[1]), nurbsCurve.Trim(array[1], array[0])] - - nums1 = SortedDictionary[int, Polyline]() - nums2 = SortedDictionary[int, Polyline]() - plane1 = Plane(plane) - plane1.Translate(plane.ZAxis * 0.01) - num1 = 0 - for curve in curveArray: - result, polyline = curve.TryGetPolyline() - if result: - - # Rhino.RhinoDoc.ActiveDoc.Objects.AddPoint(curve.PointAtNormalizedLength(0.5)) - # check which polygon is on the plane - # if this assumtion will brake in the future, thake the point that is closest to the plane by measuring the absolute point to plane distance - if ( - plane.DistanceTo(curve.PointAtNormalizedLength(0.5)) < 0.01 - and plane.DistanceTo(curve.PointAtNormalizedLength(0.5)) > -0.01 - ): - nums2.Add(num1, polyline) - else: - nums1.Add(num1, polyline) - num1 += 1 - - return tuple([nums1, nums2]) - - def GetNeighbours(self): - bounding_boxes = {} - for i in range(len(self.beams)): - bounding_boxes[i] = self.beams[i].GetBoundingBox(0.001) - - rTree = RTree() - for j in range(len(bounding_boxes)): - rTree.Insert(bounding_boxes[j], j) - - def SearchCallback(sender, e): - # Indexing - index1 = int(e.Tag) if isinstance(e.Tag, int) else None - a = index1 if index1 is not None and index1 < e.Id else e.Id - b = e.Id if index1 is not None and index1 < e.Id else index1 - - # Check1: equal elements Check2: belongs to the same component Check3: pair is visited - if a == b: - return - if self.beams[a].id == self.beams[b].id: - return - - longKey = (a << 32) + b # long key for faceID - newPair = longKey not in self.CollisionPairs - if newPair: - self.CollisionPairs.add(longKey) - else: - return - - # Proximity Search - # Get Curves for Proximity Search and CurveClosestPoints Parameters - c0 = self.beams[a].centreCurve - c1 = self.beams[b].centreCurve - minDistance = -1 - mint0 = -1 - mint1 = -1 - - if len(self.JointsPts) != 0: - # If user gives intersection points - for i in range(len(self.JointsPts)): - result, t0 = c0.ClosestPoint(self.JointsPts[i], self.closestDistanceTol) - p0 = c0.PointAt(t0) - result, t1 = c1.ClosestPoint(self.JointsPts[i], self.closestDistanceTol) - p1 = c1.PointAt(t1) - dist = p0.DistanceTo(p1) - - if dist < closestDistanceTol: - minDistance = p0.DistanceTo(p1) - mint0 = t0 - mint1 = t1 - break - - if minDistance == -1: - return - - elif len(self.JointsPts) == 0 or minDistance == -1: - # Else ClosestPoints method is called between two curves - ( - result, - p0, - p1, - ) = c0.ClosestPoints(c1) - result, mint0 = c0.ClosestPoint(p0) - result, mint1 = c1.ClosestPoint(p1) - minDistance = p0.DistanceTo(p1) - - if not (minDistance < self.closestDistanceTol): - return - - mPoint = c0.PointAt(mint0) - fPoint = c1.PointAt(mint1) - mID = a - fID = b - mT = mint0 - fT = mint1 - plane0 = self.beams[a].GetPlane_by_t(mint0) - plane1 = self.beams[b].GetPlane_by_t(mint1) - self.id.append((a, b)) - self.idParams.append((mint0, mint1)) - - if plane0.ZAxis.IsParallelTo(plane1.ZAxis, self.parallelTol) == 0: - # Non-Parallel case for Side-to-End and Side-Side Joints - - # Firstly, it is necessary to identify which beam is male and female from BeamJoint curve parameters. - # The male beam will have an intersection point close to one of the line ends, and the female will be located vice-versa. - - m = self.GetMale(self.beams[mID].centreCurve, self.beams[fID].centreCurve, mT, fT) - f = abs(m - 1) # female will have a connection close to the center - - mID = [a, b][m] # male beam id 0 -> 58 - fID = [a, b][f] # female beam id 1 -> 102 - - mT = [mint0, mint1][m] - fT = [mint0, mint1][f] - - mPoint = self.beams[mID].centreCurve.PointAt(mT) - fPoint = self.beams[fID].centreCurve.PointAt(fT) - - mRadius = self.beams[mID].GetInterpolatedRadius_by_parameter(mT) - fRadius = self.beams[fID].GetInterpolatedRadius_by_parameter(fT) - - mPlane = self.beams[mID].GetPlane_by_t(mT) - fPlane = self.beams[fID].GetPlane_by_t(fT) - - # Align plane orientation - - cross = Rhino.Geometry.Vector3d.CrossProduct(mPlane.ZAxis, fPlane.ZAxis) # YAxis - - angle0 = Rhino.Geometry.Vector3d.VectorAngle(mPlane.ZAxis, fPlane.ZAxis, cross) - angle1 = Rhino.Geometry.Vector3d.VectorAngle(-mPlane.ZAxis, fPlane.ZAxis, cross) - - angleMin = min(angle0, angle1) - - angleLimit = Rhino.RhinoMath.ToRadians(30) # Math.PI * 0.25 = 45 - - if angleMin < angleLimit: # 45 - fixAngle = angleLimit - angleMin - fixAngle *= -1 - if angle1 < angle0: - mPlane.Rotate(-fixAngle, cross, mPlane.Origin) - else: - mPlane.Rotate(fixAngle, cross, mPlane.Origin) - - ci = Rhino.Geometry.Intersect.Intersection.CurvePlane(self.beams[mID].centreCurve, mPlane, 0.1) - mPlane = Plane(ci[0].PointA, mPlane.XAxis, mPlane.YAxis) - cross = Rhino.Geometry.Vector3d.CrossProduct(mPlane.ZAxis, fPlane.ZAxis) - - fp = fPlane.Origin - fXAxis = fPlane.XAxis - mPlane = Rhino.Geometry.Plane( - mPlane.Origin, Rhino.Geometry.Vector3d.CrossProduct(mPlane.ZAxis, cross), -cross - ) - fPlane = Rhino.Geometry.Plane( - fPlane.Origin, Rhino.Geometry.Vector3d.CrossProduct(fPlane.ZAxis, cross), -cross - ) - - if self.halfLap: - mPlane.Origin = mPoint - fPlane.Origin = fPoint - mPlane.Rotate(math.pi * 0.5, mPlane.ZAxis) - else: - # Orient towards ends - # print(mT) - # Rhino.RhinoDoc.ActiveDoc.Objects.AddPoint(self.beams[mID].centreCurve.PointAt(mT)) - - mPlane = self.beams[mID].GetPlaneOrientedToShorterSide_by_t(mT) - mPlane = self.FlipAndRotate(mPlane) - # Rhino.RhinoDoc.ActiveDoc.Objects.AddPolyline(Rectangle3d(mPlane,1,1).ToPolyline()) - - # Create Elements properties - scale = 1.0 - extend0 = self.lengthOfBoxes * scale if self.halfLap else 0 - extend1 = -self.lengthOfBoxes * scale if self.halfLap else self.lengthOfBoxes * 2 * scale - - mPlane0 = self.MovePlanebyAxis(mPlane, extend0) - mPlane1 = self.MovePlanebyAxis(mPlane, extend1) - r0 = Rectangle3d(mPlane0, Interval(-mRadius, mRadius), Interval(-mRadius, mRadius)) - r1 = Rectangle3d(mPlane1, Interval(-mRadius, mRadius), Interval(-mRadius, mRadius)) - axis0 = Line(r0.Center, r1.Center) - pline0m = Polyline([r0.Corner(0), r0.Corner(1), r1.Corner(1), r1.Corner(0), r0.Corner(0)]) - pline1m = Polyline([r0.Corner(3), r0.Corner(2), r1.Corner(2), r1.Corner(3), r0.Corner(3)]) - - fID0 = self.elementCount - key0 = str(self.beams[mID].id) + ";" + str(self.elementCount) - self.elementCount += 1 - - fPlane0 = self.MovePlanebyAxis(fPlane, -self.lengthOfBoxes * scale) - fPlane1 = self.MovePlanebyAxis(fPlane, self.lengthOfBoxes * scale) - r0 = Rectangle3d(fPlane0, Interval(-fRadius, fRadius), Interval(-fRadius, fRadius)) - r1 = Rectangle3d(fPlane1, Interval(-fRadius, fRadius), Interval(-fRadius, fRadius)) - pline0f = Polyline([r0.Corner(0), r0.Corner(1), r1.Corner(1), r1.Corner(0), r0.Corner(0)]) - pline1f = Polyline([r0.Corner(3), r0.Corner(2), r1.Corner(2), r1.Corner(3), r0.Corner(3)]) - axis1 = Line(r0.Center, r1.Center) - pline2 = Polyline([r0.Corner(1), r0.Corner(2), r1.Corner(2), r1.Corner(1), r0.Corner(1)]) - pline3 = Polyline([r0.Corner(0), r0.Corner(3), r1.Corner(3), r1.Corner(0), r0.Corner(0)]) - fPlane2 = self.GetPlane(pline2) - fPlane3 = self.GetPlane(pline3) - - fID1 = self.elementCount - key1 = str(self.beams[fID].id) + ";" + str(self.elementCount) - self.elementCount += 1 - - midP = (fPlane2.Origin + fPlane3.Origin) * 0.5 - - # Orient Planes to outside of the center - if fPlane2.DistanceTo(midP) > 0: - self.FlipAndRotate(fPlane2) - if fPlane3.DistanceTo(midP) > 0: - self.FlipAndRotate(fPlane3) - - # Take nearest plane to center of male beam - fPlaneClosest = ( - fPlane2 - if mPlane1.Origin.DistanceToSquared(fPlane2.Origin) - < mPlane1.Origin.DistanceToSquared(fPlane3.Origin) - else fPlane3 - ) - - # Cut elements by nearest plane or do not cut if a cross-lap joint is needed - if not self.halfLap: - pline0m = next(iter(self.SplitCurvesByPlane(pline0m, fPlaneClosest)[0])).Value - pline1m = next(iter(self.SplitCurvesByPlane(pline1m, fPlaneClosest)[0])).Value - pline0m.Add(pline0m[0]) - pline1m.Add(pline1m[0]) - # Rhino.RhinoDoc.ActiveDoc.Objects.AddPolyline(pline0m) - - # Create Elements - e0 = Element( - fID0, Line.Unset, pline0m, pline1m, self.GetPlane(pline0m), None, key0 - ) # new Line(r0.Center, r1.Center) - e1 = Element(fID1, Line.Unset, pline0f, pline1f, self.GetPlane(pline0f), None, key1) - - # Edge Vectors - e1.Transform(Rhino.Geometry.Transform.Rotation(math.pi * 0.5, r1.Center - r0.Center, r0.Center)) - e0.d = axis0 - e1.d = axis1 - - ############################################################################################################################################### - # Match Plane orientation and rebuild female element - ############################################################################################################################################### - pline0f = e1.outlines[0].plines[0] - pline1f = e1.outlines[1].plines[0] - orientationPoint = fp + fXAxis * pline0f.Length - line = Rhino.Geometry.Line(pline0f.ClosestPoint(orientationPoint), orientationPoint) - idf = int(math.floor(pline0f.ClosestParameter(orientationPoint))) - pline0f = self.ShiftPline(pline0f, -idf) - pline1f = self.ShiftPline(pline1f, -idf) - - e1 = Element( - fID1, Rhino.Geometry.Line.Unset, pline0f, pline1f, self.GetPlane(pline0f), None, key1 - ) - e1.beamOrPlate = True - e1.d = axis1 - - # Get edgevectors - evM = [] - for i in range(pline0m.SegmentCount): - if fPlaneClosest.DistanceTo(pline0m.SegmentAt(i).PointAt(0.5)) < 0.01: - evM.append(axis0.Direction) - else: - evM.append(Rhino.Geometry.Vector3d.Unset) - - e0.ev = evM - - ############################################################################################################################################### - # Output - ############################################################################################################################################### - self.elements.Add(e0) - self.elements.Add(e1) - # print("neighbors", e0.fID, e1.fID) - self.adjacency.append([e0.fID, e1.fID]) - else: - - # region Parallel case for End-to-End Joints - - # region Get male and female plane - - midP = (mPoint + fPoint) * 0.5 - mPlane = self.beams[mID].GetPlaneOrientedToShorterSide_by_t(mT) - fPlane = self.beams[fID].GetPlaneOrientedToShorterSide_by_t(fT) - mZAxis = mPlane.ZAxis - fZAxis = fPlane.ZAxis - mRadius = self.beams[mID].GetInterpolatedRadius_by_parameter(mT) - fRadius = self.beams[fID].GetInterpolatedRadius_by_parameter(fT) - - # endregion - - # region Get Bisector Plane - - isParallel = mZAxis.IsParallelTo(fZAxis, 0.01) - ZAxis = Vector3d.CrossProduct(fZAxis, mZAxis) if isParallel == 0 else Vector3d.ZAxis - XAxis = fZAxis + mZAxis if isParallel == 0 else Vector3d.CrossProduct(ZAxis, mZAxis) - YAxis = Vector3d.CrossProduct(ZAxis, XAxis) - bisector = Plane(midP, XAxis, ZAxis) - bisector = self.AlignPlane(mPlane, bisector) - - # endregion - - # region Orient Plane towards the longer ends - - fPlaneUser = self.OrientPlaneTowardsCurveShorterEnd( - self.beams[mID].centreCurve.DuplicateCurve(), Plane(bisector), mT, "a" - ) - mPlaneUser = self.OrientPlaneTowardsCurveShorterEnd( - self.beams[fID].centreCurve.DuplicateCurve(), Plane(bisector), fT, "b" - ) - # mPlaneUser = self.FlipAndRotate(mPlaneUser) - # Rhino.RhinoDoc.ActiveDoc.Objects.AddPolyline(Rectangle3d(mPlaneUser,5,5).ToPolyline()) - # Rhino.RhinoDoc.ActiveDoc.Objects.AddPolyline(Rectangle3d(fPlaneUser,5,5).ToPolyline()) - - # endregion - - # region Create Element - - r0 = Rectangle3d(mPlaneUser, Interval(-mRadius, mRadius), Interval(-mRadius, mRadius)) - r1 = Rectangle3d( - self.MovePlanebyAxis(mPlaneUser, self.lengthOfBoxes), - Interval(-mRadius, mRadius), - Interval(-mRadius, mRadius), - ) - pline0 = Polyline([r0.Corner(0), r0.Corner(1), r1.Corner(1), r1.Corner(0), r0.Corner(0)]) - pline1 = Polyline([r0.Corner(3), r0.Corner(2), r1.Corner(2), r1.Corner(3), r0.Corner(3)]) - fID0 = self.elementCount - e0 = Element( - fID0, - Line(r0.Center, r1.Center), - pline0, - pline1, - self.GetPlane(pline0), - None, - str(self.beams[a].id) + ";" + str(self.elementCount), - ) - self.elementCount += 1 - - r0 = Rectangle3d(fPlaneUser, Interval(-fRadius, fRadius), Interval(-fRadius, fRadius)) - r1 = Rectangle3d( - self.MovePlanebyAxis(fPlaneUser, self.lengthOfBoxes), - Interval(-fRadius, fRadius), - Interval(-fRadius, fRadius), - ) - pline0 = Polyline([r0.Corner(0), r0.Corner(1), r1.Corner(1), r1.Corner(0), r0.Corner(0)]) - pline1 = Polyline([r0.Corner(3), r0.Corner(2), r1.Corner(2), r1.Corner(3), r0.Corner(3)]) - fID1 = self.elementCount - e1 = Element( - fID1, - Line(r0.Center, r1.Center), - pline0, - pline1, - self.GetPlane(pline0), - None, - str(self.beams[b].id) + ";" + str(self.elementCount), - ) - self.elementCount += 1 - - # endregion - - # region Output - - self.elements.Add(e0) - self.elements.Add(e1) - self.adjacency.Add([e0.fID, e1.fID]) - - # endregion - - # endregion - - for k in range(rTree.Count - 1): - rTree.Search(bounding_boxes[k], SearchCallback, k) - - ##################################################################################### - # Create circles around the curves - ##################################################################################### - - ##################################################################################### - # Generate Elements - # (self, axis_, C_, rebuild, indices, componentPlanes, adjustLines, closestDistanceTol, parallelTol, lengthOfBoxes, jointsPoints, halfLap) - ##################################################################################### - - # create axes from circles - list_axes_as_curves = [] - list_of_lists_circles = [] - - for i in range(_circles.BranchCount): - - axis = Polyline() - list_of_circles = [] - - for j in range(_circles.Branch(i).Count): - axis.Add(_circles.Branch(i)[j].Center) - list_of_circles.append(_circles.Branch(i)[j]) - - list_axes_as_curves.append(axis.ToNurbsCurve()) - list_of_lists_circles.append(list_of_circles) - - # numeric parameters - rebuild = 1 - indexing = ( - [] - ) # If none is added tree trunks will follow data tree order, for forks it repeat like this 0 0 0 1 1 ... - distance_tolerance = _distance_tolerance if _distance_tolerance is not None else 10 - parallel_tolerance = _parallel_tolerance if _parallel_tolerance is not None else 0.2 - length_of_box = _length_of_box if _length_of_box is not None else 1 - joint_points = ( - [] - ) # If points are given they are used for joint detection, else Curve.ClosestPoints method is used - cross_lap = ( - _cross_or_toptoside if _cross_or_toptoside is not None else False - ) # CrossLap - true, Side-End - false - # print length_of_box - # optional parameters - planes = ( - [] - ) # Used only orientation, and most importantly for components such as forks or bent beams with multiple nodes - lines = [] # adjust beam, reorient planes - - if len(list_axes_as_curves) > 0: - - elementsFromCCX = ElementsFromCCX( - list_axes_as_curves, - list_of_lists_circles, - rebuild, - indexing, - planes, - lines, - distance_tolerance, - parallel_tolerance, - length_of_box, - joint_points, - cross_lap, - ) - - _pipes = DataTree[Brep]() - if _create_pipes: - for i in range(_circles.BranchCount): - curves = [] - for j in range(_circles.Branch(i).Count): - curves.append(_circles.Branch(i)[j].ToNurbsCurve()) - - brep = Brep.CreateFromLoft( - curves, Point3d.Unset, Point3d.Unset, Rhino.Geometry.LoftType.Loose, False - )[0] - brep = brep.CapPlanarHoles(Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance) - - faces = [] - for j in range(brep.Faces.Count): - faces.append(brep.Faces[j].DuplicateFace(False)) - - brep = Rhino.Geometry.Brep.JoinBreps(faces, Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance * 10)[0] - - if brep: - brep.Faces.SplitKinkyFaces(Rhino.RhinoMath.DefaultAngleTolerance, True) - - if Rhino.Geometry.BrepSolidOrientation.Inward is brep.SolidOrientation: - brep.Flip() - _pipes.Add(brep, GH_Path(i)) - - # elements = elementsFromCCX.elements.Partition(0, True) - - _volumes = DataTree[Polyline]() - _group_id = DataTree[int]() - for key, item in elementsFromCCX.elements.eSL.items(): - ids = item.KeyToIntArray() - # print(ids) - path = GH_Path(ids[0], ids[1]) - _volumes.Add(item.outlines[0].plines[0], path) - _volumes.Add(item.outlines[1].plines[0], path) - _group_id.Add(ids[0], GH_Path(ids[0])) - - # renumerate - total_count = 0 - for i in range(_group_id.BranchCount): - for j in range(len(_group_id.Branch(i))): - _group_id.Branch(i)[j] = total_count - total_count = total_count + 1 - - # return outputs if you have them; here I try it for you: - return (_volumes, _pipes, _group_id) +# from ghpythonlib.componentbase import executingcomponent as component +# import Grasshopper + +# import Rhino +# from Rhino.Geometry import ( +# Point3d, +# Vector3d, +# Polyline, +# Curve, +# Line, +# Plane, +# Brep, +# BoundingBox, +# Interval, +# RTree, +# Transform, +# Rectangle3d, +# ) +# from collections import OrderedDict +# from Grasshopper import DataTree +# from Grasshopper.Kernel.Data import GH_Path +# import math + + +# class MyComponent(component): +# def RunScript( +# self, +# _circles: Grasshopper.DataTree[Rhino.Geometry.Circle], +# _length_of_box: float, +# _distance_tolerance: float, +# _parallel_tolerance: float, +# _cross_or_toptoside: bool, +# _create_pipes: bool, +# ): + + +# input_polylines_segment_radii = [] + +# for i in range(len(input_polylines)): +# input_polyline_segment_radii = [] +# for j in range(len(input_polylines[i].points)): +# input_polyline_segment_radii.append(10) +# input_polylines_segment_radii.append(input_polyline_segment_radii) + +# input_polylines_segment_direction = [] +# for i in range(len(input_polylines)): +# input_polyline_segment_direction = [] +# for j in range(len(input_polylines[i].points)-1): +# input_polyline_segment_direction.append([0, 1, 0]) +# input_polylines_segment_direction.append(input_polyline_segment_direction) + + +# i_polylines, i_polylines_segment, distance, points, volume_pairs, joints_areas, joints_types = beam_volumes( +# input_polylines, +# input_polylines_segment_radii, +# input_polylines_segment_direction, +# input_allowed_types_per_polyline=[-1], +# input_min_distance=20, +# input_volume_length=75, +# input_cross_or_side_to_end=0.91, +# ) diff --git a/src/rhino/gh/cpy/box_wall/code.py b/src/rhino/gh/cpy/box_wall/code.py index 2f6c32190..c3229b541 100644 --- a/src/rhino/gh/cpy/box_wall/code.py +++ b/src/rhino/gh/cpy/box_wall/code.py @@ -12,9 +12,9 @@ def RunScript( _inlay_1: bool, _skipped: System.Collections.Generic.List[int], ): - if _mesh == None: + if _mesh is None: return - if _offset == None: + if _offset is None: _offset = 1 def get_ngon_polylines(mesh): @@ -71,10 +71,6 @@ def get_ngons_boundaries_point3d(mesh, verticesIDs): def get_ngon_planes(mesh): p = [None] * mesh.Ngons.Count - - b = get_ngons_boundaries(mesh) - pts = get_ngons_boundaries_point3d(mesh, b) - for i in range(mesh.Ngons.Count): p[i] = Rhino.Geometry.Plane(get_ngon_center(mesh, i), get_ngon_normal(mesh, i)) return p @@ -182,10 +178,6 @@ def get_intersection_between_current_and_neihgbor_planes( base_plane = move_plane_by_axis(base_plane, -offset * 2) base_plane_offset = move_plane_by_axis(base_plane_offset, -offset * 2) - # shift to right - # adjacent_planes_offset.insert(0, adjacent_planes_offset.pop())#adjacent_planes_offset.append(adjacent_planes_offset.pop(0)) - # adjacent_planes_offset.insert(0, adjacent_planes_offset.pop())#adjacent_planes_offset.append(adjacent_planes_offset.pop(0)) - # perform intersection if not_skipped_faces[i]: polylines_no_offset.append(polyline_from_planes(base_plane, adjacent_planes_no_offset)) diff --git a/src/rhino/gh/cpy/chevron_mesh/code.py b/src/rhino/gh/cpy/chevron_mesh/code.py index fe23c700b..936e444e3 100644 --- a/src/rhino/gh/cpy/chevron_mesh/code.py +++ b/src/rhino/gh/cpy/chevron_mesh/code.py @@ -1,11 +1,8 @@ -"""create a quad mesh by subdividing surface from two ends""" from ghpythonlib.componentbase import executingcomponent as component -import Grasshopper, GhPython -import System -import rhinoscriptsyntax as rs import Rhino import Rhino.Geometry -from Rhino.Geometry import Surface, Mesh, MeshFace, Point3d, Point3f, Vector3d +from Rhino.Geometry import Mesh, MeshFace, Point3f +import math class Chevron: @@ -41,7 +38,7 @@ class Chevron: def __init__( self, mesh, edge_rotation=1, edge_offset=0.5, box_height=760, top_plate_inlet=80, plate_thickness=40, ortho=True ): - if mesh == None: + if mesh is None: return self.mesh = mesh.DuplicateMesh() # assuming DuplicateMesh() is a method in Rhino or some other external library self.mesh.Flip(True, True, True) @@ -85,20 +82,13 @@ def chevron_grid(self, s, u_divisions=4, v_division_dist=900, shift=0.5, scale=0 half_v = DomV.T1 * 0.5 StepU = (DomU.T1 - DomU.T0) / u_divisions baseStepV = v_division_dist - maxStepV = 2500 - Delta = maxStepV - baseStepV totalV = DomV[1] - DomV[0] - rem = (totalV / 2) - ((maxStepV / 2) + baseStepV + Delta) - stepV = rem / baseStepV # Iterate number strips of the NURBS ctU = 0 - # print(s.Domain(0)) - # print(s.Domain(1)) - # print(u_divisions) for j in range(u_divisions): - # print(j) + ctV = 0 thresh = totalV / 2 StepV1 = baseStepV diff --git a/src/rhino/gh/cpy/chevron_plates/code.py b/src/rhino/gh/cpy/chevron_plates/code.py index 455b2f683..1215e0be0 100644 --- a/src/rhino/gh/cpy/chevron_plates/code.py +++ b/src/rhino/gh/cpy/chevron_plates/code.py @@ -1,16 +1,10 @@ from ghpythonlib.componentbase import executingcomponent as component -import Grasshopper, GhPython import System import Rhino -import rhinoscriptsyntax as rs -import Rhino import Rhino.Geometry -from Rhino.Geometry import Surface, Mesh, MeshFace, Point3d, Point3f, Vector3d, Plane, Line, BoundingBox +from Rhino.Geometry import Mesh, MeshFace, Point3d, Point3f, Vector3d, Plane, Line, BoundingBox import math -import System from collections import OrderedDict -import Grasshopper -from System.Drawing import Color from compas_wood.datastructures import WoodData @@ -48,7 +42,7 @@ def __init__( self, mesh, edge_rotation=1, edge_offset=0.5, box_height=760, top_plate_inlet=80, plate_thickness=40, ortho=True ): - if mesh == None: + if mesh is None: return self.mesh = mesh # assuming DuplicateMesh() is a method in Rhino or some other external library self.mesh.Flip(True, True, True) @@ -99,12 +93,8 @@ def chevron_grid(self, s, u_divisions=4, v_division_dist=900, shift=0.5, scale=0 half_v = DomV.T1 * 0.5 StepU = (DomU.T1 - DomU.T0) / u_divisions baseStepV = v_division_dist - maxStepV = 2500 - Delta = maxStepV - baseStepV totalV = DomV[1] - DomV[0] - rem = (totalV / 2) - ((maxStepV / 2) + baseStepV + Delta) - stepV = rem / baseStepV # Iterate number strips of the NURBS ctU = 0 @@ -215,7 +205,6 @@ def chevron_grid(self, s, u_divisions=4, v_division_dist=900, shift=0.5, scale=0 ctU += StepU # Create Mesh - # print(v) self.mesh = Mesh() for point in v: self.mesh.Vertices.Add(point) @@ -226,7 +215,7 @@ def chevron_grid(self, s, u_divisions=4, v_division_dist=900, shift=0.5, scale=0 return self.mesh def get_mesh_face_edges(self, f, flag): - edge_id = self.mesh.TopologyEdges.GetEdgesForFace(f) + # edge_id = self.mesh.TopologyEdges.GetEdgesForFace(f) ids = [0, 1] if flag else [1, 2] return ids @@ -483,9 +472,9 @@ def to_line(self, v, p, scale=1): def dihedral_plane(self, plane0, plane1): # Plane between two Planes - result, l = Rhino.Geometry.Intersect.Intersection.PlanePlane(plane0, plane1) - result, t = Rhino.Geometry.Intersect.Intersection.LinePlane(l, plane0) - centerDihedral = l.PointAt(t) + result, line = Rhino.Geometry.Intersect.Intersection.PlanePlane(plane0, plane1) + result, t = Rhino.Geometry.Intersect.Intersection.LinePlane(line, plane0) + centerDihedral = line.PointAt(t) # Convert ZAxis to lines, cant it be done on origin angleLine0 = self.to_line(plane0.ZAxis, plane0.Origin) @@ -504,7 +493,7 @@ def dihedral_plane(self, plane0, plane1): v1.Unitize() # Compute Plane - dihedralPlane = Rhino.Geometry.Plane(centerDihedral, l.Direction, v0 + v1) + dihedralPlane = Rhino.Geometry.Plane(centerDihedral, line.Direction, v0 + v1) return dihedralPlane else: @@ -657,7 +646,6 @@ def get_joinery_solver_output(self): v = [self.mesh.Faces[f].A, self.mesh.Faces[f].B, self.mesh.Faces[f].C, self.mesh.Faces[f].D] v0_0 = v[e[0]] v0_1 = v[(e[0] + 1) % 4] - v1_0 = v[e[1]] v1_1 = v[(e[1] + 1) % 4] dir0 = self.mesh.Vertices[v0_1] - self.mesh.Vertices[v0_0] @@ -723,7 +711,7 @@ def get_joinery_solver_output(self): ############################################################################## # Adjacency ############################################################################## - unique_key = set() + # Box adjacency counter = 0 for o in self.f_e.items(): @@ -824,7 +812,7 @@ def get_joinery_solver_output(self): counter += 1 def run(self): - if self.mesh == None: + if self.mesh is None: print("Mesh is not given") return self.stripper() @@ -844,9 +832,6 @@ class MyComponent(component): polylines = [] def DrawViewportWires(self, args): - - is_selected = False - col = args.WireColour line_weight = args.DefaultCurveThickness @@ -879,12 +864,12 @@ def RunScript( # ============================================================================== # clear input # ============================================================================== - bbox = Rhino.Geometry.BoundingBox.Unset - lines = [] - insertion_vectors_current = [] - joint_per_face_current_text_entity = [] - polylines = [] - if _mesh == None: + self.bbox = Rhino.Geometry.BoundingBox.Unset + self.lines = [] + self.insertion_vectors_current = [] + self.joint_per_face_current_text_entity = [] + self.polylines = [] + if _mesh is None: return ############################################################################## # Output diff --git a/src/rhino/gh/cpy/closest_indexed_points/code.py b/src/rhino/gh/cpy/closest_indexed_points/code.py index 6be34d299..589ddfb68 100644 --- a/src/rhino/gh/cpy/closest_indexed_points/code.py +++ b/src/rhino/gh/cpy/closest_indexed_points/code.py @@ -1,28 +1,9 @@ from ghpythonlib.componentbase import executingcomponent as component -import Grasshopper, GhPython -import System +import Grasshopper import Rhino -import rhinoscriptsyntax as rs - -"""Provides a scripting component. - Inputs: - x: The x script variable - y: The y script variable - Output: - a: The a output variable""" - -__author__ = "petra" -__version__ = "2023.04.04" - import Rhino.Geometry -from Rhino.Geometry import RTree -from Rhino.Geometry import BoundingBox from Rhino.Geometry import Sphere -from Rhino.Geometry import Vector3d -from Rhino.Geometry import Point3d from Rhino.Geometry import Polyline -from Rhino.Geometry import Line -import Grasshopper import ghpythonlib.treehelpers as th @@ -88,8 +69,6 @@ def RunScript( rtree.Insert(segments_dictionary[i][3], i) # call_backs of rtree - hit_count = 0 - def search_callback(sender, rtree_event_args): data_by_reference.append(rtree_event_args.Id) diff --git a/src/rhino/gh/cpy/closest_lines/code.py b/src/rhino/gh/cpy/closest_lines/code.py index 81b3b18b6..8a1abd007 100644 --- a/src/rhino/gh/cpy/closest_lines/code.py +++ b/src/rhino/gh/cpy/closest_lines/code.py @@ -1,21 +1,10 @@ from ghpythonlib.componentbase import executingcomponent as component -import Grasshopper, GhPython -import System +import Grasshopper import Rhino -import rhinoscriptsyntax as rs - -__author__ = "petra" -__version__ = "2023.04.04" -import System import Rhino.Geometry -from Rhino.Geometry import RTree -from Rhino.Geometry import BoundingBox from Rhino.Geometry import Sphere from Rhino.Geometry import Vector3d -from Rhino.Geometry import Point3d from Rhino.Geometry import Polyline -from Rhino.Geometry import Line -import Grasshopper import ghpythonlib.treehelpers as th @@ -78,9 +67,7 @@ def RunScript( for i in segments_dictionary: rtree.Insert(segments_dictionary[i][3], i) - # call_backs of rtree - hit_count = 0 - + # call_backs of rtree search def search_callback(sender, rtree_event_args): data_by_reference.append(rtree_event_args.Id) diff --git a/src/rhino/gh/cpy/connectors/code.py b/src/rhino/gh/cpy/connectors/code.py index 9e4931504..717cc53eb 100644 --- a/src/rhino/gh/cpy/connectors/code.py +++ b/src/rhino/gh/cpy/connectors/code.py @@ -1,10 +1,9 @@ from ghpythonlib.componentbase import executingcomponent as component -import Grasshopper, GhPython +import Grasshopper import System import Rhino import Rhino.Geometry import Rhino -import Grasshopper import ghpythonlib.treehelpers as th from Rhino.Geometry import ( Mesh, @@ -22,934 +21,891 @@ import math -class MyComponent(component): - def RunScript( +class case_2_vda: + def __init__( self, - _mesh: Rhino.Geometry.Mesh, - _face_positions: System.Collections.Generic.List[float], - _face_thickness: float, - _divisions: System.Collections.Generic.List[int], - _division_len: System.Collections.Generic.List[float], - _edge_vectors: System.Collections.Generic.List[Rhino.Geometry.Line], - _rect_width: float, - _rect_height: float, - _rect_thickness: float, - _projection: System.Collections.Generic.List[Rhino.Geometry.Brep], + m, + s, + face_thickness, + face_positions, + edge_divisions, + edge_division_len, + insertion_vectors, + rect_width, + rect_height, + rect_thickness, + chamfer, + projection_breps, ): - class case_2_vda: - def __init__( - self, - m, - s, - face_thickness, - face_positions, - edge_divisions, - edge_division_len, - insertion_vectors, - rect_width, - rect_height, - rect_thickness, - chamfer, - projection_breps, - ): - self.m = m - - if self.m == None: - # Create vertices - vertices = [] - vertices.append(Point3d(0, 0, 0)) - vertices.append(Point3d(100, 0, 0)) - vertices.append(Point3d(100, 100, 0)) - vertices.append(Point3d(0, 100, 0)) - - # Create faces - faces = [] - faces.append(MeshFace(0, 1, 2)) - faces.append(MeshFace(0, 2, 3)) - - # Create mesh - self.m = Mesh() - - # Add vertices to the mesh - for vertex in vertices: - self.m.Vertices.Add(vertex) - - # Add faces to the mesh - for face in faces: - self.m.Faces.AddFace(face) - - # Optional: Compute vertex normals - self.m.Normals.ComputeNormals() - - # Optional: Compact the mesh to remove unused vertices - self.m.Compact() - - # Optional: Update the mesh to display changes - self.m.FaceNormals.ComputeFaceNormals() - self.m.Normals.ComputeNormals() - self.m.Normals.UnitizeNormals() - Rhino.RhinoDoc.ActiveDoc.Objects.AddMesh(self.m) - - self.s = None - self.face_thickness = face_thickness if face_thickness is not None else 1 - self.face_positions = list(face_positions) if face_positions is not None else [0] - self.face_positions.sort() - - if len(self.face_positions) == 0: - self.face_positions = [0] - - self.projection_breps = projection_breps - self.edge_divisions = edge_divisions if edge_divisions is not None else [2] - self.edge_division_len = edge_division_len if edge_division_len is not None else [] - if len(self.edge_division_len) > 0: - if self.edge_division_len[0] < 0.01: - self.edge_division_len = [] - self.has_ngons = len(self.m.Ngons) > 0 - self.rect_width = rect_width if rect_width is not None else 10 - self.rect_height = rect_height if rect_height is not None else 10 - self.rect_thickness = rect_thickness if rect_thickness is not None else 1 - self.f = None - self.e = None - self.f_v = None - self.f_e = None - self.e_f = None - self.e_ngon_e = {} - self.f_planes = [] - self.fe_planes = [] - self.bi_planes = [] - self.e90_planes = [] - self.e90_multiple_planes = [] - self.e_lines = [] - self.f_polylines_index = [] - self.f_polylines_planes = [] - self.f_polylines = [] - self.e_polylines_index = [] - self.e_polylines_planes = [] - self.e_polylines = [] - - if self.m is not None: - if self.m.IsValid: - self.m.Weld(0.01) - self.m.RebuildNormals() - else: - return - else: - return - self.s = s - # run methods in constructor - self.get_face_vertices() - self.get_faces_planes() - self.get_face_edge_planes() - self.get_bisector_planes() - self.get_face_polylines(chamfer) - self.get_edges() - self.get_edge_faces() - self.get_edge_vectors(insertion_vectors) - self.get_edge_planes() - self.get_connectors() - - def vertex_topo_vertex(self, mesh, vertex_ids): - topo_vertices = [] - for i in range(len(vertex_ids)): - topo_vertices.append(mesh.TopologyVertices.TopologyVertexIndex(vertex_ids[i])) - - return topo_vertices - - def get_ngons_topo_boundaries(self, mesh): - boundaries = [] - for i in range(mesh.Ngons.Count): - boundaries.append(self.vertex_topo_vertex(mesh, mesh.Ngons[i].BoundaryVertexIndexList())) - - return boundaries - - def get_face_vertices(self): - if self.has_ngons: - self.f = self.m.Ngons.Count - self.f_v = self.get_ngons_topo_boundaries(m) - else: - self.f = self.m.Faces.Count - self.f_v = [] - for i in range(self.m.Faces.Count): - self.f_v.append( - [ - self.m.Faces[i][0], - self.m.Faces[i][1], - self.m.Faces[i][2], - self.m.Faces[i][3], - ] - if self.m.Faces[i].IsQuad - else [ - self.m.Faces[i][0], - self.m.Faces[i][1], - self.m.Faces[i][2], - ] - ) + self.m = m + + if self.m is None: + # Create vertices + vertices = [] + vertices.append(Point3d(0, 0, 0)) + vertices.append(Point3d(100, 0, 0)) + vertices.append(Point3d(100, 100, 0)) + vertices.append(Point3d(0, 100, 0)) + + # Create faces + faces = [] + faces.append(MeshFace(0, 1, 2)) + faces.append(MeshFace(0, 2, 3)) + + # Create mesh + self.m = Mesh() + + # Add vertices to the mesh + for vertex in vertices: + self.m.Vertices.Add(vertex) + + # Add faces to the mesh + for face in faces: + self.m.Faces.AddFace(face) + + # Optional: Compute vertex normals + self.m.Normals.ComputeNormals() + + # Optional: Compact the mesh to remove unused vertices + self.m.Compact() + + # Optional: Update the mesh to display changes + self.m.FaceNormals.ComputeFaceNormals() + self.m.Normals.ComputeNormals() + self.m.Normals.UnitizeNormals() + Rhino.RhinoDoc.ActiveDoc.Objects.AddMesh(self.m) + + self.s = None + self.face_thickness = face_thickness if face_thickness is not None else 1 + self.face_positions = list(face_positions) if face_positions is not None else [0] + self.face_positions.sort() + + if len(self.face_positions) == 0: + self.face_positions = [0] + + self.projection_breps = projection_breps + self.edge_divisions = edge_divisions if edge_divisions is not None else [2] + self.edge_division_len = edge_division_len if edge_division_len is not None else [] + if len(self.edge_division_len) > 0: + if self.edge_division_len[0] < 0.01: + self.edge_division_len = [] + self.has_ngons = len(self.m.Ngons) > 0 + self.rect_width = rect_width if rect_width is not None else 10 + self.rect_height = rect_height if rect_height is not None else 10 + self.rect_thickness = rect_thickness if rect_thickness is not None else 1 + self.f = None + self.e = None + self.f_v = None + self.f_e = None + self.e_f = None + self.e_ngon_e = {} + self.f_planes = [] + self.fe_planes = [] + self.bi_planes = [] + self.e90_planes = [] + self.e90_multiple_planes = [] + self.e_lines = [] + self.f_polylines_index = [] + self.f_polylines_planes = [] + self.f_polylines = [] + self.e_polylines_index = [] + self.e_polylines_planes = [] + self.e_polylines = [] + + if self.m is not None: + if self.m.IsValid: + self.m.Weld(0.01) + self.m.RebuildNormals() + else: + return + else: + return + self.s = s + # run methods in constructor + self.get_face_vertices() + self.get_faces_planes() + self.get_face_edge_planes() + self.get_bisector_planes() + self.get_face_polylines(chamfer) + self.get_edges() + self.get_edge_faces() + self.get_edge_vectors(insertion_vectors) + self.get_edge_planes() + self.get_connectors() + + def vertex_topo_vertex(self, mesh, vertex_ids): + topo_vertices = [] + for i in range(len(vertex_ids)): + topo_vertices.append(mesh.TopologyVertices.TopologyVertexIndex(vertex_ids[i])) + + return topo_vertices + + def get_ngons_topo_boundaries(self, mesh): + boundaries = [] + for i in range(mesh.Ngons.Count): + boundaries.append(self.vertex_topo_vertex(mesh, mesh.Ngons[i].BoundaryVertexIndexList())) + + return boundaries + + def get_face_vertices(self): + if self.has_ngons: + self.f = self.m.Ngons.Count + self.f_v = self.get_ngons_topo_boundaries(self.m) + else: + self.f = self.m.Faces.Count + self.f_v = [] + for i in range(self.m.Faces.Count): + self.f_v.append( + [ + self.m.Faces[i][0], + self.m.Faces[i][1], + self.m.Faces[i][2], + self.m.Faces[i][3], + ] + if self.m.Faces[i].IsQuad + else [ + self.m.Faces[i][0], + self.m.Faces[i][1], + self.m.Faces[i][2], + ] + ) - # print(self.f) - # print(self.f_v) + def get_normal(self, mesh, f): + vector3d = Vector3f(0, 0, 0) - def get_normal(self, mesh, f): - vector3d = Vector3f(0, 0, 0) + faces = mesh.Ngons[f].FaceIndexList() - faces = mesh.Ngons[f].FaceIndexList() + for i in range(len(faces)): + vector3d += mesh.FaceNormals[faces[i]] - for i in range(len(faces)): - vector3d += mesh.FaceNormals[faces[i]] + vector3d.Unitize() - vector3d.Unitize() + return Vector3d(vector3d) - return Vector3d(vector3d) + def center_point(self, polyline): + count = len(polyline) - def center_point(self, polyline): - count = len(polyline) + if count == 0: + return Point3d.Unset - if count == 0: - return Point3d.Unset + if count == 1: + return polyline[0] - if count == 1: - return polyline[0] + center = Point3d.Origin + weight = 0.0 - center = Point3d.Origin - weight = 0.0 + stop = count - 1 + if polyline[0].DistanceToSquared(polyline[polyline.Count - 1]) > 0.001: + stop += 1 - stop = count - 1 - if polyline[0].DistanceToSquared(polyline[polyline.Count - 1]) > 0.001: - stop += 1 + for i in range(stop): + A = polyline[i] + B = polyline[(i + 1) % count] + d = A.DistanceTo(B) + center += d * 0.5 * (A + B) + weight += d - for i in range(stop): - A = polyline[i] - B = polyline[(i + 1) % count] - d = A.DistanceTo(B) - center += d * 0.5 * (A + B) - weight += d + center /= weight - center /= weight + return center - return center + def face_center(self, mesh, f): + vertices = mesh.Ngons.GetNgon(f).BoundaryVertexIndexList() + outline = Polyline() + for v in vertices: + outline.Add(mesh.Vertices[v]) + return self.center_point(outline) - def face_center(self, mesh, f): - vertices = mesh.Ngons.GetNgon(f).BoundaryVertexIndexList() - outline = Polyline() - for v in vertices: - outline.Add(mesh.Vertices[v]) - return self.center_point(outline) + def get_plane(self, mesh, f): + return Plane(self.face_center(mesh, f), self.get_normal(mesh, f)) - def get_plane(self, mesh, f): - return Plane(self.face_center(mesh, f), self.get_normal(mesh, f)) + def get_f_planes(self, mesh): + planes = [] + for i in range(mesh.Ngons.Count): + plane = self.get_plane(mesh, i) + planes.append(plane) + return planes - def get_f_planes(self, mesh): - planes = [] - for i in range(mesh.Ngons.Count): - plane = self.get_plane(mesh, i) - planes.append(plane) - return planes + def get_faces_planes(self): + if self.has_ngons: + self.f_planes = self.get_f_planes(self.m) + else: + self.f_planes = [None] * self.m.Faces.Count + for i in range(self.m.Faces.Count): + center = self.m.Faces.GetFaceCenter(i) + self.f_planes[i] = Plane(center, self.m.FaceNormals[i]) - def get_faces_planes(self): - if self.has_ngons: - self.f_planes = self.get_f_planes(self.m) - else: - self.f_planes = [None] * self.m.Faces.Count - for i in range(self.m.Faces.Count): - center = self.m.Faces.GetFaceCenter(i) - self.f_planes[i] = Plane(center, self.m.FaceNormals[i]) + # Adjust to surface + if self.s is not None: + for i in range(len(self.f_planes)): + u, v = None, None + self.s.ClosestPoint(self.f_planes[i].Origin, u, v) + normal = self.s.NormalAt(u, v) + xaxis = Vector3d.CrossProduct(normal, self.f_planes[i].YAxis) + yaxis = Vector3d.CrossProduct(normal, xaxis) + self.f_planes[i] = Plane(self.f_planes[i].Origin, xaxis, yaxis) + + def get_face_edge_planes(self): + self.fe_planes = [] + + for i in range(self.f): + n = len(self.f_v[i]) + self.fe_planes.append([None] * n) + + for j in range(len(self.f_v[i])): + v1 = self.f_v[i][(j + 0) % n] + v2 = self.f_v[i][(j + 1) % n] + + e = self.m.TopologyEdges.GetEdgeIndex(v1, v2) + cf = self.m.TopologyEdges.GetConnectedFaces(e) + + sum = Vector3f.Zero + for k in range(len(cf)): + sum += self.m.FaceNormals[cf[k]] + sum /= len(cf) + + edgePlane = Plane( + Point3d(self.m.Vertices[v1] + self.m.Vertices[v2]) * 0.5, + self.m.Vertices[v1] - self.m.Vertices[v2], + sum, + ) + self.fe_planes[i][j] = edgePlane # Adjust to surface if self.s is not None: - for i in range(len(f_planes)): - u, v = None, None - s.ClosestPoint(f_planes[i].Origin, u, v) - normal = s.NormalAt(u, v) - xaxis = Vector3d.CrossProduct(normal, f_planes[i].YAxis) - yaxis = Vector3d.CrossProduct(normal, xaxis) - self.f_planes[i] = Plane(f_planes[i].Origin, xaxis, yaxis) - - # print(self.f_planes) - - def get_face_edge_planes(self): - self.fe_planes = [] - - for i in range(self.f): - n = len(self.f_v[i]) - self.fe_planes.append([None] * n) - - for j in range(len(self.f_v[i])): - v1 = self.f_v[i][(j + 0) % n] - v2 = self.f_v[i][(j + 1) % n] - - e = self.m.TopologyEdges.GetEdgeIndex(v1, v2) - cf = self.m.TopologyEdges.GetConnectedFaces(e) - - sum = Vector3f.Zero - for k in range(len(cf)): - sum += self.m.FaceNormals[cf[k]] - sum /= len(cf) - - edgePlane = Plane( - Point3d(self.m.Vertices[v1] + self.m.Vertices[v2]) * 0.5, - self.m.Vertices[v1] - self.m.Vertices[v2], - sum, + u, v = None, None + self.s.ClosestPoint(self.fe_planes[i][j].Origin, u, v) + normal = self.s.NormalAt(u, v) + self.fe_planes[i][j] = Plane( + self.fe_planes[i][j].Origin, + Vector3d.CrossProduct(normal, self.fe_planes[i][j].ZAxis), + normal, + ) + + for brep in self.projection_breps: + if brep.IsPointInside(self.fe_planes[i][j].Origin, 0.01, False): + xform = Rhino.Geometry.Transform.PlanarProjection(Plane.WorldXY) + self.fe_planes[i][j].Transform(xform) + + def to_line(self, v, p, scale=1): + return Line(p, p + v * scale) + + def dihedral_plane(self, plane0, plane1): + # Plane between two Planes + result, line = Rhino.Geometry.Intersect.Intersection.PlanePlane(plane0, plane1) + result, t = Rhino.Geometry.Intersect.Intersection.LinePlane(line, plane0) + centerDihedral = line.PointAt(t) + + # Convert ZAxis to lines, cant it be done on origin + angleLine0 = self.to_line(plane0.ZAxis, plane0.Origin) + angleLine1 = self.to_line(plane1.ZAxis, plane1.Origin) + + # Plane cannot be anti/parallel and they must be apart from each other + if not plane0.ZAxis.IsParallelTo(plane1.ZAxis, 0.01) and plane0.Origin.DistanceToSquared(plane1.Origin) > 0.001: + # Intersect two lines to get center + result, t0, t1 = Rhino.Geometry.Intersect.Intersection.LineLine(angleLine0, angleLine1, 0.01, False) + + # Construct plane from LineLine center and plane origins + center = angleLine0.PointAt(t0) + v0 = plane0.Origin - center + v1 = plane1.Origin - center + v0.Unitize() + v1.Unitize() + + # Compute Plane + dihedralPlane = Rhino.Geometry.Plane(centerDihedral, line.Direction, v0 + v1) + + return dihedralPlane + else: + return Rhino.Geometry.Plane.Unset # Axes are parallel or anti-parallel, or planes are at the same location + + def get_bisector_planes(self): + self.bi_planes = [] + + for i in range(self.f): + n = len(self.f_v[i]) + self.bi_planes.append([None] * n) + + for j in range(n): + pl1 = self.fe_planes[i][j] + pl0 = self.fe_planes[i][(j + 1) % n] + self.bi_planes[i][j] = self.dihedral_plane(pl0, pl1) + + # print(self.bi_planes) + + def face_vertices(self, mesh, F, topo): + uintv = mesh.Ngons[F].BoundaryVertexIndexList() + v = [] + for i in range(len(uintv)): + if topo: + v.append(int(uintv[i])) + else: + v.append(mesh.TopologyVertices.TopologyVertexIndex(int(uintv[i]))) + + return v + + def e_all(self, mesh): + all_e = {} + hash_set = set() + counter = 0 + + try: + for i in range(mesh.Ngons.Count): + n = mesh.Ngons[i].BoundaryVertexCount + fv = self.face_vertices(mesh, i, True) + + for j in range(n - 1): + et = mesh.TopologyEdges.GetEdgeIndex(fv[j], fv[j + 1]) + if et not in hash_set: + hash_set.add(et) + all_e[et] = counter + counter += 1 + + e = mesh.TopologyEdges.GetEdgeIndex(fv[0], fv[n - 1]) + if e not in hash_set: + hash_set.add(e) + all_e[e] = counter + counter += 1 + except Exception as e: + Rhino.RhinoApp.WriteLine(str(e)) + return all_e + + def get_edges(self): + if self.has_ngons: + self.e_ngon_e = self.e_all(self.m) + self.e = len(self.e_ngon_e) + else: + self.e_ngon_e = {} + + for i in range(self.m.TopologyEdges.Count): + self.e_ngon_e[i] = i + self.e = len(self.e_ngon_e) + + def _ef(self, mesh, mesh_edge): + # Get connected mesh faces + connected_faces = mesh.TopologyEdges.GetConnectedFaces(mesh_edge) + connected_ngons = [] + + for face_index in connected_faces: + connected_ngons.append(mesh.Ngons.NgonIndexFromFaceIndex(face_index)) + + return connected_ngons + + def _EF(self, mesh): + e_all = self.e_all(mesh) + ef = [None] * len(e_all) + # print(e_all) + # count = 0 + for mesh_edge_id in e_all: + # print(edge_id) + ef[e_all[mesh_edge_id]] = self._ef(mesh, mesh_edge_id) + """ + ef.append(self._ef(mesh, mesh_edge_id)) + if(count == 198): + print(self._ef(mesh, mesh_edge_id)) + """ + # count = count + 1 + # print(ef[198]) + return ef + + def get_edge_faces(self): + if self.has_ngons: + self.e_f = self._EF(self.m) + # print(len(self.e_f)) + # print(self.e_f[0]) + else: + self.e_f = [] + for i in range(self.m.TopologyEdges.Count): + self.e_f.append(self.m.TopologyEdges.GetConnectedFaces(i)) + + found_ids = [] + + def get_edge_vectors(self, lines): + # Init empty vectors + self.insertion_vectors = [Vector3d.Zero] * self.e + + # Get edge lines including naked + self.e_lines = [Line.Unset] * self.e + for pair in self.e_ngon_e: + # print(self.e_ngon_e[pair]) + self.e_lines[self.e_ngon_e[pair]] = self.m.TopologyEdges.EdgeLine(pair) + if len(lines) == 0: + return + # Create rtree and add lines + rTree = Rhino.Geometry.RTree() + for i in range(len(self.e_lines)): + bbox = self.e_lines[i].BoundingBox + bbox.Inflate(1) + rTree.Insert(bbox, i) + + # Search tree + for i in range(len(lines)): + bbox = lines[i].BoundingBox + bbox.Inflate(Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance) + bbox.Inflate(1) + # print(bbox.IsValid) + rTree.Search(lines[i].BoundingBox, self.BoundingBoxCallback, self.found_ids) + + # Iterate through found ids and check if end point lies on a mesh edge + for id in self.found_ids: + # print(id) + if ( + self.e_lines[id].ClosestPoint(lines[i].From, True).DistanceToSquared(lines[i].From) + < Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance + ): + self.insertion_vectors[id] = lines[i].Direction + self.insertion_vectors[id].Unitize() + elif ( + self.e_lines[id].ClosestPoint(lines[i].To, True).DistanceToSquared(lines[i].To) + < Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance + ): + self.insertion_vectors[id] = lines[i].Direction + self.insertion_vectors[id].Unitize() + + self.found_ids = [] + + def BoundingBoxCallback(self, sender, e): + # print("Hi") + self.found_ids.append(e.Id) + + def constrain(self, x, min_val, max_val): + return max(min_val, min(x, max_val)) + + def interpolate_points(self, from_pt, to_pt, steps, include_ends=True): + if include_ends: + point3d_array = [from_pt] + for i in range(1, steps + 1): + num = i / (1.0 + steps) + interpolated_pt = Point3d( + from_pt.X + num * (to_pt.X - from_pt.X), + from_pt.Y + num * (to_pt.Y - from_pt.Y), + from_pt.Z + num * (to_pt.Z - from_pt.Z), + ) + point3d_array.append(interpolated_pt) + point3d_array.append(to_pt) + else: + point3d_array = [] + for i in range(1, steps + 1): + num = i / (1.0 + steps) + interpolated_pt = Point3d( + from_pt.X + num * (to_pt.X - from_pt.X), + from_pt.Y + num * (to_pt.Y - from_pt.Y), + from_pt.Z + num * (to_pt.Z - from_pt.Z), + ) + point3d_array.append(interpolated_pt) + return point3d_array + + def change_origin(self, pl, p): + return Rhino.Geometry.Plane(p, pl.XAxis, pl.YAxis) + + def get_edge_planes(self): + self.e90_planes = [None] * len(self.e_ngon_e) + self.e90_multiple_planes = [[] for _ in range(len(self.e_ngon_e))] + + count = 0 + # print(self.e_ngon_e) + for id in self.e_ngon_e: # id mesh edge - i ngon edge + # for i in range(len(self.e_ngon_e)): + + # print(self.e_ngon_e) + i = self.e_ngon_e[id] + + # print(i) + # print(id) + # print(len(self.f_planes)) + if len(self.m.TopologyEdges.GetConnectedFaces(id)) == 1: + self.e90_planes[i] = Plane.Unset + self.e90_multiple_planes[i] = [Plane.Unset] + continue + # print(id) + # print(i) + # print(self.e_f) + edge_line = self.m.TopologyEdges.EdgeLine(id) + origin = edge_line.PointAt(0.5) + zaxis = edge_line.Direction + zaxis.Unitize() + pair = self.m.TopologyEdges.GetTopologyVertices(id) + # edge vertex normals + yaxis = ((Vector3d(self.m.Normals[pair.I]) + Vector3d(self.m.Normals[pair.J]))) * 0.5 + # or face normals + # print(len(self.f_planes)) + # print(i) + # print(self.e_f[i]) + + # print(self.e_f[i][0]) + # print(self.e_f[i][1]) + + yaxis = (self.f_planes[self.e_f[i][0]].ZAxis + self.f_planes[self.e_f[i][1]].ZAxis) * 0.5 + + # self.f_planes[] + + if self.s is not None: + u, v = self.s.ClosestPoint(origin) + yaxis = self.s.NormalAt(u, v) + + xaxis = Vector3d.CrossProduct(zaxis, yaxis) + + # orient x-axis towards first edge index + if (origin + xaxis).DistanceToSquared(self.f_planes[self.e_f[i][0]].Origin) < ( + origin - xaxis + ).DistanceToSquared(self.f_planes[self.e_f[i][0]].Origin): + xaxis *= -1 + + # Incase insertion vectors are given + # print(self.insertion_vectors[i]) + if ( + abs(self.insertion_vectors[i].X) + abs(self.insertion_vectors[i].Y) + abs(self.insertion_vectors[i].Z) + > 0.01 + ): + # Project given vector to a plane + edge_plane = Plane(self.e_lines[i].PointAt(0.5), yaxis) + xform = Transform.PlanarProjection(edge_plane) + xaxis_ = self.insertion_vectors[i] + xaxis_.Transform(xform) + # print (xaxis_) + if (Point3d.Origin + xaxis_).DistanceToSquared(Point3d.Origin + xaxis) > ( + Point3d.Origin - xaxis_ + ).DistanceToSquared(Point3d.Origin + xaxis): + xaxis_ *= -1 + xaxis = xaxis_ + + # set plane + self.e90_planes[i] = Plane(origin, xaxis, yaxis) + # 1) By N 2) by division length 3) in both cases consider lists + # Skip emppty + + self.divisions = 1 + + if len(self.edge_division_len) > 0: + if len(self.edge_division_len) == self.e: + self.divisions = int( + ( + self.constrain( + edge_line.Length / self.edge_division_len[i], + 1, + 10, + ) ) - self.fe_planes[i][j] = edgePlane - - # Adjust to surface - if self.s is not None: - u, v = None, None - s.ClosestPoint(self.fe_planes[i][j].Origin, u, v) - normal = s.NormalAt(u, v) - self.fe_planes[i][j] = Plane( - self.fe_planes[i][j].Origin, - Vector3d.CrossProduct(normal, self.fe_planes[i][j].ZAxis), - normal, + ) + else: + self.divisions = int( + ( + self.constrain( + edge_line.Length / self.edge_division_len[0], + 1, + 10, ) + ) + ) + elif len(self.edge_divisions) > 0: + if len(self.edge_divisions) != self.e: + self.divisions = int(self.edge_divisions[0]) + else: + self.divisions = int(self.edge_divisions[i]) + pts = self.interpolate_points(edge_line.From, edge_line.To, self.divisions, False) + # print(self.divisions) + # print(edge_line.Length) - for brep in self.projection_breps: - if brep.IsPointInside(self.fe_planes[i][j].Origin, 0.01, False): - xform = Rhino.Geometry.Transform.PlanarProjection(Plane.WorldXY) - self.fe_planes[i][j].Transform(xform) + self.e90_multiple_planes[i] = [self.change_origin(self.e90_planes[i], pt) for pt in pts] + count = count + 1 - # print(self.fe_planes) + def polyline_from_planes(self, basePlane, sidePlanes, close=True): + polyline = Rhino.Geometry.Polyline() - def to_line(self, v, p, scale=1): - return Line(p, p + v * scale) + for i in range(len(sidePlanes) - 1): + result, pt = Rhino.Geometry.Intersect.Intersection.PlanePlanePlane( + basePlane, sidePlanes[i], sidePlanes[i + 1] + ) + polyline.Add(pt) - def dihedral_plane(self, plane0, plane1): - # Plane between two Planes - result, l = Rhino.Geometry.Intersect.Intersection.PlanePlane(plane0, plane1) - result, t = Rhino.Geometry.Intersect.Intersection.LinePlane(l, plane0) - centerDihedral = l.PointAt(t) + result, pt1 = Rhino.Geometry.Intersect.Intersection.PlanePlanePlane( + basePlane, sidePlanes[len(sidePlanes) - 1], sidePlanes[0] + ) + polyline.Add(pt1) - # Convert ZAxis to lines, cant it be done on origin - angleLine0 = self.to_line(plane0.ZAxis, plane0.Origin) - angleLine1 = self.to_line(plane1.ZAxis, plane1.Origin) + if close: + polyline.Add(polyline[0]) - # Plane cannot be anti/parallel and they must be apart from each other - if ( - not plane0.ZAxis.IsParallelTo(plane1.ZAxis, 0.01) - and plane0.Origin.DistanceToSquared(plane1.Origin) > 0.001 - ): - # Intersect two lines to get center - result, t0, t1 = Rhino.Geometry.Intersect.Intersection.LineLine(angleLine0, angleLine1, 0.01, False) + return polyline - # Construct plane from LineLine center and plane origins - center = angleLine0.PointAt(t0) - v0 = plane0.Origin - center - v1 = plane1.Origin - center - v0.Unitize() - v1.Unitize() + def get_connectors(self): + self.e_polylines = [] + self.e_polylines_planes = [] + self.e_polylines_index = [] - # Compute Plane - dihedralPlane = Rhino.Geometry.Plane(centerDihedral, l.Direction, v0 + v1) + for i in range(len(self.e90_multiple_planes)): + self.e_polylines.append([None] * (len(self.e90_multiple_planes[i]) * 2)) + self.e_polylines_planes.append([None] * len(self.e90_multiple_planes[i])) + self.e_polylines_index.append([None] * len(self.e90_multiple_planes[i])) - return dihedralPlane - else: - return ( - Rhino.Geometry.Plane.Unset - ) # Axes are parallel or anti-parallel, or planes are at the same location - - def get_bisector_planes(self): - self.bi_planes = [] - - for i in range(self.f): - n = len(self.f_v[i]) - self.bi_planes.append([None] * n) - - for j in range(n): - pl1 = self.fe_planes[i][j] - pl0 = self.fe_planes[i][(j + 1) % n] - self.bi_planes[i][j] = self.dihedral_plane(pl0, pl1) - - # print(self.bi_planes) - - def face_vertices(self, mesh, F, topo): - uintv = mesh.Ngons[F].BoundaryVertexIndexList() - v = [] - for i in range(len(uintv)): - if topo: - v.append(int(uintv[i])) - else: - v.append(mesh.TopologyVertices.TopologyVertexIndex(int(uintv[i]))) - - return v - - def e_all(self, mesh): - all_e = {} - hash_set = set() - counter = 0 - - try: - for i in range(mesh.Ngons.Count): - n = mesh.Ngons[i].BoundaryVertexCount - fv = self.face_vertices(mesh, i, True) - - for j in range(n - 1): - et = mesh.TopologyEdges.GetEdgeIndex(fv[j], fv[j + 1]) - if et not in hash_set: - hash_set.add(et) - all_e[et] = counter - counter += 1 - - e = mesh.TopologyEdges.GetEdgeIndex(fv[0], fv[n - 1]) - if e not in hash_set: - hash_set.add(e) - all_e[e] = counter - counter += 1 - except Exception as e: - Rhino.RhinoApp.WriteLine(str(e)) - return all_e - - def get_edges(self): - if self.has_ngons: - self.e_ngon_e = self.e_all(self.m) - self.e = len(self.e_ngon_e) + for j in range(len(self.e90_multiple_planes[i])): + if self.e90_multiple_planes[i][j] == Plane.Unset: + self.e_polylines[i] = [] + self.e_polylines_planes[i][j] = None + self.e_polylines_index[i][j] = None else: - self.e_ngon_e = {} - - for i in range(self.m.TopologyEdges.Count): - self.e_ngon_e[i] = i - self.e = len(self.e_ngon_e) - - def _ef(self, mesh, mesh_edge): - # Get connected mesh faces - connected_faces = mesh.TopologyEdges.GetConnectedFaces(mesh_edge) - connected_ngons = [] - - for face_index in connected_faces: - connected_ngons.append(mesh.Ngons.NgonIndexFromFaceIndex(face_index)) - - return connected_ngons - - def _EF(self, mesh): - e_all = self.e_all(mesh) - ef = [None] * len(e_all) - # print(e_all) - # count = 0 - for mesh_edge_id in e_all: - # print(edge_id) - ef[e_all[mesh_edge_id]] = self._ef(mesh, mesh_edge_id) - """ - ef.append(self._ef(mesh, mesh_edge_id)) - if(count == 198): - print(self._ef(mesh, mesh_edge_id)) - """ - # count = count + 1 - # print(ef[198]) - return ef - - def get_edge_faces(self): - if self.has_ngons: - self.e_f = self._EF(self.m) - # print(len(self.e_f)) - # print(self.e_f[0]) - else: - self.e_f = [] - for i in range(self.m.TopologyEdges.Count): - self.e_f.append(self.m.TopologyEdges.GetConnectedFaces(i)) - - found_ids = [] - - def get_edge_vectors(self, lines): - # Init empty vectors - self.insertion_vectors = [Vector3d.Zero] * self.e - - # Get edge lines including naked - self.e_lines = [Line.Unset] * self.e - for pair in self.e_ngon_e: - # print(self.e_ngon_e[pair]) - self.e_lines[self.e_ngon_e[pair]] = self.m.TopologyEdges.EdgeLine(pair) - if len(lines) == 0: - return - # Create rtree and add lines - rTree = Rhino.Geometry.RTree() - for i in range(len(self.e_lines)): - bbox = self.e_lines[i].BoundingBox - bbox.Inflate(1) - rTree.Insert(bbox, i) - - # Search tree - for i in range(len(lines)): - bbox = lines[i].BoundingBox - bbox.Inflate(Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance) - bbox.Inflate(1) - # print(bbox.IsValid) - rTree.Search(lines[i].BoundingBox, self.BoundingBoxCallback, self.found_ids) - - # Iterate through found ids and check if end point lies on a mesh edge - for id in self.found_ids: - # print(id) - if ( - self.e_lines[id].ClosestPoint(lines[i].From, True).DistanceToSquared(lines[i].From) - < Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance - ): - self.insertion_vectors[id] = lines[i].Direction - self.insertion_vectors[id].Unitize() - elif ( - self.e_lines[id].ClosestPoint(lines[i].To, True).DistanceToSquared(lines[i].To) - < Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance - ): - self.insertion_vectors[id] = lines[i].Direction - self.insertion_vectors[id].Unitize() - - self.found_ids = [] - - def BoundingBoxCallback(self, sender, e): - # print("Hi") - self.found_ids.append(e.Id) - - def constrain(self, x, min_val, max_val): - return max(min_val, min(x, max_val)) - - def interpolate_points(self, from_pt, to_pt, steps, include_ends=True): - if include_ends: - point3d_array = [from_pt] - for i in range(1, steps + 1): - num = i / (1.0 + steps) - interpolated_pt = Point3d( - from_pt.X + num * (to_pt.X - from_pt.X), - from_pt.Y + num * (to_pt.Y - from_pt.Y), - from_pt.Z + num * (to_pt.Z - from_pt.Z), + if self.rect_height > 0 and self.rect_width > 0: + # type0 + rect0 = Rectangle3d( + self.move_plane_by_axis( + self.e90_multiple_planes[i][j], + self.rect_thickness * 0.5, + ), + Interval(-self.rect_width * 0.5, self.rect_width * 0.5), + Interval(-self.rect_height * 0.5, self.rect_height * 0.5), ) - point3d_array.append(interpolated_pt) - point3d_array.append(to_pt) - else: - point3d_array = [] - for i in range(1, steps + 1): - num = i / (1.0 + steps) - interpolated_pt = Point3d( - from_pt.X + num * (to_pt.X - from_pt.X), - from_pt.Y + num * (to_pt.Y - from_pt.Y), - from_pt.Z + num * (to_pt.Z - from_pt.Z), + rect1 = Rectangle3d( + self.move_plane_by_axis( + self.e90_multiple_planes[i][j], + self.rect_thickness * -0.5, + ), + Interval(-self.rect_width * 0.5, self.rect_width * 0.5), + Interval(-self.rect_height * 0.5, self.rect_height * 0.5), + ) + self.e_polylines[i][j * 2 + 0] = rect0.ToPolyline() + self.e_polylines[i][j * 2 + 1] = rect1.ToPolyline() + + elif self.rect_height <= 0 and self.rect_width <= 0: + w = abs(self.rect_height) + h = abs(self.rect_width) + + # type1 + e_plane = Plane(self.e90_multiple_planes[i][j]) + e_plane.Rotate(math.pi * 0.5, e_plane.YAxis) + top_plane_0 = self.move_plane_by_axis( + self.move_plane_by_axis( + self.f_planes[self.e_f[i][0]], + self.face_positions[-1], + ), + self.face_thickness * 0.5 + h, + ) + top_plane_1 = self.move_plane_by_axis( + self.move_plane_by_axis( + self.f_planes[self.e_f[i][1]], + self.face_positions[-1], + ), + self.face_thickness * 0.5 + h, + ) + bot_plane_0 = self.move_plane_by_axis( + self.move_plane_by_axis( + self.f_planes[self.e_f[i][0]], + self.face_positions[0], + ), + self.face_thickness * -0.5 - h, + ) + bot_plane_1 = self.move_plane_by_axis( + self.move_plane_by_axis( + self.f_planes[self.e_f[i][1]], + self.face_positions[0], + ), + self.face_thickness * -0.5 - h, ) - point3d_array.append(interpolated_pt) - return point3d_array - - def change_origin(self, pl, p): - return Rhino.Geometry.Plane(p, pl.XAxis, pl.YAxis) - - def get_edge_planes(self): - self.e90_planes = [None] * len(self.e_ngon_e) - self.e90_multiple_planes = [[] for _ in range(len(self.e_ngon_e))] - - count = 0 - # print(self.e_ngon_e) - for id in self.e_ngon_e: # id mesh edge - i ngon edge - # for i in range(len(self.e_ngon_e)): - - # print(self.e_ngon_e) - i = self.e_ngon_e[id] - - # print(i) - # print(id) - # print(len(self.f_planes)) - if len(self.m.TopologyEdges.GetConnectedFaces(id)) == 1: - self.e90_planes[i] = Plane.Unset - self.e90_multiple_planes[i] = [Plane.Unset] - continue - # print(id) - # print(i) - # print(self.e_f) - edge_line = self.m.TopologyEdges.EdgeLine(id) - origin = edge_line.PointAt(0.5) - zaxis = edge_line.Direction - zaxis.Unitize() - pair = self.m.TopologyEdges.GetTopologyVertices(id) - # edge vertex normals - yaxis = ((Vector3d(self.m.Normals[pair.I]) + Vector3d(self.m.Normals[pair.J]))) * 0.5 - # or face normals - # print(len(self.f_planes)) - # print(i) - # print(self.e_f[i]) - - # print(self.e_f[i][0]) - # print(self.e_f[i][1]) - - yaxis = (self.f_planes[self.e_f[i][0]].ZAxis + self.f_planes[self.e_f[i][1]].ZAxis) * 0.5 - - # self.f_planes[] - - if self.s is not None: - u, v = self.s.ClosestPoint(origin) - yaxis = self.s.NormalAt(u, v) - - xaxis = Vector3d.CrossProduct(zaxis, yaxis) - - # orient x-axis towards first edge index - if (origin + xaxis).DistanceToSquared(self.f_planes[self.e_f[i][0]].Origin) < ( - origin - xaxis - ).DistanceToSquared(self.f_planes[self.e_f[i][0]].Origin): - xaxis *= -1 - - # Incase insertion vectors are given - # print(self.insertion_vectors[i]) - if ( - abs(self.insertion_vectors[i].X) - + abs(self.insertion_vectors[i].Y) - + abs(self.insertion_vectors[i].Z) - > 0.01 - ): - # Project given vector to a plane - edge_plane = Plane(self.e_lines[i].PointAt(0.5), yaxis) - xform = Transform.PlanarProjection(edge_plane) - xaxis_ = self.insertion_vectors[i] - xaxis_.Transform(xform) - # print (xaxis_) - if (Point3d.Origin + xaxis_).DistanceToSquared(Point3d.Origin + xaxis) > ( - Point3d.Origin - xaxis_ - ).DistanceToSquared(Point3d.Origin + xaxis): - xaxis_ *= -1 - xaxis = xaxis_ - - # set plane - self.e90_planes[i] = Plane(origin, xaxis, yaxis) - # 1) By N 2) by division length 3) in both cases consider lists - # Skip emppty - - self.divisions = 1 - - if len(self.edge_division_len) > 0: - if len(self.edge_division_len) == self.e: - self.divisions = int( - ( - self.constrain( - edge_line.Length / self.edge_division_len[i], - 1, - 10, - ) - ) - ) - else: - self.divisions = int( - ( - self.constrain( - edge_line.Length / self.edge_division_len[0], - 1, - 10, - ) - ) - ) - elif len(self.edge_divisions) > 0: - if len(self.edge_divisions) != self.e: - self.divisions = int(self.edge_divisions[0]) - else: - self.divisions = int(self.edge_divisions[i]) - pts = self.interpolate_points(edge_line.From, edge_line.To, self.divisions, False) - # print(self.divisions) - # print(edge_line.Length) - - self.e90_multiple_planes[i] = [self.change_origin(self.e90_planes[i], pt) for pt in pts] - count = count + 1 - - def polyline_from_planes(self, basePlane, sidePlanes, close=True): - polyline = Rhino.Geometry.Polyline() - - for i in range(len(sidePlanes) - 1): - result, pt = Rhino.Geometry.Intersect.Intersection.PlanePlanePlane( - basePlane, sidePlanes[i], sidePlanes[i + 1] - ) - polyline.Add(pt) - result, pt1 = Rhino.Geometry.Intersect.Intersection.PlanePlanePlane( - basePlane, sidePlanes[len(sidePlanes) - 1], sidePlanes[0] - ) - polyline.Add(pt1) - - if close: - polyline.Add(polyline[0]) - - return polyline - - def get_connectors(self): - self.e_polylines = [] - self.e_polylines_planes = [] - self.e_polylines_index = [] - - for i in range(len(self.e90_multiple_planes)): - self.e_polylines.append([None] * (len(self.e90_multiple_planes[i]) * 2)) - self.e_polylines_planes.append([None] * len(self.e90_multiple_planes[i])) - self.e_polylines_index.append([None] * len(self.e90_multiple_planes[i])) - - for j in range(len(self.e90_multiple_planes[i])): - if self.e90_multiple_planes[i][j] == Plane.Unset: - self.e_polylines[i] = [] - self.e_polylines_planes[i][j] = None - self.e_polylines_index[i][j] = None - else: - if self.rect_height > 0 and self.rect_width > 0: - # type0 - rect0 = Rectangle3d( - self.move_plane_by_axis( - self.e90_multiple_planes[i][j], - self.rect_thickness * 0.5, - ), - Interval(-self.rect_width * 0.5, self.rect_width * 0.5), - Interval(-self.rect_height * 0.5, self.rect_height * 0.5), - ) - rect1 = Rectangle3d( - self.move_plane_by_axis( - self.e90_multiple_planes[i][j], - self.rect_thickness * -0.5, - ), - Interval(-self.rect_width * 0.5, self.rect_width * 0.5), - Interval(-self.rect_height * 0.5, self.rect_height * 0.5), - ) - self.e_polylines[i][j * 2 + 0] = rect0.ToPolyline() - self.e_polylines[i][j * 2 + 1] = rect1.ToPolyline() - # if(len(self.e_f[i])==2): - # if (self.e_f[i][0] == 99 or self.e_f[i][0] == 89 ) and(self.e_f[i][1] == 99 or self.e_f[i][1] == 89 ): - # print (self.e90_multiple_planes[i][j]) - # Rhino.RhinoDoc.ActiveDoc.Objects.AddPoint(rect0.ToPolyline()[0] ) - # Rhino.RhinoDoc.ActiveDoc.Objects.AddPoint(rect0.ToPolyline()[1] ) - # Rhino.RhinoDoc.ActiveDoc.Objects.AddPoint(rect0.ToPolyline()[2] ) - # Rhino.RhinoDoc.ActiveDoc.Objects.AddPoint(rect0.ToPolyline()[3] ) - # print(rect0.ToPolyline()[0] ) - # print(rect0.IsValid) - # print(rect0.Width) - # print(rect0.Height) - # print(self.move_plane_by_axis(self.e90_multiple_planes[i][j],self.rect_thickness * -0.5)) - # print(self.move_plane_by_axis(self.e90_multiple_planes[i][j],self.rect_thickness * 0.5)) - # print(Interval(-self.rect_width * 0.5, self.rect_width * 0.5)) - # print(Interval(-self.rect_height * 0.5, self.rect_height * 0.5)) - elif self.rect_height <= 0 and self.rect_width <= 0: - w = abs(self.rect_height) - h = abs(self.rect_width) - - # type1 - e_plane = Plane(self.e90_multiple_planes[i][j]) - e_plane.Rotate(math.pi * 0.5, e_plane.YAxis) - top_plane_0 = self.move_plane_by_axis( - self.move_plane_by_axis( - self.f_planes[self.e_f[i][0]], - self.face_positions[-1], - ), - self.face_thickness * 0.5 + h, - ) - top_plane_1 = self.move_plane_by_axis( - self.move_plane_by_axis( - self.f_planes[self.e_f[i][1]], - self.face_positions[-1], - ), - self.face_thickness * 0.5 + h, - ) - bot_plane_0 = self.move_plane_by_axis( - self.move_plane_by_axis( - self.f_planes[self.e_f[i][0]], - self.face_positions[0], - ), - self.face_thickness * -0.5 - h, - ) - bot_plane_1 = self.move_plane_by_axis( - self.move_plane_by_axis( - self.f_planes[self.e_f[i][1]], - self.face_positions[0], - ), - self.face_thickness * -0.5 - h, - ) - - e_plane_ = Plane(self.e90_planes[i]) - e_plane_.Rotate(math.pi * 0.5, e_plane_.YAxis) - - side_planes = [ - top_plane_0, - e_plane, - top_plane_1, - self.move_plane_by_axis(e_plane, w * 0.5), - bot_plane_1, - e_plane, - bot_plane_0, - self.move_plane_by_axis(e_plane, w * -0.5), - ] - # Step 1: Create polyline type1_0 - type1_0 = self.polyline_from_planes( - self.move_plane_by_axis( - self.e90_multiple_planes[i][j], - -self.rect_thickness * 0.5, - ), - side_planes, - ) - - # Step 2: Translate polyline type1_0 by ZAxis * rect_thickness to create type1_1 - type1_1 = Polyline(type1_0) - type1_1.Transform( - Transform.Translation(self.e90_multiple_planes[i][j].ZAxis * self.rect_thickness) - ) - - # Step 3: Assign type1_0 and type1_1 to corresponding variables in the e_polylines array - self.e_polylines[i][j * 2 + 0] = type1_0 - self.e_polylines[i][j * 2 + 1] = type1_1 - # Assigning values to e_polylines_planes and e_polylines_index - self.e_polylines_planes[i][j] = self.move_plane_by_axis( + e_plane_ = Plane(self.e90_planes[i]) + e_plane_.Rotate(math.pi * 0.5, e_plane_.YAxis) + + side_planes = [ + top_plane_0, + e_plane, + top_plane_1, + self.move_plane_by_axis(e_plane, w * 0.5), + bot_plane_1, + e_plane, + bot_plane_0, + self.move_plane_by_axis(e_plane, w * -0.5), + ] + # Step 1: Create polyline type1_0 + type1_0 = self.polyline_from_planes( + self.move_plane_by_axis( self.e90_multiple_planes[i][j], - self.rect_thickness * 0.5, - ) - self.e_polylines_index[i][j] = "{}-{}_{}".format(self.e_f[i][0], self.e_f[i][1], j) - - def outline_from_face_edge_corner(self, face_plane, edge_planes, bise_planes, T=1, tolerance=0.1): - polyline = Rhino.Geometry.Polyline() - - if T == 2: - for i in range(len(edge_planes)): - plane = edge_planes[i] - plane1 = edge_planes[(i + 1) % len(edge_planes)] - if ( - Rhino.Geometry.Vector3d.VectorAngle(plane.ZAxis, plane1.ZAxis) > -0.01 - and Rhino.Geometry.Vector3d.VectorAngle(plane.ZAxis, plane1.ZAxis) < 0.01 - ): - edge_planes[(i + 1) % len(edge_planes)] = plane - continue - - if Rhino.Geometry.Vector3d.VectorAngle(plane.XAxis, plane1.XAxis) < tolerance: - vector3d = Rhino.Geometry.Vector3d(plane.XAxis) - vector3d.Rotate(math.pi / 2, plane.YAxis) - plane1 = Rhino.Geometry.Plane(bise_planes[i].Origin, vector3d, plane.YAxis) - - # edge_planes[(i + 1) % len(edge_planes)] = plane - - result, line = Rhino.Geometry.Intersect.Intersection.PlanePlane(plane, plane1) - result, t = Rhino.Geometry.Intersect.Intersection.LinePlane(line, face_plane) - polyline.Add(line.PointAt(t)) - - polyline.Add(polyline[0]) - # Rhino.RhinoDoc.ActiveDoc.Objects.AddPolyline(polyline) - else: - for j in range(len(bise_planes)): - (result, p,) = Rhino.Geometry.Intersect.Intersection.PlanePlanePlane( - face_plane, bise_planes[j], edge_planes[j] + -self.rect_thickness * 0.5, + ), + side_planes, ) - polyline.Add(p) - polyline.Add(polyline[0]) + # Step 2: Translate polyline type1_0 by ZAxis * rect_thickness to create type1_1 + type1_1 = Polyline(type1_0) + type1_1.Transform( + Transform.Translation(self.e90_multiple_planes[i][j].ZAxis * self.rect_thickness) + ) - return polyline + # Step 3: Assign type1_0 and type1_1 to corresponding variables in the e_polylines array + self.e_polylines[i][j * 2 + 0] = type1_0 + self.e_polylines[i][j * 2 + 1] = type1_1 + # Assigning values to e_polylines_planes and e_polylines_index + self.e_polylines_planes[i][j] = self.move_plane_by_axis( + self.e90_multiple_planes[i][j], + self.rect_thickness * 0.5, + ) + self.e_polylines_index[i][j] = "{}-{}_{}".format(self.e_f[i][0], self.e_f[i][1], j) - def move_plane_by_axis(self, plane, dist, axis=2): - plane1 = Rhino.Geometry.Plane(plane) - if axis == 0: - plane1.Translate(plane1.XAxis * dist) - elif axis == 1: - plane1.Translate(plane1.YAxis * dist) - else: - plane1.Translate(plane1.Normal * dist) - return plane1 - - def chamfer(self, polyline, flags, value=0.001): - lines = polyline.GetSegments() - - if value <= 0: - return polyline - - p = Rhino.Geometry.Polyline() - points = Rhino.Geometry.Polyline(polyline.GetRange(0, polyline.Count - 1)) - - for i in range(points.Count): - curr = i - next = rhino_util.MathUtil.Wrap((i + 1), points.Count) - prev = rhino_util.MathUtil.Wrap((i - 1), points.Count) - - v0 = points[prev] - points[curr] - v1 = points[next] - points[curr] - angle = Rhino.Geometry.Vector3d.VectorAngle(v0, v1, Rhino.Geometry.Vector3d.CrossProduct(v0, v1)) - - if flags[i] and angle < math.pi * 0.5: - value_ = rhino_util.MathUtil.RemapNumbers(angle, 0, math.pi * 0.5, value, value * 0.1) - v0.Unitize() - v1.Unitize() - v0 *= value_ - v1 *= value_ - p.Add(points[curr] + v0) - p.Add(points[curr] + v1) - else: - p.Add(points[curr]) - p.Add(points[curr]) - - p.Add(p[0]) - - return p - - def get_face_polylines(self, chamfer_dist=0.0): - zero_layer = len(face_positions) == 0 - - self.f_polylines_index = [] - self.f_polylines_planes = [] - self.f_polylines = [] - - for i in range(self.f): - if len(self.face_positions) == 0: - self.f_polylines.append([None, None]) - - self.f_polylines[i][0] = self.outline_from_face_edge_corner( - self.move_plane_by_axis(self.f_planes[i], face_thickness * -0.5), - self.fe_planes[i], - self.bi_planes[i], - 2, - ) - self.f_polylines[i][1] = self.outline_from_face_edge_corner( - self.move_plane_by_axis(self.f_planes[i], face_thickness * 0.5), - self.fe_planes[i], - self.bi_planes[i], - 2, - ) + def outline_from_face_edge_corner(self, face_plane, edge_planes, bise_planes, T=1, tolerance=0.1): + polyline = Rhino.Geometry.Polyline() - self.f_polylines_planes.append( - [self.move_plane_by_axis(self.f_planes[i], self.face_thickness * 0.5)] - ) + if T == 2: + for i in range(len(edge_planes)): + plane = edge_planes[i] + plane1 = edge_planes[(i + 1) % len(edge_planes)] + if ( + Rhino.Geometry.Vector3d.VectorAngle(plane.ZAxis, plane1.ZAxis) > -0.01 + and Rhino.Geometry.Vector3d.VectorAngle(plane.ZAxis, plane1.ZAxis) < 0.01 + ): + edge_planes[(i + 1) % len(edge_planes)] = plane + continue + + if Rhino.Geometry.Vector3d.VectorAngle(plane.XAxis, plane1.XAxis) < tolerance: + vector3d = Rhino.Geometry.Vector3d(plane.XAxis) + vector3d.Rotate(math.pi / 2, plane.YAxis) + plane1 = Rhino.Geometry.Plane(bise_planes[i].Origin, vector3d, plane.YAxis) + + # edge_planes[(i + 1) % len(edge_planes)] = plane + + result, line = Rhino.Geometry.Intersect.Intersection.PlanePlane(plane, plane1) + result, t = Rhino.Geometry.Intersect.Intersection.LinePlane(line, face_plane) + polyline.Add(line.PointAt(t)) + + polyline.Add(polyline[0]) + # Rhino.RhinoDoc.ActiveDoc.Objects.AddPolyline(polyline) + else: + for j in range(len(bise_planes)): + ( + result, + p, + ) = Rhino.Geometry.Intersect.Intersection.PlanePlanePlane(face_plane, bise_planes[j], edge_planes[j]) + polyline.Add(p) + + polyline.Add(polyline[0]) + + return polyline + + def move_plane_by_axis(self, plane, dist, axis=2): + plane1 = Rhino.Geometry.Plane(plane) + if axis == 0: + plane1.Translate(plane1.XAxis * dist) + elif axis == 1: + plane1.Translate(plane1.YAxis * dist) + else: + plane1.Translate(plane1.Normal * dist) + return plane1 + + def remap_numbers(self, speed=50, low1=0, high1=2000, low2=0, high2=1): + return low2 + (speed - low1) * (high2 - low2) / (high1 - low1) + + def chamfer(self, polyline, flags, value=0.001): + + if value <= 0: + return polyline + + p = Rhino.Geometry.Polyline() + points = Rhino.Geometry.Polyline(polyline.GetRange(0, polyline.Count - 1)) + n = len(p) + + for i in range(n): + curr = i + next = (((i + 1) % n) + n) % n + prev = (((i - 1) % n) + n) % n + + v0 = points[prev] - points[curr] + v1 = points[next] - points[curr] + angle = Rhino.Geometry.Vector3d.VectorAngle(v0, v1, Rhino.Geometry.Vector3d.CrossProduct(v0, v1)) + + if flags[i] and angle < math.pi * 0.5: + value_ = self.remap_numbers(angle, 0, math.pi * 0.5, value, value * 0.1) + v0.Unitize() + v1.Unitize() + v0 *= value_ + v1 *= value_ + p.Add(points[curr] + v0) + p.Add(points[curr] + v1) + else: + p.Add(points[curr]) + p.Add(points[curr]) + + p.Add(p[0]) + + return p + + def get_face_polylines(self, chamfer_dist=0.0): + + self.f_polylines_index = [] + self.f_polylines_planes = [] + self.f_polylines = [] + + for i in range(self.f): + if len(self.face_positions) == 0: + self.f_polylines.append([None, None]) + + self.f_polylines[i][0] = self.outline_from_face_edge_corner( + self.move_plane_by_axis(self.f_planes[i], self.face_thickness * -0.5), + self.fe_planes[i], + self.bi_planes[i], + 2, + ) + self.f_polylines[i][1] = self.outline_from_face_edge_corner( + self.move_plane_by_axis(self.f_planes[i], self.face_thickness * 0.5), + self.fe_planes[i], + self.bi_planes[i], + 2, + ) - self.f_polylines_index.append([str(i)]) - else: - self.f_polylines.append([None] * (len(face_positions) * 2)) - self.f_polylines_planes.append([None] * len(face_positions)) - self.f_polylines_index.append([None] * len(face_positions)) - - for j in range(len(face_positions)): - pline0 = self.outline_from_face_edge_corner( - self.move_plane_by_axis( - self.f_planes[i], - self.face_positions[j] + self.face_thickness * -0.5, - ), - self.fe_planes[i], - self.bi_planes[i], - 2, - ) - pline1 = self.outline_from_face_edge_corner( - self.move_plane_by_axis( - self.f_planes[i], - self.face_positions[j] + self.face_thickness * 0.5, - ), - self.fe_planes[i], - self.bi_planes[i], - 2, - ) + self.f_polylines_planes.append([self.move_plane_by_axis(self.f_planes[i], self.face_thickness * 0.5)]) + + self.f_polylines_index.append([str(i)]) + else: + self.f_polylines.append([None] * (len(self.face_positions) * 2)) + self.f_polylines_planes.append([None] * len(self.face_positions)) + self.f_polylines_index.append([None] * len(self.face_positions)) + + for j in range(len(self.face_positions)): + pline0 = self.outline_from_face_edge_corner( + self.move_plane_by_axis( + self.f_planes[i], + self.face_positions[j] + self.face_thickness * -0.5, + ), + self.fe_planes[i], + self.bi_planes[i], + 2, + ) + pline1 = self.outline_from_face_edge_corner( + self.move_plane_by_axis( + self.f_planes[i], + self.face_positions[j] + self.face_thickness * 0.5, + ), + self.fe_planes[i], + self.bi_planes[i], + 2, + ) + + self.f_polylines[i][j * 2 + 0] = pline0 + self.f_polylines[i][j * 2 + 1] = pline1 + + self.f_polylines_planes[i][j] = self.move_plane_by_axis( + self.f_planes[i], + self.face_positions[j] + self.face_thickness * 0.5, + ) + self.f_polylines_index[i][j] = str(i) if len(self.face_positions) == 1 else "{0}-{1}".format(i, j) + + return self.f_polylines_index, self.f_polylines_planes, self.f_polylines - self.f_polylines[i][j * 2 + 0] = pline0 - self.f_polylines[i][j * 2 + 1] = pline1 - # Rhino.RhinoDoc.ActiveDoc.Objects.AddPolyline(pline0) - self.f_polylines_planes[i][j] = self.move_plane_by_axis( - self.f_planes[i], - self.face_positions[j] + self.face_thickness * 0.5, - ) - self.f_polylines_index[i][j] = ( - str(i) if len(self.face_positions) == 1 else "{0}-{1}".format(i, j) - ) - # Chamfer - """ - for i in range(self.m.Faces.Count): - v = [self.m.Faces[i].A, self.m.Faces[i].B, self.m.Faces[i].C, self.m.Faces[i].D] if self.m.Faces[i].IsQuad else [self.m.Faces[i].A, self.m.Faces[i].B, self.m.Faces[i].C] - do_chamfer = [False] * len(v) - - for j in range(len(v)): - tv = self.m.TopologyVertices.TopologyVertexIndex(v[j]) - connected_faces = self.m.TopologyVertices.ConnectedFaces(tv) - if len(connected_faces) > 3: - do_chamfer[(j - 1) % len(v)] = True - print(self.m.Faces.Count) - for j in range(len(f_polylines[i])): - f_polylines[i][j] = self.chamfer(f_polylines[i][j], do_chamfer, chamfer_dist) - """ - return self.f_polylines_index, self.f_polylines_planes, self.f_polylines +class MyComponent(component): + def RunScript( + self, + _mesh: Rhino.Geometry.Mesh, + _face_positions: System.Collections.Generic.List[float], + _face_thickness: float, + _divisions: System.Collections.Generic.List[int], + _division_len: System.Collections.Generic.List[float], + _edge_vectors: System.Collections.Generic.List[Rhino.Geometry.Line], + _rect_width: float, + _rect_height: float, + _rect_thickness: float, + _projection: System.Collections.Generic.List[Rhino.Geometry.Brep], + ): ############################################################################### # user input ############################################################################### - m = _mesh face_positions = _face_positions if _face_positions else [0] face_thickness = _face_thickness if _face_thickness is not None else 1 diff --git a/src/rhino/gh/cpy/custom_joints/code.py b/src/rhino/gh/cpy/custom_joints/code.py index 59c9dfc3b..ee7b692ce 100644 --- a/src/rhino/gh/cpy/custom_joints/code.py +++ b/src/rhino/gh/cpy/custom_joints/code.py @@ -1,10 +1,6 @@ -"""generate joints between elements""" from ghpythonlib.componentbase import executingcomponent as component -import Grasshopper, GhPython import System import Rhino -import rhinoscriptsyntax as rs -from Rhino.Geometry import Polyline, Point3d class MyComponent(component): diff --git a/src/rhino/gh/cpy/cut_group/code.py b/src/rhino/gh/cpy/cut_group/code.py index 094b6f222..9cae4f52f 100644 --- a/src/rhino/gh/cpy/cut_group/code.py +++ b/src/rhino/gh/cpy/cut_group/code.py @@ -1,8 +1,6 @@ from ghpythonlib.componentbase import executingcomponent as component -import Grasshopper, GhPython -import System +import Grasshopper import Rhino -import rhinoscriptsyntax as rs class MyComponent(component): diff --git a/src/rhino/gh/cpy/ears/code.py b/src/rhino/gh/cpy/ears/code.py index 5dc2df6a6..8280e768a 100644 --- a/src/rhino/gh/cpy/ears/code.py +++ b/src/rhino/gh/cpy/ears/code.py @@ -1,25 +1,14 @@ -"""get joints ids and connections areas between elements""" - -__author__ = "petras vestartas" -__version__ = "2023.04.01" - - -from ghpythonlib.componentbase import executingcomponent as component - -import System +from ghpythonlib.componentbase import executingcomponent as component # noqa: E402 import Rhino from Rhino.Geometry import Polyline from Rhino.Geometry import Plane -from Rhino.Geometry import Point3d from Rhino.Geometry import Vector3d from Rhino.Geometry import Line from Rhino.Geometry import Transform from Rhino.Geometry import Arc from Rhino.Geometry import Brep -from Rhino.Geometry import Curve import math import Grasshopper -from ghpythonlib import treehelpers class Ears(component): @@ -106,30 +95,30 @@ def offset_parallelograms(self, x, y, radius): closed = x[0].DistanceToSquared(x[len(x) - 1]) < 0.0001 for i in range(len(offset_planes)): - result, l = Rhino.Geometry.Intersect.Intersection.PlanePlane( + result, line = Rhino.Geometry.Intersect.Intersection.PlanePlane( offset_planes[(len(offset_planes) + (i - 1)) % len(offset_planes)], offset_planes[i] ) - result, types_of_notches_per_point = Rhino.Geometry.Intersect.Intersection.LinePlane(l, fit_plane0) - offset_polyline0.Add(l.PointAt(types_of_notches_per_point)) - result, types_of_notches_per_point = Rhino.Geometry.Intersect.Intersection.LinePlane(l, fit_plane1) - offset_polyline1.Add(l.PointAt(types_of_notches_per_point)) + result, types_of_notches_per_point = Rhino.Geometry.Intersect.Intersection.LinePlane(line, fit_plane0) + offset_polyline0.Add(line.PointAt(types_of_notches_per_point)) + result, types_of_notches_per_point = Rhino.Geometry.Intersect.Intersection.LinePlane(line, fit_plane1) + offset_polyline1.Add(line.PointAt(types_of_notches_per_point)) - if closed == False: + if closed is False: - l = Line.Unset - result, l = Rhino.Geometry.Intersect.Intersection.PlanePlane(fit_plane0, offset_planes[0]) - offset_polyline0.Insert(0, l.ClosestPoint(x[0], False)) - result, l = Rhino.Geometry.Intersect.Intersection.PlanePlane( + line = Line.Unset + result, line = Rhino.Geometry.Intersect.Intersection.PlanePlane(fit_plane0, offset_planes[0]) + offset_polyline0.Insert(0, line.ClosestPoint(x[0], False)) + result, line = Rhino.Geometry.Intersect.Intersection.PlanePlane( fit_plane0, offset_planes[len(offset_planes) - 1] ) - offset_polyline0.Add(l.ClosestPoint(x[len(x) - 1], False)) + offset_polyline0.Add(line.ClosestPoint(x[len(x) - 1], False)) - result, l = Rhino.Geometry.Intersect.Intersection.PlanePlane(fit_plane1, offset_planes[0]) - offset_polyline1.Insert(0, l.ClosestPoint(y[0], False)) - result, l = Rhino.Geometry.Intersect.Intersection.PlanePlane( + result, line = Rhino.Geometry.Intersect.Intersection.PlanePlane(fit_plane1, offset_planes[0]) + offset_polyline1.Insert(0, line.ClosestPoint(y[0], False)) + result, line = Rhino.Geometry.Intersect.Intersection.PlanePlane( fit_plane1, offset_planes[len(offset_planes) - 1] ) - offset_polyline1.Add(l.ClosestPoint(y[len(y) - 1], False)) + offset_polyline1.Add(line.ClosestPoint(y[len(y) - 1], False)) else: offset_polyline0.Add(offset_polyline0[0]) offset_polyline1.Add(offset_polyline1[0]) @@ -225,7 +214,6 @@ def notches_lines( l0 = [] l1 = [] # fillet l2 = [] # fillet - plines = [] planes = [] ############################################################################### @@ -242,7 +230,6 @@ def notches_lines( ############################################################################### fillet = False R_ = _radius * 2 if types_of_notches_per_point[0] == 4 else _radius - notchStart = True for i in range(0, len(xA)): @@ -252,19 +239,11 @@ def notches_lines( normal = Line(xA[i], xB[i]) n = len(xA) next = (i + 1) % n - nextNext = (i + 2) % n prev = (((i - 1) % n) + n) % n p0a = xA[i] p1a = xA[next] p2a = xA[prev] - p3a = xA[nextNext] - - p0b = xB[i] - p1b = xB[next] - p2b = xB[prev] - p3b = xB[nextNext] - normal1 = Line(xA[next], xB[next]) normal2 = Line(xA[prev], xB[prev]) @@ -272,7 +251,6 @@ def notches_lines( # Measure Concavity ############################################################################### cornera = Polyline([p2a, p0a, p1a]) - cornerb = Polyline([p2b, p0b, p1b]) cornera.Transform(Transform.PlaneToPlane(Plane(p0a, normal.Direction), Plane.WorldXY)) nextEdge = cornera.SegmentAt(0).Direction @@ -340,7 +318,6 @@ def notches_lines( pl0 = self.align_plane(normalPl, v0) pl1 = self.align_plane(normalPl, v1) extension0 = 0 - extension1 = 0 normalXAxis0 = Line( local_cornera.SegmentAt(0).ClosestPoint(local_cornera_[1], False), local_cornerb.SegmentAt(0).ClosestPoint(local_cornerb_[1], False), @@ -361,8 +338,6 @@ def notches_lines( # TYPE B Notch - Diaognal ############################################################################### bisectorDir = offset_distances[i] - - pl2normalXAxis2Fillet = self.align_plane(normalPl, bisectorDir) length = bisectorDir.Length normalXAxis2 = Line(xA[i] + bisectorDir, xB[i] + bisectorDir) @@ -371,7 +346,6 @@ def notches_lines( ############################################################################### bisectorDirFillet = pl0.XAxis * radius + pl1.XAxis * radius pl2 = self.align_plane(normalPl, bisectorDirFillet) - lengthFillet = bisectorDir.Length bisectorDirFillet *= -(length) / length normalXAxis2Fillet = Line( @@ -484,12 +458,6 @@ def notches_lines( # Check direction of inclined cut, the check is made according to XY plane side_plane = Plane(xA[i], xB[i], xA[next]) - - mid_0 = 0.5 * (xA[i] + xA[next]) - mid_1 = 0.5 * (xB[i] + xB[next]) - segment = Line(xB[i], xB[next]) - - tool_direction = Line(mid_0, segment.ClosestPoint(mid_0, False)) side_plane.Transform(to_xy) is_below.append(0) @@ -589,7 +557,7 @@ def sort_by_size(self, _p0, _p1): # It sorts these objects by the diagonal length of their bounding boxes in descending order. try: - # Creating a list of tuples, each containing the diagonal length and the corresponding objects from _p0 and _p1 + # List of tuples, each containing the diagonal length and the corresponding objects from _p0 and _p1 items_with_sizes = [(obj.GetBoundingBox(True).Diagonal.Length, obj, _p1[i]) for i, obj in enumerate(_p0)] except Exception as e: print(f"Error retrieving bounding box sizes: {str(e)}") @@ -643,7 +611,6 @@ def get_ears(self, _c0, _c1, _radius, _notch_type, _union): notch_types = [0] * (len(plines0[i]) - 1) offset_distances = [Vector3d(0, 0, 0)] * (len(plines0[i]) - 1) - n = len(plines0[i]) - 1 for j in range(len(plines0[i]) - 1): l1 = Line(plines0_offset[i][j], plines1_offset[i][j]) @@ -768,13 +735,13 @@ def RunScript( if _p0 and _p1: - if _p0 == None: + if _p0 is None: return - if _p1 == None: + if _p1 is None: return - if _notch_type == None: + if _notch_type is None: return if _p0.DataCount is not _p1.DataCount: @@ -818,7 +785,7 @@ def RunScript( offset0.AddRange(plines0, Grasshopper.Kernel.Data.GH_Path(i)) offset1.AddRange(plines1, Grasshopper.Kernel.Data.GH_Path(i)) planes.Add(Plane(plines0[0][0], planes0[0].ZAxis), Grasshopper.Kernel.Data.GH_Path(i)) - notch_geo = [] + if _union: cut_curves0_temp, cut_curves1_temp, cut_extrusions_temp = self.get_notch_geometry( _c0, _c1, notch_lines_nested, notch_lines_nested_corners, planes0, planes1, radius + 0.0000 diff --git a/src/rhino/gh/cpy/folding_diamonds/code.py b/src/rhino/gh/cpy/folding_diamonds/code.py index e38bd4aed..446fab0c4 100644 --- a/src/rhino/gh/cpy/folding_diamonds/code.py +++ b/src/rhino/gh/cpy/folding_diamonds/code.py @@ -1,11 +1,9 @@ -from ghpythonlib.componentbase import executingcomponent as component +from ghpythonlib.componentbase import executingcomponent as component # noqa: E402 import Rhino.Geometry as RhinoGeometry -import math from ghpythonlib import treehelpers import Grasshopper import Rhino import System -import math class case_3_folded_plates: @@ -61,7 +59,7 @@ def __init__( self._surface = surface - if self._surface == None: + if self._surface is None: crv = RhinoGeometry.Arc( RhinoGeometry.Point3d(-100, 0, 0), RhinoGeometry.Point3d(0, 0, 100), @@ -70,15 +68,15 @@ def __init__( self._surface = RhinoGeometry.Extrusion.Create(crv, 300, False).ToNurbsSurface() self._surface = self._surface.Transpose() - self._u_divisions = u_divisions if u_divisions != None else 5 - self._v_divisions = v_divisions if v_divisions != None else 2 + self._u_divisions = u_divisions if u_divisions is not None else 5 + self._v_divisions = v_divisions if v_divisions is not None else 2 self._base_planes = list(base_planes) if base_planes else [] # Run self.diamond_subdivision() self._has_ngons = self._mesh.Ngons.Count > 0 - self._face_thickness = thickness if thickness != None else 1.4 + self._face_thickness = thickness if thickness is not None else 1.4 self._chamfer = chamfer if chamfer else 0 self._face_positions = [0] if not face_positions else face_positions @@ -97,7 +95,6 @@ def diamond_subdivision(self): # Main Parameters ##################################################################################### self._mesh = RhinoGeometry.Mesh() - flags = [] if self._u_divisions < 1: self._u_divisions = 1 @@ -137,12 +134,10 @@ def diamond_subdivision(self): p4 = self._surface.PointAt(sum_step_u + step_u * 0.5, sum_step_v + step_v * 1.5) p5 = self._surface.PointAt(sum_step_u + step_u * 0.5, sum_step_v + step_v * 0.5) p6 = self._surface.PointAt(sum_step_u + step_u * 0.5, sum_step_v - step_v * 0.5) - p7 = (p5 + p6) / 2 - p8 = (p4 + p5) / 2 if j == 0: ##################################################################################### - ## start triangles + # start triangles ##################################################################################### p9 = self._surface.PointAt(sum_step_u + step_u * 0.5, interval1.T0) line = RhinoGeometry.Line(p5, p6) @@ -288,7 +283,6 @@ def get_face_vertices(self): else: self._f = self._mesh.Faces.Count - empty_list = [] self._f_v = [] for i in range(self._mesh.Faces.Count): self._f_v.append([]) @@ -347,9 +341,9 @@ def dihedral_plane(self, plane0, plane1): #################################################################################################### # Plane between two Planes #################################################################################################### - result, l = RhinoGeometry.Intersect.Intersection.PlanePlane(plane0, plane1) - result, t = RhinoGeometry.Intersect.Intersection.LinePlane(l, plane0) - centerDihedral = l.PointAt(t) + result, line = RhinoGeometry.Intersect.Intersection.PlanePlane(plane0, plane1) + result, t = RhinoGeometry.Intersect.Intersection.LinePlane(line, plane0) + centerDihedral = line.PointAt(t) #################################################################################################### # Convert ZAxis to lines, cant it be done on origin @@ -364,7 +358,7 @@ def dihedral_plane(self, plane0, plane1): plane0.ZAxis.IsParallelTo(plane1.ZAxis, 0.01) == 0 and plane0.Origin.DistanceToSquared(plane1.Origin) > 0.001 ): - ##########################################################################################3########## + #################################################################################################### # Intersect two lines to get center #################################################################################################### result, t0, t1 = RhinoGeometry.Intersect.Intersection.LineLine(angleLine0, angleLine1) @@ -381,7 +375,7 @@ def dihedral_plane(self, plane0, plane1): #################################################################################################### # Compute Plane #################################################################################################### - dihedralPlane = RhinoGeometry.Plane(centerDihedral, l.Direction, v0 + v1) + dihedralPlane = RhinoGeometry.Plane(centerDihedral, line.Direction, v0 + v1) return dihedralPlane else: @@ -486,7 +480,6 @@ def move_plane_by_axis(self, plane, distance): return RhinoGeometry.Plane(plane.Origin + plane.ZAxis * distance, plane.XAxis, plane.YAxis) def get_face_polylines(self): - zero_layer = len(self._face_positions) == 0 self._f_polylines_index = [] # new string[f][] self._f_polylines_planes = [] # new Plane[f][] @@ -552,17 +545,17 @@ def chamfer_polyline(self, polyline, value=0.001): p = RhinoGeometry.Polyline() if value < 0: - for l in lines: - l_ = RhinoGeometry.Line(l.From, l.To) + for line in lines: + l_ = RhinoGeometry.Line(line.From, line.To) l_.Extend(-abs(value), -abs(value)) lShorter = l_ p.Add(lShorter.From) p.Add(lShorter.To) else: - for l in lines: - p.Add(l.PointAt(value)) - p.Add(l.PointAt(1 - value)) + for line in lines: + p.Add(line.PointAt(value)) + p.Add(line.PointAt(1 - value)) p.Add(p[0]) @@ -570,15 +563,14 @@ def chamfer_polyline(self, polyline, value=0.001): def get_insertion_vectors(self): for i in range(self._f): - if self._flags[i] == False: + if self._flags[i] is False: vec = self._f_polylines[i][0][2] - self._f_polylines[i][0][0] vec.Unitize() vec *= 10 for j in range(3): mid = (self._f_polylines[i][0][j] + self._f_polylines[i][0][(j + 1) % 3]) * 0.5 - l = RhinoGeometry.Line(mid, vec) - self._insertion_lines.append(l) + self._insertion_lines.append(RhinoGeometry.Line(mid, vec)) # chamfer if self._chamfer > 0.000001: @@ -599,29 +591,22 @@ def RunScript( face_positions: System.Collections.Generic.List[float], ): - try: - - mtsj = case_3_folded_plates( - surface, - u_divisions, - v_divisions, - base_planes, - thickness, - chamfer, - face_positions, - ) - self.mesh = mtsj._mesh - polylines_tree = Grasshopper.DataTree[RhinoGeometry.Polyline]() - for i in range(0, len(mtsj._f_polylines)): - for j in range(0, len(mtsj._f_polylines[i])): - polylines_tree.Add(mtsj._f_polylines[i][j], Grasshopper.Kernel.Data.GH_Path(i)) - self.plates = polylines_tree - self.insertion = mtsj._insertion_lines - self.adjacency = treehelpers.list_to_tree(mtsj._adjacency) - self.flags = mtsj._flags - return self.mesh, self.plates, self.insertion, self.adjacency, self.flags - except Exception as e: - import traceback - - # Catch any exception and print the traceback - traceback.print_exc() + mtsj = case_3_folded_plates( + surface, + u_divisions, + v_divisions, + base_planes, + thickness, + chamfer, + face_positions, + ) + self.mesh = mtsj._mesh + polylines_tree = Grasshopper.DataTree[RhinoGeometry.Polyline]() + for i in range(0, len(mtsj._f_polylines)): + for j in range(0, len(mtsj._f_polylines[i])): + polylines_tree.Add(mtsj._f_polylines[i][j], Grasshopper.Kernel.Data.GH_Path(i)) + self.plates = polylines_tree + self.insertion = mtsj._insertion_lines + self.adjacency = treehelpers.list_to_tree(mtsj._adjacency) + self.flags = mtsj._flags + return self.mesh, self.plates, self.insertion, self.adjacency, self.flags diff --git a/src/rhino/gh/cpy/input_get/code.py b/src/rhino/gh/cpy/input_get/code.py index 782ae4504..068ded73b 100644 --- a/src/rhino/gh/cpy/input_get/code.py +++ b/src/rhino/gh/cpy/input_get/code.py @@ -1,15 +1,7 @@ -"""unwrap element data to polylines, insertion vectors, joint types and etc""" from ghpythonlib.componentbase import executingcomponent as component -import Grasshopper, GhPython -import System - -__author__ = "petras" -__version__ = "2023.04.02" - +import Grasshopper import ghpythonlib.treehelpers as th -from Rhino.Geometry import Polyline import Rhino -import rhinoscriptsyntax as rs class MyComponent(component): @@ -23,7 +15,7 @@ def RunScript(self, _data, _split: bool): _plines_0 = Grasshopper.DataTree[Rhino.Geometry.Curve]() _plines_1 = Grasshopper.DataTree[Rhino.Geometry.Curve]() _lines = Grasshopper.DataTree[Rhino.Geometry.Curve]() - if split == False: + if split is False: for i in range(len(_data.plines_with_joints)): for j in range(len(_data.plines_with_joints[i])): _plines_0.Add(_data.plines_with_joints[i][j].ToNurbsCurve(), Grasshopper.Kernel.Data.GH_Path(i)) diff --git a/src/rhino/gh/cpy/input_set/code.py b/src/rhino/gh/cpy/input_set/code.py index 16e6e16e5..21bed2ff8 100644 --- a/src/rhino/gh/cpy/input_set/code.py +++ b/src/rhino/gh/cpy/input_set/code.py @@ -1,24 +1,11 @@ -"""combine different data sets into one list for a faster data transder between grasshopper wires""" from ghpythonlib.componentbase import executingcomponent as component -import Grasshopper, GhPython - -__author__ = "petras" -__version__ = "2023.04.02" - - -import System +import Grasshopper import Rhino -import rhinoscriptsyntax as rs import ghpythonlib.treehelpers as th -from Rhino.Geometry import Polyline from Rhino.Geometry import Vector3d from Rhino.Geometry import Plane -import compas_wood -from compas_wood.binding import test from compas_wood.datastructures import WoodData -# r: compas - class MyComponent(component): def get_plane(self, _polyline, _orientation_point): diff --git a/src/rhino/gh/cpy/joint_parameters/code.py b/src/rhino/gh/cpy/joint_parameters/code.py index d8cf19990..e674f9364 100644 --- a/src/rhino/gh/cpy/joint_parameters/code.py +++ b/src/rhino/gh/cpy/joint_parameters/code.py @@ -1,20 +1,5 @@ -""" -Do something silly in python3. - -This component does nothing useful, it's only a kitchen sink (but in python3) example showing most available options. - - Args: - x: X value - y: Y value - z: Z value - Returns: - result: The sum of all three values. -""" from ghpythonlib.componentbase import executingcomponent as component -import System -import math - class joint_parameters_component(component): def RunScript(self, _ss_e_ip, _ss_e_op, _ts_e_p, _cr_c_ip, _tt_e_p, _ss_e_r, _b): diff --git a/src/rhino/gh/cpy/joints/code.py b/src/rhino/gh/cpy/joints/code.py index 0735e3540..13f83a579 100644 --- a/src/rhino/gh/cpy/joints/code.py +++ b/src/rhino/gh/cpy/joints/code.py @@ -1,4 +1,5 @@ """get connection zones from polylines and indices of neighboring elements""" + from ghpythonlib.componentbase import executingcomponent as component import System from ghpythonlib import treehelpers diff --git a/src/rhino/gh/cpy/line_volume/code.py b/src/rhino/gh/cpy/line_volume/code.py index 612a34ed0..750c31b21 100644 --- a/src/rhino/gh/cpy/line_volume/code.py +++ b/src/rhino/gh/cpy/line_volume/code.py @@ -1,13 +1,9 @@ -from ghpythonlib.componentbase import executingcomponent as component -import Grasshopper, GhPython -import System +from ghpythonlib.componentbase import executingcomponent as component # noqa: E402 import Rhino from Rhino.Geometry import ( Brep, - Curve, Polyline, Plane, - Vector3d, Point3d, Rectangle3d, Interval, @@ -123,8 +119,4 @@ def create_rect_pipe_from_curve(rail_curve, radius, vector, divisions=10): _brep = brep _plines = rects - # _brep = Rhino.Geometry.Brep.CreatePipe(_crv, [_radius], False, Rhino.Geometry.PipeCapMode.Flat, False, 0, 0.01) - # print(_brep) - - # return outputs if you have them; here I try it for you: return (_brep, _plines) diff --git a/src/rhino/gh/cpy/loft_brep/code.py b/src/rhino/gh/cpy/loft_brep/code.py index c8718a7c0..ebe4938c4 100644 --- a/src/rhino/gh/cpy/loft_brep/code.py +++ b/src/rhino/gh/cpy/loft_brep/code.py @@ -49,7 +49,7 @@ def loft_polylines_with_holes(self, curves0, curves1, color): if len(curves1) == 0: return - flag = len(curves0) is not 0 if True else len(curves1) != 0 + flag = len(curves0) != 0 if True else len(curves1) != 0 if flag: curves = [] curves2 = [] diff --git a/src/rhino/gh/cpy/loft_mesh/code.py b/src/rhino/gh/cpy/loft_mesh/code.py index c0a6be196..daa2bd5c7 100644 --- a/src/rhino/gh/cpy/loft_mesh/code.py +++ b/src/rhino/gh/cpy/loft_mesh/code.py @@ -16,7 +16,7 @@ def to_polyline_from_cp(self, curve): polyline = Rhino.Geometry.Polyline() result, polyline1 = curve.TryGetPolyline() - if result == False: + if result is False: nurbsCurve = curve.ToNurbsCurve() point3dArray = [] @@ -58,7 +58,7 @@ def loft_polylines_with_holes(self, curves0, curves1): # user input ############################################################################### - flag = len(curves0) is not 0 if True else len(curves1) != 0 + flag = len(curves0) != 0 if True else len(curves1) != 0 if flag: curves = [] @@ -91,7 +91,7 @@ def loft_polylines_with_holes(self, curves0, curves1): length = -1.0 border_id = -1 count = 0 - numArray = [] + for curve in curves0: diagonal = curve.GetBoundingBox(True).Diagonal temp_length = diagonal.Length diff --git a/src/rhino/gh/cpy/recenter/code.py b/src/rhino/gh/cpy/recenter/code.py index b56f6a896..29abdc8ae 100644 --- a/src/rhino/gh/cpy/recenter/code.py +++ b/src/rhino/gh/cpy/recenter/code.py @@ -1,10 +1,3 @@ -__author__ = "petras vestartas" -__version__ = "2023.03.22" - -""" -Move curves to to the origin -""" - from ghpythonlib.componentbase import executingcomponent as component import Rhino import Grasshopper @@ -13,7 +6,7 @@ class xml_recenter_component(component): def RunScript(self, _geo, _scale): - scale = _scale if _scale != None else 1 + scale = _scale if _scale is not None else 1 if _geo.AllData().Count == 0: return diff --git a/src/rhino/gh/cpy/solver/code.py b/src/rhino/gh/cpy/solver/code.py index 46cd61189..bf87fe8e5 100644 --- a/src/rhino/gh/cpy/solver/code.py +++ b/src/rhino/gh/cpy/solver/code.py @@ -81,7 +81,7 @@ def RunScript( for i in range(0, len(_scale)): input_scale[i] = _scale[i] - input_output_type = _get if _get != None else 4 + input_output_type = _get if _get is not None else 4 input_joint_volume_parameters = [0, 0, 0] @@ -119,7 +119,7 @@ def RunScript( w_output_types, to_double1(input_joint_volume_parameters), [], - [] + [], # to_point2(input_custom_joints), # to_int1(input_custom_joints_types), ) diff --git a/src/rhino/gh/cpy/solver_custom/code.py b/src/rhino/gh/cpy/solver_custom/code.py index 39ef55bab..7d0668f44 100644 --- a/src/rhino/gh/cpy/solver_custom/code.py +++ b/src/rhino/gh/cpy/solver_custom/code.py @@ -1,190 +1,52 @@ - from ghpythonlib.componentbase import executingcomponent as component -import Grasshopper, GhPython import Rhino -from Rhino.Geometry import Polyline, Point3d -#from compas_rhino import conversions import System - -import time -from ctypes import * -#from compas_wood.ctypes_conversion import * - -import os - -app_data = os.getenv('APPDATA') -vers = Rhino.RhinoApp.Version.Major -plugin_name = 'compas_wood' -plugin_path = "{0}\McNeel\Rhinoceros\packages\{1}.0\{2}".format(app_data, vers, plugin_name) - -for _path in os.walk(plugin_path): - if os.path.isdir(_path[0]): - plugin_path = _path[0] - -def list_polylines_coord(polylines, scale = 10): - f = [] - v = [] - for polyline in polylines: - f.append(len(polyline)) - for point in polyline: - v.append(point[0]*scale) - v.append(point[1]*scale) - v.append(point[2]*scale) - #v.extend(point) - _f = (c_size_t * len(f))(*f) - _v = (c_float * len(v))(*v) - return _f, c_size_t(len(f)), _v, c_size_t(len(v)) - - -def lists_vectors_coord(vectors): - faces = [len(v) for v in vectors] - f = (c_size_t * len(vectors))(*faces) - v = [coord for vec in vectors for point in vec for coord in point] - - v_s = c_size_t(len(v)) # * sizeof(c_float) - v = (c_float * len(v))(*v) - return f, c_size_t(len(vectors)), v, v_s - - -def lists_numbers_coord(numbers): - v_s = 0 - f_s = len(numbers) - f = (c_size_t * len(numbers))() - - for i in range(len(numbers)): - f[i] = len(numbers[i]) - v_s += len(numbers[i]) * 1 - - v = (c_int * v_s)() - - count = 0 - for i in range(len(numbers)): - for j in range(len(numbers[i])): - v[count] = numbers[i][j] - count += 1 - - return f, c_size_t(f_s), v, c_size_t(v_s) - - -def list_ints_coord(numbers): - f_s = len(numbers) - f = [0.0] * f_s - for i in range(f_s): - f[i] = numbers[i] - return (c_int * len(f))(*f), c_size_t(f_s) - - -def list_numbers_coord(numbers): - f_s = len(numbers) - f = [0.0] * f_s - for i in range(f_s): - f[i] = numbers[i] - return (c_float * len(f))(*f), c_size_t(f_s) - - - -def coord_polylines_lists(groups_f, groups_f_s, out_f, out_f_s, out_v, out_v_s): - polylines = [ - [Polyline([]) for j in range(groups_f[i])] for i in range(groups_f_s.value) - ] - - a = 0 - b = 0 - pline_count = 0 - num_points = 3 - num_groups = groups_f_s.value - - points = [] - for i in range(0, out_v_s.value, num_points): - #points.append([out_v[i]*0.1, out_v[i + 1]*0.1, out_v[i + 2]*0.1]) - points.append(Point3d(out_v[i]*0.1, out_v[i + 1]*0.1, out_v[i + 2]*0.1)) - num_points_per_polyline = out_f[pline_count] - - if len(points) == num_points_per_polyline: - for j in range(a, groups_f_s.value): - if groups_f[j] > 0: - a = j - break - - polylines[a][b] = Polyline(points) - points = [] - num_polylines_per_group = groups_f[a] - if b == (num_polylines_per_group - 1): - a += 1 - b = 0 - else: - b += 1 - pline_count += 1 - - return polylines - - -def coord_numbers_lists(out_f, out_f_s, out_v, out_v_s): - - # create Python objects - ids = [[] for _ in range(out_f_s.value)] - - for i in range(out_f_s.value): - ids[i] = [None] * out_f[i] - if out_f[i] == 0: - return - - # fill array with points - a = 0 - b = 0 - for i in range(0, out_v_s.value): - ids[a][b] = out_v[i] - if b == (out_f[a] - 1): - a += 1 - b = 0 - else: - b += 1 - - return ids - +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 math import floor class connections_zones(component): - - bbox = Rhino.Geometry.BoundingBox.Unset - lines = [] - insertion_vectors_current = [] - joint_per_face_current_text_entity = [] - polylines = [] - + def __init__(self): + self.bbox = Rhino.Geometry.BoundingBox.Unset + self.lines = [] + self.insertion_vectors_current = [] + self.joint_per_face_current_text_entity = [] + self.polylines = [] + def DrawViewportWires(self, args): - #GrasshopperDocument = Grasshopper.Instances.ActiveCanvas.Document - #is_selected = False - """ - for _ in GrasshopperDocument.Objects: - is_selected = _.Attributes.Selected - """ - #col = args.WireColour_Selected if is_selected else args.WireColour; - col = args.WireColour - line_weight = args.DefaultCurveThickness; - try: - for polyline in self.polylines: - args.Display.DrawPolyline(polyline, col, line_weight) - """ - plane = Plane.WorldXY - for line in self.lines: - args.Display.DrawLineArrow(line, Color.FromArgb(207, 0, 90), 2, 100) - for insertionVectorsCurrent in self.insertion_vectors_current: - if(insertionVectorsCurrent.Length<0.05): - continue - args.Display.DrawLine(insertionVectorsCurrent, Color.FromArgb(0, 0, 0), 5) - for jointPerFaceCurrent in self.joint_per_face_current_text_entity: - result, plane = Rhino.RhinoDoc.ActiveDoc.Views.ActiveView.ActiveViewport.GetCameraFrame() - plane.Origin=(jointPerFaceCurrent.Plane.Origin) - args.Display.Draw3dText(jointPerFaceCurrent.PlainText, jointPerFaceCurrent.MaskColor, plane, jointPerFaceCurrent.TextHeight, "Arial", False, False,Rhino.DocObjects.TextHorizontalAlignment.Center, Rhino.DocObjects.TextVerticalAlignment.BottomOfTop) - """ - except Exception, e: - System.Windows.Forms.MessageBox.Show(str(e), "script error") - + col = args.WireColour + line_weight = args.DefaultCurveThickness + print(self.polylines) + for polylines_list in self.polylines: + for polyline in polylines_list: + args.Display.DrawPolyline(polyline, col, line_weight) + def get_ClippingBox(self): return self.bbox - - def RunScript(self, _data, _join_p, _scale, _extension, _find, _get, _custom_joints, _custom_types): + + def RunScript( + self, + _data, + _joint_p: System.Collections.Generic.List[float], + _scale: System.Collections.Generic.List[float], + _extension: System.Collections.Generic.List[float], + _find: int, + _get: int, + _custom_joints: System.Collections.Generic.List[Rhino.Geometry.Polyline], + _custom_types: System.Collections.Generic.List[int], + ): + # ============================================================================== # clear input # ============================================================================== @@ -193,426 +55,146 @@ def RunScript(self, _data, _join_p, _scale, _extension, _find, _get, _custom_joi self.insertion_vectors_current = [] self.joint_per_face_current_text_entity = [] self.polylines = [] + # ============================================================================== # input # ============================================================================== - if(_data is None): + if _data is None: return - - input_polylines = [] - if( _data[0] != 0): - #convert to compas polylines - for i in _data[0]: - for j in i: - input_polylines.append(j)#(conversions.polyline_to_compas(j)) - - input_vectors = [] - if(_data[1] != None): - for i in _data[1]: - list = [] - for j in i: - list.append(j)#(conversions.vector_to_compas(j)) - input_vectors.append(list) - - joint_parameters = [ - 300, 0.5, 3, # 1-9 ss_e_ip (side-to-side edge in-plane) - 50, 0.64, 15, # 10-19 ss_e_op (side-to-side edge out-of-plane) - 450, 0.5, 20, # 20-29 ts_e_p (top-to-side edge plane) - 300, 0.5, 30, # 30-39 cr_c_ip (cross cutting in-plane) - 6, 0.95, 40, # 40-49 tt_e_p (top-to-top edge plane) - 300, 0.5, 58, # 50-59 ss_e_r (side-to-side edge rotated) - 300, 1.0, 60 # 60-69 b (boundary) - ] - - for i in range(0, len(_join_p)): - if(i%3==0): - joint_parameters[i] = _join_p[i]*10 - else: - joint_parameters[i] = _join_p[i]*1 - - - search = id = max(min(2, _find), 0) - - scale = [1,1,1] - for i in range(0, len(_scale)): - scale[i] = _scale[i] - - output_type = _get if _get != None else 4 - - extension = [0,0,0] - - if(len(_extension)>2): - extension = [] - for i in _extension: - extension.append(i*10) - - - - input_adjacency = [] - if(len(_data[4])>0): - for i in _data[4]: - for j in i: - input_adjacency.append(j) - - ############################################################################################################ - # Load inputs and perform conversion - ############################################################################################################ - - # input geometry - # input_polylines = data_set_plates.annen_small_polylines() - # print(len(input_polylines)) - ( - in_polyline_pairs_f, - in_polyline_pairs_f_s, - in_polyline_pairs_v, - in_polyline_pairs_v_s, - ) = list_polylines_coord(input_polylines) - - - #input_vectors = data_set_plates.annen_small_edge_directions() - - ( - in_vectors_f, - in_vectors_f_s, - in_vectors_v, - in_vectors_v_s, - ) = lists_vectors_coord(input_vectors) - - - - input_joints = _data[2]#data_set_plates.annen_small_edge_joints() - # print(len(input_joints)) - ( - in_joints_f, - in_joints_f_s, - in_joints_v, - in_joints_v_s, - ) = lists_numbers_coord(input_joints) - - input_three_valence =_data[3]#(data_set_plates.annen_small_three_valance_element_indices_and_instruction() ) - - # print(len(input_three_valence)) - - ( - in_three_valence_f, - in_three_valence_f_s, - in_three_valence_v, - in_three_valence_v_s, - ) = lists_numbers_coord(input_three_valence) - - #input_adjacency = [] - - ( - in_adjancency_v, - in_adjancency_v_s, - ) = list_ints_coord(input_adjacency) - - # input parameters - ( - in_joint_parameters_v, - in_joint_parameters_v_s, - ) = list_numbers_coord(joint_parameters) - - in_search_type = c_int(search) - ( - in_scale_v, - in_scale_v_s, - ) = list_numbers_coord(scale) - - in_output_type = c_int(output_type) - - ############################################################################################################# - # custom joint types - ############################################################################################################# - - input_joint_polyline_pairs = [] - ( - in_joint_polyline_pairs_f, - in_joint_polyline_pairs_f_s, - in_joint_polyline_pairs_v, - in_joint_polyline_pairs_v_s - ) = list_polylines_coord(_custom_joints,1) - - - input_joint_types = [] - ( - in_joint_types_v, - in_joint_types_v_s - ) = list_ints_coord(_custom_types) - ############################################################################################################# - # output parameters - ############################################################################################################# - - - # output - - # out polylines - out_plines_groups_f = POINTER(c_size_t)() - out_plines_groups_f_s = c_size_t() - out_plines_out_f = POINTER(c_size_t)() - out_plines_out_f_s = c_size_t() - out_plines_out_v = POINTER(c_float)() - out_plines_out_v_s = c_size_t() - - # out types - out_types_f = POINTER(c_size_t)() - out_types_f_s = c_size_t() - out_types_v = POINTER(c_int)() - out_types_v_s = c_size_t() - - # global_parameters - ( - in_joint_volume_parameters_v, - in_joint_volume_parameters_v_s, - ) = list_numbers_coord(extension) - - face_to_face_side_to_side_joints_dihedral_angle = c_float(130.0) - - ############################################################################################################ - # Load library and declare function signature - ############################################################################################################ - if System.Environment.OSVersion.Platform == System.PlatformID.Win32NT: - #print("Windows") - lib_ = cdll.LoadLibrary(plugin_path+"\libgmp-10.dll") - lib = cdll.LoadLibrary(plugin_path+"\pinvoke_wood.dll") - elif System.Environment.OSVersion.Platform == System.PlatformID.Unix: - #print("macOS") - lib = cdll.LoadLibrary("/Users/compas_wood/libpinvoke_wood.dylib") - else: - print("Unknown operating system") - - lib.ctypes_get_connection_zones_with_custom_joints.restype = None - lib.ctypes_get_connection_zones_with_custom_joints.argtypes = [ - # input geometry - # polylines - POINTER(c_size_t), - POINTER(c_size_t), # if a value is passed by reference, it must be a pointer - POINTER(c_float), - POINTER(c_size_t), # if a value is passed by reference, it must be a pointer - # vectors - POINTER(c_size_t), - POINTER(c_size_t), - POINTER(c_float), - POINTER(c_size_t), - # joints - POINTER(c_size_t), - POINTER(c_size_t), - POINTER(c_int), - POINTER(c_size_t), - # three valence - POINTER(c_size_t), - POINTER(c_size_t), - POINTER(c_int), - POINTER(c_size_t), - # adjacency - POINTER(c_int), - POINTER(c_size_t), - #custom joints - POINTER(c_size_t), - POINTER(c_size_t), # if a value is passed by reference, it must be a pointer - POINTER(c_float), - POINTER(c_size_t), # if a value is passed by reference, it must be a pointer - #custom joints types - POINTER(c_int), - POINTER(c_size_t), - # input parameters - POINTER(c_float), - POINTER(c_size_t), - # search_type - POINTER(c_int), - # scale - POINTER(c_float), - POINTER(c_size_t), - # output_type - POINTER(c_int), - # output - # polylines - POINTER(POINTER(c_size_t)), - POINTER(c_size_t), - POINTER(POINTER(c_size_t)), - POINTER(c_size_t), - POINTER(POINTER(c_float)), - POINTER(c_size_t), - # types - POINTER(POINTER(c_size_t)), - POINTER(c_size_t), - POINTER(POINTER(c_int)), - POINTER(c_size_t), - # global_parameters - POINTER(c_float), # joint volume - POINTER(c_size_t), # joint volume - POINTER(c_float) # dihedral angle to switch between in-plane and out-of-plane jointery default is 150 degrees - ] - - # generate joints - start_time = time.time() - ############################################################################################################ - # Call the function - # https://stackoverflow.com/questions/4145775/how-do-i-convert-a-python-list-into-a-c-array-by-using-ctypes - # https://stackoverflow.com/questions/53265216/python-ctypes-type-conversion - ############################################################################################################ - - - lib.ctypes_get_connection_zones_with_custom_joints( - # input geometry - # polylines - in_polyline_pairs_f, - byref(in_polyline_pairs_f_s), - in_polyline_pairs_v, - byref(in_polyline_pairs_v_s), - # vectors - in_vectors_f, - byref(in_vectors_f_s), - in_vectors_v, - byref(in_vectors_v_s), - # joints - in_joints_f, - byref(in_joints_f_s), - in_joints_v, - byref(in_joints_v_s), - # three_valence - in_three_valence_f, - byref(in_three_valence_f_s), - in_three_valence_v, - byref(in_three_valence_v_s), - # adjacency - in_adjancency_v, - byref(in_adjancency_v_s), - - #custom joints - in_joint_polyline_pairs_f, - byref(in_joint_polyline_pairs_f_s), # if a value is passed by reference, it must be a pointer - in_joint_polyline_pairs_v, - byref(in_joint_polyline_pairs_v_s), # if a value is passed by reference, it must be a pointer - #custom joints types - in_joint_types_v, - byref(in_joint_types_v_s), - - # input parameters - # joint_parameters - in_joint_parameters_v, - byref(in_joint_parameters_v_s), - # search_type - byref(in_search_type), - # scale - in_scale_v, - byref(in_scale_v_s), - # output_type - byref(in_output_type), - - - # output - # polylines - byref(out_plines_groups_f), - byref(out_plines_groups_f_s), - byref(out_plines_out_f), - byref(out_plines_out_f_s), - byref(out_plines_out_v), - byref(out_plines_out_v_s), - # types - byref(out_types_f), - byref(out_types_f_s), - byref(out_types_v), - byref(out_types_v_s), - # global_parameters - in_joint_volume_parameters_v, - byref(in_joint_volume_parameters_v_s), - byref(face_to_face_side_to_side_joints_dihedral_angle), + input_polyline_pairs = _data.plines + if input_polyline_pairs: + if len(input_polyline_pairs) > 0: + self.bbox = input_polyline_pairs[0].BoundingBox + for pline in input_polyline_pairs: + self.bbox.Union(pline.BoundingBox) + + input_insertion_vectors = _data.insertion_vectors + + input_joint_types = _data.joints_per_face + input_three_valence_element_indices_and_instruction = _data.three_valence + + input_search_type = max(min(2, _find), 0) if _find else 0 + + input_scale = [1, 1, 1] + if _scale: + for i in range(0, len(_scale)): + input_scale[i] = _scale[i] + + input_output_type = _get if _get is not None else 4 + + input_joint_volume_parameters = [0, 0, 0] + + if _extension: + if len(_extension) > 2: + input_joint_volume_parameters = [] + for i in _extension: + input_joint_volume_parameters.append(i * 10) + + input_adjacency = _data.adjacency + + joint_parameters = wood_globals.joints_parameters_and_types + + if _joint_p: + for i in range(0, len(_joint_p), 3): + insertion_id = floor(_joint_p[i + 2] / 10) + joint_parameters[insertion_id * 3 + 0] = _joint_p[i + 0] + joint_parameters[insertion_id * 3 + 1] = _joint_p[i + 1] + joint_parameters[insertion_id * 3 + 2] = _joint_p[i + 2] + + w_output_plines = wood_nano_point3() + w_output_types = wood_nano_cut_type2() + + if _custom_joints and _custom_types: + if len(_custom_joints) == len(_custom_types): + custom_joints_dict = { + 9: [], + -9: [], + -19: [], + 19: [], + 29: [], + -29: [], + 39: [], + -39: [], + 49: [], + -49: [], + 59: [], + -59: [], + 69: [], + -69: [], + } + for i in range(len(_custom_joints)): + custom_joints_dict[_custom_types[i]].append(_custom_joints[i]) + + for key, value in custom_joints_dict.items(): + + if key == 9: + # print(to_point2.__module__) + # print(to_point2(value)) + wood_globals.custom_joints_ss_e_ip_male = value + + # print(wood_globals.custom_joints_ss_e_ip_male) + elif key == -9: + wood_globals.custom_joints_ss_e_ip_female = value + elif key == 19: + wood_globals.custom_joints_ss_e_op_male = value + elif key == -19: + wood_globals.custom_joints_ss_e_op_female = value + elif key == 29: + wood_globals.custom_joints_ts_e_p_male = value + elif key == -29: + wood_globals.custom_joints_ts_e_p_female = value + elif key == 39: + wood_globals.custom_joints_cr_c_ip_male = value + elif key == -39: + wood_globals.custom_joints_cr_c_ip_female = value + elif key == 49: + wood_globals.custom_joints_tt_e_p_male = value + elif key == -49: + wood_globals.custom_joints_tt_e_p_female = value + elif key == 59: + wood_globals.custom_joints_ss_e_r_male = value + elif key == -59: + wood_globals.custom_joints_ss_e_r_female = value + elif key == 69: + wood_globals.custom_joints_b_male = value + elif key == -69: + wood_globals.custom_joints_b_female = value + + # print(type(wood_globals.custom_joints_ss_e_ip_male[0])) + from wood_nano import GLOBALS + + print(GLOBALS.CUSTOM_JOINTS_SS_E_IP_MALE[0][0][2]) + wood_nano_get_connection_zones( + to_point2(input_polyline_pairs), + to_vector2(input_insertion_vectors), + to_int2(input_joint_types), + to_int2(input_three_valence_element_indices_and_instruction), + to_int1(input_adjacency), + to_double1(joint_parameters), + int(input_search_type), + to_double1(input_scale), + int(input_output_type), + w_output_plines, + w_output_types, + to_double1(input_joint_volume_parameters), + [], + [], + # to_point2(input_custom_joints), + # to_int1(input_custom_joints_types), ) - """ - - print(out_plines_groups_f[0]) - out_polylines = [] - """ - out_polylines = coord_polylines_lists( - out_plines_groups_f, - out_plines_groups_f_s, - out_plines_out_f, - out_plines_out_f_s, - out_plines_out_v, - out_plines_out_v_s, - ) - - - def temp_coord_numbers_lists(out_f, out_f_s, out_v, out_v_s): - - # create Python objects - ids = [[] for _ in range(out_f_s.value)] - - - - for i in range(out_f_s.value): - #print(i, out_f_s.value) - ids[i] = [None] * out_f[i] - if out_f[i] == 0: - break - - #print( ids) - # fill array with points - a = 0 - b = 0 - #for i in range(0, out_v_s.value): - # print( out_v[i]) - """ - ids[a][b] = out_v[i] - if b == (out_f[a] - 1): - a += 1 - b = 0 - else: - b += 1 - """ - - return ids - - _cuts = coord_numbers_lists( - out_types_f, out_types_f_s, out_types_v, out_types_v_s - ) - """ - print _cuts - print out_types_f, out_types_f_s, out_types_v, out_types_v_s - print out_types_v[0] - print out_types_f[0] - """ - print( - "\n______________________________________ %s ms ______________________________________" - % round((time.time() - start_time) * 1000.0, 2) - ) - - - - - - # ============================================================================== - # output - # ============================================================================== - _plines = [] - self.bbox = Rhino.Geometry.BoundingBox.Unset - # nest two times the result and add to the tree - for i in range(0, len(out_polylines)): - list = [] - for j in range(0, len(out_polylines[i])): - list.append(out_polylines[i][j])#(conversions.polyline_to_rhino(out_polylines[i][j])) - self.polylines.append(list[-1]) - self.bbox.Union(list[-1].BoundingBox) - _plines.append(list) - - _data = [[_plines,_data[1],_data[2],_data[3],_data[4],_data[5],_cuts]] - #print(_cuts) - - ############################################################################################################ - # release the memory - ############################################################################################################ - - # release output of polylines - lib.release_size_t(byref(out_plines_groups_f), True) - lib.release_size_t(byref(out_plines_out_f), True) - lib.release_float(byref(out_plines_out_v), True) - - # release output of types - lib.release_size_t(byref(out_types_f), True) - lib.release_int(byref(out_types_v), True) - - - return _data \ No newline at end of file + self.polylines = from_point3(w_output_plines) + print(w_output_plines) + print(w_output_types) + + return WoodData( + plines=_data.plines, + insertion_vectors=_data.insertion_vectors, + joints_per_face=_data.joints_per_face, + three_valence=_data.three_valence, + adjacency=_data.adjacency, + planes=_data.planes, + plines_with_joints=self.polylines, + cut_types=from_cut_type2(w_output_types), + ) diff --git a/src/rhino/gh/cpy/xml_read/code.py b/src/rhino/gh/cpy/xml_read/code.py index 72b7cecb3..bb901ab3c 100644 --- a/src/rhino/gh/cpy/xml_read/code.py +++ b/src/rhino/gh/cpy/xml_read/code.py @@ -1,32 +1,26 @@ -__author__ = "petras vestartas" -__version__ = "2023.03.28" - -""" -Read polylines and cutting types from xml file -""" -from ghpythonlib.componentbase import executingcomponent as component +from ghpythonlib.componentbase import executingcomponent as component # noqa: E402 +import Grasshopper as gh +import Rhino.Geometry as rg import clr clr.AddReference("System.Xml") -import System.Xml -import Grasshopper as gh -import Rhino.Geometry as rg +import System.Xml # noqa: E402 class write_component(component): def RunScript(self, _path): - if _path == None: + if _path is None: return False - ############################################################################################################################################# - ##Load document - ############################################################################################################################################# + ################################################################################################################ + # Load document + ################################################################################################################ doc = System.Xml.XmlDocument() doc.Load(_path) - ############################################################################################################################################# - ##Start document - ############################################################################################################################################# + ################################################################################################################ + # Start document + ################################################################################################################ polylines_tree = gh.DataTree[rg.Polyline]() types_tree = gh.DataTree[str]() @@ -63,10 +57,4 @@ def RunScript(self, _path): types_tree.Add((node_0.ChildNodes[0].InnerText), gh.Kernel.Data.GH_Path(group_count_b)) group_count_b = group_count_b + 1 - ############################################################################################################################################# - # Close document - ############################################################################################################################################# - __plines = polylines_tree - __types = types_tree - return polylines_tree, types_tree diff --git a/src/rhino/gh/cpy/xml_write/code.py b/src/rhino/gh/cpy/xml_write/code.py index 2395945e3..75e544e68 100644 --- a/src/rhino/gh/cpy/xml_write/code.py +++ b/src/rhino/gh/cpy/xml_write/code.py @@ -1,17 +1,8 @@ -__author__ = "petras vestartas" -__version__ = "2023.03.28" - -""" -Write polylines to xml file -""" - from ghpythonlib.componentbase import executingcomponent as component import clr -import Rhino -import Grasshopper clr.AddReference("System.Xml") -import System.Xml +import System.Xml # noqa: E402 class write_component(component): @@ -37,7 +28,7 @@ def xml_polyline(self, xmlWriter, pline, name): xmlWriter.WriteEndElement() def RunScript(self, _plines, _path): - if _path == None or _plines.AllData().Count == 0: + if _path is None or _plines.AllData().Count == 0: return False ########################################################################## # Create document diff --git a/src/rhino/gh/cpy/xml_write_with_properties/code.py b/src/rhino/gh/cpy/xml_write_with_properties/code.py index 717b9b692..13d65b3c8 100644 --- a/src/rhino/gh/cpy/xml_write_with_properties/code.py +++ b/src/rhino/gh/cpy/xml_write_with_properties/code.py @@ -1,17 +1,8 @@ -__author__ = "petras vestartas" -__version__ = "2023.03.28" - -""" -Write polylines with properties to xml file -""" - from ghpythonlib.componentbase import executingcomponent as component import clr -import Rhino -import Grasshopper clr.AddReference("System.Xml") -import System.Xml +import System.Xml # noqa: E402 class write_component(component): @@ -69,7 +60,7 @@ def RunScript( self, _plines, _insertion_vectors, _joints_types, _type_of_three_valence, _three_valence, _adjacency, _path ): - if _path == None or _plines.AllData().Count == 0: + if _path is None or _plines.AllData().Count == 0: return False ##########################################################################