1 /*************************************************************************** 2 File : Spectrogram.h 3 Project : QtiPlot 4 -------------------------------------------------------------------- 5 Copyright : (C) 2006 by Ion Vasilief 6 Email (use @ for *) : ion_vasilief*yahoo.fr 7 Description : QtiPlot's Spectrogram Class 8 ***************************************************************************/ 9 10 /*************************************************************************** 11 * * 12 * This program is free software; you can redistribute it and/or modify * 13 * it under the terms of the GNU General Public License as published by * 14 * the Free Software Foundation; either version 2 of the License, or * 15 * (at your option) any later version. * 16 * * 17 * This program is distributed in the hope that it will be useful, * 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 20 * GNU General Public License for more details. * 21 * * 22 * You should have received a copy of the GNU General Public License * 23 * along with this program; if not, write to the Free Software * 24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, * 25 * Boston, MA 02110-1301 USA * 26 * * 27 ***************************************************************************/ 28 29 #ifndef SPECTROGRAM_H 30 #define SPECTROGRAM_H 31 32 #include <QApplication> 33 #include <Matrix.h> 34 #include <muParserScript.h> 35 #include <LinearColorMap.h> 36 37 #include <qwt_raster_data.h> 38 #include <qwt_plot.h> 39 #include <qwt_plot_spectrogram.h> 40 #include <qwt_plot_marker.h> 41 42 class MatrixData; 43 class Graph; 44 class PlotMarker; 45 46 class Spectrogram: public QwtPlotSpectrogram 47 { 48 public: 49 Spectrogram(Graph *graph, Matrix *m); 50 51 enum ColorMapPolicy{GrayScale, Default, Custom}; 52 53 Spectrogram* copy(Graph *g); graph()54 Graph * graph(){return d_graph;}; 55 matrix()56 Matrix * matrix(){return d_matrix;}; 57 bool setMatrix(Matrix *m, bool useFormula = false); 58 levels()59 int levels(){return (int)contourLevels().size();}; 60 void setLevelsNumber(int levels); 61 void setContourLevels (const QwtValueList & levels); 62 63 bool hasColorScale(); colorScaleAxis()64 int colorScaleAxis(){return color_axis;}; setColorScaleAxis(int axis)65 void setColorScaleAxis(int axis){color_axis = axis;}; 66 void showColorScale(int axis, bool on = true); 67 68 int colorBarWidth(); 69 void setColorBarWidth(int width); 70 71 void setGrayScale(); 72 void setDefaultColorMap(); 73 colorMap()74 LinearColorMap colorMap(){return color_map;}; colorMapPointer()75 LinearColorMap *colorMapPointer(){return &color_map;}; 76 void setCustomColorMap(const LinearColorMap& map); 77 78 //! Used when saving a project file 79 QString saveToString(); 80 colorMapPolicy()81 ColorMapPolicy colorMapPolicy(){return color_map_policy;}; 82 83 virtual QwtDoubleRect boundingRect() const; 84 hasLabels()85 bool hasLabels(){return d_show_labels;}; labelsList()86 QList <PlotMarker *> labelsList(){return d_labels_list;}; 87 88 void showContourLineLabels(bool show = true); 89 labelsFont()90 QFont labelsFont(){return d_labels_font;}; 91 void setLabelsFont(const QFont& font); 92 labelsColor()93 QColor labelsColor(){return d_labels_color;}; 94 void setLabelsColor(const QColor& c); 95 labelsWhiteOut()96 bool labelsWhiteOut(){return d_white_out_labels;}; 97 void setLabelsWhiteOut(bool whiteOut); 98 labelsXOffset()99 double labelsXOffset(){return d_labels_x_offset;}; labelsYOffset()100 double labelsYOffset(){return d_labels_y_offset;}; 101 void setLabelsOffset(double x, double y); 102 void setLabelOffset(int index, double x, double y); 103 labelsRotation()104 double labelsRotation(){return d_labels_angle;}; 105 void setLabelsRotation(double angle); 106 107 bool selectedLabels(const QPoint& pos); 108 void selectLabel(bool on); 109 bool hasSelectedLabels(); 110 void moveLabel(const QPoint& pos); 111 void clearLabels(); 112 113 virtual void setVisible(bool on); 114 virtual QPen contourPen (double level) const; 115 void setColorMapPen(bool on = true); useColorMapPen()116 bool useColorMapPen(){return d_color_map_pen;}; 117 contourPenList()118 QList<QPen> contourPenList(){return d_pen_list;}; 119 void setContourPenList(QList<QPen> lst); 120 121 void setContourLinePen(int index, const QPen &pen); 122 useMatrixFormula()123 bool useMatrixFormula(){return d_use_matrix_formula;}; 124 bool setUseMatrixFormula(bool on = true); 125 126 void updateData(); 127 QwtDoubleInterval range() const; 128 129 protected: 130 virtual QImage renderImage(const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QwtDoubleRect &rect) const; 131 virtual void drawContourLines (QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QwtRasterData::ContourLines &lines) const; 132 void updateLabels(QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QwtRasterData::ContourLines &lines) const; 133 void createLabels(); 134 //! Pointer to the parent plot 135 Graph *d_graph; 136 //! Pointer to the source data matrix 137 Matrix *d_matrix; 138 139 //! Axis used to display the color scale 140 int color_axis; 141 142 //! Flags 143 ColorMapPolicy color_map_policy; 144 145 LinearColorMap color_map; 146 //! Flag telling if we display the labels 147 bool d_show_labels; 148 //! Labels color 149 QColor d_labels_color; 150 //! Labels font 151 QFont d_labels_font; 152 //! Flag telling if we paint a white background for the labels 153 bool d_white_out_labels; 154 double d_labels_angle; 155 double d_labels_x_offset, d_labels_y_offset; 156 157 //! List of the text labels associated to this spectrogram. 158 QList <PlotMarker *> d_labels_list; 159 //! Keeps track of the plot marker on which the user clicked when selecting the labels. 160 PlotMarker *d_selected_label; 161 //! Keep track of the coordinates of the point where the user clicked when selecting the labels. 162 double d_click_pos_x, d_click_pos_y; 163 164 //! Flag telling that we evaluate the matrix expression instead of using the matrix data. 165 bool d_use_matrix_formula; 166 167 //! Flag telling if we use the color map to calculate the pen (QwtPlotSpectrogram::contourPen()). 168 bool d_color_map_pen; 169 170 QList<QPen> d_pen_list; 171 }; 172 173 class MatrixData: public QwtRasterData 174 { 175 public: 176 MatrixData(Matrix *m, bool useMatrixFormula = false): 177 QwtRasterData(m->boundingRect()), 178 d_matrix(m) 179 { 180 n_rows = d_matrix->numRows(); 181 n_cols = d_matrix->numCols(); 182 183 x_start = d_matrix->xStart(); 184 dx = d_matrix->dx(); 185 y_start = d_matrix->yStart(); 186 dy = d_matrix->dy(); 187 188 d_mup = NULL; 189 if (useMatrixFormula && d_matrix->canCalculate()){ 190 d_mup = new muParserScript(d_matrix->scriptingEnv(), d_matrix->formula(), 191 d_matrix, QString("<%1>").arg(d_matrix->objectName())); 192 193 d_x = d_mup->defineVariable("x"); 194 d_y = d_mup->defineVariable("y"); 195 d_ri = d_mup->defineVariable("i"); 196 d_rr = d_mup->defineVariable("row"); 197 d_cj = d_mup->defineVariable("j"); 198 d_cc = d_mup->defineVariable("col"); 199 200 if (!d_mup->compile()){ 201 delete d_mup; 202 d_mup = NULL; 203 } 204 205 if (d_mup){//calculate z range 206 *d_ri = 1.0; 207 *d_rr = 1.0; 208 *d_y = y_start; 209 *d_cj = 1.0; 210 *d_cc = 1.0; 211 *d_x = x_start; 212 213 if (d_mup->codeLines() == 1) 214 min_z = d_mup->evalSingleLine(); 215 else 216 min_z = d_mup->eval().toDouble(); 217 218 max_z = min_z; 219 220 if (d_mup->codeLines() == 1){ 221 for(int row = 0; row < n_rows; row++){ 222 double r = row + 1.0; 223 *d_ri = r; *d_rr = r; 224 *d_y = y_start + row*dy; 225 for(int col = 0; col < n_cols; col++){ 226 double c = col + 1.0; 227 *d_cj = c; *d_cc = c; 228 *d_x = x_start + col*dx; 229 double aux = d_mup->evalSingleLine(); 230 if (aux <= min_z) 231 min_z = aux; 232 if (aux >= max_z) 233 max_z = aux; 234 } 235 } 236 } else { 237 for(int row = 0; row < n_rows; row++){ 238 double r = row + 1.0; 239 *d_ri = r; *d_rr = r; 240 *d_y = y_start + row*dy; 241 for(int col = 0; col < n_cols; col++){ 242 double c = col + 1.0; 243 *d_cj = c; *d_cc = c; 244 *d_x = x_start + col*dx; 245 double aux = d_mup->eval().toDouble(); 246 if (aux <= min_z) 247 min_z = aux; 248 if (aux >= max_z) 249 max_z = aux; 250 } 251 qApp->processEvents(); 252 } 253 } 254 } 255 } else 256 m->range(&min_z, &max_z); 257 } 258 ~MatrixData()259 ~MatrixData() 260 { 261 if (d_mup) 262 delete d_mup; 263 } 264 copy()265 virtual QwtRasterData *copy() const 266 { 267 if (d_mup) 268 return new MatrixData(d_matrix, true); 269 270 return new MatrixData(d_matrix); 271 } 272 range()273 virtual QwtDoubleInterval range() const 274 { 275 return QwtDoubleInterval(min_z, max_z); 276 } 277 rasterHint(const QwtDoubleRect &)278 virtual QSize rasterHint (const QwtDoubleRect &) const 279 { 280 return QSize(n_cols, n_rows); 281 } 282 283 virtual double value(double x, double y) const; 284 285 private: 286 //! Pointer to the source data matrix 287 Matrix *d_matrix; 288 289 //! Data size 290 int n_rows, n_cols; 291 292 //! Min and max values in the source data matrix 293 double min_z, max_z; 294 295 //! Data resolution in x(columns) and y(rows) 296 double dx, dy; 297 298 //! X axis left value in the data matrix 299 double x_start; 300 301 //! Y axis bottom value in the data matrix 302 double y_start; 303 304 //! Pointer to a muParserScript 305 muParserScript *d_mup; 306 //! Pointers to internal variables of the muParserScript 307 double *d_x, *d_y, *d_ri, *d_rr, *d_cj, *d_cc; 308 }; 309 310 #endif 311