UltraScan III
us_plot3d.cpp
Go to the documentation of this file.
1 
3 #include "us_widgets.h"
4 #include "us_plot3d.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_Plot3D::US_Plot3D( QWidget* p = 0, US_Model* m = 0 )
17  : QMainWindow( p, Qt::Dialog )
18 {
19  model = m;
21  ncols = nrows = 0;
22 
23  // lay out the GUI
24  setWindowTitle( tr( "Model Solute 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( "Model 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  setStandardView();
310  reset_colors();
311 
312  setVisible( true );
313  resize( p1size );
314 }
315 
316 // Public function to set dimension value types and calculate data ranges
317 void US_Plot3D::setTypes( int tx, int ty, int tz )
318 {
319  const double VROUND = 10.0;
320  const double VNEGOF = (1.0/VROUND);
321  const double MAX_ANNO = (99.9/VROUND);
322 // const double MAX_ANNO = (999.0/VROUND);
324  int ncomp = model->components.size();
325  int powrz;
326  double xval;
327  double yval;
328  double zval;
329  double xround = VROUND;
330  double yround = VROUND;
331 
332  // set internal type-flag variables
333  typex = tx;
334  typey = ty;
335  typez = tz;
336 DbgLv(2) << "P3D:sT: type xyz" << typex << typey << typez;
337 
338  // determine the range of values for each of the 3 dimensions
339  sc = &model->components[ 0 ]; // first component
340  xmin = comp_value( sc, typex, 1.0 ); // initial ranges
341  ymin = comp_value( sc, typey, 1.0 );
342  zmin = comp_value( sc, -typez, 1.0 );
343  xmax = xmin;
344  ymax = ymin;
345  zmax = zmin;
346 
347  for ( int ii = 0; ii < ncomp; ii++ )
348  {
349  sc = &model->components[ ii ]; // current component
350 
351  xval = comp_value( sc, typex, 1.0 ); // x,y,z value of component
352  yval = comp_value( sc, typey, 1.0 );
353  zval = comp_value( sc, -typez, 1.0 );
354 
355  xmin = xmin < xval ? xmin : xval; // update range values
356  xmax = xmax > xval ? xmax : xval;
357  ymin = ymin < yval ? ymin : yval;
358  ymax = ymax > yval ? ymax : yval;
359  zmin = zmin < zval ? zmin : zval;
360  zmax = zmax > zval ? zmax : zval;
361  }
362 
363  if ( ncomp == 1 )
364  {
365  zmin *= 0.90;
366  zmax *= 1.10;
367  ymin *= 0.90;
368  ymax *= 1.10;
369  xmin *= 0.90;
370  xmax *= 1.10;
371  }
372 
373  // extend x,y,z ranges a bit
374  xval = ( xmax - xmin ) * 0.05;
375  xmin -= xval;
376  xmax += xval;
377  yval = ( ymax - ymin ) * 0.05;
378  ymin -= yval;
379  ymax += yval;
380 
381  // determine a normalizing power-of-ten for x and y
382  double xavg = ( xmin + xmax ) * 0.5;
383  double yavg = ( ymin + ymax ) * 0.5;
384  x_norm = MAX_ANNO / xavg;
385  y_norm = MAX_ANNO / yavg;
386  z_norm = MAX_ANNO / zmax;
387 DbgLv(2) << "P3D:sR: xmax ymax xnorm ynorm" << xmax << ymax << x_norm << y_norm;
388 DbgLv(2) << "P3D:sR: zmin zmax" << zmin << zmax;
389  powrx = qRound( log10( x_norm ) );
390  powry = qRound( log10( y_norm ) );
391  powrz = qRound( log10( z_norm ) );
392  x_norm = pow( 10.0, (double)powrx );
393  y_norm = pow( 10.0, (double)powry );
394  z_norm = pow( 10.0, (double)powrz );
395  x_norm *= 0.1;
396 
397  if ( ( xavg * x_norm ) > MAX_ANNO )
398  {
399  x_norm *= 0.1;
400  powrx--;
401  }
402 
403  if ( ( yavg * y_norm ) > MAX_ANNO )
404  {
405  y_norm *= 0.1;
406  powry--;
407  }
408 
409  if ( ( zmax * z_norm ) > MAX_ANNO )
410  {
411  z_norm *= 0.1;
412  powrz--;
413  }
414 
415  if ( typex == 6 )
416  {
417  x_norm /= 10.0;
418  xround *= 10.0;
419  }
420  if ( typey == 6 )
421  {
422  y_norm /= 10.0;
423  yround *= 10.0;
424  }
425 
426 DbgLv(2) << "P3D:sR: powx powy xnorm ynorm" << powrx << powry << x_norm << y_norm;
427  xmax *= x_norm;
428  ymax *= y_norm;
429  xmin *= x_norm;
430  ymin *= y_norm;
431  zmin *= z_norm;
432  zmax *= z_norm;
433 DbgLv(2) << "P3D:sR: xmin xmax ymin ymax" << xmin << xmax << ymin << ymax;
434  xmin = (double)( (int)( xmin * xround ) ) / xround;
435  xmax = (double)( (int)( xmax * xround ) + 1 ) / xround;
436  xmin = ( xmin < 0.0 ) ? ( xmin - VNEGOF ) : xmin;
437  ymin = (double)( (int)( ymin * yround ) ) / yround;
438  ymax = (double)( (int)( ymax * yround ) + 1 ) / yround;
439  ymin = ( ymin < 0.0 ) ? ( ymin - VNEGOF ) : ymin;
440  zmax = (double)( (int)( zmax * VROUND ) + 1 ) / VROUND;
441  zmin = 0.0;
442 DbgLv(2) << "P3D:sR: xmin xmax" << xmin << xmax
443  << " ymin ymax" << ymin << ymax << " zmin zmax" << zmin << zmax;
444 }
445 
446 // Public function to set internal variables from plot control parameters
447 void US_Plot3D::setParameters( double z_scale, double a_gridr,
448  double a_alpha, double a_beta, double x_scale, double y_scale )
449 {
450  // get the variables set in the plot control dialog
451  zscale = z_scale;
452  gridres = a_gridr;
453  alpha = a_alpha;
454  beta = a_beta;
455  xscale = x_scale;
456  yscale = y_scale;
457 
458  ncols = qRound( gridres );
459  nrows = ncols;
460 
461  // set size of raster data
462  zdata.resize( ncols );
463 
464  for ( int ii = 0; ii < ncols; ii++ )
465  zdata[ ii ].resize( nrows );
466 
467  // calculate the raster z data from the given model
468 
469  calculateData( zdata );
470 }
471 
472 // calculate raster data from model data
473 void US_Plot3D::calculateData( QVector< QVector< double > >& zdat )
474 {
476  int ncomp = model->components.size();
477  int hixd = ncols / 5; // max raster radius is 5th of total extent
478  int hiyd = nrows / 5;
479  int loxd = 5;
480  int loyd = 5;
481  int nxd = hixd;
482  int nyd = hiyd;
483  int fx;
484  int lx;
485  int rx;
486  int fy;
487  int ly;
488  int ry;
489  double xval;
490  double yval;
491  double zval = zmin;
492  double dist;
493  double dfac = M_PI * 0.5 / beta; // dist-related scale factor
494  double xdif;
495  double ydif;
496  double xpinc = (double)( nrows - 1 ) / ( xmax - xmin ); // xy points/value
497  double ypinc = (double)( ncols - 1 ) / ( ymax - ymin );
498  double zfact = zscale;
499 
500  // Calculate "nxd" and "nyd" the number of reasonable point differentials
501  // around any model point for which to calculate a decayed zvalue.
502  // Beyond these radii, the factor will be insignificant (< 1e-18).
503  // Given that the z value for any raster point near a model point is:
504  // zadd = ( z-peak * ( pow( cos( dist * dfac ), alpha ) ) );
505  // For the limiting "zpkf" factor of 1e-18,
506  // zpkf = pow( cos( dist * dfac ), alpha);
507  // pow( zpkf, 1.0/alpha ) = cos( dist * dfac );
508  // acos( pow( zpkf, 1.0/alpha ) ) = dist * dfac;
509  // acos( pow( zpkf, 1.0/alpha ) ) / dfac = dist;
510  // dist = sqrt( xdif * xdif + xdif * xdif );
511  // dist = sqrt( 2 ) * xdif;
512  // sqrt( 2 ) * xdif = acos( pow( zpkf, 1.0/alpha ) ) / dfac;
513  // xdif = acos( pow( zpkf, 1.0/alpha ) ) / ( sqrt(2) * dfac );
514  // xdif = acos( pow( zpkf, 1.0/alpha ) ) / ( sqrt(2) * M_PI * 0.5 / beta );
515 
516  xdif = acos( pow( 1e-18, ( 1.0 / alpha) ) )
517  * beta / ( M_PI * 0.5 * sqrt( 2.0 ) ); // max xy-diff at small zpkf
518  nxd = qRound( xdif * xpinc ); // reasonable x point radius
519  nyd = qRound( xdif * ypinc ); // reasonable y point radius
520 DbgLv(2) << " xdif nxd nyd" << xdif << nxd << nyd;
521  nxd = nxd * 2 + 2; // fudge each up a bit
522  nyd = nyd * 2 + 2; // just to be extra careful
523  nxd = ( nxd < hixd ) ? nxd : hixd; // at most, a 5th of extent
524  nyd = ( nyd < hiyd ) ? nyd : hiyd;
525  nxd = ( nxd > loxd ) ? nxd : loxd; // at least 5 pixels
526  nyd = ( nyd > loyd ) ? nyd : loyd;
527 DbgLv(2) << " nxd nyd" << nxd << nyd;
528 
529  for ( int ii = 0; ii < nrows; ii++ ) // initialize raster to zmin
530  for ( int jj = 0; jj < ncols; jj++ )
531  zdat[ ii ][ jj ] = zval;
532 
533  for ( int kk = 0; kk < ncomp; kk++ )
534  { // calculate spread of each model point to a radius of raster points
535  sc = &model->components[ kk ]; // current component and xyz
536  xval = comp_value( sc, typex, x_norm ) - xmin;
537  yval = comp_value( sc, typey, y_norm ) - ymin;
538  zval = comp_value( sc, -typez, z_norm );
539 
540  rx = (int)( xval * xpinc ); // raster index of model x
541  fx = rx - nxd; // range of x to work on
542  lx = rx + nxd;
543  fx = ( fx > 0 ) ? fx : 0;
544  lx = ( lx < ncols ) ? lx : ncols;
545 
546  ry = (int)( yval * ypinc ); // raster index of model y
547  fy = ry - nyd; // range of y to work on
548  ly = ry + nyd;
549  fy = ( fy > 0 ) ? fy : 0;
550  ly = ( ly < nrows ) ? ly : nrows;
551 
552  for ( int ii = fx; ii < lx; ii++ )
553  { // find square of difference of x-raster and x-model
554  xdif = sq( (double)ii / xpinc - xval );
555 
556  for ( int jj = fy; jj < ly; jj++ )
557  { // find square of difference of y-raster and y-model
558  ydif = sq( (double)jj / ypinc - yval );
559  // distance of raster point from model point
560  dist = sqrt( xdif + ydif );
561 
562  // If distance is within beta, calculate and sum in the z value
563  // for this raster point. Here is what the following amounts to.
564  // for InZ, the previous raster point Z;
565  // OutZ, the new raster point Z;
566  // ModlZ, the peak model point Z;
567  // Alpha, the user-specified peak smoothing factor;
568  // Beta, the user-specified peak width factor;
569  // Dist, the calculated model-to-raster point distance;
570  // Scale, the calculated Z decay at this distance;
571  // Zfact, the user-specified Z scaling factor;
572  // Scale = Cosine( Dist * PI/2 / Beta ) raised to the Alpha power
573  // OutZ = InZ + ( ModlZ * Scale * Zfact )
574  if ( dist <= beta )
575  {
576  zdat[ ii ][ jj ] += ( ( zval *
577  ( pow( cos( dist * dfac ), alpha ) ) ) * zfact );
578  }
579 //else {DbgLv(3) << " *dist>beta* dist beta iijj" << dist << beta << ii << jj;}
580 //*DBG*
581 //if ( kk>(ncomp/2-2) && kk<(ncomp/2+2) ) {
582 //if ( ii>3 && ii<9 && jj>5 && jj<11 ) {
583 // DbgLv(3) << "kk" << kk << "rx ry ii jj" << rx << ry << ii << jj
584 // << "zout" << zdat[ii][jj] << " zfac" << (pow(cos(dist*dfac),alpha));
585 // DbgLv(3) << " dist" << dist << "dfac alpha beta zval" << dfac
586 // << alpha << beta << zval;
587 //}
588 //*DBG*
589  }
590  }
591 //DbgLv(3) << "P3D:cD: kk fx lx fy ly" << kk << fx << lx << fy << ly
592 // << " xval yval zval" << xval << yval << zval;
593  }
594 }
595 
597 {
598  unsigned int kcols = (unsigned int)ncols;
599  unsigned int krows = (unsigned int)nrows;
600 
601  double** wdata = new double* [ ncols ];
602 DbgLv(2) << "P3D: replot: ncols nrows" << ncols << nrows;
603 
604  double zdmx = zmin;
605  double zfac = 1.0;
606 
607  for ( int ii = 0; ii < ncols; ii++ )
608  { // copy data to work 2D vector and get new z-max
609 if ((ii&63)==1) DbgLv(2) << "P3D: rp: row" << ii;
610  wdata[ ii ] = new double [ nrows ];
611 
612  for ( int jj = 0; jj < nrows; jj++ )
613  {
614  double zval = zdata[ ii ][ jj ];
615  wdata[ ii ][ jj ] = zval;
616  zdmx = zdmx > zval ? zdmx : zval;
617 if ((ii&63)==1&&(jj&63)==1) DbgLv(2) << "P3D: rp: col" << jj
618  << " wdat" << zval;
619  }
620  }
621 
622  // scale back data to have same z-max as before
623  zfac = zmax / zdmx;
624 
625  for ( int ii = 0; ii < ncols; ii++ )
626  for ( int jj = 0; jj < nrows; jj++ )
627  wdata[ ii ][ jj ] *= zfac;
628 
629  // load the widget raster data
630  //dataWidget->loadFromData( wdata, kcols, krows, ymin, ymax, xmin, xmax );
631  dataWidget->loadFromData( wdata, kcols, krows, xmin, xmax, ymin, ymax );
632 
633  // set coordinate system ranges
634  dataWidget->createCoordinateSystem( Triple( xmin, ymin, zmin ),
635  Triple( xmax, ymax, zmax ) );
636  //dataWidget->createCoordinateSystem( Triple( ymin, xmin, zmin ),
637  // Triple( ymax, xmax, zmax ) );
638  //dataWidget->createCoordinateSystem( Triple( -0.6, -0.6, -0.6 ),
639  // Triple( 0.6, 0.6, 0.6 ) );
640  //dataWidget->coordinates()->setPosition
641  // ( Triple( xmin, ymin, zmin ),
642  // Triple( xmax, ymax, zmax ) );
643 
644  dataWidget->makeCurrent();
645  dataWidget->legend()->setScale( LINEARSCALE );
646 
647  for ( uint ii = 0; ii != dataWidget->coordinates()->axes.size(); ++ii )
648  {
649  dataWidget->coordinates()->axes[ ii ].setMajors( 4 );
650  dataWidget->coordinates()->axes[ ii ].setMinors( 5 );
651  }
652 
653  dataWidget->coordinates()->setLabelFont( US_GuiSettings::fontFamily(),
655  QFont::Bold );
656  dataWidget->coordinates()->setLabelColor( Qwt3D::RGBA( 0, 0, 0, 1 ) );
657  dataWidget->coordinates()->setNumberFont( US_GuiSettings::fontFamily(),
659 
660 //dataWidget->coordinates()->setAutoScale( true );
661  QString annopad( " " );
662  x_scale = ymax / xmax;
663  y_scale = 1.0;
664  z_scale = zscale;
667  zatitle = zAxisTitle( typez );
668  xatitle = annopad + xatitle;
669  yatitle = yatitle + annopad;
670 
671 DbgLv(2) << "P3D:rP: xmin xmax" << xmin << xmax
672  << " ymin ymax" << ymin << ymax << " xscl yscl" << x_scale << y_scale;
673  if ( x_scale > 4.0 )
674  {
675  x_scale /= 4.0;
676  }
677 
678  else if ( x_scale < 0.25 )
679  {
680  x_scale *= 2.0;
681  }
682 DbgLv(2) << "P3D:rP: xscl yscl" << x_scale << y_scale;
683  x_scale *= xscale;
684  y_scale *= yscale;
685 
686  dataWidget->coordinates()->axes[X1].setLabelString( xatitle );
687  dataWidget->coordinates()->axes[X2].setLabelString( xatitle );
688  dataWidget->coordinates()->axes[X3].setLabelString( xatitle );
689  dataWidget->coordinates()->axes[X4].setLabelString( xatitle );
690  dataWidget->coordinates()->axes[Y1].setLabelString( yatitle );
691  dataWidget->coordinates()->axes[Y2].setLabelString( yatitle );
692  dataWidget->coordinates()->axes[Y3].setLabelString( yatitle );
693  dataWidget->coordinates()->axes[Y4].setLabelString( yatitle );
694  dataWidget->coordinates()->axes[Z1].setLabelString( zatitle );
695  dataWidget->coordinates()->axes[Z2].setLabelString( zatitle );
696  dataWidget->coordinates()->axes[Z3].setLabelString( zatitle );
697  dataWidget->coordinates()->axes[Z4].setLabelString( zatitle );
698 DbgLv(2) << "P3D:rp:xatitle yatitle" << xatitle << yatitle;
699 
700  dataWidget->setScale( x_scale, y_scale, z_scale );
701 
702  dataWidget->updateData();
703  dataWidget->updateGL();
704 
705  for ( int ii = 0; ii < nrows; ii++ )
706  delete [] wdata[ ii ];
707 
708  delete [] wdata;
709 }
710 
711 // Public method to return a pointer to the data widget
712 QGLWidget* US_Plot3D::dataWidgetP( void )
713 {
714  dataWidget->updateData();
715  dataWidget->updateGL();
716 
717  return (QGLWidget*)dataWidget;
718 }
719 
720 // Public method to save the plot to an image file
721 bool US_Plot3D::save_plot( const QString filename, const QString imagetype )
722 {
723  dataWidget->updateData();
724  dataWidget->updateGL();
725 
726  return IO::save( dataWidget, filename, imagetype );
727 }
728 
729 QString US_Plot3D::xyAxisTitle( int type, double sclnorm )
730 {
731  QString atitle = tr( "s" );
732 
733  switch ( type )
734  {
735  case 1:
736  default:
737  atitle = tr( "MW" );
738  break;
739  case 2:
740  atitle = tr( "s" );
741  break;
742  case 3:
743  atitle = tr( "D" );
744  break;
745  case 4:
746  atitle = tr( "f" );
747  break;
748  case 5:
749  atitle = tr( "f/f0" );
750  break;
751  case 6:
752  atitle = tr( "vbar" );
753  break;
754  }
755 
756  if ( sclnorm != 1.0 )
757  atitle = atitle + " * " + QString::number( sclnorm );
758 
759 DbgLv(2) << "P3D: xyAT: type atitle" << type << atitle;
760  return atitle;
761 }
762 
763 QString US_Plot3D::zAxisTitle( int type )
764 {
765  QString atitle = tr( "Concentration " );
766 
767  if ( type == 2 )
768  atitle = tr( "Mol.Concentr. " );
769 
770  return atitle;
771 }
772 
774 {
775  //if ( xmax < ymax )
776  dataWidget->setRotation( 30, 0, 15 );
777  //else
778  // dataWidget->setRotation( 30, 0, 105 );
779 
780  dataWidget->setViewportShift( 0.05, 0 );
781  dataWidget->setScale( x_scale, y_scale, z_scale );
782  dataWidget->setZoom( 0.95 );
783 }
784 
786 {
787  openAct = new QAction( QIcon( ":/images/fileopen.png" ),
788  tr( "&Open File" ), this );
789  openffAct = new QAction( QIcon( ":/images/filecell.png" ),
790  tr( "Open FEM File" ), this );
791  saveAct = new QAction( QIcon( ":/images/savecontent.png" ),
792  tr( "Dump Contents" ), this );
793  movieAct = new QAction( QIcon( ":/images/movie.png" ),
794  tr( "Animation" ), this );
795 
796  frameAct = new QAction( QIcon( ":/images/frame.png" ),
797  tr( "Frame Axes" ), this );
798  boxAct = new QAction( QIcon( ":/images/box.png" ),
799  tr( "Box Axes" ), this );
800  noneAct = new QAction( QIcon( ":/images/none.png" ),
801  tr( "No Axes" ), this );
802 
803  gridfrAct = new QAction( QIcon( ":/images/gridfr.png" ),
804  tr( "Front Grid" ), this );
805  gridbAct = new QAction( QIcon( ":/images/gridb.png" ),
806  tr( "Back Grid" ), this );
807  gridrAct = new QAction( QIcon( ":/images/gridr.png" ),
808  tr( "Right Grid" ), this );
809  gridlAct = new QAction( QIcon( ":/images/gridl.png" ),
810  tr( "Left Grid" ), this );
811  gridcAct = new QAction( QIcon( ":/images/gridc.png" ),
812  tr( "Ceiling Grid" ), this );
813  gridfAct = new QAction( QIcon( ":/images/gridf.png" ),
814  tr( "Floor Grid" ), this );
815 
816  scattdAct = new QAction( QIcon( ":/images/scattered.png" ),
817  tr( "Points" ), this );
818  wirefrAct = new QAction( QIcon( ":/images/wireframe.png" ),
819  tr( "Wire Frame" ), this );
820  hiddlnAct = new QAction( QIcon( ":/images/hiddenline.png" ),
821  tr( "Hidden Line" ), this );
822  polygnAct = new QAction( QIcon( ":/images/polygon.png" ),
823  tr( "Polygon only" ), this );
824  fdmeshAct = new QAction( QIcon( ":/images/filledmesh.png" ),
825  tr( "Filled Mesh" ), this );
826 
827  nodataAct = new QAction( QIcon( ":/images/nodata.png" ),
828  tr( "No Data" ), this );
829  fldataAct = new QAction( QIcon( ":/images/floordata.png" ),
830  tr( "Floor Data" ), this );
831  flisolAct = new QAction( QIcon( ":/images/flooriso.png" ),
832  tr( "Floor Isolines" ), this );
833  flemptAct = new QAction( QIcon( ":/images/floorempty.png" ),
834  tr( "Floor Empty" ), this );
835 
836  normsAct = new QAction( QIcon( ":/images/normals.png" ),
837  tr( "Normal Vectors" ), this );
838  iconAct = new QAction( QIcon( ":/images/icon.png" ),
839  tr( "Icon" ), this );
840  qwtpltAct = new QAction( QIcon( ":/images/qwtplot.png" ),
841  tr( "QwtPlot" ), this );
842 
843  exitAct = new QAction( tr( "Exit" ), this );
844 
845  coaxesAct = new QAction( tr( "Axes" ), this );
846  cobackAct = new QAction( tr( "Background" ), this );
847  comeshAct = new QAction( tr( "Mesh" ), this );
848  conumbAct = new QAction( tr( "Number" ), this );
849  colablAct = new QAction( tr( "Label" ), this );
850  cocaptAct = new QAction( tr( "Caption" ), this );
851  codataAct = new QAction( tr( "Data Color" ), this );
852  corsetAct = new QAction( tr( "Reset" ), this );
853 
854  fnnumbAct = new QAction( tr( "Scale numbering" ), this );
855  fnaxesAct = new QAction( tr( "Axes label" ), this );
856  fncaptAct = new QAction( tr( "Caption" ), this );
857  fnrsetAct = new QAction( tr( "Reset" ), this );
858 
859  cb_ifmt = new QComboBox( this );
860  cb_ifmt->addItem( tr( "BMP" ) );
861  cb_ifmt->addItem( tr( "JPEG" ) );
862  cb_ifmt->addItem( tr( "PBM" ) );
863  cb_ifmt->addItem( tr( "PGM" ) );
864  cb_ifmt->addItem( tr( "PNG" ) );
865  cb_ifmt->addItem( tr( "PPM" ) );
866  cb_ifmt->addItem( tr( "XBM" ) );
867  cb_ifmt->addItem( tr( "XPM" ) );
868  cb_ifmt->addItem( tr( "EPS" ) );
869  cb_ifmt->addItem( tr( "PS" ) );
870  cb_ifmt->addItem( tr( "EPS-GZ" ) );
871  cb_ifmt->addItem( tr( "PS-GZ" ) );
872  cb_ifmt->addItem( tr( "PDF" ) );
873  cb_ifmt->setCurrentIndex( cb_ifmt->findText( "PNG" ) );
874 }
875 
877 {
878  fileMenu = menuBar()->addMenu( tr( "&File" ) );
879  fileMenu->addAction( openAct );
880  fileMenu->addAction( openffAct );
881  fileMenu->addAction( saveAct );
882  fileMenu->addAction( movieAct );
883  fileMenu->addAction( exitAct );
884 
885  colorMenu = menuBar()->addMenu( tr( "&Color" ) );
886  colorMenu->addAction( coaxesAct );
887  colorMenu->addAction( cobackAct );
888  colorMenu->addAction( comeshAct );
889  colorMenu->addAction( conumbAct );
890  colorMenu->addAction( colablAct );
891  colorMenu->addAction( cocaptAct );
892  colorMenu->addAction( codataAct );
893  colorMenu->addAction( corsetAct );
894 
895  fontMenu = menuBar()->addMenu( tr( "Font" ) );
896  fontMenu->addAction( fnnumbAct );
897  fontMenu->addAction( fnaxesAct );
898  fontMenu->addAction( fncaptAct );
899  fontMenu->addAction( fnrsetAct );
900 }
901 
903 {
904  fileToolBar = new QToolBar( tr( "File" ) );
905  frameGroup = new QActionGroup( this );
906  gridGroup = new QActionGroup( this );
907  dataGroup = new QActionGroup( this );
908  floorGroup = new QActionGroup( this );
909 
910  fileToolBar->addAction( openAct );
911  fileToolBar->addAction( openffAct );
912  fileToolBar->addAction( saveAct );
913  fileToolBar->addWidget( cb_ifmt );
914 
915  fileToolBar->addAction( movieAct );
916  fileToolBar->addAction( frameAct );
917  fileToolBar->addAction( boxAct );
918  fileToolBar->addAction( noneAct );
919  fileToolBar->addSeparator();
920  frameGroup->addAction( frameAct );
921  frameGroup->addAction( boxAct );
922  frameGroup->addAction( noneAct );
923  movieAct->setCheckable( true );
924  frameAct->setCheckable( true );
925  boxAct ->setCheckable( true );
926  noneAct ->setCheckable( true );
927  frameAct->setChecked( true );
928 
929  fileToolBar->addAction( gridfrAct );
930  fileToolBar->addAction( gridbAct );
931  fileToolBar->addAction( gridrAct );
932  fileToolBar->addAction( gridlAct );
933  fileToolBar->addAction( gridcAct );
934  fileToolBar->addAction( gridfAct );
935  fileToolBar->addSeparator();
936  gridGroup->addAction( gridfrAct );
937  gridGroup->addAction( gridbAct );
938  gridGroup->addAction( gridrAct );
939  gridGroup->addAction( gridlAct );
940  gridGroup->addAction( gridcAct );
941  gridGroup->addAction( gridfAct );
942  gridGroup->setExclusive( false );
943  gridfrAct->setCheckable( true );
944  gridbAct ->setCheckable( true );
945  gridrAct ->setCheckable( true );
946  gridlAct ->setCheckable( true );
947  gridcAct ->setCheckable( true );
948  gridfAct ->setCheckable( true );
949  gridGroup->setEnabled( false );
950 
951  fileToolBar->addAction( scattdAct );
952  fileToolBar->addAction( wirefrAct );
953  fileToolBar->addAction( hiddlnAct );
954  fileToolBar->addAction( polygnAct );
955  fileToolBar->addAction( fdmeshAct );
956  fileToolBar->addAction( nodataAct );
957  fileToolBar->addSeparator();
958  dataGroup->addAction( scattdAct );
959  dataGroup->addAction( wirefrAct );
960  dataGroup->addAction( hiddlnAct );
961  dataGroup->addAction( polygnAct );
962  dataGroup->addAction( fdmeshAct );
963  dataGroup->addAction( nodataAct );
964  scattdAct->setCheckable( true );
965  wirefrAct->setCheckable( true );
966  hiddlnAct->setCheckable( true );
967  polygnAct->setCheckable( true );
968  fdmeshAct->setCheckable( true );
969  nodataAct->setCheckable( true );
970  fdmeshAct->setChecked( true );
971 
972  fileToolBar->addAction( fldataAct );
973  fileToolBar->addAction( flisolAct );
974  fileToolBar->addAction( flemptAct );
975  fileToolBar->addAction( normsAct );
976  floorGroup->addAction( fldataAct );
977  floorGroup->addAction( flisolAct );
978  floorGroup->addAction( flemptAct );
979  fldataAct->setCheckable( true );
980  flisolAct->setCheckable( true );
981  flemptAct->setCheckable( true );
982  normsAct ->setCheckable( true );
983  flemptAct->setChecked( true );
984 
985  openAct ->setStatusTip( tr( "Open GridData (.mes) files" ) );
986  openffAct->setStatusTip( tr( "Open Node/Cell files" ) );
987  saveAct ->setStatusTip( tr( "Dump content to image file" ) );
988  cb_ifmt ->setStatusTip( tr( "Select image file format" ) );
989  movieAct ->setStatusTip( tr( "Turn on animation" ) );
990  frameAct ->setStatusTip( tr( "Show frame axes" ) );
991  boxAct ->setStatusTip( tr( "Show box axes" ) );
992  noneAct ->setStatusTip( tr( "Hide axes" ) );
993  gridfrAct->setStatusTip( tr( "Show front grid" ) );
994  gridbAct ->setStatusTip( tr( "Show back grid" ) );
995  gridrAct ->setStatusTip( tr( "Show right grid" ) );
996  gridlAct ->setStatusTip( tr( "Show left grid" ) );
997  gridcAct ->setStatusTip( tr( "Show ceiling grid" ) );
998  gridfAct ->setStatusTip( tr( "Show floor grid" ) );
999  scattdAct->setStatusTip( tr( "Display scattered points data" ) );
1000  wirefrAct->setStatusTip( tr( "Display wire frame data" ) );
1001  hiddlnAct->setStatusTip( tr( "Display hidden line data" ) );
1002  polygnAct->setStatusTip( tr( "Display polygon only data" ) );
1003  fdmeshAct->setStatusTip( tr( "Display mesh & filled polygons" ) );
1004  nodataAct->setStatusTip( tr( "Hide data" ) );
1005  fldataAct->setStatusTip( tr( "Floor data projection" ) );
1006  flisolAct->setStatusTip( tr( "Floor isolines" ) );
1007  flemptAct->setStatusTip( tr( "Floor empty" ) );
1008  normsAct ->setStatusTip( tr( "Show normal vectors" ) );
1009 
1010  addToolBar( fileToolBar );
1011  fileToolBar->adjustSize();
1012  int wdim = qRound( (double)fileToolBar->size().width() * 0.75 );
1013  int hdim = qRound( (double)wdim * 0.75 );
1014  setMinimumSize( wdim, hdim );
1015  adjustSize();
1016 wdim = qRound( (double)size().width() * 0.75 );
1017 DbgLv(2) << " min x,y dim" << wdim;
1018 }
1019 
1020 // get simulation component x/y/z value of given type
1022  double normscl )
1023 {
1024  double xyval = sc->s;
1025 
1026  switch ( type )
1027  { // get appropriate value, based on type
1028  case 1: // x,y value is molecular weight
1029  xyval = sc->mw * normscl;
1030  break;
1031 
1032  case 2: // x,y value is sedimentation coefficient
1033  xyval = sc->s * normscl;
1034  break;
1035 
1036  case 3: // x,y value is diffusion coefficient
1037  xyval = sc->D * normscl;
1038  break;
1039 
1040  case 4: // x,y value is frictional coefficient
1041  xyval = sc->f * normscl;
1042  break;
1043 
1044  case 5: // x,y value is f/f0
1045  xyval = sc->f_f0 * normscl;
1046  break;
1047 
1048  case 6: // x,y value is vbar20
1049  xyval = sc->vbar20 * normscl;
1050  break;
1051 
1052  case -1: // z value is signal concentration
1053  xyval = sc->signal_concentration * normscl;
1054  break;
1055 
1056  case -2: // z value is molar concentration
1057  xyval = sc->molar_concentration * normscl;
1058 
1059  default:
1060  break;
1061  }
1062 
1063  return xyval;
1064 }
1065 
1066 // standard button clicked
1068 {
1069  setStandardView();
1070 }
1071 
1072 // lighting button clicked
1074 {
1075 DbgLv(2) << "light_button";
1076 }
1077 
1078 // image format chosen in combo box
1079 void US_Plot3D::ifmt_chosen( int index )
1080 {
1081 DbgLv(2) << "ifmt_chosen" << index << cb_ifmt->itemText(index);
1082 }
1083 
1084 // lighting checked
1085 void US_Plot3D::light_check( int state )
1086 {
1087 DbgLv(2) << "light_check" << (state==Qt::Checked);
1088 
1089  pb_light->setEnabled( ( state == Qt::Checked ) );
1090 }
1091 
1092 // ortho checked
1093 void US_Plot3D::ortho_check( int state )
1094 {
1095 DbgLv(2) << "ortho_check" << (state==Qt::Checked);
1096  dataWidget->setOrtho( state );
1097 }
1098 
1099 // legend checked
1100 void US_Plot3D::legnd_check( int state )
1101 {
1102 DbgLv(2) << "legnd_check" << (state==Qt::Checked);
1103  dataWidget->showColorLegend( state );
1104 }
1105 
1106 // autoscale checked
1107 void US_Plot3D::autsc_check( int state )
1108 {
1109 DbgLv(2) << "autsc_check" << (state==Qt::Checked);
1110  dataWidget->coordinates()->setAutoScale( state );
1111  dataWidget->updateGL();
1112 }
1113 
1114 // mouse checked
1115 void US_Plot3D::mouse_check( int state )
1116 {
1117 DbgLv(2) << "mouse_check" << (state==Qt::Checked);
1118 }
1119 
1120 // shading checked
1121 void US_Plot3D::shade_check( int state )
1122 {
1123 DbgLv(2) << "shade_check" << (state==Qt::Checked);
1124  dataWidget->setShading( state ? GOURAUD : FLAT );
1125 }
1126 
1127 // polygon offset slider moved
1128 void US_Plot3D::poffs_slide( int pos )
1129 {
1130 DbgLv(2) << "poffs_slide" << pos;
1131  dataWidget->setPolygonOffset( (double)pos / 10.0 );
1132  dataWidget->updateData();
1133  dataWidget->updateGL();
1134 }
1135 
1136 // resolution slider moved
1137 void US_Plot3D::resol_slide( int pos )
1138 {
1139 DbgLv(2) << "resol_slide" << pos;
1140  dataWidget->setResolution( pos );
1141  dataWidget->updateData();
1142  dataWidget->updateGL();
1143 }
1144 // movie (animation) toggled
1145 void US_Plot3D::movie_toggle( bool isOn )
1146 {
1147 DbgLv(2) << "P3D:movie_toggle" << isOn << redrawWait;
1148  if ( isOn )
1149  {
1150  timer->start( redrawWait ); // wait a bit, then redraw
1151  }
1152 
1153  else
1154  {
1155  timer->stop();
1156  }
1157 }
1158 
1159 // frame axes on/off
1160 void US_Plot3D::frame_axes_on( bool isOn )
1161 {
1162  if ( isOn )
1163  {
1164  dataWidget->setCoordinateStyle( FRAME );
1165  gridGroup->setEnabled( true );
1166  }
1167 }
1168 // box axes on/off
1169 void US_Plot3D::box_axes_on( bool isOn )
1170 {
1171  if ( isOn )
1172  {
1173  dataWidget->setCoordinateStyle( BOX );
1174  gridGroup->setEnabled( true );
1175  }
1176 }
1177 // no axes on/off
1178 void US_Plot3D::no_axes_on( bool isOn )
1179 {
1180  if ( isOn )
1181  {
1182  dataWidget->setCoordinateStyle( NOCOORD );
1183  gridGroup->setEnabled( false );
1184  }
1185 }
1186 
1187 // grid front on/off
1188 void US_Plot3D::grid_front_on( bool isOn )
1189 {
1190  set_grid_onoff( FRONT, isOn );
1191 }
1192 
1193 // grid back on/off
1194 void US_Plot3D::grid_back_on( bool isOn )
1195 {
1196  set_grid_onoff( BACK, isOn );
1197 }
1198 
1199 // grid right on/off
1200 void US_Plot3D::grid_right_on( bool isOn )
1201 {
1202  set_grid_onoff( RIGHT, isOn );
1203 }
1204 
1205 // grid left on/off
1206 void US_Plot3D::grid_left_on( bool isOn )
1207 {
1208  set_grid_onoff( LEFT, isOn );
1209 }
1210 
1211 // grid ceiling on/off
1212 void US_Plot3D::grid_ceil_on( bool isOn )
1213 {
1214  set_grid_onoff( CEIL, isOn );
1215 }
1216 
1217 // grid floor on/off
1218 void US_Plot3D::grid_floor_on( bool isOn )
1219 {
1220  set_grid_onoff( FLOOR, isOn );
1221 }
1222 
1223 // set grid(s) on/off
1224 void US_Plot3D::set_grid_onoff( Qwt3D::SIDE side, bool isOn )
1225 {
1226  int sum = dataWidget->coordinates()->grids();
1227 
1228  sum = isOn ? ( sum | side ) : ( sum & ~side );
1229 
1230  dataWidget->coordinates()->setGridLines( true, true, sum );
1231  dataWidget->updateGL();
1232 }
1233 
1234 // set plot data style points
1235 void US_Plot3D::data_points_on( bool isOn )
1236 {
1237  if ( isOn )
1238  {
1239  dataWidget->setPlotStyle( Qwt3D::POINTS );
1240  dataWidget->updateData();
1241  dataWidget->updateGL();
1242  }
1243 }
1244 // set plot data style wireframe
1245 void US_Plot3D::data_wirefr_on( bool isOn )
1246 {
1247  if ( isOn )
1248  {
1249  dataWidget->setPlotStyle( WIREFRAME );
1250  dataWidget->updateData();
1251  dataWidget->updateGL();
1252  }
1253 }
1254 // set plot data style hiddenline
1255 void US_Plot3D::data_hidden_on( bool isOn )
1256 {
1257  if ( isOn )
1258  {
1259  dataWidget->setPlotStyle( HIDDENLINE );
1260  dataWidget->updateData();
1261  dataWidget->updateGL();
1262  }
1263 }
1264 // set plot data style polygon only
1265 void US_Plot3D::data_polygn_on( bool isOn )
1266 {
1267  if ( isOn )
1268  {
1269  dataWidget->setPlotStyle( FILLED );
1270  dataWidget->updateData();
1271  dataWidget->updateGL();
1272  }
1273 }
1274 // set plot data style filled mesh
1275 void US_Plot3D::data_fimesh_on( bool isOn )
1276 {
1277  if ( isOn )
1278  {
1279  dataWidget->setPlotStyle( FILLEDMESH );
1280  dataWidget->updateData();
1281  dataWidget->updateGL();
1282  }
1283 }
1284 // set plot data style no plot
1285 void US_Plot3D::data_none_on( bool isOn )
1286 {
1287  if ( isOn )
1288  {
1289  dataWidget->setPlotStyle( NOPLOT );
1290  dataWidget->updateData();
1291  dataWidget->updateGL();
1292  }
1293 }
1294 
1295 // set floor as data on
1296 void US_Plot3D::floor_data_on( bool isOn )
1297 {
1298  if ( isOn )
1299  {
1300  dataWidget->setFloorStyle( FLOORDATA );
1301  dataWidget->updateData();
1302  dataWidget->updateGL();
1303  }
1304 }
1305 // set floor as isolines on
1306 void US_Plot3D::floor_isol_on( bool isOn )
1307 {
1308  if ( isOn )
1309  {
1310  dataWidget->setFloorStyle( FLOORISO );
1311  dataWidget->updateData();
1312  dataWidget->updateGL();
1313  }
1314 }
1315 // set floor as empty on
1316 void US_Plot3D::floor_empty_on( bool isOn )
1317 {
1318  if ( isOn )
1319  {
1320  dataWidget->setFloorStyle( NOFLOOR );
1321  dataWidget->updateData();
1322  dataWidget->updateGL();
1323  }
1324 }
1325 
1326 // set show-normals on
1327 void US_Plot3D::normals_on( bool isOn )
1328 {
1329 DbgLv(2) << "normals_on" << isOn;
1330  dataWidget->showNormals( isOn );
1331  dataWidget->updateNormals();
1332  dataWidget->updateGL();
1333 }
1334 // set normal length
1335 void US_Plot3D::norml_slide( int val )
1336 {
1337 DbgLv(2) << "norml_slide" << val;
1338  dataWidget->setNormalLength( (double)val / 400.0 );
1339  dataWidget->updateNormals();
1340  dataWidget->updateGL();
1341 }
1342 // set normal quality
1343 void US_Plot3D::normq_slide( int val )
1344 {
1345 DbgLv(2) << "normq_slide" << val;
1346  dataWidget->setNormalQuality( val );
1347  dataWidget->updateNormals();
1348  dataWidget->updateGL();
1349 }
1350 
1351 // rotate 3d plot
1353 {
1354  if ( dataWidget )
1355  {
1356  dataWidget->setRotation(
1357  (int)( dataWidget->xRotation() + 1 ) % 360,
1358  (int)( dataWidget->yRotation() + 1 ) % 360,
1359  (int)( dataWidget->zRotation() + 1 ) % 360 );
1360  }
1361 }
1362 
1363 // open file selected
1365 {
1366 DbgLv(2) << "open_file";
1367 }
1368 
1369 // exit selected
1371 {
1372 DbgLv(2) << "close_all";
1373  if ( ( ncols = zdata.size() ) != 0 )
1374  {
1375  for ( int ii = 0; ii < ncols; ii++ )
1376  zdata[ ii ].clear();
1377 
1378  zdata.clear();
1379  }
1380 
1381  close();
1382 }
1383 
1384 // pick axes color
1386 {
1387  QColor cc = QColorDialog::getColor( Qt::black, this,
1388  tr( "Select Axes Color" ) );
1389  Qwt3D::RGBA rgb = Qt2GL( cc );
1390  dataWidget->coordinates()->setAxesColor( rgb );
1391  dataWidget->updateGL();
1392 }
1393 // pick axes color
1395 {
1396  QColor cc = QColorDialog::getColor( Qt::white, this,
1397  tr( "Select Background Color" ) );
1398  Qwt3D::RGBA rgb = Qt2GL( cc );
1399  dataWidget->setBackgroundColor( rgb );
1400  dataWidget->updateGL();
1401 }
1402 // pick mesh color
1404 {
1405  QColor cc = QColorDialog::getColor( Qt::black, this,
1406  tr( "Select Mesh Color" ) );
1407  Qwt3D::RGBA rgb = Qt2GL( cc );
1408  dataWidget->setMeshColor( rgb );
1409  dataWidget->updateData();
1410  dataWidget->updateGL();
1411 }
1412 // pick number color
1414 {
1415  QColor cc = QColorDialog::getColor( Qt::black, this,
1416  tr( "Select Number Color" ) );
1417  Qwt3D::RGBA rgb = Qt2GL( cc );
1418  dataWidget->coordinates()->setNumberColor( rgb );
1419  dataWidget->updateGL();
1420 }
1421 // pick label color
1423 {
1424  QColor cc = QColorDialog::getColor( Qt::black, this,
1425  tr( "Select Label Color" ) );
1426  Qwt3D::RGBA rgb = Qt2GL( cc );
1427  dataWidget->coordinates()->setLabelColor( rgb );
1428  dataWidget->updateGL();
1429 }
1430 // pick caption color
1432 {
1433  QColor cc = QColorDialog::getColor( Qt::black, this,
1434  tr( "Select Caption Color" ) );
1435  Qwt3D::RGBA rgb = Qt2GL( cc );
1436  dataWidget->setTitleColor( rgb );
1437  dataWidget->updateGL();
1438 }
1439 // pick data color map
1441 {
1442  QList< QColor > colorlist;
1443  Qwt3D::ColorVector colorvect;
1444  Qwt3D::StandardColor* stdcol;
1445  Qwt3D::RGBA rgb;
1446 
1447  QString filter = tr( "Color Map files (*cm-*.xml);;" )
1448  + tr( "Any XML files (*.xml);;" )
1449  + tr( "Any files (*)" );
1450 
1451 #ifndef Q_WS_MAC
1452  QString mapfname = QFileDialog::getOpenFileName( this,
1453  tr( "Load Color Map File" ),
1454  US_Settings::etcDir(), filter, 0, 0 );
1455 #else
1456  QFileDialog fd( this, tr( "Load Color Map File" ) );
1457  fd.selectFile( US_Settings::etcDir() + "/myFile.txt" );
1458  fd.setFilter ( filter );
1459  fd.setOption ( QFileDialog::DontUseNativeDialog );
1460  QString mapfname = fd.getOpenFileName();
1461 #endif
1462 
1463  if ( mapfname.isEmpty() )
1464  return;
1465 
1466  US_ColorGradIO::read_color_gradient( mapfname, colorlist );
1467 
1468  for ( int ii = 0; ii < colorlist.size(); ii++ )
1469  {
1470  rgb = Qt2GL( colorlist.at( ii ) );
1471  colorvect.push_back( rgb );
1472  }
1473 
1474  stdcol = new StandardColor( dataWidget );
1475  stdcol->setColorVector( colorvect );
1476 
1477  dataWidget->setDataColor( stdcol );
1478  dataWidget->updateData();
1479  dataWidget->updateNormals();
1480  dataWidget->showColorLegend( ck_legend->isChecked() );
1481  dataWidget->updateGL();
1482 }
1483 // reset to default colors
1485 {
1486  if ( !dataWidget )
1487  return;
1488 
1489  const QString dmapfn = US_Settings::etcDir()
1490  + "/cm-w-green-blue-red-black.xml";
1491  const Qwt3D::RGBA blackc = Qt2GL( QColor( Qt::black ) );
1492  const Qwt3D::RGBA whitec = Qt2GL( QColor( Qt::white ) );
1493  QList< QColor > colorlist;
1494  Qwt3D::ColorVector colorvect;
1495  Qwt3D::RGBA rgb;
1496  Qwt3D::StandardColor* stdcol = new StandardColor( dataWidget );
1497 
1498  US_ColorGradIO::read_color_gradient( dmapfn, colorlist );
1499 
1500  for ( int ii = 0; ii < colorlist.size(); ii++ )
1501  {
1502  rgb = Qt2GL( colorlist.at( ii ) );
1503  colorvect.push_back( rgb );
1504  }
1505 
1506  stdcol ->setColorVector( colorvect );
1507  dataWidget->coordinates()->setAxesColor( blackc );
1508  dataWidget->coordinates()->setNumberColor( blackc );
1509  dataWidget->coordinates()->setLabelColor( blackc );
1510  dataWidget->setBackgroundColor( whitec );
1511  dataWidget->setMeshColor( blackc );
1512  dataWidget->setTitleColor( blackc );
1513  dataWidget->setDataColor( stdcol );
1514  dataWidget->showColorLegend( ck_legend->isChecked() );
1515  dataWidget->updateData();
1516  dataWidget->updateNormals();
1517  dataWidget->updateGL();
1518 }
1519 
1520 // pick scale number font
1522 {
1523  bool ok;
1524  QFont oldfont = dataWidget->coordinates()->axes[X1].numberFont();
1525  QFont newfont = QFontDialog::getFont( &ok, oldfont, this,
1526  tr( "Select Scale Numbers Font" ) );
1527 
1528  if ( !ok )
1529  return;
1530 
1531  dataWidget->coordinates()->setNumberFont( newfont );
1532  dataWidget->updateGL();
1533 }
1534 // pick axes labels font
1536 {
1537  bool ok;
1538  QFont oldfont = dataWidget->coordinates()->axes[X1].labelFont();
1539  QFont newfont = QFontDialog::getFont( &ok, oldfont, this,
1540  tr( "Select Axes Labels Font" ) );
1541 
1542  if ( !ok )
1543  return;
1544 
1545  dataWidget->coordinates()->setLabelFont( newfont );
1546  dataWidget->updateGL();
1547 }
1548 // pick title caption font
1550 {
1551  bool ok;
1552  QFont newfont = QFontDialog::getFont( &ok, titleFont, this,
1553  tr( "Select Title Caption Font" ) );
1554 
1555  if ( !ok )
1556  return;
1557 
1558  dataWidget->setTitleFont( newfont.family(), newfont.pointSize(),
1559  newfont.weight() );
1560  dataWidget->updateGL();
1561  titleFont = newfont;
1562 }
1563 // rset fonts
1565 {
1566  dataWidget->setTitleFont( US_GuiSettings::fontFamily(),
1568  dataWidget->coordinates()->setLabelFont( US_GuiSettings::fontFamily(),
1570  QFont::Bold );
1571  dataWidget->coordinates()->setNumberFont( US_GuiSettings::fontFamily(),
1573  dataWidget->updateGL();
1574 }
1575 
1576 // dump plot contents to image file
1578 {
1579  QString modldesc = model->description.section( "_", 0, 1 );
1580  QString imagetype = cb_ifmt->currentText();
1581  QString fileext = cb_ifmt->currentText().toLower();
1582  QString datetime = QDateTime::currentDateTime().toString( "yyMMddhhmm" );
1583 
1584  if ( !imagetype.contains( "PS" ) && !imagetype.contains( "PDF" ) )
1585  imagetype = imagetype.toLower();
1586 
1587  QDir dir;
1588  QString reportDir = US_Settings::reportDir();
1589  if ( ! dir.exists( reportDir ) ) dir.mkpath( reportDir );
1590 
1591  QString ofname = US_Settings::reportDir() + "/" + modldesc
1592  + "_" + datetime + "_plot3d." + fileext;
1593 
1594  bool ok = IO::save( dataWidget, ofname, imagetype );
1595 //DbgLv(2) << " oformats" << IO::outputFormatList();
1596 DbgLv(2) << " dump_contents" << ofname << " OK " << ok;
1597 DbgLv(2) << " imagetype" << imagetype;
1598 
1599  if ( ok )
1600  {
1601  statusBar()->showMessage( tr( "Successful dump to " )
1602  + ofname );
1603  }
1604 
1605  else
1606  {
1607  statusBar()->showMessage( tr( "*ERROR* Unable to create " )
1608  + ofname );
1609  }
1610 }
1611