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