improved performance for face search -- some debugging required
[engrid-github.git] / src / libengrid / blenderreader.cpp
blob21dd7b858205e4df7cce8c774581b23a2a6471ab
1 //
2 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 // + +
4 // + This file is part of enGrid. +
5 // + +
6 // + Copyright 2008-2013 enGits GmbH +
7 // + +
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. +
12 // + +
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. +
17 // + +
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/>. +
20 // + +
21 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
22 //
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()
37 try {
38 QFileInfo file_info(GuiMainWindow::pointer()->getFilename());
39 readInputFileName(file_info.completeBaseName() + ".begc", false);
40 if (isValid()) {
41 // read raw data from exported file
42 QFile file(getFileName());
43 file.open(QIODevice::ReadOnly | QIODevice::Text);
44 QTextStream f(&file);
45 QList<vec3_t> rnodes;
46 QList<QVector<int> > rfaces;
47 int num_parts;
48 f >> num_parts;
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) {
63 vec3_t x;
64 f >> x[0] >> x[1] >> x[2];
65 rnodes.push_back(x);
67 for (int i = 0; i < num_faces; ++i) {
68 int N;
69 f >> N;
70 QVector<int> face(N+1);
71 face[0] = i_part;
72 for (int j = 0; j < N; ++j) {
73 f >> face[j+1];
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
84 double L = 1e99;
85 foreach (QVector<int> face, faces) {
86 for (int i = 1; i < face.size(); ++i) {
87 int n1 = face[i];
88 int n2 = face[1];
89 if (i < face.size() - 1) {
90 n2 = face[i+1];
92 double l = (nodes[n1] - nodes[n2]).abs();
93 L = min(l, L);
97 cout << "smallest edge length is " << L << endl;
99 // delete duplicate nodes
100 PointFinder finder;
101 finder.setPoints(nodes);
102 QList<vec3_t> non_dup;
103 QVector<int> o2n(nodes.size());
104 int num_non_dup = 0;
105 for (int i = 0; i < nodes.size(); ++i) {
106 o2n[i] = num_non_dup;
107 bool dup = false;
108 QVector<int> close_points;
109 finder.getClosePoints(nodes[i], close_points);
110 foreach (int j, close_points) {
111 if (i > j) {
112 double l = (nodes[i] - nodes[j]).abs();
113 if (l < m_RelativeTolerance*L || l == 0) {
114 o2n[i] = o2n[j];
115 dup = true;
116 break;
120 if (!dup) {
121 non_dup.push_back(nodes[i]);
122 ++num_non_dup;
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());
134 ++id_node;
137 foreach (QVector<int> face, faces) {
138 if (face.size() == 4) {
139 vtkIdType pts[3];
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) {
150 vtkIdType pts[4];
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) {
192 err.display();