2 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 // + This file is part of enGrid. +
6 // + Copyright 2008-2013 enGits GmbH +
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. +
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. +
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/>. +
21 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
24 #include "reducedpolydatareader.h"
25 #include "guimainwindow.h"
30 #include <vtkPolyDataReader.h>
31 #include <vtkEgPolyDataToUnstructuredGridFilter.h>
32 #include <vtkDelaunay3D.h>
33 #include <vtkClipVolume.h>
34 #include <vtkContourFilter.h>
35 #include <vtkGeometryFilter.h>
36 #include <vtkDecimatePro.h>
37 #include <vtkSmoothPolyDataFilter.h>
39 ReducedPolyDataReader::ReducedPolyDataReader()
41 setFormat("legacy VTK files(*.vtk)");
46 void ReducedPolyDataReader::computeLevelSet(vtkUnstructuredGrid
* m_Grid
, vtkPolyData
* poly
)
50 QVector
<Triangle
> triangles(poly
->GetNumberOfPolys());
51 for (vtkIdType id_poly
= 0; id_poly
< poly
->GetNumberOfPolys(); ++id_poly
) {
53 poly
->GetCellPoints(id_poly
, Npts
, pts
);
55 poly
->GetPoint(pts
[0], triangles
[id_poly
].a
.data());
56 poly
->GetPoint(pts
[1], triangles
[id_poly
].b
.data());
57 poly
->GetPoint(pts
[2], triangles
[id_poly
].c
.data());
58 triangles
[id_poly
].id_a
= pts
[0];
59 triangles
[id_poly
].id_b
= pts
[1];
60 triangles
[id_poly
].id_c
= pts
[2];
61 triangles
[id_poly
].g1
= triangles
[id_poly
].b
- triangles
[id_poly
].a
;
62 triangles
[id_poly
].g2
= triangles
[id_poly
].c
- triangles
[id_poly
].a
;
63 triangles
[id_poly
].g3
= triangles
[id_poly
].g1
.cross(triangles
[id_poly
].g2
);
64 triangles
[id_poly
].A
= 0.5*triangles
[id_poly
].g3
.abs();
65 triangles
[id_poly
].g3
.normalise();
66 triangles
[id_poly
].G
.column(0, triangles
[id_poly
].g1
);
67 triangles
[id_poly
].G
.column(1, triangles
[id_poly
].g2
);
68 triangles
[id_poly
].G
.column(2, triangles
[id_poly
].g3
);
69 triangles
[id_poly
].GI
= triangles
[id_poly
].G
.inverse();
70 triangles
[id_poly
].smallest_length
= (triangles
[id_poly
].b
- triangles
[id_poly
].a
).abs();
71 triangles
[id_poly
].smallest_length
= min(triangles
[id_poly
].smallest_length
, (triangles
[id_poly
].c
- triangles
[id_poly
].b
).abs());
72 triangles
[id_poly
].smallest_length
= min(triangles
[id_poly
].smallest_length
, (triangles
[id_poly
].a
- triangles
[id_poly
].c
).abs());
78 //vtkDoubleArray *scalars = vtkDoubleArray::New();
79 EG_VTKSP(vtkDoubleArray
, scalars
);
80 scalars
->SetNumberOfComponents(1);
81 scalars
->SetName("g");
82 scalars
->Allocate(m_Grid
->GetNumberOfPoints());
84 QProgressDialog
progress("Reducing triangulation", "Abort", 0, m_Grid
->GetNumberOfPoints());
85 progress
.setWindowModality(Qt::ApplicationModal
);
86 for (vtkIdType id_node
= 0; id_node
< m_Grid
->GetNumberOfPoints(); ++id_node
) {
87 progress
.setValue(id_node
);
88 QApplication::processEvents();
89 if (progress
.wasCanceled()) {
90 EG_ERR_RETURN("interrupted by user");
92 double g_levelset
= 1e99
;
94 m_Grid
->GetPoint(id_node
, xp
.data());
95 foreach (Triangle T
, triangles
) {
96 vec3_t
xi(1e99
,1e99
,1e99
);
98 double scal
= (xp
- T
.a
)*T
.g3
;
102 x2
= xp
- scal
*T
.g3
- T
.g3
;
105 x2
= xp
- scal
*T
.g3
+ T
.g3
;
109 bool intersects_face
= GeometryTools::intersectEdgeAndTriangle(T
.a
, T
.b
, T
.c
, x1
, x2
, xi
, ri
);
110 if (intersects_face
) {
114 double kab
= GeometryTools::intersection(T
.a
, T
.b
- T
.a
, xp
, T
.b
- T
.a
);
115 double kac
= GeometryTools::intersection(T
.a
, T
.c
- T
.a
, xp
, T
.c
- T
.a
);
116 double kbc
= GeometryTools::intersection(T
.b
, T
.c
- T
.b
, xp
, T
.c
- T
.b
);
117 double dab
= (T
.a
+ kab
*(T
.b
-T
.a
) - xp
).abs();
118 double dac
= (T
.a
+ kac
*(T
.c
-T
.a
) - xp
).abs();
119 double dbc
= (T
.b
+ kbc
*(T
.c
-T
.b
) - xp
).abs();
121 if ((kab
>= 0) && (kab
<= 1)) {
123 xi
= T
.a
+ kab
*(T
.b
-T
.a
);
128 if ((kac
>= 0) && (kac
<= 1)) {
130 xi
= T
.a
+ kac
*(T
.c
-T
.a
);
135 if ((kbc
>= 0) && (kbc
<= 1)) {
137 xi
= T
.b
+ kbc
*(T
.c
-T
.b
);
142 double da
= (T
.a
- xp
).abs();
143 double db
= (T
.b
- xp
).abs();
144 double dc
= (T
.c
- xp
).abs();
167 if (d
< fabs(g_levelset
)) {
175 scalars
->InsertTuple1(id_node
, g_levelset
);
177 progress
.setValue(m_Grid
->GetNumberOfPoints());
178 m_Grid
->GetPointData()->SetScalars(scalars
);
182 void ReducedPolyDataReader::operate()
185 QFileInfo
file_info(GuiMainWindow::pointer()->getFilename());
186 readInputFileName(file_info
.completeBaseName() + ".vtk");
188 EG_VTKSP(vtkPolyDataReader
, vtk
);
190 vtk
->SetFileName(qPrintable(getFileName()));
192 vtk
->GetOutput()->GetBounds(bounds
);
193 vec3_t
x1(bounds
[0], bounds
[2], bounds
[4]);
194 vec3_t
x2(bounds
[1], bounds
[3], bounds
[5]);
195 double m_MaxEdgeLength
= (x1
-x2
).abs()/20;
196 // double m_MinEdgeLength = (x1-x2).abs()/100;
197 vec3_t x12
= 0.5*(x1
+ x2
);
199 double d
= max(dx
[0], max(dx
[1], dx
[2]));
204 octree
.setBounds(x1
, x2
);
205 octree
.setSmoothTransitionOn();
207 EG_VTKSP(vtkSmoothPolyDataFilter
, smooth1
);
208 smooth1
->SetInput(vtk
->GetOutput());
209 smooth1
->FeatureEdgeSmoothingOn();
210 smooth1
->BoundarySmoothingOn();
211 smooth1
->SetNumberOfIterations(200);
213 smooth1
->GetOutput()->BuildCells();
216 QVector<double> max_length(smooth->GetOutput()->GetNumberOfPoints(), m_MaxEdgeLength);
217 for (vtkIdType id_node = 0; id_node < smooth->GetOutput()->GetNumberOfPolys(); ++id_node) {
218 vtkIdType N_pts, *pts;
219 smooth1->GetOutput()->GetCellPoints(id_node, N_pts, pts);
221 for (int i = 0; i < N_pts; ++i) {
222 smooth1->GetOutput()->GetPoint(pts[i], x[i].data());
224 for (int i = 0; i < N_pts-1; ++i) {
229 double L = (x[i]-x[j]).abs();
230 max_length[pts[i]] = max(max_length[pts[i]], L);
231 max_length[pts[j]] = max(max_length[pts[j]], L);
236 EG_VTKSP(vtkDecimatePro
, decimate
);
237 decimate
->SetFeatureAngle(20.0);
238 decimate
->PreserveTopologyOn();
239 decimate
->SetInput(smooth1
->GetOutput());
240 decimate
->SetTargetReduction(0.9);
241 EG_VTKSP(vtkSmoothPolyDataFilter
, smooth2
);
242 smooth2
->SetInput(decimate
->GetOutput());
243 smooth2
->FeatureEdgeSmoothingOn();
244 smooth2
->BoundarySmoothingOn();
245 smooth2
->SetNumberOfIterations(200);
250 for (vtkIdType id_node
= 0; id_node
< smooth2
->GetOutput()->GetNumberOfPoints(); ++id_node
) {
252 smooth2
->GetOutput()->GetPoint(id_node
, x
.data());
253 int cell
= octree
.findCell(x
);
254 if (octree
.getDx(cell
) >m_MaxEdgeLength
) {
255 octree
.markToRefine(cell
);
258 N
= octree
.refineAll();
261 EG_VTKSP(vtkUnstructuredGrid
, oct_grid
);
262 octree
.toVtkGrid(oct_grid
, true, false);
264 computeLevelSet(oct_grid
, smooth2
->GetOutput());
266 EG_VTKSP(vtkDelaunay3D
, delaunay
);
267 delaunay
->SetInput(oct_grid
);
269 EG_VTKSP(vtkContourFilter
, contour
);
270 contour
->SetInput(delaunay
->GetOutput());
271 contour
->GenerateValues(1, 0, 0);
272 contour
->SetInput(oct_grid
);
276 EG_VTKSP(vtkXMLUnstructuredGridWriter
,vtu
);
277 QString file_name
= GuiMainWindow::pointer()->getCwd() + "/oct_grid.vtu";
278 vtu
->SetFileName(qPrintable(file_name
));
279 vtu
->SetDataModeToBinary();
280 vtu
->SetInput(oct_grid
);
283 if (contour
->GetOutput()->GetNumberOfPolys() == 0) {
284 EG_ERR_RETURN("unable to extract reduced surface");
287 EG_VTKSP(vtkEgPolyDataToUnstructuredGridFilter
, poly2ug
);
288 poly2ug
->SetInput(contour
->GetOutput());
291 makeCopy(poly2ug
->GetOutput(), m_Grid
);
292 createBasicFields(m_Grid
, m_Grid
->GetNumberOfCells(), m_Grid
->GetNumberOfPoints());
293 UpdateNodeIndex(m_Grid
);
294 UpdateCellIndex(m_Grid
);
295 EG_VTKDCC(vtkIntArray
, bc
, m_Grid
, "cell_code");
296 for (vtkIdType id_cell
= 0; id_cell
< m_Grid
->GetNumberOfCells(); ++id_cell
) {
297 bc
->SetValue(id_cell
, 0);
300 } catch (Error err
) {