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 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
24 #include "brlcadreader.h"
25 #include "vtkEgPolyDataToUnstructuredGridFilter.h"
26 #include "setboundarycode.h"
27 #include "facefinder.h"
28 #include "guimainwindow.h"
29 #include "guibrlcadimportdialogue.h"
30 #include "createcadtesselation.h"
31 #include "stlreader.h"
32 #include "brlcadinterface.h"
34 #include <vtkSTLReader.h>
36 BrlcadReader::BrlcadReader()
39 setFormat("BRL-CAD database files(*.g)");
43 void BrlcadReader::processStlFile(QString file_name
, bool append_to_list
)
45 vtkSTLReader
*stl
= vtkSTLReader::New();
47 stl
->SetFileName(file_name
.toAscii().data());
49 EG_VTKSP(vtkPolyData
, poly
);
50 poly
->DeepCopy(stl
->GetOutput());
53 for (vtkIdType cellId
= 0; cellId
< poly
->GetNumberOfCells(); ++cellId
) {
55 poly
->GetCellPoints(cellId
, Npts
, pts
);
56 for (int i
= 0; i
< Npts
; ++i
) {
58 poly
->GetPoints()->GetPoint(pts
[i
], x1
.data());
60 poly
->GetPoints()->GetPoint(pts
[0], x2
.data());
62 poly
->GetPoints()->GetPoint(pts
[i
+1], x2
.data());
64 L
= min(L
, (x1
-x2
).abs());
67 EG_VTKSP(vtkEgPolyDataToUnstructuredGridFilter
, poly2ugrid
);
68 poly2ugrid
->SetInput(poly
);
71 EG_VTKSP(vtkUnstructuredGrid
, grid
);
72 allocateGrid(grid
, poly2ugrid
->GetOutput()->GetNumberOfCells(), poly2ugrid
->GetOutput()->GetNumberOfPoints());
73 for (vtkIdType id_node
= 0; id_node
< poly2ugrid
->GetOutput()->GetNumberOfPoints(); ++id_node
) {
75 poly2ugrid
->GetOutput()->GetPoints()->GetPoint(id_node
, x
.data());
76 grid
->GetPoints()->SetPoint(id_node
, x
.data());
78 for (vtkIdType id_cell
= 0; id_cell
< poly2ugrid
->GetOutput()->GetNumberOfCells(); ++id_cell
) {
79 vtkIdType N_pts
, *pts
;
80 vtkIdType type_cell
= poly2ugrid
->GetOutput()->GetCellType(id_cell
);
81 poly2ugrid
->GetOutput()->GetCellPoints(id_cell
, N_pts
, pts
);
82 grid
->InsertNextCell(type_cell
, N_pts
, pts
);
85 EG_VTKDCC(vtkIntArray
, cell_code
, grid
, "cell_code");
86 EG_VTKDCC(vtkIntArray
, orgdir
, grid
, "cell_orgdir");
87 EG_VTKDCC(vtkIntArray
, voldir
, grid
, "cell_voldir");
88 EG_VTKDCC(vtkIntArray
, curdir
, grid
, "cell_curdir");
89 for (vtkIdType id_cell
= 0; id_cell
< grid
->GetNumberOfCells(); ++id_cell
) {
90 cell_code
->SetValue(id_cell
, 9999);
91 orgdir
->SetValue(id_cell
, 0);
92 voldir
->SetValue(id_cell
, 0);
93 curdir
->SetValue(id_cell
, 0);
97 SetBoundaryCode set_bc
;
99 set_bc
.setAllSurfaceCells();
103 vtkIdType id_start
= -1;
104 for (vtkIdType id_cell
= 0; id_cell
< grid
->GetNumberOfCells(); ++id_cell
) {
105 if (cell_code
->GetValue(id_cell
) == 9999) {
110 if (id_start
== -1) {
113 set_bc
.setFeatureAngle(20.0);
114 set_bc
.setBC(bc_max
);
115 set_bc
.setProcessAll(true);
116 set_bc
.setSelectAllVisible(false);
117 set_bc
.setOnlyPickedCell(false);
118 set_bc
.setOnlyPickedCellAndNeighbours(false);
119 set_bc
.setStart(id_start
);
124 cout
<< "file: " << qPrintable(file_name
) << endl
;
125 for (int bc
= 1; bc
< bc_max
; ++bc
) {
126 QList
<vtkIdType
> cells
;
127 for (vtkIdType id_cell
= 0; id_cell
< grid
->GetNumberOfCells(); ++id_cell
) {
128 if (cell_code
->GetValue(id_cell
) == bc
) {
129 cells
.append(id_cell
);
132 vtkUnstructuredGrid
*new_grid
= vtkUnstructuredGrid::New();
136 bc_txt
= bc_txt
.rightJustified(2, '0');
138 QFileInfo
file_info(file_name
);
139 m_BCNames
[new_grid
] = file_info
.baseName() + "." + bc_txt
;
140 cout
<< " " << qPrintable(file_info
.baseName() + "." + bc_txt
) << endl
;
141 makeCopy(grid
, new_grid
, cells
);
142 m_Grids
.append(new_grid
);
145 makeCopy(grid
, m_Grid
);
149 void BrlcadReader::findBoundaryCodes()
151 int num_grids
= m_Grids
.size();
152 QVector
<vtkUnstructuredGrid
*> grids(num_grids
);
153 qCopy(m_Grids
.begin(), m_Grids
.end(), grids
.begin());
154 QVector
<FaceFinder
> finders(num_grids
);
155 for (int i_grid
= 0; i_grid
< num_grids
; ++i_grid
) {
156 finders
[i_grid
].setGrid(grids
[i_grid
]);
158 EG_VTKDCC(vtkIntArray
, cell_code
, m_Grid
, "cell_code");
159 bool has_errors
= false;
160 QVector
<bool> bc_exists(num_grids
, false);
161 for (vtkIdType id_cell
= 0; id_cell
< m_Grid
->GetNumberOfCells(); ++id_cell
) {
164 vec3_t x1
= cellCentre(m_Grid
, id_cell
);
165 for (int i_grid
= 0; i_grid
< num_grids
; ++i_grid
) {
167 vtkIdType id_closest
= finders
[i_grid
].getClosestFace(x1
, L
);
168 vec3_t
x2(-999,-999,-999);
169 if (id_closest
!= -1) x2
= cellCentre(m_Grids
[i_grid
], id_closest
);
170 if (id_closest
!= -1) {
177 if (best_grid
== -1) {
179 cell_code
->SetValue(id_cell
, 9999);
181 bc_exists
[best_grid
] = true;
182 cell_code
->SetValue(id_cell
, best_grid
+ 1);
185 GuiMainWindow::pointer()->clearBCs();
187 QVector
<int> bc_map(num_grids
+1,9999);
188 m_BC2GridIndex
.clear();
189 for (int i_grid
= 0; i_grid
< num_grids
; ++i_grid
) {
190 if (bc_exists
[i_grid
]) {
191 bc_map
[i_grid
+1] = bc_max
;
192 GuiMainWindow::pointer()->addBC(bc_max
, BoundaryCondition(m_BCNames
[grids
[i_grid
]], "patch"));
193 m_BC2GridIndex
[bc_max
] = i_grid
;
197 for (vtkIdType id_cell
= 0; id_cell
< m_Grid
->GetNumberOfCells(); ++id_cell
) {
198 if (cell_code
->GetValue(id_cell
) != 9999) {
199 cell_code
->SetValue(id_cell
, bc_map
[cell_code
->GetValue(id_cell
)]);
203 GuiMainWindow::pointer()->addBC(9999, BoundaryCondition("error-faces", "patch"));
205 GuiMainWindow::pointer()->updateBoundaryCodes(true);
208 void BrlcadReader::createBackgroundGeometry()
210 // make a backup of the existing grid
211 EG_VTKSP(vtkUnstructuredGrid
, backup_grid
);
212 makeCopy(m_Grid
, backup_grid
);
214 QSet
<int> bcs
= GuiMainWindow::pointer()->getAllBoundaryCodes();
216 // count total number of nodes and faces for background geometry
219 foreach (int bc
, bcs
) {
220 int i_grid
= m_BC2GridIndex
[bc
];
221 num_nodes
+= m_Grids
[i_grid
]->GetNumberOfPoints();
222 num_faces
+= m_Grids
[i_grid
]->GetNumberOfCells();
224 allocateGrid(m_Grid
, num_faces
, num_nodes
);
225 EG_VTKDCC(vtkIntArray
, cell_code
, m_Grid
, "cell_code");
227 // copy STL grids into background grid
228 vtkIdType id_node_max
= 0;
229 foreach (int bc
, bcs
) {
230 int i_grid
= m_BC2GridIndex
[bc
];
233 QVector
<int> local2global(m_Grids
[i_grid
]->GetNumberOfPoints());
234 for (vtkIdType id_node
= 0; id_node
< m_Grids
[i_grid
]->GetNumberOfPoints(); ++id_node
) {
235 local2global
[id_node
] = id_node_max
;
237 m_Grids
[i_grid
]->GetPoint(id_node
, x
.data());
238 m_Grid
->GetPoints()->SetPoint(id_node_max
, x
.data());
243 for (vtkIdType id_face
= 0; id_face
< m_Grids
[i_grid
]->GetNumberOfCells(); ++id_face
) {
244 vtkIdType
*pts
, N_pts
;
245 m_Grids
[i_grid
]->GetCellPoints(id_face
, N_pts
, pts
);
246 QVector
<vtkIdType
> new_pts(N_pts
);
247 for (int i
= 0; i
< N_pts
; ++i
) {
248 new_pts
[i
] = local2global
[pts
[i
]];
250 vtkIdType id_new_face
= m_Grid
->InsertNextCell(m_Grids
[i_grid
]->GetCellType(id_face
), N_pts
, new_pts
.data());
251 cell_code
->SetValue(id_new_face
, bc
);
255 // store background grid for surface projection
256 GuiMainWindow::pointer()->storeCadInterfaces();
258 // restore the initial grid from the backup copy
259 makeCopy(backup_grid
, m_Grid
);
262 void BrlcadReader::operateOld()
264 readInputDirectory("Select BRL-CAD export directory");
266 QDir
dir(getFileName());
268 filters
<< "*.s.stl";
269 QStringList file_names
= dir
.entryList(filters
);
270 foreach (QString file_name
, file_names
) {
271 processStlFile(dir
.path() + "/"+ file_name
);
273 processStlFile(dir
.path() + "/volume.stl", false);
275 createBackgroundGeometry();
279 void BrlcadReader::operate()
282 QFileInfo
file_info(GuiMainWindow::pointer()->getFilename());
283 readInputFileName(file_info
.completeBaseName() + ".g");
285 GuiBrlCadImportDialogue dlg
;
286 dlg
.prepare(getFileName());
288 BrlCadInterface
* brlcad_interface
= new BrlCadInterface(getFileName(), dlg
.selectedObject());
289 if (dlg
.useStlFile()) {
291 stl
.setFileName(dlg
.stlFileName());
293 } else if (dlg
.hasSelectedObject()) {
294 CreateCadTesselation
tess(brlcad_interface
);
295 tess
.setScanMemory(dlg
.scanMemory());
296 tess
.setPreservationType(dlg
.preservationType());
297 tess
.setSmoothingIterations(dlg
.smoothingIterations());
298 tess
.setSmallestFeatureSize(dlg
.smallestFeatureSize());
299 tess
.setSmallestResolution(dlg
.smallestResolution());
300 tess
.setTargetReduction(dlg
.reduction());
303 GuiMainWindow::pointer()->setUniversalCadInterface(brlcad_interface
);
306 } catch (Error err
) {
311 #endif // BRLCAD_SUPPORT