Skip to content

Commit

Permalink
Adding documentation about how Fortran Status-es are used.
Browse files Browse the repository at this point in the history
  • Loading branch information
dhermes committed Nov 17, 2017
1 parent 0426c92 commit c2accf7
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 17 deletions.
55 changes: 43 additions & 12 deletions src/bezier/curve_intersection.f90
Expand Up @@ -16,7 +16,7 @@ module curve_intersection
use types, only: dp
use status, only: &
Status_SUCCESS, Status_PARALLEL, Status_WIGGLE_FAIL, &
Status_NO_CONVERGE, Status_TOO_SMALL
Status_NO_CONVERGE, Status_INSUFFICIENT_SPACE
use helpers, only: &
VECTOR_CLOSE_EPS, cross_product, bbox, wiggle_interval, &
vector_close, in_interval, ulps_away
Expand Down Expand Up @@ -255,6 +255,16 @@ subroutine from_linearized( &
refined_s, refined_t, does_intersect, status) &
bind(c, name='from_linearized')

! Possible error states:
! * Status_SUCCESS : On success.
! * Status_PARALLEL : If ``segment_intersection()`` fails (which means
! the linearized segments are parallel). This
! can still be avoided if the "root" curves are
! also (parallel) lines that don't overlap or if
! the "root" curves have disjoint bounding boxes.
! * Status_WIGGLE_FAIL: If the s- or t-parameter are too far outside of
! [0, 1] to be "wiggled" into it.

real(c_double), intent(in) :: error1, start1, end1
real(c_double), intent(in) :: start_node1(1, 2)
real(c_double), intent(in) :: end_node1(1, 2)
Expand Down Expand Up @@ -311,7 +321,6 @@ subroutine from_linearized( &
end if
end if

! Expect the wrapper code to raise.
status = Status_PARALLEL
return
end if
Expand Down Expand Up @@ -495,6 +504,11 @@ subroutine add_from_linearized( &
!
! NOTE: This is **explicitly** not intended for C inter-op.

! Possible error states:
! * Status_SUCCESS : On success.
! * Status_PARALLEL : Via ``from_linearized()``.
! * Status_WIGGLE_FAIL: Via ``from_linearized()``.

type(CurveData), intent(in) :: first
real(c_double), intent(in) :: root_nodes1(:, :)
real(c_double), intent(in) :: linearization_error1
Expand Down Expand Up @@ -681,6 +695,11 @@ subroutine intersect_one_round( &
! NOTE: This assumes, but does not check, that ``candidates`` has
! two rows and has at **least** ``num_candidates`` columns.

! Possible error states:
! * Status_SUCCESS : On success.
! * Status_PARALLEL : Via ``add_from_linearized()``.
! * Status_WIGGLE_FAIL: Via ``add_from_linearized()``.

real(c_double), intent(in) :: root_nodes_first(:, :)
real(c_double), intent(in) :: root_nodes_second(:, :)
integer(c_int), intent(in) :: num_candidates
Expand Down Expand Up @@ -800,6 +819,15 @@ subroutine all_intersections( &
! NOTE: This is **explicitly** not intended for C inter-op, but
! a C compatible interface is exposed as ``all_intersections_abi``.

! Possible error states:
! * Status_SUCCESS : On success.
! * Status_PARALLEL : Via ``intersect_one_round()``.
! * Status_WIGGLE_FAIL: Via ``intersect_one_round()``.
! * Status_NO_CONVERGE: If the curves don't converge to linear after
! ``MAX_INTERSECT_SUBDIVISIONS``.
! * (N >= 64) : The number of candidates if it exceeds the limit
! ``MAX_CANDIDATES == 64``.

integer(c_int), intent(in) :: num_nodes_first
real(c_double), intent(in) :: nodes_first(num_nodes_first, 2)
integer(c_int), intent(in) :: num_nodes_second
Expand Down Expand Up @@ -844,15 +872,9 @@ subroutine all_intersections( &
! NOTE: This only checks for two error statuses from
! ``intersect_one_round()``, so it is inherently brittle
! to changes there.
if (intersect_status == Status_PARALLEL) then
status = Status_PARALLEL
if (intersect_status /= Status_SUCCESS) then
status = intersect_status
return
else if (intersect_status == Status_WIGGLE_FAIL) then
! NOTE: We exclude this block from testing because it's
! quite difficult to come up with an example that
! causes it.
status = Status_WIGGLE_FAIL ! LCOV_EXCL_LINE
return ! LCOV_EXCL_LINE
end if

! Update the number of candidates.
Expand Down Expand Up @@ -890,10 +912,19 @@ subroutine all_intersections_abi( &
! by Bezout's theorem). If ``intersections`` is not large enough
! (i.e. if ``intersections_size`` < num_intersections``), then
! ``intersections`` will not be populated and the ``status`` will be
! set to ``Status_TOO_SMALL``. However, the value of
! set to ``Status_INSUFFICIENT_SPACE``. However, the value of
! ``num_intersections`` will be accurate and ``intersections``
! should be re-sized by the caller to accommodate.

! Possible error states:
! * Status_SUCCESS : On success.
! * Status_PARALLEL : Via ``all_intersections()``.
! * Status_WIGGLE_FAIL : Via ``all_intersections()``.
! * Status_NO_CONVERGE : Via ``all_intersections()``.
! * Status_INSUFFICIENT_SPACE: If ``intersections_size`` is smaller than
! the number of intersections.
! * (N >= 64) : Via ``all_intersections()``.

integer(c_int), intent(in) :: num_nodes_first
real(c_double), intent(in) :: nodes_first(num_nodes_first, 2)
integer(c_int), intent(in) :: num_nodes_second
Expand All @@ -912,7 +943,7 @@ subroutine all_intersections_abi( &
end if

if (num_intersections > intersections_size) then
status = Status_TOO_SMALL
status = Status_INSUFFICIENT_SPACE
else if (num_intersections > 0) then
! NOTE: This assumes, but doesn't check that
! ``INTERSECTIONS_WORKSPACE`` has been allocated
Expand Down
21 changes: 18 additions & 3 deletions src/bezier/status.f90
Expand Up @@ -17,19 +17,34 @@ module status
private
public &
Status_SUCCESS, Status_PARALLEL, Status_WIGGLE_FAIL, &
Status_NO_CONVERGE, Status_TOO_SMALL, Status_SAME_CURVATURE, &
Status_NO_CONVERGE, Status_INSUFFICIENT_SPACE, Status_SAME_CURVATURE, &
Status_BAD_TANGENT, Status_EDGE_END

! Values of Status enum:
! SUCCESS: Procedure exited with no error.
integer(c_int), parameter :: Status_SUCCESS = 0
! PARALLEL: Corresponds to ``NotImplementedError('Line segments parallel.')``
integer(c_int), parameter :: Status_PARALLEL = 1
! WIGGLE_FAIL: Indicates that ``wiggle_interval`` failed.
! WIGGLE_FAIL: Indicates that ``helpers.wiggle_interval()`` failed.
integer(c_int), parameter :: Status_WIGGLE_FAIL = 2
! NO_CONVERGE: An iterative algorithm has failed to converge. Used by
! ``curve_intersection.all_intersections()``.
integer(c_int), parameter :: Status_NO_CONVERGE = 3
integer(c_int), parameter :: Status_TOO_SMALL = 4
! INSUFFICIENT_SPACE: Intended to be used by ABI versions of procedures. Will
! be used when the caller has not allocated enough space
! for the output values. (On the Fortran side, an
! ``allocatable`` array can be resized, but in the ABI,
! we can only use what the caller has passed.)
integer(c_int), parameter :: Status_INSUFFICIENT_SPACE = 4
! SAME_CURVATURE: Can't classify curve-curve intersection when the curves
! have identical curvature at the point of intersection.
integer(c_int), parameter :: Status_SAME_CURVATURE = 5
! BAD_TANGENT: Two curves are tangent where they intersect, but they move
! in an opposite direction while defining overlapping arcs.
integer(c_int), parameter :: Status_BAD_TANGENT = 6
! EDGE_END: A surface-surface intersection point occurs at the **end** of
! an edge (only intersections at the beginning of an edge should
! be used).
integer(c_int), parameter :: Status_EDGE_END = 7

end module status
5 changes: 3 additions & 2 deletions tests/fortran/test_curve_intersection.f90
Expand Up @@ -14,7 +14,8 @@ module test_curve_intersection

use, intrinsic :: iso_c_binding, only: c_bool, c_double, c_int
use status, only: &
Status_SUCCESS, Status_PARALLEL, Status_NO_CONVERGE, Status_TOO_SMALL
Status_SUCCESS, Status_PARALLEL, Status_NO_CONVERGE, &
Status_INSUFFICIENT_SPACE
use curve, only: &
CurveData, evaluate_multi, subdivide_nodes, curves_equal, &
subdivide_curve
Expand Down Expand Up @@ -1714,7 +1715,7 @@ subroutine test_all_intersections_abi(success)
num_intersections, status)
case_success = ( &
num_intersections == 3 .AND. &
status == Status_TOO_SMALL)
status == Status_INSUFFICIENT_SPACE)
call print_status(name, case_id, case_success, success)

! CASE 3: Just case 7, but with large enough ``intersections``.
Expand Down

0 comments on commit c2accf7

Please sign in to comment.