Skip to content

Commit

Permalink
- fix #3288
Browse files Browse the repository at this point in the history
- Create library function separate_loose_mesh.py
  • Loading branch information
satabol committed Sep 21, 2023
1 parent 4c4bbca commit bc644d8
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 42 deletions.
26 changes: 26 additions & 0 deletions nodes/modifier_change/extrude_region.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
from sverchok.data_structure import updateNode, match_long_repeat, repeat_last_for_length
from sverchok.utils.sv_bmesh_utils import bmesh_from_pydata, pydata_from_bmesh
from sverchok.utils.nodes_mixins.sockets_config import ModifierNode
from sverchok.utils.mesh.separate_loose_mesh import separate_loose_mesh
import numpy as np

is_290 = bpy.app.version >= (2, 90, 0)

Expand Down Expand Up @@ -217,6 +219,16 @@ def process(self):
if face_data:
face_data_matched = repeat_last_for_length(face_data, len(faces))

need_fake_face = True
loops = [[faces]]
if need_fake_face:
_, _, loops = separate_loose_mesh(vertices, faces)

for loop in loops:
vertices.append( vertices[loop[0][0]] )
faces.append( [loop[0][0], loop[0][1], len(vertices)-1] ) # face area is zero but this is not important. It will not extrude.
mask_matched.append(False)

bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True, markup_face_data=True)
mask_layer = bm.faces.layers.int.new('mask')
bm.faces.ensure_lookup_table()
Expand Down Expand Up @@ -295,6 +307,20 @@ def process(self):

extrude_geom = new_geom

if need_fake_face:
for loop in loops:
bm.verts.ensure_lookup_table()
bm.verts.remove(bm.verts[len(vertices)-1])
vertices.pop()
faces.pop()
mask_matched.pop()

bm.verts.index_update()
bm.edges.index_update()
bm.faces.index_update()
bm.verts.ensure_lookup_table()
bm.faces.ensure_lookup_table()

if face_data:
new_vertices, new_edges, new_faces, new_face_data = pydata_from_bmesh(bm, face_data_matched)
else:
Expand Down
90 changes: 48 additions & 42 deletions nodes/modifier_change/mesh_separate.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import zip_long_repeat
from sverchok.utils.nodes_mixins.sockets_config import ModifierLiteNode
from sverchok.utils.mesh.separate_loose_mesh import separate_loose_mesh


class SvSeparateMeshNode(ModifierLiteNode, SverchCustomTreeNode, bpy.types.Node):
Expand All @@ -47,49 +48,54 @@ def process(self):
verts_out = []
poly_edge_out = []
for ve, pe in zip_long_repeat(verts, poly):
# build links
node_links = {}
for edge_face in pe:
for i in edge_face:
if i not in node_links:
node_links[i] = set()
node_links[i].update(edge_face)
# # build links
# node_links = {}
# for edge_face in pe:
# for i in edge_face:
# if i not in node_links:
# node_links[i] = set()
# node_links[i].update(edge_face)

nodes = set(node_links.keys())
n = nodes.pop()
node_set_list = [set([n])]
node_stack = collections.deque()
node_stack_append = node_stack.append
node_stack_pop = node_stack.pop
node_set = node_set_list[-1]
# find separate sets
while nodes:
for node in node_links[n]:
if node not in node_set:
node_stack_append(node)
if not node_stack: # new mesh part
n = nodes.pop()
node_set_list.append(set([n]))
node_set = node_set_list[-1]
else:
while node_stack and n in node_set:
n = node_stack_pop()
nodes.discard(n)
node_set.add(n)
# create new meshes from sets, new_pe is the slow line.
if len(node_set_list) > 1:
for node_set in node_set_list:
mesh_index = sorted(node_set)
vert_dict = {j: i for i, j in enumerate(mesh_index)}
new_vert = [ve[i] for i in mesh_index]
new_pe = [[vert_dict[n] for n in fe]
for fe in pe
if fe[0] in node_set]
verts_out.append(new_vert)
poly_edge_out.append(new_pe)
elif node_set_list: # no reprocessing needed
verts_out.append(ve)
poly_edge_out.append(pe)
# nodes = set(node_links.keys())
# n = nodes.pop()
# node_set_list = [set([n])]
# node_stack = collections.deque()
# node_stack_append = node_stack.append
# node_stack_pop = node_stack.pop
# node_set = node_set_list[-1]
# # find separate sets
# while nodes:
# for node in node_links[n]:
# if node not in node_set:
# node_stack_append(node)
# if not node_stack: # new mesh part
# n = nodes.pop()
# node_set_list.append(set([n]))
# node_set = node_set_list[-1]
# else:
# while node_stack and n in node_set:
# n = node_stack_pop()
# nodes.discard(n)
# node_set.add(n)
# # create new meshes from sets, new_pe is the slow line.
# if len(node_set_list) > 1:
# for node_set in node_set_list:
# mesh_index = sorted(node_set)
# vert_dict = {j: i for i, j in enumerate(mesh_index)}
# new_vert = [ve[i] for i in mesh_index]
# new_pe = [[vert_dict[n] for n in fe]
# for fe in pe
# if fe[0] in node_set]
# verts_out.append(new_vert)
# poly_edge_out.append(new_pe)
# elif node_set_list: # no reprocessing needed
# verts_out.append(ve)
# poly_edge_out.append(pe)

vo, po, _ = separate_loose_mesh(ve, pe)
verts_out.extend(vo)
poly_edge_out.extend(po)


self.outputs['Vertices'].sv_set(verts_out)
self.outputs['Poly Egde'].sv_set(poly_edge_out)
Expand Down
81 changes: 81 additions & 0 deletions utils/mesh/separate_loose_mesh.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# ##### 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 collections

import bpy

from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import zip_long_repeat
from sverchok.utils.nodes_mixins.sockets_config import ModifierLiteNode

def separate_loose_mesh(verts_in, poly_edge_in):
verts_out = []
poly_edge_out = []
poly_edge_old_indexes_out = [] # faces with old indices

# build links
node_links = {}
for edge_face in poly_edge_in:
for i in edge_face:
if i not in node_links:
node_links[i] = set()
node_links[i].update(edge_face)

nodes = set(node_links.keys())
n = nodes.pop()
node_set_list = [set([n])]
node_stack = collections.deque()
node_stack_append = node_stack.append
node_stack_pop = node_stack.pop
node_set = node_set_list[-1]
# find separate sets
while nodes:
for node in node_links[n]:
if node not in node_set:
node_stack_append(node)
if not node_stack: # new mesh part
n = nodes.pop()
node_set_list.append(set([n]))
node_set = node_set_list[-1]
else:
while node_stack and n in node_set:
n = node_stack_pop()
nodes.discard(n)
node_set.add(n)
# create new meshes from sets, new_pe is the slow line.
if len(node_set_list) > 1:
for node_set in node_set_list:
mesh_index = sorted(node_set)
vert_dict = {j: i for i, j in enumerate(mesh_index)}
new_vert = [verts_in[i] for i in mesh_index]
new_pe = [[vert_dict[n] for n in fe]
for fe in poly_edge_in
if fe[0] in node_set]
old_pe = [fe for fe in poly_edge_in
if fe[0] in node_set]
verts_out.append(new_vert)
poly_edge_out.append(new_pe)
poly_edge_old_indexes_out.append(old_pe)
elif node_set_list: # no reprocessing needed
verts_out.append(verts_in)
poly_edge_out.append(poly_edge_in)
poly_edge_old_indexes_out.append(poly_edge_in)

return verts_out, poly_edge_out, poly_edge_old_indexes_out

0 comments on commit bc644d8

Please sign in to comment.