1 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 // + This file is part of enGrid. +
5 // + Copyright 2008-2014 enGits GmbH +
7 // + enGrid is free software: you can redistribute it and/or modify +
8 // + it under the terms of the GNU General Public License as published by +
9 // + the Free Software Foundation, either version 3 of the License, or +
10 // + (at your option) any later version. +
12 // + enGrid is distributed in the hope that it will be useful, +
13 // + but WITHOUT ANY WARRANTY; without even the implied warranty of +
14 // + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +
15 // + GNU General Public License for more details. +
17 // + You should have received a copy of the GNU General Public License +
18 // + along with enGrid. If not, see <http://www.gnu.org/licenses/>. +
20 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
22 #include "reducedpolydatareader.h"
24 #include "guimainwindow.h"
29 #include <vtkPolyDataReader.h>
30 #include <vtkEgPolyDataToUnstructuredGridFilter.h>
31 #include <vtkDelaunay3D.h>
32 #include <vtkClipVolume.h>
33 #include <vtkContourFilter.h>
34 #include <vtkGeometryFilter.h>
35 #include <vtkDecimatePro.h>
36 #include <vtkSmoothPolyDataFilter.h>
38 ReducedPolyDataReader::ReducedPolyDataReader()
40 setFormat("legacy VTK files(*.vtk)");
45 void ReducedPolyDataReader::computeLevelSet(vtkUnstructuredGrid
* m_Grid
, vtkPolyData
* poly
)
49 QVector
<Triangle
> triangles(poly
->GetNumberOfPolys());
50 for (vtkIdType id_poly
= 0; id_poly
< poly
->GetNumberOfPolys(); ++id_poly
) {
51 EG_GET_CELL(id_poly
, poly
);
53 poly
->GetPoint(pts
[0], triangles
[id_poly
].a
.data());
54 poly
->GetPoint(pts
[1], triangles
[id_poly
].b
.data());
55 poly
->GetPoint(pts
[2], triangles
[id_poly
].c
.data());
56 triangles
[id_poly
].id_a
= pts
[0];
57 triangles
[id_poly
].id_b
= pts
[1];
58 triangles
[id_poly
].id_c
= pts
[2];
59 triangles
[id_poly
].g1
= triangles
[id_poly
].b
- triangles
[id_poly
].a
;
60 triangles
[id_poly
].g2
= triangles
[id_poly
].c
- triangles
[id_poly
].a
;
61 triangles
[id_poly
].g3
= triangles
[id_poly
].g1
.cross(triangles
[id_poly
].g2
);
62 triangles
[id_poly
].A
= 0.5*triangles
[id_poly
].g3
.abs();
63 triangles
[id_poly
].g3
.normalise();
64 triangles
[id_poly
].G
.column(0, triangles
[id_poly
].g1
);
65 triangles
[id_poly
].G
.column(1, triangles
[id_poly
].g2
);
66 triangles
[id_poly
].G
.column(2, triangles
[id_poly
].g3
);
67 triangles
[id_poly
].GI
= triangles
[id_poly
].G
.inverse();
68 triangles
[id_poly
].smallest_length
= (triangles
[id_poly
].b
- triangles
[id_poly
].a
).abs();
69 triangles
[id_poly
].smallest_length
= min(triangles
[id_poly
].smallest_length
, (triangles
[id_poly
].c
- triangles
[id_poly
].b
).abs());
70 triangles
[id_poly
].smallest_length
= min(triangles
[id_poly
].smallest_length
, (triangles
[id_poly
].a
- triangles
[id_poly
].c
).abs());
76 //vtkDoubleArray *scalars = vtkDoubleArray::New();
77 EG_VTKSP(vtkDoubleArray
, scalars
);
78 scalars
->SetNumberOfComponents(1);
79 scalars
->SetName("g");
80 scalars
->Allocate(m_Grid
->GetNumberOfPoints());
82 QProgressDialog
progress("Reducing triangulation", "Abort", 0, m_Grid
->GetNumberOfPoints());
83 progress
.setWindowModality(Qt::ApplicationModal
);
84 for (vtkIdType id_node
= 0; id_node
< m_Grid
->GetNumberOfPoints(); ++id_node
) {
85 progress
.setValue(id_node
);
86 QApplication::processEvents();
87 if (progress
.wasCanceled()) {
88 EG_ERR_RETURN("interrupted by user");
90 double g_levelset
= 1e99
;
92 m_Grid
->GetPoint(id_node
, xp
.data());
93 foreach (Triangle T
, triangles
) {
94 vec3_t
xi(1e99
,1e99
,1e99
);
96 double scal
= (xp
- T
.a
)*T
.g3
;
100 x2
= xp
- scal
*T
.g3
- T
.g3
;
103 x2
= xp
- scal
*T
.g3
+ T
.g3
;
107 bool intersects_face
= GeometryTools::intersectEdgeAndTriangle(T
.a
, T
.b
, T
.c
, x1
, x2
, xi
, ri
);
108 if (intersects_face
) {
112 double kab
= GeometryTools::intersection(T
.a
, T
.b
- T
.a
, xp
, T
.b
- T
.a
);
113 double kac
= GeometryTools::intersection(T
.a
, T
.c
- T
.a
, xp
, T
.c
- T
.a
);
114 double kbc
= GeometryTools::intersection(T
.b
, T
.c
- T
.b
, xp
, T
.c
- T
.b
);
115 double dab
= (T
.a
+ kab
*(T
.b
-T
.a
) - xp
).abs();
116 double dac
= (T
.a
+ kac
*(T
.c
-T
.a
) - xp
).abs();
117 double dbc
= (T
.b
+ kbc
*(T
.c
-T
.b
) - xp
).abs();
119 if ((kab
>= 0) && (kab
<= 1)) {
121 xi
= T
.a
+ kab
*(T
.b
-T
.a
);
126 if ((kac
>= 0) && (kac
<= 1)) {
128 xi
= T
.a
+ kac
*(T
.c
-T
.a
);
133 if ((kbc
>= 0) && (kbc
<= 1)) {
135 xi
= T
.b
+ kbc
*(T
.c
-T
.b
);
140 double da
= (T
.a
- xp
).abs();
141 double db
= (T
.b
- xp
).abs();
142 double dc
= (T
.c
- xp
).abs();
165 if (d
< fabs(g_levelset
)) {
173 scalars
->InsertTuple1(id_node
, g_levelset
);
175 progress
.setValue(m_Grid
->GetNumberOfPoints());
176 m_Grid
->GetPointData()->SetScalars(scalars
);
180 void ReducedPolyDataReader::operate()
183 QFileInfo
file_info(GuiMainWindow::pointer()->getFilename());
184 readInputFileName(file_info
.completeBaseName() + ".vtk");
186 EG_VTKSP(vtkPolyDataReader
, vtk
);
188 vtk
->SetFileName(qPrintable(getFileName()));
190 vtk
->GetOutput()->GetBounds(bounds
);
191 vec3_t
x1(bounds
[0], bounds
[2], bounds
[4]);
192 vec3_t
x2(bounds
[1], bounds
[3], bounds
[5]);
193 double m_MaxEdgeLength
= (x1
-x2
).abs()/20;
194 // double m_MinEdgeLength = (x1-x2).abs()/100;
195 vec3_t x12
= 0.5*(x1
+ x2
);
197 double d
= max(dx
[0], max(dx
[1], dx
[2]));
202 octree
.setBounds(x1
, x2
);
203 octree
.setSmoothTransitionOn();
205 EG_VTKSP(vtkSmoothPolyDataFilter
, smooth1
);
206 smooth1
->SetInputConnection(vtk
->GetOutputPort());
207 smooth1
->FeatureEdgeSmoothingOn();
208 smooth1
->BoundarySmoothingOn();
209 smooth1
->SetNumberOfIterations(200);
211 smooth1
->GetOutput()->BuildCells();
214 QVector<double> max_length(smooth->GetOutput()->GetNumberOfPoints(), m_MaxEdgeLength);
215 for (vtkIdType id_node = 0; id_node < smooth->GetOutput()->GetNumberOfPolys(); ++id_node) {
216 vtkIdType N_pts, *pts;
217 smooth1->GetOutput()->GetCellPoints(id_node, N_pts, pts);
219 for (int i = 0; i < N_pts; ++i) {
220 smooth1->GetOutput()->GetPoint(pts[i], x[i].data());
222 for (int i = 0; i < N_pts-1; ++i) {
227 double L = (x[i]-x[j]).abs();
228 max_length[pts[i]] = max(max_length[pts[i]], L);
229 max_length[pts[j]] = max(max_length[pts[j]], L);
234 EG_VTKSP(vtkDecimatePro
, decimate
);
235 decimate
->SetFeatureAngle(20.0);
236 decimate
->PreserveTopologyOn();
237 decimate
->SetInputConnection(smooth1
->GetOutputPort());
238 decimate
->SetTargetReduction(0.9);
239 EG_VTKSP(vtkSmoothPolyDataFilter
, smooth2
);
240 smooth2
->SetInputConnection(decimate
->GetOutputPort());
241 smooth2
->FeatureEdgeSmoothingOn();
242 smooth2
->BoundarySmoothingOn();
243 smooth2
->SetNumberOfIterations(200);
248 for (vtkIdType id_node
= 0; id_node
< smooth2
->GetOutput()->GetNumberOfPoints(); ++id_node
) {
250 smooth2
->GetOutput()->GetPoint(id_node
, x
.data());
251 int cell
= octree
.findCell(x
);
252 if (octree
.getDx(cell
) >m_MaxEdgeLength
) {
253 octree
.markToRefine(cell
);
256 N
= octree
.refineAll();
259 EG_VTKSP(vtkUnstructuredGrid
, oct_grid
);
260 octree
.toVtkGridHangingNodes(oct_grid
);
262 computeLevelSet(oct_grid
, smooth2
->GetOutput());
264 EG_VTKSP(vtkDelaunay3D
, delaunay
);
265 delaunay
->SetInputData(oct_grid
);
267 EG_VTKSP(vtkContourFilter
, contour
);
268 contour
->SetInputConnection(delaunay
->GetOutputPort());
269 contour
->GenerateValues(1, 0, 0);
270 contour
->SetInputData(oct_grid
);
274 EG_VTKSP(vtkXMLUnstructuredGridWriter
,vtu
);
275 QString file_name
= GuiMainWindow::pointer()->getCwd() + "/oct_grid.vtu";
276 vtu
->SetFileName(qPrintable(file_name
));
277 vtu
->SetDataModeToBinary();
278 vtu
->SetInputData(oct_grid
);
281 if (contour
->GetOutput()->GetNumberOfPolys() == 0) {
282 EG_ERR_RETURN("unable to extract reduced surface");
285 EG_VTKSP(vtkEgPolyDataToUnstructuredGridFilter
, poly2ug
);
286 poly2ug
->SetInputConnection(contour
->GetOutputPort());
289 makeCopy(poly2ug
->GetOutput(), m_Grid
);
290 createBasicFields(m_Grid
, m_Grid
->GetNumberOfCells(), m_Grid
->GetNumberOfPoints());
291 updateNodeIndex(m_Grid
);
292 updateCellIndex(m_Grid
);
293 EG_VTKDCC(vtkIntArray
, bc
, m_Grid
, "cell_code");
294 for (vtkIdType id_cell
= 0; id_cell
< m_Grid
->GetNumberOfCells(); ++id_cell
) {
295 bc
->SetValue(id_cell
, 0);
298 } catch (Error err
) {