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 "blenderreader.h"
23 #include "guimainwindow.h"
24 #include "pointfinder.h"
26 BlenderReader::BlenderReader()
28 setFormat("Blender/Engrid files(*.begc *.BEGC)");
29 getSet("General", "tolerance for importing geometries (% of smallest edge length)", 0.1, m_RelativeTolerance
);
30 m_RelativeTolerance
*= 1e-2;
34 void BlenderReader::operate()
37 QFileInfo
file_info(GuiMainWindow::pointer()->getFilename());
38 readInputFileName(file_info
.completeBaseName() + ".begc", false);
40 // read raw data from exported file
41 QFile
file(getFileName());
42 file
.open(QIODevice::ReadOnly
| QIODevice::Text
);
45 QList
<QVector
<int> > rfaces
;
48 QVector
<QString
> part_name(num_parts
);
49 for (int i_part
= 0; i_part
< num_parts
; ++i_part
) {
50 f
>> part_name
[i_part
];
52 QVector
<QString
> sorted_part_name
= part_name
;
53 qSort(sorted_part_name
);
54 QVector
<int> part_bc(part_name
.size());
55 for (int i_part
= 0; i_part
< num_parts
; ++i_part
) {
56 part_bc
[i_part
] = sorted_part_name
.indexOf(part_name
[i_part
]) + 1;
58 for (int i_part
= 0; i_part
< num_parts
; ++i_part
) {
59 int num_nodes
, num_faces
;
60 f
>> num_nodes
>> num_faces
;
61 for (int i
= 0; i
< num_nodes
; ++i
) {
63 f
>> x
[0] >> x
[1] >> x
[2];
66 for (int i
= 0; i
< num_faces
; ++i
) {
69 QVector
<int> face(N
+1);
71 for (int j
= 0; j
< N
; ++j
) {
74 rfaces
.push_back(face
);
77 QVector
<vec3_t
> nodes(rnodes
.size());
78 qCopy(rnodes
.begin(), rnodes
.end(), nodes
.begin());
79 QVector
<QVector
<int> > faces(rfaces
.size());
80 qCopy(rfaces
.begin(), rfaces
.end(), faces
.begin());
82 // find smallest edge length
84 foreach (QVector
<int> face
, faces
) {
85 for (int i
= 1; i
< face
.size(); ++i
) {
88 if (i
< face
.size() - 1) {
91 double l
= (nodes
[n1
] - nodes
[n2
]).abs();
96 cout
<< "smallest edge length is " << L
<< endl
;
98 // delete duplicate nodes
100 finder
.setPoints(nodes
);
101 QList
<vec3_t
> non_dup
;
102 QVector
<int> o2n(nodes
.size());
104 for (int i
= 0; i
< nodes
.size(); ++i
) {
105 o2n
[i
] = num_non_dup
;
107 QVector
<int> close_points
;
108 finder
.getClosePoints(nodes
[i
], close_points
);
109 foreach (int j
, close_points
) {
111 double l
= (nodes
[i
] - nodes
[j
]).abs();
112 if (l
< m_RelativeTolerance
*L
|| l
== 0) {
120 non_dup
.push_back(nodes
[i
]);
125 EG_VTKSP(vtkUnstructuredGrid
, new_grid
);
127 allocateGrid(new_grid
, faces
.size(), non_dup
.size());
128 EG_VTKDCC(vtkIntArray
, cell_code
, new_grid
, "cell_code");
129 EG_VTKDCC(vtkIntArray
, orgdir
, new_grid
, "cell_orgdir");
130 EG_VTKDCC(vtkIntArray
, voldir
, new_grid
, "cell_voldir");
131 EG_VTKDCC(vtkIntArray
, curdir
, new_grid
, "cell_curdir");
132 vtkIdType id_node
= 0;
133 foreach (vec3_t x
, non_dup
) {
134 new_grid
->GetPoints()->SetPoint(id_node
, x
.data());
138 foreach (QVector
<int> face
, faces
) {
139 if (face
.size() == 4) {
141 pts
[0] = o2n
[face
[1]];
142 pts
[1] = o2n
[face
[2]];
143 pts
[2] = o2n
[face
[3]];
144 vtkIdType id_cell
= new_grid
->InsertNextCell(VTK_TRIANGLE
, 3, pts
);
145 cell_code
->SetValue(id_cell
, part_bc
[face
[0]]);
146 orgdir
->SetValue(id_cell
, 0);
147 voldir
->SetValue(id_cell
, 0);
148 curdir
->SetValue(id_cell
, 0);
150 if (face
.size() == 5) {
152 pts
[0] = o2n
[face
[1]];
153 pts
[1] = o2n
[face
[2]];
154 pts
[2] = o2n
[face
[3]];
155 pts
[3] = o2n
[face
[4]];
156 vtkIdType id_cell
= new_grid
->InsertNextCell(VTK_QUAD
, 4, pts
);
157 cell_code
->SetValue(id_cell
, part_bc
[face
[0]]);
158 orgdir
->SetValue(id_cell
, 0);
159 voldir
->SetValue(id_cell
, 0);
160 curdir
->SetValue(id_cell
, 0);
166 MeshPartition
new_part(new_grid
);
167 new_part
.setAllCells();
168 m_Part
.addPartition(new_part
);
170 makeCopy(new_grid
, m_Grid
);
173 UpdateNodeIndex(m_Grid
);
174 UpdateCellIndex(m_Grid
);
176 // check and set the boundary names if required
177 int update_required
= true;
178 QSet
<int> old_bcs
= GuiMainWindow::pointer()->getAllBoundaryCodes();
179 if (old_bcs
.size() == part_name
.size()) {
180 QSet
<QString
> old_names
;
181 foreach (int bc
, old_bcs
) {
182 old_names
.insert(GuiMainWindow::pointer()->getBC(bc
).getName());
184 QSet
<QString
> new_names
;
185 foreach (QString name
, part_name
) {
186 new_names
.insert(name
);
188 if (old_names
== new_names
) {
189 update_required
= false;
190 cout
<< "no update required" << endl
;
193 if (update_required
) {
194 GuiMainWindow::pointer()->resetXmlDoc();
195 GuiMainWindow::pointer()->clearBCs();
196 for (int i_part
= 0; i_part
< part_name
.size(); ++i_part
) {
197 GuiMainWindow::pointer()->addBC(part_bc
[i_part
], BoundaryCondition(part_name
[i_part
], "patch"));
202 } catch (Error err
) {