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