Skip to content

Commit

Permalink
Removing true_(start|end) and curve_(start|end) from `specialize_…
Browse files Browse the repository at this point in the history
…curve()`.

This is no longer needed (it was present when `start` and `end` were
tracked on `Curve` instances in Python).
  • Loading branch information
dhermes committed Jan 11, 2018
1 parent 4a44ef8 commit 959c547
Show file tree
Hide file tree
Showing 10 changed files with 576 additions and 690 deletions.
3 changes: 1 addition & 2 deletions src/bezier/_curve.pxd
Expand Up @@ -25,8 +25,7 @@ cdef extern from "bezier/curve.h":
int *num_vals, double *s_vals, double *evaluated)
void specialize_curve(
int *num_nodes, int *dimension, double *nodes,
double *start, double *end, double *curve_start, double *curve_end,
double *new_nodes, double *true_start, double *true_end)
double *start, double *end, double* new_nodes)
void evaluate_hodograph(
double *s, int *num_nodes, int *dimension, double *nodes,
double *hodograph)
Expand Down
15 changes: 3 additions & 12 deletions src/bezier/_curve_helpers.py
Expand Up @@ -427,7 +427,7 @@ def de_casteljau_one_round(nodes, lambda1, lambda2):
lambda1 * nodes[:-1, :] + lambda2 * nodes[1:, :])


def _specialize_curve(nodes, start, end, curve_start, curve_end):
def _specialize_curve(nodes, start, end):
"""Specialize a curve to a re-parameterization
Does so by taking two points along the number line and then
Expand All @@ -447,15 +447,9 @@ def _specialize_curve(nodes, start, end, curve_start, curve_end):
nodes (numpy.ndarray): Control points for a curve.
start (float): The start point of the interval we are specializing to.
end (float): The end point of the interval we are specializing to.
curve_start (float): The beginning of the original interval which the
the curve defined by ``nodes`` defines.
curve_end (float): The end of the original interval which the
the curve defined by ``nodes`` defines.
Returns:
Tuple[numpy.ndarray, float, float]: The control points for the
specialized curve, as well as the true start and true end of the
newly created curve.
numpy.ndarray: The control points for the specialized curve.
"""
# pylint: disable=too-many-locals
num_nodes, _ = np.shape(nodes)
Expand Down Expand Up @@ -486,10 +480,7 @@ def _specialize_curve(nodes, start, end, curve_start, curve_end):
key = (0,) * (num_nodes - index - 1) + (1,) * index
result[index, :] = partial_vals[key]

interval_delta = curve_end - curve_start
true_start = curve_start + start * interval_delta
true_end = curve_start + end * interval_delta
return result, true_start, true_end
return result
# pylint: enable=too-many-locals


Expand Down
1,143 changes: 546 additions & 597 deletions src/bezier/_curve_speedup.c

Large diffs are not rendered by default.

11 changes: 2 additions & 9 deletions src/bezier/_curve_speedup.pyx
Expand Up @@ -72,11 +72,8 @@ def evaluate_multi(
return evaluated


def specialize_curve(
double[::1, :] nodes, double start, double end,
double curve_start, double curve_end):
def specialize_curve(double[::1, :] nodes, double start, double end):
cdef int num_nodes, dimension
cdef double true_start, true_end
cdef ndarray_t[double, ndim=2, mode='fortran'] new_nodes

num_nodes, dimension = np.shape(nodes)
Expand All @@ -88,14 +85,10 @@ def specialize_curve(
&nodes[0, 0],
&start,
&end,
&curve_start,
&curve_end,
&new_nodes[0, 0],
&true_start,
&true_end,
)

return new_nodes, true_start, true_end
return new_nodes


def evaluate_hodograph(double s, double[::1, :] nodes):
Expand Down
13 changes: 2 additions & 11 deletions src/bezier/curve.f90
Expand Up @@ -232,17 +232,13 @@ subroutine specialize_curve_quadratic( &
end subroutine specialize_curve_quadratic

subroutine specialize_curve( &
num_nodes, dimension_, nodes, start, end_, curve_start, curve_end, &
new_nodes, true_start, true_end) &
num_nodes, dimension_, nodes, start, end_, new_nodes) &
bind(c, name='specialize_curve')

integer(c_int), intent(in) :: num_nodes, dimension_
real(c_double), intent(in) :: nodes(num_nodes, dimension_)
real(c_double), intent(in) :: start, end_, curve_start, curve_end
real(c_double), intent(in) :: start, end_
real(c_double), intent(out) :: new_nodes(num_nodes, dimension_)
real(c_double), intent(out) :: true_start, true_end
! Variables outside of signature.
real(c_double) :: interval_delta

if (num_nodes == 2) then
new_nodes(1, :) = (1.0_dp - start) * nodes(1, :) + start * nodes(2, :)
Expand All @@ -255,11 +251,6 @@ subroutine specialize_curve( &
num_nodes, dimension_, nodes, start, end_, new_nodes)
end if

! Now, compute the new interval.
interval_delta = curve_end - curve_start
true_start = curve_start + start * interval_delta
true_end = curve_start + end_ * interval_delta

end subroutine specialize_curve

subroutine evaluate_hodograph( &
Expand Down
3 changes: 1 addition & 2 deletions src/bezier/curve.py
Expand Up @@ -604,8 +604,7 @@ def specialize(self, start, end):
Returns:
Curve: The newly-specialized curve.
"""
new_nodes, _, _ = _curve_helpers.specialize_curve(
self._nodes, start, end, 0.0, 1.0)
new_nodes = _curve_helpers.specialize_curve(self._nodes, start, end)
return Curve(new_nodes, self._degree, _copy=False)

def locate(self, point):
Expand Down
3 changes: 1 addition & 2 deletions src/bezier/include/bezier/curve.h
Expand Up @@ -27,8 +27,7 @@ void evaluate_multi(
int *num_vals, double *s_vals, double *evaluated);
void specialize_curve(
int *num_nodes, int *dimension, double *nodes,
double *start, double *end, double *curve_start, double *curve_end,
double *new_nodes, double *true_start, double *true_end);
double *start, double *end, double *new_nodes);
void evaluate_hodograph(
double *s, int *num_nodes, int *dimension, double *nodes,
double *hodograph);
Expand Down
3 changes: 1 addition & 2 deletions src/bezier/surface.py
Expand Up @@ -1127,8 +1127,7 @@ def _make_intersection(edge_info, all_edge_nodes):
edges = []
for index, start, end in edge_info:
nodes = all_edge_nodes[index]
new_nodes, _, _ = _curve_helpers.specialize_curve(
nodes, start, end, 0.0, 1.0)
new_nodes = _curve_helpers.specialize_curve(nodes, start, end)
degree = new_nodes.shape[0] - 1
edge = _curve_mod.Curve(new_nodes, degree, _copy=False)
edges.append(edge)
Expand Down
35 changes: 10 additions & 25 deletions tests/fortran/test_curve.f90
Expand Up @@ -136,7 +136,6 @@ subroutine test_specialize_curve(success)
logical(c_bool), intent(inout) :: success
! Variables outside of signature.
logical :: case_success
real(c_double) :: true_start, true_end
real(c_double) :: nodes1(2, 2)
real(c_double) :: new_nodes1(2, 2), expected1(2, 2)
real(c_double) :: nodes2(3, 2), left_nodes(3, 2), right_nodes(3, 2)
Expand All @@ -155,11 +154,8 @@ subroutine test_specialize_curve(success)
expected1(1, :) = [0.25_dp, 0.25_dp]
expected1(2, :) = [0.75_dp, 0.75_dp]
call specialize_curve( &
2, 2, nodes1, 0.25_dp, 0.75_dp, 0.125_dp, 0.25_dp, &
new_nodes1, true_start, true_end)
case_success = ( &
all(new_nodes1 == expected1) .AND. &
true_start == 0.15625_dp .AND. true_end == 0.21875_dp)
2, 2, nodes1, 0.25_dp, 0.75_dp, new_nodes1)
case_success = all(new_nodes1 == expected1)
call print_status(name, case_id, case_success, success)

! CASE 2: Quadratic curve, after subdivision.
Expand All @@ -169,19 +165,14 @@ subroutine test_specialize_curve(success)
call subdivide_nodes( &
3, 2, nodes2, left_nodes, right_nodes)
call specialize_curve( &
3, 2, nodes2, 0.0_dp, 0.5_dp, 0.0_dp, 1.0_dp, &
new_nodes2, true_start, true_end)
case_success = ( &
all(new_nodes2 == left_nodes) .AND. &
true_start == 0.0_dp .AND. true_end == 0.5_dp)
3, 2, nodes2, 0.0_dp, 0.5_dp, new_nodes2)
case_success = all(new_nodes2 == left_nodes)
! Do a "second" check for the right-hand nodes.
call specialize_curve( &
3, 2, nodes2, 0.5_dp, 1.0_dp, 0.0_dp, 1.0_dp, &
new_nodes2, true_start, true_end)
3, 2, nodes2, 0.5_dp, 1.0_dp, new_nodes2)
case_success = ( &
case_success .AND. &
all(new_nodes2 == right_nodes) .AND. &
true_start == 0.5_dp .AND. true_end == 1.0_dp)
all(new_nodes2 == right_nodes))
call print_status(name, case_id, case_success, success)

! CASE 3: Cubic curve.
Expand All @@ -194,11 +185,8 @@ subroutine test_specialize_curve(success)
expected3(3, :) = [499.0_dp, -579.0_dp] / 512.0_dp
expected3(4, :) = [735.0_dp, -335.0_dp] / 512.0_dp
call specialize_curve( &
4, 2, nodes3, 0.125_dp, 0.625_dp, 0.0_dp, 1.0_dp, &
new_nodes3, true_start, true_end)
case_success = ( &
all(new_nodes3 == expected3) .AND. &
true_start == 0.125_dp .AND. true_end == 0.625_dp)
4, 2, nodes3, 0.125_dp, 0.625_dp, new_nodes3)
case_success = all(new_nodes3 == expected3)
call print_status(name, case_id, case_success, success)

! CASE 4: Quartic curve.
Expand All @@ -213,12 +201,9 @@ subroutine test_specialize_curve(success)
expected4(4, :) = [2.2578125_dp, 6.484375_dp]
expected4(5, :) = [2.47265625_dp, 6.5234375_dp]
call specialize_curve( &
5, 2, nodes4, 0.5_dp, 0.75_dp, 0.0_dp, 1.0_dp, &
new_nodes4, true_start, true_end)
5, 2, nodes4, 0.5_dp, 0.75_dp, new_nodes4)

case_success = ( &
all(new_nodes4 == expected4) .AND. &
true_start == 0.5_dp .AND. true_end == 0.75_dp)
case_success = all(new_nodes4 == expected4)
call print_status(name, case_id, case_success, success)

end subroutine test_specialize_curve
Expand Down
37 changes: 9 additions & 28 deletions tests/unit/test__curve_helpers.py
Expand Up @@ -479,27 +479,22 @@ def test_it(self):
class Test__specialize_curve(utils.NumPyTestCase):

@staticmethod
def _call_function_under_test(
nodes, start, end, curve_start, curve_end):
def _call_function_under_test(nodes, start, end):
from bezier import _curve_helpers

return _curve_helpers._specialize_curve(
nodes, start, end, curve_start, curve_end)
return _curve_helpers._specialize_curve(nodes, start, end)

def test_linear(self):
nodes = np.asfortranarray([
[0.0, 0.0],
[1.0, 1.0],
])
result, true_start, true_end = self._call_function_under_test(
nodes, 0.25, 0.75, 0.125, 0.25)
result = self._call_function_under_test(nodes, 0.25, 0.75)
expected = np.asfortranarray([
[0.25, 0.25],
[0.75, 0.75],
])
self.assertEqual(result, expected)
self.assertEqual(true_start, 0.15625)
self.assertEqual(true_end, 0.21875)

def test_against_subdivision(self):
import bezier
Expand All @@ -512,17 +507,11 @@ def test_against_subdivision(self):
curve = bezier.Curve(nodes, 2)
left, right = curve.subdivide()

left_nodes, true_start, true_end = self._call_function_under_test(
nodes, 0.0, 0.5, 0.0, 1.0)
left_nodes = self._call_function_under_test(nodes, 0.0, 0.5)
self.assertEqual(left.nodes, left_nodes)
self.assertEqual(true_start, 0.0)
self.assertEqual(true_end, 0.5)

right_nodes, true_start, true_end = self._call_function_under_test(
nodes, 0.5, 1.0, 0.0, 1.0)
right_nodes = self._call_function_under_test(nodes, 0.5, 1.0)
self.assertEqual(right.nodes, right_nodes)
self.assertEqual(true_start, 0.5)
self.assertEqual(true_end, 1.0)

def test_cubic(self):
nodes = np.asfortranarray([
Expand All @@ -531,17 +520,14 @@ def test_cubic(self):
[1.0, -2.0],
[3.0, 2.0],
])
result, true_start, true_end = self._call_function_under_test(
nodes, 0.125, 0.625, 0.0, 1.0)
result = self._call_function_under_test(nodes, 0.125, 0.625)
expected = np.asfortranarray([
[171, -187],
[375, -423],
[499, -579],
[735, -335],
], dtype=FLOAT64) / 512.0
self.assertEqual(result, expected)
self.assertEqual(true_start, 0.125)
self.assertEqual(true_end, 0.625)

def test_quartic(self):
nodes = np.asfortranarray([
Expand All @@ -551,8 +537,7 @@ def test_quartic(self):
[3.0, 6.0],
[3.0, 7.0],
])
result, true_start, true_end = self._call_function_under_test(
nodes, 0.5, 0.75, 0.0, 1.0)
result = self._call_function_under_test(nodes, 0.5, 0.75)
expected = np.asfortranarray([
[1.5625, 6.375],
[1.78125, 6.4375],
Expand All @@ -561,20 +546,16 @@ def test_quartic(self):
[2.47265625, 6.5234375],
])
self.assertEqual(result, expected)
self.assertEqual(true_start, 0.5)
self.assertEqual(true_end, 0.75)


@utils.needs_curve_speedup
class Test_speedup_specialize_curve(Test__specialize_curve):

@staticmethod
def _call_function_under_test(
nodes, start, end, curve_start, curve_end):
def _call_function_under_test(nodes, start, end):
from bezier import _curve_speedup

return _curve_speedup.specialize_curve(
nodes, start, end, curve_start, curve_end)
return _curve_speedup.specialize_curve(nodes, start, end)


class Test__evaluate_hodograph(utils.NumPyTestCase):
Expand Down

0 comments on commit 959c547

Please sign in to comment.