Открыть боковую панель
nikitronn
sverchok
Коммиты
98b16325
Коммит
98b16325
создал
Дек 13, 2018
по автору
Victor Doval
Просмотр файлов
added Tension Node
владелец
987fc402
Изменения
2
Скрыть пробелы
Построчно
Рядом
index.md
Просмотр файла @
98b16325
...
...
@@ -65,6 +65,7 @@
SvRaycasterLiteNode
SvOBJInsolationNode
EvaluateImageNode
SvTensionNode
## Transforms
SvRotationNode
...
...
nodes/analyzer/tension.py
0 → 100644
Просмотр файла @
98b16325
# ##### 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
bpy
from
bpy.props
import
BoolProperty
from
sverchok.node_tree
import
SverchCustomTreeNode
from
sverchok.data_structure
import
updateNode
,
match_long_repeat
,
match_long_cycle
import
numpy
as
np
def
edge_elongation
(
np_verts
,
np_verts_n
,
np_edges
):
'''Calculate edge length variation'''
pairs_edges
=
np_verts
[
np_edges
,
:]
vect_rest
=
(
pairs_edges
[:,
0
,
:]
-
pairs_edges
[:,
1
,
:])
dist_rest
=
np
.
linalg
.
norm
(
vect_rest
,
axis
=
1
)
pairs
=
np_verts_n
[
np_edges
,
:]
dif_v
=
pairs
[:,
0
,
:]
-
pairs
[:,
1
,
:]
dist
=
np
.
linalg
.
norm
(
dif_v
,
axis
=
1
)
dif_l
=
dist
-
dist_rest
return
dif_l
def
vert_edge_tension
(
dif_l
,
np_verts
,
np_edges
):
'''Redistribute edge length variation to verts'''
x
=
dif_l
[:,
np
.
newaxis
]
/
2
v_len
=
len
(
np_verts
)
tension
=
np
.
zeros
((
v_len
,
v_len
,
1
),
dtype
=
np
.
float32
)
tension
[
np_edges
[:,
0
],
np_edges
[:,
1
],
:]
=
x
tension
[
np_edges
[:,
1
],
np_edges
[:,
0
],
:]
=
x
tension
=
np
.
sum
(
tension
,
axis
=
1
)[:,
0
]
return
tension
def
area_calc_setup
(
pols
):
'''Analyze pols information'''
np_pols
=
np
.
array
(
pols
)
p_len
=
len
(
pols
)
if
np_pols
.
dtype
==
np
.
object
:
np_len
=
np
.
vectorize
(
len
)
pols_sides
=
np_len
(
np_pols
)
pols_sides_max
=
np
.
amax
(
pols_sides
)
pols
=
match_long_cycle
(
pols
)
np_pols
=
np
.
array
(
pols
)
p_non_regular
=
True
else
:
p_non_regular
=
False
pols_sides
=
np
.
array
(
p_len
)
pols_sides_max
=
len
(
pols
[
0
])
return
[
np_pols
,
pols_sides_max
,
pols_sides
,
p_len
,
p_non_regular
]
def
get_normals
(
v_pols
):
'''calculate polygon normals'''
v1
=
v_pols
[:,
1
,
:]
-
v_pols
[:,
0
,
:]
v2
=
v_pols
[:,
2
,
:]
-
v_pols
[:,
0
,
:]
pols_normal
=
np
.
cross
(
v1
,
v2
)
pols_normal_d
=
np
.
linalg
.
norm
(
pols_normal
,
axis
=
1
)
return
pols_normal
/
pols_normal_d
[:,
np
.
newaxis
]
def
area_calc
(
np_verts
,
area_params
):
'''Calculate polygons area'''
np_pols
,
pols_sides_max
,
pols_sides
,
p_len
,
p_non_regular
=
area_params
v_pols
=
np_verts
[
np_pols
,
:]
pols_normal
=
get_normals
(
v_pols
)
prod
=
np
.
zeros
((
pols_sides_max
,
p_len
,
3
),
dtype
=
np
.
float32
)
if
p_non_regular
:
for
i
in
range
(
pols_sides_max
):
mask
=
pols_sides
>
i
end_i
=
(
i
+
1
)
%
pols_sides_max
prod
[
i
,
mask
,
:]
=
np
.
cross
(
v_pols
[
mask
,
i
,
:],
v_pols
[
mask
,
end_i
,
:])
prod
=
np
.
sum
(
prod
,
axis
=
0
)
area
=
abs
(
np
.
sum
(
prod
*
pols_normal
,
axis
=
1
)
/
2
)
else
:
for
i
in
range
(
pols_sides_max
):
end_i
=
(
i
+
1
)
%
pols_sides_max
prod
[
i
,
:,
:]
=
np
.
cross
(
v_pols
[:,
i
,
:],
v_pols
[:,
end_i
,
:])
prod
=
np
.
sum
(
prod
,
axis
=
0
)
area
=
abs
(
np
.
sum
(
prod
*
pols_normal
,
axis
=
1
)
/
2
)
return
area
def
area_to_verts
(
np_verts
,
area_params
,
pols_tension
):
'''Redistribute area variation to verts'''
np_pols
,
pols_sides_max
,
pols_sides
,
p_len
,
advance
=
area_params
pol_id
=
np
.
arange
(
p_len
)
pol_tens_to_vert
=
pols_tension
/
pols_sides
tension
=
np
.
zeros
((
len
(
np_verts
),
p_len
),
dtype
=
np
.
float32
)
if
advance
:
for
i
in
range
(
pols_sides_max
):
mask
=
pols_sides
>
i
tension
[
np_pols
[
mask
,
i
],
pol_id
[
mask
]]
+=
pol_tens_to_vert
[
mask
]
else
:
for
i
in
range
(
pols_sides_max
):
tension
[
np_pols
[:,
i
],
pol_id
]
+=
pols_tension
return
np
.
sum
(
tension
,
axis
=
1
)
def
calc_pols_tension
(
np_verts
,
np_verts_n
,
area_params
):
relax_area
=
area_calc
(
np_verts
,
area_params
)
tension_area
=
area_calc
(
np_verts_n
,
area_params
)
return
tension_area
-
relax_area
def
calc_tensions
(
meshes
,
gates
,
result
):
for
vertices
,
vertices_n
,
edges
,
pols
in
zip
(
*
meshes
):
np_verts
=
np
.
array
(
vertices
)
np_verts_n
=
np
.
array
(
vertices_n
)
if
len
(
edges
)
>
0
and
(
gates
[
0
]
or
gates
[
1
]):
np_edges
=
np
.
array
(
edges
)
dif_l
=
edge_elongation
(
np_verts
,
np_verts_n
,
np_edges
)
result
[
0
].
append
(
dif_l
if
gates
[
4
]
else
dif_l
.
tolist
())
if
gates
[
1
]:
tension
=
vert_edge_tension
(
dif_l
,
np_verts
,
np_edges
)
result
[
1
].
append
(
tension
if
gates
[
4
]
else
tension
.
tolist
())
if
len
(
pols
)
>
0
and
(
gates
[
2
]
or
gates
[
3
]):
area_params
=
area_calc_setup
(
pols
)
pols_tension
=
calc_pols_tension
(
np_verts
,
np_verts_n
,
area_params
)
result
[
2
].
append
(
pols_tension
if
gates
[
4
]
else
pols_tension
.
tolist
())
if
gates
[
3
]:
tens_verts_pols
=
area_to_verts
(
np_verts
,
area_params
,
pols_tension
)
result
[
3
].
append
(
tens_verts_pols
if
gates
[
4
]
else
tens_verts_pols
.
tolist
())
return
result
class
SvTensionNode
(
bpy
.
types
.
Node
,
SverchCustomTreeNode
):
'''
Triggers: Measure deformation
Tooltip: Measure deformation
'''
bl_idname
=
'SvTensionNode'
bl_label
=
'Tension'
bl_icon
=
'SNAP_NORMAL'
output_numpy
=
BoolProperty
(
name
=
'Output NumPy'
,
description
=
'output NumPy arrays'
,
default
=
False
,
update
=
updateNode
)
def
draw_buttons_ext
(
self
,
context
,
layout
):
layout
.
prop
(
self
,
"output_numpy"
,
toggle
=
False
)
def
sv_init
(
self
,
context
):
sinw
=
self
.
inputs
.
new
sonw
=
self
.
outputs
.
new
sinw
(
'VerticesSocket'
,
"Rest Verts"
)
sinw
(
'VerticesSocket'
,
"Distort Verts"
)
sinw
(
'StringsSocket'
,
"Edges"
)
sinw
(
'StringsSocket'
,
"Pols"
)
sonw
(
'StringsSocket'
,
"Edges_Tension"
)
sonw
(
'StringsSocket'
,
"Pols_Tension"
)
sonw
(
'StringsSocket'
,
"Vert_Edge_T"
)
sonw
(
'StringsSocket'
,
"Vert_Pol_T"
)
def
get_data
(
self
):
si
=
self
.
inputs
vertices_s
=
si
[
'Rest Verts'
].
sv_get
(
default
=
[[]])
vertices_n
=
si
[
'Distort Verts'
].
sv_get
(
default
=
[[]])
edges_in
=
si
[
'Edges'
].
sv_get
(
default
=
[[]])
pols_in
=
si
[
'Pols'
].
sv_get
(
default
=
[[]])
return
match_long_repeat
([
vertices_s
,
vertices_n
,
edges_in
,
pols_in
])
def
ready
(
self
):
'''check if there are the needed links'''
si
=
self
.
inputs
so
=
self
.
outputs
ready
=
any
(
s
.
is_linked
for
s
in
so
)
ready
=
ready
and
si
[
0
].
is_linked
and
si
[
1
].
is_linked
ready
=
ready
and
(
si
[
2
].
is_linked
or
si
[
3
].
is_linked
)
return
ready
def
process
(
self
):
so
=
self
.
outputs
if
not
self
.
ready
():
return
result
=
[[],
[],
[],
[]]
gates
=
[]
gates
.
append
(
so
[
'Edges_Tension'
].
is_linked
)
gates
.
append
(
so
[
'Vert_Edge_T'
].
is_linked
)
gates
.
append
(
so
[
'Pols_Tension'
].
is_linked
)
gates
.
append
(
so
[
'Vert_Pol_T'
].
is_linked
)
gates
.
append
(
self
.
output_numpy
)
meshes
=
self
.
get_data
()
result
=
calc_tensions
(
meshes
,
gates
,
result
)
if
gates
[
0
]:
so
[
'Edges_Tension'
].
sv_set
(
result
[
0
])
if
gates
[
1
]:
so
[
'Vert_Edge_T'
].
sv_set
(
result
[
1
])
if
gates
[
2
]:
so
[
'Pols_Tension'
].
sv_set
(
result
[
2
])
if
gates
[
3
]:
so
[
'Vert_Pol_T'
].
sv_set
(
result
[
3
])
def
register
():
bpy
.
utils
.
register_class
(
SvTensionNode
)
def
unregister
():
bpy
.
utils
.
unregister_class
(
SvTensionNode
)
Редактирование
Предварительный просмотр
Поддерживает Markdown
0%
Попробовать снова
или
прикрепить новый файл
.
Отмена
You are about to add
0
people
to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Отмена
Пожалуйста,
зарегистрируйтесь
или
войдите
чтобы прокомментировать