Skip to content

Commit

Permalink
Merge pull request #4999 from nortikin/fix_3288_Extrude_region_node_k…
Browse files Browse the repository at this point in the history
…eep_original

fix #3288 "Extrude region node - keep original"
  • Loading branch information
satabol authored Sep 25, 2023
2 parents 7b719b5 + 047b12a commit d0d5217
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 43 deletions.
28 changes: 28 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,17 @@ def process(self):
if face_data:
face_data_matched = repeat_last_for_length(face_data, len(faces))

# see: https://github.com/nortikin/sverchok/pull/4999#issuecomment-1734256435
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 +308,21 @@ def process(self):

extrude_geom = new_geom

# see: https://github.com/nortikin/sverchok/pull/4999#issuecomment-1734256435
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
48 changes: 5 additions & 43 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,10 @@ 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)

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
90 changes: 90 additions & 0 deletions utils/mesh/separate_loose_mesh.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# ##### 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):
''' separate a mesh by loose parts.
input:
1. list of verts
2. list of edges/polygons
output: list of
1. separated list of verts
2. separated list of edges/polygons with new indices of separated elements
3. separated list of edges/polygons (like 2) with old indices
'''
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 d0d5217

Please sign in to comment.