Code:
LOCAL CRID:="Bézier V0.1 StephenG1CMZ 2018";
//LOCAL ImpSTEPSZ:=1/(10000-2);//Most Detailed-List Limit
//! Android: Insufficient Memory may occur.
//These steps allow a spline along a diagonal
//LOCAL GSTEPSZ:=1/(4406-2); //4K
//LOCAL GSTEPSZ:=1/(2203-2); //HD
//LOCAL GSTEPSZ:=1/(800-2);//VGA
EXPORT GSTEPSZ:=1/(400-2);//QVGA
//0..1 ALSO IMP>0.001=10000 PTS
EXPORT ROTMATRIX:=[[1,0],[0,1]];//DEFAULT: NO ROT (ONLY USED WITH CN=1)
LOCAL CN:=1;//0=POINTS 1=LINES (EXAMPLES)
//NB PROCEDURES RETURN COMPLEX REAL (X,Y) VALUES
//WHICH YOU MIGHT WISH TO PIXELLATE
//PROCEDURES PREFIXED G GENERATE CURVE POINTS
//PROCEDURES SUFFIXED 1 GENERATE 1 POINT
//POLYBEZIER NOT IMLEMENTED:ADDITIONAL PARAMETERS IGNORED
GETPT(N1,N2,PERCY)
//FRACTION ALONG LINE:X OR Y
//USED BY BEZIER PROCS
BEGIN
LOCAL DFF:=N2-N1;
RETURN (N1+(DFF*PERCY));
//
END;
EXPORT GBezierQUAD1 (XX,YY,PERCY)
//Generate a point along a Bezier Quadratic curve
//PERCY AND II: 0..1
BEGIN
LOCAL XA,YA,XB,YB;
LOCAL II:=PERCY;
// FIRST CONSTRUCT GREEN LINE
XA:=GETPT(XX(1),XX(2),II);
YA:=GETPT(YY(1),YY(2),II);
XB:=GETPT(XX(2),XX(3),II);
YB:=GETPT(YY(2),YY(3),II);
//GENERATE BEZIER POINT
RETURN ((GETPT(XA,XB,II)),(GETPT(YA,YB,II)));
END;
EXPORT GBezierQUAD(XX,YY)
//Generate Bezier Quadratic curve
//XY: 1 AND 3 ON CURVE. 2 CONTROLPT.
BEGIN
LOCAL II;
LOCAL XA,YA,XB,YB;
LOCAL PTS:={};
//FOR EACH
FOR II FROM 0 TO 1 STEP GSTEPSZ DO
PTS(0):=GBezierQUAD1(XX,YY,II);
END;//FOR
//ENSURE PT3 ON CURVE
PTS(0):=GBezierQUAD1(XX,YY,1); //(XX(3),YY(3));
RETURN PTS;
END;
EXPORT GBezierCUBIC1(XX,YY,PERCY)
//Generate a point along a Bezier Cubic curve
//PERCY AND II: 0..1
BEGIN
LOCAL II:=PERCY;
LOCAL XA,YA,XB,YB,XC,YC;
LOCAL XM,YM,XN,YN;
// FIRST CONSTRUCT GREEN LINES
XA:=GETPT(XX(1),XX(2),II);
YA:=GETPT(YY(1),YY(2),II);
XB:=GETPT(XX(2),XX(3),II);
YB:=GETPT(YY(2),YY(3),II);
XC:=GETPT(XX(3),XX(4),II);
YC:=GETPT(YY(3),YY(4),II);
//BLUE LINE
XM:=GETPT(XA,XB,II);
YM:=GETPT(YA,YB,II);
XN:=GETPT(XB,XC,II);
YN:=GETPT(YB,YC,II);
//GENERATE BEZIER POINT
RETURN (GETPT(XM,XN,II),GETPT(YM,YN,II));//X AND Y
END;
EXPORT GBezierCUBIC(XX,YY)
//Generate Bezier Cubic curve
//XY: 1 AND 4 ON CURVE. 2 AND 3 CONTROL PT.
BEGIN
LOCAL II;
LOCAL PTS:={};
//FOR EACH
FOR II FROM 0 TO 1 STEP GSTEPSZ DO
PTS(0):=GBezierCUBIC1(XX,YY,II); //X AND Y
END;//FOR
//ENSURE PT4 ON CURVE
PTS(0):=GBezierCUBIC1(XX,YY,1); //(XX(4),YY(4));
RETURN PTS;
END;
EXPORT DRAWC(PTS,COLR,CONN)
//DRAW POINTS CONNECTED
//PTS: (X,Y) AS COMPLEX ie LINE FORMT
//CONN 0: POINTS 1 BY 1
//CONN 1: LINES ALL AT ONCE
//(GUARDS AGANST GAPS)
//TBD: IMPLEMENT _P AND NON_P VARIANTS
BEGIN
LOCAL II;
LOCAL LINESLST:={};
CASE
IF SIZE(PTS)==0 THEN //NOTHING TO DRAW
END;
IF CONN==0 OR SIZE(PTS)==1 THEN //POINTS
FOR II FROM 1 TO SIZE(PTS) DO
PIXON_P(RE(PTS(II)),IM(PTS(II)),COLR);
//WAIT(1);//ANIMABLE
END;
END; //POINTS
IF CONN==1 THEN //LINES
LINESLST:=MAKELIST({II-1,II},II,2,SIZE(PTS));
LINE_P(PTS,CONCAT(COLR,LINESLST),ROTMATRIX);
//LINE_P(G9,PTS,CONCAT(COLR,LINESLST),ROTMATRIX);
END; //LINES
DEFAULT
//UNKNOWN CONN
END;//CASE
END;
EXPORT IsOnCurve(Points,Point,Rounding)
//Is PT on curve described by PTS
//Points:Points comprising curve
//Point: Search Point (Complex XY)
//Rounding: −12..12 allows inexact real matches
//NB if points change, conclusion may
//Enhancements: Consider alternatives to rounding
BEGIN
LOCAL RND:=Rounding;
RETURN POS(ROUND(Points,RND),ROUND(Point,RND));
END;
EXPORT BezierExample()
BEGIN
LOCAL TM,GTIME;
LOCAL PTS;
LOCAL COLR:=#FF00FF;
LOCAL GSTEPSZ_SAVE:=GSTEPSZ;
GSTEPSZ:=1/(200-2);//LOCALVALUE FOR DEMO
RECT_P();
TEXTOUT_P(CRID,0,220);
TEXTOUT_P("Generate",0,0);
DRAWC({(320/2,240/2)},COLR,CN);//TEST 1 PT
DRAWC({},COLR,CN);//TEST NULL
TEXTOUT_P("Draw",160,0);
TEXTOUT_P(TEVAL(PTS:=GBezierQUAD({10,80,240},{200,100,150})),0,20);
TEXTOUT_P(TEVAL(DRAWC(PTS,COLR,CN)),160,20);
TEXTOUT_P(SIZE(PTS)+" Points/Bézier",0,200);
TEXTOUT_P(TEVAL(PTS:=GBezierCUBIC({10,0,150,240},{200,20,20,150})),0,40);
TEXTOUT_P(TEVAL(DRAWC(PTS,COLR,CN)),160,40);
TEXTOUT_P(TEVAL(PTS:=GBezierQUAD({100,250,250,325},{100,100,200,350})),0,60);
TEXTOUT_P(TEVAL(DRAWC(PTS,#FF0000,CN)),160,60);
GSTEPSZ:=GSTEPSZ_SAVE;
//PRINT();
//PRINT("RESULT:POS is "+IsOnCurve({(1,2)},(1,2),0));
WAIT;
END;
EXPORT BEZIER()
BEGIN
BezierExample();
END;