Skip to content

Commit

Permalink
Give FCStd_read a method to automatically remove redundant faces for …
Browse files Browse the repository at this point in the history
…basic and standard modes (#4525)

* add numpy version of non_redundant_faces_indices_np

* add trianglecheck+redundancy remover for basic and standard

* test

* remove debug code

* move method into else statement
  • Loading branch information
zeffii authored Jun 12, 2022
1 parent 9888971 commit 6af8ca3
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 12 deletions.
24 changes: 14 additions & 10 deletions nodes/exchange/FCStd_read.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,13 @@ def sv_init(self, context):
self.inputs.new('SvFilePathSocket', "File Path")
self.inputs.new('SvStringsSocket', "Part Filter")
self.outputs.new('SvSolidSocket', "Solid")
self.outputs.new('SvTextSocket', "Names")

def read_FCStd(self,node):
def ensure_name_socket_exists(self):
if not "Names" in self.outputs:
self.outputs.new('SvTextSocket', "Names")

def read_FCStd(self, node):

files = node.inputs['File Path'].sv_get()[0]

Expand All @@ -93,6 +98,7 @@ def read_FCStd(self,node):

solids = []
obj_mask = []
names = []

if node.read_features:
obj_mask.append('PartDesign')
Expand All @@ -104,10 +110,13 @@ def read_FCStd(self,node):
for f in files:
S = LoadSolid(f, part_filter, obj_mask, node.tool_parts, node.inv_filter)

for s in S:
for s, n in S:
solids.append(s)
names.append(list(n))

node.outputs['Solid'].sv_set(solids)
self.ensure_name_socket_exists()
node.outputs['Names'].sv_set(names)


def process(self):
Expand Down Expand Up @@ -151,7 +160,7 @@ def LabelReader(self,context):

for obj in doc.Objects:
if obj.Module in obj_mask or obj.TypeId in obj_mask:
labels.append( (obj.Label, obj.Label, obj.Label) ) # TODO, identifier [A-Za-z0-9_]
labels.append( (obj.Label, obj.Label, obj.Label) )

except Exception as err:
info(f'FCStd label read error: {Fname=}')
Expand Down Expand Up @@ -210,11 +219,11 @@ def LoadSolid(fc_file, part_filter, obj_mask, tool_parts, inv_filter):

if not inv_filter:
if obj.Label in part_filter or len(part_filter)==0:
solids.add(obj.Shape)
solids.add((obj.Shape, (obj.FullName, obj.Name, obj.Label)))

else:
if not obj.Label in part_filter:
solids.add(obj.Shape)
solids.add((obj.Shape, (obj.FullName, obj.Name, obj.Label)))

except:
info('FCStd read error')
Expand All @@ -223,11 +232,6 @@ def LoadSolid(fc_file, part_filter, obj_mask, tool_parts, inv_filter):

return solids

# unused?
def open_fc_file(fc_file):
F.open(fc_file)
Fname = doc.Name or bpy.path.display_name_from_filepath(fc_file)
F.setActiveDocument(Fname)

def register():
if FreeCAD is not None:
Expand Down
17 changes: 15 additions & 2 deletions nodes/solid/solid_to_mesh_mk2.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from sverchok.dependencies import FreeCAD
from sverchok.utils.dummy_nodes import add_dummy



if FreeCAD is None:
add_dummy('SvSolidToMeshNode', 'Solid to Mesh', 'FreeCAD')
else:
Expand All @@ -11,12 +13,15 @@
from bpy.props import FloatProperty, EnumProperty, BoolProperty, IntProperty

from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode, match_long_repeat as mlr
from sverchok.data_structure import updateNode, has_element, match_long_repeat as mlr
from sverchok.utils.solid import mesh_from_solid_faces
from sverchok.utils.sv_bmesh_utils import recalc_normals
from sverchok.utils.sv_mesh_utils import non_redundant_faces_indices_np as clean

import MeshPart

def is_triangles_only(faces):
if has_element(faces): return all((len(f) == 3 for f in faces))

class SvSolidToMeshNodeMk2(bpy.types.Node, SverchCustomTreeNode):
"""
Expand Down Expand Up @@ -155,6 +160,8 @@ def basic_mesher(self):
for f in rawdata[1]:
b_faces.append(f)
verts.append(b_verts)

b_faces = clean(b_faces).tolist() if is_triangles_only(b_faces) else b_faces
faces.append(b_faces)

return verts, faces
Expand All @@ -178,7 +185,10 @@ def standard_mesher(self):
Relative=self.relative_surface_deviation)

verts.append([v[:] for v in mesh.Topology[0]])
faces.append(mesh.Topology[1])

b_faces = mesh.Topology[1]
b_faces = clean(b_faces).tolist() if is_triangles_only(b_faces) else b_faces
faces.append(b_faces)

return verts, faces

Expand All @@ -204,6 +214,9 @@ def mefisto_mesher(self):
return verts, faces

def trivial_mesher(self):
"""
this mode will produce a variety of polygon types (tris, quads, ngons...)
"""
solids = self.inputs[self["shape_type"]].sv_get()

verts = []
Expand Down
11 changes: 11 additions & 0 deletions utils/sv_mesh_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,17 @@ def clean_meshes(vertices, edges, faces,

return verts_out, edges_out, faces_out, verts_removed_out, edges_removed_out, faces_removed_out


def non_redundant_faces_indices_np(faces):
F = np.array(faces)
M = np.sort(F, axis=-1, order=None)

# from https://stackoverflow.com/a/16973510/1243487
K = np.ascontiguousarray(M).view(np.dtype((np.void, M.dtype.itemsize * M.shape[1])))
_, idx = np.unique(K, return_index=True)
return F[idx]


def point_inside_mesh(bvh, point):
point = Vector(point)
axis = Vector((1, 0, 0))
Expand Down

0 comments on commit 6af8ca3

Please sign in to comment.