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 "blenderreader.h"
25 #include "guimainwindow.h"
26 #include "pointfinder.h"
28 BlenderReader::BlenderReader()
30 setFormat("Blender/Engrid files(*.begc *.BEGC)");
31 getSet("General", "tolerance for importing geometries (% of smallest edge length)", 0.1, m_RelativeTolerance
);
32 m_RelativeTolerance
*= 1e-2;
35 void BlenderReader::operate()
38 QFileInfo
file_info(GuiMainWindow::pointer()->getFilename());
39 readInputFileName(file_info
.completeBaseName() + ".begc", false);
41 // read raw data from exported file
42 QFile
file(getFileName());
43 file
.open(QIODevice::ReadOnly
| QIODevice::Text
);
46 QList
<QVector
<int> > rfaces
;
49 QVector
<QString
> part_name(num_parts
);
50 for (int i_part
= 0; i_part
< num_parts
; ++i_part
) {
51 f
>> part_name
[i_part
];
53 QVector
<QString
> sorted_part_name
= part_name
;
54 qSort(sorted_part_name
);
55 QVector
<int> part_bc(part_name
.size());
56 for (int i_part
= 0; i_part
< num_parts
; ++i_part
) {
57 part_bc
[i_part
] = sorted_part_name
.indexOf(part_name
[i_part
]) + 1;
59 for (int i_part
= 0; i_part
< num_parts
; ++i_part
) {
60 int num_nodes
, num_faces
;
61 f
>> num_nodes
>> num_faces
;
62 for (int i
= 0; i
< num_nodes
; ++i
) {
64 f
>> x
[0] >> x
[1] >> x
[2];
67 for (int i
= 0; i
< num_faces
; ++i
) {
70 QVector
<int> face(N
+1);
72 for (int j
= 0; j
< N
; ++j
) {
75 rfaces
.push_back(face
);
78 QVector
<vec3_t
> nodes(rnodes
.size());
79 qCopy(rnodes
.begin(), rnodes
.end(), nodes
.begin());
80 QVector
<QVector
<int> > faces(rfaces
.size());
81 qCopy(rfaces
.begin(), rfaces
.end(), faces
.begin());
83 // find smallest edge length
85 foreach (QVector
<int> face
, faces
) {
86 for (int i
= 1; i
< face
.size(); ++i
) {
89 if (i
< face
.size() - 1) {
92 double l
= (nodes
[n1
] - nodes
[n2
]).abs();
97 cout
<< "smallest edge length is " << L
<< endl
;
99 // delete duplicate nodes
101 finder
.setPoints(nodes
);
102 QList
<vec3_t
> non_dup
;
103 QVector
<int> o2n(nodes
.size());
105 for (int i
= 0; i
< nodes
.size(); ++i
) {
106 o2n
[i
] = num_non_dup
;
108 QVector
<int> close_points
;
109 finder
.getClosePoints(nodes
[i
], close_points
);
110 foreach (int j
, close_points
) {
112 double l
= (nodes
[i
] - nodes
[j
]).abs();
113 if (l
< m_RelativeTolerance
*L
|| l
== 0) {
121 non_dup
.push_back(nodes
[i
]);
126 allocateGrid(m_Grid
, faces
.size(), non_dup
.size());
127 EG_VTKDCC(vtkIntArray
, cell_code
, m_Grid
, "cell_code");
128 EG_VTKDCC(vtkIntArray
, orgdir
, m_Grid
, "cell_orgdir");
129 EG_VTKDCC(vtkIntArray
, voldir
, m_Grid
, "cell_voldir");
130 EG_VTKDCC(vtkIntArray
, curdir
, m_Grid
, "cell_curdir");
131 vtkIdType id_node
= 0;
132 foreach (vec3_t x
, non_dup
) {
133 m_Grid
->GetPoints()->SetPoint(id_node
, x
.data());
137 foreach (QVector
<int> face
, faces
) {
138 if (face
.size() == 4) {
140 pts
[0] = o2n
[face
[1]];
141 pts
[1] = o2n
[face
[2]];
142 pts
[2] = o2n
[face
[3]];
143 vtkIdType id_cell
= m_Grid
->InsertNextCell(VTK_TRIANGLE
, 3, pts
);
144 cell_code
->SetValue(id_cell
, part_bc
[face
[0]]);
145 orgdir
->SetValue(id_cell
, 0);
146 voldir
->SetValue(id_cell
, 0);
147 curdir
->SetValue(id_cell
, 0);
149 if (face
.size() == 5) {
151 pts
[0] = o2n
[face
[1]];
152 pts
[1] = o2n
[face
[2]];
153 pts
[2] = o2n
[face
[3]];
154 pts
[3] = o2n
[face
[4]];
155 vtkIdType id_cell
= m_Grid
->InsertNextCell(VTK_QUAD
, 4, pts
);
156 cell_code
->SetValue(id_cell
, part_bc
[face
[0]]);
157 orgdir
->SetValue(id_cell
, 0);
158 voldir
->SetValue(id_cell
, 0);
159 curdir
->SetValue(id_cell
, 0);
162 UpdateNodeIndex(m_Grid
);
163 UpdateCellIndex(m_Grid
);
165 // check and set the boundary names if required
166 int update_required
= true;
167 QSet
<int> old_bcs
= GuiMainWindow::pointer()->getAllBoundaryCodes();
168 if (old_bcs
.size() == part_name
.size()) {
169 QSet
<QString
> old_names
;
170 foreach (int bc
, old_bcs
) {
171 old_names
.insert(GuiMainWindow::pointer()->getBC(bc
).getName());
173 QSet
<QString
> new_names
;
174 foreach (QString name
, part_name
) {
175 new_names
.insert(name
);
177 if (old_names
== new_names
) {
178 update_required
= false;
179 cout
<< "no update required" << endl
;
182 if (update_required
) {
183 GuiMainWindow::pointer()->resetXmlDoc();
184 GuiMainWindow::pointer()->clearBCs();
185 for (int i_part
= 0; i_part
< part_name
.size(); ++i_part
) {
186 GuiMainWindow::pointer()->addBC(part_bc
[i_part
], BoundaryCondition(part_name
[i_part
], "patch"));
191 } catch (Error err
) {