From 676f58a85482baea7181d43241254a35df0a5845 Mon Sep 17 00:00:00 2001 From: Ilya Portnov Date: Thu, 13 Feb 2020 20:18:22 +0500 Subject: [PATCH 1/3] "Clip vertices" node. --- index.md | 4 +- nodes/modifier_make/clip_verts.py | 76 +++++++++++++++++++++++++++++++ utils/sv_bmesh_utils.py | 36 +++++++++++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 nodes/modifier_make/clip_verts.py diff --git a/index.md b/index.md index 69ae04741..52975475b 100644 --- a/index.md +++ b/index.md @@ -146,9 +146,11 @@ Voronoi2DNode SvOffsetLineNode SvContourNode + SvRandomPointsOnMesh + --- SvDualMeshNode SvDiamondMeshNode - SvRandomPointsOnMesh + SvClipVertsNode --- SvBevelCurveNode SvAdaptiveEdgeNode diff --git a/nodes/modifier_make/clip_verts.py b/nodes/modifier_make/clip_verts.py new file mode 100644 index 000000000..44a24c9d8 --- /dev/null +++ b/nodes/modifier_make/clip_verts.py @@ -0,0 +1,76 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +import bpy +from mathutils import Matrix, Vector + +from bpy.props import IntProperty, FloatProperty, EnumProperty +from sverchok.node_tree import SverchCustomTreeNode +from sverchok.data_structure import updateNode, zip_long_repeat +from sverchok.utils.sv_bmesh_utils import pydata_from_bmesh, bmesh_from_pydata, truncate_vertices + +class SvClipVertsNode(bpy.types.Node, SverchCustomTreeNode): + """ + Trigers: Clip / Truncate Vertices + Tooltip: Clip all vertices of the mesh + """ + bl_idname = 'SvClipVertsNode' + bl_label = "Clip Vertices" + bl_icon = 'OUTLINER_OB_EMPTY' + sv_icon = 'SV_DIAMOND_MESH' + + def sv_init(self, context): + self.inputs.new('SvVerticesSocket', 'Vertices') + self.inputs.new('SvStringsSocket', 'Edges') + self.inputs.new('SvStringsSocket', 'Faces') + + self.outputs.new('SvVerticesSocket', 'Vertices') + self.outputs.new('SvStringsSocket', 'Edges') + self.outputs.new('SvStringsSocket', 'Faces') + + def process(self): + if not any((s.is_linked for s in self.outputs)): + return + + verts_s = self.inputs['Vertices'].sv_get() + edges_s = self.inputs['Edges'].sv_get(default=[[]]) + faces_s = self.inputs['Faces'].sv_get() + + verts_out = [] + edges_out = [] + faces_out = [] + for verts, edges, faces in zip_long_repeat(verts_s, edges_s, faces_s): + bm = bmesh_from_pydata(verts, edges, faces, normal_update=True) + new_bm = truncate_vertices(bm) + bm.free() + new_verts, new_edges, new_faces = pydata_from_bmesh(new_bm) + new_bm.free() + verts_out.append(new_verts) + edges_out.append(new_edges) + faces_out.append(new_faces) + + self.outputs['Vertices'].sv_set(verts_out) + self.outputs['Edges'].sv_set(edges_out) + self.outputs['Faces'].sv_set(faces_out) + +def register(): + bpy.utils.register_class(SvClipVertsNode) + +def unregister(): + bpy.utils.unregister_class(SvClipVertsNode) + diff --git a/utils/sv_bmesh_utils.py b/utils/sv_bmesh_utils.py index a289d8cbd..7b2d525cf 100644 --- a/utils/sv_bmesh_utils.py +++ b/utils/sv_bmesh_utils.py @@ -368,6 +368,42 @@ def diamond_mesh(bm): return new_bm +def truncate_vertices(bm): + + def calc_angle(co, orth, co_orth, vert): + direction = vert.co - co + dx = direction.dot(orth) + dy = direction.dot(co_orth) + return math.atan2(dy, dx) + + new_bm = bmesh.new() + edge_centers = dict() + for edge in bm.edges: + center_co = (edge.verts[0].co + edge.verts[1].co) / 2.0 + edge_centers[edge.index] = new_bm.verts.new(center_co) + for face in bm.faces: + new_face = [edge_centers[edge.index] for edge in face.edges] + old_normal = face.normal + new_normal = mathutils.geometry.normal(*[vert.co for vert in new_face]) + if new_normal.dot(old_normal) < 0: + new_face = list(reversed(new_face)) + new_bm.faces.new(new_face) + for vertex in bm.verts: + new_face = [edge_centers[edge.index] for edge in vertex.link_edges] + if len(new_face) > 2: + old_normal = vertex.normal + orth = old_normal.orthogonal() + co_orth = old_normal.cross(orth) + new_face = sorted(new_face, key = lambda edge_center : calc_angle(vertex.co, orth, co_orth, edge_center)) + new_face = list(new_face) + new_bm.faces.new(new_face) + + new_bm.verts.index_update() + new_bm.edges.index_update() + new_bm.faces.index_update() + + return new_bm + def get_neighbour_faces(face, by_vert = True): """ Get neighbour faces of the given face. -- GitLab From 1b1c69199a0a85079a812336634658851d404999 Mon Sep 17 00:00:00 2001 From: Ilya Portnov Date: Thu, 13 Feb 2020 20:28:26 +0500 Subject: [PATCH 2/3] Icon. --- nodes/modifier_make/clip_verts.py | 2 +- ui/icons/sv_clip_verts.png | Bin 0 -> 2663 bytes ui/icons/svg/sv_clip_verts.svg | 153 ++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 ui/icons/sv_clip_verts.png create mode 100644 ui/icons/svg/sv_clip_verts.svg diff --git a/nodes/modifier_make/clip_verts.py b/nodes/modifier_make/clip_verts.py index 44a24c9d8..ad7729ea6 100644 --- a/nodes/modifier_make/clip_verts.py +++ b/nodes/modifier_make/clip_verts.py @@ -32,7 +32,7 @@ class SvClipVertsNode(bpy.types.Node, SverchCustomTreeNode): bl_idname = 'SvClipVertsNode' bl_label = "Clip Vertices" bl_icon = 'OUTLINER_OB_EMPTY' - sv_icon = 'SV_DIAMOND_MESH' + sv_icon = 'SV_CLIP_VERTS' def sv_init(self, context): self.inputs.new('SvVerticesSocket', 'Vertices') diff --git a/ui/icons/sv_clip_verts.png b/ui/icons/sv_clip_verts.png new file mode 100644 index 0000000000000000000000000000000000000000..2aa3392ba4f1e146fcffac3ef5269b9182b6f355 GIT binary patch literal 2663 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 z + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + -- GitLab From b08153044d32a7be27ee12502791c3caac3c8f73 Mon Sep 17 00:00:00 2001 From: Ilya Portnov Date: Thu, 13 Feb 2020 20:44:18 +0500 Subject: [PATCH 3/3] Documentation. --- docs/nodes/modifier_make/clip_verts.rst | 53 +++++++++++++++++++ .../modifier_make/modifier_make_index.rst | 1 + 2 files changed, 54 insertions(+) create mode 100644 docs/nodes/modifier_make/clip_verts.rst diff --git a/docs/nodes/modifier_make/clip_verts.rst b/docs/nodes/modifier_make/clip_verts.rst new file mode 100644 index 000000000..bf8cc96ac --- /dev/null +++ b/docs/nodes/modifier_make/clip_verts.rst @@ -0,0 +1,53 @@ +Clip Vertices +============= + +Functionality +------------- + +This node cuts off (clips, truncates) all vertices of original mesh, by cutting +each edge in half, and then connecting centers of all edges incidential to each +vertex, to produce new faces. Please refer to usage examples for better +understanding. + +This can give interesting topology, especially in combination with +"dual mesh" and/or "triangulate" and/or "join triangles" and/or "limited +dissolve" nodes. + +Inputs +------ + +This node has the following inputs: + +- **Vertices**. Vertices of original mesh. This input is mandatory. +- **Edges**. Edges of original mesh. +- **Faces**. Faces of original mesh. This input is mandatory. + +Outputs +------- + +This node has the following outputs: + +- **Vertices**. Vertices of the new mesh. +- **Edges**. Edges of the new mesh. +- **Faces**. Faces of the new mesh. + +Examples of Usage +----------------- + +Clip a simple plane / grid: + +.. image:: https://user-images.githubusercontent.com/284644/74450509-fb3bfa80-4e9f-11ea-9acb-f40c44ae2f3d.png + +Clip vertices of a cube: + +.. image:: https://user-images.githubusercontent.com/284644/74450490-f6774680-4e9f-11ea-8504-85d9a7902b52.png + +Applied to a cylinder: + +.. image:: https://user-images.githubusercontent.com/284644/74450506-faa36400-4e9f-11ea-85c5-6899bcaef782.png + + +Applied to Suzanne: + +.. image:: https://user-images.githubusercontent.com/284644/74450498-f8d9a080-4e9f-11ea-9ee2-dbbb0914eb53.png + diff --git a/docs/nodes/modifier_make/modifier_make_index.rst b/docs/nodes/modifier_make/modifier_make_index.rst index c6366ef29..94b45a57f 100644 --- a/docs/nodes/modifier_make/modifier_make_index.rst +++ b/docs/nodes/modifier_make/modifier_make_index.rst @@ -27,6 +27,7 @@ Modifier Make convex_hull_mk2 dual_mesh diamond_mesh + clip_verts random_points_on_mesh delaunay_2d_cdt sweep_modulator -- GitLab