B-spline: Difference between revisions
Content added Content deleted
(Added Lua.) |
(Added Algol 68) |
||
Line 26: | Line 26: | ||
<br><br> |
<br><br> |
||
=={{header|ALGOL 68}}== |
|||
{{Trans|Lua}}Suppresses unused parts of the plot. |
|||
<lang algol68>BEGIN # construct a B-Spline # |
|||
# mode to hold a B Spline # |
|||
MODE BSPLINE = STRUCT( FLEX[ 1 : 0, 1 : 2 ]INT control points |
|||
, INT n |
|||
, INT k |
|||
, FLEX[ 1 : 0 ]INT t |
|||
); |
|||
PROC uniform knot vector = ( INT lb, ub )[]INT: |
|||
BEGIN |
|||
[ lb : ub ]INT range; |
|||
FOR n FROM lb TO ub DO range[ n ] := n OD; |
|||
range |
|||
END # uniform knot vector # ; |
|||
PROC calculate bspline = ( REF BSPLINE bs, INT i, k, x )REAL: |
|||
IF k = 1 |
|||
THEN ABS ( ( t OF bs )[ i ] <= x AND x < ( t OF bs )[ i + 1 ] ) |
|||
ELSE |
|||
PROC helper = ( REF BSPLINE bs, INT i, k, x )REAL: |
|||
IF ( t OF bs )[ i + k ] /= ( t OF bs )[ i ] |
|||
THEN ( x - ( t OF bs )[ i ] ) / ( ( t OF bs )[ i + k ] - ( t OF bs )[ i ] ) |
|||
ELSE 0 |
|||
FI # helper # ; |
|||
( helper( bs, i, k - 1, x ) ) * calculate bspline( bs, i, k - 1, x ) |
|||
+ ( 1 - helper( bs, i + 1, k - 1, x ) ) * calculate bspline( bs, i + 1, k - 1, x ) |
|||
FI # calculate bspline # ; |
|||
PROC round = ( REAL n )INT: ENTIER( n + 0.5 ); |
|||
PROC get bspline points = ( REF BSPLINE bs )[,]INT: |
|||
BEGIN |
|||
INT p from = ( t OF bs )[ k OF bs ]; |
|||
INT p to = ( t OF bs )[ 1 + n OF bs ] - 1; |
|||
[ p from : p to, 1 : 2 ]INT points; |
|||
FOR x FROM p from TO p to DO |
|||
REAL sum x := 0; |
|||
REAL sum y := 0; |
|||
FOR i TO n OF bs DO |
|||
REAL f = calculate bspline( bs, i, k OF bs, x ); |
|||
sum x +:= f * ( control points OF bs )[ i, 1 ]; |
|||
sum y +:= f * ( control points OF bs )[ i, 2 ] |
|||
OD; |
|||
points[ x, 1 ] := round( sum x ); |
|||
points[ x, 2 ] := round( sum y ) |
|||
OD; |
|||
points |
|||
END # get bspline points # ; |
|||
PROC raytrace = ( INT x0, y0, x2, y2, REF[,]BOOL plot, PROC( REF[,]BOOL, INT, INT )VOID visit )VOID: |
|||
BEGIN |
|||
INT x := x0; |
|||
INT y := y0; |
|||
INT dx := ABS ( x2 - x ); |
|||
INT dy := ABS ( y2 - y ); |
|||
INT n = 1 + dx + dy; |
|||
INT dir x = IF x2 > x THEN 1 ELSE -1 FI; |
|||
INT dir y = IF y2 > y THEN 1 ELSE -1 FI; |
|||
INT err := dx - dy; |
|||
dx *:= 2; |
|||
dy *:= 2; |
|||
FOR i TO n DO |
|||
visit( plot, x, y ); |
|||
IF err > 0 |
|||
THEN x +:= dir x; err -:= dy |
|||
ELSE y +:= dir y; err +:= dx |
|||
FI |
|||
OD |
|||
END # raytrace # ; |
|||
PROC plot line = ( REF[,]BOOL plot, INT x1, y1, x2, y2 )VOID: |
|||
raytrace( x1, y1, x2, y2, plot |
|||
, ( REF[,]BOOL plot, INT x, INT y )VOID: IF x >= 0 |
|||
AND y >= 0 |
|||
AND x < 1 UPB plot |
|||
AND y < 2 UPB plot |
|||
THEN plot[ x + 1, y + 1 ] := TRUE |
|||
FI |
|||
); |
|||
PROC plot bspline = ( REF BSPLINE bs, REF[,]BOOL plot, REAL scale x, scale y )VOID: |
|||
IF k OF bs > n OF bs OR k OF bs < 1 THEN |
|||
print( ( "k (= ", whole( k OF bs, 0 ), ") can't be more than ", whole( n OF bs, 0 ), " or less than 1." ) ); |
|||
stop |
|||
ELSE |
|||
[,]INT points = get bspline points( bs ); |
|||
# Plot the curve. # |
|||
FOR i FROM 1 LWB points TO 1 UPB points - 1 DO |
|||
INT p1x = points[ i, 1 ], p1y = points[ i, 2 ]; |
|||
INT p2x = points[ i + 1, 1 ], p2y = points[ i + 1, 2 ]; |
|||
plot line( plot |
|||
, round( p1x * scale x ), round( p1y * scale y ) |
|||
, round( p2x * scale x ), round( p2y * scale y ) |
|||
) |
|||
OD |
|||
FI # plot bspline # ; |
|||
# print the plot - outputs @ or blank depending on whether the point is plotted or not # |
|||
PROC print plot = ( [,]BOOL plot )VOID: |
|||
FOR row FROM 1 LWB plot |
|||
TO BEGIN # find the highest used row # |
|||
INT max row := 1 UPB plot; |
|||
WHILE IF max row < 1 LWB plot |
|||
THEN FALSE |
|||
ELSE |
|||
BOOL empty row := TRUE; |
|||
FOR column FROM 2 LWB plot TO 2 UPB plot |
|||
WHILE empty row := NOT plot[ column, max row ] |
|||
DO |
|||
SKIP |
|||
OD; |
|||
empty row |
|||
FI |
|||
DO |
|||
max row -:= 1 |
|||
OD; |
|||
max row |
|||
END |
|||
DO |
|||
INT max column := 2 UPB plot; |
|||
WHILE IF max column < 2 LWB plot THEN FALSE ELSE NOT plot[ max column, row ] FI |
|||
DO |
|||
max column -:= 1 |
|||
OD; |
|||
FOR column FROM 2 LWB plot TO max column DO |
|||
print( ( IF plot[ column, row ] THEN "@" ELSE " " FI ) ) |
|||
OD; |
|||
print( ( newline ) ) |
|||
OD # print plot # ; |
|||
# task # |
|||
[,]INT control points |
|||
= ( ( 171, 171 ), ( 185, 111 ), ( 202, 109 ), ( 202, 189 ), ( 328, 160 ), ( 208, 254 ) |
|||
, ( 241, 330 ), ( 164, 252 ), ( 69, 278 ), ( 139, 208 ), ( 72, 148 ), ( 168, 172 ) |
|||
); |
|||
INT k = 4; # Polynomial degree is one less than this i.e. cubic. # |
|||
BSPLINE bs |
|||
:= BSPLINE( control points |
|||
, UPB control points |
|||
, k |
|||
, uniform knot vector( 1, UPB control points + k ) |
|||
); |
|||
REAL scale x = 0.4; # Since we print the plot to the console as text let's scale things appropriately. # |
|||
REAL scale y = 0.2; |
|||
[ 1 : 350, 1 : 350 ]BOOL plot; |
|||
FOR r FROM 1 LWB plot TO 1 UPB plot DO FOR c FROM 2 LWB plot TO 2 UPB plot DO plot[ c, r ] := FALSE OD OD; |
|||
plot bspline( bs, plot, scale x, scale y ); |
|||
print plot( plot ) |
|||
END</lang> |
|||
{{out}} |
|||
leading blank lines removed... |
|||
<pre> |
|||
@@@@ |
|||
@@@@ |
|||
@@ |
|||
@@ |
|||
@@ |
|||
@@ |
|||
@@ |
|||
@@ |
|||
@@ |
|||
@@ |
|||
@@@@@@@@ |
|||
@@@@@@@@@@@@@@ |
|||
@@@@@@@@ |
|||
@@ |
|||
@@@ |
|||
@@ |
|||
@@@ |
|||
@@ |
|||
@ @@@ |
|||
@@ @@ |
|||
@@ @@@ |
|||
@ @@ |
|||
@@ @@@ |
|||
@@ @@ |
|||
@@ @@@ |
|||
@ @@ |
|||
@@ @@ |
|||
@@ @@ |
|||
@@@@@@@ @ |
|||
@@@@@@@@@@@@@@ @@ |
|||
@@@@@@@@@ @ |
|||
@@@@ @ |
|||
@@@@@ @@ |
|||
@@@@@ @ |
|||
@@@@ @@ |
|||
@@@@@ @ |
|||
@@@@ @@ |
|||
@@@ |
|||
</pre> |
|||
=={{header|Julia}}== |
=={{header|Julia}}== |