Открыть боковую панель
nikitronn
sverchok
Коммиты
e7a8a690
Коммит
e7a8a690
создал
Июл 01, 2021
по автору
Ilya Portnov
Просмотр файлов
On knots precision.
владелец
7129742f
Изменения
6
Скрыть пробелы
Построчно
Рядом
tests/dict_tests.py
0 → 100644
Просмотр файла @
e7a8a690
import
unittest
from
sverchok.utils.logging
import
error
from
sverchok.utils.testing
import
*
from
sverchok.utils.dictionary
import
SvApproxDict
from
sverchok.utils.curve.nurbs_algorithms
import
KnotvectorDict
class
ApproxDictTests
(
SverchokTestCase
):
def
test_repr
(
self
):
d
=
SvApproxDict
([(
1.0
,
"A"
),
(
2.0
,
"B"
)])
s
=
repr
(
d
)
self
.
assertEquals
(
s
,
"{1.0: A, 2.0: B}"
)
def
test_dict_1
(
self
):
d
=
SvApproxDict
([(
1.0
,
"A"
),
(
2.0
,
"B"
)],
precision
=
1
)
d
[
2.01
]
=
"C"
self
.
assertEquals
(
repr
(
d
),
"{1.0: A, 2.0: C}"
)
self
.
assertEquals
(
d
[
1.0
],
"A"
)
self
.
assertEquals
(
d
[
1.01
],
"A"
)
self
.
assertEquals
(
d
[
0.99
],
"A"
)
self
.
assertEquals
(
d
[
2.0
],
"C"
)
self
.
assertEquals
(
d
[
2.01
],
"C"
)
self
.
assertEquals
(
d
[
1.99
],
"C"
)
d
[
2.5
]
=
"K"
self
.
assertEquals
(
repr
(
d
),
"{1.0: A, 2.0: C, 2.5: K}"
)
self
.
assertEquals
(
d
[
2.5
],
"K"
)
self
.
assertEquals
(
d
[
2.51
],
"K"
)
self
.
assertEquals
(
d
[
2.49
],
"K"
)
d
[
1.5
]
=
"H"
self
.
assertEquals
(
repr
(
d
),
"{1.0: A, 1.5: H, 2.0: C, 2.5: K}"
)
self
.
assertEquals
(
d
[
1.5
],
"H"
)
self
.
assertEquals
(
d
[
1.51
],
"H"
)
self
.
assertEquals
(
d
[
1.49
],
"H"
)
class
KnotvectorDictTests
(
SverchokTestCase
):
def
test_dict_1
(
self
):
d
=
KnotvectorDict
(
accuracy
=
3
)
curve1_kv
=
[
0
,
0.499
,
0.501
,
1
]
for
k
in
curve1_kv
:
d
.
update
(
1
,
k
,
1
)
curve2_kv
=
[
0
,
0.5
,
1
]
for
k
in
curve2_kv
:
d
.
update
(
2
,
k
,
1
)
expected_items
=
[(
0
,
1
),
(
0.499
,
1
),
(
0.5
,
1
),
(
0.501
,
1
),
(
1
,
1
)]
self
.
assertEquals
(
d
.
items
(),
expected_items
)
def
test_dict_2
(
self
):
d
=
KnotvectorDict
(
accuracy
=
3
)
curve1_kv
=
[(
0
,
4
),
(
0.499
,
3
),
(
0.501
,
3
),
(
1
,
4
)]
for
k
,
m
in
curve1_kv
:
d
.
update
(
1
,
k
,
m
)
curve2_kv
=
[(
0
,
4
),
(
0.5
,
3
),
(
1
,
4
)]
for
k
,
m
in
curve2_kv
:
d
.
update
(
2
,
k
,
m
)
expected_items
=
[(
0
,
4
),
(
0.499
,
3
),
(
0.5
,
3
),
(
0.501
,
3
),
(
1
,
4
)]
self
.
assertEquals
(
d
.
items
(),
expected_items
)
def
test_dict_3
(
self
):
d
=
KnotvectorDict
(
accuracy
=
2
)
curve1_kv
=
[(
0
,
4
),
(
0.499
,
3
),
(
0.501
,
3
),
(
1
,
4
)]
for
k
,
m
in
curve1_kv
:
d
.
update
(
1
,
k
,
m
)
expected_items
=
[(
0
,
4
),
(
0.499
,
3
),
(
0.501
,
3
),
(
1
,
4
)]
self
.
assertEquals
(
d
.
items
(),
expected_items
)
curve2_kv
=
[(
0
,
4
),
(
0.5
,
3
),
(
1
,
4
)]
for
k
,
m
in
curve2_kv
:
d
.
update
(
2
,
k
,
m
)
expected_items
=
[(
0
,
4
),
(
0.499
,
3
),
(
0.5
,
3
),
(
0.501
,
3
),
(
1
,
4
)]
self
.
assertEquals
(
d
.
items
(),
expected_items
)
utils/curve/nurbs_algorithms.py
Просмотр файла @
e7a8a690
...
...
@@ -16,6 +16,7 @@ from sverchok.utils.nurbs_common import SvNurbsBasisFunctions, SvNurbsMaths, fro
from
sverchok.utils.curve
import
knotvector
as
sv_knotvector
from
sverchok.utils.curve.algorithms
import
unify_curves_degree
from
sverchok.utils.decorators
import
deprecated
from
sverchok.utils.dictionary
import
SvApproxDict
from
sverchok.dependencies
import
scipy
if
scipy
is
not
None
:
...
...
@@ -32,16 +33,65 @@ def unify_degrees(curves):
curves
=
[
curve
.
elevate_degree
(
target
=
max_degree
)
for
curve
in
curves
]
return
curves
def
unify_curves
(
curves
,
method
=
'UNIFY'
):
class
KnotvectorDict
(
object
):
def
__init__
(
self
,
accuracy
):
self
.
multiplicities
=
[]
self
.
accuracy
=
accuracy
self
.
done_knots
=
set
()
self
.
skip_insertions
=
defaultdict
(
list
)
def
tolerance
(
self
):
return
10
**
(
-
self
.
accuracy
)
def
update
(
self
,
curve_idx
,
knot
,
multiplicity
):
found_idx
=
None
found_knot
=
None
for
idx
,
(
c
,
k
,
m
)
in
enumerate
(
self
.
multiplicities
):
if
curve_idx
!=
c
:
if
abs
(
knot
-
k
)
<
self
.
tolerance
():
print
(
f
"Found: #
{
curve_idx
}
: added
{
knot
}
~= existing
{
k
}
"
)
if
(
curve_idx
,
k
)
not
in
self
.
done_knots
:
found_idx
=
idx
found_knot
=
k
break
if
found_idx
is
not
None
:
self
.
multiplicities
[
found_idx
]
=
(
curve_idx
,
knot
,
multiplicity
)
self
.
skip_insertions
[
curve_idx
].
append
(
found_knot
)
else
:
self
.
multiplicities
.
append
((
curve_idx
,
knot
,
multiplicity
))
self
.
done_knots
.
add
((
curve_idx
,
knot
))
def
get
(
self
,
knot
):
result
=
0
for
c
,
k
,
m
in
self
.
multiplicities
:
if
abs
(
knot
-
k
)
<
self
.
tolerance
():
result
=
max
(
result
,
m
)
return
result
def
__repr__
(
self
):
items
=
[
f
"c#
{
c
}
:
{
k
}
:
{
m
}
"
for
c
,
k
,
m
in
self
.
multiplicities
]
s
=
", "
.
join
(
items
)
return
"{"
+
s
+
"}"
def
items
(
self
):
max_per_knot
=
defaultdict
(
int
)
for
c
,
k
,
m
in
self
.
multiplicities
:
max_per_knot
[
k
]
=
max
(
max_per_knot
[
k
],
m
)
keys
=
sorted
(
max_per_knot
.
keys
())
return
[(
key
,
max_per_knot
[
key
])
for
key
in
keys
]
def
unify_curves
(
curves
,
method
=
'UNIFY'
,
accuracy
=
6
):
tolerance
=
10
**
(
-
accuracy
)
curves
=
[
curve
.
reparametrize
(
0.0
,
1.0
)
for
curve
in
curves
]
if
method
==
'UNIFY'
:
dst_knots
=
defaultdict
(
int
)
for
curve
in
curves
:
m
=
sv_knotvector
.
to_multiplicity
(
curve
.
get_knotvector
())
dst_knots
=
KnotvectorDict
(
accuracy
)
for
i
,
curve
in
enumerate
(
curves
):
m
=
sv_knotvector
.
to_multiplicity
(
curve
.
get_knotvector
(),
tolerance
**
2
)
print
(
f
"Curve #
{
i
}
: degree=
{
curve
.
get_degree
()
}
, cpts=
{
len
(
curve
.
get_control_points
())
}
,
{
m
}
"
)
for
u
,
count
in
m
:
u
=
round
(
u
,
6
)
dst_knots
[
u
]
=
max
(
dst_knots
[
u
],
count
)
dst_knots
.
update
(
i
,
u
,
count
)
result
=
[]
# for i, curve1 in enumerate(curves):
...
...
@@ -50,22 +100,31 @@ def unify_curves(curves, method='UNIFY'):
# curve1 = curve1.to_knotvector(curve2)
# result.append(curve1)
for
curve
in
curves
:
for
idx
,
curve
in
enumerate
(
curves
)
:
diffs
=
[]
kv
=
np
.
round
(
curve
.
get_knotvector
(),
6
)
ms
=
dict
(
sv_knotvector
.
to_multiplicity
(
kv
))
#kv = np.round(curve.get_knotvector(), accuracy)
#curve = curve.copy(knotvector = kv)
print
(
'next curve'
,
curve
.
get_knotvector
())
ms
=
dict
(
sv_knotvector
.
to_multiplicity
(
curve
.
get_knotvector
(),
tolerance
**
2
))
for
dst_u
,
dst_multiplicity
in
dst_knots
.
items
():
src_multiplicity
=
ms
.
get
(
dst_u
,
0
)
diff
=
dst_multiplicity
-
src_multiplicity
print
(
f
"U =
{
dst_u
}
, was =
{
src_multiplicity
}
, need =
{
dst_multiplicity
}
, diff =
{
diff
}
"
)
diffs
.
append
((
dst_u
,
diff
))
#print(f"Src {ms}, dst {dst_knots} => diff {diffs}")
for
u
,
diff
in
diffs
:
if
diff
>
0
:
curve
=
curve
.
insert_knot
(
u
,
diff
)
if
u
in
dst_knots
.
skip_insertions
[
idx
]:
print
(
f
"C: skip insertion T =
{
u
}
"
)
else
:
#kv = curve.get_knotvector()
print
(
f
"C: Insert T =
{
u
}
x
{
diff
}
"
)
curve
=
curve
.
insert_knot
(
u
,
diff
)
result
.
append
(
curve
)
return
result
elif
method
==
'AVERAGE'
:
kvs
=
[
len
(
curve
.
get_control_points
())
for
curve
in
curves
]
max_kv
,
min_kv
=
max
(
kvs
),
min
(
kvs
)
...
...
utils/dictionary.py
Просмотр файла @
e7a8a690
...
...
@@ -5,6 +5,7 @@
# SPDX-License-Identifier: GPL3
# License-Filename: LICENSE
import
numpy
as
np
from
itertools
import
zip_longest
class
SvDict
(
dict
):
...
...
@@ -135,3 +136,76 @@ class SvDict(dict):
types
[
i
]
=
'SvStringsSocket'
return
types
class
SvApproxDict
(
object
):
def
__init__
(
self
,
pairs
=
None
,
precision
=
6
):
self
.
precision
=
precision
self
.
keys
=
np
.
array
([])
self
.
values
=
np
.
array
([])
if
pairs
is
not
None
:
for
key
,
value
in
pairs
:
self
[
key
]
=
value
def
tolerance
(
self
):
return
10
**
(
-
self
.
precision
)
def
__repr__
(
self
):
items
=
[
f
"
{
key
}
:
{
value
}
"
for
key
,
value
in
zip
(
self
.
keys
,
self
.
values
)]
s
=
", "
.
join
(
items
)
return
"{"
+
s
+
"}"
def
__setitem__
(
self
,
key
,
value
):
if
len
(
self
.
keys
)
==
0
:
self
.
keys
=
np
.
array
([
key
])
self
.
values
=
np
.
array
([
value
])
return
i
=
self
.
keys
.
searchsorted
(
key
)
if
i
>
0
:
smaller
=
self
.
keys
[
i
-
1
]
else
:
smaller
=
None
if
i
<
len
(
self
.
keys
):
greater
=
self
.
keys
[
i
]
else
:
greater
=
None
if
smaller
is
not
None
and
(
key
-
smaller
)
<
self
.
tolerance
():
#self.keys[i-1] = 0.5*(key + self.keys[i-1])
self
.
values
[
i
-
1
]
=
value
return
if
greater
is
not
None
and
(
greater
-
key
)
<
self
.
tolerance
():
#self.keys[i] = 0.5*(key + self.keys[i])
self
.
values
[
i
]
=
value
return
self
.
keys
=
np
.
insert
(
self
.
keys
,
i
,
key
)
self
.
values
=
np
.
insert
(
self
.
values
,
i
,
value
)
def
get
(
self
,
key
,
default
=
None
):
if
len
(
self
.
keys
)
==
0
:
return
default
i
=
self
.
keys
.
searchsorted
(
key
)
if
i
>
0
:
smaller
=
self
.
keys
[
i
-
1
]
if
(
key
-
smaller
)
<
self
.
tolerance
():
return
self
.
values
[
i
-
1
]
if
i
<
len
(
self
.
keys
):
greater
=
self
.
keys
[
i
]
if
(
greater
-
key
)
<
self
.
tolerance
():
return
self
.
values
[
i
]
return
default
def
__getitem__
(
self
,
key
):
value
=
self
.
get
(
key
,
None
)
if
value
is
None
:
raise
KeyError
(
"Key not found"
)
return
value
def
items
(
self
):
return
zip
(
self
.
keys
,
self
.
values
)
utils/surface/algorithms.py
Просмотр файла @
e7a8a690
...
...
@@ -1175,7 +1175,7 @@ def unify_nurbs_surfaces(surfaces, knots_method = 'UNIFY', knotvector_accuracy=6
for
u
,
diff
in
diffs_u
:
if
diff
>
0
:
#
print(f"Insert U = {u} x {diff}")
print
(
f
"
S:
Insert U =
{
u
}
x
{
diff
}
"
)
surface
=
surface
.
insert_knot
(
SvNurbsSurface
.
U
,
u
,
diff
)
diffs_v
=
[]
...
...
@@ -1188,7 +1188,7 @@ def unify_nurbs_surfaces(surfaces, knots_method = 'UNIFY', knotvector_accuracy=6
for
v
,
diff
in
diffs_v
:
if
diff
>
0
:
#
print(f"Insert V = {v} x {diff}")
print
(
f
"
S:
Insert V =
{
v
}
x
{
diff
}
"
)
surface
=
surface
.
insert_knot
(
SvNurbsSurface
.
V
,
v
,
diff
)
result
.
append
(
surface
)
...
...
utils/surface/gordon.py
Просмотр файла @
e7a8a690
...
...
@@ -53,10 +53,10 @@ def gordon_surface(u_curves, v_curves, intersections, metric='POINTS', u_knots=N
else
:
loft_u_kwargs
=
loft_v_kwargs
=
interpolate_kwargs
=
{
'metric'
:
metric
}
u_curves
=
unify_curves_degree
(
u_curves
)
u_curves
=
unify_curves
(
u_curves
)
#, method='AVERAGE')
v_curves
=
unify_curves_degree
(
v_curves
)
v_curves
=
unify_curves
(
v_curves
)
#, method='AVERAGE')
#
u_curves = unify_curves_degree(u_curves)
#
u_curves = unify_curves(u_curves
, accuracy=knotvector_accuracy
)#, method='AVERAGE')
#
v_curves = unify_curves_degree(v_curves)
#
v_curves = unify_curves(v_curves
, accuracy=knotvector_accuracy
)#, method='AVERAGE')
u_curves_degree
=
u_curves
[
0
].
get_degree
()
v_curves_degree
=
v_curves
[
0
].
get_degree
()
...
...
@@ -66,8 +66,8 @@ def gordon_surface(u_curves, v_curves, intersections, metric='POINTS', u_knots=N
loft_v_degree
=
min
(
len
(
u_curves
)
-
1
,
v_curves_degree
)
loft_u_degree
=
min
(
len
(
v_curves
)
-
1
,
u_curves_degree
)
_
,
_
,
lofted_v
=
simple_loft
(
u_curves
,
degree_v
=
loft_v_degree
,
**
loft_v_kwargs
)
_
,
_
,
lofted_u
=
simple_loft
(
v_curves
,
degree_v
=
loft_u_degree
,
**
loft_u_kwargs
)
_
,
_
,
lofted_v
=
simple_loft
(
u_curves
,
degree_v
=
loft_v_degree
,
knotvector_accuracy
=
knotvector_accuracy
,
**
loft_v_kwargs
)
_
,
_
,
lofted_u
=
simple_loft
(
v_curves
,
degree_v
=
loft_u_degree
,
knotvector_accuracy
=
knotvector_accuracy
,
**
loft_u_kwargs
)
lofted_u
=
lofted_u
.
swap_uv
()
int_degree_u
=
min
(
m
-
1
,
u_curves_degree
)
...
...
utils/surface/nurbs.py
Просмотр файла @
e7a8a690
...
...
@@ -787,7 +787,7 @@ def build_from_curves(curves, degree_u = None, implementation = SvNurbsSurface.N
return
curves
,
surface
def
simple_loft
(
curves
,
degree_v
=
None
,
knots_u
=
'UNIFY'
,
metric
=
'DISTANCE'
,
tknots
=
None
,
implementation
=
SvNurbsSurface
.
NATIVE
):
def
simple_loft
(
curves
,
degree_v
=
None
,
knots_u
=
'UNIFY'
,
knotvector_accuracy
=
6
,
metric
=
'DISTANCE'
,
tknots
=
None
,
implementation
=
SvNurbsSurface
.
NATIVE
):
"""
Loft between given NURBS curves (a.k.a skinning).
...
...
@@ -809,7 +809,7 @@ def simple_loft(curves, degree_v = None, knots_u = 'UNIFY', metric='DISTANCE', t
curve_class
=
type
(
curves
[
0
])
curves
=
unify_curves_degree
(
curves
)
if
knots_u
==
'UNIFY'
:
curves
=
unify_curves
(
curves
)
curves
=
unify_curves
(
curves
,
accuracy
=
knotvector_accuracy
)
else
:
kvs
=
[
len
(
curve
.
get_control_points
())
for
curve
in
curves
]
max_kv
,
min_kv
=
max
(
kvs
),
min
(
kvs
)
...
...
@@ -824,6 +824,7 @@ def simple_loft(curves, degree_v = None, knots_u = 'UNIFY', metric='DISTANCE', t
raise
Exception
(
f
"V degree (
{
degree_v
}
) must be not greater than number of curves (
{
len
(
curves
)
}
) minus 1"
)
src_points
=
[
curve
.
get_homogenous_control_points
()
for
curve
in
curves
]
print
(
"P"
,
[
p
.
shape
for
p
in
src_points
])
# lens = [len(pts) for pts in src_points]
# max_len, min_len = max(lens), min(lens)
# if max_len != min_len:
...
...
Редактирование
Предварительный просмотр
Поддерживает Markdown
0%
Попробовать снова
или
прикрепить новый файл
.
Отмена
You are about to add
0
people
to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Отмена
Пожалуйста,
зарегистрируйтесь
или
войдите
чтобы прокомментировать