Открыть боковую панель
nikitronn
sverchok
Коммиты
8737855e
Коммит
8737855e
создал
Сен 23, 2021
по автору
Ilya Portnov
Просмотр файлов
Curve length: possibility to specify precision.
владелец
9cdf8e70
Изменения
4
Скрыть пробелы
Построчно
Рядом
nodes/curve/curve_length.py
Просмотр файла @
8737855e
...
...
@@ -6,6 +6,9 @@ from bpy.props import FloatProperty, EnumProperty, BoolProperty, IntProperty
from
sverchok.node_tree
import
SverchCustomTreeNode
from
sverchok.data_structure
import
updateNode
,
zip_long_repeat
,
ensure_nesting_level
from
sverchok.utils.curve.algorithms
import
SvCurveLengthSolver
from
sverchok.utils.curve.nurbs
import
SvNurbsCurve
from
sverchok.utils.curve.nurbs_algorithms
import
SvNurbsCurveLengthSolver
class
SvCurveLengthNode
(
bpy
.
types
.
Node
,
SverchCustomTreeNode
):
"""
...
...
@@ -44,6 +47,17 @@ class SvCurveLengthNode(bpy.types.Node, SverchCustomTreeNode):
items
=
modes
,
update
=
updateNode
)
specify_accuracy
:
BoolProperty
(
name
=
"Specify accuracy"
,
default
=
False
,
update
=
updateNode
)
accuracy
:
IntProperty
(
name
=
"Accuracy"
,
default
=
3
,
min
=
0
,
update
=
updateNode
)
def
sv_init
(
self
,
context
):
self
.
inputs
.
new
(
'SvCurveSocket'
,
"Curve"
)
self
.
inputs
.
new
(
'SvStringsSocket'
,
"TMin"
).
prop_name
=
't_min'
...
...
@@ -54,6 +68,12 @@ class SvCurveLengthNode(bpy.types.Node, SverchCustomTreeNode):
def
draw_buttons
(
self
,
context
,
layout
):
layout
.
label
(
text
=
'T mode:'
)
layout
.
prop
(
self
,
'mode'
,
expand
=
True
)
layout
.
prop
(
self
,
'specify_accuracy'
)
if
self
.
specify_accuracy
:
layout
.
prop
(
self
,
'accuracy'
)
def
draw_buttons_ext
(
self
,
context
,
layout
):
self
.
draw_buttons
(
context
,
layout
)
def
process
(
self
):
if
not
any
(
socket
.
is_linked
for
socket
in
self
.
outputs
):
...
...
@@ -68,6 +88,11 @@ class SvCurveLengthNode(bpy.types.Node, SverchCustomTreeNode):
t_max_s
=
ensure_nesting_level
(
t_max_s
,
2
)
resolution_s
=
ensure_nesting_level
(
resolution_s
,
2
)
if
self
.
specify_accuracy
:
tolerance
=
10
**
(
-
self
.
accuracy
)
else
:
tolerance
=
None
length_out
=
[]
for
curve
,
t_mins
,
t_maxs
,
resolutions
in
zip_long_repeat
(
curves
,
t_min_s
,
t_max_s
,
resolution_s
):
for
t_min
,
t_max
,
resolution
in
zip_long_repeat
(
t_mins
,
t_maxs
,
resolutions
):
...
...
@@ -86,7 +111,9 @@ class SvCurveLengthNode(bpy.types.Node, SverchCustomTreeNode):
resolution
=
int
(
resolution
*
(
t_max
-
t_min
)
/
(
curve_t_max
-
curve_t_min
))
if
resolution
<
1
:
resolution
=
1
length
=
curve
.
calc_length
(
t_min
,
t_max
,
resolution
)
solver
=
SvCurveLengthSolver
(
curve
)
solver
.
prepare
(
'SPL'
,
resolution
,
tolerance
=
tolerance
)
length
=
solver
.
calc_length
(
t_min
,
t_max
)
length_out
.
append
([
length
])
...
...
utils/curve/algorithms.py
Просмотр файла @
8737855e
...
...
@@ -49,14 +49,41 @@ class SvCurveLengthSolver(object):
raise
Exception
(
"You have to call solver.prepare() first"
)
return
self
.
_length_params
[
-
1
]
def
prepare
(
self
,
mode
,
resolution
=
50
):
def
_calc_tknots_fixed
(
self
,
resolution
):
t_min
,
t_max
=
self
.
curve
.
get_u_bounds
()
tknots
=
np
.
linspace
(
t_min
,
t_max
,
num
=
resolution
)
lengths
=
self
.
calc_length_segments
(
tknots
)
self
.
_length_params
=
np
.
cumsum
(
np
.
insert
(
lengths
,
0
,
0
))
return
tknots
def
_prepare_find
(
self
,
resolution
,
tolerance
,
tknots
=
None
,
lengths
=
None
,
length_params
=
None
):
if
tknots
is
None
:
tknots
=
self
.
_calc_tknots_fixed
(
resolution
)
if
lengths
is
None
:
lengths
=
self
.
calc_length_segments
(
tknots
)
if
length_params
is
None
:
length_params
=
np
.
cumsum
(
np
.
insert
(
lengths
,
0
,
0
))
resolution2
=
resolution
*
2
-
1
tknots2
=
self
.
_calc_tknots_fixed
(
resolution2
)
lengths2
=
self
.
calc_length_segments
(
tknots2
)
length_params2
=
np
.
cumsum
(
np
.
insert
(
lengths2
,
0
,
0
))
dl
=
abs
(
length_params2
[::
2
]
-
length_params
)
if
(
dl
<
tolerance
).
all
():
return
tknots2
,
length_params2
else
:
return
self
.
_prepare_find
(
resolution2
,
tolerance
,
tknots2
,
lengths2
,
length_params2
)
def
prepare
(
self
,
mode
,
resolution
=
50
,
tolerance
=
None
):
if
tolerance
is
None
:
tknots
=
self
.
_calc_tknots_fixed
(
resolution
)
lengths
=
self
.
calc_length_segments
(
tknots
)
self
.
_length_params
=
np
.
cumsum
(
np
.
insert
(
lengths
,
0
,
0
))
else
:
tknots
,
self
.
_length_params
=
self
.
_prepare_find
(
resolution
,
tolerance
)
self
.
_reverse_spline
=
self
.
_make_spline
(
mode
,
tknots
,
self
.
_length_params
)
self
.
_prime_spline
=
self
.
_make_spline
(
mode
,
self
.
_length_params
,
tknots
)
def
_make_spline
(
self
,
mode
,
tknots
,
values
):
zeros
=
np
.
zeros
(
len
(
tknots
))
control_points
=
np
.
vstack
((
values
,
tknots
,
zeros
)).
T
...
...
@@ -72,7 +99,7 @@ class SvCurveLengthSolver(object):
if
self
.
_prime_spline
is
None
:
raise
Exception
(
"You have to call solver.prepare() first"
)
lengths
=
self
.
_prime_spline
.
eval
(
np
.
array
([
t_min
,
t_max
]))
return
lengths
[
1
]
-
lengths
[
0
]
return
lengths
[
1
]
[
1
]
-
lengths
[
0
]
[
1
]
def
calc_length_params
(
self
,
ts
):
if
self
.
_prime_spline
is
None
:
...
...
utils/curve/nurbs.py
Просмотр файла @
8737855e
...
...
@@ -467,7 +467,7 @@ class SvNurbsCurve(SvCurve):
curve
=
curve
.
reparametrize
(
0
,
1
)
return
curve
def
is_line
(
self
,
tolerance
=
0.001
):
def
is_line
(
self
,
tolerance
=
0.001
,
use_length_tolerance
=
False
):
# Check that the provided curve is nearly a straight line segment.
# This implementation depends heavily on the fact that this curve is
# NURBS. It uses so-called "godograph property". In short, this
...
...
@@ -488,9 +488,14 @@ class SvNurbsCurve(SvCurve):
dv
=
cpt2
-
cpt1
dv
/=
np
.
linalg
.
norm
(
dv
)
cos_angle
=
np
.
dot
(
dv
,
direction
)
tan_angle
=
sqrt
(
1.0
-
cos_angle
**
2
)
/
cos_angle
if
vector_len
*
tan_angle
>
tolerance
:
return
False
if
use_length_tolerance
:
vector2_len
=
vector_len
/
cos_angle
if
abs
(
vector2_len
-
vector_len
)
>
tolerance
/
10
:
return
False
else
:
tan_angle
=
sqrt
(
1.0
-
cos_angle
**
2
)
/
cos_angle
if
vector_len
*
tan_angle
>
tolerance
:
return
False
return
True
...
...
utils/curve/nurbs_algorithms.py
Просмотр файла @
8737855e
...
...
@@ -16,7 +16,7 @@ from sverchok.utils.math import distribute_int
from
sverchok.utils.geom
import
Spline
,
linear_approximation
,
intersect_segment_segment
from
sverchok.utils.nurbs_common
import
SvNurbsBasisFunctions
,
SvNurbsMaths
,
from_homogenous
,
CantInsertKnotException
from
sverchok.utils.curve
import
knotvector
as
sv_knotvector
from
sverchok.utils.curve.algorithms
import
unify_curves_degree
from
sverchok.utils.curve.algorithms
import
unify_curves_degree
,
SvCurveLengthSolver
from
sverchok.utils.decorators
import
deprecated
from
sverchok.utils.logging
import
getLogger
from
sverchok.dependencies
import
scipy
...
...
@@ -441,3 +441,51 @@ def refine_curve(curve, samples, algorithm=REFINE_DISTRIBUTE, refine_max=False,
return
curve
class
SvNurbsCurveLengthSolver
(
SvCurveLengthSolver
):
def
__init__
(
self
,
curve
):
self
.
curve
=
curve
self
.
_reverse_spline
=
None
self
.
_prime_spline
=
None
def
_calc_tknots
(
self
,
resolution
,
tolerance
):
def
middle
(
segment
):
u1
,
u2
=
segment
.
get_u_bounds
()
u
=
(
u1
+
u2
)
*
0.5
return
u
def
split
(
segment
):
u
=
middle
(
segment
)
return
segment
.
split_at
(
u
)
def
calc_tknots
(
segment
):
if
segment
.
is_line
(
tolerance
,
use_length_tolerance
=
True
):
u1
,
u2
=
segment
.
get_u_bounds
()
return
set
([
u1
,
u2
])
else
:
segment1
,
segment2
=
split
(
segment
)
knots1
=
calc_tknots
(
segment1
)
knots2
=
calc_tknots
(
segment2
)
knots
=
knots1
.
union
(
knots2
)
return
knots
t_min
,
t_max
=
self
.
curve
.
get_u_bounds
()
init_knots
=
np
.
linspace
(
t_min
,
t_max
,
num
=
resolution
)
segments
=
[
self
.
curve
.
cut_segment
(
u1
,
u2
)
for
u1
,
u2
in
zip
(
init_knots
,
init_knots
[
1
:])]
all_knots
=
set
()
for
segment
in
segments
:
knots
=
calc_tknots
(
segment
)
all_knots
=
all_knots
.
union
(
knots
)
return
np
.
array
(
sorted
(
all_knots
))
def
prepare
(
self
,
mode
,
resolution
=
50
,
tolerance
=
1e-3
):
if
tolerance
is
None
:
tolerance
=
1e-3
tknots
=
self
.
_calc_tknots
(
resolution
,
tolerance
)
lengths
=
self
.
calc_length_segments
(
tknots
)
self
.
_length_params
=
np
.
cumsum
(
np
.
insert
(
lengths
,
0
,
0
))
self
.
_reverse_spline
=
self
.
_make_spline
(
mode
,
tknots
,
self
.
_length_params
)
self
.
_prime_spline
=
self
.
_make_spline
(
mode
,
self
.
_length_params
,
tknots
)
Редактирование
Предварительный просмотр
Поддерживает Markdown
0%
Попробовать снова
или
прикрепить новый файл
.
Отмена
You are about to add
0
people
to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Отмена
Пожалуйста,
зарегистрируйтесь
или
войдите
чтобы прокомментировать