Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #5123 Add quadriflow node #5124

Merged
merged 2 commits into from
May 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,14 @@ def draw_message(box, package, dependencies=None):
except ImportError:
pyacvd = None

pyQuadriFlow_d = sv_dependencies["pyQuadriFlow"] = SvDependency("pyQuadriFlow","https://github.com/satabol/pyQuadriFlow")
pyQuadriFlow_d.pip_installable = True
try:
import pyQuadriFlow
pyQuadriFlow_d.module = pyQuadriFlow
except ImportError:
pyQuadriFlow = None

settings.pip = pip
settings.sv_dependencies = sv_dependencies
settings.ensurepip = ensurepip
Expand Down
31 changes: 31 additions & 0 deletions docs/nodes/modifier_change/quadriflow.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Quadriflow
==========

.. image:: https://github.com/nortikin/sverchok/assets/14288520/094fb95a-e199-438e-b1e8-dcca9132ebe5
:target: https://github.com/nortikin/sverchok/assets/14288520/094fb95a-e199-438e-b1e8-dcca9132ebe5


Description
-----------

This node is a fork of the operator in Blender:

.. image:: https://github.com/nortikin/sverchok/assets/14288520/181ab570-c13d-496a-b5b8-c8418fe31bf9
:target: https://github.com/nortikin/sverchok/assets/14288520/181ab570-c13d-496a-b5b8-c8418fe31bf9

Functionality
-------------

.. image:: https://github.com/nortikin/sverchok/assets/14288520/642dab70-49e3-4142-8de9-32381502e5d2
:target: https://github.com/nortikin/sverchok/assets/14288520/642dab70-49e3-4142-8de9-32381502e5d2

Warning
-------

This is a time consumer node so be carefully with settings.

Examples
--------

.. image:: https://github.com/nortikin/sverchok/assets/14288520/33de8b65-962f-4b05-8bcf-f537690cefd6
:target: https://github.com/nortikin/sverchok/assets/14288520/33de8b65-962f-4b05-8bcf-f537690cefd6
2 changes: 2 additions & 0 deletions index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,8 @@
- SvOffsetLineNode
- SvContourNode
- ---
- SvQuadriFlowNode
- ---
- SvDualMeshNode
- SvDiamondMeshNode
- SvClipVertsNode
Expand Down
2 changes: 2 additions & 0 deletions menus/full_by_data_type.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@
- SvOffsetLineNode
- SvContourNode
- ---
- SvQuadriFlowNode
- ---
- SvDualMeshNode
- SvDiamondMeshNode
- SvClipVertsNode
Expand Down
2 changes: 2 additions & 0 deletions menus/full_nortikin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,8 @@
- SvOffsetLineNode
- SvContourNode
- ---
- SvQuadriFlowNode
- ---
- SvDualMeshNode
- SvDiamondMeshNode
- SvClipVertsNode
Expand Down
217 changes: 217 additions & 0 deletions nodes/modifier_change/quadriflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
# ##### 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 #####

# Implements the QuadriFlow Node
# sverchok/nodes/modifier_change/quadriflow.py

import bpy
import bmesh
from bpy.props import IntProperty, BoolProperty, EnumProperty
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode, match_long_repeat, flatten_data
from sverchok.utils.sv_bmesh_utils import bmesh_from_pydata, pydata_from_bmesh

enable_module = False
try:
import pyQuadriFlow
from pyQuadriFlow.pyQuadriFlow import pyquadriflow
enable_module = True
except ModuleNotFoundError:
enable_module = False

from itertools import chain
import traceback
class SvQuadriFlowNode(bpy.types.Node,SverchCustomTreeNode):
bl_idname = "SvQuadriFlowNode" # Use this for index.md reference
bl_label = "Quadriflow"
bl_icon = 'OUTLINER_OB_EMPTY'
sv_icon = None

sv_dependencies = ['pyQuadriFlow']

#maxSubdivision = 6 # creates a self.maxSubdivision attribute
flag_preserve_sharp : BoolProperty(
name = "Preserve Sharp",
description = "Try to preserve sharp features on the mesh",
default = False,
update = updateNode) # type: ignore

flag_preserve_boundary : BoolProperty(
name = "Preserve Mesh Boundary",
description = "Try to preserve mesh boundary on the mesh",
default = False,
update = updateNode) # type: ignore

flag_adaptive_scale : BoolProperty(
name = "Preserve Adaptive Scale",
description = "???",
default = False,
update = updateNode) # type: ignore

flag_aggresive_sat : BoolProperty(
name = "Preserve Aggresive Sat",
description = "???",
default = False,
update = updateNode) # type: ignore

flag_minimum_cost_flow : BoolProperty(
name = "Minimum Cost Flow",
description = "???",
default = False,
update = updateNode) # type: ignore

quad_modes = [
( "BEAUTY", "Beauty", "Split the quads in nice triangles, slower method", 1),
( "FIXED", "Fixed", "Split the quads on the 1st and 3rd vertices", 2),
( "ALTERNATE", "Fixed Alternate", "Split the quads on the 2nd and 4th vertices", 3),
("SHORT_EDGE", "Shortest Diagonal", "Split the quads based on the distance between the vertices", 4)
]

ngon_modes = [
( "BEAUTY", "Beauty", "Arrange the new triangles nicely, slower method", 1),
("EAR_CLIP", "Clip", "Split the ngons using a scanfill algorithm", 2)
]

quad_mode: EnumProperty(
name='Quads mode',
description="Quads processing mode",
items=quad_modes,
default="BEAUTY",
update=updateNode) # type: ignore

ngon_mode: EnumProperty(
name="Polygons mode",
description="Polygons processing mode",
items=ngon_modes,
default="BEAUTY",
update=updateNode) # type: ignore


# Mute Node Implementation
@property
def sv_internal_links(self):
mapping = [
(self.inputs['Vertices'],self.outputs['Vertices']),
(self.inputs['Faces'],self.outputs['Faces'])
]
return mapping

def sv_init(self,context):
self.width = 200
self.inputs.new('SvVerticesSocket', "vertices")
#self.inputs.new('SvVerticesSocket', "Edges")
self.inputs.new('SvStringsSocket', "faces")
self.inputs["vertices"].label = "vertices"
self.inputs["faces"].label = "Faces"

socket = self.inputs.new('SvStringsSocket', "number_faces")
socket.use_prop=True
socket.default_property_type = 'int'
socket.default_int_property = 1000
socket.label = "Number of Faces"

socket = self.inputs.new('SvStringsSocket', "seed")
socket.use_prop=True
socket.default_property_type = 'int'
socket.default_int_property = 0
socket.label = "Seed"

self.outputs.new('SvVerticesSocket', "vertices")
self.outputs.new('SvStringsSocket', "faces")
self.outputs["vertices"].label = "vertices"
self.outputs["faces"].label = "Faces"

def draw_buttons(self, context, layout):
layout.prop(self, "flag_preserve_sharp")
layout.prop(self, "flag_preserve_boundary")
layout.prop(self, "flag_adaptive_scale")
layout.prop(self, "flag_aggresive_sat")
layout.prop(self, "flag_minimum_cost_flow")

col = layout.column()
col.row().label(text="Triangulate mesh polygons:")
row = col.row()
split = row.split(factor=0.4)
split.column().label(text="Quads mode:")
split.column().row(align=True).prop(self, "quad_mode", text='')

row = col.row()
split = row.split(factor=0.5)
split.column().label(text="Polygons mode:")
split.column().row(align=True).prop(self, "ngon_mode", text='')




def process(self):
if not enable_module:
raise Exception("The dependent library is not installed (pyQuadriFlow).")

outputs = self.outputs
if not any( [o.is_linked for o in outputs]):
return

verts_sets = self.inputs['vertices'].sv_get(default=[],deepcopy=False)
faces_sets = self.inputs['faces'].sv_get(default=[],deepcopy=False)
_number_faces_sets = self.inputs['number_faces'].sv_get(default=[[4000]],deepcopy=False)
number_faces_sets = flatten_data(_number_faces_sets)
_seed_sets = self.inputs['seed'].sv_get(default=[[0]],deepcopy=False)
seed_sets = flatten_data(_seed_sets)

new_meshes = {
'vertices':[],
'edges':[],
'faces':[]
}

if(verts_sets != [] and faces_sets != []):
for verts_set, faces_set, number_faces_set, seed_set in zip(*match_long_repeat([verts_sets,faces_sets, number_faces_sets, seed_sets])):
bm_I = bmesh_from_pydata(verts_set, [], faces_set, markup_face_data=True, normal_update=True)
b_faces = []
for face in bm_I.faces:
b_faces.append(face)
res = bmesh.ops.triangulate( bm_I, faces=b_faces, quad_method=self.quad_mode, ngon_method=self.ngon_mode )
new_vertices_I, new_edges_I, new_faces_I = pydata_from_bmesh(bm_I, ret_edges=False)
bm_I.free()

#new_mesh = {'vertices': new_vertices_I, 'faces': new_faces_I}

new_mesh = pyquadriflow(number_faces_set,
seed_set,
new_vertices_I,
new_faces_I,
self.flag_preserve_sharp,
self.flag_preserve_boundary,
self.flag_adaptive_scale,
self.flag_aggresive_sat,
self.flag_minimum_cost_flow
)

new_meshes['vertices'].append(new_mesh['vertices'])
#new_meshes['edges'].append(new_mesh['edges'])
new_meshes['faces'].append(new_mesh['faces'])

self.outputs['vertices'].sv_set(new_meshes['vertices'])
#self.outputs['Edges'].sv_set(new_meshes['edges'])
self.outputs['faces'].sv_set(new_meshes['faces'])

def register():
bpy.utils.register_class(SvQuadriFlowNode)

def unregister():
bpy.utils.unregister_class(SvQuadriFlowNode)
1 change: 1 addition & 0 deletions settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,7 @@ def draw_freecad_ops():
draw_message(box, "numexpr")
draw_message(box, "ezdxf")
draw_message(box, "pyacvd")
draw_message(box, "pyQuadriFlow")

draw_freecad_ops()

Expand Down