Открыть боковую панель
nikitronn
sverchok
Коммиты
ab7c67db
Не подтверждена
Коммит
ab7c67db
создал
Окт 26, 2019
по автору
Victor Doval
Зафиксировано автором
GitHub
Окт 26, 2019
Просмотр файлов
Select similar sv_b28 (#2643)
* faces mode updated * all modes updated * refactor and cleaning
владелец
6b3a3898
Изменения
5
Скрыть пробелы
Построчно
Рядом
nodes/analyzer/select_similar.py
Просмотр файла @
ab7c67db
...
...
@@ -18,11 +18,40 @@
import
bpy
from
bpy.props
import
IntProperty
,
FloatProperty
,
BoolProperty
,
EnumProperty
import
bmesh.ops
from
mathutils
import
Vector
from
sverchok.node_tree
import
SverchCustomTreeNode
from
sverchok.data_structure
import
updateNode
,
match_long_repeat
,
fullList
from
sverchok.utils.sv_bmesh_utils
import
bmesh_from_pydata
,
pydata_from_bmesh
from
sverchok.utils.modules.polygon_utils
import
areas_from_polygons
,
perimeters_from_polygons
from
sverchok.utils.modules.edge_utils
import
edges_length
,
edges_direction
,
adjacent_faces
,
faces_angle
from
sverchok.utils.modules.vertex_utils
import
adjacent_edg_pol
def
equals
(
val
,
orig_val
,
threshold
):
return
orig_val
-
threshold
<=
val
<=
orig_val
+
threshold
def
less_or_equal
(
val
,
orig_val
,
threshold
):
return
val
<=
orig_val
+
threshold
def
more_or_equal
(
val
,
orig_val
,
threshold
):
return
orig_val
-
threshold
<=
val
def
equal_vectors
(
val
,
orig_val
,
threshold
):
are_equal
=
True
for
v
,
ov
in
zip
(
val
,
orig_val
):
are_equal
=
are_equal
and
(
ov
-
threshold
<=
v
<=
ov
+
threshold
)
return
are_equal
def
coplanar_pols
(
val
,
orig_val
,
threshold
):
equal_normals
=
equal_vectors
(
val
[
0
],
orig_val
[
0
],
threshold
)
if
equal_normals
:
vector_base
=
Vector
(
val
[
1
])
-
Vector
(
orig_val
[
1
])
distance
=
vector_base
.
dot
(
Vector
(
val
[
0
]))
return
abs
(
distance
)
<
threshold
else
:
return
False
class
SvSelectSimilarNode
(
bpy
.
types
.
Node
,
SverchCustomTreeNode
):
"""
...
...
@@ -76,36 +105,40 @@ class SvSelectSimilarNode(bpy.types.Node, SverchCustomTreeNode):
]
def
update_mode
(
self
,
context
):
self
.
outputs
[
'Vertices'
].
hide_safe
=
(
self
.
mode
!=
"verts"
)
self
.
outputs
[
'Edges'
].
hide_safe
=
(
self
.
mode
!=
"edges"
)
self
.
outputs
[
'Faces'
].
hide_safe
=
(
self
.
mode
!=
"faces"
)
for
mode
in
self
.
modes
:
if
self
.
mode
!=
mode
[
0
]:
if
not
self
.
outputs
[
mode
[
1
]].
hide_safe
:
self
.
outputs
[
mode
[
1
]].
hide_safe
=
True
else
:
if
self
.
outputs
[
mode
[
1
]].
hide_safe
:
self
.
outputs
[
mode
[
1
]].
hide_safe
=
False
updateNode
(
self
,
context
)
mode
:
EnumProperty
(
name
=
"Select"
,
items
=
modes
,
default
=
"faces"
,
update
=
update_mode
)
vertex_mode
:
EnumProperty
(
name
=
"Select by"
,
items
=
vertex_modes
,
default
=
"0"
,
update
=
update_mode
)
edge_mode
:
EnumProperty
(
name
=
"Select by"
,
items
=
edge_modes
,
default
=
"101"
,
update
=
update_mode
)
face_mode
:
EnumProperty
(
name
=
"Select by"
,
items
=
face_modes
,
default
=
"203"
,
update
=
update_mode
)
compare
:
EnumProperty
(
name
=
"Compare by"
,
items
=
cmp_modes
,
default
=
"0"
,
update
=
update_mode
)
threshold
:
FloatProperty
(
name
=
"Threshold"
,
mode
:
EnumProperty
(
name
=
"Select"
,
items
=
modes
,
default
=
"faces"
,
update
=
update_mode
)
vertex_mode
:
EnumProperty
(
name
=
"Select by"
,
items
=
vertex_modes
,
default
=
"0"
,
update
=
update_mode
)
edge_mode
:
EnumProperty
(
name
=
"Select by"
,
items
=
edge_modes
,
default
=
"101"
,
update
=
update_mode
)
face_mode
:
EnumProperty
(
name
=
"Select by"
,
items
=
face_modes
,
default
=
"203"
,
update
=
update_mode
)
compare
:
EnumProperty
(
name
=
"Compare by"
,
items
=
cmp_modes
,
default
=
"0"
,
update
=
update_mode
)
threshold
:
FloatProperty
(
name
=
"Threshold"
,
min
=
0.0
,
default
=
0.1
,
update
=
updateNode
)
...
...
@@ -137,11 +170,55 @@ class SvSelectSimilarNode(bpy.types.Node, SverchCustomTreeNode):
self
.
update_mode
(
context
)
def
get_mask
(
self
,
new_geom
,
old_geom
):
mask
=
[]
for
item
in
old_geom
:
mask
.
append
(
item
in
new_geom
)
return
mask
def
set_up_verts
(
self
,
vertices
,
edges
,
faces
,
compare_func
):
if
int
(
self
.
vertex_mode
)
==
0
:
bm
=
bmesh_from_pydata
(
vertices
,
edges
,
faces
,
normal_update
=
True
)
vals
=
[
tuple
(
v
.
normal
)
for
v
in
bm
.
verts
]
bm
.
free
()
compare_func
=
equal_vectors
elif
int
(
self
.
vertex_mode
)
==
1
:
vals
=
adjacent_edg_pol
(
vertices
,
faces
)
elif
int
(
self
.
vertex_mode
)
==
3
:
vals
=
adjacent_edg_pol
(
vertices
,
edges
)
return
vals
,
compare_func
def
set_up_edges
(
self
,
vertices
,
edges
,
faces
,
compare_func
):
if
int
(
self
.
edge_mode
)
==
101
:
vals
=
edges_length
(
vertices
,
edges
,
sum_length
=
False
,
out_numpy
=
False
)
elif
int
(
self
.
edge_mode
)
==
102
:
vals
=
edges_direction
(
vertices
,
edges
,
out_numpy
=
False
)
compare_func
=
equal_vectors
elif
int
(
self
.
edge_mode
)
==
103
:
vals
=
adjacent_faces
(
edges
,
faces
)
elif
int
(
self
.
edge_mode
)
==
104
:
bm
=
bmesh_from_pydata
(
vertices
,
edges
,
faces
,
normal_update
=
True
)
normals
=
[
tuple
(
face
.
normal
)
for
face
in
bm
.
faces
]
bm
.
free
()
vals
=
faces_angle
(
normals
,
edges
,
faces
)
return
vals
,
compare_func
def
set_up_pols
(
self
,
vertices
,
edges
,
faces
,
compare_func
):
if
int
(
self
.
face_mode
)
==
203
:
vals
=
areas_from_polygons
(
vertices
,
faces
,
sum_faces
=
False
)
elif
int
(
self
.
face_mode
)
==
204
:
vals
=
[
len
(
p
)
for
p
in
faces
]
elif
int
(
self
.
face_mode
)
==
205
:
vals
=
perimeters_from_polygons
(
vertices
,
faces
)
elif
int
(
self
.
face_mode
)
==
206
:
bm
=
bmesh_from_pydata
(
vertices
,
edges
,
faces
,
normal_update
=
True
)
vals
=
[
tuple
(
face
.
normal
)
for
face
in
bm
.
faces
]
bm
.
free
()
compare_func
=
equal_vectors
elif
int
(
self
.
face_mode
)
==
207
:
bm
=
bmesh_from_pydata
(
vertices
,
edges
,
faces
,
normal_update
=
True
)
vals
=
[[
tuple
(
bm_face
.
normal
),
vertices
[
face
[
0
]]]
for
bm_face
,
face
in
zip
(
bm
.
faces
,
faces
)]
bm
.
free
()
compare_func
=
coplanar_pols
return
vals
,
compare_func
def
process
(
self
):
if
not
any
(
output
.
is_linked
for
output
in
self
.
outputs
):
...
...
@@ -159,83 +236,62 @@ class SvSelectSimilarNode(bpy.types.Node, SverchCustomTreeNode):
result_mask
=
[]
meshes
=
match_long_repeat
([
vertices_s
,
edges_s
,
faces_s
,
masks_s
,
thresholds
])
compare_funcs
=
[
equals
,
more_or_equal
,
less_or_equal
]
compare_func
=
compare_funcs
[
int
(
self
.
compare
)]
info_funcs
=
{
'verts'
:
self
.
set_up_verts
,
'edges'
:
self
.
set_up_edges
,
'faces'
:
self
.
set_up_pols
}
info_func
=
info_funcs
[
self
.
mode
]
for
vertices
,
edges
,
faces
,
masks
,
threshold
in
zip
(
*
meshes
):
if
self
.
mode
==
"verts"
:
fullList
(
masks
,
len
(
vertices
))
fullList
(
thresholds
,
len
(
vertices
))
elif
self
.
mode
==
"edges"
:
fullList
(
masks
,
len
(
edges
))
fullList
(
thresholds
,
len
(
edges
))
elif
self
.
mode
==
"faces"
:
fullList
(
masks
,
len
(
faces
))
fullList
(
thresholds
,
len
(
faces
))
selected_faces
=
[]
selected_vertices
=
[]
selected_edges
=
[]
out_mask
=
[]
selected_vals
=
[]
if
self
.
mode
==
'verts'
:
components
=
vertices
selected_components
=
selected_vertices
elif
self
.
mode
==
'edges'
:
components
=
edges
selected_components
=
selected_edges
elif
self
.
mode
==
'faces'
:
components
=
faces
selected_components
=
selected_faces
vals
,
compare_func
=
info_func
(
vertices
,
edges
,
faces
,
compare_func
)
fullList
(
masks
,
len
(
components
))
fullList
(
thresholds
,
len
(
components
))
selected_vals
=
[
val
for
mask
,
val
in
zip
(
masks
,
vals
)
if
mask
]
for
mask
,
component
,
val
in
zip
(
masks
,
components
,
vals
):
if
mask
:
selected_components
.
append
(
component
)
out_mask
.
append
(
True
)
else
:
select
=
False
for
val_s
in
selected_vals
:
if
compare_func
(
val
,
val_s
,
threshold
):
selected_components
.
append
(
component
)
out_mask
.
append
(
True
)
select
=
True
break
if
not
select
:
out_mask
.
append
(
False
)
bm
=
bmesh_from_pydata
(
vertices
,
edges
,
faces
,
normal_update
=
True
)
if
self
.
mode
==
"verts"
:
selected_verts
=
[
v
for
v
,
m
in
zip
(
bm
.
verts
,
masks
)
if
m
]
geom
=
bmesh
.
ops
.
similar_verts
(
bm
,
verts
=
selected_verts
,
type
=
int
(
self
.
vertex_mode
),
thresh
=
threshold
,
compare
=
int
(
self
.
compare
))
s_verts
=
[
list
(
v
.
co
[:])
for
v
in
geom
[
'verts'
]]
v_mask
=
self
.
get_mask
(
geom
[
'verts'
],
bm
.
verts
)
result_verts
.
append
(
s_verts
)
result_mask
.
append
(
v_mask
)
elif
self
.
mode
==
"edges"
:
selected_edges
=
[]
for
m
,
edge
in
zip
(
masks
,
edges
):
if
not
m
:
continue
found
=
False
for
bmesh_edge
in
bm
.
edges
:
if
set
(
v
.
index
for
v
in
bmesh_edge
.
verts
)
==
set
(
edge
):
found
=
True
break
if
found
:
selected_edges
.
append
(
bmesh_edge
)
else
:
print
(
"Cant find edge: "
+
str
(
edge
))
geom
=
bmesh
.
ops
.
similar_edges
(
bm
,
edges
=
selected_edges
,
type
=
int
(
self
.
edge_mode
),
thresh
=
threshold
,
compare
=
int
(
self
.
compare
))
s_edges
=
[[
v
.
index
for
v
in
e
.
verts
]
for
e
in
geom
[
'edges'
]]
e_mask
=
self
.
get_mask
(
geom
[
'edges'
],
bm
.
edges
)
result_edges
.
append
(
s_edges
)
result_mask
.
append
(
e_mask
)
elif
self
.
mode
==
"faces"
:
selected_faces
=
[]
for
m
,
face
in
zip
(
masks
,
faces
):
if
not
m
:
continue
found
=
False
for
bmesh_face
in
bm
.
faces
:
if
set
(
v
.
index
for
v
in
bmesh_face
.
verts
)
==
set
(
face
):
#print("Found: " + str(face))
found
=
True
break
if
found
:
selected_faces
.
append
(
bmesh_face
)
else
:
print
(
"Cant find face: "
+
str
(
face
))
geom
=
bmesh
.
ops
.
similar_faces
(
bm
,
faces
=
selected_faces
,
type
=
int
(
self
.
face_mode
),
thresh
=
threshold
,
compare
=
int
(
self
.
compare
))
s_faces
=
[[
v
.
index
for
v
in
f
.
verts
]
for
f
in
geom
[
'faces'
]]
f_mask
=
self
.
get_mask
(
geom
[
'faces'
],
bm
.
faces
)
result_faces
.
append
(
s_faces
)
result_mask
.
append
(
f_mask
)
result_verts
.
append
(
selected_vertices
)
result_edges
.
append
(
selected_edges
)
result_faces
.
append
(
selected_faces
)
result_mask
.
append
(
out_mask
)
else
:
raise
NotImplementedError
(
"Unsupported mode: "
+
self
.
mode
)
bm
.
free
()
self
.
outputs
[
'Mask'
].
sv_set
(
result_mask
)
self
.
outputs
[
'Vertices'
].
sv_set
(
result_verts
)
...
...
ui/icons/sv_select_similar.png
Просмотр заменённого файла @
6b3a3898
Просмотр файла @
ab7c67db
334 Б
|
W:
|
H:
196 Б
|
W:
|
H:
2-up
Swipe
Onion skin
utils/modules/edge_utils.py
0 → 100644
Просмотр файла @
ab7c67db
# 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
mathutils
import
Vector
from
math
import
acos
,
pi
import
numpy
as
np
from
numpy.linalg
import
norm
as
np_norm
def
edges_aux
(
vertices
):
'''create auxiliary edges array '''
v_len
=
[
len
(
v
)
for
v
in
vertices
]
v_len_max
=
max
(
v_len
)
np_in
=
np
.
arange
(
v_len_max
-
1
)
np_edges
=
np
.
array
([
np_in
,
np_in
+
1
]).
T
return
[
np_edges
]
def
edges_length
(
vertices
,
edges
,
sum_length
=
False
,
out_numpy
=
False
):
'''calculate edges length '''
np_verts
=
np
.
array
(
vertices
)
if
type
(
edges
[
0
])
in
(
list
,
tuple
):
np_edges
=
np
.
array
(
edges
)
else
:
np_edges
=
edges
[:
len
(
vertices
)
-
1
,
:]
vect
=
np_verts
[
np_edges
[:,
0
],
:]
-
np_verts
[
np_edges
[:,
1
],
:]
length
=
np
.
linalg
.
norm
(
vect
,
axis
=
1
)
if
sum_length
:
length
=
np
.
sum
(
length
)[
np
.
newaxis
]
return
length
if
out_numpy
else
length
.
tolist
()
def
edges_direction
(
vertices
,
edges
,
out_numpy
=
False
):
'''calculate edges direction '''
np_verts
=
np
.
array
(
vertices
)
if
type
(
edges
[
0
])
in
(
list
,
tuple
):
np_edges
=
np
.
array
(
edges
)
else
:
np_edges
=
edges
[:
len
(
vertices
)
-
1
,
:]
vect
=
np_verts
[
np_edges
[:,
1
],
:]
-
np_verts
[
np_edges
[:,
0
],
:]
dist
=
np_norm
(
vect
,
axis
=
1
)
vect_norm
=
vect
/
dist
[:,
np
.
newaxis
]
return
vect_norm
if
out_numpy
else
vect_norm
.
tolist
()
def
adjacent_faces
(
edges
,
pols
):
'''calculate number of adjacent faces '''
e_sorted
=
[
sorted
(
e
)
for
e
in
edges
]
ad_faces
=
[
0
for
e
in
edges
]
for
pol
in
pols
:
for
edge
in
zip
(
pol
,
pol
[
1
:]
+
[
pol
[
0
]]):
e_s
=
sorted
(
edge
)
if
e_s
in
e_sorted
:
idx
=
e_sorted
.
index
(
e_s
)
ad_faces
[
idx
]
+=
1
return
ad_faces
def
faces_angle
(
normals
,
edges
,
pols
):
ad_faces
=
adjacent_faces
(
edges
,
pols
)
e_sorted
=
[
sorted
(
e
)
for
e
in
edges
]
ad_faces
=
[[]
for
e
in
edges
]
for
idp
,
pol
in
enumerate
(
pols
):
for
edge
in
zip
(
pol
,
pol
[
1
:]
+
[
pol
[
0
]]):
e_s
=
sorted
(
edge
)
if
e_s
in
e_sorted
:
idx
=
e_sorted
.
index
(
e_s
)
ad_faces
[
idx
].
append
(
idp
)
angles
=
[]
for
edg
in
ad_faces
:
if
len
(
edg
)
>
1
:
dot_p
=
Vector
(
normals
[
edg
[
0
]]).
dot
(
Vector
(
normals
[
edg
[
1
]]))
ang
=
acos
(
dot_p
)
else
:
ang
=
2
*
pi
angles
.
append
(
ang
)
return
angles
utils/modules/polygon_utils.py
Просмотр файла @
ab7c67db
# 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
...
...
@@ -36,4 +36,20 @@ def areas_from_polygons(verts, polygons, sum_faces=False):
if
sum_faces
:
areas
=
[
sum
(
areas
)]
return
areas
\ Нет новой строки в конце файла
return
areas
def
perimeters_from_polygons
(
verts
,
polygons
):
perimeters
=
[]
concat_perimeters
=
perimeters
.
append
for
polygon
in
polygons
:
perimeter
=
0
for
v_id
,
v_id2
in
zip
(
polygon
,
polygon
[
1
:]
+
[
polygon
[
0
]]):
perimeter
+=
(
Vector
(
verts
[
v_id
])
-
Vector
(
verts
[
v_id2
])).
magnitude
concat_perimeters
(
perimeter
)
return
perimeters
utils/modules/vertex_utils.py
0 → 100644
Просмотр файла @
ab7c67db
# 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
def
adjacent_edg_pol
(
verts
,
edg_pol
):
'''calculate number of adjacent faces '''
adj_edg_pol
=
[
0
for
v
in
verts
]
for
ep
in
edg_pol
:
for
v
in
ep
:
adj_edg_pol
[
v
]
+=
1
return
adj_edg_pol
Редактирование
Предварительный просмотр
Поддерживает Markdown
0%
Попробовать снова
или
прикрепить новый файл
.
Отмена
You are about to add
0
people
to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Отмена
Пожалуйста,
зарегистрируйтесь
или
войдите
чтобы прокомментировать