267 lines
6.1 KiB
C++
267 lines
6.1 KiB
C++
#include "stdafx.h"
|
|
#include "bhplot.h"
|
|
|
|
CBHPlot::CBHPlot()
|
|
{
|
|
NumRows=0;
|
|
NumCols=0;
|
|
NumPts=0;
|
|
M=NULL;
|
|
lbls=NULL;
|
|
Pts=NULL;
|
|
|
|
}
|
|
|
|
CBHPlot::~CBHPlot()
|
|
{
|
|
if (NumRows==0) return;
|
|
|
|
int i;
|
|
for(i=0;i<NumRows;i++) free(M[i]);
|
|
for(i=0;i<NumCols;i++) free(lbls[i]);
|
|
free(M);
|
|
free(lbls);
|
|
NumRows=0;
|
|
NumCols=0;
|
|
if (NumPts!=0)
|
|
{
|
|
free(Pts);
|
|
NumPts=0;
|
|
}
|
|
}
|
|
|
|
BOOL CBHPlot::Create(int rows, int cols)
|
|
{
|
|
int i;
|
|
BOOL flag=TRUE;
|
|
|
|
NumRows=rows;
|
|
NumCols=cols;
|
|
M=(double **)calloc(rows,sizeof(double*));
|
|
lbls=(char **)calloc(cols,sizeof(char*));
|
|
if ((M==NULL) || (lbls==NULL)) flag=FALSE;
|
|
for(i=0;i<rows;i++){
|
|
M[i]=(double *)calloc(cols,sizeof(double));
|
|
if (M[i]==NULL) flag=FALSE;
|
|
}
|
|
for(i=0;i<cols;i++){
|
|
lbls[i]=(char *)calloc(80,sizeof(char));
|
|
if (lbls[i]==0) flag=FALSE;
|
|
}
|
|
|
|
if(flag==FALSE){
|
|
NumRows=0;
|
|
NumCols=0;
|
|
for(i=0;i<rows;i++) free(M[i]);
|
|
for(i=0;i<cols;i++) free(lbls[i]);
|
|
free(M);
|
|
free(lbls);
|
|
}
|
|
|
|
return flag;
|
|
}
|
|
|
|
void CBHPlot::MakePlot(CDC *pDC, BOOL logscale)
|
|
{
|
|
double HiX,LoX,HiY,LoY,dx,dy,d;
|
|
static const double Height=250.;
|
|
static const double Width=400.;
|
|
static const double OffsetX=80.;
|
|
static const double OffsetY=30.;
|
|
char s[80];
|
|
int i,j,k;
|
|
CPen PlotPen;
|
|
CPen *pOldPen;
|
|
static COLORREF PenCols[]={0x00000000,0x00ff0000,0x0000ff00,0x000000ff,
|
|
0x00ffff00,0x00ff00ff,0x0000ffff};
|
|
|
|
if (NumRows==0) return;
|
|
|
|
|
|
// catch the case where logscale barfs
|
|
if((Pts[0].re==0) && (logscale))
|
|
{
|
|
for(i=1;i<NumPts;i++) Pts[i-1]=Pts[i];
|
|
NumPts--;
|
|
|
|
for(i=0,j=0;i<NumRows;i++) if (M[i][0]<Pts[0].re) j++;
|
|
NumRows-=j;
|
|
for(i=0;i<NumRows;i++)
|
|
for(k=0;k<NumCols;k++) M[i][k]=M[i+j][k];
|
|
}
|
|
|
|
// if logscale, take the log of H
|
|
if(logscale){
|
|
for(i=0;i<NumRows;i++) M[i][0]=log10(M[i][0]);
|
|
for(i=0;i<NumPts;i++) Pts[i].re=log10(Pts[i].re);
|
|
}
|
|
|
|
LoY=M[0][1];
|
|
HiY=M[0][1];
|
|
|
|
for(i=1;i<NumRows;i++)
|
|
for(j=1;j<NumCols;j++)
|
|
{
|
|
if (M[i][j]>HiY) HiY=M[i][j];
|
|
if (M[i][j]<LoY) LoY=M[i][j];
|
|
}
|
|
|
|
if(HiY==LoY){
|
|
HiY=1.;
|
|
LoY=-1.;
|
|
}
|
|
|
|
dy=pow(10.,floor(log10(HiY-LoY)));
|
|
LoY=dy*floor(LoY/dy);
|
|
HiY=dy*ceil(HiY/dy);
|
|
|
|
if (logscale){
|
|
LoX=floor(Re(Pts[0]));
|
|
HiX=ceil(Re(Pts[NumPts-1]));
|
|
dx=1.;
|
|
}
|
|
else
|
|
{
|
|
HiX=M[NumRows-1][0];
|
|
LoX=M[0][0]; // LoX=0.;
|
|
dx=pow(10.,floor(log10(HiX-LoX)));
|
|
}
|
|
|
|
// scale those suckers...
|
|
for(i=0;i<NumRows;i++){
|
|
for(j=1;j<NumCols;j++)
|
|
M[i][j]=Height-(M[i][j]-LoY)*Height/(HiY-LoY)+OffsetY;
|
|
M[i][0]=(M[i][0]-LoX)*Width/(HiX-LoX)+OffsetX;
|
|
}
|
|
|
|
for(i=0;i<NumPts;i++)
|
|
{
|
|
Pts[i].re=(Pts[i].re-LoX)*Width/(HiX-LoX)+OffsetX;
|
|
Pts[i].im=Height-(Pts[i].im-LoY)*Height/(HiY-LoY)+OffsetY;
|
|
}
|
|
|
|
PlotPen.CreatePen(PS_SOLID,1,PenCols[0]);
|
|
pOldPen=pDC->SelectObject( &PlotPen );
|
|
pDC->MoveTo(0,0);
|
|
pDC->LineTo(588,0);
|
|
pDC->LineTo(588,343);
|
|
pDC->LineTo(0,343);
|
|
pDC->LineTo(0,0);
|
|
|
|
pDC->MoveTo((int) OffsetX,(int) OffsetY);
|
|
pDC->LineTo((int) OffsetX,(int) (OffsetY+Height));
|
|
pDC->LineTo((int) (OffsetX+Width),(int) (OffsetY+Height));
|
|
pDC->SelectObject(pOldPen);
|
|
PlotPen.DeleteObject();
|
|
|
|
CFont fntArial,*pOldFont;
|
|
fntArial.CreateFont(12,0,0,0,0,0,0,0,0,0,0,0,0,"Tahoma");
|
|
pOldFont=pDC->SelectObject(&fntArial);
|
|
|
|
// draw those suckers...
|
|
PlotPen.CreatePen(PS_SOLID,1,PenCols[1]);
|
|
pOldPen=pDC->SelectObject( &PlotPen );
|
|
for(i=0;i<NumPts;i++)
|
|
{
|
|
pDC->MoveTo( (int)Pts[i].re-2, (int)Pts[i].im-2);
|
|
pDC->LineTo( (int)Pts[i].re-2, (int)Pts[i].im+2);
|
|
pDC->LineTo( (int)Pts[i].re+2, (int)Pts[i].im+2);
|
|
pDC->LineTo( (int)Pts[i].re+2, (int)Pts[i].im-2);
|
|
pDC->LineTo( (int)Pts[i].re-2, (int)Pts[i].im-2);
|
|
}
|
|
pDC->SelectObject(pOldPen);
|
|
PlotPen.DeleteObject();
|
|
|
|
for(i=1;i<NumCols;i++){
|
|
PlotPen.CreatePen(PS_SOLID,1,PenCols[i-1]);
|
|
pOldPen=pDC->SelectObject( &PlotPen );
|
|
pDC->MoveTo((int)M[0][0],(int)M[0][i]);
|
|
for(j=0;j<NumRows;j++)
|
|
pDC->LineTo((int)M[j][0],(int)M[j][i]);
|
|
pDC->SetTextColor(PenCols[i-1]);
|
|
pDC->TextOut((int)(OffsetX+Width+10.),((int) OffsetY)+14*i,lbls[i],(int) strlen(lbls[i]));
|
|
pDC->SelectObject(pOldPen); PlotPen.DeleteObject();
|
|
}
|
|
pDC->SetTextColor(0x00000000);
|
|
pDC->TextOut(200,(int) (OffsetY+Height+30),lbls[0],(int) strlen(lbls[0]));
|
|
k=(int)((HiY-LoY)/dy + 0.5);
|
|
if(k<4){
|
|
k*=2;
|
|
dy/=2.;
|
|
}
|
|
if(k==0) k++;
|
|
pDC->SetTextAlign(TA_RIGHT);
|
|
for(i=0;i<=k;i++){
|
|
pDC->MoveTo((int) OffsetX,(i*(int)Height)/k +(int) OffsetY);
|
|
pDC->LineTo((int) OffsetX-5,(i*(int) Height)/k+ (int) OffsetY);
|
|
sprintf(s,"%.4g",HiY-((double) i)*dy);
|
|
pDC->TextOut(((int) OffsetX)-10,(i*(int)Height)/k +(int) OffsetY-6,s,(int) strlen(s));
|
|
}
|
|
k=(int)((HiX-LoX)/dx);
|
|
if((k<4) && (!logscale)){
|
|
dx/=2.;
|
|
k=(int)((HiX-LoX)/dx);
|
|
}
|
|
d=( ((double) Width) * dx/ (HiX-LoX));
|
|
pDC->SetTextAlign(TA_CENTER);
|
|
for(i=0;i<=k;i++){
|
|
pDC->MoveTo((int) (((double) i)*d + OffsetX),(int) (OffsetY+Height));
|
|
pDC->LineTo((int) (((double) i)*d + OffsetX),(int) (OffsetY+Height)+5);
|
|
if(logscale) sprintf(s,"%g",pow((double)10,LoX+((double) i)*dx));
|
|
else sprintf(s,"%.0f",LoX+((double) i)*dx);
|
|
pDC->TextOut((int)(((double) i)*d + OffsetX),(int) OffsetY+(int)Height+10,s,(int) strlen(s));
|
|
}
|
|
pDC->SetTextAlign(TA_LEFT);
|
|
|
|
|
|
pDC->SelectObject(pOldFont);
|
|
}
|
|
|
|
BOOL CBHPlot::ToDisk()
|
|
{
|
|
FILE *fp;
|
|
int i,j;
|
|
CString dest_name;
|
|
|
|
if((NumCols==0) || (NumRows==0)){
|
|
MsgBox("No data to write to disk.");
|
|
return FALSE;
|
|
}
|
|
|
|
CFileDialog *fname_dia=new CFileDialog(
|
|
FALSE,
|
|
"txt | * ",
|
|
dest_name,
|
|
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
|
|
"Text Files (*.txt) | *.txt; *.TXT | All Files (*.*) | *.*||",
|
|
NULL);
|
|
|
|
if(fname_dia->DoModal()==IDCANCEL){
|
|
delete[] fname_dia;
|
|
return FALSE;
|
|
}
|
|
|
|
dest_name=fname_dia->GetPathName();
|
|
|
|
delete[] fname_dia;
|
|
|
|
if((fp=fopen(dest_name,"wt"))!=NULL){
|
|
for(i=0;i<NumCols;i++)
|
|
fprintf(fp,"#Column %i: %s\n",i,lbls[i]);
|
|
for(i=0;i<NumRows;i++){
|
|
for(j=0;j<NumCols;j++)
|
|
fprintf(fp,"%e ",M[i][j]);
|
|
fprintf(fp,"\n");
|
|
}
|
|
fclose(fp);
|
|
CString OutMsg="Output written to "+ dest_name;
|
|
AfxMessageBox(OutMsg,MB_ICONINFORMATION);
|
|
}
|
|
else{
|
|
MsgBox("Couldn't open output file");
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|