Bézier curves/Intersections: Difference between revisions

→‎{{header|ATS}}: Changes to make the program more robust against duplicates. Similar to what was done to the D and Modula-2. Also now the parameters are sorted.
(→‎{{header|Modula-2}}: Removed the stop after four intersections (it seems inadvisable, given there might be "near-intersections").)
(→‎{{header|ATS}}: Changes to make the program more robust against duplicates. Similar to what was done to the D and Modula-2. Also now the parameters are sorted.)
Line 228:
error_squared / tol <= length_squared * tol
end
 
(* One might be curious why "t@ype" instead of "type". The answer is:
the notation "type" is restricted to types that take up the same
space as a C void-pointer, which includes ATS pointers, "boxed"
types, etc. A "t@ype" can take up any amount of space, and so
includes any type there is (except for linear types, which is a
whole other subject). For instance, "int", "double", unboxed
records, unboxed tuples, and so on. *)
fun {a, b : t@ype} (* A polymorphic template function. *)
list_any (pred : (a, b) -<cloref1> bool,
inobj : a,
lst : List0 b)
: bool =
(* Does pred(obj, item) return true for any list item? Here the
<cloref1> notation means that pred is a CLOSURE of the ordinary
garbage-collected kind, such as functions tend implicitly to be
in Lisps, MLs, Haskell, etc. *)
case+ lst of
| NIL => false
| hd :: tl =>
if pred (obj, hd) then
true
else
list_any (pred, obj, tl)
 
fun
find_intersection_parameters
(px : @(double, double, double),
py : @(double, double, double),
qx : @(double, double, double),
qy : @(double, double, double),
tol : double),
: [m : nat | m <= 4]spacing list: (double, m) =
: List0 double =
let
val px = bernstein2spower_degree2 px
Line 242 ⟶ 267:
 
fun
within_spacing (t_candidate : double,
loop {n : nat | n <= 4}
t_in_list : double)
:<cloref1> bool =
abs (t_candidate - t_in_list) < spacing
 
fun
loop {n : nat | n <= 4}
(params : list (double, n),
n : int n,
workload : List0 (@(double, double)))
: [mList0 : nat | m <= 4] list (double, m) =
ifcase+ nworkload = 4 thenof
| NIL => params
else| hd :: tl =>
case+ workload oflet
| NIL val portionx => paramsspower_portion_degree2 (px, hd)
| hd ::and tlportiony => spower_portion_degree2 (py, hd)
letin
if flat_enough val (portionx, = spower_portion_degree2 (pxportiony, hdtol) then
and portiony = spower_portion_degree2 (py, hd)let
val solve_linear_quadratic (@(portionx0, _, portionx2), = portionx
in
if flat_enough and @(portionxportiony0, portiony_, tolportiony2) then= portiony
letval @(root0, root1) =
valsolve_linear_quadratic (@(portionx0, _, portionx2) = portionx,
and @(portiony0, _, portiony2) = portiony,
val @(root0 qx, root1qy) =
in
solve_linear_quadratic (@(portionx0, portionx2),
if 0.0 <= root0 && root0 <= 1.0 @(portiony0, portiony2),&&
~list_any (within_spacing, qxroot0, qyparams) then
in begin
if 0.0 <= root0root1 && root0root1 <= 1.0 then&&
begin ~list_any (within_spacing, root1, params) then
ifloop (nroot0 <:: 3)root1 *:: (0.0params, <=n root1+ &&2, root1 <= 1.0tl) then
loop (root0 :: root1 :: params, n + 2, tl)else
elseloop (root0 :: params, n + 1, tl)
loop (root0 :: params, n + 1, tl)end
else if 0.0 <= endroot1 && root1 <= 1.0 &&
else if 0.0 <= root1 && root1 <= 1.0~list_any (within_spacing, root1, params) then
loop (root1 :: params, n + 1, tl)
else
loop (params, n, tl)
end
else
let
val @(t0, t1) = hd
val tmiddle = (0.5 * t0) + (0.5 * t1)
val job1 = @(t0, tmiddle)
and job2 = @(tmiddle, t1)
in
loop (params, n, job1 :: job2 :: tl)
end
end
in
loop (NIL, 0, @(0.0, 1.0) :: NIL)
Line 300 ⟶ 331:
val qy = @(1.0, 2.0, 3.0)
val tol = 0.001 (* "Flatness ratio" *)
val t_listspacing = find_intersection_parameters0.0000001 (px,* Min. py,spacing qx,between qy,parameters. tol*)
val t_list = find_intersection_parameters (px, py, qx, qy,
tol, spacing)
 
(* For no particular reason, sort the intersections so they go
from top to bottom. *)
val t_list = list_vt2t (list_vt_reverse (list_mergesort t_list))
val () = println! ("From top to bottom:")
 
fun
Line 320 ⟶ 358:
 
{{out}}
<pre>From top to bottom:
<pre>(0.881023, 1.118975)
(0.654983, 2.854983)
(-0.681024, 2.681025)
(-0.854982, 1.345016)</pre>
<pre>(0.881023, 1.118975)</pre>
 
=={{header|D}}==
1,448

edits