Коммит c5568211 создал по автору Ilya Portnov's avatar Ilya Portnov
Просмотр файлов

Knotvector insert / remove testing.

владелец e7a8a690
......@@ -418,6 +418,76 @@ class OtherNurbsTests(SverchokTestCase):
result = inserted.evaluate_array(ts)
self.assert_numpy_arrays_equal(result, expected)
#@unittest.skip
def test_remove_1(self):
points = np.array([[0, 0, 0], [1, 1, 0], [2, 1, 0], [3, 0, 0]])
degree = 3
kv = np.array([0, 0, 0, 0, 1, 1, 1, 1], dtype=np.float64)
weights = [1, 1, 1, 1]
curve = SvNativeNurbsCurve(degree, kv, points, weights)
kv_err = sv_knotvector.check(degree, kv, len(points))
if kv_err is not None:
raise Exception(kv_err)
knot = 0.5
inserted = curve.insert_knot(knot, 2)
self.assertEquals(len(inserted.get_control_points()), len(points)+2)
expected_inserted_kv = np.array([0, 0, 0, 0, 0.5, 0.5, 1, 1, 1, 1])
inserted_kv = inserted.get_knotvector()
self.assert_numpy_arrays_equal(inserted_kv, expected_inserted_kv)
removed = inserted.remove_knot(knot, 1)
expected_removed_kv = np.array([0, 0, 0, 0, 0.5, 1, 1, 1, 1])
self.assert_numpy_arrays_equal(removed.get_knotvector(), expected_removed_kv)
removed2 = removed.remove_knot(knot, 1)
expected_removed_kv = np.array([0, 0, 0, 0, 1, 1, 1, 1])
self.assert_numpy_arrays_equal(removed2.get_knotvector(), expected_removed_kv)
def test_remove_2(self):
points = np.array([[0, 0, 0],
[0, 1, 0],
[1, 2, 0],
[2, 2, 0],
[3, 1, 0],
[3, 0, 0]], dtype=np.float64)
degree = 3
kv = np.array([0, 0, 0, 0, 0.25, 0.75, 1, 1, 1, 1])
weights = [1, 1, 1, 1, 1, 1]
curve = SvNativeNurbsCurve(degree, kv, points, weights)
kv_err = sv_knotvector.check(degree, kv, len(points))
if kv_err is not None:
raise Exception(kv_err)
knot = 0.1
inserted = curve.insert_knot(knot, 1)
self.assertEquals(len(inserted.get_control_points()), len(points)+1)
expected_inserted_kv = np.array([0, 0, 0, 0, 0.1, 0.25, 0.75, 1, 1, 1, 1])
self.assert_numpy_arrays_equal(inserted.get_knotvector(), expected_inserted_kv)
inserted_kv = inserted.get_knotvector()
k = np.searchsorted(inserted_kv, knot, side='right')-1
s = sv_knotvector.find_multiplicity(inserted_kv, knot)
print("K:", k, "S:", s)
removed = inserted.remove_knot(knot, 1)
self.assert_numpy_arrays_equal(removed.get_knotvector(), kv)
#@unittest.skip
def test_remove_geomdl_1(self):
points = np.array([[0, 0, 0], [1, 1, 0], [2, 0, 0]])
degree = 2
kv = sv_knotvector.generate(degree,3)
weights = [1, 1, 1]
curve = SvGeomdlCurve.build_geomdl(degree, kv, points, weights)
inserted = curve.insert_knot(0.5, 1)
expected_inserted_kv = np.array([0, 0, 0, 0.5, 1, 1, 1])
self.assert_numpy_arrays_equal(inserted.get_knotvector(), expected_inserted_kv)
removed = inserted.remove_knot(0.5, 1)
self.assert_numpy_arrays_equal(removed.get_knotvector(), kv)
def test_split_1(self):
points = np.array([[0, 0, 0], [1, 0, 0]])
kv = sv_knotvector.generate(1,2)
......@@ -518,6 +588,31 @@ class OtherNurbsTests(SverchokTestCase):
expected_pt2 = curve.evaluate(0.75)
self.assert_numpy_arrays_equal(pt2, expected_pt2, precision=4)
def test_split_5(self):
points = np.array([[0, 0, 0],
[0, 1, 0],
[1, 2, 0],
[2, 2, 0],
[3, 1, 0],
[3, 0, 0]])
weights = [1, 1, 1, 1, 1, 1]
degree = 3
knotvector = np.array([0, 0, 0, 0, 0.25, 0.75, 1, 1, 1, 1])
#print("KV", knotvector)
curve = SvNativeNurbsCurve(degree, knotvector, points, weights)
t0 = knotvector[4] # 0.25
curve1, curve2 = curve.split_at(t0)
expected_kv1 = np.array([0, 0, 0, 0, 0.25, 0.25, 0.25, 0.25])
expected_kv2 = np.array([0.25, 0.25, 0.25, 0.25, 0.75, 1, 1, 1, 1])
self.assert_numpy_arrays_equal(curve1.get_knotvector(), expected_kv1)
self.assert_numpy_arrays_equal(curve2.get_knotvector(), expected_kv2)
result = curve1.concatenate(curve2, remove_knots=True)
expected_result_kv = knotvector
self.assert_numpy_arrays_equal(result.get_knotvector(), expected_result_kv)
def test_single_1(self):
points = np.array([[0, 0, 0], [1, 1, 0], [2, 0, 0]])
kv = sv_knotvector.generate(2,3)
......
......@@ -68,6 +68,13 @@ def generate(degree, num_ctrlpts, clamped=True):
# Return auto-generated knot vector
return np.array(knot_vector)
def find_span(knot_vector, num_ctrlpts, knot):
span = 0 # Knot span index starts from zero
while span < num_ctrlpts and knot_vector[span] <= knot:
span += 1
return span - 1
def from_tknots(degree, tknots):
n = len(tknots)
#m = degree + n + 1
......
......@@ -126,7 +126,7 @@ class SvNurbsCurve(SvCurve):
def get_bounding_box(self):
return bounding_box(self.get_control_points())
def concatenate(self, curve2, tolerance=1e-6):
def concatenate(self, curve2, tolerance=1e-6, remove_knots=False):
curve1 = self
curve2 = SvNurbsCurve.to_nurbs(curve2)
if curve2 is None:
......@@ -177,8 +177,12 @@ class SvNurbsCurve(SvCurve):
weights = np.concatenate((curve1.get_weights(), curve2.get_weights()[1:]))
control_points = np.concatenate((curve1.get_control_points(), curve2.get_control_points()[1:]))
return SvNurbsCurve.build(self.get_nurbs_implementation(),
result = SvNurbsCurve.build(self.get_nurbs_implementation(),
p, knotvector, control_points, weights)
if remove_knots:
join_point = kv1[-1]
result = result.remove_knot(join_point, p-1)
return result
def lerp_to(self, curve2, coefficient):
curve1 = self
......@@ -684,11 +688,13 @@ class SvGeomdlCurve(SvNurbsCurve):
return surface
def insert_knot(self, u, count=1):
curve = operations.insert_knot(self.curve, [u], [count])
curve = self.copy()
curve = operations.insert_knot(curve.curve, [u], [count])
return SvGeomdlCurve(curve)
def remove_knot(self, u, count=1):
curve = operations.remove_knot(self.curve, [u], [count])
curve = self.copy()
curve = operations.remove_knot(curve.curve, [u], [count])
return SvGeomdlCurve(curve)
class SvNativeNurbsCurve(SvNurbsCurve):
......@@ -859,13 +865,14 @@ class SvNativeNurbsCurve(SvNurbsCurve):
def insert_knot(self, u_bar, count=1):
# "The NURBS book", 2nd edition, p.5.2, eq. 5.11
s = sv_knotvector.find_multiplicity(self.knotvector, u_bar)
N = len(self.control_points)
s = sv_knotvector.find_multiplicity(self.get_knotvector(), u_bar)
#print(f"I: kv {len(self.knotvector)}{self.knotvector}, u_bar {u_bar} => s {s}")
k = np.searchsorted(self.knotvector, u_bar, side='right')-1
#k = np.searchsorted(self.knotvector, u_bar, side='right')-1
k = sv_knotvector.find_span(self.knotvector, N, u_bar)
p = self.degree
u = self.knotvector
new_knotvector = sv_knotvector.insert(self.knotvector, u_bar, count)
N = len(self.control_points)
control_points = self.get_homogenous_control_points()
for r in range(1, count+1):
......@@ -907,9 +914,11 @@ class SvNativeNurbsCurve(SvNurbsCurve):
degree = self.get_degree()
knotvector = self.get_knotvector()
ctrlpts = self.get_homogenous_control_points().tolist()
N = len(ctrlpts)
s = sv_knotvector.find_multiplicity(knotvector, u)-1 # multiplicity
r = knotvector.searchsorted(u, side='right')- 1 # knot span
s = sv_knotvector.find_multiplicity(knotvector, u)#-1 # multiplicity
#r = knotvector.searchsorted(u, side='right')- 1 # knot span
r = sv_knotvector.find_span(self.knotvector, N, u)
# Edge case
if count < 1:
......@@ -927,6 +936,7 @@ class SvNativeNurbsCurve(SvNurbsCurve):
# Loop for Eqs 5.28 & 5.29
for t in range(0, count):
#print(f"T: {t} / {count}, first = {first}, last = {last}; N = {len(ctrlpts)}, degree = {degree}, r = {r}, s = {s}")
temp[0] = ctrlpts[first - 1]
temp[last - first + 2] = ctrlpts[last + 1]
i = first
......@@ -967,6 +977,9 @@ class SvNativeNurbsCurve(SvNurbsCurve):
ctrlpts_new[j] = temp[j - first + 1]
i += 1
j -= 1
else:
break
#raise Exception(f"Knot {u} can not be removed {count} times")
# Update indices
first -= 1
......@@ -993,7 +1006,9 @@ class SvNativeNurbsCurve(SvNurbsCurve):
ctrlpts_new = np.array(ctrlpts_new)
control_points, weights = from_homogenous(ctrlpts_new)
new_kv = np.delete(self.get_knotvector(), np.s_[(r-count):(r)])
new_kv = np.delete(self.get_knotvector(), np.s_[(r-t+1):(r+1)])
#print(f"R: r = {r}, t = {t}, N ctrlpts {len(ctrlpts_new)}")
#print(f" {self.get_knotvector()} => {new_kv}")
return self.copy(knotvector = new_kv, control_points = control_points, weights = weights)
......
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать