1 /***************************************************************************
2 File : Spectrogram.cpp
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 #include <Spectrogram.h>
29 #include <Graph.h>
30 #include <MultiLayer.h>
31 #include <ApplicationWindow.h>
32 #include <PlotCurve.h>
33 #include <PenStyleBox.h>
34
35 #include <math.h>
36 #include <QPen>
37 #include <QPainter>
38 #include <qwt_scale_widget.h>
39 #include <qwt_painter.h>
40
Spectrogram(Graph * graph,Matrix * m)41 Spectrogram::Spectrogram(Graph *graph, Matrix *m):
42 QwtPlotSpectrogram(QString(m->objectName())),
43 d_graph(graph),
44 d_matrix(m),
45 color_axis(QwtPlot::yRight),
46 color_map_policy(Default),
47 color_map(LinearColorMap()),
48 d_show_labels(true),
49 d_labels_color(Qt::black),
50 d_labels_font(QFont()),
51 d_white_out_labels(false),
52 d_labels_angle(0.0),
53 d_labels_x_offset(0),
54 d_labels_y_offset(0),
55 d_selected_label(NULL),
56 d_use_matrix_formula(false),
57 d_color_map_pen(false)
58 {
59 setData(MatrixData(m));
60
61 double step = fabs(data().range().maxValue() - data().range().minValue())/5.0;
62
63 QwtValueList contourLevels;
64 for ( double level = data().range().minValue() + step;
65 level < data().range().maxValue(); level += step )
66 contourLevels += level;
67
68 setContourLevels(contourLevels);
69 }
70
updateData()71 void Spectrogram::updateData()
72 {
73 if (!d_matrix || !d_graph)
74 return;
75
76 setData(MatrixData(d_matrix, d_use_matrix_formula));
77
78 QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
79 if (colorAxis)
80 colorAxis->setColorMap(range(), colorMap());
81
82 d_graph->setAxisScale(color_axis, range().minValue(), range().maxValue());
83 d_graph->replot();
84 }
85
range() const86 QwtDoubleInterval Spectrogram::range() const
87 {
88 if (color_map.intensityRange().isValid())
89 return color_map.intensityRange();
90
91 double mmin, mmax;
92 d_matrix->range(&mmin, &mmax);
93 return QwtDoubleInterval(mmin, mmax);
94 }
95
setMatrix(Matrix * m,bool useFormula)96 bool Spectrogram::setMatrix(Matrix *m, bool useFormula)
97 {
98 if (!m)
99 return false;
100
101 if (m == d_matrix && useFormula == d_use_matrix_formula)
102 return true;
103
104 bool changedUseFormula = (useFormula != d_use_matrix_formula) ? true : false;
105 bool canCalculate = false;
106 if (useFormula){
107 canCalculate = m->canCalculate();
108 if (!canCalculate){
109 QMessageBox::warning(d_graph->multiLayer(), QObject::tr("QtiPlot - Script Error"),
110 QObject::tr("Python-like syntax is not supported in this case since it severely reduces drawing speed!"));
111 changedUseFormula = false;
112 d_use_matrix_formula = false;
113 }
114 }
115
116 if (changedUseFormula)
117 d_use_matrix_formula = useFormula;
118
119 bool changedMatrix = (d_matrix != m) ? true : false;
120 if (changedMatrix)
121 d_matrix = m;
122
123 if (changedMatrix || changedUseFormula)
124 updateData();
125
126 if (!canCalculate)
127 return false;
128 return true;
129 }
130
setLevelsNumber(int levels)131 void Spectrogram::setLevelsNumber(int levels)
132 {
133 if (levels <= 0)
134 return;
135
136 double step = fabs(range().maxValue() - range().minValue())/(double)levels;
137
138 QwtValueList contourLevels;
139 for ( double level = range().minValue() + 0.5*step;
140 level < range().maxValue(); level += step )
141 contourLevels += level;
142
143 setContourLevels(contourLevels);
144 }
145
setContourLevels(const QwtValueList & levels)146 void Spectrogram::setContourLevels (const QwtValueList & levels)
147 {
148 QwtPlotSpectrogram::setContourLevels(levels);
149 createLabels();
150 }
151
hasColorScale()152 bool Spectrogram::hasColorScale()
153 {
154 if (!d_graph)
155 return false;
156
157 if (!d_graph->axisEnabled (color_axis))
158 return false;
159
160 QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
161 if (colorAxis)
162 return colorAxis->isColorBarEnabled();
163
164 return false;
165 }
166
showColorScale(int axis,bool on)167 void Spectrogram::showColorScale(int axis, bool on)
168 {
169 if (hasColorScale() == on && color_axis == axis)
170 return;
171
172 if (!d_graph)
173 return;
174
175 QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
176 colorAxis->setColorBarEnabled(false);
177
178 color_axis = axis;
179
180 // We must switch main and the color scale axes and their respective scales
181 int xAxis = this->xAxis();
182 int yAxis = this->yAxis();
183 int oldMainAxis = QwtPlot::xBottom;
184 if (axis == QwtPlot::xBottom || axis == QwtPlot::xTop){
185 oldMainAxis = xAxis;
186 xAxis = 5 - color_axis;
187 } else if (axis == QwtPlot::yLeft || axis == QwtPlot::yRight){
188 oldMainAxis = yAxis;
189 yAxis = 1 - color_axis;
190 }
191
192 // First we switch axes
193 setAxis(xAxis, yAxis);
194
195 // Next we switch axes scales
196 QwtScaleDiv *scDiv = d_graph->axisScaleDiv(oldMainAxis);
197 if (axis == QwtPlot::xBottom || axis == QwtPlot::xTop)
198 d_graph->setAxisScale(xAxis, scDiv->lowerBound(), scDiv->upperBound());
199 else if (axis == QwtPlot::yLeft || color_axis == QwtPlot::yRight)
200 d_graph->setAxisScale(yAxis, scDiv->lowerBound(), scDiv->upperBound());
201
202 colorAxis = d_graph->axisWidget(color_axis);
203 d_graph->setAxisScale(color_axis, range().minValue(), range().maxValue());
204 colorAxis->setColorBarEnabled(on);
205 colorAxis->setColorMap(range(), colorMap());
206 if (!d_graph->axisEnabled(color_axis))
207 d_graph->enableAxis(color_axis);
208 colorAxis->show();
209 d_graph->updateLayout();
210 }
211
colorBarWidth()212 int Spectrogram::colorBarWidth()
213 {
214 if (!d_graph)
215 return 0;
216
217 QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
218 return colorAxis->colorBarWidth();
219 }
220
setColorBarWidth(int width)221 void Spectrogram::setColorBarWidth(int width)
222 {
223 if (!d_graph)
224 return;
225
226 QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
227 colorAxis->setColorBarWidth(width);
228 }
229
copy(Graph * g)230 Spectrogram* Spectrogram::copy(Graph *g)
231 {
232 Spectrogram *new_s = new Spectrogram(g, matrix());
233 new_s->setDisplayMode(QwtPlotSpectrogram::ImageMode, testDisplayMode(QwtPlotSpectrogram::ImageMode));
234 new_s->setDisplayMode(QwtPlotSpectrogram::ContourMode, testDisplayMode(QwtPlotSpectrogram::ContourMode));
235 new_s->setCustomColorMap(color_map);
236 new_s->setAxis(xAxis(), yAxis());
237 new_s->setDefaultContourPen(defaultContourPen());
238 new_s->color_map_policy = color_map_policy;
239 new_s->d_show_labels = d_show_labels;
240 new_s->d_labels_angle = d_labels_angle;
241 new_s->d_labels_color = d_labels_color;
242 new_s->d_white_out_labels = d_white_out_labels;
243 new_s->d_labels_font = d_labels_font;
244 new_s->d_labels_x_offset = d_labels_x_offset;
245 new_s->d_labels_y_offset = d_labels_y_offset;
246 new_s->setContourLevels(contourLevels());
247
248 if (defaultContourPen().style() == Qt::NoPen && !d_color_map_pen)
249 new_s->setContourPenList(d_pen_list);
250 else
251 new_s->d_color_map_pen = d_color_map_pen;
252
253 if (d_labels_list.isEmpty()){
254 new_s->clearLabels();
255 return new_s;
256 }
257
258 QList <PlotMarker *> lst = new_s->labelsList();
259 int count = lst.size();
260 for(int i = 0; i < count; i++){
261 PlotMarker *m = lst[i];
262 PlotMarker *mrk = d_labels_list[i];
263 if (m && mrk)
264 m->setLabelOffset(mrk->xLabelOffset(), mrk->yLabelOffset());
265 }
266
267 return new_s;
268 }
269
setGrayScale()270 void Spectrogram::setGrayScale()
271 {
272 color_map = LinearColorMap(Qt::black, Qt::white);
273 setColorMap(color_map);
274 color_map_policy = GrayScale;
275
276 if (!d_graph)
277 return;
278
279 QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
280 if (colorAxis)
281 colorAxis->setColorMap(range(), colorMap());
282 }
283
setDefaultColorMap()284 void Spectrogram::setDefaultColorMap()
285 {
286 if (!d_graph)
287 return;
288
289 color_map = d_graph->multiLayer()->applicationWindow()->d_3D_color_map;
290 setColorMap(color_map);
291 color_map_policy = Default;
292
293 QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
294 if (colorAxis)
295 colorAxis->setColorMap(range(), colorMap());
296 }
297
setCustomColorMap(const LinearColorMap & map)298 void Spectrogram::setCustomColorMap(const LinearColorMap& map)
299 {
300 setColorMap(map);
301 color_map = map;
302 color_map_policy = Custom;
303
304 if (!d_graph)
305 return;
306
307 QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
308 if (colorAxis)
309 colorAxis->setColorMap(range(), colorMap());
310 }
311
saveToString()312 QString Spectrogram::saveToString()
313 {
314 QString s = "<spectrogram>\n";
315 s += "\t<matrix>" + QString(d_matrix->objectName()) + "</matrix>\n";
316 s += "\t<useMatrixFormula>" + QString::number(d_use_matrix_formula) + "</useMatrixFormula>\n";
317 s += "\t<xAxis>" + QString::number(xAxis()) + "</xAxis>\n";
318 s += "\t<yAxis>" + QString::number(yAxis()) + "</yAxis>\n";
319
320 if (color_map_policy != Custom)
321 s += "\t<ColorPolicy>" + QString::number(color_map_policy) + "</ColorPolicy>\n";
322 else
323 s += color_map.toXmlString();
324 s += "\t<Image>"+QString::number(testDisplayMode(QwtPlotSpectrogram::ImageMode))+"</Image>\n";
325
326 bool contourLines = testDisplayMode(QwtPlotSpectrogram::ContourMode);
327 s += "\t<ContourLines>"+QString::number(contourLines)+"</ContourLines>\n";
328 if (contourLines){
329 QwtValueList levels = contourLevels();
330 s += "\t\t<Levels>" + QString::number(levels.size()) + "</Levels>\n";
331 for (int i = 0; i < levels.size(); i++)
332 s += "\t\t<z>" + QString::number(levels[i]) + "</z>\n";
333
334 bool defaultPen = defaultContourPen().style() != Qt::NoPen;
335 s += "\t\t<DefaultPen>" + QString::number(defaultPen) + "</DefaultPen>\n";
336 if (defaultPen){
337 s += "\t\t\t<PenColor>" + defaultContourPen().color().name() + "</PenColor>\n";
338 s += "\t\t\t<PenWidth>" + QString::number(defaultContourPen().widthF()) + "</PenWidth>\n";
339 s += "\t\t\t<PenStyle>" + QString::number(defaultContourPen().style() - 1) + "</PenStyle>\n";
340 } else if (!d_color_map_pen && !d_pen_list.isEmpty()){
341 s += "\t\t<PenList>\n";
342 for (int i = 0; i < d_pen_list.size(); i++){
343 QPen pen = d_pen_list[i];
344 s += "\t\t\t<pen>" + pen.color().name () + "," + QString::number(pen.widthF()) + ",";
345 s += QString::number(PenStyleBox::styleIndex(pen.style())) + "</pen>\n";
346 }
347 s += "\t\t</PenList>\n";
348 }
349
350 if (d_show_labels){
351 s += "\t\t<Labels>\n";
352 s += "\t\t\t<Color>" + d_labels_color.name() + "</Color>\n";
353 s += "\t\t\t<WhiteOut>" + QString::number(d_white_out_labels) +"</WhiteOut>\n";
354 s += "\t\t\t<Angle>" + QString::number(d_labels_angle) + "</Angle>\n";
355 s += "\t\t\t<xOffset>" + QString::number(d_labels_x_offset) + "</xOffset>\n";
356 s += "\t\t\t<yOffset>" + QString::number(d_labels_y_offset) + "</yOffset>\n";
357 s += "\t\t\t<Font>" + d_labels_font.toString() + "</Font>\n";
358 foreach(PlotMarker *m, d_labels_list){
359 if (m->xLabelOffset() != 0.0 || m->xLabelOffset() != 0.0){
360 s += "\t\t\t<offset>" + QString::number(m->index()) + ",";
361 s += QString::number(m->xLabelOffset()) + ",";
362 s += QString::number(m->yLabelOffset()) + "</offset>\n";
363 }
364 }
365 s += "\t\t</Labels>\n";
366 }
367 }
368
369 QwtScaleWidget *colorAxis = d_graph->axisWidget(color_axis);
370 if (colorAxis && colorAxis->isColorBarEnabled()){
371 s += "\t<ColorBar>\n\t\t<axis>" + QString::number(color_axis) + "</axis>\n";
372 s += "\t\t<width>" + QString::number(colorAxis->colorBarWidth()) + "</width>\n";
373 s += "\t</ColorBar>\n";
374 }
375 s += "\t<Visible>"+ QString::number(isVisible()) + "</Visible>\n";
376 return s+"</spectrogram>\n";
377 }
378
boundingRect() const379 QwtDoubleRect Spectrogram::boundingRect() const
380 {
381 return d_matrix->boundingRect();
382 }
383
createLabels()384 void Spectrogram::createLabels()
385 {
386 clearLabels();
387
388 QwtValueList levels = contourLevels();
389 const int numLevels = levels.size();
390 for (int l = 0; l < numLevels; l++){
391 PlotMarker *m = new PlotMarker(l, d_labels_angle);
392
393 QwtText t = QwtText(QString::number(levels[l]));
394 t.setColor(d_labels_color);
395 t.setFont(d_labels_font);
396
397 if (d_white_out_labels)
398 t.setBackgroundBrush(QBrush(Qt::white));
399 else
400 t.setBackgroundBrush(QBrush(Qt::transparent));
401 m->setLabel(t);
402
403 int x_axis = xAxis();
404 int y_axis = yAxis();
405 m->setAxis(x_axis, y_axis);
406
407 if (d_graph && d_show_labels)
408 m->attach(d_graph);
409 d_labels_list << m;
410 }
411 }
412
showContourLineLabels(bool show)413 void Spectrogram::showContourLineLabels(bool show)
414 {
415 if (show == d_show_labels)
416 return;
417
418 d_show_labels = show;
419
420 foreach(PlotMarker *m, d_labels_list){
421 if (d_show_labels)
422 m->attach(d_graph);
423 else
424 m->detach();
425 }
426 }
427
drawContourLines(QPainter * p,const QwtScaleMap & xMap,const QwtScaleMap & yMap,const QwtRasterData::ContourLines & contourLines) const428 void Spectrogram::drawContourLines (QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QwtRasterData::ContourLines &contourLines) const
429 {
430 QwtValueList levels = contourLevels();
431 const int numLevels = (int)levels.size();
432 for (int l = 0; l < numLevels; l++){
433 const double level = levels[l];
434
435 QPen pen = defaultContourPen();
436 if ( pen.style() == Qt::NoPen )
437 pen = contourPen(level);
438
439 if ( pen.style() == Qt::NoPen )
440 continue;
441
442 p->setPen(QwtPainter::scaledPen(pen));
443
444 const QPolygonF &lines = contourLines[level];
445 for ( int i = 0; i < (int)lines.size(); i += 2 ){
446 const QPointF p1( xMap.xTransform(lines[i].x()),
447 yMap.transform(lines[i].y()) );
448 const QPointF p2( xMap.xTransform(lines[i + 1].x()),
449 yMap.transform(lines[i + 1].y()) );
450
451 p->drawLine(p1, p2);
452 }
453 }
454
455 if (d_show_labels)
456 updateLabels(p, xMap, yMap, contourLines);
457 }
458
updateLabels(QPainter * p,const QwtScaleMap &,const QwtScaleMap &,const QwtRasterData::ContourLines & contourLines) const459 void Spectrogram::updateLabels(QPainter *p, const QwtScaleMap &, const QwtScaleMap &,
460 const QwtRasterData::ContourLines &contourLines) const
461 {
462 QwtValueList levels = contourLevels();
463 const int numLevels = levels.size();
464 int x_axis = xAxis();
465 int y_axis = yAxis();
466 for (int l = 0; l < numLevels; l++){
467 const double level = levels[l];
468 const QPolygonF &lines = contourLines[level];
469 if (lines.isEmpty())
470 continue;
471
472 PlotMarker *mrk = d_labels_list[l];
473 if (!mrk)
474 return;
475
476 QSize size = mrk->label().textSize();
477 int dx = int((d_labels_x_offset + mrk->xLabelOffset())*0.01*size.height());
478 int dy = -int(((d_labels_y_offset + mrk->yLabelOffset())*0.01 + 0.5)*size.height());
479
480 int i = (int)lines.size()/2;
481 double x = lines[i].x();
482 double y = lines[i].y();
483
484 int x2 = d_graph->transform(x_axis, x) + dx;
485 int y2 = d_graph->transform(y_axis, y) + dy;
486
487 if (p->device()->logicalDpiX() == plot()->logicalDpiX() ||
488 p->device()->logicalDpiY() == plot()->logicalDpiY())
489 mrk->setValue(d_graph->invTransform(x_axis, x2),
490 d_graph->invTransform(y_axis, y2));
491 }
492 }
493
setLabelsFont(const QFont & font)494 void Spectrogram::setLabelsFont(const QFont& font)
495 {
496 if (font == d_labels_font)
497 return;
498
499 d_labels_font = font;
500
501 foreach(QwtPlotMarker *m, d_labels_list){
502 QwtText t = m->label();
503 t.setFont(font);
504 m->setLabel(t);
505 }
506 }
507
setLabelsColor(const QColor & c)508 void Spectrogram::setLabelsColor(const QColor& c)
509 {
510 if (c == d_labels_color)
511 return;
512
513 d_labels_color = c;
514
515 foreach(QwtPlotMarker *m, d_labels_list){
516 QwtText t = m->label();
517 t.setColor(c);
518 m->setLabel(t);
519 }
520 }
521
setLabelsWhiteOut(bool whiteOut)522 void Spectrogram::setLabelsWhiteOut(bool whiteOut)
523 {
524 if (whiteOut == d_white_out_labels)
525 return;
526
527 d_white_out_labels = whiteOut;
528
529 foreach(QwtPlotMarker *m, d_labels_list){
530 QwtText t = m->label();
531 if (whiteOut)
532 t.setBackgroundBrush(QBrush(Qt::white));
533 else
534 t.setBackgroundBrush(QBrush(Qt::transparent));
535 m->setLabel(t);
536 }
537 }
538
setLabelsOffset(double x,double y)539 void Spectrogram::setLabelsOffset(double x, double y)
540 {
541 if (x == d_labels_x_offset && y == d_labels_y_offset)
542 return;
543
544 d_labels_x_offset = x;
545 d_labels_y_offset = y;
546 }
547
setLabelOffset(int index,double x,double y)548 void Spectrogram::setLabelOffset(int index, double x, double y)
549 {
550 if (index < 0 || index >= d_labels_list.size())
551 return;
552
553 PlotMarker *m = d_labels_list[index];
554 if (!m)
555 return;
556
557 m->setLabelOffset(x, y);
558 }
559
setLabelsRotation(double angle)560 void Spectrogram::setLabelsRotation(double angle)
561 {
562 if (angle == d_labels_angle)
563 return;
564
565 d_labels_angle = angle;
566
567 foreach(PlotMarker *m, d_labels_list)
568 m->setAngle(angle);
569 }
570
selectedLabels(const QPoint & pos)571 bool Spectrogram::selectedLabels(const QPoint& pos)
572 {
573 d_selected_label = NULL;
574
575 if (d_graph->hasActiveTool())
576 return false;
577
578 foreach(PlotMarker *m, d_labels_list){
579 int x = d_graph->transform(xAxis(), m->xValue());
580 int y = d_graph->transform(yAxis(), m->yValue());
581
582 QMatrix wm;
583 wm.translate(x, y);
584 wm.rotate(-d_labels_angle);
585 if (wm.mapToPolygon(QRect(QPoint(0, 0), m->label().textSize())).containsPoint(pos, Qt::OddEvenFill)){
586 d_selected_label = m;
587 d_click_pos_x = d_graph->invTransform(xAxis(), pos.x());
588 d_click_pos_y = d_graph->invTransform(yAxis(), pos.y());
589 selectLabel(true);
590 return true;
591 }
592 }
593 return false;
594 }
595
selectLabel(bool on)596 void Spectrogram::selectLabel(bool on)
597 {
598 if (on){
599 d_graph->deselect();
600 d_graph->notifyFontChange(d_labels_font);
601 d_graph->notifyColorChange(d_labels_color);
602 }
603
604 foreach(PlotMarker *m, d_labels_list){
605 QwtText t = m->label();
606 if(t.text().isEmpty())
607 return;
608
609 if (d_selected_label && m == d_selected_label && on)
610 t.setBackgroundPen(QPen(Qt::blue));
611 else
612 t.setBackgroundPen(QPen(Qt::NoPen));
613
614 m->setLabel(t);
615 }
616
617 d_graph->replot();
618 }
619
hasSelectedLabels()620 bool Spectrogram::hasSelectedLabels()
621 {
622 /*if (d_labels_list.isEmpty())
623 return false;
624
625 foreach(PlotMarker *m, d_labels_list){
626 if (m->label().backgroundPen() == QPen(Qt::blue))
627 return true;
628 else
629 return false;
630 }
631 return false;*/
632
633 if (d_selected_label)
634 return true;
635 return false;
636 }
637
moveLabel(const QPoint & pos)638 void Spectrogram::moveLabel(const QPoint& pos)
639 {
640 if (!d_selected_label || d_labels_list.isEmpty())
641 return;
642
643 d_graph->replot();
644 int x_axis = xAxis();
645 int y_axis = yAxis();
646
647 int d_x = pos.x() - d_graph->transform(x_axis, d_click_pos_x);
648 int d_y = pos.y() - d_graph->transform(y_axis, d_click_pos_y);
649
650 int height = d_selected_label->label().textSize().height();
651 double x_offset = d_selected_label->xLabelOffset() + d_x*100.0/(double)height;
652 double y_offset = d_selected_label->yLabelOffset() - d_y*100.0/(double)height;
653
654 d_selected_label->setLabelOffset(x_offset, y_offset);
655
656 d_graph->replot();
657 d_graph->notifyChanges();
658
659 d_click_pos_x = d_graph->invTransform(x_axis, pos.x());
660 d_click_pos_y = d_graph->invTransform(y_axis, pos.y());
661 }
662
clearLabels()663 void Spectrogram::clearLabels()
664 {
665 foreach(PlotMarker *m, d_labels_list){
666 m->detach();
667 delete m;
668 }
669 d_labels_list.clear();
670 }
671
setVisible(bool on)672 void Spectrogram::setVisible(bool on)
673 {
674 QwtPlotItem::setVisible(on);
675 foreach(PlotMarker *m, d_labels_list)
676 m->setVisible(on);
677 }
678
contourPen(double level) const679 QPen Spectrogram::contourPen (double level) const
680 {
681 if (d_color_map_pen)
682 return QwtPlotSpectrogram::contourPen(level);
683
684 QwtValueList levels = contourLevels();
685 int index = levels.indexOf (level);
686 if (index >= 0 && index < d_pen_list.size())
687 return d_pen_list[index];
688
689 return QPen();
690 }
691
setColorMapPen(bool on)692 void Spectrogram::setColorMapPen(bool on)
693 {
694 d_color_map_pen = on;
695 if (on) {
696 setDefaultContourPen(Qt::NoPen);
697 d_pen_list.clear();
698 }
699 }
700
setContourPenList(QList<QPen> lst)701 void Spectrogram::setContourPenList(QList<QPen> lst)
702 {
703 d_pen_list = lst;
704 setDefaultContourPen(Qt::NoPen);
705 d_color_map_pen = false;
706 }
707
setContourLinePen(int index,const QPen & pen)708 void Spectrogram::setContourLinePen(int index, const QPen &pen)
709 {
710 QwtValueList levels = contourLevels();
711 if (index < 0 || index >= levels.size())
712 return;
713
714 if (d_pen_list.isEmpty()){
715 QPen p = defaultContourPen();
716 for (int i = 0; i < levels.size(); i++){
717 if (p.style() == Qt::NoPen)
718 d_pen_list << contourPen(levels[i]);
719 else
720 d_pen_list << p;
721 }
722 }
723
724 d_pen_list[index] = pen;
725 setDefaultContourPen(Qt::NoPen);
726 d_color_map_pen = false;
727 d_graph->replot();
728 }
729
setUseMatrixFormula(bool on)730 bool Spectrogram::setUseMatrixFormula(bool on)
731 {
732 if (on && !d_matrix->canCalculate())
733 return false;
734
735 d_use_matrix_formula = on;
736 updateData();
737 return true;
738 }
739
renderImage(const QwtScaleMap & xMap,const QwtScaleMap & yMap,const QwtDoubleRect & area) const740 QImage Spectrogram::renderImage(const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QwtDoubleRect &area) const
741 {
742 if (area.isEmpty())
743 return QImage();
744
745 QRect rect = transform(xMap, yMap, area);
746
747 QwtScaleMap xxMap = xMap;
748 QwtScaleMap yyMap = yMap;
749
750 MatrixData *d_data = (MatrixData *)data().copy();
751 const QSize res = d_data->rasterHint(area);
752 if (res.isValid()){
753 rect.setSize(rect.size().boundedTo(res));
754
755 int px1 = rect.x();
756 int px2 = rect.x() + rect.width();
757 if ( xMap.p1() > xMap.p2() )
758 qSwap(px1, px2);
759
760 double sx1 = area.x();
761 double sx2 = area.x() + area.width();
762 if ( xMap.s1() > xMap.s2() )
763 qSwap(sx1, sx2);
764
765 int py1 = rect.y();
766 int py2 = rect.y() + rect.height();
767 if ( yMap.p1() > yMap.p2() )
768 qSwap(py1, py2);
769
770 double sy1 = area.y();
771 double sy2 = area.y() + area.height();
772 if ( yMap.s1() > yMap.s2() )
773 qSwap(sy1, sy2);
774
775 xxMap.setPaintInterval(px1, px2);
776 xxMap.setScaleInterval(sx1, sx2);
777 yyMap.setPaintInterval(py1, py2);
778 yyMap.setScaleInterval(sy1, sy2);
779 }
780
781 QImage image(rect.size(), QImage::Format_ARGB32);
782
783 const QwtDoubleInterval intensityRange = range();
784 if(!intensityRange.isValid())
785 return image;
786
787 d_data->initRaster(area, rect.size());
788
789 for (int y = rect.top(); y <= rect.bottom(); y++){
790 const double ty = yyMap.invTransform(y);
791 QRgb *line = (QRgb *)image.scanLine(y - rect.top());
792 for (int x = rect.left(); x <= rect.right(); x++){
793 const double tx = xxMap.invTransform(x);
794 *line++ = color_map.rgb(intensityRange, d_data->value(tx, ty));
795 }
796 }
797
798 d_data->discardRaster();
799
800 // Mirror the image in case of inverted maps
801 const bool hInvert = xxMap.p1() > xxMap.p2();
802 const bool vInvert = yyMap.p1() < yyMap.p2();
803 if (hInvert || vInvert)
804 image = image.mirrored(hInvert, vInvert);
805
806 return image;
807 }
808
value(double x,double y) const809 double MatrixData::value(double x, double y) const
810 {
811 x += 0.5*dx;
812 y -= 0.5*dy;
813
814 int i = qRound(fabs((y - y_start)/dy));
815 int j = qRound(fabs((x - x_start)/dx));
816
817 if (d_mup){
818 *d_y = y;
819 *d_x = x;
820 *d_ri = i;
821 *d_rr = i;
822 *d_cj = j;
823 *d_cc = j;
824
825 if (d_mup->codeLines() == 1)
826 return d_mup->evalSingleLine();
827 else
828 return d_mup->eval().toDouble();
829 } else
830 return d_matrix->cell(i, j);
831
832 return 0.0;
833 }
834