//////////////////This program is written by Lutz Tautenhahn, Chemnitz 1995. ////////////////////////////////You may use this code for your own purposes. ////////////////////////////////There are no conditions and no restrictions. #include #include #include #include #include #include "ltdiagrm.h" LTDiagram::LTDiagram(double theLeftX, double theRightX, double theBottomY, double theTopY, int theLeft, int theTop, int theRight, int theBottom, void* theScaleX, void* theScaleY, void* theTitle) { xmin = theLeftX; xmax = theRightX; ymin = theBottomY; ymax = theTopY; left = theLeft; right = theRight; top = theTop; bottom = theBottom; sprintf(xtext,"%s", theScaleX); sprintf(ytext,"%s", theScaleY); sprintf(title,"%s", theTitle); } //////////////////////////////////////////////////////////////////////////// void LTDiagram::SetFrame (int theLeft, int theTop, int theRight, int theBottom) { left = theLeft; right = theRight; top = theTop; bottom = theBottom; } //////////////////////////////////////////////////////////////////////////// void LTDiagram::SetBorder(double theLeftX, double theRightX, double theBottomY, double theTopY) { xmin = theLeftX; xmax = theRightX; ymin = theBottomY; ymax = theTopY; } //////////////////////////////////////////////////////////////////////////// void LTDiagram::SetText(void* theScaleX, void* theScaleY, void* theTitle) { xtext[0]='\0'; ytext[0]='\0'; title[0]='\0'; sprintf(xtext,"%s", theScaleX); sprintf(ytext,"%s", theScaleY); sprintf(title,"%s", theTitle); } //////////////////////////////////////////////////////////////////////////// int LTDiagram::ScreenX(double theRealX) { return(round((theRealX-xmin)/(xmax-xmin)*(right-left)+left)); } //////////////////////////////////////////////////////////////////////////// int LTDiagram::ScreenY(double theRealY) { return(round((ymax-theRealY)/(ymax-ymin)*(bottom-top)+top)); } //////////////////////////////////////////////////////////////////////////// double LTDiagram::RealX(int theScreenX) { return(xmin+(xmax-xmin)*(theScreenX-left)/(right-left)); } //////////////////////////////////////////////////////////////////////////// double LTDiagram::RealY(int theScreenY) { return(ymax-(ymax-ymin)*(theScreenY-top)/(bottom-top)); } //////////////////////////////////////////////////////////////////////////// int LTDiagram::sign(double rr) { if (rr<0) return(-1); else return(1); } //////////////////////////////////////////////////////////////////////////// int LTDiagram::round( double xx) { if (xx < 0.0) xx -= 0.5; if (xx > 0.0) xx += 0.5; return(int(xx)); } //////////////////////////////////////////////////////////////////////////// void LTDiagram::Draw(int DrawColor, int TextColor, int ZeroColor, boolean isGrid, boolean isScaleText) { const int hh=15; int x0,y0,i,j,maxpix,itext,ltext,hfont; double x,y,r,dx,dy,xl,yl,xr,yr,invdifx,invdify,deltax,deltay; char atext[StringLength]; struct _fontinfo fi; _setgtextvector( 1, 0 ); if (_getfontinfo(&fi)<0) { _outtext("Error, no font! First use 'setfont'!"); exit(1); } hfont=fi.pixheight/4; ////////////this seems to be a good fit for small fonts////////////////////// invdifx=(right-left)/(xmax-xmin); invdify=(bottom-top)/(ymax-ymin); _setcolor(DrawColor); for (i=left; i<=right; i++) { _setpixel(i,top); _setpixel(i,bottom); } for (i=top; i<= bottom; i++) { _setpixel(left,i); _setpixel(right,i); } ///////////////////////////Draw X-Grid////////////////////////////////////// dx=(xmax-xmin); if (fabs(dx)>0) { r=1; while (fabs(dx)>=100) { dx/=10; r*=10; } while (fabs(dx)<10) { dx*=10; r/=10; }; if (fabs(dx)>=50) deltax=10*r*sign(dx); else { if (fabs(dx)>=20) deltax=5*r*sign(dx); else deltax=2*r*sign(dx); } x=int(xmin/deltax)*deltax; itext=0; for (j=12; j>= -1; j--) { xr=x+j*deltax; xl=left+(-xmin+x+j*deltax)*invdifx; x0=round(xl); if ((x0>=left)&(x0<=right)) { itext++; _setcolor(TextColor); if ((itext!=2)|(!isScaleText)) { ltext=MinLength(xr); sprintf(atext, "%f", xr); atext[ltext]='\0'; _moveto(x0- _getgtextextent(atext)/2, bottom+hh); _outgtext(atext); } else { _moveto(x0- _getgtextextent(xtext)/2, bottom+hh); _outgtext(xtext); } if (isGrid) maxpix=top; else maxpix=bottom-6; _setcolor(DrawColor); for (i=maxpix; i<=bottom+6; i++) _setpixel(x0,i); } } x0=round(left-xmin*invdifx); if ((x0>=left)&(x0<=right)) { _setcolor(ZeroColor); for (i=top; i<=bottom; i++) _setpixel(x0,i); } } ///////////////////////////Draw Y-Grid////////////////////////////////////// dy=ymax-ymin; if (fabs(dy)>0) { r=1; while (fabs(dy)>=100) { dy/=10; r*=10; } while (fabs(dy)<10) { dy*=10; r/=10; } if (fabs(dy)>=50) deltay=10*r*sign(dy); else { if (fabs(dy)>=20) deltay=5*r*sign(dy); else deltay=2*r*sign(dy); } y=int(ymax/deltay)*deltay; itext=0; for (j=-1; j<=12; j++) { yr=y-j*deltay; yl=top+(ymax-y+j*deltay)*invdify; y0=round(yl); if ((y0>=top)&(y0<=bottom)) { itext++; _setcolor(TextColor); if ((itext!=2)|(!isScaleText)) { ltext=MinLength(yr); sprintf(atext, "%f", yr); atext[ltext]='\0'; _moveto(left-hh- _getgtextextent(atext),y0-hfont); _outgtext(atext); } else { _moveto(left-hh- _getgtextextent(ytext),y0-hfont); _outgtext(ytext); } if (isGrid) maxpix=right; else maxpix=left+6; _setcolor(DrawColor); for (i=left-6; i<=maxpix; i++) _setpixel(i,y0); } } y0=round(top+ymax*invdify); if ((y0>=top)&(y0<=bottom)) { _setcolor(ZeroColor); for (i=left; i<=right; i++) _setpixel(i,y0); } } _setcolor(TextColor); _moveto((left+right-hh- _getgtextextent(title))/2, top-hh-2*hfont); _outgtext(title); } /////////////////////////////////////////////////////////////////////////// int LTDiagram::MinLength(double theValue) { boolean isPoint=false; int aOldLength, aNewLength; char aValueChar[20]; sprintf(aValueChar, "%f", theValue); aOldLength=strlen(aValueChar); aNewLength=aOldLength; for(int ii = 0; ii < aOldLength; ii++) if (aValueChar[ii]=='.') isPoint=true; if (isPoint==true) { for(int ii = aOldLength-1; ii >= 0; ii--) { if ((isPoint)&((aValueChar[ii]=='0')^(aValueChar[ii]=='.'))) aNewLength--; else isPoint=false; if (aValueChar[ii]=='.') isPoint=false; } } return(aNewLength); }