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 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
21 #include "utilities.h"
25 #include <QApplication>
26 #include <QPushButton>
27 #include <QHBoxLayout>
28 #include <QFormLayout>
30 #include <QMainWindow>
31 #include <QHBoxLayout>
33 #include <QStringList>
37 // #include <QFileDialogArgs>
41 #include "math/mathvector.h"
42 #include "math/smallsquarematrix.h"
43 #include "math/linsolve.h"
45 #include "vtkIntArray.h"
46 #include "vtkCellData.h"
47 #include "vtkDataSet.h"
48 #include "egvtkobject.h"
51 double toDouble(QString str
) {
52 str
.replace(QString(QObject::tr(",")), QString(QObject::tr(".")));
53 return(str
.toDouble());
56 QString
toString(double x
, QString separator
) {
59 ret
.replace(QString(QObject::tr(".")), separator
);
63 QString
addSuffix(QString filename
, QString suffix
, bool remove_old_suffix
) {
64 QFileInfo
fileinfo(filename
);
65 if (remove_old_suffix
) {
66 return fileinfo
.completeBaseName() + QObject::tr(".") + suffix
;
68 if (fileinfo
.suffix().toLower() == suffix
) {
69 return fileinfo
.absoluteFilePath();
71 return fileinfo
.absoluteFilePath() + QObject::tr(".") + suffix
;
76 Qt::CheckState
int2CheckState(int a
) {
77 if (a
== 0) return(Qt::Unchecked
);
78 if (a
== 1) return(Qt::PartiallyChecked
);
79 else return(Qt::Checked
);
82 int CheckState2int(Qt::CheckState a
) {
83 if (a
== Qt::Unchecked
) return(0);
84 if (a
== Qt::PartiallyChecked
) return(1);
88 QString
vector2csv(QVector
<double> vector
) {
90 for (int i
= 0; i
< vector
.size(); i
++) {
91 csv
+= QString::number(vector
[i
]);
92 if (i
< vector
.size() - 1) csv
+= QObject::tr(";");
97 QVector
<double> csv2vector(QString csv
)
99 QVector
<double> vector
;
100 if (csv
.isEmpty()) return vector
;
101 QStringList list
= csv
.split(QObject::tr(";"));
102 foreach(QString str
, list
) {
103 vector
.push_back(str
.toDouble());
108 mat3_t
rotationMatrix_X(double a_rad
)
111 Rx
[0][0] = 1; Rx
[0][1] = 0; Rx
[0][2] = 0;
112 Rx
[1][0] = 0; Rx
[1][1] = cos(a_rad
); Rx
[1][2] = sin(a_rad
);
113 Rx
[2][0] = 0; Rx
[2][1] = -sin(a_rad
); Rx
[2][2] = cos(a_rad
);
117 mat3_t
rotationMatrix_Y(double a_rad
)
120 Ry
[0][0] = cos(a_rad
); Ry
[0][1] = 0; Ry
[0][2] = -sin(a_rad
);
121 Ry
[1][0] = 0; Ry
[1][1] = 1; Ry
[1][2] = 0;
122 Ry
[2][0] = sin(a_rad
); Ry
[2][1] = 0; Ry
[2][2] = cos(a_rad
);
126 mat3_t
rotationMatrix_Z(double a_rad
)
129 Rz
[0][0] = cos(a_rad
); Rz
[0][1] = sin(a_rad
); Rz
[0][2] = 0;
130 Rz
[1][0] = -sin(a_rad
); Rz
[1][1] = cos(a_rad
); Rz
[1][2] = 0;
131 Rz
[2][0] = 0; Rz
[2][1] = 0; Rz
[2][2] = 1;
135 mat3_t
rotateRelativeZXZ(double angle_1_rad
, double angle_2_rad
, double angle_3_rad
)
137 return rotationMatrix_Z(angle_3_rad
)*rotationMatrix_X(angle_2_rad
)*rotationMatrix_Z(angle_1_rad
);
140 mat3_t
rotateAbsoluteZXY(double angle_1_rad
, double angle_2_rad
, double angle_3_rad
)
142 return rotationMatrix_Z(angle_1_rad
)*rotationMatrix_X(angle_2_rad
)*rotationMatrix_Y(angle_3_rad
);
145 double getGamma(vec3_t V
) {
146 return V
[0] == 0.0 && V
[1] == 0.0 && V
[2] == 0.0 ? 0.0 : atan2(sqrt(V
[0]*V
[0] + V
[1]*V
[1]), V
[2]);
149 double getPhi(vec3_t V
) {
150 return V
[0] == 0.0 && V
[1] == 0.0 ? 0.0 : atan2(V
[1], V
[0]);
153 QString
getDirectory(QWidget
* parent
, const QString
& caption
, const QString
& selected
)
155 qDebug() << "selected=" << selected
;
156 QFileInfo
fileinfo(selected
);
157 QString dir
= fileinfo
.absolutePath();
158 qDebug() << "dir=" << dir
;
160 // create a qt dialog
161 QFileDialog
dialog(parent
, caption
, dir
);//(args);
162 dialog
.setFileMode(QFileDialog::Directory
);
163 #if QT_VERSION >= 0x040500
164 dialog
.setOption(QFileDialog::ShowDirsOnly
, true);
166 dialog
.selectFile(selected
);
168 if (dialog
.exec() == QDialog::Accepted
) {
169 return dialog
.selectedFiles().value(0);
174 int cout_grid(ostream
&stream
, vtkUnstructuredGrid
*grid
, bool npoints
, bool ncells
, bool points
, bool cells
) {
175 stream
<< "=============" << endl
;
176 if (npoints
) stream
<< "grid->GetNumberOfPoints()=" << grid
->GetNumberOfPoints() << endl
;
177 if (ncells
) stream
<< "grid->GetNumberOfCells()=" << grid
->GetNumberOfCells() << endl
;
179 for (vtkIdType i
= 0; i
< grid
->GetNumberOfPoints(); ++i
) {
181 grid
->GetPoint(i
, x
.data());
182 stream
<< "Vertex " << i
<< " = " << x
<< endl
;
186 EG_VTKDCC(vtkIntArray
, cell_code
, grid
, "cell_code");
187 for (vtkIdType i
= 0; i
< grid
->GetNumberOfCells(); ++i
) {
188 vtkCell
*C
= (vtkCell
*) vtkCell::New();
189 C
= grid
->GetCell(i
);
190 vtkIdType npts
= C
->GetNumberOfPoints();
192 grid
->GetCellPoints(i
, npts
, pts
);
193 stream
<< "Cell " << i
<< " = ";
194 for (int j
= 0; j
< npts
; j
++) stream
<< pts
[j
] << " ";
195 stream
<< "boundary_code=" << cell_code
->GetValue(i
);
199 stream
<< "=============" << endl
;
203 ///////////////////////////////////////////
205 int addCell(vtkUnstructuredGrid
* a_grid
, vtkIdType A
, vtkIdType B
, vtkIdType C
, int bc
) {
211 vtkIdType newCellId
= a_grid
->InsertNextCell(VTK_TRIANGLE
, npts
, pts
);
212 EG_VTKDCC(vtkIntArray
, cell_code
, a_grid
, "cell_code");
213 cell_code
->SetValue(newCellId
, bc
);
217 ///////////////////////////////////////////
219 int getShortestSide(vtkIdType a_id_cell
, vtkUnstructuredGrid
* a_grid
) {
220 vtkIdType N_pts
, *pts
;
221 a_grid
->GetCellPoints(a_id_cell
, N_pts
, pts
);
222 vec3_t
* x
= new vec3_t
[N_pts
];
223 for (int i
= 0; i
< N_pts
; i
++) a_grid
->GetPoints()->GetPoint(pts
[i
], x
[i
].data());
225 double minlen
= (x
[1] - x
[0]).abs();
226 for (int i
= 1; i
< N_pts
; i
++) {
227 double len
= (x
[(i
+1)%N_pts
] - x
[i
]).abs();
237 int getLongestSide(vtkIdType a_id_cell
, vtkUnstructuredGrid
* a_grid
) {
238 vtkIdType N_pts
, *pts
;
239 a_grid
->GetCellPoints(a_id_cell
, N_pts
, pts
);
240 vec3_t
* x
= new vec3_t
[N_pts
];
241 for (int i
= 0; i
< N_pts
; i
++) a_grid
->GetPoints()->GetPoint(pts
[i
], x
[i
].data());
243 double maxlen
= (x
[1] - x
[0]).abs();
244 cout
<< "maxlen=" << maxlen
<< endl
;
245 for (int i
= 1; i
< N_pts
; i
++) {
246 double len
= (x
[(i
+1)%N_pts
] - x
[i
]).abs();
247 cout
<< "len[" << i
<< "]=" << len
<< endl
;
257 int getSide(vtkIdType a_id_cell
, vtkUnstructuredGrid
* a_grid
, vtkIdType a_id_node1
, vtkIdType a_id_node2
) {
258 vtkIdType N_pts
, *pts
;
259 a_grid
->GetCellPoints(a_id_cell
, N_pts
, pts
);
260 QVector
<vtkIdType
> edge(2);
263 for (int i
= 0; i
< N_pts
; i
++) {
264 if (pts
[i
] == a_id_node1
) { edge
[0] = i
; n
++;}
265 if (pts
[i
] == a_id_node2
) { edge
[1] = i
; n
++;}
271 qSort(edge
.begin(), edge
.end());
272 if (edge
[0] == 0 && edge
[1] == N_pts
- 1) return(N_pts
- 1);
273 else return(edge
[0]);
275 ///////////////////////////////////////////
277 QString
cell2str(vtkIdType id_cell
, vtkUnstructuredGrid
* grid
) {
280 QString txt
= "id_cell=" + tmp
;
282 vtkIdType N_pts
, *pts
;
283 grid
->GetCellPoints(id_cell
, N_pts
, pts
);
286 for (int i_pts
= 0; i_pts
< N_pts
; ++i_pts
) {
287 tmp
.setNum(pts
[i_pts
]);
289 if (i_pts
< N_pts
- 1) {
299 ///////////////////////////////////////////
301 pair
<vtkIdType
, vtkIdType
> OrderedPair(vtkIdType a
, vtkIdType b
) {
302 vtkIdType x
= min(a
, b
);
303 vtkIdType y
= max(a
, b
);
304 return(pair
<vtkIdType
, vtkIdType
>(x
, y
));
307 const char* VertexType2Str(char T
) {
308 if (T
== EG_SIMPLE_VERTEX
) return("EG_SIMPLE_VERTEX");
309 if (T
== EG_FIXED_VERTEX
) return("EG_FIXED_VERTEX");
310 if (T
== EG_FEATURE_EDGE_VERTEX
) return("EG_FEATURE_EDGE_VERTEX");
311 if (T
== EG_FEATURE_CORNER_VERTEX
) return("EG_FEATURE_CORNER_VERTEX");
312 if (T
== EG_BOUNDARY_EDGE_VERTEX
) return("EG_BOUNDARY_EDGE_VERTEX");
313 else return("Unknown vertex type");
316 char Str2VertexType(QString S
) {
317 if (S
== "EG_SIMPLE_VERTEX") return(EG_SIMPLE_VERTEX
);
318 if (S
== "EG_FIXED_VERTEX") return(EG_FIXED_VERTEX
);
319 if (S
== "EG_FEATURE_EDGE_VERTEX") return(EG_FEATURE_EDGE_VERTEX
);
320 if (S
== "EG_FEATURE_CORNER_VERTEX") return(EG_FEATURE_CORNER_VERTEX
);
321 if (S
== "EG_BOUNDARY_EDGE_VERTEX") return(EG_BOUNDARY_EDGE_VERTEX
);
322 else return((char) - 1);
325 bool checkVector(vec3_t V
)
327 for (int i
= 0; i
< 3; i
++) {
338 bool checkVector(vec2_t V
)
340 for (int i
= 0; i
< 2; i
++) {
351 bool checkReal(double v
)
362 QDebug
operator<<(QDebug dbg
, const vec3_t
&v
)
364 dbg
.nospace() << "(" << v
[0] << ", " << v
[1] << ", " << v
[2] << ")";
368 QDebug
operator<<(QDebug dbg
, const vec2_t
&v
)
370 dbg
.nospace() << "(" << v
[0] << ", " << v
[1] << ")";
374 QDebug
operator<<(QDebug dbg
, const dcmplx
&c
)
376 dbg
.nospace() << real(c
)<<" + "<<imag(c
)<<" *i";
380 dcmplx
complex_pow(dcmplx base
, double power
)
383 double alpha
= atan2(imag(base
),real(base
));
384 return pow(abs(base
),power
)*exp(power
*alpha
*i
);
387 #define SWAP(a,b) do { double tmp = b ; b = a ; a = tmp ; } while(0)
389 int poly_solve_cubic(double a
, double b
, double c
, double * x0
, double * x1
, double * x2
)
391 double q
= (a
* a
- 3 * b
);
392 double r
= (2 * a
* a
* a
- 9 * a
* b
+ 27 * c
);
397 double Q3
= Q
* Q
* Q
;
400 double CR2
= 729 * r
* r
;
401 double CQ3
= 2916 * q
* q
* q
;
403 if (R
== 0 && Q
== 0)
412 // this test is actually R2 == Q3, written in a form suitable
413 // for exact computation with integers
415 // Due to finite precision some double roots may be missed, and
416 // considered to be a pair of complex roots z = x +/- epsilon i
417 // close to the real axis.
419 double sqrtQ
= sqrt (Q
);
423 *x0
= -2 * sqrtQ
- a
/ 3;
427 *x0
= - sqrtQ
- a
/ 3;
428 *x1
= - sqrtQ
- a
/ 3;
429 *x2
= 2 * sqrtQ
- a
/ 3;
432 } else if (CR2
< CQ3
) { // equivalent to R2 < Q3
433 double sqrtQ
= sqrt (Q
);
434 double sqrtQ3
= sqrtQ
* sqrtQ
* sqrtQ
;
435 double theta
= acos (R
/ sqrtQ3
);
436 double norm
= -2 * sqrtQ
;
437 *x0
= norm
* cos (theta
/ 3) - a
/ 3;
438 *x1
= norm
* cos ((theta
+ 2.0 * M_PI
) / 3) - a
/ 3;
439 *x2
= norm
* cos ((theta
- 2.0 * M_PI
) / 3) - a
/ 3;
441 // Sort *x0, *x1, *x2 into increasing order
456 double sgnR
= (R
>= 0 ? 1 : -1);
457 double A
= -sgnR
* pow (fabs (R
) + sqrt (R2
- Q3
), 1.0/3.0);
464 // a x^2 + b x + c = 0
465 int poly_solve_quadratic(double a
, double b
, double c
, double * x0
, double * x1
)
475 double delta
= pow(b
, 2) - 4 * a
* c
;
479 *x0
= (-b
+ sqrt(delta
)) / (2 * a
);
480 *x1
= (-b
- sqrt(delta
)) / (2 * a
);