Открыть боковую панель
nikitronn
sverchok
Коммиты
6dbe477e
Не подтверждена
Коммит
6dbe477e
создал
Дек 05, 2020
по автору
Ilya V. Portnov
Зафиксировано автором
GitHub
Дек 05, 2020
Просмотр файлов
Merge pull request #3755 from nortikin/splprep_node
"Approximate Nurbs Curve" Mk2
владельцы
415efa52
56c91c7a
Изменения
5
Скрыть пробелы
Построчно
Рядом
docs/nodes/curve/approximate_nurbs_curve.rst
Просмотр файла @
6dbe477e
...
...
@@ -4,9 +4,10 @@ Approximate NURBS Curve
Dependencies
------------
This node requires
Geomdl
_ library to work.
This node requires
either Geomdl_ or SciPy
_ library to work.
.. _Geomdl: https://onurraufbingol.com/NURBS-Python/
.. _SciPy: https://scipy.org/
Functionality
-------------
...
...
@@ -17,6 +18,22 @@ points, i.e. goes as close to them as possible while remaining a smooth curve.
In fact, the generated curve always will be a non-rational curve, which means
that all weights will be equal to 1.
This node supports two implementations of curve approximation algorithm.
Different implementation give you different ways of controlling them:
* Geomdl_ implementation can either define the number of control points of
generated curve automatically, or you can provide it with desired number of
control points. This implementation supports only two metrics - euclidean and
centripetal. This implementation can not generate cyclic (closed) curves.
* SciPy_ implementation allows you to define "smoothing" parameter, to define
how smooth you want the curve to be. By default, it selects the smoothing
factor automatically. If you explicitly set the smoothing factor to zero, the
curve will go exactly through all provided points, i.e. the node will perform
interpolation instead of approximation. This implementation supports wider
selection of metrics. This implementation can make cyclic (closed) curves.
Additionally, when smoothing factor is not zero, you can provide different
weights for different points.
.. _NURBS: https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline
Inputs
...
...
@@ -25,21 +42,64 @@ Inputs
This node has the following inputs:
* **Vertices**. The points to be approximated. This input is mandatory.
* **Weights**. This input is available only when **Implementation** parameter
is set to **SciPy**. Weights of points to be approximated. Bigger values of
weight mean that the curve will pass through corresponding point at the
smaller distance. This does not have sense if **Smoothing** input is set to
zero. Optional input. If not connected, the node will consider weights of all
points as equal.
* **Degree**. Degree of the curve to be built. Default value is 3. Most useful values are 3, 5 and 7.
* **PointsCnt**. Number of curve's control points. This input is available only
when **Specify points count** parameter is checked. Default value is 5.
when **Implementation** parameter is set to **Geomdl**, and **Specify points
count** parameter is checked. Default value is 5.
* **Smoothing**. This input is available only when **Implementation** parameter
is set to **SciPy**, and **Scpecify smoothing** parameter is checked.
Smoothing factor. Bigger values will make more smooth curves. Value of 0
(zero) mean that the curve will exactly pass through all points. The default
value is 0.1.
Parameters
----------
This node has the following parameters:
* **Centripetal**. This defines whether the node will use centripetal
approximation method. Unchecked by default.
* **Specify points count**. If checked, then it will be possible to specify the
number of curve's control points in **PointsCnt** input. Otherwise, the node
will determine required number of control points by itself (this number can
be too big for many applications).
* **Implementation**. Approximation algorithm implementation to be used. The available values are:
* **Geomdl**. Use the implementation from Geomdl_ library. This is available only when Geomdl library is installed.
* **SciPy**. Use the implementation from SciPy_ library. This is available only when SciPy library is installed.
By default, the first available implementaiton is used.
* **Centripetal**. This parameter is available only when **Implementation**
parameter is set to **Geomdl**. This defines whether the node will use
centripetal metric. If not checked, the node will use euclidian metric.
Unchecked by default.
* **Specify points count**. This parameter is available only when
**Implementation** parameter is set to **Geomdl**. If checked, then it will
be possible to specify the number of curve's control points in **PointsCnt**
input. Otherwise, the node will determine required number of control points
by itself (this number can be too big for many applications).
* **Cyclic**. This parameter is available only when **Implementation**
parameter is set to **SciPy**. Defines whether the generated curve will be
cyclic (closed). Unchecked by default.
* **Metric**. This parameter is available only when **Implementation**
parameter is set to **SciPy**.Metric to be used for interpolation. The
available values are:
* Manhattan
* Euclidian
* Points (just number of points from the beginning)
* Chebyshev
* Centripetal (square root of Euclidian distance)
* X, Y, Z axis - use distance along one of coordinate axis, ignore others.
The default value is Euclidian.
* **Specify smoothing**. This parameter is available only when
**Implementation** parameter is set to **SciPy**. If checked, the node will
allow you to specify smoothing factor via **Smoothing** input. If not
checked, the node will select the smoothing factor automatically. Unchecked
by default.
Outputs
-------
...
...
@@ -57,3 +117,7 @@ Take points from Greasepencil drawing and approximate them with a smooth curve:
.. image:: https://user-images.githubusercontent.com/284644/74363000-7becef00-4deb-11ea-9963-e864dc3a3599.png
Use SciPy implementation to make a closed curve:
.. image:: https://user-images.githubusercontent.com/284644/101246890-d61ebe00-3737-11eb-942d-c31e02bf3c3d.png
index.md
Просмотр файла @
6dbe477e
...
...
@@ -71,7 +71,7 @@
## Curves @ NURBS
SvExNurbsCurveNode
Sv
Ex
ApproxNurbsCurveNode
SvApproxNurbsCurve
Mk2
Node
SvExInterpolateNurbsCurveNode
SvDeconstructCurveNode
...
...
nodes/curve/approximate_nurbs_curve.py
Просмотр файла @
6dbe477e
# 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
import
numpy
as
np
import
bpy
from
bpy.props
import
FloatProperty
,
EnumProperty
,
BoolProperty
,
IntProperty
from
sverchok.node_tree
import
SverchCustomTreeNode
from
sverchok.data_structure
import
updateNode
,
zip_long_repeat
,
throttle_and_update_node
,
get_data_nesting_level
,
ensure_nesting_level
from
sverchok.data_structure
import
updateNode
,
zip_long_repeat
,
throttle_and_update_node
,
get_data_nesting_level
,
ensure_nesting_level
,
repeat_last_for_length
from
sverchok.utils.math
import
supported_metrics
,
xyz_metrics
from
sverchok.utils.logging
import
info
,
exception
from
sverchok.utils.curve.nurbs
import
SvGeomdlCurve
from
sverchok.dependencies
import
geomdl
from
sverchok.utils.curve.splprep
import
scipy_nurbs_approximate
from
sverchok.dependencies
import
geomdl
,
scipy
from
sverchok.utils.dummy_nodes
import
add_dummy
if
geomdl
is
None
:
add_dummy
(
'SvExApproxNurbsCurveNode'
,
"Approximate NURBS Curve"
,
'geomdl'
)
else
:
if
geomdl
is
None
and
scipy
is
None
:
add_dummy
(
'SvApproxNurbsCurveMk2Node'
,
"Approximate NURBS Curve"
,
'geomdl or scipy'
)
if
geomdl
is
not
None
:
from
geomdl
import
fitting
class
SvExApproxNurbsCurveNode
(
bpy
.
types
.
Node
,
SverchCustomTreeNode
):
"""
Triggers: NURBS Curve
Tooltip: Approximate NURBS Curve
"""
bl_idname
=
'SvExApproxNurbsCurveNode'
bl_label
=
'Approximate NURBS Curve'
bl_icon
=
'CURVE_NCURVE'
degree
:
IntProperty
(
name
=
"Degree"
,
min
=
2
,
max
=
6
,
default
=
3
,
update
=
updateNode
)
centripetal
:
BoolProperty
(
name
=
"Centripetal"
,
default
=
False
,
update
=
updateNode
)
@
throttle_and_update_node
def
update_sockets
(
self
,
context
):
self
.
inputs
[
'PointsCnt'
].
hide_safe
=
not
self
.
has_points_cnt
has_points_cnt
:
BoolProperty
(
name
=
"Specify points count"
,
default
=
False
,
update
=
update_sockets
)
points_cnt
:
IntProperty
(
name
=
"Points count"
,
min
=
3
,
default
=
5
,
update
=
updateNode
)
def
draw_buttons
(
self
,
context
,
layout
):
class
SvApproxNurbsCurveMk2Node
(
bpy
.
types
.
Node
,
SverchCustomTreeNode
):
"""
Triggers: NURBS Curve
Tooltip: Approximate NURBS Curve
"""
bl_idname
=
'SvApproxNurbsCurveMk2Node'
bl_label
=
'Approximate NURBS Curve'
bl_icon
=
'CURVE_NCURVE'
degree
:
IntProperty
(
name
=
"Degree"
,
min
=
1
,
max
=
6
,
default
=
3
,
update
=
updateNode
)
centripetal
:
BoolProperty
(
name
=
"Centripetal"
,
default
=
False
,
update
=
updateNode
)
metric
:
EnumProperty
(
name
=
'Metric'
,
description
=
"Knot mode"
,
default
=
"DISTANCE"
,
items
=
supported_metrics
+
xyz_metrics
,
update
=
updateNode
)
@
throttle_and_update_node
def
update_sockets
(
self
,
context
):
self
.
inputs
[
'PointsCnt'
].
hide_safe
=
not
(
self
.
implementation
==
'GEOMDL'
and
self
.
has_points_cnt
)
self
.
inputs
[
'Smoothing'
].
hide_safe
=
not
(
self
.
implementation
==
'SCIPY'
and
self
.
has_smoothing
)
self
.
inputs
[
'Weights'
].
hide_safe
=
not
(
self
.
implementation
==
'SCIPY'
)
has_points_cnt
:
BoolProperty
(
name
=
"Specify points count"
,
default
=
False
,
update
=
update_sockets
)
points_cnt
:
IntProperty
(
name
=
"Points count"
,
min
=
3
,
default
=
5
,
update
=
updateNode
)
def
get_implementations
(
self
,
context
):
implementations
=
[]
if
geomdl
is
not
None
:
implementations
.
append
((
'GEOMDL'
,
"Geomdl"
,
"Geomdl (NURBS-Python) package implementation"
,
0
))
if
scipy
is
not
None
:
implementations
.
append
((
'SCIPY'
,
"SciPy"
,
"SciPy package implementation"
,
1
))
return
implementations
implementation
:
EnumProperty
(
name
=
"Implementation"
,
description
=
"Approximation algorithm implmenetation"
,
items
=
get_implementations
,
update
=
update_sockets
)
smoothing
:
FloatProperty
(
name
=
"Smoothing"
,
description
=
"Smoothing factor. Set to 0 to do interpolation"
,
min
=
0.0
,
default
=
0.1
,
update
=
updateNode
)
has_smoothing
:
BoolProperty
(
name
=
"Specify smoothing"
,
default
=
False
,
update
=
update_sockets
)
is_cyclic
:
BoolProperty
(
name
=
"Cyclic"
,
default
=
False
,
update
=
updateNode
)
def
draw_buttons
(
self
,
context
,
layout
):
layout
.
prop
(
self
,
'implementation'
,
text
=
''
)
if
self
.
implementation
==
'GEOMDL'
:
layout
.
prop
(
self
,
'centripetal'
,
toggle
=
True
)
layout
.
prop
(
self
,
'has_points_cnt'
,
toggle
=
True
)
def
sv_init
(
self
,
context
):
self
.
inputs
.
new
(
'SvVerticesSocket'
,
"Vertices"
)
self
.
inputs
.
new
(
'SvStringsSocket'
,
"Degree"
).
prop_name
=
'degree'
self
.
inputs
.
new
(
'SvStringsSocket'
,
"PointsCnt"
).
prop_name
=
'points_cnt'
self
.
outputs
.
new
(
'SvCurveSocket'
,
"Curve"
)
self
.
outputs
.
new
(
'SvVerticesSocket'
,
"ControlPoints"
)
self
.
outputs
.
new
(
'SvStringsSocket'
,
"Knots"
)
self
.
update_sockets
(
context
)
def
process
(
self
):
if
not
any
(
socket
.
is_linked
for
socket
in
self
.
outputs
):
return
vertices_s
=
self
.
inputs
[
'Vertices'
].
sv_get
()
degree_s
=
self
.
inputs
[
'Degree'
].
sv_get
()
points_cnt_s
=
self
.
inputs
[
'PointsCnt'
].
sv_get
()
input_level
=
get_data_nesting_level
(
vertices_s
)
vertices_s
=
ensure_nesting_level
(
vertices_s
,
4
)
degree_s
=
ensure_nesting_level
(
degree_s
,
2
)
points_cnt_s
=
ensure_nesting_level
(
points_cnt_s
,
2
)
nested_output
=
input_level
>
3
curves_out
=
[]
points_out
=
[]
knots_out
=
[]
for
params
in
zip_long_repeat
(
vertices_s
,
degree_s
,
points_cnt_s
):
new_curves
=
[]
new_points
=
[]
new_knots
=
[]
for
vertices
,
degree
,
points_cnt
in
zip_long_repeat
(
*
params
):
else
:
layout
.
prop
(
self
,
'is_cyclic'
)
layout
.
prop
(
self
,
'metric'
)
layout
.
prop
(
self
,
'has_smoothing'
)
def
sv_init
(
self
,
context
):
self
.
inputs
.
new
(
'SvVerticesSocket'
,
"Vertices"
)
self
.
inputs
.
new
(
'SvStringsSocket'
,
"Weights"
)
self
.
inputs
.
new
(
'SvStringsSocket'
,
"Degree"
).
prop_name
=
'degree'
self
.
inputs
.
new
(
'SvStringsSocket'
,
"PointsCnt"
).
prop_name
=
'points_cnt'
self
.
inputs
.
new
(
'SvStringsSocket'
,
"Smoothing"
).
prop_name
=
'smoothing'
self
.
outputs
.
new
(
'SvCurveSocket'
,
"Curve"
)
self
.
outputs
.
new
(
'SvVerticesSocket'
,
"ControlPoints"
)
self
.
outputs
.
new
(
'SvStringsSocket'
,
"Knots"
)
self
.
update_sockets
(
context
)
def
process
(
self
):
if
not
any
(
socket
.
is_linked
for
socket
in
self
.
outputs
):
return
vertices_s
=
self
.
inputs
[
'Vertices'
].
sv_get
()
weights_s
=
self
.
inputs
[
'Weights'
].
sv_get
(
default
=
[[[
None
]]])
degree_s
=
self
.
inputs
[
'Degree'
].
sv_get
()
points_cnt_s
=
self
.
inputs
[
'PointsCnt'
].
sv_get
()
smoothing_s
=
self
.
inputs
[
'Smoothing'
].
sv_get
()
input_level
=
get_data_nesting_level
(
vertices_s
)
vertices_s
=
ensure_nesting_level
(
vertices_s
,
4
)
degree_s
=
ensure_nesting_level
(
degree_s
,
2
)
points_cnt_s
=
ensure_nesting_level
(
points_cnt_s
,
2
)
smoothing_s
=
ensure_nesting_level
(
smoothing_s
,
2
)
has_weights
=
self
.
inputs
[
'Weights'
].
is_linked
if
has_weights
:
weights_s
=
ensure_nesting_level
(
weights_s
,
3
)
nested_output
=
input_level
>
3
curves_out
=
[]
points_out
=
[]
knots_out
=
[]
for
params
in
zip_long_repeat
(
vertices_s
,
weights_s
,
degree_s
,
points_cnt_s
,
smoothing_s
):
new_curves
=
[]
new_points
=
[]
new_knots
=
[]
for
vertices
,
weights
,
degree
,
points_cnt
,
smoothing
in
zip_long_repeat
(
*
params
):
if
self
.
implementation
==
'GEOMDL'
:
kwargs
=
dict
(
centripetal
=
self
.
centripetal
)
if
self
.
has_points_cnt
:
kwargs
[
'ctrlpts_size'
]
=
points_cnt
curve
=
fitting
.
approximate_curve
(
vertices
,
degree
,
**
kwargs
)
new_points
.
append
(
curve
.
ctrlpts
)
new_knots
.
append
(
curve
.
knotvector
)
control_points
=
curve
.
ctrlpts
knotvector
=
curve
.
knotvector
curve
=
SvGeomdlCurve
(
curve
)
new_curves
.
append
(
curve
)
if
nested_output
:
curves_out
.
append
(
new_curves
)
points_out
.
append
(
new_points
)
knots_out
.
append
(
new_knots
)
else
:
curves_out
.
extend
(
new_curves
)
points_out
.
extend
(
new_points
)
knots_out
.
extend
(
new_knots
)
self
.
outputs
[
'Curve'
].
sv_set
(
curves_out
)
self
.
outputs
[
'ControlPoints'
].
sv_set
(
points_out
)
self
.
outputs
[
'Knots'
].
sv_set
(
knots_out
)
else
:
# SCIPY:
points
=
np
.
array
(
vertices
)
if
has_weights
:
weights
=
repeat_last_for_length
(
weights
,
len
(
vertices
))
else
:
weights
=
None
if
not
self
.
has_smoothing
:
smoothing
=
None
curve
=
scipy_nurbs_approximate
(
points
,
weights
=
weights
,
metric
=
self
.
metric
,
degree
=
degree
,
smoothing
=
smoothing
,
is_cyclic
=
self
.
is_cyclic
)
control_points
=
curve
.
get_control_points
().
tolist
()
knotvector
=
curve
.
get_knotvector
().
tolist
()
new_curves
.
append
(
curve
)
new_points
.
append
(
control_points
)
new_knots
.
append
(
knotvector
)
if
nested_output
:
curves_out
.
append
(
new_curves
)
points_out
.
append
(
new_points
)
knots_out
.
append
(
new_knots
)
else
:
curves_out
.
extend
(
new_curves
)
points_out
.
extend
(
new_points
)
knots_out
.
extend
(
new_knots
)
self
.
outputs
[
'Curve'
].
sv_set
(
curves_out
)
self
.
outputs
[
'ControlPoints'
].
sv_set
(
points_out
)
self
.
outputs
[
'Knots'
].
sv_set
(
knots_out
)
def
register
():
if
geomdl
is
not
None
:
bpy
.
utils
.
register_class
(
Sv
Ex
ApproxNurbsCurveNode
)
if
geomdl
is
not
None
or
scipy
is
not
None
:
bpy
.
utils
.
register_class
(
SvApproxNurbsCurve
Mk2
Node
)
def
unregister
():
if
geomdl
is
not
None
:
bpy
.
utils
.
unregister_class
(
Sv
Ex
ApproxNurbsCurveNode
)
if
geomdl
is
not
None
or
scipy
is
not
None
:
bpy
.
utils
.
unregister_class
(
SvApproxNurbsCurve
Mk2
Node
)
old_nodes/approximate_nurbs_curve.py
0 → 100644
Просмотр файла @
6dbe477e
import
bpy
from
bpy.props
import
FloatProperty
,
EnumProperty
,
BoolProperty
,
IntProperty
from
sverchok.node_tree
import
SverchCustomTreeNode
from
sverchok.data_structure
import
updateNode
,
zip_long_repeat
,
throttle_and_update_node
,
get_data_nesting_level
,
ensure_nesting_level
from
sverchok.utils.logging
import
info
,
exception
from
sverchok.utils.curve.nurbs
import
SvGeomdlCurve
from
sverchok.dependencies
import
geomdl
from
sverchok.utils.dummy_nodes
import
add_dummy
if
geomdl
is
None
:
add_dummy
(
'SvExApproxNurbsCurveNode'
,
"Approximate NURBS Curve"
,
'geomdl'
)
else
:
from
geomdl
import
fitting
class
SvExApproxNurbsCurveNode
(
bpy
.
types
.
Node
,
SverchCustomTreeNode
):
"""
Triggers: NURBS Curve
Tooltip: Approximate NURBS Curve
"""
bl_idname
=
'SvExApproxNurbsCurveNode'
bl_label
=
'Approximate NURBS Curve'
bl_icon
=
'CURVE_NCURVE'
degree
:
IntProperty
(
name
=
"Degree"
,
min
=
2
,
max
=
6
,
default
=
3
,
update
=
updateNode
)
centripetal
:
BoolProperty
(
name
=
"Centripetal"
,
default
=
False
,
update
=
updateNode
)
@
throttle_and_update_node
def
update_sockets
(
self
,
context
):
self
.
inputs
[
'PointsCnt'
].
hide_safe
=
not
self
.
has_points_cnt
has_points_cnt
:
BoolProperty
(
name
=
"Specify points count"
,
default
=
False
,
update
=
update_sockets
)
points_cnt
:
IntProperty
(
name
=
"Points count"
,
min
=
3
,
default
=
5
,
update
=
updateNode
)
def
draw_buttons
(
self
,
context
,
layout
):
layout
.
prop
(
self
,
'centripetal'
,
toggle
=
True
)
layout
.
prop
(
self
,
'has_points_cnt'
,
toggle
=
True
)
def
sv_init
(
self
,
context
):
self
.
inputs
.
new
(
'SvVerticesSocket'
,
"Vertices"
)
self
.
inputs
.
new
(
'SvStringsSocket'
,
"Degree"
).
prop_name
=
'degree'
self
.
inputs
.
new
(
'SvStringsSocket'
,
"PointsCnt"
).
prop_name
=
'points_cnt'
self
.
outputs
.
new
(
'SvCurveSocket'
,
"Curve"
)
self
.
outputs
.
new
(
'SvVerticesSocket'
,
"ControlPoints"
)
self
.
outputs
.
new
(
'SvStringsSocket'
,
"Knots"
)
self
.
update_sockets
(
context
)
def
process
(
self
):
if
not
any
(
socket
.
is_linked
for
socket
in
self
.
outputs
):
return
vertices_s
=
self
.
inputs
[
'Vertices'
].
sv_get
()
degree_s
=
self
.
inputs
[
'Degree'
].
sv_get
()
points_cnt_s
=
self
.
inputs
[
'PointsCnt'
].
sv_get
()
input_level
=
get_data_nesting_level
(
vertices_s
)
vertices_s
=
ensure_nesting_level
(
vertices_s
,
4
)
degree_s
=
ensure_nesting_level
(
degree_s
,
2
)
points_cnt_s
=
ensure_nesting_level
(
points_cnt_s
,
2
)
nested_output
=
input_level
>
3
curves_out
=
[]
points_out
=
[]
knots_out
=
[]
for
params
in
zip_long_repeat
(
vertices_s
,
degree_s
,
points_cnt_s
):
new_curves
=
[]
new_points
=
[]
new_knots
=
[]
for
vertices
,
degree
,
points_cnt
in
zip_long_repeat
(
*
params
):
kwargs
=
dict
(
centripetal
=
self
.
centripetal
)
if
self
.
has_points_cnt
:
kwargs
[
'ctrlpts_size'
]
=
points_cnt
curve
=
fitting
.
approximate_curve
(
vertices
,
degree
,
**
kwargs
)
new_points
.
append
(
curve
.
ctrlpts
)
new_knots
.
append
(
curve
.
knotvector
)
curve
=
SvGeomdlCurve
(
curve
)
new_curves
.
append
(
curve
)
if
nested_output
:
curves_out
.
append
(
new_curves
)
points_out
.
append
(
new_points
)
knots_out
.
append
(
new_knots
)
else
:
curves_out
.
extend
(
new_curves
)
points_out
.
extend
(
new_points
)
knots_out
.
extend
(
new_knots
)
self
.
outputs
[
'Curve'
].
sv_set
(
curves_out
)
self
.
outputs
[
'ControlPoints'
].
sv_set
(
points_out
)
self
.
outputs
[
'Knots'
].
sv_set
(
knots_out
)
def
register
():
if
geomdl
is
not
None
:
bpy
.
utils
.
register_class
(
SvExApproxNurbsCurveNode
)
def
unregister
():
if
geomdl
is
not
None
:
bpy
.
utils
.
unregister_class
(
SvExApproxNurbsCurveNode
)
utils/curve/splprep.py
0 → 100644
Просмотр файла @
6dbe477e
# 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
import
numpy
as
np
from
sverchok.utils.curve.nurbs
import
SvNurbsCurve
from
sverchok.utils.geom
import
Spline
from
sverchok.dependencies
import
scipy
if
scipy
is
not
None
:
from
scipy
import
interpolate
def
scipy_nurbs_approximate
(
points
,
weights
=
None
,
metric
=
'DISTANCE'
,
degree
=
3
,
smoothing
=
None
,
is_cyclic
=
False
):
points
=
np
.
asarray
(
points
)
if
weights
is
not
None
and
len
(
points
)
!=
len
(
weights
):
raise
Exception
(
"Number of weights must be equal to number of points"
)
if
is_cyclic
:
points
=
np
.
vstack
((
points
,
points
[
0
]))
if
weights
is
not
None
:
weights
=
np
.
insert
(
weights
,
-
1
,
weights
[
0
])
points_orig
=
points
points
=
points
.
T
kwargs
=
dict
()
if
weights
is
not
None
:
kwargs
[
'w'
]
=
np
.
asarray
(
weights
)
if
metric
is
not
None
:
tknots
=
Spline
.
create_knots
(
points_orig
,
metric
)
if
len
(
tknots
)
!=
len
(
points
.
T
):
raise
Exception
(
f
"Number of T knots (
{
len
(
tknots
)
}
) is not equal to number of points (
{
len
(
points
.
T
)
}
)"
)
kwargs
[
'u'
]
=
tknots
if
degree
is
not
None
:
kwargs
[
'k'
]
=
degree
if
smoothing
is
not
None
:
kwargs
[
's'
]
=
smoothing
if
is_cyclic
:
kwargs
[
'per'
]
=
1
tck
,
u
=
interpolate
.
splprep
(
points
,
**
kwargs
)
knotvector
=
tck
[
0
]
control_points
=
np
.
stack
(
tck
[
1
]).
T
degree
=
tck
[
2
]
curve
=
SvNurbsCurve
.
build
(
SvNurbsCurve
.
NATIVE
,
degree
,
knotvector
,
control_points
)
if
is_cyclic
:
curve
=
curve
.
cut_segment
(
0.0
,
1.0
)
#curve.u_bounds = (0.0, 1.0)
return
curve
Редактирование
Предварительный просмотр
Поддерживает Markdown
0%
Попробовать снова
или
прикрепить новый файл
.
Отмена
You are about to add
0
people
to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Отмена
Пожалуйста,
зарегистрируйтесь
или
войдите
чтобы прокомментировать