Curve that touches three points: Difference between revisions

Content added Content deleted
(Ada version)
(Added solution for Action!)
Line 5: Line 5:
::#  Do not use functions of a library, implement the curve() function yourself
::#  Do not use functions of a library, implement the curve() function yourself
::#  coordinates:(x,y) starting point (10,10) medium point (100,200) final point (200,10)
::#  coordinates:(x,y) starting point (10,10) medium point (100,200) final point (200,10)

=={{header|Action!}}==
{{libheader|Action! Tool Kit}}
<lang Action!>INCLUDE "D2:REAL.ACT" ;from the Action! Tool Kit

TYPE Point=[INT x,y]

PROC MyIntToReal(INT a REAL POINTER r)
BYTE ARRAY x

IF a>=0 THEN
IntToReal(a,r)
ELSE
IntToReal(-a,r)
x=r
x(0)==%$80
FI
RETURN

INT FUNC MyRealToInt(REAL POINTER r)
BYTE ARRAY x
REAL tmp
INT i

x=r
IF (x(0)&$80)=0 THEN
i=RealToInt(r)
ELSE
RealAssign(r,tmp)
x=tmp
x(0)==&$7F
i=-RealToInt(tmp)
FI
RETURN (i)

BYTE FUNC IsNegative(REAL POINTER r)
BYTE ARRAY x

x=r
IF (x(0)&$80)=$80 THEN
RETURN (1)
FI
RETURN (0)

PROC QuadraticCurve(Point POINTER p1,p2,p3 REAL POINTER a,b,c)
REAL x1,y1,x2,y2,x3,y3,x11,x22,x33,m,n,tmp1,tmp2,tmp3,tmp4,r1

MyIntToReal(-1,r1)
MyIntToReal(p1.x,x1) MyIntToReal(p1.y,y1)
MyIntToReal(p2.x,x2) MyIntToReal(p2.y,y2)
MyIntToReal(p3.x,x3) MyIntToReal(p3.y,y3)

RealMult(x1,x1,x11) ;x11=x1^2
RealMult(x2,x2,x22) ;x22=x2^2
RealMult(x3,x3,x33) ;x33=x3^2

RealSub(x1,x2,m) ;m=x1-x2
RealSub(x3,x2,n) ;n=x3-x2
RealMult(m,n,tmp1) ;tmp1=m*n

IF IsNegative(tmp1) THEN
RealMult(m,r1,tmp1)
RealAssign(tmp1,m) ;m=-m
FI

RealSub(y1,y2,tmp1) ;tmp1=y1-y2
RealMult(n,tmp1,tmp2) ;tmp2=n*(y1-y2)
RealSub(y3,y2,tmp1) ;tmp1=y3-y2
RealMult(m,tmp1,tmp3) ;tmp3=m*(y3-y2)
RealAdd(tmp2,tmp3,tmp1) ;tmp1=n*(y1-y2)+m*(y3-y2)

RealSub(x11,x22,tmp2) ;tmp2=x1^2-x2^2
RealMult(n,tmp2,tmp3) ;tmp3=n*(x1^2-x2^2)
RealSub(x33,x22,tmp2) ;tmp2=x3^2-x2^2
RealMult(m,tmp2,tmp4) ;tmp4=m*(x3^2-x2^2)
RealAdd(tmp3,tmp4,tmp2) ;tmp2=n*(x1^2-x2^2)+m*(x3^2-x2^2)

RealDiv(tmp1,tmp2,a) ;a=(n*(y1-y2)+m*(y3-y2)) / (n*(x1^2-x2^2)+m*(x3^2-x2^2))

RealSub(x33,x22,tmp1) ;tmp1=x3^2-x2^2
RealMult(tmp1,a,tmp2) ;tmp2=(x3^2-x2^2)*a
RealSub(y3,y2,tmp1) ;tmp1=y3-y2
RealSub(tmp1,tmp2,tmp3) ;tmp3=(y3-y2)-(x3^2-x2^2)*a
RealSub(x3,x2,tmp1) ;tmp1=x3-x2
RealDiv(tmp3,tmp1,b) ;b=((y3-y2)-(x3^2-x2^2)*a) / (x3-x2)

RealMult(a,x11,tmp1) ;tmp1=a*x1^2
RealMult(b,x1,tmp2) ;tmp2=b*x1
RealSub(y1,tmp1,tmp3) ;tmp3=y1-a*x1^2
RealSub(tmp3,tmp2,c) ;c=y1-a*x1^2-b*x1
RETURN

PROC DrawPoint(INT x,y)
Plot(x-2,y-2) DrawTo(x+2,y-2)
DrawTo(x+2,y+2) DrawTo(x-2,y+2)
DrawTo(x-2,y-2)
RETURN

INT FUNC Min(INT a,b)
IF a<b THEN RETURN (a) FI
RETURN (b)

INT FUNC Max(INT a,b)
IF a>b THEN RETURN (a) FI
RETURN (b)

INT FUNC CalcY(REAL POINTER a,b,c INT xi)
REAL xr,xr2,yr,tmp1,tmp2,tmp3
INT yi

MyIntToReal(xi,xr) ;xr=x
RealMult(xr,xr,xr2) ;xr2=x^2
RealMult(a,xr2,tmp1) ;tmp1=a*x^2
RealMult(b,xr,tmp2) ;tmp2=b*x
RealAdd(tmp1,tmp2,tmp3) ;tmp3=a*x^2+b*x
RealAdd(tmp3,c,yr) ;y3=a*x^2+b*x+c
yi=MyRealToInt(yr)
RETURN (yi)

PROC DrawCurve(Point POINTER p1,p2,p3)
REAL a,b,c
INT xi,yi,minX,maxX

QuadraticCurve(p1,p2,p3,a,b,c)

DrawPoint(p1.x,p1.y)
DrawPoint(p2.x,p2.y)
DrawPoint(p3.x,p3.y)

minX=Min(p1.x,p2.x)
minX=Min(minX,p3.x)
maxX=Max(p1.x,p2.x)
maxX=Max(maxX,p3.x)

yi=CalcY(a,b,c,minX)
Plot(minX,yi)
FOR xi=minX TO maxX
DO
yi=CalcY(a,b,c,xi)
DrawTo(xi,yi)
OD
RETURN

PROC Main()
BYTE CH=$02FC,COLOR1=$02C5,COLOR2=$02C6
Point p1,p2,p3

Graphics(8+16)
Color=1
COLOR1=$0C
COLOR2=$02

p1.x=10 p1.y=10
p2.x=100 p2.y=180
p3.x=200 p3.y=10
DrawCurve(p1,p2,p3)

DO UNTIL CH#$FF OD
CH=$FF
RETURN</lang>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Curve_that_touches_three_points.png Screenshot from Atari 8-bit computer]


=={{header|Ada}}==
=={{header|Ada}}==