UltraScan III
us_plot3d_xyz.cpp
Go to the documentation of this file.
1 
3 #include "us_widgets.h"
4 #include "us_plot3d_xyz.h"
5 #include "us_math2.h"
6 #include "us_settings.h"
7 #include "us_gui_settings.h"
8 #include "us_colorgradIO.h"
9 #include <qwt_legend.h>
10 #include <qwt3d_plot.h>
11 
12 using namespace Qwt3D;
13 //using namespace std;
14 
15 // constructor: 3-d plot mainwindow widget
16 US_Plot3Dxyz::US_Plot3Dxyz( QWidget* p = 0, QVector< QVector3D >* d = 0 )
17  : QMainWindow( p, Qt::Dialog )
18 {
19  xyzdat = d;
21  ncols = nrows = 0;
22 
23  // lay out the GUI
24  setWindowTitle( tr( "XYZ Data 3-Dimensional Viewer" ) );
25  setPalette( US_GuiSettings::frameColor() );
26 #ifndef Q_WS_MAC
27  setAttribute( Qt::WA_DeleteOnClose, true );
28 #endif
29 
30  QSize p1size( 960, 720 );
31 
32  mainLayout = new QGridLayout();
33  rightLayout = new QVBoxLayout();
34  bottomLayout = new QHBoxLayout();
35  rsliderLayout = new QGridLayout();
36  bsliderLayout = new QGridLayout();
37  frame = new QFrame();
38  setCentralWidget( frame );
39  frame->setLayout( mainLayout );
40 
41  mainLayout->setSpacing ( 2 );
42  mainLayout->setContentsMargins( 2, 2, 2, 2 );
43 
44  dataWidget = new Qwt3D::SurfacePlot( frame );
45  mainLayout->addWidget( dataWidget, 0, 0, 20, 20 );
46  mainLayout->addLayout( rightLayout, 0, 20, 20, 1 );
47  mainLayout->addLayout( bottomLayout, 20, 0, 1, 20 );
48 
49  poffsSlider = new QSlider( Qt::Horizontal, this );
50  resolSlider = new QSlider( Qt::Horizontal, this );
51  normqSlider = new QSlider( Qt::Vertical, this );
52  normlSlider = new QSlider( Qt::Vertical, this );
53  poffsSlider->setMinimum( 0 );
54  poffsSlider->setMaximum( 30 );
55  poffsSlider->setValue( 5 );
56  resolSlider->setMinimum( 1 );
57  resolSlider->setMaximum( 20 );
58  resolSlider->setValue( 1 );
59  normqSlider->setMinimum( 3 );
60  normqSlider->setMaximum( 32 );
61  normqSlider->setValue( 1 );
62  normlSlider->setMinimum( 0 );
63  normlSlider->setMaximum( 100 );
64  normlSlider->setValue( 8 );
65  poffsSlider->setTickInterval( 2 );
66  resolSlider->setTickInterval( 2 );
67  normqSlider->setTickInterval( 1 );
68  normlSlider->setTickInterval( 8 );
69  poffsSlider->setTickPosition( QSlider::TicksAbove );
70  resolSlider->setTickPosition( QSlider::TicksAbove );
71  normqSlider->setTickPosition( QSlider::TicksLeft );
72  normlSlider->setTickPosition( QSlider::TicksLeft );
73  poffsSlider->setTracking( false );
74  resolSlider->setTracking( false );
75  normqSlider->setTracking( false );
76  normlSlider->setTracking( false );
77  poffsSlider->setStatusTip( tr( "Polygon Offset increase surface quality)" ));
78  resolSlider->setStatusTip( tr( "Data Resolution (rectangular data)" ) );
79  normqSlider->setStatusTip( tr( "Normals Quality (Roundness)" ) );
80  normlSlider->setStatusTip( tr( "Normals Length" ) );
81  poffsSlider->setToolTip( tr( "Polygon Offset" ) );
82  resolSlider->setToolTip( tr( "Data Resolution" ) );
83  normqSlider->setToolTip( tr( "Normals Quality" ) );
84  normlSlider->setToolTip( tr( "Normals Length" ) );
85 
86  ck_ortho = new QCheckBox( tr( "Ortho" ) );
87  ck_legend = new QCheckBox( tr( "Legend" ) );
88  ck_autosc = new QCheckBox( tr( "Autoscale" ) );
89  ck_mouse = new QCheckBox( tr( "Mouse" ) );
90  ck_shade = new QCheckBox( tr( "Shading" ) );
91 
92  QPalette pal = US_GuiSettings::normalColor();
93  QFont font = QFont( US_GuiSettings::fontFamily(),
95  QFont::Normal );
96  ck_ortho ->setFont( font );
97  ck_ortho ->setPalette( pal );
98  ck_ortho ->setAutoFillBackground( true );
99  ck_legend->setFont( font );
100  ck_legend->setPalette( pal );
101  ck_legend->setAutoFillBackground( true );
102  ck_autosc->setFont( font );
103  ck_autosc->setPalette( pal );
104  ck_autosc->setAutoFillBackground( true );
105  ck_mouse ->setFont( font );
106  ck_mouse ->setPalette( pal );
107  ck_mouse ->setAutoFillBackground( true );
108  ck_shade ->setFont( font );
109  ck_shade ->setPalette( pal );
110  ck_shade ->setAutoFillBackground( true );
111 
112  QLabel* normLabl = new QLabel( tr( "Normals" ) );
113  rsliderLayout->addWidget( normLabl, 0, 0, 1, 2 );
114  rsliderLayout->addWidget( normqSlider, 1, 0, 20, 1 );
115  rsliderLayout->addWidget( normlSlider, 1, 1, 20, 1 );
116  rightLayout->addWidget( ck_ortho );
117  rightLayout->addWidget( ck_legend );
118  rightLayout->addWidget( ck_autosc );
119  rightLayout->addWidget( ck_mouse );
120  rightLayout->addWidget( ck_shade );
121  rightLayout->addLayout( rsliderLayout );
122 
123  pb_std = new QPushButton( tr( "Std" ) );
124  pb_light = new QPushButton( tr( "Lighting" ) );
125  ck_light = new QCheckBox( "" );
126  pb_std ->setToolTip( tr( "Standard View" ) );
127  pb_light->setToolTip( tr( "Calibrate Lighting" ) );
128  ck_light->setToolTip( tr( "Lighting On/Off" ) );
129  pb_std ->setStatusTip( tr( "Set standard view" ) );
130  pb_light->setStatusTip( tr( "Calibrate Lighting" ) );
131  ck_light->setStatusTip( tr( "Turn Lighting On/Off" ) );
132  ck_light ->setFont( font );
133  ck_light ->setPalette( pal );
134  ck_light ->setAutoFillBackground( true );
135 
136  QLabel* offsLabl = new QLabel( tr( "Polygon Offset" ) );
137  QLabel* resoLabl = new QLabel( tr( "Resolution" ) );
138  QLabel* dumyLabl = new QLabel(" " );
139  offsLabl->setAlignment( Qt::AlignVCenter | Qt::AlignHCenter );
140  resoLabl->setAlignment( Qt::AlignVCenter | Qt::AlignHCenter );
141  bsliderLayout->addWidget( offsLabl, 0, 0, 1, 10 );
142  bsliderLayout->addWidget( poffsSlider, 1, 0, 1, 10 );
143  bsliderLayout->addWidget( dumyLabl, 0, 10, 2, 1 );
144  bsliderLayout->addWidget( resoLabl, 0, 11, 1, 10 );
145  bsliderLayout->addWidget( resolSlider, 1, 11, 1, 10 );
146  bottomLayout->addWidget( pb_std );
147  bottomLayout->addWidget( pb_light );
148  bottomLayout->addWidget( ck_light );
149  bottomLayout->addLayout( bsliderLayout );
150 
151  bottomLayout->setStretchFactor( pb_std, 0 );
152  bottomLayout->setStretchFactor( pb_light, 0 );
153  bottomLayout->setStretchFactor( ck_light, 0 );
154  bottomLayout->setStretchFactor( bsliderLayout, 2 );
155 
156  createActions();
157  createMenus();
158  createToolBar();
159 
160  statusBar()->showMessage( tr( "status bar active" ) );
161 
162  pb_light ->setEnabled( false );
163  ck_light ->setChecked( false );
164  ck_ortho ->setChecked( true );
165  ck_legend->setChecked( false );
166  ck_autosc->setChecked( true );
167  ck_mouse ->setChecked( true );
168  ck_shade ->setChecked( true );
169 
170  connect( pb_std, SIGNAL( clicked() ),
171  this, SLOT( std_button() ) );
172  connect( pb_light, SIGNAL( clicked() ),
173  this, SLOT( light_button() ) );
174 
175  connect( cb_ifmt, SIGNAL( activated( int ) ),
176  this, SLOT( ifmt_chosen( int ) ) );
177 
178  connect( ck_light, SIGNAL( stateChanged( int ) ),
179  this, SLOT( light_check( int ) ) );
180  connect( ck_ortho, SIGNAL( stateChanged( int ) ),
181  this, SLOT( ortho_check( int ) ) );
182  connect( ck_legend, SIGNAL( stateChanged( int ) ),
183  this, SLOT( legnd_check( int ) ) );
184  connect( ck_autosc, SIGNAL( stateChanged( int ) ),
185  this, SLOT( autsc_check( int ) ) );
186  connect( ck_mouse, SIGNAL( stateChanged( int ) ),
187  this, SLOT( mouse_check( int ) ) );
188  connect( ck_shade, SIGNAL( stateChanged( int ) ),
189  this, SLOT( shade_check( int ) ) );
190 
191  connect( poffsSlider, SIGNAL( valueChanged( int ) ),
192  this, SLOT( poffs_slide( int ) ) );
193  connect( resolSlider, SIGNAL( valueChanged( int ) ),
194  this, SLOT( resol_slide( int ) ) );
195  connect( normlSlider, SIGNAL( valueChanged( int ) ),
196  this, SLOT( norml_slide( int ) ) );
197  connect( normqSlider, SIGNAL( valueChanged( int ) ),
198  this, SLOT( normq_slide( int ) ) );
199 
200  timer = new QTimer( this );
201  connect( movieAct, SIGNAL( toggled( bool ) ),
202  this, SLOT( movie_toggle( bool ) ) );
203  connect( timer, SIGNAL( timeout() ),
204  this, SLOT( rotate() ) );
205  connect( openAct, SIGNAL( triggered( bool ) ),
206  this, SLOT( open_file() ) );
207  connect( saveAct, SIGNAL( triggered( bool ) ),
208  this, SLOT( dump_contents() ) );
209  connect( exitAct, SIGNAL( triggered( bool ) ),
210  this, SLOT( close_all() ) );
211 
212  connect( coaxesAct, SIGNAL( triggered( bool ) ),
213  this, SLOT( pick_axes_co() ) );
214  connect( cobackAct, SIGNAL( triggered( bool ) ),
215  this, SLOT( pick_back_co() ) );
216  connect( comeshAct, SIGNAL( triggered( bool ) ),
217  this, SLOT( pick_mesh_co() ) );
218  connect( conumbAct, SIGNAL( triggered( bool ) ),
219  this, SLOT( pick_numb_co() ) );
220  connect( colablAct, SIGNAL( triggered( bool ) ),
221  this, SLOT( pick_labl_co() ) );
222  connect( cocaptAct, SIGNAL( triggered( bool ) ),
223  this, SLOT( pick_capt_co() ) );
224  connect( codataAct, SIGNAL( triggered( bool ) ),
225  this, SLOT( pick_data_co() ) );
226  connect( corsetAct, SIGNAL( triggered( bool ) ),
227  this, SLOT( reset_colors() ) );
228 
229  connect( fnnumbAct, SIGNAL( triggered( bool ) ),
230  this, SLOT( pick_numb_fn() ) );
231  connect( fnaxesAct, SIGNAL( triggered( bool ) ),
232  this, SLOT( pick_axes_fn() ) );
233  connect( fncaptAct, SIGNAL( triggered( bool ) ),
234  this, SLOT( pick_capt_fn() ) );
235  connect( fnrsetAct, SIGNAL( triggered( bool ) ),
236  this, SLOT( reset_fonts() ) );
237 
238  connect( frameAct, SIGNAL( toggled( bool ) ),
239  this, SLOT( frame_axes_on( bool ) ) );
240  connect( boxAct, SIGNAL( toggled( bool ) ),
241  this, SLOT( box_axes_on( bool ) ) );
242  connect( noneAct, SIGNAL( toggled( bool ) ),
243  this, SLOT( no_axes_on( bool ) ) );
244 
245  connect( gridfrAct, SIGNAL( toggled( bool ) ),
246  this, SLOT( grid_front_on( bool ) ) );
247  connect( gridbAct, SIGNAL( toggled( bool ) ),
248  this, SLOT( grid_back_on( bool ) ) );
249  connect( gridrAct, SIGNAL( toggled( bool ) ),
250  this, SLOT( grid_right_on( bool ) ) );
251  connect( gridlAct, SIGNAL( toggled( bool ) ),
252  this, SLOT( grid_left_on( bool ) ) );
253  connect( gridcAct, SIGNAL( toggled( bool ) ),
254  this, SLOT( grid_ceil_on( bool ) ) );
255  connect( gridfAct, SIGNAL( toggled( bool ) ),
256  this, SLOT( grid_floor_on( bool ) ) );
257  connect( gridbAct, SIGNAL( toggled( bool ) ),
258  this, SLOT( grid_back_on( bool ) ) );
259  connect( gridbAct, SIGNAL( toggled( bool ) ),
260  this, SLOT( grid_back_on( bool ) ) );
261 
262  connect( scattdAct, SIGNAL( toggled( bool ) ),
263  this, SLOT( data_points_on( bool ) ) );
264  connect( wirefrAct, SIGNAL( toggled( bool ) ),
265  this, SLOT( data_wirefr_on( bool ) ) );
266  connect( hiddlnAct, SIGNAL( toggled( bool ) ),
267  this, SLOT( data_hidden_on( bool ) ) );
268  connect( polygnAct, SIGNAL( toggled( bool ) ),
269  this, SLOT( data_polygn_on( bool ) ) );
270  connect( fdmeshAct, SIGNAL( toggled( bool ) ),
271  this, SLOT( data_fimesh_on( bool ) ) );
272  connect( nodataAct, SIGNAL( toggled( bool ) ),
273  this, SLOT( data_none_on( bool ) ) );
274 
275  connect( fldataAct, SIGNAL( toggled( bool ) ),
276  this, SLOT( floor_data_on( bool ) ) );
277  connect( flisolAct, SIGNAL( toggled( bool ) ),
278  this, SLOT( floor_isol_on( bool ) ) );
279  connect( flemptAct, SIGNAL( toggled( bool ) ),
280  this, SLOT( floor_empty_on( bool ) ) );
281 
282  connect( normsAct, SIGNAL( toggled( bool ) ),
283  this, SLOT( normals_on( bool ) ) );
284 
285  dataWidget->coordinates()->setLineSmooth( true );
286  //dataWidget->coordinates()->setGridLinesColr( RGBA( 0.35, 0.35, 0.35, 1 ) );
287  dataWidget->enableMouse( true );
288  dataWidget->setKeySpeed( 15, 20, 20 );
289 
292  dataWidget->setTitleFont( titleFont.family(), titleFont.pointSize(),
293  titleFont.weight() );
294  dataWidget->setTitle( tr( "XYZ 3-D Plot " ) );
295 
296  dataWidget->setPlotStyle( FILLEDMESH );
297  dataWidget->setFloorStyle( NOFLOOR );
298  dataWidget->setCoordinateStyle( FRAME );
299 
300  skip_plot = false;
301  x_scale = 1.0;
302  y_scale = 1.0;
303  z_scale = 1.0;
304  x_norm = 1.0;
305  y_norm = 1.0;
306  z_norm = 1.0;
307  redrawWait = 50;
308 
309  reset_colors();
310  setStandardView();
311 
312  setVisible( true );
313  resize( p1size );
314 }
315 
316 // Public function to set dimension value types and calculate data ranges
317 void US_Plot3Dxyz::setTitles( QString wndt, QString pltt,
318  QString xat, QString yat, QString zat )
319 {
320  const double VROUND = 10.0;
321  const double MAX_ANNO = (99.9/VROUND);
322 // const double MAX_ANNO = (999.0/VROUND);
323 #if 0
324  const double VNEGOF = (1.0/VROUND);
325  double xround = VROUND;
326  double yround = VROUND;
327 #endif
328  int nidpt = xyzdat->count();
329  int powrz;
330  double xval;
331  double yval;
332  double zval;
333 
334  // Set internal type-flag variables
335  setWindowTitle( wndt );
336  dataWidget->setTitle( pltt );
337  xatitle = xat;
338  yatitle = yat;
339  zatitle = zat;
340 
341 DbgLv(2) << "P3D:sT: titles xyz" << xatitle << yatitle << zatitle;
342 
343  // Determine the range of values for each of the 3 dimensions
344  xmin = xyzdat->at( 0 ).x(); // initial ranges
345  ymin = xyzdat->at( 0 ).y();
346  zmin = xyzdat->at( 0 ).z();
347  xmax = xmin;
348  ymax = ymin;
349  zmax = zmin;
350 
351  for ( int ii = 1; ii < nidpt; ii++ )
352  {
353  xval = xyzdat->at( ii ).x(); // x,y,z value of point
354  yval = xyzdat->at( ii ).y();
355  zval = xyzdat->at( ii ).z();
356 
357  xmin = qMin( xmin, xval ); // update range values
358  xmax = qMax( xmax, xval );
359  ymin = qMin( ymin, yval );
360  ymax = qMax( ymax, yval );
361  zmin = qMin( zmin, zval );
362  zmax = qMax( zmax, zval );
363  }
364 
365  if ( nidpt == 1 )
366  {
367  zmin *= 0.90;
368  zmax *= 1.10;
369  ymin *= 0.90;
370  ymax *= 1.10;
371  xmin *= 0.90;
372  xmax *= 1.10;
373  }
374 
375  // extend x,y,z ranges a bit
376  xval = ( xmax - xmin ) * 0.01;
377  xmin -= xval;
378  xmax += xval;
379  yval = ( ymax - ymin ) * 0.01;
380  ymin -= yval;
381  ymax += yval;
382 
383  // determine a normalizing power-of-ten for x and y
384 #if 0
385  double xavg = ( xmin + xmax ) * 0.5;
386  double yavg = ( ymin + ymax ) * 0.5;
387  x_norm = MAX_ANNO / xavg;
388  y_norm = MAX_ANNO / yavg;
389 #endif
390  z_norm = MAX_ANNO / zmax;
391 DbgLv(1) << "P3D:sR: xmax ymax xnorm ynorm" << xmax << ymax << x_norm << y_norm;
392 DbgLv(1) << "P3D:sR: zmin zmax" << zmin << zmax;
393  powrx = qRound( log10( x_norm ) );
394  powry = qRound( log10( y_norm ) );
395  powrz = qRound( log10( z_norm ) );
396  powrx = ( powrx > (-2) && powrz < 6 ) ? 0 : powrx;
397  powry = ( powry > (-2) && powry < 6 ) ? 0 : powry;
398  x_norm = pow( 10.0, (double)powrx );
399  y_norm = pow( 10.0, (double)powry );
400  z_norm = pow( 10.0, (double)powrz );
401 #if 0
402  x_norm = MAX_ANNO / xavg;
403 #endif
404 #if 1
405  x_norm *= 0.1;
406 #endif
407 
408 #if 0
409  if ( ( xavg * x_norm ) > MAX_ANNO )
410  {
411  x_norm *= 0.1;
412  powrx--;
413  }
414 
415  if ( ( yavg * y_norm ) > MAX_ANNO )
416  {
417  y_norm *= 0.1;
418  powry--;
419  }
420 
421 #endif
422  if ( ( zmax * z_norm ) > MAX_ANNO )
423  {
424  z_norm *= 0.1;
425  powrz--;
426  }
427 
428 DbgLv(1) << "P3D:sR: powx powy" << powrx << powry << "xnorm ynorm znorm"
429  << x_norm << y_norm << z_norm;
430  xmax *= x_norm;
431  ymax *= y_norm;
432  xmin *= x_norm;
433  ymin *= y_norm;
434  zmin *= z_norm;
435  zmax *= z_norm;
436 DbgLv(1) << "P3D:sR: nrm'd xmin xmax" << xmin << xmax << "ymin ymax"
437  << ymin << ymax << "zmin zmax" << zmin << zmax;
438 #if 0
439  xmin = (double)( (int)( xmin * xround ) ) / xround;
440  xmax = (double)( (int)( xmax * xround ) + 1 ) / xround;
441  xmin = ( xmin < 0.0 ) ? ( xmin - VNEGOF ) : xmin;
442  ymin = (double)( (int)( ymin * yround ) ) / yround;
443  ymax = (double)( (int)( ymax * yround ) + 1 ) / yround;
444  ymin = ( ymin < 0.0 ) ? ( ymin - VNEGOF ) : ymin;
445  zmax = (double)( (int)( zmax * VROUND ) + 1 ) / VROUND;
446  zmin = 0.0;
447 #endif
448 DbgLv(1) << "P3D:sR: xmin xmax" << xmin << xmax
449  << " ymin ymax" << ymin << ymax << " zmin zmax" << zmin << zmax;
450 }
451 
452 // Public function to reset the plot title
453 void US_Plot3Dxyz::setPlotTitle( QString pltt )
454 {
455  dataWidget->setTitle( pltt );
456 }
457 
458 // Public function to set internal variables from plot control parameters
459 void US_Plot3Dxyz::setParameters( int a_gridy, int a_gridx,
460  double x_scale, double y_scale, double z_scale,
461  double a_alpha, double a_beta )
462 {
463  // Get the variables set in the plot control dialog
464  reverse_y = ( y_scale > 0.0 );
465  xscale = x_scale;
466  yscale = qAbs( y_scale );
467  zscale = z_scale;
468  alpha = a_alpha;
469  beta = a_beta;
470  triples_in = ( alpha == 0.0 );
471 DbgLv(1) << "P3D:sP: zscl xscl yscl" << zscale << xscale << yscale;
472 
473  ncols = a_gridy;
474  nrows = a_gridx;
475 
476  if ( ! triples_in && ncols > 0 && nrows > 0 )
477  {
478  // Do a new allocation of the raster vector
479  clear_2dvect( zdata );
481  }
482 
483  // calculate the raster z data from the given xyz data
484 
485  calculateData( );
486 }
487 
488 // Reload the data after pointing to new data
489 void US_Plot3Dxyz::reloadData( QVector< QVector3D >* d )
490 {
491  xyzdat = d;
492  int nidpt = xyzdat->count();
493  QList< double > xvals;
494 
495  for ( int ii = 0; ii < nidpt; ii++ )
496  { // Accumulate unique X values so that we can count rows
497  double xval = xyzdat->at( ii ).x();
498  if ( ! xvals.contains( xval ) )
499  xvals << xval;
500  }
501 
502  // Recompute dimensions
503  nrows = xvals.count();
504  ncols = nidpt / nrows;
505 DbgLv(1) << "P3D:rD: nidpt ncols nrows" << nidpt << ncols << nrows;
506 DbgLv(1) << "P3D:rD: x0 x1 xm xn" << xvals[0] << xvals[1] << xvals[nrows-2]
507  << xvals[nrows-1];
508 
509  // Return coordinate annotation titles to base state
510  clean_title( xatitle );
511  clean_title( yatitle );
512  clean_title( zatitle );
513 
514  // Recalculate internal data matrix
515  calculateData( );
516 }
517 
518 // Calculate raster data from xyz data
520 {
521  if ( triples_in ) // Calculate for a contour plot
523  else // Calculate for a points plot
524  calculatePoints ();
525 }
526 
527 // Calculate raster data from xyz data for a contour plot.
528 // For each output Triple raster point, a Z value is fetched from an input
529 // matrix of the same dimensions.
531 {
532  int nidpt = xyzdat->count();
533 DbgLv(1) << "P3D:cC: nidpt ncols nrows" << nidpt << ncols << nrows;
534 DbgLv(1) << "P3D:cC: tdata N" << tdata.size();
535 if(tdata.size()>0)
536 DbgLv(1) << "P3D:cC: tdata M" << tdata[0].size();
537  int kk = 0;
538  clear_2dvect( tdata );
539  alloc_2dvect( tdata, ncols, nrows );
540 
541  for ( int ii = 0; ii < ncols; ii++ ) // Fill raster Triple points
542  {
543  for ( int jj = 0; jj < nrows; jj++ )
544  {
545  if ( kk >= nidpt )
546  {
547  qDebug() << "P3Dxyz: *ERROR* xyzdat overrun" << nidpt;
548  break;
549  }
550 
551  QVector3D v3d = xyzdat->at( kk++ );
552  double xval = v3d.x() * x_norm;
553  double yval = v3d.y() * y_norm;
554  double zval = v3d.z() * z_norm;
555  tdata[ ii ][ jj ] = Triple( xval, yval, zval );
556  }
557  }
558 }
559 
560 // Calculate raster data from xyz data for a points plot
561 // For each input point, a radius of raster points is added to by
562 // gaussian decay around the input point.
564 {
565  int nidpt = xyzdat->count();
566  int kcols = zdata.count();
567  int krows = ( kcols == 0 ) ? 0 : zdata[ 0 ].count();
568 
569  if ( nrows != krows || ncols != kcols )
570  {
571  clear_2dvect( zdata );
573  }
574 
575  int hixd = ncols / 5; // max raster radius is 5th of total extent
576  int hiyd = nrows / 5;
577  int loxd = 5;
578  int loyd = 5;
579  int nxd = hixd;
580  int nyd = hiyd;
581 DbgLv(1) << "cP: ncols nrows hixd hiyd" << ncols << nrows << hixd << hiyd;
582  int fx;
583  int lx;
584  int rx;
585  int fy;
586  int ly;
587  int ry;
588  double xval;
589  double yval;
590  double dist;
591  double dfac = M_PI * 0.5 / beta; // dist-related scale factor
592  double xdif = xmax - xmin;
593  double ydif = ymax - ymin;
594  double xpinc = (double)( nrows - 1 ) / xdif; // xy points/value
595  double ypinc = (double)( ncols - 1 ) / ydif;
596  double zfact = zscale;
597 DbgLv(1) << "cP: dfac xdif ydif" << dfac << xdif << ydif
598  << "xpinc ypinc zfact" << xpinc << ypinc << zfact;
599 
600  // Calculate "nxd" and "nyd" the number of reasonable point differentials
601  // around any data point for which to calculate a decayed zvalue.
602  // Beyond these radii, the factor will be insignificant (< 1e-18).
603  // Given that the z value for any raster point near a data point is:
604  // zadd = ( z-peak * ( pow( cos( dist * dfac ), alpha ) ) );
605  // For the limiting "zpkf" factor of 1e-18,
606  // zpkf = pow( cos( dist * dfac ), alpha);
607  // pow( zpkf, 1.0/alpha ) = cos( dist * dfac );
608  // acos( pow( zpkf, 1.0/alpha ) ) = dist * dfac;
609  // acos( pow( zpkf, 1.0/alpha ) ) / dfac = dist;
610  // dist = sqrt( xdif * xdif + ydif * ydif );
611  // dist = sqrt( 2 ) * xdif;
612  // sqrt( 2 ) * xdif = acos( pow( zpkf, 1.0/alpha ) ) / dfac;
613  // xdif = acos( pow( zpkf, 1.0/alpha ) ) / ( sqrt(2) * dfac );
614  // xdif = acos( pow( zpkf, 1.0/alpha ) ) / ( sqrt(2) * M_PI * 0.5 / beta );
615 
616  //xdif = acos( pow( 1e-8, ( 1.0 / alpha) ) )
617  xdif = acos( pow( 1e-18, ( 1.0 / alpha) ) )
618  * beta / ( M_PI * 0.5 * sqrt( 2.0 ) ); // max xy-diff at small zpkf
619  nxd = qRound( xdif * xpinc ); // reasonable x point radius
620  nyd = qRound( xdif * ypinc ); // reasonable y point radius
621 DbgLv(1) << "cP: xdif nxd nyd" << xdif << nxd << nyd << "nidpt" << nidpt;
622  nxd = nxd * 2 + 2; // fudge each up a bit
623  nyd = nyd * 2 + 2; // just to be extra careful
624  nxd = qMin( nxd, hixd ); // at most, a 5th of extent
625  nyd = qMin( nyd, hiyd );
626  nxd = qMax( nxd, loxd ); // at least 5 pixels
627  nyd = qMax( nyd, loyd );
628 DbgLv(1) << "cP: nxd nyd" << nxd << nyd << "ncols nrows" << ncols << nrows;
629  double zval = zmin;
630  //double zval = qMin( zmin, 0.0 );
631  //double beta_d = beta / (double)ncols;
632 
633  for ( int ii = 0; ii < ncols; ii++ ) // initialize raster to zmin
634  for ( int jj = 0; jj < nrows; jj++ )
635  zdata[ ii ][ jj ] = zval;
636 
637  for ( int kk = 0; kk < nidpt; kk++ )
638  { // calculate spread of each data point to a radius of raster points
639  xval = xyzdat->at( kk ).x() * x_norm - xmin;
640  yval = xyzdat->at( kk ).y() * y_norm - ymin;
641  zval = xyzdat->at( kk ).z() * z_norm;
642 
643  rx = (int)( xval * xpinc ); // raster index of x
644  fx = rx - nxd; // range of x to work on
645  lx = rx + nxd;
646  fx = qMax( fx, 0 );
647  lx = qMin( lx, nrows );
648 
649  ry = (int)( yval * ypinc ); // raster index of y
650  fy = ry - nyd; // range of y to work on
651  ly = ry + nyd;
652  fy = qMax( fy, 0 );
653  ly = qMin( ly, ncols );
654 
655  //for ( int ii = fy; ii < ly; ii++ )
656  for ( int ii = fx; ii < lx; ii++ )
657  { // find square of difference of y-raster and y-data
658  xdif = sq( (double)ii / xpinc - xval );
659  //ydif = (double)sq( ( ii - ry ) );
660 
661  //for ( int jj = fx; jj < lx; jj++ )
662  for ( int jj = fy; jj < ly; jj++ )
663  { // find square of difference of y-raster and y-data
664  ydif = sq( (double)jj / ypinc - yval );
665  //xdif = (double)sq( ( jj - rx ) );
666  // distance of raster point from data point
667  dist = sqrt( xdif + ydif );
668 //DbgLv(0) << "cP:tif: kk ii jj" << kk << ii << jj << "dist beta_d"
669 // << dist << beta_d;
670 
671  // If distance is within beta, calculate and sum in the z value
672  // for this raster point. Here is what the following amounts to.
673  // for InZ, the previous raster point Z;
674  // OutZ, the new raster point Z;
675  // DataZ, the peak data point Z;
676  // Alpha, the user-specified peak smoothing factor;
677  // Beta, the user-specified peak width factor;
678  // Dist, the calculated data-to-raster point distance;
679  // Scale, the calculated Z decay at this distance;
680  // Zfact, the user-specified Z scaling factor;
681  // Scale = Cosine( Dist * PI/2 / Beta ) raised to the Alpha power
682  // OutZ = InZ + ( DataZ * Scale * Zfact )
683  //if ( dist <= beta_d )
684  if ( dist <= beta )
685  {
686  //zdata[ jj ][ ii ] += ( ( zval *
687  zdata[ ii ][ jj ] += ( ( zval *
688  ( pow( cos( dist * dfac ), alpha ) ) ) * zfact );
689 //DbgLv(0) << "cP:tif: ii jj" << ii << jj << "zval dist dfac alpha zfact beta_d"
690 // << zval << dist << dfac << alpha << zfact << beta_d
691 // << "zdataij" << zdata[ii][jj];
692  }
693 //else {DbgLv(3) << " *dist>beta* dist beta iijj" << dist << beta << ii << jj;}
694 //*DBG*
695 //if ( kk>(nidpt/2-2) && kk<(nidpt/2+2) ) {
696 //if ( ii>3 && ii<9 && jj>5 && jj<11 ) {
697 // DbgLv(3) << "kk" << kk << "rx ry ii jj" << rx << ry << ii << jj
698 // << "zout" << zdata[ii][jj] << " zfac" << (pow(cos(dist*dfac),alpha));
699 // DbgLv(3) << " dist" << dist << "dfac alpha beta zval" << dfac
700 // << alpha << beta << zval;
701 //}
702 //}
703 //*DBG*
704  }
705  }
706 //DbgLv(3) << "P3D:cD: kk fx lx fy ly" << kk << fx << lx << fy << ly
707 // << " xval yval zval" << xval << yval << zval;
708  }
709 }
710 
711 void US_Plot3Dxyz::replot( bool hold_color )
712 {
713  unsigned int kcols = (unsigned int)ncols;
714  unsigned int krows = (unsigned int)nrows;
715 DbgLv(1) << "P3D:replot: ncols nrows" << ncols << nrows
716  << "triples-in" << triples_in;
717  double xcmin = xmin;
718  double xcmax = xmax;
719  double ycmin = reverse_y ? ymax : ymin;
720  double ycmax = reverse_y ? ymin : ymax;
721  double zcmin = zmin;
722  double zcmax = zmax;
723  double zdmx = zmin;
724  double zfac = 1.0;
725  Triple** wdata = NULL;
726  double** wddat = NULL;
727  int lcol = ncols - 1;
728  dataWidget->makeCurrent();
729 //if(reverse_y) y_scale *= -1.0;
730 
731  if ( triples_in )
732  {
733  wdata = new Triple* [ ncols ];
734 DbgLv(1) << "P3D:replot: wdata size" << tdata.size();
735 if(tdata.size()>0)
736 DbgLv(1) << "P3D:replot: wdata0 size" << tdata[0].size();
737 
738  if ( reverse_y )
739  {
740  double yroff = ( ymin + ymax ) / y_norm;
741 
742  for ( int ii = 0; ii < ncols; ii++ )
743  {
744  wdata[ ii ] = new Triple [ nrows ];
745  int kk = lcol - ii;
746 
747  for ( int jj = 0; jj < nrows; jj++ )
748  {
749  double xval = tdata[ kk ][ jj ].x;
750  double yval = ( yroff - tdata[ kk ][ jj ].y );
751  double zval = tdata[ kk ][ jj ].z;
752  wdata[ ii ][ jj ] = Triple( xval, yval, zval );
753  }
754  }
755  }
756 
757  else
758  {
759  for ( int ii = 0; ii < ncols; ii++ )
760  {
761  wdata[ ii ] = new Triple [ nrows ];
762  for ( int jj = 0; jj < nrows; jj++ )
763  wdata[ ii ][ jj ] = tdata[ ii ][ jj ];
764  }
765  }
766 
767  if ( hold_color )
768  { // If hold-colors option is on, use point with max to hold colors
769  double xval = wdata[ lcol ][ 0 ].x;
770  double yval = wdata[ lcol ][ 0 ].y;
771  wdata[ lcol ][ 0 ]= Triple( xval, yval, zmax );
772  }
773 
774 int m=nrows-1;
775 int n=ncols-1;
776 DbgLv(1) << "P3D:replot: wdata[0][0]" << wdata[0][0].x << wdata[0][0].y
777  << wdata[0][0].z;
778 DbgLv(1) << "P3D:replot: wdata[n][0]" << wdata[n][0].x << wdata[n][0].y
779  << wdata[n][0].z;
780 DbgLv(1) << "P3D:replot: wdata[0][m]" << wdata[0][m].x << wdata[0][m].y
781  << wdata[0][m].z;
782 DbgLv(1) << "P3D:replot: wdata[n][m]" << wdata[n][m].x << wdata[n][m].y
783  << wdata[n][m].z;
784 
785 DbgLv(1) << "P3D:replot: ldDa rev_y ycmin ycmax" << reverse_y << ycmin << ycmax;
786  // Load the widget raster data
787  bool uperio = true;
788  bool vperio = true;
789  dataWidget->loadFromData( wdata, kcols, krows, uperio, vperio );
790 DbgLv(1) << "P3D:replot: createCoordSys";
791  dataWidget->createCoordinateSystem( Triple( xcmin, ycmin, zcmin ),
792  Triple( xcmax, ycmax, zcmax ) );
793 DbgLv(1) << "P3D:replot: xmin xmax ycmin ycmax" << xmin << xmax
794  << ycmin << ycmax << "zcmin zcmax" << zcmin << zcmax;
795  }
796 
797  else
798  {
799  wddat = new double* [ ncols ];
800  zdmx = zdata[ 0 ][ 0 ];
801 
802  for ( int ii = 0; ii < ncols; ii++ )
803  { // copy data to work 2D vector and get new z-max
804 if ((ii&63)==1) DbgLv(2) << "P3D: rp: row" << ii;
805  wddat[ ii ] = new double [ nrows ];
806 
807  for ( int jj = 0; jj < nrows; jj++ )
808  {
809  double zval = zdata[ ii ][ jj ];
810  wddat[ ii ][ jj ] = zval;
811  zdmx = qMax( zdmx, zval );
812 if ((ii&63)==1&&(jj&63)==1) DbgLv(2) << "P3D: rp: col" << jj
813  << " wdat" << zval;
814  }
815  }
816 
817  // scale back data to have same z-max as before
818  zfac = ( zdmx < 1e-20 ) ? zmax : ( zmax / zdmx );
819 
820  for ( int ii = 0; ii < ncols; ii++ )
821  for ( int jj = 0; jj < nrows; jj++ )
822  wddat[ ii ][ jj ] *= zfac;
823 
824 DbgLv(1) << "P3D:ld: xmin xmax ycmin ycmax" << xmin << xmax
825  << ycmin << ycmax << "zmin zmax zfac zdmx" << zmin << zmax << zfac << zdmx;
826 
827  // Load the widget raster data
828  dataWidget->loadFromData( wddat, kcols, krows, xmin, xmax, ycmin, ycmax );
829  dataWidget->createCoordinateSystem( Triple( xmin, ycmin, zmin ),
830  Triple( xmax, ycmax, zmax ) );
831  }
832 
833  // set coordinate system ranges
834 // dataWidget->createCoordinateSystem( Triple( xmin, ycmin, zmin ),
835 // Triple( xmax, ycmax, zmax ) );
836  //dataWidget->coordinates()->setPosition
837  // ( Triple( xmin, ymin, zmin ),
838  // Triple( xmax, ymax, zmax ) );
839 
840  dataWidget->makeCurrent();
841  dataWidget->legend()->setScale( LINEARSCALE );
842 
843  for ( uint ii = 0; ii != dataWidget->coordinates()->axes.size(); ++ii )
844  {
845  dataWidget->coordinates()->axes[ ii ].setMajors( 7 );
846  dataWidget->coordinates()->axes[ ii ].setMinors( 5 );
847  }
848 
849  dataWidget->coordinates()->setLabelFont ( US_GuiSettings::fontFamily(),
851  QFont::Bold );
852  dataWidget->coordinates()->setLabelColor( Qwt3D::RGBA( 0, 0, 0, 1 ) );
853  dataWidget->coordinates()->setNumberFont( US_GuiSettings::fontFamily(),
855 // double majtl = 0.2;
856 // double mintl = majtl * 0.5;
857 // dataWidget->coordinates()->setTicLength ( majtl, mintl );
858 
859 //dataWidget->coordinates()->setAutoScale( true );
860  //QString annopad( " " );
861  QString annopad( " " );
862  x_scale = ymax / xmax;
863  y_scale = 1.0;
864  z_scale = zscale * ( x_scale * 0.40 );
865  if ( x_norm != 1.0 )
866  xatitle = xatitle + " * " + QString::number( x_norm );
867  xatitle = annopad + xatitle;
868  if ( y_norm != 1.0 )
869  yatitle = yatitle + " * " + QString::number( y_norm );
870  yatitle = yatitle + annopad;
871  if ( z_norm != 1.0 )
872  zatitle = zatitle + " * " + QString::number( z_norm );
873 
874 DbgLv(2) << "P3D:rP: xmin xmax" << xmin << xmax
875  << " ymin ymax" << ymin << ymax << " zmin zmax" << zmin << zmax
876  << " xscl yscl zscl" << x_scale << y_scale << z_scale;
877 #if 0
878  if ( x_scale > 4.0 )
879  {
880  x_scale /= 4.0;
881  }
882 
883  else if ( x_scale < 0.25 )
884  {
885  x_scale *= 2.0;
886  }
887 #endif
888  x_scale *= xscale;
889  y_scale *= yscale;
890 DbgLv(1) << "P3D:rP: xscl yscl" << x_scale << y_scale;
891 // double xtic1 = 1.0 / ( 5.0 * x_scale );
892 // double ytic1 = 1.0 / ( 20.0 * y_scale );
893 // double ztic1 = 1.0 / ( 20.0 * z_scale );
894  double xtic1 = 0.04;
895  double ytic1 = 0.02;
896  double ztic1 = 0.02;
897  double xtic2 = xtic1 * 0.4;
898  double ytic2 = ytic1 * 0.4;
899  double ztic2 = ztic1 * 0.4;
900 DbgLv(1) << "P3D:rP: xtic1 ytic1 ztic1" << xtic1 << ytic1 << ztic1;
901 
902  dataWidget->coordinates()->axes[X1].setLabelString( xatitle );
903  dataWidget->coordinates()->axes[X2].setLabelString( xatitle );
904  dataWidget->coordinates()->axes[X3].setLabelString( xatitle );
905  dataWidget->coordinates()->axes[X4].setLabelString( xatitle );
906  dataWidget->coordinates()->axes[Y1].setLabelString( yatitle );
907  dataWidget->coordinates()->axes[Y2].setLabelString( yatitle );
908  dataWidget->coordinates()->axes[Y3].setLabelString( yatitle );
909  dataWidget->coordinates()->axes[Y4].setLabelString( yatitle );
910  dataWidget->coordinates()->axes[Z1].setLabelString( zatitle );
911  dataWidget->coordinates()->axes[Z2].setLabelString( zatitle );
912  dataWidget->coordinates()->axes[Z3].setLabelString( zatitle );
913  dataWidget->coordinates()->axes[Z4].setLabelString( zatitle );
914 DbgLv(1) << "P3D:rp: xatitle yatitle" << xatitle << yatitle;
915  dataWidget->coordinates()->axes[X1].setTicLength( xtic1, xtic2 );
916  dataWidget->coordinates()->axes[X2].setTicLength( xtic1, xtic2 );
917  dataWidget->coordinates()->axes[X3].setTicLength( xtic1, xtic2 );
918  dataWidget->coordinates()->axes[X4].setTicLength( xtic1, xtic2 );
919  dataWidget->coordinates()->axes[Y1].setTicLength( ytic1, ytic2 );
920  dataWidget->coordinates()->axes[Y2].setTicLength( ytic1, ytic2 );
921  dataWidget->coordinates()->axes[Y3].setTicLength( ytic1, ytic2 );
922  dataWidget->coordinates()->axes[Y4].setTicLength( ytic1, ytic2 );
923  dataWidget->coordinates()->axes[Z1].setTicLength( ztic1, ztic2 );
924  dataWidget->coordinates()->axes[Z2].setTicLength( ztic1, ztic2 );
925  dataWidget->coordinates()->axes[Z3].setTicLength( ztic1, ztic2 );
926  dataWidget->coordinates()->axes[Z4].setTicLength( ztic1, ztic2 );
927 
928  if ( reverse_y )
929  {
930  dataWidget->coordinates()->axes[Y1].setScale( new ReversedScale );
931  dataWidget->coordinates()->axes[Y2].setScale( new ReversedScale );
932  dataWidget->coordinates()->axes[Y3].setScale( new ReversedScale );
933  dataWidget->coordinates()->axes[Y4].setScale( new ReversedScale );
934  }
935  else
936  {
937  dataWidget->coordinates()->setStandardScale();
938  }
939 DbgLv(1) << "P3D:rp: xscl yscl zscl" << x_scale << y_scale << z_scale;
940  dataWidget->setScale( x_scale, y_scale, z_scale );
941 
942  dataWidget->updateData();
943  dataWidget->updateGL();
944 DbgLv(1) << "P3D:rp: Data/GL updated";
945 
946  if ( wdata != NULL )
947  {
948  for ( int ii = 0; ii < ncols; ii++ )
949  delete [] wdata[ ii ];
950 
951  delete [] wdata;
952  wdata = NULL;
953  }
954 
955  if ( wddat != NULL )
956  {
957  for ( int ii = 0; ii < ncols; ii++ )
958  delete [] wddat[ ii ];
959 
960  delete [] wddat;
961  wddat = NULL;
962  }
963 DbgLv(1) << "P3D:rp: Data freed";
964 }
965 
966 // Public method to return a pointer to the data widget
967 QGLWidget* US_Plot3Dxyz::dataWidgetP( void )
968 {
969  dataWidget->updateData();
970  dataWidget->updateGL();
971 
972  return (QGLWidget*)dataWidget;
973 }
974 
975 // Public method to save the plot to an image file
976 bool US_Plot3Dxyz::save_plot( const QString filename, const QString imagetype )
977 {
978  dataWidget->updateData();
979  dataWidget->updateGL();
980 
981  return IO::save( dataWidget, filename, imagetype );
982 }
983 
984 QString US_Plot3Dxyz::xyAxisTitle( int type, double sclnorm )
985 {
986  QString atitle = tr( "s" );
987 
988  switch ( type )
989  {
990  case 1:
991  default:
992  atitle = tr( "MW" );
993  break;
994  case 2:
995  atitle = tr( "s" );
996  break;
997  case 3:
998  atitle = tr( "D" );
999  break;
1000  case 4:
1001  atitle = tr( "f" );
1002  break;
1003  case 5:
1004  atitle = tr( "f/f0" );
1005  break;
1006  case 6:
1007  atitle = tr( "vbar" );
1008  break;
1009  }
1010 
1011  if ( sclnorm != 1.0 )
1012  atitle = atitle + " * " + QString::number( sclnorm );
1013 
1014 DbgLv(2) << "P3D: xyAT: type atitle" << type << atitle;
1015  return atitle;
1016 }
1017 
1018 QString US_Plot3Dxyz::zAxisTitle( int type )
1019 {
1020  QString atitle = tr( "Concentration " );
1021 
1022  if ( type == 2 )
1023  atitle = tr( "Mol.Concentr. " );
1024 
1025  return atitle;
1026 }
1027 
1029 {
1030  //if ( xmax < ymax )
1031  dataWidget->setRotation( 30, 0, 15 );
1032  //else
1033  // dataWidget->setRotation( 30, 0, 105 );
1034 
1035  dataWidget->setViewportShift( 0.05, 0 );
1036  dataWidget->setScale( x_scale, y_scale, z_scale );
1037  dataWidget->setZoom( 0.95 );
1038 }
1039 
1041 {
1042  openAct = new QAction( QIcon( ":/images/fileopen.png" ),
1043  tr( "&Open File" ), this );
1044  openffAct = new QAction( QIcon( ":/images/filecell.png" ),
1045  tr( "Open FEM File" ), this );
1046  saveAct = new QAction( QIcon( ":/images/savecontent.png" ),
1047  tr( "Dump Contents" ), this );
1048  movieAct = new QAction( QIcon( ":/images/movie.png" ),
1049  tr( "Animation" ), this );
1050 
1051  frameAct = new QAction( QIcon( ":/images/frame.png" ),
1052  tr( "Frame Axes" ), this );
1053  boxAct = new QAction( QIcon( ":/images/box.png" ),
1054  tr( "Box Axes" ), this );
1055  noneAct = new QAction( QIcon( ":/images/none.png" ),
1056  tr( "No Axes" ), this );
1057 
1058  gridfrAct = new QAction( QIcon( ":/images/gridfr.png" ),
1059  tr( "Front Grid" ), this );
1060  gridbAct = new QAction( QIcon( ":/images/gridb.png" ),
1061  tr( "Back Grid" ), this );
1062  gridrAct = new QAction( QIcon( ":/images/gridr.png" ),
1063  tr( "Right Grid" ), this );
1064  gridlAct = new QAction( QIcon( ":/images/gridl.png" ),
1065  tr( "Left Grid" ), this );
1066  gridcAct = new QAction( QIcon( ":/images/gridc.png" ),
1067  tr( "Ceiling Grid" ), this );
1068  gridfAct = new QAction( QIcon( ":/images/gridf.png" ),
1069  tr( "Floor Grid" ), this );
1070 
1071  scattdAct = new QAction( QIcon( ":/images/scattered.png" ),
1072  tr( "Points" ), this );
1073  wirefrAct = new QAction( QIcon( ":/images/wireframe.png" ),
1074  tr( "Wire Frame" ), this );
1075  hiddlnAct = new QAction( QIcon( ":/images/hiddenline.png" ),
1076  tr( "Hidden Line" ), this );
1077  polygnAct = new QAction( QIcon( ":/images/polygon.png" ),
1078  tr( "Polygon only" ), this );
1079  fdmeshAct = new QAction( QIcon( ":/images/filledmesh.png" ),
1080  tr( "Filled Mesh" ), this );
1081 
1082  nodataAct = new QAction( QIcon( ":/images/nodata.png" ),
1083  tr( "No Data" ), this );
1084  fldataAct = new QAction( QIcon( ":/images/floordata.png" ),
1085  tr( "Floor Data" ), this );
1086  flisolAct = new QAction( QIcon( ":/images/flooriso.png" ),
1087  tr( "Floor Isolines" ), this );
1088  flemptAct = new QAction( QIcon( ":/images/floorempty.png" ),
1089  tr( "Floor Empty" ), this );
1090 
1091  normsAct = new QAction( QIcon( ":/images/normals.png" ),
1092  tr( "Normal Vectors" ), this );
1093  iconAct = new QAction( QIcon( ":/images/icon.png" ),
1094  tr( "Icon" ), this );
1095  qwtpltAct = new QAction( QIcon( ":/images/qwtplot.png" ),
1096  tr( "QwtPlot" ), this );
1097 
1098  exitAct = new QAction( tr( "Exit" ), this );
1099 
1100  coaxesAct = new QAction( tr( "Axes" ), this );
1101  cobackAct = new QAction( tr( "Background" ), this );
1102  comeshAct = new QAction( tr( "Mesh" ), this );
1103  conumbAct = new QAction( tr( "Number" ), this );
1104  colablAct = new QAction( tr( "Label" ), this );
1105  cocaptAct = new QAction( tr( "Caption" ), this );
1106  codataAct = new QAction( tr( "Data Color" ), this );
1107  corsetAct = new QAction( tr( "Reset" ), this );
1108 
1109  fnnumbAct = new QAction( tr( "Scale numbering" ), this );
1110  fnaxesAct = new QAction( tr( "Axes label" ), this );
1111  fncaptAct = new QAction( tr( "Caption" ), this );
1112  fnrsetAct = new QAction( tr( "Reset" ), this );
1113 
1114  cb_ifmt = new QComboBox( this );
1115  cb_ifmt->addItem( tr( "BMP" ) );
1116  cb_ifmt->addItem( tr( "JPEG" ) );
1117  cb_ifmt->addItem( tr( "PBM" ) );
1118  cb_ifmt->addItem( tr( "PGM" ) );
1119  cb_ifmt->addItem( tr( "PNG" ) );
1120  cb_ifmt->addItem( tr( "PPM" ) );
1121  cb_ifmt->addItem( tr( "XBM" ) );
1122  cb_ifmt->addItem( tr( "XPM" ) );
1123  cb_ifmt->addItem( tr( "EPS" ) );
1124  cb_ifmt->addItem( tr( "PS" ) );
1125  cb_ifmt->addItem( tr( "EPS-GZ" ) );
1126  cb_ifmt->addItem( tr( "PS-GZ" ) );
1127  cb_ifmt->addItem( tr( "PDF" ) );
1128  cb_ifmt->setCurrentIndex( cb_ifmt->findText( "PNG" ) );
1129 }
1130 
1132 {
1133  fileMenu = menuBar()->addMenu( tr( "&File" ) );
1134  fileMenu->addAction( openAct );
1135  fileMenu->addAction( openffAct );
1136  fileMenu->addAction( saveAct );
1137  fileMenu->addAction( movieAct );
1138  fileMenu->addAction( exitAct );
1139 
1140  colorMenu = menuBar()->addMenu( tr( "&Color" ) );
1141  colorMenu->addAction( coaxesAct );
1142  colorMenu->addAction( cobackAct );
1143  colorMenu->addAction( comeshAct );
1144  colorMenu->addAction( conumbAct );
1145  colorMenu->addAction( colablAct );
1146  colorMenu->addAction( cocaptAct );
1147  colorMenu->addAction( codataAct );
1148  colorMenu->addAction( corsetAct );
1149 
1150  fontMenu = menuBar()->addMenu( tr( "Font" ) );
1151  fontMenu->addAction( fnnumbAct );
1152  fontMenu->addAction( fnaxesAct );
1153  fontMenu->addAction( fncaptAct );
1154  fontMenu->addAction( fnrsetAct );
1155 }
1156 
1158 {
1159  fileToolBar = new QToolBar( tr( "File" ) );
1160  frameGroup = new QActionGroup( this );
1161  gridGroup = new QActionGroup( this );
1162  dataGroup = new QActionGroup( this );
1163  floorGroup = new QActionGroup( this );
1164 
1165  fileToolBar->addAction( openAct );
1166  fileToolBar->addAction( openffAct );
1167  fileToolBar->addAction( saveAct );
1168  fileToolBar->addWidget( cb_ifmt );
1169 
1170  fileToolBar->addAction( movieAct );
1171  fileToolBar->addAction( frameAct );
1172  fileToolBar->addAction( boxAct );
1173  fileToolBar->addAction( noneAct );
1174  fileToolBar->addSeparator();
1175  frameGroup->addAction( frameAct );
1176  frameGroup->addAction( boxAct );
1177  frameGroup->addAction( noneAct );
1178  movieAct->setCheckable( true );
1179  frameAct->setCheckable( true );
1180  boxAct ->setCheckable( true );
1181  noneAct ->setCheckable( true );
1182  frameAct->setChecked( true );
1183 
1184  fileToolBar->addAction( gridfrAct );
1185  fileToolBar->addAction( gridbAct );
1186  fileToolBar->addAction( gridrAct );
1187  fileToolBar->addAction( gridlAct );
1188  fileToolBar->addAction( gridcAct );
1189  fileToolBar->addAction( gridfAct );
1190  fileToolBar->addSeparator();
1191  gridGroup->addAction( gridfrAct );
1192  gridGroup->addAction( gridbAct );
1193  gridGroup->addAction( gridrAct );
1194  gridGroup->addAction( gridlAct );
1195  gridGroup->addAction( gridcAct );
1196  gridGroup->addAction( gridfAct );
1197  gridGroup->setExclusive( false );
1198  gridfrAct->setCheckable( true );
1199  gridbAct ->setCheckable( true );
1200  gridrAct ->setCheckable( true );
1201  gridlAct ->setCheckable( true );
1202  gridcAct ->setCheckable( true );
1203  gridfAct ->setCheckable( true );
1204  gridGroup->setEnabled( false );
1205 
1206  fileToolBar->addAction( scattdAct );
1207  fileToolBar->addAction( wirefrAct );
1208  fileToolBar->addAction( hiddlnAct );
1209  fileToolBar->addAction( polygnAct );
1210  fileToolBar->addAction( fdmeshAct );
1211  fileToolBar->addAction( nodataAct );
1212  fileToolBar->addSeparator();
1213  dataGroup->addAction( scattdAct );
1214  dataGroup->addAction( wirefrAct );
1215  dataGroup->addAction( hiddlnAct );
1216  dataGroup->addAction( polygnAct );
1217  dataGroup->addAction( fdmeshAct );
1218  dataGroup->addAction( nodataAct );
1219  scattdAct->setCheckable( true );
1220  wirefrAct->setCheckable( true );
1221  hiddlnAct->setCheckable( true );
1222  polygnAct->setCheckable( true );
1223  fdmeshAct->setCheckable( true );
1224  nodataAct->setCheckable( true );
1225  fdmeshAct->setChecked( true );
1226 
1227  fileToolBar->addAction( fldataAct );
1228  fileToolBar->addAction( flisolAct );
1229  fileToolBar->addAction( flemptAct );
1230  fileToolBar->addAction( normsAct );
1231  floorGroup->addAction( fldataAct );
1232  floorGroup->addAction( flisolAct );
1233  floorGroup->addAction( flemptAct );
1234  fldataAct->setCheckable( true );
1235  flisolAct->setCheckable( true );
1236  flemptAct->setCheckable( true );
1237  normsAct ->setCheckable( true );
1238  flemptAct->setChecked( true );
1239 
1240  openAct ->setStatusTip( tr( "Open GridData (.mes) files" ) );
1241  openffAct->setStatusTip( tr( "Open Node/Cell files" ) );
1242  saveAct ->setStatusTip( tr( "Dump content to image file" ) );
1243  cb_ifmt ->setStatusTip( tr( "Select image file format" ) );
1244  movieAct ->setStatusTip( tr( "Turn on animation" ) );
1245  frameAct ->setStatusTip( tr( "Show frame axes" ) );
1246  boxAct ->setStatusTip( tr( "Show box axes" ) );
1247  noneAct ->setStatusTip( tr( "Hide axes" ) );
1248  gridfrAct->setStatusTip( tr( "Show front grid" ) );
1249  gridbAct ->setStatusTip( tr( "Show back grid" ) );
1250  gridrAct ->setStatusTip( tr( "Show right grid" ) );
1251  gridlAct ->setStatusTip( tr( "Show left grid" ) );
1252  gridcAct ->setStatusTip( tr( "Show ceiling grid" ) );
1253  gridfAct ->setStatusTip( tr( "Show floor grid" ) );
1254  scattdAct->setStatusTip( tr( "Display scattered points data" ) );
1255  wirefrAct->setStatusTip( tr( "Display wire frame data" ) );
1256  hiddlnAct->setStatusTip( tr( "Display hidden line data" ) );
1257  polygnAct->setStatusTip( tr( "Display polygon only data" ) );
1258  fdmeshAct->setStatusTip( tr( "Display mesh & filled polygons" ) );
1259  nodataAct->setStatusTip( tr( "Hide data" ) );
1260  fldataAct->setStatusTip( tr( "Floor data projection" ) );
1261  flisolAct->setStatusTip( tr( "Floor isolines" ) );
1262  flemptAct->setStatusTip( tr( "Floor empty" ) );
1263  normsAct ->setStatusTip( tr( "Show normal vectors" ) );
1264 
1265  addToolBar( fileToolBar );
1266  fileToolBar->adjustSize();
1267  int wdim = qRound( (double)fileToolBar->size().width() * 0.75 );
1268  int hdim = qRound( (double)wdim * 0.75 );
1269  setMinimumSize( wdim, hdim );
1270  adjustSize();
1271 wdim = qRound( (double)size().width() * 0.75 );
1272 DbgLv(2) << " min x,y dim" << wdim;
1273 }
1274 
1275 #if 0
1276 // get simulation component x/y/z value of given type
1277 double US_Plot3Dxyz::comp_value( US_Model::SimulationComponent* sc, int type,
1278  double normscl )
1279 {
1280  double xyval = sc->s;
1281 
1282  switch ( type )
1283  { // get appropriate value, based on type
1284  case 1: // x,y value is molecular weight
1285  xyval = sc->mw * normscl;
1286  break;
1287 
1288  case 2: // x,y value is sedimentation coefficient
1289  xyval = sc->s * normscl;
1290  break;
1291 
1292  case 3: // x,y value is diffusion coefficient
1293  xyval = sc->D * normscl;
1294  break;
1295 
1296  case 4: // x,y value is frictional coefficient
1297  xyval = sc->f * normscl;
1298  break;
1299 
1300  case 5: // x,y value is f/f0
1301  xyval = sc->f_f0 * normscl;
1302  break;
1303 
1304  case 6: // x,y value is vbar20
1305  xyval = sc->vbar20 * normscl;
1306  break;
1307 
1308  case -1: // z value is signal concentration
1309  xyval = sc->signal_concentration * normscl;
1310  break;
1311 
1312  case -2: // z value is molar concentration
1313  xyval = sc->molar_concentration * normscl;
1314 
1315  default:
1316  break;
1317  }
1318 
1319  return xyval;
1320 }
1321 #endif
1322 
1323 // standard button clicked
1325 {
1326  setStandardView();
1327 }
1328 
1329 // lighting button clicked
1331 {
1332 DbgLv(2) << "light_button";
1333 }
1334 
1335 // image format chosen in combo box
1336 void US_Plot3Dxyz::ifmt_chosen( int index )
1337 {
1338 DbgLv(2) << "ifmt_chosen" << index << cb_ifmt->itemText(index);
1339 }
1340 
1341 // lighting checked
1342 void US_Plot3Dxyz::light_check( int state )
1343 {
1344 DbgLv(2) << "light_check" << (state==Qt::Checked);
1345 
1346  pb_light->setEnabled( ( state == Qt::Checked ) );
1347 }
1348 
1349 // ortho checked
1350 void US_Plot3Dxyz::ortho_check( int state )
1351 {
1352 DbgLv(2) << "ortho_check" << (state==Qt::Checked);
1353  dataWidget->setOrtho( state );
1354 }
1355 
1356 // legend checked
1357 void US_Plot3Dxyz::legnd_check( int state )
1358 {
1359 DbgLv(2) << "legnd_check" << (state==Qt::Checked);
1360  dataWidget->showColorLegend( state );
1361 }
1362 
1363 // autoscale checked
1364 void US_Plot3Dxyz::autsc_check( int state )
1365 {
1366 DbgLv(2) << "autsc_check" << (state==Qt::Checked);
1367  dataWidget->coordinates()->setAutoScale( state );
1368  dataWidget->updateGL();
1369 }
1370 
1371 // mouse checked
1372 void US_Plot3Dxyz::mouse_check( int state )
1373 {
1374 DbgLv(2) << "mouse_check" << (state==Qt::Checked);
1375 }
1376 
1377 // shading checked
1378 void US_Plot3Dxyz::shade_check( int state )
1379 {
1380 DbgLv(2) << "shade_check" << (state==Qt::Checked);
1381  dataWidget->setShading( state ? GOURAUD : FLAT );
1382 }
1383 
1384 // polygon offset slider moved
1386 {
1387 DbgLv(2) << "poffs_slide" << pos;
1388  dataWidget->setPolygonOffset( (double)pos / 10.0 );
1389  dataWidget->updateData();
1390  dataWidget->updateGL();
1391 }
1392 
1393 // resolution slider moved
1395 {
1396 DbgLv(2) << "resol_slide" << pos;
1397  dataWidget->setResolution( pos );
1398  dataWidget->updateData();
1399  dataWidget->updateGL();
1400 }
1401 // movie (animation) toggled
1403 {
1404 DbgLv(2) << "P3D:movie_toggle" << isOn << redrawWait;
1405  if ( isOn )
1406  {
1407  timer->start( redrawWait ); // wait a bit, then redraw
1408  }
1409 
1410  else
1411  {
1412  timer->stop();
1413  }
1414 }
1415 
1416 // frame axes on/off
1418 {
1419  if ( isOn )
1420  {
1421  dataWidget->setCoordinateStyle( FRAME );
1422  gridGroup->setEnabled( true );
1423  }
1424 }
1425 // box axes on/off
1426 void US_Plot3Dxyz::box_axes_on( bool isOn )
1427 {
1428  if ( isOn )
1429  {
1430  dataWidget->setCoordinateStyle( BOX );
1431  gridGroup->setEnabled( true );
1432  }
1433 }
1434 // no axes on/off
1435 void US_Plot3Dxyz::no_axes_on( bool isOn )
1436 {
1437  if ( isOn )
1438  {
1439  dataWidget->setCoordinateStyle( NOCOORD );
1440  gridGroup->setEnabled( false );
1441  }
1442 }
1443 
1444 // grid front on/off
1446 {
1447  set_grid_onoff( FRONT, isOn );
1448 }
1449 
1450 // grid back on/off
1452 {
1453  set_grid_onoff( BACK, isOn );
1454 }
1455 
1456 // grid right on/off
1458 {
1459  set_grid_onoff( RIGHT, isOn );
1460 }
1461 
1462 // grid left on/off
1464 {
1465  set_grid_onoff( LEFT, isOn );
1466 }
1467 
1468 // grid ceiling on/off
1470 {
1471  set_grid_onoff( CEIL, isOn );
1472 }
1473 
1474 // grid floor on/off
1476 {
1477  set_grid_onoff( FLOOR, isOn );
1478 }
1479 
1480 // set grid(s) on/off
1481 void US_Plot3Dxyz::set_grid_onoff( Qwt3D::SIDE side, bool isOn )
1482 {
1483  int sum = dataWidget->coordinates()->grids();
1484 
1485  sum = isOn ? ( sum | side ) : ( sum & ~side );
1486 
1487  dataWidget->coordinates()->setGridLines( true, true, sum );
1488  dataWidget->updateGL();
1489 }
1490 
1491 // set plot data style points
1493 {
1494  if ( isOn )
1495  {
1496  dataWidget->setPlotStyle( Qwt3D::POINTS );
1497  dataWidget->updateData();
1498  dataWidget->updateGL();
1499  }
1500 }
1501 // set plot data style wireframe
1503 {
1504  if ( isOn )
1505  {
1506  dataWidget->setPlotStyle( WIREFRAME );
1507  dataWidget->updateData();
1508  dataWidget->updateGL();
1509  }
1510 }
1511 // set plot data style hiddenline
1513 {
1514  if ( isOn )
1515  {
1516  dataWidget->setPlotStyle( HIDDENLINE );
1517  dataWidget->updateData();
1518  dataWidget->updateGL();
1519  }
1520 }
1521 // set plot data style polygon only
1523 {
1524  if ( isOn )
1525  {
1526  dataWidget->setPlotStyle( FILLED );
1527  dataWidget->updateData();
1528  dataWidget->updateGL();
1529  }
1530 }
1531 // set plot data style filled mesh
1533 {
1534  if ( isOn )
1535  {
1536  dataWidget->setPlotStyle( FILLEDMESH );
1537  dataWidget->updateData();
1538  dataWidget->updateGL();
1539  }
1540 }
1541 // set plot data style no plot
1543 {
1544  if ( isOn )
1545  {
1546  dataWidget->setPlotStyle( NOPLOT );
1547  dataWidget->updateData();
1548  dataWidget->updateGL();
1549  }
1550 }
1551 
1552 // set floor as data on
1554 {
1555  if ( isOn )
1556  {
1557  dataWidget->setFloorStyle( FLOORDATA );
1558  dataWidget->updateData();
1559  dataWidget->updateGL();
1560  }
1561 }
1562 // set floor as isolines on
1564 {
1565  if ( isOn )
1566  {
1567  dataWidget->setFloorStyle( FLOORISO );
1568  dataWidget->updateData();
1569  dataWidget->updateGL();
1570  }
1571 }
1572 // set floor as empty on
1574 {
1575  if ( isOn )
1576  {
1577  dataWidget->setFloorStyle( NOFLOOR );
1578  dataWidget->updateData();
1579  dataWidget->updateGL();
1580  }
1581 }
1582 
1583 // set show-normals on
1584 void US_Plot3Dxyz::normals_on( bool isOn )
1585 {
1586 DbgLv(2) << "normals_on" << isOn;
1587  dataWidget->showNormals( isOn );
1588  dataWidget->updateNormals();
1589  dataWidget->updateGL();
1590 }
1591 // set normal length
1593 {
1594 DbgLv(2) << "norml_slide" << val;
1595  dataWidget->setNormalLength( (double)val / 400.0 );
1596  dataWidget->updateNormals();
1597  dataWidget->updateGL();
1598 }
1599 // set normal quality
1601 {
1602 DbgLv(2) << "normq_slide" << val;
1603  dataWidget->setNormalQuality( val );
1604  dataWidget->updateNormals();
1605  dataWidget->updateGL();
1606 }
1607 
1608 // rotate 3d plot
1610 {
1611  if ( dataWidget )
1612  {
1613  dataWidget->setRotation(
1614  (int)( dataWidget->xRotation() + 1 ) % 360,
1615  (int)( dataWidget->yRotation() + 1 ) % 360,
1616  (int)( dataWidget->zRotation() + 1 ) % 360 );
1617  }
1618 }
1619 
1620 // open file selected
1622 {
1623 DbgLv(2) << "open_file";
1624 }
1625 
1626 // exit selected
1628 {
1629 DbgLv(2) << "close_all";
1630  clear_2dvect( tdata );
1631  clear_2dvect( zdata );
1632 
1633  emit has_closed();
1634 
1635  close();
1636 }
1637 
1638 // pick axes color
1640 {
1641  QColor cc = QColorDialog::getColor( Qt::black, this,
1642  tr( "Select Axes Color" ) );
1643  Qwt3D::RGBA rgb = Qt2GL( cc );
1644  dataWidget->coordinates()->setAxesColor( rgb );
1645  dataWidget->updateGL();
1646 }
1647 // pick axes color
1649 {
1650  QColor cc = QColorDialog::getColor( Qt::white, this,
1651  tr( "Select Background Color" ) );
1652  Qwt3D::RGBA rgb = Qt2GL( cc );
1653  dataWidget->setBackgroundColor( rgb );
1654  dataWidget->updateGL();
1655 }
1656 // pick mesh color
1658 {
1659  QColor cc = QColorDialog::getColor( Qt::black, this,
1660  tr( "Select Mesh Color" ) );
1661  Qwt3D::RGBA rgb = Qt2GL( cc );
1662  dataWidget->setMeshColor( rgb );
1663  dataWidget->updateData();
1664  dataWidget->updateGL();
1665 }
1666 // pick number color
1668 {
1669  QColor cc = QColorDialog::getColor( Qt::black, this,
1670  tr( "Select Number Color" ) );
1671  Qwt3D::RGBA rgb = Qt2GL( cc );
1672  dataWidget->coordinates()->setNumberColor( rgb );
1673  dataWidget->updateGL();
1674 }
1675 // pick label color
1677 {
1678  QColor cc = QColorDialog::getColor( Qt::black, this,
1679  tr( "Select Label Color" ) );
1680  Qwt3D::RGBA rgb = Qt2GL( cc );
1681  dataWidget->coordinates()->setLabelColor( rgb );
1682  dataWidget->updateGL();
1683 }
1684 // pick caption color
1686 {
1687  QColor cc = QColorDialog::getColor( Qt::black, this,
1688  tr( "Select Caption Color" ) );
1689  Qwt3D::RGBA rgb = Qt2GL( cc );
1690  dataWidget->setTitleColor( rgb );
1691  dataWidget->updateGL();
1692 }
1693 // pick data color map
1695 {
1696  QList< QColor > colorlist;
1697  Qwt3D::ColorVector colorvect;
1698  Qwt3D::StandardColor* stdcol;
1699  Qwt3D::RGBA rgb;
1700 
1701  QString filter = tr( "Color Map files (*cm-*.xml);;" )
1702  + tr( "Any XML files (*.xml);;" )
1703  + tr( "Any files (*)" );
1704 
1705  QString mapfname = QFileDialog::getOpenFileName( this,
1706  tr( "Load Color Map File" ),
1707  US_Settings::etcDir(), filter, 0, 0 );
1708 
1709  if ( mapfname.isEmpty() )
1710  return;
1711 
1712  US_ColorGradIO::read_color_gradient( mapfname, colorlist );
1713 
1714  for ( int ii = 0; ii < colorlist.size(); ii++ )
1715  {
1716  rgb = Qt2GL( colorlist.at( ii ) );
1717  colorvect.push_back( rgb );
1718 DbgLv(1) << "P3D: ii" << ii << "cvec[ii]" << colorlist[ii];
1719  }
1720 
1721  stdcol = new StandardColor( dataWidget );
1722  stdcol ->setColorVector( colorvect );
1723 
1724  dataWidget->setDataColor( stdcol );
1725  dataWidget->updateData();
1726  dataWidget->updateNormals();
1727  dataWidget->showColorLegend( ck_legend->isChecked() );
1728  dataWidget->updateGL();
1729 }
1730 // reset to default colors
1732 {
1733  if ( !dataWidget )
1734  return;
1735 
1736  const Qwt3D::RGBA blackc = Qt2GL( QColor( Qt::black ) );
1737  const Qwt3D::RGBA whitec = Qt2GL( QColor( Qt::white ) );
1738  QList< QColor > colorlist;
1739  Qwt3D::ColorVector colorvect;
1740  Qwt3D::RGBA rgb;
1741  QString mapfname = US_Settings::etcDir() + "/cm-rainbow.xml";
1742  US_ColorGradIO::read_color_gradient( mapfname, colorlist );
1743 
1744  for ( int ii = 0; ii < colorlist.size(); ii++ )
1745  {
1746  rgb = Qt2GL( colorlist.at( ii ) );
1747  colorvect.push_back( rgb );
1748 //DbgLv(1) << "P3D:rc: ii" << ii << "cvec[ii]" << colorlist[ii];
1749  }
1750 
1751  Qwt3D::StandardColor* stdcol = new StandardColor( dataWidget );
1752  stdcol ->setColorVector( colorvect );
1753 
1754  dataWidget->setDataColor( stdcol );
1755  dataWidget->coordinates()->setAxesColor( blackc );
1756  dataWidget->coordinates()->setNumberColor( blackc );
1757  dataWidget->coordinates()->setLabelColor( blackc );
1758  dataWidget->setBackgroundColor( whitec );
1759  dataWidget->setMeshColor( blackc );
1760  dataWidget->setTitleColor( blackc );
1761  dataWidget->updateData();
1762  dataWidget->updateNormals();
1763  dataWidget->showColorLegend( ck_legend->isChecked() );
1764  dataWidget->updateGL();
1765 }
1766 
1767 // pick scale number font
1769 {
1770  bool ok;
1771  QFont oldfont = dataWidget->coordinates()->axes[X1].numberFont();
1772  QFont newfont = QFontDialog::getFont( &ok, oldfont, this,
1773  tr( "Select Scale Numbers Font" ) );
1774 
1775  if ( !ok )
1776  return;
1777 
1778  dataWidget->coordinates()->setNumberFont( newfont );
1779  dataWidget->updateGL();
1780 }
1781 // pick axes labels font
1783 {
1784  bool ok;
1785  QFont oldfont = dataWidget->coordinates()->axes[X1].labelFont();
1786  QFont newfont = QFontDialog::getFont( &ok, oldfont, this,
1787  tr( "Select Axes Labels Font" ) );
1788 
1789  if ( !ok )
1790  return;
1791 
1792  dataWidget->coordinates()->setLabelFont( newfont );
1793  dataWidget->updateGL();
1794 }
1795 // pick title caption font
1797 {
1798  bool ok;
1799  QFont newfont = QFontDialog::getFont( &ok, titleFont, this,
1800  tr( "Select Title Caption Font" ) );
1801 
1802  if ( !ok )
1803  return;
1804 
1805  dataWidget->setTitleFont( newfont.family(), newfont.pointSize(),
1806  newfont.weight() );
1807  dataWidget->updateGL();
1808  titleFont = newfont;
1809 }
1810 // rset fonts
1812 {
1813  dataWidget->setTitleFont( US_GuiSettings::fontFamily(),
1815  dataWidget->coordinates()->setLabelFont( US_GuiSettings::fontFamily(),
1817  QFont::Bold );
1818  dataWidget->coordinates()->setNumberFont( US_GuiSettings::fontFamily(),
1820  dataWidget->updateGL();
1821 }
1822 
1823 // dump plot contents to image file
1825 {
1826  //QString modldesc = model->description.section( "_", 0, 1 );
1827  QString modldesc = "xyz";
1828  QString imagetype = cb_ifmt->currentText();
1829  QString fileext = cb_ifmt->currentText().toLower();
1830  QString datetime = QDateTime::currentDateTime().toString( "yyMMddhhmm" );
1831 
1832  if ( !imagetype.contains( "PS" ) && !imagetype.contains( "PDF" ) )
1833  imagetype = imagetype.toLower();
1834 
1835  QDir dir;
1836  QString reportDir = US_Settings::reportDir();
1837  if ( ! dir.exists( reportDir ) ) dir.mkpath( reportDir );
1838 
1839  QString ofname = US_Settings::reportDir() + "/" + modldesc
1840  + "_" + datetime + "_plot3d." + fileext;
1841 
1842  bool ok = IO::save( dataWidget, ofname, imagetype );
1843 //DbgLv(2) << " oformats" << IO::outputFormatList();
1844 DbgLv(2) << " dump_contents" << ofname << " OK " << ok;
1845 DbgLv(2) << " imagetype" << imagetype;
1846 
1847  if ( ok )
1848  {
1849  statusBar()->showMessage( tr( "Successful dump to " )
1850  + ofname );
1851  }
1852 
1853  else
1854  {
1855  statusBar()->showMessage( tr( "*ERROR* Unable to create " )
1856  + ofname );
1857  }
1858 }
1859 
1860 // Clean up an annotation title for a reload of data
1861 void US_Plot3Dxyz::clean_title( QString& atitle )
1862 {
1863  // Remove any " * <n>" type of appendage
1864  atitle = atitle.section( "*", 0, 0 );
1865 
1866  // Remove leading or trailing blanks
1867  atitle = atitle.simplified();
1868 }
1869 
1870 // Clear 2-D vector
1871 void US_Plot3Dxyz::clear_2dvect( QVector< QVector< double > >& vec )
1872 {
1873  int ncol = vec.size();
1874  if ( ncol < 1 ) return;
1875 
1876  for ( int ii = 0; ii < ncol; ii++ )
1877  vec[ ii ].clear();
1878 
1879  vec.clear();
1880 }
1881 
1882 // Clear 2-D vector
1883 void US_Plot3Dxyz::clear_2dvect( QVector< QVector< Triple > >& vec )
1884 {
1885  int ncol = vec.size();
1886  if ( ncol < 1 ) return;
1887 
1888  for ( int ii = 0; ii < ncol; ii++ )
1889  vec[ ii ].clear();
1890 
1891  vec.clear();
1892 }
1893 
1894 // Allocate 2-D vector
1895 void US_Plot3Dxyz::alloc_2dvect( QVector< QVector< double > >& vec,
1896  int ncol, int nrow )
1897 {
1898  vec.resize( ncol );
1899 
1900  for ( int ii = 0; ii < ncol; ii++ )
1901  vec[ ii ].resize( nrow );
1902 }
1903 
1904 // Allocate 2-D vector
1905 void US_Plot3Dxyz::alloc_2dvect( QVector< QVector< Triple > >& vec,
1906  int ncol, int nrow )
1907 {
1908  vec.resize( ncol );
1909 
1910  for ( int ii = 0; ii < ncol; ii++ )
1911  vec[ ii ].resize( nrow );
1912 }
1913 
1914 
1915