From 44cde8e28c37b36f6b1f42fdcb42a47a88fe1a25 Mon Sep 17 00:00:00 2001 From: rendetto <66558924+rendetto@users.noreply.github.com> Date: Mon, 16 Jan 2023 22:15:55 +0200 Subject: [PATCH 1/8] "Solid Section" node first implementation A node that generates Curves and Points from intersecting different Shapes. --- nodes/solid/solid_section.py | 112 +++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 nodes/solid/solid_section.py diff --git a/nodes/solid/solid_section.py b/nodes/solid/solid_section.py new file mode 100644 index 000000000..61e9b72e8 --- /dev/null +++ b/nodes/solid/solid_section.py @@ -0,0 +1,112 @@ +# This file is part of project Sverchok. It's copyrighted by the contributors +# recorded in the version control history of the file, available from +# its original location https://github.com/nortikin/sverchok/commit/master +# +# SPDX-License-Identifier: GPL3 +# License-Filename: LICENSE + +import bpy +from bpy.props import BoolProperty, EnumProperty + +from sverchok.node_tree import SverchCustomTreeNode +from sverchok.data_structure import (updateNode, map_recursive, zip_long_repeat, + ensure_nesting_level, get_data_nesting_level) +from sverchok.utils.curve.freecad import SvSolidEdgeCurve +from sverchok.dependencies import FreeCAD + +if FreeCAD is not None: + from sverchok.utils.solid import SvBoolResult + import Part + +class SvSolidSectionNode(SverchCustomTreeNode, bpy.types.Node): + """ + Triggers: Section + Tooltip: Generate Intersection Curves and Points + """ + bl_idname = 'SvSolidSectionNode' + bl_label = 'Solid Section' + bl_icon = 'OUTLINER_OB_EMPTY' + sv_icon = 'SV_SOLID_SECTION' + sv_category = "Solid Operators" + sv_dependencies = {'FreeCAD'} + + nurbs_output : BoolProperty( + name = "NURBS Output", + description = "Output curves in NURBS representation", + default = False, + update=updateNode) + + def draw_buttons_ext(self, context, layout): + self.draw_buttons(context, layout) + layout.prop(self, 'nurbs_output', toggle=True) + + def sv_init(self, context): + self.inputs.new('SvSolidSocket', "Shape A") + self.inputs.new('SvSolidSocket', "Shape B") + + self.outputs.new('SvVerticesSocket', "Vertices") + self.outputs.new('SvCurveSocket', "Curves") + + def make_solid(self, solids): + solid = self.make_solid_simple(solids) + return SvBoolResult(solid) + + def make_solid_simple(self, solids): + base = solids[0].copy() + rest = solids[1:] + solid = base.section(rest) + return solid + + def process(self): + if not any(socket.is_linked for socket in self.outputs): + return + + solids_out = [] + + solids_a_in = self.inputs['Shape A'].sv_get() + solids_b_in = self.inputs['Shape B'].sv_get() + level_a = get_data_nesting_level(solids_a_in, data_types=(Part.Shape,)) + level_b = get_data_nesting_level(solids_b_in, data_types=(Part.Shape,)) + solids_a_in = ensure_nesting_level(solids_a_in, 2, data_types=(Part.Shape,)) + solids_b_in = ensure_nesting_level(solids_b_in, 2, data_types=(Part.Shape,)) + level = max(level_a, level_b) + + for params in zip_long_repeat(solids_a_in, solids_b_in): + new_solids = [] + for solid_a, solid_b in zip_long_repeat(*params): + result = self.make_solid([solid_a, solid_b]) + new_solids.append(result.solid) + solids_out.extend(new_solids) + + def get_verts(solid): + verts = [] + for v in solid.Vertexes: + verts.append(v.Point[:]) + return verts + + def get_edges(solid): + edges_curves = [] + for e in solid.Edges: + try: + curve = SvSolidEdgeCurve(e) + if self.nurbs_output: + curve = curve.to_nurbs() + edges_curves.append(curve) + except TypeError: + pass + return edges_curves + + verts_out = map_recursive(get_verts, solids_out, data_types=(Part.Shape,)) + edges_out = map_recursive(get_edges, solids_out, data_types=(Part.Shape,)) + + self.outputs['Vertices'].sv_set(verts_out) + self.outputs['Curves'].sv_set(edges_out) + + +def register(): + bpy.utils.register_class(SvSolidSectionNode) + + +def unregister(): + bpy.utils.unregister_class(SvSolidSectionNode) + -- GitLab From f0515dc729bec0f48be026903f2402ac1bf207bb Mon Sep 17 00:00:00 2001 From: rendetto <66558924+rendetto@users.noreply.github.com> Date: Mon, 16 Jan 2023 22:17:13 +0200 Subject: [PATCH 2/8] Add "Solid Section" node to the menu --- index.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/index.yaml b/index.yaml index bfcf91ffb..da78d20a2 100644 --- a/index.yaml +++ b/index.yaml @@ -270,6 +270,7 @@ - SvChamferSolidNode - SvFilletSolidNode - SvSolidBooleanNode + - SvSolidSectionNode - SvSolidGeneralFuseNode - SvMirrorSolidNode - SvOffsetSolidNode -- GitLab From 00cd6ae0e1d2506dc7fd15c77c37a1f58aee00f2 Mon Sep 17 00:00:00 2001 From: rendetto <66558924+rendetto@users.noreply.github.com> Date: Mon, 16 Jan 2023 22:18:22 +0200 Subject: [PATCH 3/8] Add "Solid Section" node icon --- ui/icons/sv_solid_section.png | Bin 0 -> 1173 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ui/icons/sv_solid_section.png diff --git a/ui/icons/sv_solid_section.png b/ui/icons/sv_solid_section.png new file mode 100644 index 0000000000000000000000000000000000000000..467b3b0dabcb86b276cdc2da892b8acb624150e9 GIT binary patch literal 1173 zcmV;G1Zw+Cjl6y!!xO*w3=U& zg75Glgh2!`DKpzz$}Z;6HGUqcn&KfYdUdbs7@>k{Gr-qJJj*QZ5YH2*w;W6G9`P_M z$pzvQ;uxm`65k44@%T+}(c>?{JeOGj{Gz8+Y-6R3S&19OQ^Zk2udwEM#7)Agxss(k zN^1-@GDsl_2?{FMgboLB$|lXMvoF!`Eu%~xMt=)caB>t;B5#b;3UyT}Yox36>8Ogi z|DUI=%}jgU!%3j`)pb9|f#5z+uet8;sq5CyfWQlIZMOVnn$z4j>9v*?Jq98>z~xO# zQx1TuU0~$dlDXWF0<`>^27Fuq19@QR9_U~9X4Txs`4f=arYE`s4v&Bds*h~^0n0&W z@`N`_z5oCK32;bRa{vGV1ONa51Oc)w@HGGc0?J85K~z}7&6iDU6hRP%dxr5N5se13 ziX zTtb}yr5yh+;3*`Q3L!vZ86N{fI<*ce-~;%sb34F3&M$4tKKKYGTuCGejG%^r1Xv)@Gn)YT?MIyfTR|DWX%_;%2HBk``;2Y! z`U*TxRz3-8pr2U1&IFL-`uv`Ni!K3_#4_rY4oCHM+7ZBbJGxKDFIWAPKuR$qe<=+NgM%?w$c*v^6hi?}bbm%ftM zdm+O{Ue}Z`jyuNB3A)WPc^o{*seb{5>!6r(>i=;>*vE% zN>kRc(n7A-7Q39UmwY^%{=%aeF=5ZMDO^j3+p-o7)v8Q(z#(d zm~1P7-DT809o`_;b7uldLe2o`Txm?{(sOz-$x1u`q{Hu;=p?)kZo4E;Eh|CKo9Hu( zJM|lwQri_1b@sg3JUxGcYb@Z7ZBlZ`ZR;qQ3;tl_dE*%DRD*u7OOw|Uq=&Rx55RSo zrfZZSZIXbp>cgoyP)K Date: Mon, 16 Jan 2023 22:19:28 +0200 Subject: [PATCH 4/8] Add "Solid Section" node documentation --- docs/nodes/solid/solid_section.rst | 93 ++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 docs/nodes/solid/solid_section.rst diff --git a/docs/nodes/solid/solid_section.rst b/docs/nodes/solid/solid_section.rst new file mode 100644 index 000000000..7842f6b97 --- /dev/null +++ b/docs/nodes/solid/solid_section.rst @@ -0,0 +1,93 @@ +Solid Section +============= + +.. image:: https://user-images.githubusercontent.com/66558924/212058287-c0426edb-7f56-425d-8e7c-cc99ff8700c7.jpg + +Dependencies +------------ + +This node requires `FreeCAD library `_ to work. + + +Functionality +------------- + +This node generates the intersection Curves and Points between different Shapes including Solids, Solid Faces, Solid Edges, NURBS Surfaces and NURBS Curves. + +The node can operate on pair of objects ("Shape A" intersects "Shape B") or on pair of lists of objects. + +Inputs +------ + +This node has the following inputs: + +* **Shape A**. The first object to perform operation on. This input is + mandatory and can accept a list of Shapes*. +* **Shape B**. The second object to perform operation on. This input is + mandatory and can accept a list of Shapes*. + + Curves (NURBS Curves and Solid Edges) cannot be mixed with other Shape types. + For example [, , ] is not a valid input list. + + Valid inputs are [, , ] or [, ] + or [, , ] etc. + +Options +------- + +This node has the following parameters: + +* **NURBS Output**. This parameter is available in the N panel only. If + checked, the node will generate curves in NURBS representation. Otherwise, it + will generate standard FreeCAD curves (Solid Edge curves). Unchecked by default. + +Outputs +------- + +This node has the following outputs: + +* **Vertices**. The resulting intersection (puncture) Points or endpoints of the intersection Curves. +* **Curves**. The resulting intersection Curves. + +Product variations of the Section operation: + +* Solid × Curve → Point (common case) or Curve (if the curve or part of the curve overlays with the solid) + +* Solid × Surface → Curve (common case) or Point (when both are only touching) + +* Curve × Surface → Point (common case) or Curve (if the curve or part of the curve overlays with the surface) + +* Solid × Solid → Curve (common case) or Point (when both are only touching) + +* Surface × Surface → Curve (common case) or Point (when both are only touching) + +* Curve × Curve → Point (common case) or Curve (if curves overlay at a certain segment) + + +If no intersections are found the node will output empty lists. + + +Examples +-------- + +**Curve** × **Curve** → **Points**: + +.. image:: https://user-images.githubusercontent.com/66558924/212648237-1f4f052f-1a61-496c-a0db-27eebb8c9524.jpg + + + +**Curves** × **Surface** → **Points and Curve**: + +.. image:: https://user-images.githubusercontent.com/66558924/212650377-26c0af14-1b6d-4039-b655-7719ae4dee03.jpg + + +**Surface** × **List of Surfaces** → **Curves**: + +.. image:: https://user-images.githubusercontent.com/66558924/212664158-65bc2f04-0376-4b8a-bbbf-05812fc4e76e.jpg + + +**Surface** × **Solid** → **Curves**: + +.. image:: https://user-images.githubusercontent.com/66558924/212653198-d616f3ad-d533-4409-a2bf-2e65213f6939.jpg + + -- GitLab From 9cb331ddf3acbc6fbb9582a1b797422c5686d04a Mon Sep 17 00:00:00 2001 From: rendetto <66558924+rendetto@users.noreply.github.com> Date: Mon, 16 Jan 2023 22:42:00 +0200 Subject: [PATCH 5/8] Update full_by_data_type.yaml --- menus/full_by_data_type.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/menus/full_by_data_type.yaml b/menus/full_by_data_type.yaml index d34fa2158..579f9594b 100644 --- a/menus/full_by_data_type.yaml +++ b/menus/full_by_data_type.yaml @@ -471,6 +471,7 @@ - SvChamferSolidNode - SvFilletSolidNode - SvSolidBooleanNode + - SvSolidSectionNode - SvSolidGeneralFuseNode - SvMirrorSolidNode - SvOffsetSolidNode -- GitLab From 957b5ddb71efd24d19f0cc1678f7477dababdac3 Mon Sep 17 00:00:00 2001 From: rendetto <66558924+rendetto@users.noreply.github.com> Date: Mon, 16 Jan 2023 22:46:16 +0200 Subject: [PATCH 6/8] Update full_nortikin.yaml --- menus/full_nortikin.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/menus/full_nortikin.yaml b/menus/full_nortikin.yaml index 940e53878..9c63661b7 100644 --- a/menus/full_nortikin.yaml +++ b/menus/full_nortikin.yaml @@ -561,6 +561,7 @@ - SvChamferSolidNode - SvFilletSolidNode - SvSolidBooleanNode + - SvSolidSectionNode - SvSolidGeneralFuseNode - --- -- GitLab From 3e6f78e07ffa4c98628d6e8fe78450fbaa740ed9 Mon Sep 17 00:00:00 2001 From: rendetto <66558924+rendetto@users.noreply.github.com> Date: Tue, 17 Jan 2023 14:36:25 +0200 Subject: [PATCH 7/8] Cease using SvBoolResult class... ...and some minor changes. --- nodes/solid/solid_section.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/nodes/solid/solid_section.py b/nodes/solid/solid_section.py index 61e9b72e8..14ead478d 100644 --- a/nodes/solid/solid_section.py +++ b/nodes/solid/solid_section.py @@ -6,7 +6,7 @@ # License-Filename: LICENSE import bpy -from bpy.props import BoolProperty, EnumProperty +from bpy.props import BoolProperty from sverchok.node_tree import SverchCustomTreeNode from sverchok.data_structure import (updateNode, map_recursive, zip_long_repeat, @@ -15,7 +15,6 @@ from sverchok.utils.curve.freecad import SvSolidEdgeCurve from sverchok.dependencies import FreeCAD if FreeCAD is not None: - from sverchok.utils.solid import SvBoolResult import Part class SvSolidSectionNode(SverchCustomTreeNode, bpy.types.Node): @@ -48,10 +47,6 @@ class SvSolidSectionNode(SverchCustomTreeNode, bpy.types.Node): self.outputs.new('SvCurveSocket', "Curves") def make_solid(self, solids): - solid = self.make_solid_simple(solids) - return SvBoolResult(solid) - - def make_solid_simple(self, solids): base = solids[0].copy() rest = solids[1:] solid = base.section(rest) @@ -75,7 +70,7 @@ class SvSolidSectionNode(SverchCustomTreeNode, bpy.types.Node): new_solids = [] for solid_a, solid_b in zip_long_repeat(*params): result = self.make_solid([solid_a, solid_b]) - new_solids.append(result.solid) + new_solids.append(result) solids_out.extend(new_solids) def get_verts(solid): -- GitLab From 6c61104f161f4f6eb179cec85cdcf9f520782d56 Mon Sep 17 00:00:00 2001 From: rendetto <66558924+rendetto@users.noreply.github.com> Date: Tue, 17 Jan 2023 20:15:26 +0200 Subject: [PATCH 8/8] Some renaming... Add more appropriate variable and method names. --- nodes/solid/solid_section.py | 49 ++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/nodes/solid/solid_section.py b/nodes/solid/solid_section.py index 14ead478d..9bfe3ca0e 100644 --- a/nodes/solid/solid_section.py +++ b/nodes/solid/solid_section.py @@ -41,47 +41,48 @@ class SvSolidSectionNode(SverchCustomTreeNode, bpy.types.Node): def sv_init(self, context): self.inputs.new('SvSolidSocket', "Shape A") + #"Shape" is a generic term covering all different topological types defined by Open CASCADE Technology (OCCT) self.inputs.new('SvSolidSocket', "Shape B") self.outputs.new('SvVerticesSocket', "Vertices") self.outputs.new('SvCurveSocket', "Curves") - def make_solid(self, solids): - base = solids[0].copy() - rest = solids[1:] - solid = base.section(rest) - return solid + def make_section(self, shapes): + base = shapes[0].copy() + rest = shapes[1:] + section = base.section(rest) + return section def process(self): if not any(socket.is_linked for socket in self.outputs): return - solids_out = [] + sections_out = [] - solids_a_in = self.inputs['Shape A'].sv_get() - solids_b_in = self.inputs['Shape B'].sv_get() - level_a = get_data_nesting_level(solids_a_in, data_types=(Part.Shape,)) - level_b = get_data_nesting_level(solids_b_in, data_types=(Part.Shape,)) - solids_a_in = ensure_nesting_level(solids_a_in, 2, data_types=(Part.Shape,)) - solids_b_in = ensure_nesting_level(solids_b_in, 2, data_types=(Part.Shape,)) + shapes_a_in = self.inputs['Shape A'].sv_get() + shapes_b_in = self.inputs['Shape B'].sv_get() + level_a = get_data_nesting_level(shapes_a_in, data_types=(Part.Shape,)) + level_b = get_data_nesting_level(shapes_b_in, data_types=(Part.Shape,)) + shapes_a_in = ensure_nesting_level(shapes_a_in, 2, data_types=(Part.Shape,)) + shapes_b_in = ensure_nesting_level(shapes_b_in, 2, data_types=(Part.Shape,)) level = max(level_a, level_b) - for params in zip_long_repeat(solids_a_in, solids_b_in): - new_solids = [] - for solid_a, solid_b in zip_long_repeat(*params): - result = self.make_solid([solid_a, solid_b]) - new_solids.append(result) - solids_out.extend(new_solids) + for params in zip_long_repeat(shapes_a_in, shapes_b_in): + new_sections = [] + for shape_a, shape_b in zip_long_repeat(*params): + result = self.make_section([shape_a, shape_b]) + new_sections.append(result) + sections_out.extend(new_sections) - def get_verts(solid): + def get_verts(section): verts = [] - for v in solid.Vertexes: + for v in section.Vertexes: verts.append(v.Point[:]) return verts - def get_edges(solid): + def get_edges(section): edges_curves = [] - for e in solid.Edges: + for e in section.Edges: try: curve = SvSolidEdgeCurve(e) if self.nurbs_output: @@ -91,8 +92,8 @@ class SvSolidSectionNode(SverchCustomTreeNode, bpy.types.Node): pass return edges_curves - verts_out = map_recursive(get_verts, solids_out, data_types=(Part.Shape,)) - edges_out = map_recursive(get_edges, solids_out, data_types=(Part.Shape,)) + verts_out = map_recursive(get_verts, sections_out, data_types=(Part.Shape,)) + edges_out = map_recursive(get_edges, sections_out, data_types=(Part.Shape,)) self.outputs['Vertices'].sv_set(verts_out) self.outputs['Curves'].sv_set(edges_out) -- GitLab