added progress bar
[engrid.git] / src / libengrid / guimainwindow.cpp
blobe4cd0819bff0928ef07f679f77bb62004377477d
1 //
2 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 // + +
4 // + This file is part of enGrid. +
5 // + +
6 // + Copyright 2008-2012 enGits GmbH +
7 // + +
8 // + enGrid is free software: you can redistribute it and/or modify +
9 // + it under the terms of the GNU General Public License as published by +
10 // + the Free Software Foundation, either version 3 of the License, or +
11 // + (at your option) any later version. +
12 // + +
13 // + enGrid is distributed in the hope that it will be useful, +
14 // + but WITHOUT ANY WARRANTY; without even the implied warranty of +
15 // + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +
16 // + GNU General Public License for more details. +
17 // + +
18 // + You should have received a copy of the GNU General Public License +
19 // + along with enGrid. If not, see <http://www.gnu.org/licenses/>. +
20 // + +
21 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
22 //
23 #include "guimainwindow.h"
24 #include "guiselectboundarycodes.h"
25 #include "guiimproveaspectratio.h"
26 #include "guinormalextrusion.h"
27 #include "guisetboundarycode.h"
28 #include "guipick.h"
30 #include "vtkEgPolyDataToUnstructuredGridFilter.h"
31 #include "stlreader.h"
32 #include "gmshreader.h"
33 #include "gmshwriter.h"
34 #include "neutralwriter.h"
35 #include "stlwriter.h"
36 #include "plywriter.h"
37 #include "correctsurfaceorientation.h"
38 #include "guieditboundaryconditions.h"
39 #include "laplacesmoother.h"
40 #include "swaptriangles.h"
42 #include <vtkRenderer.h>
43 #include <vtkRenderWindow.h>
44 #include <vtkXMLUnstructuredGridWriter.h>
45 #include <vtkXMLUnstructuredGridReader.h>
46 #include <vtkProperty.h>
47 #include <vtkCallbackCommand.h>
48 #include <vtkCamera.h>
49 #include <vtkCharArray.h>
50 #include <vtkTextActor.h>
51 #include <vtkVectorText.h>
52 #include <vtkFollower.h>
53 #include <vtkLookupTable.h>
54 #include <vtkScalarBarActor.h>
56 #include <QFileDialog>
57 #include <QFileSystemWatcher>
58 #include <QFileInfo>
59 #include <QAction>
60 #include <stdlib.h>
61 #include <stdio.h>
63 #include "geometrytools.h"
64 #include "engrid_version.h"
66 using namespace GeometryTools;
68 #include "guisettingsviewer.h"
69 #include "guitransform.h"
70 #include "egvtkinteractorstyle.h"
71 #include "showinfo.h"
72 #include "engrid_version.h"
74 QString GuiMainWindow::m_cwd = ".";
75 QSettings GuiMainWindow::m_qset("enGits","enGrid");
76 GuiMainWindow* GuiMainWindow::THIS = NULL;
77 QMutex GuiMainWindow::m_Mutex;
78 bool GuiMainWindow::m_UnSaved = true;
80 GuiMainWindow::GuiMainWindow() : QMainWindow(NULL)
82 setupGuiMainWindow();
83 if(m_open_last) {
84 if(m_qset.contains("LatestFile")) {
85 // qDebug()<<"Opening latest";
86 open(m_qset.value("LatestFile").toString());
91 GuiMainWindow::GuiMainWindow(QString file_name) : QMainWindow(NULL)
93 setupGuiMainWindow();
94 open(file_name);
97 void GuiMainWindow::setupGuiMainWindow()
99 ui.setupUi(this);
100 THIS = this;
102 // restore window size
103 if(m_qset.contains("GuiMainWindow")) {
104 setGeometry(m_qset.value("GuiMainWindow").toRect());
106 else {
107 this->setWindowState(Qt::WindowMaximized);
110 // restore dockwidget positions
111 if(m_qset.contains("dockWidget_states")) {
112 restoreState(m_qset.value("dockWidget_states").toByteArray());
114 else {
115 tabifyDockWidget(ui.dockWidget_output, ui.dockWidget_node_cell_info);
116 tabifyDockWidget(ui.dockWidget_DisplayOptions, ui.dockWidget_DebuggingUtilities);
117 ui.dockWidget_node_cell_info->hide();
118 ui.dockWidget_DebuggingUtilities->hide();
121 # include "std_connections.h"
123 if (m_qset.contains("working_directory")) {
124 m_cwd = m_qset.value("working_directory").toString();
127 setupVtk();
129 resetOperationCounter();//clears undo/redo list and disables undo/redo
130 m_CurrentFilename = "untitled.egc";
131 setWindowTitle(m_CurrentFilename + " - enGrid - " + QString("%1").arg(m_CurrentOperation) );
132 setUnsaved(true);
134 m_StatusInfoLabel = new QLabel(this);
135 statusBar()->addWidget(m_StatusInfoLabel);
136 m_StatusInfoLabel->setText("");
138 m_StatusProgressBar = new QProgressBar(this);
139 statusBar()->addWidget(m_StatusProgressBar);
141 m_StatusLabel = new QLabel(this);
142 statusBar()->addWidget(m_StatusLabel);
144 QString txt = "0 volume cells (0 tetras, 0 hexas, 0 pyramids, 0 prisms), ";
145 txt += "0 surface cells (0 triangles, 0 quads), 0 nodes";
146 m_StatusLabel->setText(txt);
147 ui.label_node_cell_info->setText(txt);
149 #ifdef WIN32
150 QString user = QString(getenv("USERNAME"));
151 #else
152 QString user = QString(getenv("USER"));
153 #endif // WIN32
154 QString basename="enGrid_output.txt";
156 // define temporary path
157 QDir dir("/");
158 if (m_qset.contains("tmp_directory")) {
159 m_LogDir = m_qset.value("tmp_directory").toString();
160 } else {
161 m_LogDir = dir.tempPath();
163 QDateTime now = QDateTime::currentDateTime();
164 m_LogDir = m_LogDir + "/" + "enGrid_" + QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz") + "/";
165 dir.mkpath(m_LogDir);
167 m_LogFileName = m_LogDir + basename;
168 cout << "m_LogFileName = " << qPrintable(m_LogFileName) << endl;
170 #if defined( __linux__ ) //for Linux
171 //Sources for POSIX redirection:
172 // http://c-faq.com/stdio/undofreopen.html
173 // http://stackoverflow.com/questions/4832603/how-could-i-temporary-redirect-stdout-to-a-file-in-a-c-program
175 fflush(stdout);
176 fgetpos(stdout, &m_SystemStdout_pos);
177 m_SystemStdout = dup(fileno(stdout)); //backup a duplicate of the stdout
178 if (freopen (qPrintable(m_LogFileName), "w", stdout)==NULL) {
179 EG_BUG;
181 m_LogFileStdout = dup(fileno(stdout)); //backup a duplicate of the log_out
183 #elif defined( _WIN32 ) //for Windows
184 m_SystemStdout = stdout;
185 if (freopen (qPrintable(m_LogFileName), "w", stdout)==NULL) {
186 EG_BUG;
188 m_LogFileStdout = stdout;
190 #else
191 #error "Please define the proper way to save the stdout."
192 #endif
194 m_Busy = false;
196 setPickMode(true,true);
197 m_PickedPoint = -1;
198 m_PickedCell = -1;
200 updateStatusBar();
202 connect(&m_GarbageTimer, SIGNAL(timeout()), this, SLOT(periodicUpdate()));
203 m_GarbageTimer.start(1000);
205 connect(&m_LogTimer, SIGNAL(timeout()), this, SLOT(updateOutput()));
206 m_LogTimer.start(1000);
208 m_N_chars = 0;
210 bool exp_features=false;
211 getSet("General","enable experimental features",false,exp_features);
212 getSet("General","enable undo+redo",false,m_undo_redo_enabled);
213 bool undo_redo_mode;
214 getSet("General","use RAM for undo+redo operations",false,undo_redo_mode);
215 getSet("General", "open last used file on startup", false, m_open_last);
217 ui.actionMirrorMesh->setEnabled(exp_features);
218 ui.actionBooleanOperation->setEnabled(exp_features);
219 ui.actionCreateHexCore->setEnabled(exp_features);
220 ui.actionOptimiseOrthogonalty->setEnabled(exp_features);
221 ui.actionImportFluentCase->setEnabled(exp_features);
223 m_ReferenceSize=0.2;
225 ui.doubleSpinBox_HueMin->setValue(0.667);
226 ui.doubleSpinBox_HueMax->setValue(0);
228 egvtkInteractorStyle *style = egvtkInteractorStyle::New();
229 getInteractor()->SetInteractorStyle(style);
230 style->Delete();
232 // initialise XML document
233 m_XmlHandler = new XmlHandler("engridcase");
234 // this->resetXmlDoc();
236 m_SolverIndex = 0;
238 readRecentFiles();
240 // load plugins
241 QString plugin_path;
242 getSet("General", "plugin path", "/usr/lib/engrid", plugin_path);
243 QDir plugin_dir(plugin_path);
244 m_PluginOperations.clear();
245 foreach (QString file_name, plugin_dir.entryList(QDir::Files)) {
246 if (file_name.right(3) == ".so") {
247 cout << qPrintable(plugin_dir.absoluteFilePath(file_name)) << endl;
248 QPluginLoader loader(plugin_dir.absoluteFilePath(file_name));
249 QObject *qobject = loader.instance();
250 if (!qobject) {
251 cout << "an error occurred while loading the plugins:\n";
252 cout << qPrintable(loader.errorString()) << "\n" << endl;
254 if (Operation *operation = qobject_cast<Operation*>(qobject)) {
255 //operation->setLockGui();
256 QAction *action = new QAction(operation->getMenuText(), this);
257 connect(action, SIGNAL(triggered()), this, SLOT(pluginCalled()));
258 m_PluginOperations[action] = operation;
259 ui.menuPlugins->addAction(action);
264 m_EscAction = new QAction("escape", this);
265 addAction(m_EscAction);
266 m_EscAction->setShortcut(QKeySequence(Qt::Key_Escape));
267 connect(m_EscAction, SIGNAL(triggered()), this, SLOT(onEsc()));
270 //end of GuiMainWindow::GuiMainWindow() : QMainWindow(NULL)
272 void GuiMainWindow::pluginCalled()
274 QAction *action = qobject_cast<QAction*>(QObject::sender());
275 if (action) {
276 Operation *operation = m_PluginOperations[action];
277 operation->operator()();
281 void GuiMainWindow::resetXmlDoc()
283 m_XmlHandler->resetXmlDoc();
286 GuiMainWindow::~GuiMainWindow()
288 writeRecentFiles();
290 m_qset.setValue("GuiMainWindow", this->geometry());
291 m_qset.setValue("dockWidget_states", this->saveState());
293 #ifndef QT_DEBUG
294 setSystemOutput(); //close the output to the log file
295 QDirIterator it(m_LogDir);
296 while (it.hasNext()) {
297 QString str = it.next();
298 QFileInfo fileinfo(str);
299 if(fileinfo.isFile()) {
300 QFile file(str);
301 if(!file.remove()) {
302 setLogFileOutput(); //reinstate the connection to the log file
303 qDebug() << "Failed to remove " << file.fileName();
307 QDir dir(m_LogDir);
308 dir.rmdir(m_LogDir);
309 #endif
311 delete m_XmlHandler;
313 #if defined( __linux__ ) //for Linux
314 ::close(m_SystemStdout); //close this duplicate
315 ::close(m_LogFileStdout); //close this duplicate
317 #elif defined( _WIN32 ) //for Windows
318 //Nothing to do so far
319 #else
320 #error "Please define the proper way to close the saved stdouts."
321 #endif
324 void GuiMainWindow::setupVtk()
326 // colour settings
327 getSet("Colours", "'A' faces (1-red)", 0.5, m_ColAR);
328 getSet("Colours", "'A' faces (2-green)", 1.0, m_ColAG);
329 getSet("Colours", "'A' faces (3-blue)", 0.5, m_ColAB);
331 getSet("Colours", "'B' faces (1-red)", 1.0, m_ColBR);
332 getSet("Colours", "'B' faces (2-green)", 1.0, m_ColBG);
333 getSet("Colours", "'B' faces (3-blue)", 0.5, m_ColBB);
335 getSet("Colours", " tetras (1-red)", 1.0, m_ColTetraR);
336 getSet("Colours", " tetras (2-green)", 0.0, m_ColTetraG);
337 getSet("Colours", " tetras (3-blue)", 0.0, m_ColTetraB);
339 getSet("Colours", " prisms (1-red)", 0.0, m_ColPrismR);
340 getSet("Colours", " prisms (2-green)", 1.0, m_ColPrismG);
341 getSet("Colours", " prisms (3-blue)", 0.0, m_ColPrismB);
343 getSet("Colours", " pyramids (1-red)", 1.0, m_ColPyraR);
344 getSet("Colours", " pyramids (2-green)", 1.0, m_ColPyraG);
345 getSet("Colours", " pyramids (3-blue)", 0.0, m_ColPyraB);
347 getSet("Colours", " hexes (1-red)", 0.0, m_ColHexR);
348 getSet("Colours", " hexes (2-green)", 0.7, m_ColHexG);
349 getSet("Colours", " hexes (3-blue)", 1.0, m_ColHexB);
351 m_Grid = vtkUnstructuredGrid::New();
352 m_Renderer = vtkRenderer::New();
353 getRenderWindow()->AddRenderer(m_Renderer);
355 // coordinate axes
356 m_Axes = vtkCubeAxesActor2D::New();
358 m_Axes->SetCamera(getRenderer()->GetActiveCamera());
359 getRenderer()->AddActor(m_Axes);
360 m_Axes->SetVisibility(0);
362 // surface pipelines
363 m_BackfaceProperty = vtkProperty::New();
364 m_SurfaceFilter = vtkGeometryFilter::New();
365 m_SurfaceMapper = vtkPolyDataMapper::New();
366 m_SurfaceWireMapper = vtkPolyDataMapper::New();
367 m_BCodesFilter = vtkEgBoundaryCodesFilter::New();
368 m_LookupTable = vtkLookupTable::New();
369 m_SurfaceActor = vtkActor::New();
370 m_SurfaceWireActor = vtkActor::New();
371 m_LegendActor = vtkScalarBarActor::New();
373 m_BCodesFilter->SetBoundaryCodes(m_DisplayBoundaryCodes);
374 m_BCodesFilter->SetInput(m_Grid);
375 m_SurfaceFilter->SetInput(m_BCodesFilter->GetOutput());
376 m_SurfaceMapper->SetInput(m_SurfaceFilter->GetOutput());
377 m_SurfaceWireMapper->SetInput(m_SurfaceFilter->GetOutput());
378 m_SurfaceMapper->SetLookupTable(m_LookupTable);
379 m_SurfaceActor->GetProperty()->SetRepresentationToSurface();
380 m_SurfaceActor->GetProperty()->SetColor(m_ColAR, m_ColAG, m_ColAB);
381 m_SurfaceActor->SetBackfaceProperty(m_BackfaceProperty);
382 m_SurfaceActor->GetBackfaceProperty()->SetColor(m_ColBR, m_ColBG, m_ColBB);
383 m_SurfaceActor->SetMapper(m_SurfaceMapper);
384 getRenderer()->AddActor(m_SurfaceActor);
385 m_SurfaceActor->SetVisibility(1);
386 m_LegendActor->SetLookupTable(m_LookupTable);
387 getRenderer()->AddActor(m_LegendActor);
388 m_LegendActor->SetVisibility(0);
389 m_SurfaceWireActor->GetProperty()->SetRepresentationToWireframe();
390 m_SurfaceWireActor->GetProperty()->SetColor(0,0,1);
391 m_SurfaceWireActor->SetMapper(m_SurfaceWireMapper);
392 getRenderer()->AddActor(m_SurfaceWireActor);
393 m_SurfaceWireActor->SetVisibility(1);
395 // tetra pipline
396 m_ExtrTetras = vtkEgExtractVolumeCells::New();
397 m_TetraActor = vtkActor::New();
398 m_TetraGeometry = vtkGeometryFilter::New();
399 m_TetraMapper = vtkPolyDataMapper::New();
401 m_ExtrTetras->SetInput(m_Grid);
402 m_ExtrTetras->SetAllOff();
403 m_ExtrTetras->SetTetrasOn();;
404 m_TetraGeometry->SetInput(m_ExtrTetras->GetOutput());
405 m_TetraMapper->SetInput(m_TetraGeometry->GetOutput());
406 m_TetraActor->SetMapper(m_TetraMapper);
407 m_TetraActor->GetProperty()->SetColor(m_ColTetraR, m_ColTetraG, m_ColTetraB);
408 getRenderer()->AddActor(m_TetraActor);
409 m_TetraActor->SetVisibility(0);
411 // pyramid pipeline
412 m_PyramidActor = vtkActor::New();
413 m_ExtrPyramids = vtkEgExtractVolumeCells::New();
414 m_PyramidGeometry = vtkGeometryFilter::New();
415 m_PyramidMapper = vtkPolyDataMapper::New();
417 m_ExtrPyramids->SetInput(m_Grid);
418 m_ExtrPyramids->SetAllOff();
419 m_ExtrPyramids->SetPyramidsOn();
420 m_PyramidGeometry->SetInput(m_ExtrPyramids->GetOutput());
421 m_PyramidMapper->SetInput(m_PyramidGeometry->GetOutput());
422 m_PyramidActor->SetMapper(m_PyramidMapper);
423 m_PyramidActor->GetProperty()->SetColor(m_ColPyraR, m_ColPyraG, m_ColPyraB);
424 getRenderer()->AddActor(m_PyramidActor);
425 m_PyramidActor->SetVisibility(0);
427 // wedge pipeline
428 m_WedgeActor = vtkActor::New();
429 m_ExtrWedges = vtkEgExtractVolumeCells::New();
430 m_WedgeGeometry = vtkGeometryFilter::New();
431 m_WedgeMapper = vtkPolyDataMapper::New();
433 m_ExtrWedges->SetInput(m_Grid);
434 m_ExtrWedges->SetAllOff();
435 m_ExtrWedges->SetWedgesOn();
436 m_WedgeGeometry->SetInput(m_ExtrWedges->GetOutput());
437 m_WedgeMapper->SetInput(m_WedgeGeometry->GetOutput());
438 m_WedgeActor->SetMapper(m_WedgeMapper);
439 m_WedgeActor->GetProperty()->SetColor(m_ColPrismR, m_ColPrismG, m_ColPrismB);
440 getRenderer()->AddActor(m_WedgeActor);
441 m_WedgeActor->SetVisibility(0);
443 // hexa pipeline
444 m_HexaActor = vtkActor::New();
445 m_ExtrHexes = vtkEgExtractVolumeCells::New();
446 m_HexaGeometry = vtkGeometryFilter::New();
447 m_HexaMapper = vtkPolyDataMapper::New();
449 m_ExtrHexes->SetInput(m_Grid);
450 m_ExtrHexes->SetAllOff();
451 m_ExtrHexes->SetHexesOn();
452 m_HexaGeometry->SetInput(m_ExtrHexes->GetOutput());
453 m_HexaMapper->SetInput(m_HexaGeometry->GetOutput());
454 m_HexaActor->SetMapper(m_HexaMapper);
455 m_HexaActor->GetProperty()->SetColor(m_ColHexR, m_ColHexG, m_ColHexB);
456 getRenderer()->AddActor(m_HexaActor);
457 m_HexaActor->SetVisibility(0);
459 // polyhedra pipeline
460 m_PolyhedraActor = vtkActor::New();
461 m_ExtrPolyhedra = vtkEgExtractVolumeCells::New();
462 m_PolyhedraGeometry = vtkGeometryFilter::New();
463 m_PolyhedraMapper = vtkPolyDataMapper::New();
465 m_ExtrPolyhedra->SetInput(m_Grid);
466 m_ExtrPolyhedra->SetAllOff();
467 m_ExtrPolyhedra->SetPolysOn();
468 m_PolyhedraGeometry->SetInput(m_ExtrPolyhedra->GetOutput());
469 m_PolyhedraMapper->SetInput(m_PolyhedraGeometry->GetOutput());
470 m_PolyhedraActor->SetMapper(m_PolyhedraMapper);
471 m_PolyhedraActor->GetProperty()->SetColor(1,0.5,0);
472 getRenderer()->AddActor(m_PolyhedraActor);
473 m_PolyhedraActor->SetVisibility(0);
475 // volume wire pipeline
476 m_VolumeWireActor = vtkActor::New();
477 m_ExtrVol = vtkEgExtractVolumeCells::New();
478 m_VolumeGeometry = vtkGeometryFilter::New();
479 m_VolumeWireMapper = vtkPolyDataMapper::New();
481 m_ExtrVol->SetInput(m_Grid);
482 m_ExtrVol->SetAllOn();
483 m_VolumeGeometry->SetInput(m_ExtrVol->GetOutput());
484 m_VolumeWireMapper->SetInput(m_VolumeGeometry->GetOutput());
485 m_VolumeWireActor->SetMapper(m_VolumeWireMapper);
486 m_VolumeWireActor->GetProperty()->SetRepresentationToWireframe();
487 m_VolumeWireActor->GetProperty()->SetColor(0,0,1);
488 getRenderer()->AddActor(m_VolumeWireActor);
489 m_VolumeWireActor->SetVisibility(0);
491 // picker stuff
492 m_PickSphere = vtkSphereSource::New();
493 m_PickMapper = vtkPolyDataMapper::New();
494 m_PickActor = vtkActor::New();
495 m_CellPicker = vtkCellPicker::New();
496 m_PointPicker = vtkPointPicker::New();
498 m_PickSphere->SetRadius(0.25); //in case the user starts picking points instead of cells
499 m_PickMapper->SetInput(m_PickSphere->GetOutput());
500 m_PickActor->SetMapper(m_PickMapper);
501 m_PickActor->GetProperty()->SetRepresentationToSurface();
502 m_PickActor->GetProperty()->SetColor(0,0,1);
503 m_PickActor->VisibilityOff();
504 getRenderer()->AddActor(m_PickActor);
506 vtkCallbackCommand *cbc = vtkCallbackCommand::New();
507 cbc->SetCallback(pickCallBack);
509 m_CellPicker->AddObserver(vtkCommand::EndPickEvent, cbc);
510 m_PointPicker->AddObserver(vtkCommand::EndPickEvent, cbc);
511 m_PickedObject = 0;
513 viewFront();
514 // cbc->Delete();
517 void GuiMainWindow::updateOutput()
519 QFile log_file(m_LogFileName);
520 log_file.open(QIODevice::ReadOnly);
521 QByteArray buffer = log_file.readAll();
522 if (buffer.size() > m_N_chars) {
523 QByteArray newchars = buffer.right(buffer.size() - m_N_chars);
524 m_N_chars = buffer.size();
525 QString txt(newchars);
526 if (txt.right(1) == "\n") {
527 txt = txt.left(txt.size()-1);
529 ui.textEditOutput->append(txt);
533 void GuiMainWindow::exit()
535 QCoreApplication::exit();
538 vtkRenderWindow* GuiMainWindow::getRenderWindow()
540 return ui.qvtkWidget->GetRenderWindow();
543 vtkRenderer* GuiMainWindow::getRenderer()
545 return m_Renderer;
548 QVTKInteractor* GuiMainWindow::getInteractor()
550 return ui.qvtkWidget->GetInteractor();
553 QString GuiMainWindow::getCwd()
555 return m_cwd;
558 void GuiMainWindow::setCwd(QString dir)
560 m_cwd = dir;
561 m_qset.setValue("working_directory",dir);
564 void GuiMainWindow::setUnsaved(bool unsaved)
566 m_UnSaved = unsaved;
569 void GuiMainWindow::scaleToData()
571 int current_field=ui.comboBox_Field->currentIndex();
572 if(current_field>0)
574 double range[2];
576 m_SurfaceFilter->GetOutput()->GetPointData()->GetArray(current_field-1)->GetRange(range);
577 //boundary_pd->GetPointData()->GetArray(current_field-1)->GetRange(range);
578 cout<<"current_field="<<current_field<<endl;
579 cout<<"range[0]="<<range[0]<<endl;
580 cout<<"range[1]="<<range[1]<<endl;
581 ui.doubleSpinBox_FieldMin->setRange(range[0],range[1]);
582 ui.doubleSpinBox_FieldMax->setRange(range[0],range[1]);
583 ui.doubleSpinBox_FieldMin->setValue(range[0]);
584 ui.doubleSpinBox_FieldMax->setValue(range[1]);
588 void GuiMainWindow::setClipX(const QString &txt)
590 m_ExtrVol->Setx(txt.toDouble());
591 m_ExtrTetras->Setx(txt.toDouble());
592 m_ExtrPyramids->Setx(txt.toDouble());
593 m_ExtrWedges->Setx(txt.toDouble());
594 m_ExtrHexes->Setx(txt.toDouble());
595 m_ExtrPolyhedra->Setx(txt.toDouble());
598 void GuiMainWindow::setClipY(const QString &txt)
600 m_ExtrVol->Sety(txt.toDouble());
601 m_ExtrTetras->Sety(txt.toDouble());
602 m_ExtrPyramids->Sety(txt.toDouble());
603 m_ExtrWedges->Sety(txt.toDouble());
604 m_ExtrHexes->Sety(txt.toDouble());
605 m_ExtrPolyhedra->Sety(txt.toDouble());
608 void GuiMainWindow::setClipZ(const QString &txt)
610 m_ExtrVol->Setz(txt.toDouble());
611 m_ExtrTetras->Setz(txt.toDouble());
612 m_ExtrPyramids->Setz(txt.toDouble());
613 m_ExtrWedges->Setz(txt.toDouble());
614 m_ExtrHexes->Setz(txt.toDouble());
615 m_ExtrPolyhedra->Setz(txt.toDouble());
618 void GuiMainWindow::setClipNX(const QString &txt)
620 m_ExtrVol->Setnx(txt.toDouble());
621 m_ExtrTetras->Setnx(txt.toDouble());
622 m_ExtrPyramids->Setnx(txt.toDouble());
623 m_ExtrWedges->Setnx(txt.toDouble());
624 m_ExtrHexes->Setnx(txt.toDouble());
625 m_ExtrPolyhedra->Setnx(txt.toDouble());
628 void GuiMainWindow::setClipNY(const QString &txt)
630 m_ExtrVol->Setny(txt.toDouble());
631 m_ExtrTetras->Setny(txt.toDouble());
632 m_ExtrPyramids->Setny(txt.toDouble());
633 m_ExtrWedges->Setny(txt.toDouble());
634 m_ExtrHexes->Setny(txt.toDouble());
635 m_ExtrPolyhedra->Setny(txt.toDouble());
638 void GuiMainWindow::setClipNZ(const QString &txt)
640 m_ExtrVol->Setnz(txt.toDouble());
641 m_ExtrTetras->Setnz(txt.toDouble());
642 m_ExtrPyramids->Setnz(txt.toDouble());
643 m_ExtrWedges->Setnz(txt.toDouble());
644 m_ExtrHexes->Setnz(txt.toDouble());
645 m_ExtrPolyhedra->Setnz(txt.toDouble());
648 void GuiMainWindow::updateSurfaceActors(bool forced)
650 if (ui.checkBoxSurface->isChecked()) {
651 if (forced) {
652 m_SurfaceFilter->Update();
655 // fill node field combobox
656 int current_field=ui.comboBox_Field->currentIndex();
657 ui.comboBox_Field->clear();
658 ui.comboBox_Field->addItem("None");
659 for (int i = 0; i < m_Grid->GetPointData()->GetNumberOfArrays(); ++i) {
660 ui.comboBox_Field->addItem(m_Grid->GetPointData()->GetArrayName(i));
662 if(current_field == -1) {
663 ui.comboBox_Field->setCurrentIndex(0);
664 } else {
665 ui.comboBox_Field->setCurrentIndex(current_field);
668 // fill cell field combobox
669 int current_cell_field = ui.comboBox_CellTextField->currentIndex();
670 ui.comboBox_CellTextField->clear();
671 ui.comboBox_CellTextField->addItem("Cell ID");
672 for (int i = 0; i < m_SurfaceFilter->GetOutput()->GetCellData()->GetNumberOfArrays(); ++i) {
673 ui.comboBox_CellTextField->addItem(m_Grid->GetCellData()->GetArrayName(i));
675 if(current_cell_field == -1) {
676 ui.comboBox_CellTextField->setCurrentIndex(0);
677 } else {
678 ui.comboBox_CellTextField->setCurrentIndex(current_cell_field);
680 current_field = ui.comboBox_Field->currentIndex();
681 if(current_field > 0) {
682 double range[2];
683 m_SurfaceFilter->GetOutput()->GetPointData()->GetArray(current_field-1)->GetRange(range);
684 ui.doubleSpinBox_FieldMin->setRange(range[0],range[1]);
685 ui.doubleSpinBox_FieldMax->setRange(range[0],range[1]);
688 if(ui.comboBox_Field->currentIndex() > 0) {
689 m_SurfaceMapper->SetColorModeToMapScalars();
690 m_LookupTable->SetNumberOfColors(ui.spinBox_Color->value());
691 m_LookupTable->SetHueRange(ui.doubleSpinBox_HueMin->value(),ui.doubleSpinBox_HueMax->value());
692 m_LookupTable->Build();
693 m_SurfaceMapper->SetScalarModeToUsePointFieldData();
694 m_SurfaceMapper->ColorByArrayComponent(qPrintable(ui.comboBox_Field->currentText()),0);
695 m_SurfaceMapper->SetScalarRange(ui.doubleSpinBox_FieldMin->value(),ui.doubleSpinBox_FieldMax->value());
696 m_SurfaceMapper->ScalarVisibilityOn();
697 if(ui.checkBox_Legend->checkState()) {
698 m_LegendActor->SetVisibility(1);
699 } else {
700 m_LegendActor->SetVisibility(0);
702 } else {
703 m_SurfaceMapper->SetColorModeToDefault();
704 m_SurfaceMapper->ScalarVisibilityOff();
705 m_LegendActor->SetVisibility(0);
707 if (forced) {
708 m_BCodesFilter->Update();
710 if(ui.checkBox_ShowPickSphere->checkState()) {
711 if(m_UseVTKInteractor) {
712 if(ui.radioButton_CellPicker->isChecked()) {
713 getInteractor()->SetPicker(m_CellPicker);
714 vtkIdType id_cell = getPickedCell();
715 pickCell(id_cell);
716 } else {
717 getInteractor()->SetPicker(m_PointPicker);
718 vtkIdType id_node = getPickedPoint();
719 pickPoint(id_node);
721 } else {
722 if (ui.radioButton_CellPicker->isChecked()) {
723 pickCell(m_PickedCell);
724 } else {
725 pickPoint(m_PickedPoint);
729 m_SurfaceActor->SetVisibility(1);
730 m_SurfaceWireActor->SetVisibility(1);
731 } else {
732 m_SurfaceActor->SetVisibility(0);
733 m_SurfaceWireActor->SetVisibility(0);
737 void GuiMainWindow::updateVolumeActors(bool forced)
739 if (ui.checkBoxVolume->isChecked()) {
740 if (ui.checkBoxTetra->isChecked()) {
741 m_ExtrVol->SetTetrasOn();
742 if (ui.checkBoxClip->isChecked()) {
743 m_ExtrTetras->SetClippingOn();
744 } else {
745 m_ExtrTetras->SetClippingOff();
747 if (forced) {
748 m_TetraGeometry->Update();
750 m_TetraActor->SetVisibility(1);
751 } else {
752 m_ExtrVol->SetTetrasOff();
753 m_TetraActor->SetVisibility(0);
755 if (ui.checkBoxPyramid->isChecked()) {
756 m_ExtrVol->SetPyramidsOn();
757 if (ui.checkBoxClip->isChecked()) {
758 m_ExtrPyramids->SetClippingOn();
759 } else {
760 m_ExtrPyramids->SetClippingOff();
762 if (forced) {
763 m_PyramidGeometry->Update();
765 m_PyramidActor->SetVisibility(1);
766 } else {
767 m_ExtrVol->SetPyramidsOff();
768 m_PyramidActor->SetVisibility(0);
770 if (ui.checkBoxWedge->isChecked()) {
771 m_ExtrVol->SetWedgesOn();
772 if (ui.checkBoxClip->isChecked()) {
773 m_ExtrWedges->SetClippingOn();
774 } else {
775 m_ExtrWedges->SetClippingOff();
777 if (forced) {
778 m_WedgeGeometry->Update();
780 m_WedgeActor->SetVisibility(1);
781 } else {
782 m_ExtrVol->SetWedgesOff();
783 m_WedgeActor->SetVisibility(0);
785 if (ui.checkBoxHexa->isChecked()) {
786 m_ExtrVol->SetHexesOn();
787 if (ui.checkBoxClip->isChecked()) {
788 m_ExtrHexes->SetClippingOn();
789 } else {
790 m_ExtrHexes->SetClippingOff();
792 if (forced) {
793 m_HexaGeometry->Update();
795 m_HexaActor->SetVisibility(1);
796 } else {
797 m_ExtrVol->SetHexesOff();
798 m_HexaActor->SetVisibility(0);
800 if (ui.checkBoxPoly->isChecked()) {
801 m_ExtrVol->SetPolysOn();
802 if (ui.checkBoxClip->isChecked()) {
803 m_ExtrPolyhedra->SetClippingOn();
804 } else {
805 m_ExtrPolyhedra->SetClippingOff();
807 if (forced) {
808 m_PolyhedraGeometry->Update();
810 m_PolyhedraActor->SetVisibility(1);
811 } else {
812 m_ExtrVol->SetPolysOff();
813 m_PolyhedraActor->SetVisibility(0);
816 // wireframe
817 if (ui.checkBoxClip->isChecked()) {
818 m_ExtrVol->SetClippingOn();
819 } else {
820 m_ExtrVol->SetClippingOff();
822 if (forced) {
823 m_VolumeGeometry->Update();
825 m_VolumeWireActor->SetVisibility(1);
826 } else {
827 m_TetraActor->VisibilityOff();
828 m_PyramidActor->VisibilityOff();
829 m_WedgeActor->VisibilityOff();
830 m_HexaActor->VisibilityOff();
831 m_PolyhedraActor->VisibilityOff();
832 m_VolumeWireActor->VisibilityOff();
836 void GuiMainWindow::updateActors(bool forced)
838 // qDebug()<<"QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); called()";
839 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
841 //if (!tryLock()) return;
842 try {
843 m_Axes->SetInput(m_Grid);
844 updateSurfaceActors(forced);
845 updateVolumeActors(forced);
846 updateStatusBar();
847 } catch (Error err) {
848 err.display();
850 //unlock();
852 // qDebug()<<"QApplication::restoreOverrideCursor(); called()";
853 QApplication::restoreOverrideCursor();
858 void GuiMainWindow::forceUpdateActors()
860 // qDebug()<<"void GuiMainWindow::forceUpdateActors() START";
861 updateActors(true);
862 getRenderWindow()->Render();
863 // qDebug()<<"void GuiMainWindow::forceUpdateActors() END";
866 void GuiMainWindow::setPickMode(bool a_UseVTKInteractor,bool a_CellPickerMode)
868 m_UseVTKInteractor=a_UseVTKInteractor;
869 if (a_UseVTKInteractor) {
870 ui.checkBox_UseVTKInteractor->setCheckState(Qt::Checked);
871 } else {
872 ui.checkBox_UseVTKInteractor->setCheckState(Qt::Unchecked);
874 if (a_CellPickerMode) {
875 ui.radioButton_CellPicker->toggle();
876 } else {
877 ui.radioButton_PointPicker->toggle();
881 void GuiMainWindow::setUseVTKInteractor(int a_UseVTKInteractor)
883 m_UseVTKInteractor = a_UseVTKInteractor;
886 bool GuiMainWindow::pickPoint(vtkIdType id_node)
888 if ((id_node >= 0) && (id_node < m_Grid->GetNumberOfPoints())) {
889 vec3_t x(0,0,0);
890 m_Grid->GetPoints()->GetPoint(id_node, x.data());
891 m_PickSphere->SetCenter(x.data());
892 m_PickedPoint = id_node;
893 m_PickActor->GetProperty()->SetColor(0,0,1);
894 m_PickActor->VisibilityOn();
895 m_PickedObject = 1;
896 return(true);
897 } else {
898 m_PickActor->VisibilityOff();
899 m_PickedObject = 0;
900 return(false);
904 bool GuiMainWindow::pickCell(vtkIdType id_cell)
906 if ((id_cell >= 0) && (id_cell < m_Grid->GetNumberOfCells())) {
907 vtkIdType *pts, Npts;
908 m_Grid->GetCellPoints(id_cell, Npts, pts);
909 vec3_t x(0,0,0);
910 for (vtkIdType i = 0; i < Npts; ++i) {
911 vec3_t xp;
912 m_Grid->GetPoints()->GetPoint(pts[i], xp.data());
913 x += double(1)/Npts * xp;
915 m_PickSphere->SetCenter(x.data());
916 double R = 1e99;
917 for (vtkIdType i = 0; i < Npts; ++i) {
918 vec3_t xp;
919 m_Grid->GetPoints()->GetPoint(pts[i], xp.data());
920 R = min(R, 0.25*(xp-x).abs());
922 m_ReferenceSize = R; //Used for text annotations too!
923 m_PickSphere->SetRadius(R);
924 m_PickedCell = id_cell;
925 m_PickActor->GetProperty()->SetColor(1,0,0);
926 m_PickActor->VisibilityOn();
927 m_PickedObject = 2;
928 return(true);
929 } else {
930 m_PickActor->VisibilityOff();
931 m_PickedObject = 0;
932 return(false);
936 void GuiMainWindow::importSTL()
938 StlReader stl;
939 stl();
940 //FIXME: emits an error if no file is imported, so check if there is a valid file
941 updateBoundaryCodes(true);
942 updateActors();
943 updateStatusBar();
944 zoomAll();
947 void GuiMainWindow::importGmsh1Ascii()
949 GmshReader gmsh;
950 gmsh.setV1Ascii();
951 gmsh();
952 updateBoundaryCodes(true);
953 updateActors();
954 updateStatusBar();
955 zoomAll();
958 void GuiMainWindow::exportGmsh1Ascii()
960 GmshWriter gmsh;
961 gmsh.setV1Ascii();
962 gmsh();
965 void GuiMainWindow::importGmsh2Ascii()
967 GmshReader gmsh;
968 gmsh.setV2Ascii();
969 gmsh();
970 updateBoundaryCodes(true);
971 updateActors();
972 updateStatusBar();
973 zoomAll();
976 void GuiMainWindow::exportGmsh2Ascii()
978 GmshWriter gmsh;
979 gmsh.setV2Ascii();
980 gmsh();
983 void GuiMainWindow::exportNeutral()
985 NeutralWriter neutral;
986 neutral();
989 void GuiMainWindow::zoomAll()
991 getRenderer()->ResetCamera();
992 getRenderWindow()->Render();
995 void GuiMainWindow::zoomOnPickedObject()
997 if(m_PickActor->GetVisibility()) {
998 getRenderer()->ResetCamera(m_PickActor->GetBounds());
999 getRenderWindow()->Render();
1003 void GuiMainWindow::deselectAll()
1005 cout << "void GuiMainWindow::deselectAll()" << endl;
1006 m_PickActor->VisibilityOff();
1007 updateActors();
1010 ///\todo Should display a window
1011 void GuiMainWindow::info()
1013 ShowInfo info(ui.radioButton_CellPicker->isChecked(), m_PickedPoint, m_PickedCell);
1014 info();
1017 int GuiMainWindow::quickSave()
1019 ///\todo add RAM support
1020 if(m_undo_redo_enabled) {
1021 if(m_Grid->GetNumberOfPoints()>0)
1023 m_CurrentOperation++;
1024 QFileInfo fileinfo(m_CurrentFilename);
1025 QString l_filename = m_LogDir + fileinfo.completeBaseName() + "_" + QString("%1").arg(m_CurrentOperation);
1026 m_LastOperation=m_CurrentOperation;
1027 cout<<"Operation "<<m_CurrentOperation<<endl;
1028 saveAs(l_filename, false);
1029 if(m_CurrentOperation>0) ui.actionUndo->setEnabled(true);
1030 ui.actionRedo->setEnabled(false);
1032 else cout<<"No grid to save!"<<endl;
1033 return(m_CurrentOperation);
1035 return 0;
1038 void GuiMainWindow::quickLoad(int a_operation)
1040 ///\todo add RAM support
1041 if(m_undo_redo_enabled) {
1042 QFileInfo fileinfo(m_CurrentFilename);
1043 QString l_filename = m_LogDir + fileinfo.completeBaseName() + "_" + QString("%1").arg(a_operation) + ".egc";
1044 open(l_filename, false);
1048 void GuiMainWindow::undo()
1050 if(m_undo_redo_enabled) {
1051 cout << "Undoing operation " << m_CurrentOperation << endl;
1052 m_CurrentOperation--;
1053 quickLoad(m_CurrentOperation);
1054 ui.actionRedo->setEnabled(true);
1055 if(m_CurrentOperation<=0) ui.actionUndo->setEnabled(false);
1057 else {
1058 resetOperationCounter();
1059 QMessageBox::critical(this, "de-activated", "Undo is not doing anything at the moment!");
1063 void GuiMainWindow::redo()
1065 if(m_undo_redo_enabled) {
1066 m_CurrentOperation++;
1067 cout << "Redoing operation " << m_CurrentOperation << endl;
1068 quickLoad(m_CurrentOperation);
1069 ui.actionUndo->setEnabled(true);
1070 if(m_CurrentOperation>=m_LastOperation) ui.actionRedo->setEnabled(false);
1072 else {
1073 resetOperationCounter();
1074 QMessageBox::critical(this, "de-activated", "Redo is not doing anything at the moment!");
1078 void GuiMainWindow::resetOperationCounter()
1080 m_CurrentOperation=-1;
1081 m_LastOperation=m_CurrentOperation;
1082 ui.actionUndo->setEnabled(false);
1083 ui.actionRedo->setEnabled(false);
1086 QString GuiMainWindow::getXmlSection(QString name)
1088 return m_XmlHandler->getXmlSection(name);
1091 void GuiMainWindow::setXmlSection(QString name, QString contents)
1093 m_XmlHandler->setXmlSection(name,contents);
1096 void GuiMainWindow::openPhysicalBoundaryConditions()
1098 m_PhysicalBoundaryConditionsMap.clear();
1099 QString buffer = getXmlSection("engrid/physical");
1100 QTextStream f(&buffer, QIODevice::ReadOnly);
1101 while (!f.atEnd()) {
1102 QString name, type;
1103 int index;
1104 f >> index >> name >> type;
1105 if ((name != "") && (type != "")) {
1106 PhysicalBoundaryCondition PBC;
1107 PBC.setName(name);
1108 PBC.setIndex(index);
1109 PBC.setType(type);
1110 for (int i = 0; i < PBC.getNumVars(); ++i) {
1111 double v;
1112 f >> v;
1113 PBC.setValue(i, v);
1115 m_PhysicalBoundaryConditionsMap[name] = PBC;
1120 void GuiMainWindow::savePhysicalBoundaryConditions()
1122 QString buffer("");
1123 QTextStream f(&buffer, QIODevice::WriteOnly);
1124 f << "\n";
1125 foreach (PhysicalBoundaryCondition PBC, m_PhysicalBoundaryConditionsMap) {
1126 f << PBC.getIndex() << " " << PBC.getName() << " " << PBC.getType();
1127 for (int i = 0; i < PBC.getNumVars(); ++i) {
1128 f << " " << PBC.getVarValue(i);
1130 f << "\n";
1132 setXmlSection("engrid/physical", buffer);
1135 void GuiMainWindow::openBC()
1137 m_bcmap.clear();
1138 m_VolMap.clear();
1139 QString buffer = getXmlSection("engrid/bc");
1140 QTextStream f(&buffer, QIODevice::ReadOnly);
1141 while (!f.atEnd()) {
1142 QString name, type;
1143 int i;
1144 f >> i >> name >> type;
1145 if(name!="" && type!="") {
1146 if (i >= 0) {
1147 m_bcmap[i] = BoundaryCondition(name,type);
1148 } else {
1149 VolumeDefinition V(name, -i);
1150 QString text = type.replace(",", " ").replace(":", " ");
1151 QTextStream s(&text);
1152 while (!s.atEnd()) {
1153 QString bc_txt, sign_txt;
1154 s >> bc_txt >> sign_txt;
1155 V.addBC(bc_txt.toInt(), sign_txt.toInt());
1157 m_VolMap[name] = V;
1163 void GuiMainWindow::saveBC()
1165 QString buffer("");
1166 QTextStream f(&buffer, QIODevice::WriteOnly);
1167 f << "\n";
1168 foreach (int i, m_AllBoundaryCodes) {
1169 BoundaryCondition bc = m_bcmap[i];
1170 f << i << " " << bc.getName() << " " << bc.getType() << "\n";
1172 foreach (VolumeDefinition V, m_VolMap) {
1173 QString dirs = "";
1174 bool first = true;
1175 foreach (int i, m_AllBoundaryCodes) {
1176 BoundaryCondition bc = m_bcmap[i];
1177 if (!first) {
1178 dirs += ",";
1179 } else {
1180 first = false;
1182 QString num;
1183 num.setNum(i);
1184 dirs += num + ":";
1185 num.setNum(V.getSign(i));
1186 dirs += num;
1188 f << "-" << V.getVC() << " " << V.getName() << " " << dirs << "\n";
1190 setXmlSection("engrid/bc", buffer);
1193 void GuiMainWindow::openGrid(QString file_name)
1195 file_name += ".vtu";
1196 EG_VTKSP(vtkXMLUnstructuredGridReader,vtu);
1197 vtu->SetFileName(qPrintable(file_name));
1198 vtu->Update();
1199 m_Grid->DeepCopy(vtu->GetOutput());
1200 if (m_Grid->GetPointData()->GetArray("node_meshdensity_current")) {
1201 m_Grid->GetPointData()->RemoveArray("node_meshdensity_current");
1203 if (m_Grid->GetCellData()->GetArray("cell_VA")) {
1204 m_Grid->GetCellData()->RemoveArray("cell_VA");
1206 createBasicFields(m_Grid, m_Grid->GetNumberOfCells(), m_Grid->GetNumberOfPoints());
1207 openBC();
1208 openPhysicalBoundaryConditions();
1209 updateBoundaryCodes(true);
1210 createIndices(m_Grid);
1211 updateActors();
1212 updateStatusBar();
1213 zoomAll();
1216 ///\todo I think this should also be a done by a subclass of IOOperation just like for import operations
1217 void GuiMainWindow::open()
1219 QFileDialog dialog(NULL, "open grid from file", getCwd(), "enGrid case files (*.egc *.EGC);; legacy grid files(*.vtu *.VTU)");
1220 QFileInfo file_info(m_CurrentFilename);
1221 dialog.selectFile(file_info.completeBaseName() + ".egc");
1222 if (dialog.exec()) {
1223 QStringList selected_files = dialog.selectedFiles();
1224 QString file_name = selected_files[0];
1225 if (!file_name.isNull()) {
1226 this->open(file_name);
1231 void GuiMainWindow::open(QString file_name, bool update_current_filename)
1233 cout << "Opening " << qPrintable(file_name) << endl;
1235 //QFileInfo file_info(file_name);
1236 bool no_case_file = false;
1237 QString file_extension = getExtension(file_name);
1238 QString grid_file_name = file_name;
1239 if (file_extension.toLower() == "vtu") {
1240 no_case_file = true;
1241 grid_file_name = stripFromExtension(file_name);
1243 if (!no_case_file) {
1244 if(!m_XmlHandler->openXml(file_name)) {
1245 QMessageBox::critical(this, tr("Open failed"), tr("Error reading enGrid case file:\n%1").arg(file_name));
1246 return;
1249 if(update_current_filename) {
1250 GuiMainWindow::setCwd(QFileInfo(file_name).absolutePath());
1252 resetSurfaceProjection();
1254 QFile geo_file(file_name + ".geo.vtu");
1255 if (geo_file.exists()) {
1256 openGrid(file_name + ".geo");
1257 storeSurfaceProjection(true);
1260 openGrid(grid_file_name);
1261 openBC();
1262 openPhysicalBoundaryConditions();
1263 // update current filename
1264 if(update_current_filename) m_CurrentFilename = stripFromExtension(file_name) + ".egc";
1265 setWindowTitle(m_CurrentFilename + " - enGrid - " + QString("%1").arg(m_CurrentOperation) );
1266 setUnsaved(false);
1268 if(update_current_filename) {
1269 this->addRecentFile(file_name,QDateTime::currentDateTime());
1270 m_qset.setValue("LatestFile",file_name);
1271 resetOperationCounter();
1272 quickSave();
1276 QString GuiMainWindow::saveAs(QString file_name, bool update_current_filename)
1278 QString buffer = m_XmlHandler->getBuffer(0);
1279 if(update_current_filename) {
1280 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1282 QFileInfo file_info(file_name);
1283 if (file_info.suffix().toLower() != "egc") {
1284 file_name += ".egc";
1286 if(update_current_filename) {
1287 GuiMainWindow::setCwd(file_info.absolutePath());
1288 m_CurrentFilename = file_name;
1290 if(!saveGrid(m_Grid, file_name)) {
1291 QMessageBox::critical(this, QObject::tr("Save failed"), QObject::tr("The grid could not be saved as:\n%1").arg(file_name));
1293 saveBC();
1294 savePhysicalBoundaryConditions();
1295 m_XmlHandler->saveXml(file_name);
1296 setWindowTitle(m_CurrentFilename + " - enGrid - " + QString("%1").arg(m_CurrentOperation) );
1297 setUnsaved(false);
1298 if(update_current_filename) {
1299 QApplication::restoreOverrideCursor();
1301 if(update_current_filename) {
1302 this->addRecentFile(file_name,QDateTime::currentDateTime());
1303 m_qset.setValue("LatestFile",file_name);
1305 return(file_name);
1308 void GuiMainWindow::save()
1310 if ( m_CurrentFilename == "untitled.egc" || m_UnSaved ) {
1312 //FIXME: This is more of a hack than a fix...
1313 if(GuiMainWindow::tryLock()) {
1314 GuiMainWindow::unlock(); //must unlock before continuing.
1315 saveAs();
1316 } else {
1317 cout <<endl
1318 << "WARNING: Please save the project before running the requested operation "
1319 "or after the current operation is complete."
1320 <<endl;
1322 } else {
1323 saveAs(m_CurrentFilename);
1327 void GuiMainWindow::saveAs()
1329 QApplication::restoreOverrideCursor();
1330 //saveGrid(m_Grid, m_CurrentFilename + ".geo");
1331 bool geo_file_exists = false;
1332 QString old_geo_file = m_CurrentFilename + ".geo.vtu";
1334 if (QFileInfo(old_geo_file).exists()) {
1335 geo_file_exists = true;
1338 QFileDialog dialog(NULL, "write case to file", getCwd(), "enGrid case files (*.egc)");
1339 QFileInfo file_info(m_CurrentFilename);
1340 dialog.selectFile(file_info.completeBaseName() + ".egc");
1341 dialog.setAcceptMode(QFileDialog::AcceptSave);
1342 dialog.setConfirmOverwrite(true);
1343 if (dialog.exec()) {
1344 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1345 QStringList selected_files = dialog.selectedFiles();
1346 QString file_name = selected_files[0];
1347 if (!file_name.isNull()) {
1348 QString new_geo_file = file_name + ".geo.vtu";
1350 QFile file(new_geo_file);
1351 file.remove();
1353 QFile geo_file(old_geo_file);
1354 geo_file.copy(new_geo_file);
1355 saveAs(file_name);
1356 //for the undo/redo operations
1357 resetOperationCounter();
1358 quickSave();
1361 QApplication::restoreOverrideCursor();
1364 void GuiMainWindow::updateStatusBar()
1366 QString num, txt = "enGrid is currently busy with an operation ...";
1367 if (!m_Busy) {
1368 txt = "";
1370 if (!tryLock()) {
1371 m_StatusLabel->setText(txt);
1372 ui.label_node_cell_info->setText(txt);
1373 return;
1375 vtkIdType Ncells = m_Grid->GetNumberOfCells();
1376 vtkIdType Nnodes = m_Grid->GetNumberOfPoints();
1377 vtkIdType Ntris = 0;
1378 vtkIdType Nquads = 0;
1379 vtkIdType Ntets = 0;
1380 vtkIdType Npyras = 0;
1381 vtkIdType Nprism = 0;
1382 vtkIdType Nhexas = 0;
1383 for (vtkIdType i = 0; i < Ncells; ++i) {
1384 int ct = m_Grid->GetCellType(i);
1385 if (ct == VTK_TRIANGLE) ++Ntris;
1386 else if (ct == VTK_QUAD) ++Nquads;
1387 else if (ct == VTK_TETRA) ++Ntets;
1388 else if (ct == VTK_WEDGE) ++Nprism;
1389 else if (ct == VTK_PYRAMID) ++Npyras;
1390 else if (ct == VTK_HEXAHEDRON) ++Nhexas;
1392 num.setNum(Ntets + Npyras + Nprism + Nhexas); txt += num + " volume cells(";
1393 num.setNum(Ntets); txt += num + " tetras, ";
1394 num.setNum(Npyras); txt += num + " pyramids, ";
1395 num.setNum(Nprism); txt += num + " prisms, ";
1396 num.setNum(Nhexas); txt += num + " hexas), ";
1397 num.setNum(Ntris + Nquads); txt += num + " surface cells(";
1398 num.setNum(Ntris); txt += num + " triangles, ";
1399 num.setNum(Nquads); txt += num + " quads), ";
1400 num.setNum(Nnodes); txt += num + " nodes";
1402 if(ui.radioButton_CellPicker->isChecked())
1404 QString pick_txt = ", picked cell: ";
1405 vtkIdType id_cell = m_PickedCell;
1406 if (id_cell < 0 || id_cell>=m_Grid->GetNumberOfCells()) {
1407 pick_txt += "no cell picked";
1408 } else {
1409 vtkIdType type_cell = m_Grid->GetCellType(id_cell);
1410 if (type_cell == VTK_TRIANGLE) pick_txt += "tri";
1411 else if (type_cell == VTK_QUAD) pick_txt += "qua";
1412 else if (type_cell == VTK_TETRA) pick_txt += "tet";
1413 else if (type_cell == VTK_PYRAMID) pick_txt += "pyr";
1414 else if (type_cell == VTK_WEDGE) pick_txt += "pri";
1415 else if (type_cell == VTK_HEXAHEDRON) pick_txt += "hex";
1416 vtkIdType N_pts, *pts;
1417 m_Grid->GetCellPoints(id_cell, N_pts, pts);
1418 pick_txt += " [";
1419 for (int i_pts = 0; i_pts < N_pts; ++i_pts) {
1420 QString num;
1421 num.setNum(pts[i_pts]);
1422 pick_txt += num;
1423 if (i_pts < N_pts-1) {
1424 pick_txt += ",";
1427 pick_txt += "]";
1428 QString tmp;
1429 EG_VTKDCC(vtkIntArray, cell_code, m_Grid, "cell_code");
1430 tmp.setNum(cell_code->GetValue(id_cell));
1431 pick_txt += " code=" + tmp;
1432 tmp.setNum(id_cell);
1433 pick_txt += " id=" + tmp;
1435 txt += pick_txt;
1437 else
1439 QString pick_txt = ", picked node: ";
1440 vtkIdType id_node = m_PickedPoint;
1441 if (id_node < 0) {
1442 pick_txt += "no node picked";
1443 } else {
1445 vec3_t x;
1446 m_Grid->GetPoints()->GetPoint(id_node,x.data());
1447 pick_txt += " [";
1448 for (int i = 0; i < 3; i++) {
1449 QString num;
1450 num.setNum(x[i]);
1451 pick_txt += num;
1452 if (i < 2) {
1453 pick_txt += ",";
1456 pick_txt += "]";
1458 QString tmp;
1459 EG_VTKDCN(vtkDoubleArray, characteristic_length_desired, m_Grid, "node_meshdensity_desired");
1460 tmp.setNum(characteristic_length_desired->GetValue(id_node));
1461 pick_txt += " wanted density=" + tmp;
1462 //EG_VTKDCN(vtkDoubleArray, node_meshdensity_current, m_Grid, "node_meshdensity_current");
1463 //tmp.setNum(node_meshdensity_current->GetValue(id_node));
1464 //pick_txt += " current density=" + tmp;
1465 EG_VTKDCN(vtkIntArray, node_specified_density, m_Grid, "node_specified_density");
1466 tmp.setNum(node_specified_density->GetValue(id_node));
1467 pick_txt += " node_specified_density=" + tmp;
1468 EG_VTKDCN(vtkCharArray, node_type, m_Grid, "node_type");
1469 pick_txt += " type=" + QString(VertexType2Str( node_type->GetValue(id_node)));
1470 tmp.setNum(id_node);
1471 pick_txt += " id_node=" + tmp;
1474 txt += pick_txt;
1477 m_StatusLabel->setText(txt);
1478 ui.label_node_cell_info->setText(txt);
1479 unlock();
1482 void GuiMainWindow::selectBoundaryCodes()
1484 GuiSelectBoundaryCodes bcodes;
1485 bcodes.setDisplayBoundaryCodes(m_DisplayBoundaryCodes);
1486 bcodes.setBoundaryCodes(m_AllBoundaryCodes);
1487 bcodes();
1488 bcodes.getThread().wait();
1489 bcodes.getSelectedBoundaryCodes(m_DisplayBoundaryCodes);
1490 m_BCodesFilter->SetBoundaryCodes(m_DisplayBoundaryCodes);
1491 updateActors();
1494 void GuiMainWindow::updateBoundaryCodes(bool all_on)
1496 try {
1497 m_AllBoundaryCodes.clear();
1498 EG_VTKDCC(vtkIntArray, cell_code, m_Grid, "cell_code");
1499 for (vtkIdType i = 0; i < m_Grid->GetNumberOfCells(); ++i) {
1500 int ct = m_Grid->GetCellType(i);
1501 if ((ct == VTK_TRIANGLE) || (ct == VTK_QUAD)) {
1502 m_AllBoundaryCodes.insert(cell_code->GetValue(i));
1505 if (all_on) {
1506 m_DisplayBoundaryCodes.clear();
1507 foreach (int bc, m_AllBoundaryCodes) {
1508 m_DisplayBoundaryCodes.insert(bc);
1510 } else {
1511 QSet<int> dbcs;
1512 foreach (int bc, m_DisplayBoundaryCodes) {
1513 if (m_AllBoundaryCodes.contains(bc)) {
1514 dbcs.insert(bc);
1517 m_DisplayBoundaryCodes.clear();
1518 foreach (int bc, m_AllBoundaryCodes) {
1519 if (dbcs.contains(bc)) {
1520 m_DisplayBoundaryCodes.insert(bc);
1524 m_BCodesFilter->SetBoundaryCodes(m_DisplayBoundaryCodes);
1525 } catch (Error err) {
1526 err.display();
1530 void GuiMainWindow::normalExtrusion()
1532 GuiNormalExtrusion extr;
1533 extr();
1534 updateBoundaryCodes(false);
1535 updateActors();
1538 void GuiMainWindow::setAxesVisibility()
1540 if (ui.actionViewAxes->isChecked()) {
1541 m_Axes->VisibilityOn();
1542 } else {
1543 m_Axes->VisibilityOff();
1545 getRenderWindow()->Render();
1548 void GuiMainWindow::setViewingMode()
1550 if (ui.actionViewOrthogonal->isChecked()) getRenderer()->GetActiveCamera()->ParallelProjectionOn();
1551 else getRenderer()->GetActiveCamera()->ParallelProjectionOff();
1552 getRenderWindow()->Render();
1555 void GuiMainWindow::viewNodeIDs()
1557 int N = m_Grid->GetNumberOfPoints();
1558 cout<<"N="<<N<<endl;
1559 if (ui.actionViewNodeIDs->isChecked()) {
1560 cout<<"Activating node ID view"<<endl;
1561 m_NodeTextVectorText.resize(N);
1562 m_NodeTextPolyDataMapper.resize(N);
1563 m_NodeTextFollower.resize(N);
1564 for(int i = 0; i < N; ++i){
1565 m_NodeTextVectorText[i]=vtkVectorText::New();
1566 QString tmp;
1567 tmp.setNum(i);
1568 m_NodeTextVectorText[i]->SetText(qPrintable(tmp));
1569 m_NodeTextPolyDataMapper[i]=vtkPolyDataMapper::New();
1570 m_NodeTextPolyDataMapper[i]->SetInputConnection(m_NodeTextVectorText[i]->GetOutputPort());
1571 m_NodeTextFollower[i]=vtkFollower::New();
1572 m_NodeTextFollower[i]->SetMapper(m_NodeTextPolyDataMapper[i]);
1573 m_NodeTextFollower[i]->SetScale(m_ReferenceSize, m_ReferenceSize, m_ReferenceSize);
1574 vec3_t M;
1575 m_Grid->GetPoint(i, M.data());
1576 vec3_t tmp_M = M;
1577 vec3_t OffSet = m_ReferenceSize*tmp_M.normalise();
1578 M = M + OffSet;
1579 m_NodeTextFollower[i]->AddPosition(M[0], M[1], M[2]);
1580 m_NodeTextFollower[i]->SetCamera(getRenderer()->GetActiveCamera());
1581 m_NodeTextFollower[i]->GetProperty()->SetColor(0,0,1);
1582 getRenderer()->AddActor(m_NodeTextFollower[i]);
1585 else {
1586 cout<<"Deactivating node ID view"<<endl;
1587 for(unsigned int i = 0; i < m_NodeTextFollower.size();i++){
1588 getRenderer()->RemoveActor(m_NodeTextFollower[i]);
1589 m_NodeTextFollower[i]->Delete();
1590 m_NodeTextPolyDataMapper[i]->Delete();
1591 m_NodeTextVectorText[i]->Delete();
1593 m_NodeTextFollower.clear();
1594 m_NodeTextPolyDataMapper.clear();
1595 m_NodeTextVectorText.clear();
1598 getRenderWindow()->Render();
1601 void GuiMainWindow::viewCellIDs()
1603 vtkIdType N = m_Grid->GetNumberOfCells();
1604 cout<<"N="<<N<<endl;
1605 if (ui.actionViewCellIDs->isChecked()) {
1606 cout<<"Activating cell ID view"<<endl;
1607 m_CellTextVectorText.resize(N);
1608 m_CellTextPolyDataMapper.resize(N);
1609 m_CellTextFollower.resize(N);
1610 for (vtkIdType id_cell = 0; id_cell < N; ++id_cell){
1611 m_CellTextVectorText[id_cell] = vtkVectorText::New();
1613 QString tmp;
1615 if(ui.comboBox_CellTextField->currentIndex()==0) {
1616 tmp.setNum(id_cell);
1617 } else if (ui.comboBox_CellTextField->currentIndex()>0) {
1618 EG_VTKDCC(vtkIntArray, current_cell_field, m_Grid, qPrintable(ui.comboBox_CellTextField->currentText()));
1619 tmp.setNum(current_cell_field->GetValue(id_cell));
1621 else EG_BUG;
1623 m_CellTextVectorText[id_cell]->SetText(qPrintable(tmp));
1624 m_CellTextPolyDataMapper[id_cell]=vtkPolyDataMapper::New();
1625 m_CellTextPolyDataMapper[id_cell]->SetInputConnection(m_CellTextVectorText[id_cell]->GetOutputPort());
1626 m_CellTextFollower[id_cell]=vtkFollower::New();
1627 m_CellTextFollower[id_cell]->SetMapper(m_CellTextPolyDataMapper[id_cell]);
1628 m_CellTextFollower[id_cell]->SetScale(m_ReferenceSize, m_ReferenceSize, m_ReferenceSize);
1629 vtkIdType N_pts,*pts;
1630 m_Grid->GetCellPoints(id_cell,N_pts,pts);
1631 vec3_t Center(0,0,0);
1632 for (int p = 0; p < N_pts; ++p) {
1633 vec3_t M;
1634 m_Grid->GetPoint(pts[p],M.data());
1635 Center+=M.data();
1637 vec3_t OffSet = m_ReferenceSize*triNormal(m_Grid, pts[0], pts[1], pts[2]).normalise();
1638 Center = 1.0/(double)N_pts*Center+OffSet;
1639 m_CellTextFollower[id_cell]->AddPosition(Center[0], Center[1], Center[2]);
1640 m_CellTextFollower[id_cell]->SetCamera(getRenderer()->GetActiveCamera());
1641 m_CellTextFollower[id_cell]->GetProperty()->SetColor(1, 0, 0);
1642 getRenderer()->AddActor(m_CellTextFollower[id_cell]);
1644 } else {
1645 cout<<"Deactivating cell ID view"<<endl;
1646 for (vtkIdType id_cell = 0; id_cell < (vtkIdType) m_CellTextFollower.size(); ++id_cell) {
1647 getRenderer()->RemoveActor(m_CellTextFollower[id_cell]);
1648 m_CellTextFollower[id_cell]->Delete();
1649 m_CellTextPolyDataMapper[id_cell]->Delete();
1650 m_CellTextVectorText[id_cell]->Delete();
1652 m_CellTextFollower.clear();
1653 m_CellTextPolyDataMapper.clear();
1654 m_CellTextVectorText.clear();
1657 getRenderWindow()->Render();
1660 void GuiMainWindow::pickCallBack
1662 vtkObject *caller,
1663 unsigned long int eid,
1664 void *clientdata,
1665 void *calldata
1668 caller = caller;
1669 eid = eid;
1670 clientdata = clientdata;
1671 calldata = calldata;
1672 THIS->updateActors();
1673 THIS->updateStatusBar();
1676 vtkIdType GuiMainWindow::getPickedCell()
1678 if(!ui.radioButton_CellPicker->isChecked()) return(-1);
1680 vtkIdType picked_cell = -1;
1681 if (m_Grid->GetNumberOfCells() > 0) {
1682 m_BCodesFilter->Update();
1683 if (m_BCodesFilter->GetOutput()->GetNumberOfCells() > 0) {
1684 EG_VTKDCC(vtkLongArray_t, cell_index, m_BCodesFilter->GetOutput(), "cell_index");
1685 if (m_UseVTKInteractor) {
1686 picked_cell = cell_index->GetValue(m_CellPicker->GetCellId());
1687 } else {
1688 picked_cell = m_PickedCell;
1692 return picked_cell;
1695 vtkIdType GuiMainWindow::getPickedPoint()
1697 if(ui.radioButton_CellPicker->isChecked()) return(-1);
1699 vtkIdType picked_point = -1;
1700 if (m_Grid->GetNumberOfCells() > 0) {
1701 m_BCodesFilter->Update();
1702 if (m_BCodesFilter->GetOutput()->GetNumberOfCells() > 0) {
1703 EG_VTKDCN(vtkLongArray_t, node_index, m_BCodesFilter->GetOutput(), "node_index");
1704 if (m_UseVTKInteractor) {
1705 picked_point = node_index->GetValue(m_PointPicker->GetPointId());
1706 } else {
1707 picked_point = m_PickedPoint;
1711 return picked_point;
1714 void GuiMainWindow::changeSurfaceOrientation()
1716 for (vtkIdType cellId = 0; cellId < m_Grid->GetNumberOfCells(); ++cellId) {
1717 vtkIdType Npts, *pts;
1718 m_Grid->GetCellPoints(cellId, Npts, pts);
1719 QVector<vtkIdType> nodes(Npts);
1720 for (vtkIdType j = 0; j < Npts; ++j) nodes[j] = pts[j];
1721 for (vtkIdType j = 0; j < Npts; ++j) pts[Npts - j - 1] = nodes[j];
1723 updateActors();
1724 m_Grid->Modified();// to make sure VTK notices the changes and changes the cell colors
1725 //m_Renderer->GetRenderWindow()->Render();
1728 void GuiMainWindow::checkSurfaceOrientation()
1730 CorrectSurfaceOrientation corr_surf;
1731 vtkIdType picked_cell = getPickedCell();
1732 if (picked_cell >= 0) {
1733 corr_surf.setStart(picked_cell);
1735 corr_surf();
1736 updateActors();
1737 m_Grid->Modified();// to make sure VTK notices the changes and changes the cell colors
1738 //m_Renderer->GetRenderWindow()->Render();
1741 void GuiMainWindow::improveAspectRatio()
1743 GuiImproveAspectRatio impr_ar;
1744 impr_ar();
1745 updateActors();
1748 void GuiMainWindow::exportAsciiStl()
1750 StlWriter stl;
1751 stl.setFileTypeToASCII();
1752 stl();
1755 void GuiMainWindow::exportBinaryStl()
1757 StlWriter stl;
1758 stl.setFileTypeToBinary();
1759 stl();
1762 void GuiMainWindow::exportAsciiPly()
1764 PlyWriter ply;
1765 ply.setFileTypeToASCII();
1766 ply();
1769 void GuiMainWindow::exportBinaryPly()
1771 PlyWriter ply;
1772 ply.setFileTypeToBinary();
1773 ply();
1776 void GuiMainWindow::periodicUpdate()
1778 Operation::collectGarbage();
1779 updateStatusBar();
1782 void GuiMainWindow::viewRight()
1784 bool use_blender;
1785 getSet("General","use Blender definition for front, top, etc.", true, use_blender);
1786 getRenderer()->ResetCamera();
1787 double x[3];
1788 getRenderer()->GetActiveCamera()->GetFocalPoint(x);
1789 if (use_blender) {
1790 x[0] += 1;
1791 getRenderer()->GetActiveCamera()->SetPosition(x);
1792 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1793 getRenderer()->GetActiveCamera()->SetViewUp(0,0,1);
1794 } else {
1795 x[0] += 1;
1796 getRenderer()->GetActiveCamera()->SetPosition(x);
1797 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1798 getRenderer()->GetActiveCamera()->SetViewUp(0,1,0);
1800 getRenderer()->ResetCamera();
1801 getRenderWindow()->Render();
1804 void GuiMainWindow::viewLeft()
1806 bool use_blender;
1807 getSet("General","use Blender definition for front, top, etc.", true, use_blender);
1808 getRenderer()->ResetCamera();
1809 double x[3];
1810 getRenderer()->GetActiveCamera()->GetFocalPoint(x);
1811 if (use_blender) {
1812 x[0] -= 1;
1813 getRenderer()->GetActiveCamera()->SetPosition(x);
1814 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1815 getRenderer()->GetActiveCamera()->SetViewUp(0,0,1);
1816 } else {
1817 x[0] -= 1;
1818 getRenderer()->GetActiveCamera()->SetPosition(x);
1819 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1820 getRenderer()->GetActiveCamera()->SetViewUp(0,1,0);
1822 getRenderer()->ResetCamera();
1823 getRenderWindow()->Render();
1826 void GuiMainWindow::viewTop()
1828 bool use_blender;
1829 getSet("General","use Blender definition for front, top, etc.", true, use_blender);
1830 getRenderer()->ResetCamera();
1831 double x[3];
1832 getRenderer()->GetActiveCamera()->GetFocalPoint(x);
1833 if (use_blender) {
1834 x[2] += 1;
1835 getRenderer()->GetActiveCamera()->SetPosition(x);
1836 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1837 getRenderer()->GetActiveCamera()->SetViewUp(0,1,0);
1838 } else {
1839 x[1] += 1;
1840 getRenderer()->GetActiveCamera()->SetPosition(x);
1841 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1842 getRenderer()->GetActiveCamera()->SetViewUp(0,0,-1);
1844 getRenderer()->ResetCamera();
1845 getRenderWindow()->Render();
1848 void GuiMainWindow::viewBottom()
1850 bool use_blender;
1851 getSet("General","use Blender definition for front, top, etc.", true, use_blender);
1852 getRenderer()->ResetCamera();
1853 double x[3];
1854 getRenderer()->GetActiveCamera()->GetFocalPoint(x);
1855 if (use_blender) {
1856 x[2] -= 1;
1857 getRenderer()->GetActiveCamera()->SetPosition(x);
1858 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1859 getRenderer()->GetActiveCamera()->SetViewUp(0,-1,0);
1860 } else {
1861 x[1] -= 1;
1862 getRenderer()->GetActiveCamera()->SetPosition(x);
1863 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1864 getRenderer()->GetActiveCamera()->SetViewUp(0,0,-1);
1866 getRenderer()->ResetCamera();
1867 getRenderWindow()->Render();
1870 void GuiMainWindow::viewFront()
1872 bool use_blender;
1873 getSet("General","use Blender definition for front, top, etc.", true, use_blender);
1874 getRenderer()->ResetCamera();
1875 double x[3];
1876 getRenderer()->GetActiveCamera()->GetFocalPoint(x);
1877 if (use_blender) {
1878 x[1] -= 1;
1879 getRenderer()->GetActiveCamera()->SetPosition(x);
1880 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1881 getRenderer()->GetActiveCamera()->SetViewUp(0,0,1);
1882 } else {
1883 x[2] += 1;
1884 getRenderer()->GetActiveCamera()->SetPosition(x);
1885 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1886 getRenderer()->GetActiveCamera()->SetViewUp(0,1,0);
1888 getRenderer()->ResetCamera();
1889 getRenderWindow()->Render();
1892 void GuiMainWindow::viewBack()
1894 bool use_blender;
1895 getSet("General","use Blender definition for front, top, etc.", true, use_blender);
1896 getRenderer()->ResetCamera();
1897 double x[3];
1898 getRenderer()->GetActiveCamera()->GetFocalPoint(x);
1899 if (use_blender) {
1900 x[1] += 1;
1901 getRenderer()->GetActiveCamera()->SetPosition(x);
1902 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1903 getRenderer()->GetActiveCamera()->SetViewUp(0,0,1);
1904 } else {
1905 x[2] -= 1;
1906 getRenderer()->GetActiveCamera()->SetPosition(x);
1907 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1908 getRenderer()->GetActiveCamera()->SetViewUp(0,1,0);
1910 getRenderer()->ResetCamera();
1911 getRenderWindow()->Render();
1914 void GuiMainWindow::callFixSTL()
1916 FixSTL *fix;
1917 fix = new FixSTL();
1918 fix->setLockGui();
1919 (*fix)();
1920 updateBoundaryCodes(false);
1921 updateActors();
1924 void GuiMainWindow::callDeletePickedPoint()
1926 EG_STDINTERSLOT( DeletePickedPoint );
1929 void GuiMainWindow::editBoundaryConditions()
1931 GuiEditBoundaryConditions editbcs;
1932 editbcs.setBoundaryCodes(m_AllBoundaryCodes);
1933 editbcs.setMap(&m_bcmap);
1934 editbcs();
1937 void GuiMainWindow::configure()
1940 // Just to create initial entries in the settings file
1941 // so that the options menu isn't empty at first start.
1942 try {
1943 GridSmoother tmp01;
1944 GuiCreateBoundaryLayer tmp02;
1945 SurfaceProjection tmp03;
1946 SurfaceMesher tmp04;
1947 UpdateDesiredMeshDensity tmp05;
1948 InsertPoints tmp06;
1949 RemovePoints tmp07;
1950 LaplaceSmoother tmp08;
1951 SwapTriangles tmp09;
1952 OpenFOAMTools tmp10;
1953 BlenderReader tmp11;
1954 } catch (Error err) {
1955 err.display();
1958 GuiSettingsViewer settings(&m_qset);
1959 settings.CreateViewer();
1960 settings.exec();
1962 getSet("General","enable undo+redo",false,m_undo_redo_enabled);
1965 void GuiMainWindow::about()
1967 //Load the HTML code snippet with the list of contributions
1968 QFileInfo fileinfo;
1969 fileinfo.setFile(":/contributions.htm");
1970 QFile file(fileinfo.filePath());
1971 if (!file.exists()) {
1972 qDebug() << "ERROR: " << fileinfo.filePath() << " not found.";
1973 EG_BUG;
1975 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
1976 qDebug() << "ERROR: Failed to open file " << fileinfo.filePath();
1977 EG_BUG;
1979 QTextStream text_stream(&file);
1980 QString contributionsIncluded = text_stream.readAll();
1981 file.close();
1984 //Do the About box
1985 QMessageBox box(this);
1987 QString title="ENGRID";
1988 QString version = ENGRID_VERSION;
1989 version += " built on ";
1990 version += QString(__DATE__);
1991 version += " at ";
1992 version += QString(__TIME__);
1994 QString address = tr("ENGRID is being developed and maintained by:<br/>"
1995 "enGits GmbH<br/>"
1996 "Postfach 32<br/>"
1997 "79674 Todtnau<br/>"
1998 "Germany<br/>");
2000 QString mainurl="<a href=\"http://engits.eu/\">http://engits.eu</a>";
2001 QString mail="<a href=\"mailto:info@engits.com\">info@engits.com</a>";
2002 QString gnuurl="<a href=\"http://www.gnu.org/licenses\">http://www.gnu.org/licenses</a>";
2003 QString license=tr("ENGRID is licenced under the GPL version 3.<br/>"
2004 "(see ")+gnuurl+tr(" for details)<br/>");
2005 QString contributions=tr("Contributions:");
2007 box.setText(QString::fromLatin1("<center><img src=\":/icons/resources/icons/G.png\">"
2008 "<h3>%1</h3>"
2009 "<p>%2</p>"
2010 "<p>%3</p>"
2011 "<p>Homepage: %4</p>"
2012 "<p>E-mail: %5</p>"
2013 "<p>%6</p></center>"
2014 "<p>%7</p><blockquote>%8</blockquote>")
2015 .arg(title).arg(version).arg(address).arg(mainurl).arg(mail).arg(license)
2016 .arg(contributions).arg(contributionsIncluded));
2017 box.setWindowTitle(tr("about ENGRID"));
2018 box.setIcon(QMessageBox::NoIcon);
2019 box.exec();
2023 ///\todo Why not use bcs = m_AllBoundaryCodes; ?
2024 void GuiMainWindow::getAllBoundaryCodes(QVector<int> &bcs)
2026 m_AllBoundaryCodes;
2027 bcs.resize(m_AllBoundaryCodes.size());
2028 qCopy(m_AllBoundaryCodes.begin(), m_AllBoundaryCodes.end(), bcs.begin());
2029 qSort(bcs);
2032 QSet<int> GuiMainWindow::getAllBoundaryCodes()
2034 return m_AllBoundaryCodes;
2037 void GuiMainWindow::getDisplayBoundaryCodes(QSet<int> &bcs)
2039 bcs.clear();
2040 foreach (int bc, m_DisplayBoundaryCodes) {
2041 bcs.insert(bc);
2045 QList<VolumeDefinition> GuiMainWindow::getAllVols()
2047 QList<VolumeDefinition> vols;
2048 foreach(VolumeDefinition vol, m_VolMap) {
2049 vols.push_back(vol);
2051 return vols;
2054 void GuiMainWindow::setAllVols(QList<VolumeDefinition> vols)
2056 m_VolMap.clear();
2057 foreach (VolumeDefinition V, vols) {
2058 m_VolMap[V.getName()] = V;
2062 QList<PhysicalBoundaryCondition> GuiMainWindow::getAllPhysicalBoundaryConditions()
2064 QList<PhysicalBoundaryCondition> physical_boundary_conditions;
2065 foreach(PhysicalBoundaryCondition PBC, m_PhysicalBoundaryConditionsMap) {
2066 physical_boundary_conditions.push_back(PBC);
2068 return physical_boundary_conditions;
2071 void GuiMainWindow::setAllPhysicalBoundaryConditions(QList<PhysicalBoundaryCondition> physical_boundary_conditions)
2073 m_PhysicalBoundaryConditionsMap.clear();
2074 foreach (PhysicalBoundaryCondition PBC, physical_boundary_conditions) {
2075 m_PhysicalBoundaryConditionsMap[PBC.getName()] = PBC;
2079 void GuiMainWindow::setAllPhysicalBoundaryConditions(QMap<QString,PhysicalBoundaryCondition> physical_boundary_conditions) {
2080 m_PhysicalBoundaryConditionsMap = physical_boundary_conditions;
2083 void GuiMainWindow::createDefaultVol()
2085 QList<VolumeDefinition> vols = getAllVols();
2086 if (vols.size() == 0) {
2087 VolumeDefinition V("default", 1);
2088 QVector<int> bcs;
2089 getAllBoundaryCodes(bcs);
2090 foreach (int bc, bcs) {
2091 V.addBC(bc, 1);
2093 vols.append(V);
2094 setAllVols(vols);
2098 QString GuiMainWindow::getFilePath()
2100 QFileInfo fileinfo(m_CurrentFilename);
2101 return fileinfo.absolutePath()+"/";
2104 void GuiMainWindow::markOutputLine()
2106 cout << "\n****************************************\n";
2107 cout << qPrintable(QTime::currentTime().toString("hh:mm:ss"));
2108 cout << "\n****************************************\n" << endl;
2111 void GuiMainWindow::storeSurfaceProjection(bool nosave)
2113 try {
2114 resetSurfaceProjection();
2115 foreach (int bc, m_AllBoundaryCodes) {
2116 SurfaceProjection *proj = new SurfaceProjection();
2117 m_SurfProj[bc] = proj;
2118 QSet<int> bcs;
2119 bcs.insert(bc);
2120 QVector<vtkIdType> cls;
2121 getSurfaceCells(bcs, cls, m_Grid);
2122 proj->setBackgroundGrid(m_Grid, cls);
2124 if (!nosave) {
2125 save();
2126 saveGrid(m_Grid, m_CurrentFilename + ".geo");
2128 } catch (Error E) {
2129 E.display();
2133 void GuiMainWindow::resetSurfaceProjection()
2135 foreach (SurfaceProjection* proj, m_SurfProj) {
2136 delete proj;
2138 m_SurfProj.clear();
2139 try {
2140 EG_VTKDCN(vtkLongArray_t, pindex, m_Grid, "node_pindex");
2141 for (vtkIdType id_node = 0; id_node < m_Grid->GetNumberOfPoints(); ++id_node) {
2142 pindex->SetValue(id_node, -1);
2144 SurfaceProjection::resetPindex();
2145 } catch (Error) {
2149 SurfaceProjection* GuiMainWindow::getSurfProj(int bc)
2151 QString bc_txt;
2152 bc_txt.setNum(bc);
2153 if (!m_SurfProj.contains(bc)) {
2154 bc = 0;
2156 if (!m_SurfProj.contains(bc)) {
2157 EG_ERR_RETURN("No surface projection found for boundary code " + bc_txt);
2159 return m_SurfProj[bc];
2162 bool GuiMainWindow::checkSurfProj()
2164 bool ok = true;
2165 foreach (int bc, m_AllBoundaryCodes) {
2166 if (!m_SurfProj.contains(bc)) {
2167 ok = false;
2168 break;
2171 return ok;
2174 void GuiMainWindow::setSystemOutput()
2176 #if defined( __linux__ ) //for Linux
2178 if(m_SystemStdout != fileno(stdout))
2180 fflush(stdout);
2181 fgetpos(stdout, &m_LogFileStdout_pos); //store current position
2182 dup2(m_SystemStdout, fileno(stdout)); //reassign the original stdout to stdout
2183 clearerr(stdout);
2184 fsetpos(stdout, &m_SystemStdout_pos); /* for C9X */
2187 #elif defined( _WIN32 ) //for Windows
2189 freopen("CON","a",m_SystemStdout);
2191 #else
2192 #error "Please define the proper way to recover the stdout."
2193 #endif
2196 void GuiMainWindow::setLogFileOutput()
2198 #if defined( __linux__ ) //for Linux
2200 if(m_SystemStdout != fileno(stdout))
2202 fflush(stdout);
2203 fgetpos(stdout, &m_SystemStdout_pos); //store current position
2204 dup2(m_LogFileStdout, fileno(stdout)); //reassign the log_out to stdout
2205 clearerr(stdout);
2206 fsetpos(stdout, &m_LogFileStdout_pos); /* for C9X */
2209 #elif defined( _WIN32 ) //for Windows
2211 freopen(qPrintable(m_LogFileName),"a",m_LogFileStdout);
2213 #else
2214 #error "Please define the proper way to recover the stdout."
2215 #endif
2219 void GuiMainWindow::openRecent(QAction *action)
2221 qDebug()<<"GuiMainWindow::openRecent called";
2222 QString file_name = action->text().right(action->text().length()-23);
2223 this->open(file_name);
2226 void GuiMainWindow::readRecentFiles()
2228 m_RecentFiles.clear();
2229 this->recentFileMenu()->clear();
2230 QStringList file_names = m_qset.value("FileNames").toStringList();
2231 QStringList file_dates = m_qset.value("FileDates").toStringList();
2232 int N = min(10,m_qset.value("NumberOfFiles").toInt());
2233 // cout << "NumberOfFiles=" << N << endl;
2234 for (int i = 0; i < N; ++i) {
2235 QString new_file = file_names.at(i);
2236 QString date_text = file_dates.at(i);
2237 QDateTime date = QDateTime::fromString(date_text,"dd.MM.yyyy_hh:mm:ss");
2238 addRecentFile(new_file,date);
2242 void GuiMainWindow::writeRecentFiles()
2244 m_qset.setValue("NumberOfFiles",m_RecentFiles.size());
2245 QStringList file_names;
2246 QStringList file_dates;
2247 for (QMap<QString,QDateTime>::iterator i = m_RecentFiles.begin(); i != m_RecentFiles.end(); ++i) {
2248 QString file_name = i.key();
2249 QString date_text = i.value().toString("dd.MM.yyyy_hh:mm:ss");
2250 file_names.append(file_name);
2251 file_dates.append(date_text);
2253 m_qset.setValue("FileNames",file_names);
2254 m_qset.setValue("FileDates",file_dates);
2257 void GuiMainWindow::addRecentFile(QString file_name, QDateTime date)
2259 m_RecentFiles[file_name] = date;
2260 while (m_RecentFiles.size() > 10) {
2261 QMap<QString,QDateTime>::iterator i,j;
2262 QDateTime old = QDateTime::currentDateTime();
2263 for (i = m_RecentFiles.begin(); i != m_RecentFiles.end(); ++i) {
2264 if (i.value() <= old) {
2265 old = i.value();
2266 j = i;
2269 m_RecentFiles.erase(j);
2271 this->recentFileMenu()->clear();
2272 QMap<int,QString> menu_map;
2273 QDateTime now = QDateTime::currentDateTime();
2274 for (QMap<QString,QDateTime>::iterator i = m_RecentFiles.begin(); i != m_RecentFiles.end(); ++i) {
2275 QString action_text = i.value().toString("dd.MM.yyyy hh:mm:ss");
2276 action_text += " -> ";
2277 action_text += i.key();
2278 menu_map[i.value().secsTo(now)] = action_text;
2281 for (QMap<int,QString>::iterator i = menu_map.begin(); i != menu_map.end(); ++i) {
2282 QAction *action = new QAction(i.value(),this);
2283 this->recentFileMenu()->addAction(action);
2288 void GuiMainWindow::callInsertNewCell()
2290 bool ok1,ok2,ok3,ok4;
2291 vtkIdType pts[3];
2292 #if QT_VERSION < 0x040500
2293 pts[0] = QInputDialog::getInteger(this, tr("id_node1"),tr("id_node1:"), 0, 0, m_Grid->GetNumberOfPoints(), 1, &ok1);
2294 pts[1] = QInputDialog::getInteger(this, tr("id_node2"),tr("id_node2:"), 0, 0, m_Grid->GetNumberOfPoints(), 1, &ok2);
2295 pts[2] = QInputDialog::getInteger(this, tr("id_node3"),tr("id_node3:"), 0, 0, m_Grid->GetNumberOfPoints(), 1, &ok3);
2296 vtkIdType id_cell = QInputDialog::getInteger(this, tr("copy cell data from id_cell"),tr("copy cell data from id_cell:"), 0, 0, m_Grid->GetNumberOfCells(), 1, &ok4);
2297 #else
2298 pts[0] = QInputDialog::getInt(this, tr("id_node1"),tr("id_node1:"), 0, 0, m_Grid->GetNumberOfPoints(), 1, &ok1);
2299 pts[1] = QInputDialog::getInt(this, tr("id_node2"),tr("id_node2:"), 0, 0, m_Grid->GetNumberOfPoints(), 1, &ok2);
2300 pts[2] = QInputDialog::getInt(this, tr("id_node3"),tr("id_node3:"), 0, 0, m_Grid->GetNumberOfPoints(), 1, &ok3);
2301 vtkIdType id_cell = QInputDialog::getInt(this, tr("copy cell data from id_cell"),tr("copy cell data from id_cell:"), 0, 0, m_Grid->GetNumberOfCells(), 1, &ok4);
2302 #endif
2303 if (ok1 && ok2 && ok3 && ok4) {
2304 EG_VTKSP( vtkUnstructuredGrid, new_grid );
2305 allocateGrid( new_grid, m_Grid->GetNumberOfCells() + 1, m_Grid->GetNumberOfPoints() );
2306 makeCopyNoAlloc(m_Grid, new_grid);
2307 vtkIdType id_new_cell = new_grid->InsertNextCell(VTK_TRIANGLE, 3, pts);
2308 copyCellData(m_Grid, id_cell, new_grid, id_new_cell);
2309 makeCopy(new_grid, m_Grid);
2310 m_Grid->Modified();
2311 QMessageBox::information(NULL, "new cell", tr("The new cell has ID = %1").arg(id_new_cell));
2312 qDebug()<<tr("The new cell has ID = %1").arg(id_new_cell);
2316 void GuiMainWindow::callMergeNodes()
2318 bool ok1,ok2;
2319 #if QT_VERSION < 0x040500
2320 vtkIdType id_node1 = QInputDialog::getInteger(this, tr("id_node1"),tr("id_node1:"), 0, 0, m_Grid->GetNumberOfPoints(), 1, &ok1);
2321 vtkIdType id_node2 = QInputDialog::getInteger(this, tr("id_node2"),tr("id_node2:"), 0, 0, m_Grid->GetNumberOfPoints(), 1, &ok2);
2322 #else
2323 vtkIdType id_node1 = QInputDialog::getInt(this, tr("id_node1"),tr("id_node1:"), 0, 0, m_Grid->GetNumberOfPoints(), 1, &ok1);
2324 vtkIdType id_node2 = QInputDialog::getInt(this, tr("id_node2"),tr("id_node2:"), 0, 0, m_Grid->GetNumberOfPoints(), 1, &ok2);
2325 #endif
2326 if (ok1 && ok2) {
2327 EG_VTKSP( vtkUnstructuredGrid, new_grid );
2328 allocateGrid( new_grid, m_Grid->GetNumberOfCells(), m_Grid->GetNumberOfPoints() - 1 );
2330 QVector<vtkIdType> old2new_nodes(m_Grid->GetNumberOfPoints(), -1);
2331 QVector<vtkIdType> old2new_cells(m_Grid->GetNumberOfCells(), -1);
2333 vtkIdType id_new_node = 0;
2334 for (vtkIdType id_node = 0; id_node < m_Grid->GetNumberOfPoints(); ++id_node) {
2335 if(id_node!=id_node1 && id_node!=id_node2) {
2336 vec3_t x;
2337 m_Grid->GetPoints()->GetPoint(id_node, x.data());
2338 new_grid->GetPoints()->SetPoint(id_new_node, x.data());
2339 copyNodeData(m_Grid, id_node, new_grid, id_new_node);
2340 old2new_nodes[id_node] = id_new_node;
2341 id_new_node++;
2343 else if(id_node==id_node1) {
2344 vec3_t x1;
2345 m_Grid->GetPoints()->GetPoint(id_node1, x1.data());
2346 vec3_t x2;
2347 m_Grid->GetPoints()->GetPoint(id_node2, x2.data());
2348 vec3_t x = 0.5*(x1+x2);
2349 new_grid->GetPoints()->SetPoint(id_new_node, x.data());
2350 copyNodeData(m_Grid, id_node, new_grid, id_new_node);
2351 old2new_nodes[id_node1] = id_new_node;
2352 old2new_nodes[id_node2] = id_new_node;
2353 id_new_node++;
2355 else {
2359 for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
2360 vtkIdType N_pts, *pts;
2361 vtkIdType type_cell = m_Grid->GetCellType(id_cell);
2362 m_Grid->GetCellPoints(id_cell, N_pts, pts);
2363 QVector<vtkIdType> new_pts(N_pts);
2364 for (int i = 0; i < N_pts; ++i) {
2365 new_pts[i] = old2new_nodes[pts[i]];
2367 vtkIdType id_new_cell = new_grid->InsertNextCell(type_cell, N_pts, new_pts.data());
2368 copyCellData(m_Grid, id_cell, new_grid, id_new_cell);
2371 makeCopy(new_grid, m_Grid);
2372 m_Grid->Modified();
2373 qDebug()<<"The fusion is complete.";
2378 void GuiMainWindow::onEsc()
2380 setPickMode(true, true);
2381 pickCell(-1);
2382 m_CellPicker->Pick(-1e99,-1e99,0,m_Renderer);
2383 updateActors(true);
2384 updateStatusBar();
2387 void GuiMainWindow::resetProgress(QString info_text, int p_max)
2389 m_StatusInfoLabel->setText(info_text);
2390 m_StatusProgressBar->setMaximum(p_max);
2391 m_StatusProgressBar->setValue(0);
2392 QApplication::processEvents();
2395 void GuiMainWindow::setProgress(int p)
2397 m_StatusProgressBar->setValue(p);
2398 for (int i = 0; i < 3; ++i) {
2399 QApplication::processEvents();