From 0113ac877f8cb15b2eeaecfac7381818317535b6 Mon Sep 17 00:00:00 2001 From: Durman Date: Sun, 15 Dec 2019 09:37:55 +0400 Subject: [PATCH 1/3] new node --- index.md | 1 + nodes/modifier_make/delaunay_2d_cdt.py | 90 ++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 nodes/modifier_make/delaunay_2d_cdt.py diff --git a/index.md b/index.md index 014132ece..08048db35 100644 --- a/index.md +++ b/index.md @@ -127,6 +127,7 @@ SvConvexHullNodeMK2 SvSubdivideNode DelaunayTriangulation2DNode + SvDelaunay2DCdt Voronoi2DNode SvOffsetLineNode SvContourNode diff --git a/nodes/modifier_make/delaunay_2d_cdt.py b/nodes/modifier_make/delaunay_2d_cdt.py new file mode 100644 index 000000000..64c730f61 --- /dev/null +++ b/nodes/modifier_make/delaunay_2d_cdt.py @@ -0,0 +1,90 @@ +# 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 + + +from itertools import cycle + +import bpy +from mathutils import Vector + +from sverchok.node_tree import SverchCustomTreeNode +from sverchok.data_structure import updateNode + +try: + from mathutils.geometry import delaunay_2d_cdt as bl_delaunay +except ImportError: + print("Sv: The 'Delaunay 2D Cdt' node is not available in your Blender version. Blender 2.81+ is required") + bl_delaunay = None + + +def get_delaunay(verts, edges=None, faces=None, mode=0, epsilon=1e-5): + if edges is None: + edges = [] + if faces is None: + faces = [] + bl_verts = [Vector(co[:2]) for co in verts] + new_verts, new_edges, new_faces, _, _, _ = bl_delaunay(bl_verts, edges, faces, mode, epsilon) + return [v.to_3d()[:] for v in new_verts], new_edges, new_faces + + +class SvDelaunay2DCdt(bpy.types.Node, SverchCustomTreeNode): + """ + Triggers: ... + Tooltip: ... + + ... + """ + bl_idname = 'SvDelaunay2DCdt' + bl_label = 'Delaunay 2D Cdt' + bl_icon = 'MOD_BOOLEAN' + + mode_list = ['convex', 'inside', 'intersected', 'extra edges'] + mode_items = [(v, v.title(), "", i) for i, v in enumerate(mode_list)] + + mode: bpy.props.EnumProperty(items=mode_items, update=updateNode, description="What output looks like") + epsilon: bpy.props.IntProperty(name='Epsilon', update=updateNode, default=5, min=3, max=12, + description='For nearness tests; should not be zero') + + def draw_buttons(self, context, layout): + if not bl_delaunay: + layout.label(text="For 2.81+ only") + else: + layout.prop(self, 'mode', text="") + + def draw_buttons_ext(self, context, layout): + layout.prop(self, 'epsilon') + + def sv_init(self, context): + if bl_delaunay: + self.inputs.new('SvVerticesSocket', 'Verts') + self.inputs.new('SvStringsSocket', "Edges") + self.inputs.new('SvStringsSocket', "Faces") + self.outputs.new('SvVerticesSocket', 'Verts') + self.outputs.new('SvStringsSocket', "Edges") + self.outputs.new('SvStringsSocket', "Faces") + + def process(self): + if not self.inputs['Verts'].is_linked: + return + + out = [] + for v, e, f in zip(self.inputs['Verts'].sv_get(), + self.inputs['Edges'].sv_get() if self.inputs['Edges'].is_linked else cycle([None]), + self.inputs['Faces'].sv_get() if self.inputs['Faces'].is_linked else cycle([None])): + out.append(get_delaunay(v, e, f, self.mode_list.index(self.mode), 1 / 10 ** self.epsilon)) + out_v, out_e, out_f = zip(*out) + self.outputs['Verts'].sv_set(out_v) + self.outputs['Edges'].sv_set(out_e) + self.outputs['Faces'].sv_set(out_f) + + +def register(): + bpy.utils.register_class(SvDelaunay2DCdt) + + +def unregister(): + bpy.utils.unregister_class(SvDelaunay2DCdt) -- GitLab From bbffd9a8d9d617340feab607031e12d55744a542 Mon Sep 17 00:00:00 2001 From: Durman Date: Sun, 15 Dec 2019 21:19:35 +0400 Subject: [PATCH 2/3] add face data input/output --- nodes/modifier_make/delaunay_2d_cdt.py | 44 +++++++++++++++++++------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/nodes/modifier_make/delaunay_2d_cdt.py b/nodes/modifier_make/delaunay_2d_cdt.py index 64c730f61..b03abc09a 100644 --- a/nodes/modifier_make/delaunay_2d_cdt.py +++ b/nodes/modifier_make/delaunay_2d_cdt.py @@ -21,28 +21,44 @@ except ImportError: bl_delaunay = None -def get_delaunay(verts, edges=None, faces=None, mode=0, epsilon=1e-5): +def get_delaunay(verts, edges=None, faces=None, face_data=None, mode=0, epsilon=1e-5): + """ + Crete delaunay triangulation from given mesh, can cut by given faces and closed edge loops in mode=1 + :param verts: list of Sv vertices + :param edges: list of (int, int) + :param faces: list of list int + :param face_data: any data related with given faces + :param mode: 0 or 1, when 1 it does not consider mesh outside given faces and closed edges loops + :param epsilon: int > 0; For nearness tests; should not be zero + :return: list of Sv vertices, edges, faces, filtered related with faces data if given + or indexes of old given faces per new face + """ if edges is None: edges = [] if faces is None: faces = [] bl_verts = [Vector(co[:2]) for co in verts] - new_verts, new_edges, new_faces, _, _, _ = bl_delaunay(bl_verts, edges, faces, mode, epsilon) - return [v.to_3d()[:] for v in new_verts], new_edges, new_faces + new_verts, new_edges, new_faces, orig_v, orig_e, orig_f = bl_delaunay(bl_verts, edges, faces, mode, epsilon) + if face_data: + face_data_out = [face_data[li[0] if li else -1] for li in orig_f] + else: + face_data_out = [li[0] if li else -1 for li in orig_f] + return [v.to_3d()[:] for v in new_verts], new_edges, new_faces, face_data_out class SvDelaunay2DCdt(bpy.types.Node, SverchCustomTreeNode): """ - Triggers: ... - Tooltip: ... + Triggers: Delaunay triangulation 2D + Tooltip: Can crete triangulation inside given faces or closed edge loops - ... + Also it finds intersection of given edges """ bl_idname = 'SvDelaunay2DCdt' bl_label = 'Delaunay 2D Cdt' bl_icon = 'MOD_BOOLEAN' + sv_icon = 'SV_DELAUNAY' - mode_list = ['convex', 'inside', 'intersected', 'extra edges'] + mode_list = ['convex', 'inside'] mode_items = [(v, v.title(), "", i) for i, v in enumerate(mode_list)] mode: bpy.props.EnumProperty(items=mode_items, update=updateNode, description="What output looks like") @@ -53,7 +69,7 @@ class SvDelaunay2DCdt(bpy.types.Node, SverchCustomTreeNode): if not bl_delaunay: layout.label(text="For 2.81+ only") else: - layout.prop(self, 'mode', text="") + layout.prop(self, 'mode', expand=True) def draw_buttons_ext(self, context, layout): layout.prop(self, 'epsilon') @@ -63,23 +79,27 @@ class SvDelaunay2DCdt(bpy.types.Node, SverchCustomTreeNode): self.inputs.new('SvVerticesSocket', 'Verts') self.inputs.new('SvStringsSocket', "Edges") self.inputs.new('SvStringsSocket', "Faces") + self.inputs.new('SvStringsSocket', "Face data") self.outputs.new('SvVerticesSocket', 'Verts') self.outputs.new('SvStringsSocket', "Edges") self.outputs.new('SvStringsSocket', "Faces") + self.outputs.new('SvStringsSocket', "Face data") def process(self): if not self.inputs['Verts'].is_linked: return out = [] - for v, e, f in zip(self.inputs['Verts'].sv_get(), + for v, e, f, fd in zip(self.inputs['Verts'].sv_get(), self.inputs['Edges'].sv_get() if self.inputs['Edges'].is_linked else cycle([None]), - self.inputs['Faces'].sv_get() if self.inputs['Faces'].is_linked else cycle([None])): - out.append(get_delaunay(v, e, f, self.mode_list.index(self.mode), 1 / 10 ** self.epsilon)) - out_v, out_e, out_f = zip(*out) + self.inputs['Faces'].sv_get() if self.inputs['Faces'].is_linked else cycle([None]), + self.inputs['Face data'].sv_get() if self.inputs['Face data'].is_linked else cycle([None])): + out.append(get_delaunay(v, e, f, fd, self.mode_list.index(self.mode), 1 / 10 ** self.epsilon)) + out_v, out_e, out_f, out_fd = zip(*out) self.outputs['Verts'].sv_set(out_v) self.outputs['Edges'].sv_set(out_e) self.outputs['Faces'].sv_set(out_f) + self.outputs['Face data'].sv_set(out_fd) def register(): -- GitLab From 6285aa8f6a2be19949c9a6425046523b4804a8f0 Mon Sep 17 00:00:00 2001 From: Durman Date: Sun, 15 Dec 2019 21:36:01 +0400 Subject: [PATCH 3/3] documentation --- docs/nodes/modifier_make/delaunay_2d_cdt.rst | 60 +++++++++++++++++++ .../modifier_make/modifier_make_index.rst | 1 + 2 files changed, 61 insertions(+) create mode 100644 docs/nodes/modifier_make/delaunay_2d_cdt.rst diff --git a/docs/nodes/modifier_make/delaunay_2d_cdt.rst b/docs/nodes/modifier_make/delaunay_2d_cdt.rst new file mode 100644 index 000000000..1503ece97 --- /dev/null +++ b/docs/nodes/modifier_make/delaunay_2d_cdt.rst @@ -0,0 +1,60 @@ +Random points on mesh +===================== + +.. image:: https://user-images.githubusercontent.com/28003269/70866264-f088e600-1f80-11ea-91b2-f8b785c597a3.png + +Functionality +------------- +Computes the Constrained Delaunay Triangulation of a set of vertices, +with edges and faces that must appear in the triangulation. Some triangles may be eaten away, +or combined with other triangles, according to output type. +The returned verts may be in a different order from input verts, may be moved slightly, +and may be merged with other nearby verts. + +Category +-------- + +Modifiers -> Modifier make -> Delaunay 2D cdt + +Inputs +------ + +- **Verts** - vertices of given mesh(es) +- **Edges** - edges of given mesh(es) +- **Faces** - faces of given mesh(es) +- **Face data** (optional, one value per face of mesh) - Any data related with given faces. + + +Outputs +------- + +- **Verts** - vertices, some can be deleted +- **Edges** - new and old edges +- **Faces** - new and old faces +- **Face data** - filtered according topology changes given face data if was give one or indexes of old faces + +Modes +----- + +- **Convex** - given mesh will be triangulated into bounding convex face +- **Inside** - all parts outside given faces or closed edge loops will be ignored by triangulation algorithm + +N panel +------- + +- **Epsilon** - For nearness tests; number of figures after coma + +Examples +-------- + +**Combine of a line and random points into Delaunay triangulation:** + +.. image:: https://user-images.githubusercontent.com/28003269/70866163-b10dca00-1f7f-11ea-9fb3-5af27c211b4a.png + +**Triangulation of points inside given face:** + +.. image:: https://user-images.githubusercontent.com/28003269/70858673-aa4f6a80-1f1f-11ea-8c94-dbae1ce37909.png + +**Keeping color initial faces:** + +.. image:: https://user-images.githubusercontent.com/28003269/70865972-0399b700-1f7d-11ea-9d23-c3dafe3158a5.png \ No newline at end of file diff --git a/docs/nodes/modifier_make/modifier_make_index.rst b/docs/nodes/modifier_make/modifier_make_index.rst index 07d9ccdec..5e97e8e6a 100644 --- a/docs/nodes/modifier_make/modifier_make_index.rst +++ b/docs/nodes/modifier_make/modifier_make_index.rst @@ -26,3 +26,4 @@ Modifier Make convex_hull_mk2 dual_mesh random_points_on_mesh + delaunay_2d_cdt -- GitLab