00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 #include <math.h>
00039 #include <memory.h>
00040 #include <float.h>
00041 #include <string.h>
00042 #include <ctype.h>
00043 #include "Plot2D.h"
00044 
00045 #define PLOT2D_MAX_PLO2D_ReadFromFile_BUFFER (8192)
00046 
00047 #ifndef _CRT_SECURE_NO_DEPRECATE
00048 #define _CRT_SECURE_NO_DEPRECATE
00049 #endif
00050 
00051 
00052 namespace namespace_Plot2D
00053 {
00054   
00055 
00056 
00057 
00058   typedef struct _listItem
00059   {
00060     bool    isReal;    
00061     double  *rowptr;   
00062     struct _listItem  *next;  
00063   } _PLOT2D_structReadFromFileListElem;
00064 
00065 
00066   
00067 
00068 
00069 
00070   static bool _PLOT2D_get_next_valid_data_line( 
00071     FILE *in,               
00072     char *linebuf,          
00073     unsigned *line_length,  
00074     bool *atEOF             
00075     );
00076 
00077 
00078   static bool _PLOT2D_get_row_array_from_string( char *datastr, _PLOT2D_structReadFromFileListElem *L, const unsigned ncols );
00079 
00080 
00081 
00082   static bool _PLO2D_determine_nr_cols_in_data_str( const char *datastr, unsigned *ncols );
00083 
00084 
00085 
00086 
00087   static bool _PLOT2D_determine_file_delimiter( 
00088     const char *path,    
00089     char *delimiter,     
00090     bool *hasComment     
00091     );
00092 
00093 
00094 
00095 
00096   static bool _PLOT2D_ReadFromFile( Plot2D::_PLOT2D_structMTX *M, const char *path );
00097 
00098 
00099   
00100   
00101 
00102   bool _PLOT2D_get_next_valid_data_line( 
00103     FILE *in,               
00104     char *linebuf,          
00105     unsigned *line_length,  
00106     bool *atEOF             
00107     )
00108   {
00109     unsigned i = 0;
00110     i = 0;
00111     *line_length = 0;
00112     while( i == *line_length )
00113     {
00114       if( fgets( linebuf, PLOT2D_MAX_PLO2D_ReadFromFile_BUFFER, in ) == NULL )
00115       {
00116         *atEOF = true;
00117         if( feof(in) )
00118         {
00119           
00120           fclose(in);        
00121           return true;
00122         }
00123         else if( ferror(in) != 0 )
00124         {
00125           
00126           fclose(in);
00127           return false;        
00128         }
00129         else
00130         {
00131           
00132           fclose(in);
00133           return false;
00134         }
00135       }  
00136 
00137       *line_length = (unsigned int)strlen(linebuf);
00138       for( i = 0; i < *line_length; i++ )
00139       {
00140         if( !isspace(linebuf[i]) )
00141           break;
00142       }
00143     }
00144 
00145     
00146     if( *line_length < PLOT2D_MAX_PLO2D_ReadFromFile_BUFFER-2 )
00147     {
00148       linebuf[*line_length] = '\0';
00149       linebuf[(*line_length)+1] = '\0';
00150     }
00151 
00152     return true;
00153   }
00154 
00155 
00156 
00157   bool _PLOT2D_determine_file_delimiter( 
00158     const char *path,    
00159     char *delimiter,     
00160     bool *hasComment     
00161     )
00162   { 
00163     unsigned i = 0;
00164     unsigned line_length = 0;   
00165     char line[PLOT2D_MAX_PLO2D_ReadFromFile_BUFFER];
00166     char *linebuf;  
00167     FILE *in;
00168     bool atEOF = false;
00169 
00170     *hasComment = false;
00171 
00172     
00173     in = fopen( path, "r" );
00174     if( !in )
00175       return false;
00176 
00177     
00178     if( !_PLOT2D_get_next_valid_data_line( in, line, &line_length, &atEOF ) )
00179       return false;
00180     if( atEOF )
00181       return false;
00182 
00183     
00184     linebuf = (char *)line;
00185     for( i = 0; i < line_length; i++ )
00186     {
00187       if( isalpha( line[i] ) )
00188       {
00189         if( line[i] == 'e' || line[i] == 'E' || line[i] == '-' || line[i] == '+' || line[i] == '.' || line[i] == 'i' || line[i] == 'j' )
00190           continue;
00191 
00192         
00193         *hasComment = true;
00194 
00195         if( !_PLOT2D_get_next_valid_data_line( in, line, &line_length, &atEOF ) )
00196           return false;
00197         if( atEOF )
00198           return false;      
00199 
00200         linebuf = (char *)line;
00201         break;
00202       }
00203     }
00204     fclose( in ); 
00205 
00206     
00207     *delimiter = 'w';
00208 
00209     if( strstr( linebuf, "," ) )  { *delimiter = ','; return true; }
00210     if( strstr( linebuf, ":" ) )  { *delimiter = ':'; return true; }
00211     if( strstr( linebuf, ";" ) )  { *delimiter = ';'; return true; }
00212     if( strstr( linebuf, "|" ) )  { *delimiter = '|'; return true; }
00213     if( strstr( linebuf, "`" ) )  { *delimiter = '`'; return true; }
00214     if( strstr( linebuf, "~" ) )  { *delimiter = '~'; return true; }
00215     if( strstr( linebuf, "!" ) )  { *delimiter = '!'; return true; }
00216     if( strstr( linebuf, "@" ) )  { *delimiter = '@'; return true; }
00217     if( strstr( linebuf, "#" ) )  { *delimiter = '#'; return true; }
00218     if( strstr( linebuf, "$" ) )  { *delimiter = '$'; return true; }
00219     if( strstr( linebuf, "%%" ) ) { *delimiter = '%'; return true; }
00220     if( strstr( linebuf, "^" ) )  { *delimiter = '^'; return true; }
00221     if( strstr( linebuf, "&" ) )  { *delimiter = '&'; return true; }
00222     if( strstr( linebuf, "*" ) )  { *delimiter = '*'; return true; }
00223     if( strstr( linebuf, "(" ) )  { *delimiter = '('; return true; }
00224     if( strstr( linebuf, ")" ) )  { *delimiter = ')'; return true; }
00225     if( strstr( linebuf, "_" ) )  { *delimiter = '_'; return true; }
00226     if( strstr( linebuf, "=" ) )  { *delimiter = '='; return true; }
00227     if( strstr( linebuf, "{" ) )  { *delimiter = '{'; return true; }
00228     if( strstr( linebuf, "}" ) )  { *delimiter = '}'; return true; }
00229     if( strstr( linebuf, "[" ) )  { *delimiter = '['; return true; }
00230     if( strstr( linebuf, "]" ) )  { *delimiter = ']'; return true; }
00231     if( strstr( linebuf, "\\" ) ) { *delimiter = '\\'; return true; }
00232     if( strstr( linebuf, "\'" ) ) { *delimiter = '\''; return true; }
00233     if( strstr( linebuf, "<" ) )  { *delimiter = '<'; return true; }
00234     if( strstr( linebuf, "<" ) )  { *delimiter = '<'; return true; }
00235     if( strstr( linebuf, ">" ) )  { *delimiter = '>'; return true; }
00236     if( strstr( linebuf, "?" ) )  { *delimiter = '?'; return true; }
00237     if( strstr( linebuf, "/" ) )  { *delimiter = '/'; return true; }
00238 
00239     return true;
00240   }
00241 
00242 
00243 
00244   bool _PLO2D_determine_nr_cols_in_data_str( const char *datastr, unsigned *ncols )
00245   { 
00246     unsigned i = 0;
00247     unsigned line_length;
00248     char c;
00249     bool wasLastCharData = false;
00250     double dtmp;
00251     int rv;
00252 
00253     if( !datastr )
00254       return false;
00255 
00256     line_length = (unsigned int)strlen(datastr);
00257     if( line_length == 0 )
00258       return false;
00259 
00260     
00261     *ncols = 0;
00262 
00263     
00264     for( i = 0; i < line_length; i++ )
00265     {
00266       if( isspace(datastr[i]) )         
00267         continue;
00268       else 
00269         break;
00270     }  
00271     if( i == line_length )
00272     {
00273       
00274       return false;
00275     }
00276 
00277     
00278     for( ; i < line_length; i++ )
00279     {
00280       c = datastr[i];
00281       if( isdigit(c) || c == '.' || c == '-' || c == '+' )
00282       {
00283         if( !wasLastCharData )
00284         {
00285           
00286 #ifndef _CRT_SECURE_NO_DEPRECATE
00287           rv = sscanf_s( &(datastr[i]), "%lf", &dtmp );
00288 #else
00289           rv = sscanf( &(datastr[i]), "%lf", &dtmp );
00290 #endif
00291           if( rv == 0 || rv == EOF )
00292           {
00293             
00294             (*ncols) = 0;
00295             return false;          
00296           }
00297           (*ncols)++;
00298         }
00299         wasLastCharData = true;
00300       }
00301       else if( c == 'e' || c == 'E' )
00302       {
00303         if( !wasLastCharData )
00304         {
00305           
00306           
00307           (*ncols) = 0;
00308           return false;
00309         }
00310         continue;
00311       }
00312       else
00313       {
00314         wasLastCharData = false;
00315       }
00316     }
00317 
00318     return true;
00319   }
00320 
00321 
00322   bool _PLOT2D_get_row_array_from_string( char *datastr, _PLOT2D_structReadFromFileListElem *L, const unsigned ncols )
00323   {
00324     unsigned i = 0;
00325     unsigned n; 
00326     unsigned line_length;
00327     char c;
00328     BOOL wasLastCharData = false;
00329     int rv;
00330 
00331     if( !datastr )
00332       return false;
00333 
00334     if( !L )
00335       return false;
00336 
00337     if( !L->rowptr )
00338       return false;
00339 
00340     line_length = (unsigned int)strlen(datastr);
00341     if( line_length == 0 )
00342       return false;
00343 
00344     
00345     for( i = 0; i < line_length; i++ )
00346     {
00347       if( isspace(datastr[i]) )         
00348         continue;
00349       else 
00350         break;
00351     }  
00352     if( i == line_length )
00353     {
00354       
00355       return false;
00356     }
00357 
00358     
00359     n = 0;  
00360     for( ; i < line_length; i++ )
00361     {
00362       c = datastr[i];
00363       if( isdigit(c) || c == '.' || c == '-' || c == '+' )
00364       {
00365         if( !wasLastCharData )
00366         {
00367           
00368 #ifndef _CRT_SECURE_NO_DEPRECATE
00369           rv = sscanf_s( &(datastr[i]), "%lf", &(L->rowptr[n]) );
00370 #else
00371           rv = sscanf( &(datastr[i]), "%lf", &(L->rowptr[n]) );
00372 #endif
00373           if( rv == 0 || rv == EOF )
00374           {
00375             
00376             return false;          
00377           }
00378           n++;
00379           if( n == ncols )
00380             break;
00381         }
00382         wasLastCharData = true;
00383       }
00384       else if( c == 'e' || c == 'E' )
00385       {
00386         if( !wasLastCharData )
00387         {
00388           
00389           
00390           return false;
00391         }
00392         continue;
00393       }
00394       else
00395       {
00396         wasLastCharData = false;
00397       }
00398     }
00399 
00400     if( n != ncols )
00401     {
00402       
00403       return false;
00404     }
00405 
00406     return true;
00407   }
00408 
00409 
00410 
00411 
00412   
00413   
00414   
00415   
00416   bool _PLOT2D_ReadFromFile( Plot2D::_PLOT2D_structMTX *M, const char *path )
00417   {
00418     unsigned i = 0;
00419     unsigned j = 0;
00420     FILE *in = NULL;
00421     char delimiter = 0;
00422     char linebuf[PLOT2D_MAX_PLO2D_ReadFromFile_BUFFER];
00423     unsigned ncols = 0;
00424     unsigned nrows = 0;
00425     unsigned line_length = 0;
00426     bool hasCommentLine = false;  
00427     bool errorInReadingDataFile = false;
00428     bool atEOF = false;
00429 
00430     
00431     _PLOT2D_structReadFromFileListElem *L = NULL;
00432     _PLOT2D_structReadFromFileListElem *nL = NULL;
00433     _PLOT2D_structReadFromFileListElem head;
00434     head.next = NULL;
00435     head.rowptr = NULL;
00436 
00437     
00438     if( !M )
00439       return false;
00440 
00441     M->data = NULL;
00442     M->nrows = 0;
00443     M->ncols = 0;
00444 
00445     
00446     if( !path  )
00447       return false;
00448 
00449     
00450     in = fopen( path, "r" );
00451     if( !in )
00452       return false;
00453     fclose(in);
00454 
00455     
00456     if( _PLOT2D_determine_file_delimiter( path, &delimiter, &hasCommentLine ) == false )  
00457       return false;
00458 
00459     
00460     in = fopen( path, "r" );
00461     if( !in )
00462       return false;
00463 
00464     
00465     if( !_PLOT2D_get_next_valid_data_line( in, linebuf, &line_length, &atEOF ) )
00466       return false;
00467     if( atEOF )
00468       return false;
00469 
00470     if( hasCommentLine )
00471     {
00472       if( !_PLOT2D_get_next_valid_data_line( in, linebuf, &line_length, &atEOF ) )
00473         return false;
00474       if( atEOF )
00475         return false;
00476     }
00477 
00478     
00479     if( _PLO2D_determine_nr_cols_in_data_str( linebuf, &ncols ) == false )
00480       return false;
00481 
00482 
00483     
00484     
00485     
00486     nrows = 0;
00487     head.rowptr = (double*)malloc( ncols*sizeof(double) );
00488     
00489     if( _PLOT2D_get_row_array_from_string( linebuf, &head, ncols ) == false )
00490     { 
00491       
00492       free( head.rowptr );
00493       return false;
00494     }
00495     nrows++;
00496     nL = &head;
00497 
00498     while(1)
00499     { 
00500       
00501       if( !_PLOT2D_get_next_valid_data_line( in, linebuf, &line_length, &atEOF ) )
00502       {
00503         errorInReadingDataFile = true;
00504         break;
00505       }
00506       if( atEOF )
00507       {
00508         break;
00509       }
00510 
00511       
00512       L = nL;
00513 
00514       
00515       nL = (_PLOT2D_structReadFromFileListElem*)malloc( sizeof( _PLOT2D_structReadFromFileListElem ) );
00516       if( !nL )
00517       {
00518         
00519         
00520         errorInReadingDataFile = true;
00521         
00522         free( head.rowptr );
00523         return false;
00524       }
00525       
00526       nL->rowptr = NULL;
00527       nL->next = NULL;
00528       
00529       nL->rowptr = (double*)malloc( ncols*sizeof(double) );
00530       if( !nL->rowptr )
00531       {
00532         
00533         
00534         errorInReadingDataFile = true;
00535         break;      
00536       }
00537 
00538       
00539       
00540       L->next = nL;
00541 
00542       
00543       if( _PLOT2D_get_row_array_from_string( linebuf, nL, ncols ) == false )
00544       { 
00545         
00546         errorInReadingDataFile = true;
00547         break;      
00548       }
00549       nrows++;
00550     }
00551 
00552     if( errorInReadingDataFile )
00553     {
00554       
00555       L = head.next;
00556       while( L!=NULL )
00557       {
00558         nL = L->next;
00559         free( L->rowptr );
00560         free(L);
00561         L = nL;    
00562       }
00563       free( head.rowptr );
00564 
00565       return false;
00566     }
00567 
00568     
00569 
00570     
00571     M->data = (double*)malloc( nrows*ncols*sizeof(double) );
00572     if( !M->data )
00573       return false;
00574 
00575     L = &head;
00576     for( i = 0; i < nrows; i++ )
00577     {
00578       if( L == NULL )
00579       {
00580         
00581         free( M->data );
00582         return false;
00583       }
00584       memcpy( &(M->data[i*ncols]), L->rowptr, sizeof(double)*ncols );
00585       free( L->rowptr );
00586       L->rowptr = NULL;
00587       L = L->next;
00588     }
00589 
00590     
00591     L = head.next;
00592     while( L!=NULL )
00593     {
00594       nL = L->next;
00595       if( L->rowptr )
00596       {
00597         
00598         free( L->rowptr );
00599       }        
00600       free(L);
00601       L = nL;    
00602     }
00603     
00604     if( head.rowptr )
00605     {
00606       
00607       free( head.rowptr );
00608     }
00609 
00610     M->nrows = nrows;
00611     M->ncols = ncols;
00612 
00613     return true;
00614   }  
00615 
00616 
00617   Plot2D::~Plot2D()
00618   {
00619     int i = 0;
00620 
00621     if( m_mtx.data != NULL )
00622     {
00623       free( m_mtx.data );
00624       m_mtx.data = NULL;
00625     }
00626     for( i = 0; i < 12; i++ )
00627     {
00628       if( m_Series[i].X != NULL )
00629       {
00630         free(m_Series[i].X);
00631         m_Series[i].X = NULL;
00632       }
00633       if( m_Series[i].Y != NULL )
00634       {
00635         free(m_Series[i].Y);
00636         m_Series[i].Y = NULL;
00637       }
00638     }
00639   }
00640 
00641 
00642   Plot2D::Plot2D()
00643     : m_ArePlotOptionsSet(false),
00644     m_xmin(DBL_MAX),
00645     m_xmax(-DBL_MAX),
00646     m_ymin(DBL_MAX),
00647     m_ymax(-DBL_MAX)
00648   {
00649     int i = 0;    
00650     CPLOT_PlotOptionsInit( &m_opt );
00651     CPLOT_Init( &m_plot );
00652 
00653     for( i = 0; i < 12; i++ )
00654     {
00655       memset( &m_Series[i], 0, sizeof(CPLOT_structSeries) );
00656     }
00657   }
00658 
00659   void Plot2D::SetTitle( const std::string title )
00660   {
00661     m_title = title;
00662     m_opt.title = (char*)m_title.c_str();
00663   }
00664 
00665   bool Plot2D::SetNrSeries( const int nrSeries )
00666   {
00667     if( nrSeries >= 12 )
00668       return false;
00669 
00670     m_opt.numberOfSeries = nrSeries;
00671 
00672     return true;
00673   }
00674 
00675   bool Plot2D::SetPlotSize( const int width_cm, const int height_cm )
00676   {
00677     if( width_cm <= 0 || height_cm <= 0 )
00678       return false;
00679 
00680     m_opt.PlotSize_Width_cm = width_cm;
00681     m_opt.PlotSize_Height_cm = height_cm;
00682 
00683     return true;
00684   }
00685 
00686   bool Plot2D::Set_X_Axis_LowerLimit( const double value )
00687   {
00688     m_opt.x.lowerlimit.doNotUseDefault = true;
00689     m_opt.x.lowerlimit.val = value;    
00690 
00691     if( m_opt.x.upperlimit.doNotUseDefault )
00692     {
00693       if( m_opt.x.lowerlimit.val >= m_opt.x.upperlimit.val )
00694         return false;
00695 
00696     }
00697     return true;
00698   }
00699 
00700   bool Plot2D::Set_X_Axis_UpperLimit( const double value )
00701   {
00702     m_opt.x.upperlimit.doNotUseDefault = true;
00703     m_opt.x.upperlimit.val = value;    
00704 
00705     if( m_opt.x.lowerlimit.doNotUseDefault )
00706     {
00707       if( m_opt.x.lowerlimit.val >= m_opt.x.upperlimit.val )
00708         return false;
00709 
00710     }
00711     return true;
00712   }
00713 
00714   bool Plot2D::Set_X_Axis_TickStart( const double value )
00715   {
00716     m_opt.x.tickstart.doNotUseDefault = true;
00717     m_opt.x.tickstart.val = value;    
00718 
00719     if( m_opt.x.tickend.doNotUseDefault )
00720     {
00721       if( m_opt.x.tickstart.val >= m_opt.x.tickend.val )
00722         return false;
00723     }
00724     return true;
00725   }
00726 
00727   bool Plot2D::Set_X_Axis_TickSize( const double value )
00728   {
00729     m_opt.x.ticksize.doNotUseDefault = true;
00730     m_opt.x.ticksize.val = value;    
00731     return true;
00732   }
00733 
00734   bool Plot2D::Set_X_Axis_TickEnd( const double value )
00735   {
00736     m_opt.x.tickend.doNotUseDefault = true;
00737     m_opt.x.tickend.val = value;    
00738 
00739     if( m_opt.x.tickstart.doNotUseDefault )
00740     {
00741       if( m_opt.x.tickstart.val >= m_opt.x.tickend.val )
00742         return false;
00743     }
00744     return true;
00745   }
00746 
00747   bool Plot2D::Set_X_Label( const std::string label )
00748   {
00749     m_x_label = label;
00750     m_opt.x.label = (char*)m_x_label.c_str();
00751     return true;
00752   }
00753 
00754   bool Plot2D::Set_Y_Label( const std::string label )
00755   {
00756     m_y_label = label;
00757     m_opt.y.label = (char*)m_y_label.c_str();
00758     return true;
00759   }
00760 
00761   bool Plot2D::Set_X_Axis_isGridOn( const bool isGridOn )
00762   {
00763     m_opt.x.isGridOn = isGridOn;
00764     return true;
00765   }
00766 
00767   bool Plot2D::Set_Y_Axis_isGridOn( const bool isGridOn )
00768   {
00769     m_opt.y.isGridOn = isGridOn;
00770     return true;
00771   }
00772 
00773 
00774 
00775   bool Plot2D::Set_Y_Axis_LowerLimit( const double value )
00776   {
00777     m_opt.y.lowerlimit.doNotUseDefault = true;
00778     m_opt.y.lowerlimit.val = value;    
00779 
00780     if( m_opt.y.upperlimit.doNotUseDefault )
00781     {
00782       if( m_opt.y.lowerlimit.val >= m_opt.y.upperlimit.val )
00783         return false;
00784 
00785     }
00786     return true;
00787   }
00788 
00789   bool Plot2D::Set_Y_Axis_UpperLimit( const double value )
00790   {
00791     m_opt.y.upperlimit.doNotUseDefault = true;
00792     m_opt.y.upperlimit.val = value;    
00793 
00794     if( m_opt.y.lowerlimit.doNotUseDefault )
00795     {
00796       if( m_opt.y.lowerlimit.val >= m_opt.y.upperlimit.val )
00797         return false;
00798 
00799     }
00800     return true;
00801   }
00802 
00803   bool Plot2D::Set_Y_Axis_TickStart( const double value )
00804   {
00805     m_opt.y.tickstart.doNotUseDefault = true;
00806     m_opt.y.tickstart.val = value;    
00807 
00808     if( m_opt.y.tickend.doNotUseDefault )
00809     {
00810       if( m_opt.y.tickstart.val >= m_opt.y.tickend.val )
00811         return false;
00812     }
00813     return true;
00814   }
00815 
00816   bool Plot2D::Set_Y_Axis_TickSize( const double value )
00817   {
00818     m_opt.y.ticksize.doNotUseDefault = true;
00819     m_opt.y.ticksize.val = value;    
00820     return true;
00821   }
00822 
00823   bool Plot2D::Set_Y_Axis_TickEnd( const double value )
00824   {
00825     m_opt.y.tickend.doNotUseDefault = true;
00826     m_opt.y.tickend.val = value;    
00827 
00828     if( m_opt.y.tickstart.doNotUseDefault )
00829     {
00830       if( m_opt.y.tickstart.val >= m_opt.y.tickend.val )
00831         return false;
00832     }
00833     return true;
00834   }
00835 
00836   bool Plot2D::SetRightYLabel( 
00837     const std::string label,            
00838     double y_label_right_scale_factor,  
00839     double y_label_right_bias,          
00840     CPLOT_enumColor color               
00841     )
00842   {
00843     if( label.empty() )
00844       return false;
00845     m_y_label_right = label;
00846     
00847     m_opt.y_label_right = (char *)m_y_label_right.c_str();
00848     m_opt.y_label_right_scale_factor = y_label_right_scale_factor;
00849     m_opt.y_label_right_bias = y_label_right_bias;
00850     m_opt.RightYLabelColor = color;
00851     return true;
00852   }
00853 
00854   bool Plot2D::SetGPSLabel( const int UTCOffset )
00855   {
00856     if( UTCOffset < 0 )
00857       return false;
00858     m_opt.useGPSLabel = true;
00859     m_opt.UTCOffset = UTCOffset;
00860     return true;
00861   }
00862 
00863   bool Plot2D::SetBackgroundColor( const CPLOT_enumColor color )
00864   {
00865     m_opt.figureBackgroundColor = color;
00866     return true;
00867   }
00868     
00869 
00870   void Plot2D::EnablePlotStatistics( const bool enable )
00871   {
00872     m_opt.plotStatistics = enable;    
00873   }
00874 
00875   void Plot2D::SetTheSeriesLabelsBelowThePlot( const bool setBelow )
00876   {
00877     m_opt.plotLabelOnRight = !setBelow;
00878   }
00879 
00880   bool Plot2D::SavePlotToBitmapFile( std::string filename )
00881   {
00882     if( !CPLOT_SaveToFile( &m_plot, filename.c_str() ) )
00883       return false;
00884 
00885     return true;
00886   }
00887   
00888   bool Plot2D::SetSeriesInfo( const unsigned index, PLOT2D_structSeriesInfo &series )
00889   {
00890     unsigned i = 0;
00891     unsigned n = 0;         
00892     double *X = NULL;       
00893     double *Y = NULL;       
00894 
00895     double xmin = 0;
00896     double xmax = 0;
00897     double ymin = 0;
00898     double ymax = 0;
00899     
00900     if( index >= 12 )
00901       return false;
00902 
00903     if( index >= (unsigned)m_opt.numberOfSeries )
00904       return false;
00905 
00906     
00907     if( m_prev_datapath.compare( series.DataPath ) != 0 )
00908     {
00909       if( m_mtx.data != NULL )
00910       {
00911         free( m_mtx.data );
00912         m_mtx.data = NULL;
00913         m_mtx.ncols = 0;
00914         m_mtx.nrows = 0;
00915       }      
00916       if( series.DataPath.compare( "stdin" ) == 0 )
00917       {
00918         
00919         
00920         FILE* fid = NULL;
00921         char buffer[8192];
00922         size_t buffer_length = 0;
00923         fid = fopen("_plot2d_stdin_.tmp", "w" );
00924         if( fid == NULL )        
00925           return false;
00926         do
00927         {
00928           if( fgets( buffer, 8192, stdin ) == NULL )
00929             break;
00930           buffer_length = strlen( buffer );
00931           if( buffer_length > 0 )
00932             fprintf( fid, buffer ); 
00933         }
00934         while( buffer_length > 1 );
00935         fclose(fid);
00936 
00937         if( !_PLOT2D_ReadFromFile( &m_mtx, "_plot2d_stdin_.tmp" ) )
00938           return false;
00939 
00940         
00941         remove( "_plot2d_stdin_.tmp" );
00942       }
00943       else
00944       {
00945         if( !_PLOT2D_ReadFromFile( &m_mtx, series.DataPath.c_str() ) )
00946           return false;
00947       }
00948       m_prev_datapath = series.DataPath;
00949     }
00950 
00951     
00952     if( m_mtx.ncols == 1 && series.X_Column == 0 && series.Y_Column == 1 )
00953     {
00954       
00955       
00956       series.Y_Column = 0;
00957     }
00958 
00959     
00960     if( series.X_Column >= m_mtx.ncols )
00961     {
00962       return false;
00963     }
00964     if( series.Y_Column >= m_mtx.ncols )
00965     {
00966       return false;
00967     }
00968 
00969     n = m_mtx.nrows;
00970 
00971     
00972     X = (double*)malloc( n*sizeof(double) );
00973     if( !X )
00974     {      
00975       return false;
00976     }
00977     Y = (double*)malloc( n*sizeof(double) );
00978     if( !Y )
00979     {
00980       free( X );      
00981       return false;
00982     }
00983 
00984     
00985     if( series.X_Column == series.Y_Column && series.Y_Column == 0 && m_mtx.ncols == 1 )
00986     {
00987       for( i = 0; i < n; i++ )
00988       { 
00989         X[i] = i+1.0;
00990         Y[i] = m_mtx.data[i*m_mtx.ncols + series.Y_Column];
00991       }
00992     }
00993     else
00994     {
00995       for( i = 0; i < n; i++ )
00996       {      
00997         X[i] = m_mtx.data[i*m_mtx.ncols + series.X_Column];
00998         Y[i] = m_mtx.data[i*m_mtx.ncols + series.Y_Column];
00999       }
01000     }
01001     if( series.negate_X )
01002     {
01003       for( i = 0; i < n; i++ )
01004       {      
01005         X[i] *= -1;
01006       }
01007     }
01008     if( series.negate_Y )
01009     {
01010       for( i = 0; i < n; i++ )
01011       {      
01012         Y[i] *= -1;
01013       }
01014     }
01015     
01016     if( m_Series[index].X != NULL )
01017     {
01018       
01019       free( m_Series[index].X );
01020       m_Series[index].X = NULL;
01021     }
01022     if( m_Series[index].Y != NULL )
01023     {
01024       
01025       free( m_Series[index].Y );
01026       m_Series[index].Y = NULL;
01027     }
01028     m_Series[index].X = X;
01029     m_Series[index].Y = Y;
01030     m_Series[index].label = (char*)series.Label.c_str();
01031     m_Series[index].units = (char*)series.Units.c_str();
01032     m_Series[index].n = n;
01033     m_Series[index].connected = series.IsConnected;
01034     m_Series[index].markOutlierData = series.MarkOutlierData;
01035     m_Series[index].precision = series.Precision;
01036     m_Series[index].color = series.Color;
01037 
01038 
01039     
01040     
01041     
01042     xmin = DBL_MAX;
01043     xmax = -DBL_MAX;
01044     for( i = 0; i < n; i++ )
01045     {
01046       
01047       if( CPLOT_IsNAN( X[i] ) || CPLOT_IsPostiveINF( X[i] ) || CPLOT_IsNegativeINF( X[i] ) )
01048         continue;
01049 
01050       if( X[i] < xmin )
01051       {
01052         xmin = X[i];
01053       }
01054       if( X[i] > xmax )
01055       {
01056         xmax = X[i];
01057       }            
01058     }
01059 
01060     ymin = DBL_MAX;
01061     ymax = -DBL_MAX;
01062     for( i = 0; i < n; i++ )
01063     {
01064       
01065       if( CPLOT_IsNAN( Y[i] ) || CPLOT_IsPostiveINF( Y[i] ) || CPLOT_IsNegativeINF( Y[i] ) )
01066         continue;
01067 
01068       if( Y[i] < ymin )
01069       {
01070         ymin = Y[i];
01071       }
01072       if( Y[i] > ymax )
01073       {
01074         ymax = Y[i];
01075       }
01076     }
01077 
01078     if( xmin < m_xmin )
01079       m_xmin = xmin;
01080     if( xmax > m_xmax )
01081       m_xmax = xmax;
01082     if( ymin < m_ymin )
01083       m_ymin = ymin;
01084     if( ymax > m_ymax )
01085       m_ymax = ymax;
01086     
01087     return true;
01088   }
01089 
01090   bool Plot2D::PlotAll()
01091   {
01092     int i = 0;
01093     double val = 0;
01094     typedef struct 
01095     {
01096       double lowerlimit;
01097       double upperlimit;
01098       double tickstart;
01099       double ticksize;
01100       double tickend;
01101     } _structAxis;
01102     _structAxis x;
01103     _structAxis y;
01104     
01105     
01106     
01107     
01108     
01109 
01110     
01111     if( !m_opt.x.lowerlimit.doNotUseDefault &&
01112       !m_opt.x.upperlimit.doNotUseDefault &&
01113       !m_opt.x.tickstart.doNotUseDefault &&
01114       !m_opt.x.tickend.doNotUseDefault )
01115     {
01116       val = m_xmin;
01117       if( val < 0 )
01118       {
01119         val = -ceil( -val * 10.0 ) / 10.0;
01120       }
01121       else
01122       {
01123         val = floor( val * 10.0 ) / 10.0;        
01124       }
01125       x.lowerlimit = val;
01126 
01127       val = m_xmax;
01128       if( val < 0 )
01129       {
01130         val = -floor( -val * 10.0 ) / 10.0;      
01131       }
01132       else
01133       {
01134         val = ceil( val * 10.0 ) / 10.0;        
01135       }
01136       x.upperlimit = val;
01137 
01138 
01139       if( x.lowerlimit == x.upperlimit )
01140       {
01141         x.lowerlimit -= x.lowerlimit/100.0;
01142         x.upperlimit += x.upperlimit/100.0;
01143       }
01144 
01145       x.tickstart = x.lowerlimit;
01146       x.ticksize = (x.upperlimit-x.lowerlimit)/5.0; 
01147       x.tickend = x.upperlimit;
01148     }
01149     else 
01150     {  
01151       
01152 
01153       if( m_opt.x.lowerlimit.doNotUseDefault )
01154         x.lowerlimit = m_opt.x.lowerlimit.val;
01155       else
01156         x.lowerlimit = m_xmin;
01157 
01158       if( m_opt.x.upperlimit.doNotUseDefault )
01159         x.upperlimit = m_opt.x.upperlimit.val;
01160       else
01161         x.upperlimit = m_xmax;
01162 
01163       if( m_opt.x.tickstart.doNotUseDefault )
01164         x.tickstart = m_opt.x.tickstart.val;
01165       else
01166         x.tickstart = x.lowerlimit;
01167 
01168       if( m_opt.x.tickend.doNotUseDefault )
01169         x.tickend = m_opt.x.tickend.val;
01170       else
01171         x.tickend = x.upperlimit;
01172 
01173       if( m_opt.x.ticksize.doNotUseDefault )
01174         x.ticksize = m_opt.x.ticksize.val;
01175       else
01176         x.ticksize = (x.tickend - x.tickstart)/5.0;
01177     }
01178     if( x.lowerlimit == x.upperlimit )
01179       return false;
01180     if( x.tickstart == x.tickend )
01181       return false;
01182     if( x.ticksize <= 0.0 )
01183       return false;
01184 
01185 
01186 
01187     
01188     if( !m_opt.y.lowerlimit.doNotUseDefault &&
01189       !m_opt.y.upperlimit.doNotUseDefault &&
01190       !m_opt.y.tickstart.doNotUseDefault &&
01191       !m_opt.y.tickend.doNotUseDefault )
01192     {
01193       val = m_ymin;
01194       if( val < 0 )
01195       {
01196         val = -ceil( -val * 10.0 ) / 10.0;
01197       }
01198       else
01199       {
01200         val = floor( val * 10.0 ) / 10.0;        
01201       }
01202       y.lowerlimit = val;
01203 
01204       val = m_ymax;
01205       if( val < 0 )
01206       {
01207         val = -floor( -val * 10.0 ) / 10.0;      
01208       }
01209       else
01210       {
01211         val = ceil( val * 10.0 ) / 10.0;        
01212       }
01213       y.upperlimit = val;
01214 
01215 
01216       if( y.lowerlimit == y.upperlimit )
01217       {
01218         y.lowerlimit -= y.lowerlimit/100.0;
01219         y.upperlimit += y.upperlimit/100.0;
01220       }
01221 
01222       y.tickstart = y.lowerlimit;
01223       y.ticksize = (y.upperlimit-y.lowerlimit)/10.0; 
01224       y.tickend = y.upperlimit;
01225     }
01226     else 
01227     {  
01228       
01229 
01230       if( m_opt.y.lowerlimit.doNotUseDefault )
01231         y.lowerlimit = m_opt.y.lowerlimit.val;
01232       else
01233         y.lowerlimit = m_ymin;
01234 
01235       if( m_opt.y.upperlimit.doNotUseDefault )
01236         y.upperlimit = m_opt.y.upperlimit.val;
01237       else
01238         y.upperlimit = m_ymax;
01239 
01240       if( m_opt.y.tickstart.doNotUseDefault )
01241         y.tickstart = m_opt.y.tickstart.val;
01242       else
01243         y.tickstart = y.lowerlimit;
01244 
01245       if( m_opt.y.tickend.doNotUseDefault )
01246         y.tickend = m_opt.y.tickend.val;
01247       else
01248         y.tickend = y.upperlimit;
01249 
01250       if( m_opt.y.ticksize.doNotUseDefault )
01251         y.ticksize = m_opt.y.ticksize.val;
01252       else
01253         y.ticksize = (y.tickend - y.tickstart)/10.0;
01254     }
01255     if( y.lowerlimit == y.upperlimit )
01256       return false;
01257     if( y.tickstart == y.tickend )
01258       return false;  
01259     if( y.ticksize <= 0.0 )
01260       return false;
01261 
01262     
01263 
01264     m_opt.x.lowerlimit.val = x.lowerlimit;
01265     m_opt.x.upperlimit.val = x.upperlimit;
01266     m_opt.x.tickstart.val = x.tickstart;
01267     m_opt.x.ticksize.val = x.ticksize;
01268     m_opt.x.tickend.val = x.tickend;
01269 
01270     m_opt.x.lowerlimit.doNotUseDefault = TRUE;
01271     m_opt.x.upperlimit.doNotUseDefault = TRUE;
01272     m_opt.x.tickstart.doNotUseDefault = TRUE;
01273     m_opt.x.ticksize.doNotUseDefault = TRUE;
01274     m_opt.x.tickend.doNotUseDefault = TRUE;
01275 
01276     m_opt.y.lowerlimit.val = y.lowerlimit;
01277     m_opt.y.upperlimit.val = y.upperlimit;
01278     m_opt.y.tickstart.val = y.tickstart;
01279     m_opt.y.ticksize.val = y.ticksize;
01280     m_opt.y.tickend.val = y.tickend;
01281 
01282     m_opt.y.lowerlimit.doNotUseDefault = TRUE;
01283     m_opt.y.upperlimit.doNotUseDefault = TRUE;
01284     m_opt.y.tickstart.doNotUseDefault = TRUE;
01285     m_opt.y.ticksize.doNotUseDefault = TRUE;
01286     m_opt.y.tickend.doNotUseDefault = TRUE;
01287 
01288     if( !CPLOT_SetPlotOptions( &m_plot, &m_opt ) )
01289       return false;
01290     m_ArePlotOptionsSet = true;
01291 
01292     for( i = 0; i < m_opt.numberOfSeries; i++ )
01293     {
01294       if( m_Series[i].X == NULL ||  m_Series[i].Y == NULL )
01295         return false;
01296 
01297       if( !CPLOT_Plot( &m_plot, &m_Series[i] ) )
01298       {
01299         free( m_Series[i].X );
01300         free( m_Series[i].Y );
01301         m_Series[i].X = NULL;
01302         m_Series[i].Y = NULL;        
01303         return false;
01304       }
01305 
01306       free( m_Series[i].X );
01307       free( m_Series[i].Y );
01308       m_Series[i].X = NULL;
01309       m_Series[i].Y = NULL;
01310     }
01311 
01312     return true;
01313   }
01314 
01315   bool Plot2D::Plot( PLOT2D_structSeriesInfo &series )
01316   {
01317     unsigned i = 0;
01318     unsigned n = 0;         
01319     double *X = NULL;       
01320     double *Y = NULL;       
01321     CPLOT_structSeries s;   
01322 
01323     memset( &s, 0, sizeof(CPLOT_structSeries) );
01324     
01325     if( !m_ArePlotOptionsSet )
01326     {
01327       if( !CPLOT_SetPlotOptions( &m_plot, &m_opt ) )
01328         return false;
01329       m_ArePlotOptionsSet = true;
01330     }
01331 
01332     if( m_prev_datapath.compare( series.DataPath ) != 0 )
01333     {
01334       if( m_mtx.data != NULL )
01335       {
01336         free( m_mtx.data );
01337         m_mtx.data = NULL;
01338         m_mtx.ncols = 0;
01339         m_mtx.nrows = 0;
01340       }
01341       if( !_PLOT2D_ReadFromFile( &m_mtx, series.DataPath.c_str() ) )
01342         return false;
01343       m_prev_datapath = series.DataPath;
01344     }
01345 
01346     
01347     if( series.X_Column >= m_mtx.ncols )
01348     {
01349       return false;
01350     }
01351     if( series.Y_Column >= m_mtx.ncols )
01352     {
01353       return false;
01354     }
01355 
01356     n = m_mtx.nrows;
01357 
01358     
01359     X = (double*)malloc( n*sizeof(double) );
01360     if( !X )
01361     {
01362       return false;
01363     }
01364     Y = (double*)malloc( n*sizeof(double) );
01365     if( !Y )
01366     {
01367       free( X );
01368       return false;
01369     }
01370 
01371     
01372     for( i = 0; i < n; i++ )
01373     {
01374       X[i] = m_mtx.data[i*m_mtx.ncols + series.X_Column];
01375       Y[i] = m_mtx.data[i*m_mtx.ncols + series.Y_Column];
01376     }
01377 
01378     s.X = X;
01379     s.Y = Y;
01380     s.label = (char*)series.Label.c_str();
01381     s.units = (char*)series.Units.c_str();
01382     s.n = n;
01383     s.connected = series.IsConnected;
01384     s.markOutlierData = series.MarkOutlierData;
01385     s.precision = series.Precision;
01386     s.color = series.Color;
01387     
01388     if( !CPLOT_Plot( &m_plot, &s ) )
01389     {
01390       free( X );
01391       free( Y );
01392       X = NULL;
01393       Y = NULL;
01394       s.X = NULL;
01395       s.Y = NULL;        
01396       return false;
01397     }
01398 
01399     free( X );
01400     free( Y );
01401     X = NULL;
01402     Y = NULL;
01403     s.X = NULL;
01404     s.Y = NULL;    
01405     return true;
01406   }
01407 
01408 
01409 
01410   
01411 } 
01412