/***************************************************** * Unit to draw a 2D curve with manual scaling * * -------------------------------------------------- * * REFERENCE: * * From Pascal unit GRAPH2D By Robert DONY, * * "Graphisme dans le plan et dans l'espace en Turbo * * Pascal 4.0, MASSON 1990" [BIBLI 12]. * * * * Visual C++ version by J-P Moreau, Paris * * (www.jpmoreau.fr) * *****************************************************/ #include "Gr2d.h" #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif //implemented by main program void DrawLine(int,int,int,int); void OutText(int,int,char *); // define a window in physical coordinates void Fenetre(ar_reel f1,ar_reel f2, ar_reel f3, ar_reel f4) { xgfen=f1; /* valeur mini x */ xdfen=f2; /* valeur maxi x */ ybfen=f3; /* valeur mini y */ yhfen=f4; /* valeur maxi y */ } // define a window in screen pixels (this function must be called // after Fenetre, or else a diempty by zero error will occur!) void Cloture(int c1,int c2,int c3,int c4) { xgclot=c1; // left margin in pixels xdclot=c2; // MaxX-right margin in pixels ybclot=c3; // lower margin in pixels yhclot=c4; // MaxY-upper margin in pixels xrapport=(xdclot-xgclot)/(xdfen-xgfen); yrapport=(yhclot-ybclot)/(yhfen-ybfen); // size in x and y of axis arrow dxx=0.01*(xdfen-xgfen); dyy=0.01*(yhfen-ybfen); } // define a full client zone window in pixels void PleinEcran() { Cloture(0,MaxX,0,MaxY); } // used by function Decoupage() - Define position code of point (x,y) // with respect to current drawing window int CodeBin( ar_reel x, ar_reel y) { int c; c=vide; if (x < xgfen) c=gauche; else if (x > xdfen) c=droite; if (y < ybfen) c=c+basse; else if (y > yhfen) c=c+haute; return(c); } // used by Decoupage() - Conversion from physical coordinates to // screen pixels and draw a segment (x1,y1) - (x2,y2) void Decoupe(ar_reel x1,ar_reel y1,ar_reel x2,ar_reel y2) { int xx1,yy1,xx2,yy2; xx1=xgclot+(int) floor((x1-xgfen)*xrapport+0.5); yy1=MaxY-yhclot+(int) floor((yhfen-y1)*yrapport+0.5); xx2=xgclot+(int) floor((x2-xgfen)*xrapport+0.5); yy2=MaxY-yhclot+(int) floor((yhfen-y2)*yrapport+0.5); DrawLine(xx1,yy1,xx2,yy2); } // Clipping function - Draw the visible part of segment (x1,y1) - (x2,y2) // (physical coordinates) - Adapted from Pascal by J-P Moreau void Decoupage(ar_reel x1,ar_reel y1,ar_reel x2,ar_reel y2) { int c,c1,c2; ar_reel x,y; c1=CodeBin(x1,y1); c2=CodeBin(x2,y2); while (c1 != vide || c2 != vide) { /* return si intersection de c1 et c2 <> vide */ if ((c1==gauche || c1==gauche+basse || c1==gauche+haute) && (c2==gauche || c2==gauche+basse || c2==gauche+haute)) return; if ((c1==droite || c1==droite+basse || c1==droite+haute) && (c2==droite || c2==droite+basse || c2==droite+haute)) return; if ((c1==basse || c1==gauche+basse || c1==droite+basse) && (c2==basse || c2==gauche+basse || c2==droite+basse)) return; if ((c1==haute || c1==droite+haute || c1==gauche+haute) && (c2==haute || c2==droite+haute || c2==gauche+haute)) return; if (c1 == vide) c=c2; else c=c1; if (c==gauche || c==gauche+basse || c==gauche+haute) { x=xgfen; y=y1+(y2-y1)*(xgfen-x1)/(x2-x1); } else if (c==droite || c==droite+basse || c==droite+haute) { x=xdfen; y=y1+(y2-y1)*(xdfen-x1)/(x2-x1); } else if (c==basse || c==droite+basse || c==gauche+basse) { y=ybfen; x=x1+(x2-x1)*(ybfen-y1)/(y2-y1); } else if (c==haute || c==droite+haute || c==gauche+haute) { y=yhfen; x=x1+(x2-x1)*(yhfen-y1)/(y2-y1); } if (c==c1) { x1=x; y1=y; c1=CodeBin(x,y); } else { x2=x; y2=y; c2=CodeBin(x,y); } } /* end while */ Decoupe(x1,y1,x2,y2); } // Draw a line from current point to point (x,y) with clipping void LineXY(ar_reel x,ar_reel y) { xp2=x; yp2=y; Decoupage(xp1,yp1,xp2,yp2); xp1=xp2; yp1=yp2; } // store new current point (x,y) void MoveXY(ar_reel x,ar_reel y) { xp1=x; yp1=y; } // draw a frame around client drawing zone with current pen void Bordure() { MoveXY(xgfen,yhfen); LineXY(xdfen,yhfen); LineXY(xdfen,ybfen); LineXY(xgfen,ybfen); LineXY(xgfen,yhfen); } // draw a polygon defined by X[i],Y[i] (closed or open) void Polygon(Table X,Table Y,int Lim,int Mode) { int i; MoveXY(X[1],Y[1]); for(i=2;i<=Lim;i++) LineXY(X[i],Y[i]); if (Mode != 0) LineXY(X[1],Y[1]); } // draw an arrow at end of Ox axis void FlecheX() { MoveXY(xdfen-dxx,YOrig+dyy); LineXY(xdfen,YOrig); LineXY(xdfen-dxx,YOrig-dyy); } // draw an arrow at end of Oy axis void FlecheY() { MoveXY(XOrig-dxx,yhfen-dyy); LineXY(XOrig,yhfen); LineXY(XOrig+dxx,yhfen-dyy); } // draw Ox and Oy axes void Axes() { if ((xgfen < 0.0) && (xdfen > 0.0)) XOrig=0.0; else XOrig=xgfen; if ((ybfen < 0.0) && (yhfen > 0.0)) YOrig=0.0; else YOrig=ybfen; MoveXY(xgfen,YOrig); LineXY(xdfen,YOrig); FlecheX(); MoveXY(XOrig,ybfen); LineXY(XOrig,yhfen); FlecheY(); } // utility function used by function Gradue() for Ox axis ar_reel CorrectX(ar_reel xorig,ar_reel xgfen,ar_reel unitx) { ar_reel ntir,corx; if (xorig==0) { ntir=(xorig-xgfen)/unitx; corx=(ntir-floor(ntir))*unitx; } else if (xorig > 0) corx=floor(xorig/unitx+1)*unitx-xorig; else corx=fabs(xorig)+floor(xorig/unitx)*unitx; return(corx); } // utility function used by function Gradue() for Oy axis ar_reel CorrectY(ar_reel yorig,ar_reel ybfen,ar_reel unity) { ar_reel ntir,cory; if (yorig==0) { ntir=(yorig-ybfen)/unity; cory=(ntir-floor(ntir))*unity; } else if (yorig > 0) cory=floor(yorig/unity+1)*unity-yorig; else cory=fabs(yorig)+floor(yorig/unity)*unity; return(cory); } // graduate axes Ox and Oy with steps UnitX and UnitY void Gradue(ar_reel UnitX,ar_reel UnitY) { int xx,yy; ar_reel CorX,CorY,X,Y; ar_reel tiretx,tirety; char mot[12]; tiretx=UnitX/10; tirety=UnitY/10; if (UnitX > 0) { CorX=CorrectX(XOrig,xgfen,UnitX); X=xgfen+CorX; do { MoveXY(X,YOrig+tirety); LineXY(X,YOrig-tirety); sprintf(mot,"%5.2f",X); xx=xgclot+(int) floor((X-xgfen)*xrapport); OutText(xx-15,MaxY-ybclot+10,mot); X=X + UnitX; } while (X < 1.01*xdfen); } if (UnitY > 0) { CorY=CorrectY(YOrig,ybfen,UnitY); Y=ybfen+CorY; do { MoveXY(XOrig-tiretx,Y); LineXY(XOrig+tiretx,Y); sprintf(mot,"%5.2f",Y); yy=MaxY-yhclot+(int) floor((yhfen-Y)*yrapport); OutText(5,yy-5,mot); Y=Y + UnitY; } while (Y <= yhfen); } } // draw a grid with steps UnitX and UnitY using current pen void Grille(ar_reel UnitX,ar_reel UnitY) { ar_reel i,j,corX,corY; corX=CorrectX(XOrig,xgfen,UnitX); corY=CorrectY(YOrig,ybfen,UnitY); i= floor(xgfen+corX); while (i <= xdfen) { MoveXY (i,ybfen); LineXY (i,yhfen); i=i+UnitX; } j= floor(ybfen+corY); while (j <= yhfen) { MoveXY (xgfen,j); LineXY (xdfen,j); j=j+UnitY; } } // draw a circle of center (xc,yc) and radius r (dotted line or normal line) void Cercle(ar_reel xc,ar_reel yc,ar_reel r,int trait) { ar_reel s,c,x,y,aux; int n; s=sin(pi/36); c=cos(pi/36); x=xc+r; y=yc; MoveXY(x,y); for (n=2; n<=73; n++) { aux=xc+(x-xc)*c-(y-yc)*s; y =yc+(x-xc)*s+(y-yc)*c; x =aux; if (trait) MoveXY(x,y); LineXY(x,y); } } // End of fole Gr2D.cpp