Bitmap/Bézier curves/Cubic: Difference between revisions

Content added Content deleted
m (→‎[[Cubic_bezier_curves#ALGOL 68]]: virtualise procedure and add flag for test)
(add Tcl)
Line 272: Line 272:
by_pair pts (fun p0 p1 -> line ~p0 ~p1);
by_pair pts (fun p0 p1 -> line ~p0 ~p1);
;;</lang>
;;</lang>

=={{header|Tcl}}==
This solution can be applied to any number of points
<lang tcl>package require Tcl 8.5
package require Tk

proc drawBezier {img colour args} {
# ensure the 3 points are increasing along the x-axis
set points [lsort -real -index 0 $args]
set xmin [x [lindex $points 0]]
set xmax [x [lindex $points end]]
set prev [lindex $points 0]
set increment 2
for {set x [expr {$xmin + $increment}]} {$x <= $xmax} {incr x $increment} {
set t [expr {1.0 * ($x - $xmin) / ($xmax - $xmin)}]
set this [list $x [::tcl::mathfunc::round [bezier $t $points]]]
drawLine $img $colour $prev $this
set prev $this
}
}

# the generalized n-degree Bezier summation
proc bezier {t points} {
set n [expr {[llength $points] - 1}]
set sum 0.0
for {set i 0} {$i <= $n} {incr i} {
set sum [expr {$sum + [C $n $i] * (1-$t)**($n - $i) * $t**$i * [y [lindex $points $i]]}]
}
return $sum
}

proc C {n i} {expr {[ifact $n] / ([ifact $i] * [ifact [expr {$n - $i}]])}}
proc ifact n {
for {set i $n; set sum 1} {$i >= 2} {incr i -1} {
set sum [expr {$sum * $i}]
}
return $sum
}

proc x p {lindex $p 0}
proc y p {lindex $p 1}

proc newbezier {n w} {
set size 400
set bezier [newImage $size $size]
fill $bezier white
for {set i 1} {$i <= $n} {incr i} {
set point [list [expr {int($size*rand())}] [expr {int($size*rand())}]]
lappend points $point
drawCircle $bezier red $point 3
}
puts $points
drawBezier $bezier blue {*}$points
$w configure -image $bezier
}

set degree 4 ;# cubic bezier -- for quadratic, use 3
label .img
button .new -command [list newbezier $degree .img] -text New
button .exit -command exit -text Exit
pack .new .img .exit -side top</lang>