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 /** @file utilities.h Contains several utility functions. */
30 #include <QFileDialog>
35 #include "math/mathvector.h"
36 #include "math/smallsquarematrix.h"
37 #include "math/linsolve.h"
39 #include "vtkUnstructuredGrid.h"
45 #define isnan(x) _isnan(x)
46 #define isinf(x) !_finite(x)
51 /** Restricts value to the CYCLIC [min,max[ range.
52 * Equivalent to min + modulo(value-min, max-min)
53 * @param value value to restrict
55 * @param max maximum (if value=max, then min will be returned)
57 inline double restrict_to(double value
, double min
, double max
)
59 return value
- floor((value
- min
) / (max
- min
))*(max
- min
);
62 /// Converts degrees to radians
63 inline double RadiansFromDegrees(double a_deg
)
65 return(a_deg
/ 180.0*M_PI
);
68 /// Converts radians to degrees
69 inline double DegreesFromRadians(double a_rad
)
71 return(a_rad
/ M_PI
*180.0);
74 double toDouble(QString str
);///< Equivalent of the QString::toDouble function, but it also replaces "," with "."
76 /** Converts a double to a string.
77 * @param x double value to convert
78 * @param separator symbol to use as decimal separator. It is recommended to always use the default: ".".
80 QString
toString(double x
, QString separator
= QObject::tr("."));
82 /// a modulo function which also works for negative numbers
83 inline int modulo(int a
, int b
)
85 return((a
% b
+ b
) % b
);
88 /// a modulo function which also works for negative numbers
89 inline double modulo(double a
, double b
)
92 while (a
>= b
) a
-= b
;
96 /** Adds a suffix to a filename if it is missing.
97 * @param filename string to which to add the suffix
98 * @param suffix suffix to add. suffix should be of the form 'ext' without the dot!!!
99 * @param remove_old_suffix If true, any previous suffix of filename will be removed. ex: foo.bar -> foo.png
100 * @return the filename with the new suffix
102 QString
addSuffix(QString filename
, QString suffix
, bool remove_old_suffix
);
104 ///////////////////////////////////////////
106 /** Transposes a vector of vectors (matrix)
107 * @param in the matrix to transpose
108 * @param nrows the number of rows of the input matrix
109 * @param ncolumns the number of columns of the input matrix
110 * @return the transposed "matrix"
113 QVector
< QVector
<T
> > transpose(QVector
< QVector
<T
> > & in
, int nrows
, int ncolumns
)
115 QVector
< QVector
<T
> > out(ncolumns
);
116 QVector
<T
> col(nrows
);
119 for (int i
= 0; i
< in
.size(); i
++) {
120 QVector
<T
> row
= in
[i
];
121 for (int j
= 0; j
< row
.size(); j
++) {
122 out
[j
][i
] = in
[i
][j
];
128 ///////////////////////////////////////////
130 /// ostream operator for QVectors
132 ostream
&operator<<(ostream
&out
, QVector
<T
> const & vector
)
134 int N
= vector
.size();
136 for (int i
= 0; i
< N
; ++i
) {
138 if (i
!= N
- 1) out
<< ",";
144 /// ostream operator for QSets
146 ostream
&operator<<(ostream
&out
, QSet
<T
> const & set
)
149 foreach(T value
, set
) out
<< value
<< " ";
154 /// ostream operator for QVectors of QSets
156 ostream
&operator<<(ostream
&out
, QVector
<QSet
<T
> > & vector
)
158 int N
= vector
.size();
160 for (int i
= 0; i
< N
; ++i
) {
161 QSet
<T
> set
= vector
.at(i
);
163 if (i
!= N
- 1) out
<< ",";
169 /// ostream operator for QVectors of QVectors
171 ostream
&operator<<(ostream
&out
, QVector
<QVector
<T
> > & vector
)
173 int N
= vector
.size();
175 for (int i
= 0; i
< N
; ++i
) {
176 QVector
<T
> subvector
= vector
.at(i
);
178 if (i
!= N
- 1) out
<< ",";
184 /// ostream operator for QMaps
185 template <class T1
, class T2
>
186 ostream
&operator<<(ostream
&out
, QMap
<T1
, T2
> & map
)
188 QMapIterator
<T1
, T2
> i(map
);
190 while (i
.hasNext()) {
192 out
<< " [" << i
.key() << ": " << i
.value() << "]";
198 /// ostream operator for a QVector of pairs
199 template <class T1
, class T2
>
200 ostream
&operator<<(ostream
&out
, QVector
< pair
<T1
, T2
> > & vector
)
202 int N
= vector
.size();
204 for (int i
= 0; i
< N
; ++i
) {
206 out
<< vector
.at(i
).first
;
208 out
<< vector
.at(i
).second
;
210 if (i
!= N
- 1) out
<< ",";
216 ////////////////////////////////////////////////////
219 QVector
<T
> set2Vector(QSet
<T
> a_set
, bool a_sort
)
221 QVector
<T
> l_vector(a_set
.size());
222 qCopy(a_set
.begin(),a_set
.end(),l_vector
.begin());
223 if(a_sort
) qSort(l_vector
.begin(),l_vector
.end());
228 QSet
<T
> vector2Set(QVector
<T
> a_vector
, bool a_sort
)
231 foreach(T element
, a_vector
) l_set
.insert(element
);
232 if(a_sort
) qSort(l_set
.begin(),l_set
.end());
237 bool duplicates(QVector
<T
> a_vector
)
240 foreach(T element
, a_vector
) l_set
.insert(element
);
241 return l_set
.size()!=a_vector
.size();
244 ////////////////////////////////////////////////////
246 Qt::CheckState
int2CheckState(int a
);///< Converts an integer into a Qt::CheckState: Qt::Unchecked=0, Qt::PartiallyChecked=1, Qt::Checked=2
247 int CheckState2int(Qt::CheckState a
);///< Converts a Qt::CheckState into an integer: Qt::Unchecked=0, Qt::PartiallyChecked=1, Qt::Checked=2
249 QString
vector2csv(QVector
<double> vector
);///< Converts a vector into a CSV string
250 QVector
<double> csv2vector(QString csv
);///< Converts a CSV string into a vector
252 /// V(rotated base) = rotationMatrix_X * V(original base)
253 mat3_t
rotationMatrix_X(double a_rad
);
255 /// V(rotated base) = rotationMatrix_Y * V(original base)
256 mat3_t
rotationMatrix_Y(double a_rad
);
258 /// V(rotated base) = rotationMatrix_Z * V(original base)
259 mat3_t
rotationMatrix_Z(double a_rad
);
261 /// V(rotated base) = rotateRelativeZXZ * V(original base)
262 mat3_t
rotateRelativeZXZ(double angle_1_rad
, double angle_2_rad
, double angle_3_rad
);
264 /// V(rotated base) = rotateAbsoluteZXY * V(original base)
265 mat3_t
rotateAbsoluteZXY(double angle_1_rad
, double angle_2_rad
, double angle_3_rad
);
267 /// returns the polar angle in radians
268 double getGamma(vec3_t V
);
270 /// returns the azimuth angle in radians. returns phi from -pi to pi
271 double getPhi(vec3_t V
);
273 /// A version of QFileDialog::getExistingDirectory which allows preselecting a directory
274 QString
getDirectory(QWidget
* parent
= 0, const QString
& caption
= QString(), const QString
& selected
= QString());
275 // QString getDirectory( QWidget * parent = 0, const QString & caption = QString(), const QString & dir = QString(), const QString & selected = QString() , Options options = ShowDirsOnly );
278 * Utility function that allows printing selected data from an vtkUnstructuredGrid to any ostream (includes ofstream objects)
279 * @param stream ostream object to print to
280 * @param grid vtkUnstructuredGrid you want to print data from
281 * @param npoints print number of points in the grid
282 * @param ncells print number of cells in the grid
283 * @param points print points in the grid
284 * @param cells print cells in the grid
286 int cout_grid(ostream
&stream
, vtkUnstructuredGrid
*grid
, bool npoints
=true, bool ncells
=true, bool points
=false, bool cells
=false);
288 ///////////////////////////////////////////
289 int addCell(vtkUnstructuredGrid
* a_grid
, vtkIdType A
, vtkIdType B
, vtkIdType C
, int bc
);
291 ///get number of the shortest side of the cell
292 int getShortestSide(vtkIdType a_id_cell
,vtkUnstructuredGrid
* a_grid
);
293 ///get number of the longest side of the cell
294 int getLongestSide(vtkIdType a_id_cell
,vtkUnstructuredGrid
* a_grid
);
295 //sort sides by length
296 //QVector <vtkIdType> sortSidesByLength(vtkIdType a_id_cell,vtkUnstructuredGrid* a_grid);
298 ///get number of the edge corresponding to node1-node2
299 int getSide(vtkIdType a_id_cell
,vtkUnstructuredGrid
* a_grid
,vtkIdType a_id_node1
,vtkIdType a_id_node2
);
301 // QSet <int> complementary_bcs(QSet <int> &bcs, vtkUnstructuredGrid *a_grid, QVector <vtkIdType> &a_cells);
302 QString
cell2str(vtkIdType id_cell
,vtkUnstructuredGrid
* grid
);
304 ///////////////////////////////////////////
305 ///////////////////////////////////////////
306 pair
<vtkIdType
,vtkIdType
> OrderedPair(vtkIdType a
, vtkIdType b
);
308 const char* VertexType2Str(char T
);
309 char Str2VertexType(QString S
);
310 QDebug
operator<<(QDebug dbg
, const vec3_t
&v
);
311 QDebug
operator<<(QDebug dbg
, const vec2_t
&v
);
313 bool checkVector(vec3_t V
);
314 bool checkVector(vec2_t V
);
315 bool checkReal(double v
);
317 /// returns the index of a node in a structured triangle grid
318 inline vtkIdType
trigrid_idx(vtkIdType N
, int i
, int j
) {
319 int offset
= -i
* (i
- 2 * N
- 1) / 2;
323 /// returns the index of a node in a structured quad grid
324 inline vtkIdType
quadgrid_idx(vtkIdType N
, int i
, int j
) {
329 typedef complex<double> dcmplx
;
330 QDebug
operator<<(QDebug dbg
, const dcmplx
&c
);
331 dcmplx
complex_pow(dcmplx base
, double power
);
332 // x^3 + a x^2 + b x + c = 0
333 int poly_solve_cubic(double a
, double b
, double c
, double * x0
, double * x1
, double * x2
);
334 // a x^2 + b x + c = 0
335 int poly_solve_quadratic(double a
, double b
, double c
, double * x0
, double * x1
);
337 inline double logarithm(double a
, double b
)
339 return log(b
)/log(a
);