- Integrated the file import into the main interface (not as a plugin anymore)
[mldemos:mldemos.git] / Core / canvas.cpp
1 /*********************************************************************
2 MLDemos: A User-Friendly visualization toolkit for machine learning
3 Copyright (C) 2010  Basilio Noris
4 Contact: mldemos@b4silio.com
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free
18 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *********************************************************************/
20 #include <QtGui>
21 #include <QWidget>
22 #include <QSize>
23 #include <QPixmap>
24 #include <QPainter>
25 #include <QPen>
26 #include <QImage>
27 #include <iostream>
28
29 #include "expose.h"
30 #include "public.h"
31 #include "basicMath.h"
32 #include "canvas.h"
33 #include "drawUtils.h"
34
35 using namespace std;
36
37 //DatasetManager Canvas::data;
38 bool Canvas::bCrossesAsDots = true;
39
40 Canvas::Canvas(QWidget *parent)
41         : QWidget(parent),
42           bDisplayMap(false),
43           bDisplayInfo(false),
44           bDisplaySingle(false),
45           bDisplaySamples(true),
46           bDisplayTrajectories(true),
47           bDisplayTimeSeries(true),
48           bDisplayLearned(true),
49           bDisplayGrid(true),
50           crosshair(QPainterPath()),
51           bShowCrosshair(false),
52           bNewCrosshair(true),
53           trajectoryCenterType(0),
54           trajectoryResampleType(1),
55           trajectoryResampleCount(100),
56           liveTrajectory(vector<fvec>()),
57           centers(map<int,fvec>()),
58           drawnSamples(0),
59           drawnTrajectories(0),
60           drawnTimeseries(0),
61           mouseAnchor(QPoint(-1,-1)),
62           bDrawing(false),
63           zoom(1.f),
64           zooms(2,1.f),
65           center(2,0),
66       xIndex(0), yIndex(1), zIndex(-1),
67       canvasType(0),
68           data(new DatasetManager())
69 {
70         resize(640,480);
71         setAcceptDrops(true);
72
73         setMouseTracking(true);
74         setCursor(Qt::CrossCursor);
75         setBackgroundRole(QPalette::Base);
76         setMouseTracking(true);
77
78         QPalette p(palette());
79         p.setColor(backgroundRole(), Qt::white);
80         setPalette(p);
81         show();
82 }
83
84 Canvas::~Canvas()
85 {
86         if(data) DEL(data);
87 }
88
89 void Canvas::dragEnterEvent(QDragEnterEvent *event)
90 {
91         if (event->mimeData()->hasFormat("text/plain")) event->acceptProposedAction();
92 }
93
94 void Canvas::dropEvent(QDropEvent *event)
95 {
96         if(event->mimeData()->text() == "Target")
97         {
98                 QPointF position = event->pos();
99                 //qDebug() << "Dropping Target at coordinates: " << position;
100                 targets.push_back(toSampleCoords(position.x(), position.y()));
101         }
102         else if(event->mimeData()->text() == "Gaussian")
103         {
104                 QPointF position = event->pos();
105                 double variance = event->mimeData()->colorData().toDouble();
106                 PaintGaussian(position, variance);
107         }
108         else if(event->mimeData()->text() == "Gradient")
109         {
110                 QPointF position = event->pos();
111                 PaintGradient(position);
112         }
113         event->acceptProposedAction();
114 }
115
116 void Canvas::SetConfidenceMap(QImage image)
117 {
118         maps.confidence = QPixmap::fromImage(image);
119         repaint();
120 }
121
122 void Canvas::SetModelImage(QImage image)
123 {
124         maps.model = QPixmap::fromImage(image);
125         repaint();
126 }
127
128 void Canvas::SetCanvasType(int type)
129 {
130     if(canvasType || type)
131     {
132         maps.model = QPixmap();
133         maps.info = QPixmap();
134     }
135     maps.samples = QPixmap();
136     maps.trajectories = QPixmap();
137     maps.grid = QPixmap();
138     canvasType = type;
139     ResetSamples();
140     bNewCrosshair = true;
141 }
142
143 void Canvas::PaintStandard(QPainter &painter, bool bSvg)
144 {
145         painter.setBackgroundMode(Qt::OpaqueMode);
146         painter.setBackground(Qt::white);
147
148         painter.fillRect(geometry(),Qt::white);
149
150     if(bDisplayMap)
151         {
152                 if(!maps.confidence.isNull()) painter.drawPixmap(geometry(), maps.confidence);
153         }
154         painter.setRenderHint(QPainter::Antialiasing);
155         painter.setRenderHint(QPainter::HighQualityAntialiasing);
156
157         if(bDisplaySamples)
158         {
159                 DrawRewards();
160                 if(!maps.reward.isNull())
161                 {
162                         painter.setBackgroundMode(Qt::TransparentMode);
163                         painter.drawPixmap(geometry(), maps.reward);
164                 }
165                 if(bSvg) DrawSamples(painter);
166                 else
167                 {
168                         DrawSamples();
169                         painter.setBackgroundMode(Qt::TransparentMode);
170                         painter.drawPixmap(geometry(), maps.samples);
171                 }
172                 DrawObstacles(painter);
173                 //painter.drawPixmap(geometry(), maps.obstacles);
174         }
175     if(bDisplayTrajectories)
176         {
177                 if(bSvg)
178                 {
179                         DrawTrajectories(painter);
180                 }
181                 else
182                 {
183                         DrawTrajectories();
184                         painter.setBackgroundMode(Qt::TransparentMode);
185                         painter.drawPixmap(geometry(), maps.trajectories);
186                 }
187                 if(targets.size()) DrawTargets(painter);
188         }
189     if(bDisplayTimeSeries)
190         {
191                 if(bSvg)
192                 {
193
194                 }
195                 else
196                 {
197                         DrawTimeseries();
198                         painter.setBackgroundMode(Qt::TransparentMode);
199                         painter.drawPixmap(geometry(), maps.timeseries);
200                 }
201         }
202     if(!bSvg && bDisplayLearned)
203         {
204         if(maps.model.isNull())
205         {
206             int w = width();
207             int h = height();
208             maps.model = QPixmap(w,h);
209             QBitmap bitmap(w,h);
210             bitmap.clear();
211             maps.model.setMask(bitmap);
212             maps.model.fill(Qt::transparent);
213             QPainter painter(&maps.model);
214             DrawSampleColors(painter);
215         }
216                 painter.setBackgroundMode(Qt::TransparentMode);
217                 painter.drawPixmap(geometry(), maps.model);
218         }
219         if(!bSvg && bDisplayInfo && !maps.info.isNull())
220         {
221                 painter.setBackgroundMode(Qt::TransparentMode);
222                 painter.drawPixmap(geometry(), maps.info);
223         }
224         if(!bSvg && bShowCrosshair)
225         {
226                 if(bNewCrosshair) emit DrawCrosshair();
227                 painter.setBackgroundMode(Qt::TransparentMode);
228                 painter.drawPath(crosshair.translated(mouse));
229                 if(liveTrajectory.size()) DrawLiveTrajectory(painter);
230         }
231         if(bDisplayGrid)
232         {
233                 if(bSvg)
234                 {
235                 }
236                 else
237                 {
238                         if(maps.grid.isNull()) RedrawAxes();
239                         painter.setBackgroundMode(Qt::TransparentMode);
240                         painter.drawPixmap(geometry(), maps.grid);
241                 }
242         }
243 }
244
245 void Canvas::PaintMultivariate(QPainter &painter, int type)
246 {
247     painter.setBackgroundMode(Qt::OpaqueMode);
248     painter.setBackground(Qt::white);
249
250     painter.fillRect(geometry(),Qt::white);
251
252     std::pair<fvec,fvec> bounds = data->GetBounds();
253
254     if(bDisplaySamples)
255     {
256         if(maps.samples.isNull())
257         {
258             int w = width();
259             int h = height();
260             maps.samples = QPixmap(w,h);
261             QBitmap bitmap(w,h);
262             bitmap.clear();
263             maps.samples.setMask(bitmap);
264             maps.samples.fill(Qt::transparent);
265             Expose::DrawData(maps.samples, data->GetSamples(), data->GetLabels(), data->GetFlags(), type, data->bProjected, dimNames, bounds);
266         }
267         painter.setBackgroundMode(Qt::TransparentMode);
268         painter.drawPixmap(geometry(), maps.samples);
269     }
270     if(bDisplayTrajectories && (type != 1 && type != 3))
271     {
272         if(maps.trajectories.isNull())
273         {
274             int w = width();
275             int h = height();
276             maps.trajectories = QPixmap(w,h);
277             QBitmap bitmap(w,h);
278             bitmap.clear();
279             maps.trajectories.setMask(bitmap);
280             maps.trajectories.fill(Qt::transparent);
281             Expose::DrawTrajectories(maps.trajectories, data->GetTrajectories(trajectoryResampleType, trajectoryResampleCount, trajectoryCenterType, 0.1, true), data->GetLabels(), type, 0, bounds);
282         }
283         painter.setBackgroundMode(Qt::TransparentMode);
284         painter.drawPixmap(geometry(), maps.trajectories);
285     }
286     if(bDisplayLearned)
287     {
288         if(maps.model.isNull() && sampleColors.size())
289         {
290             int w = width();
291             int h = height();
292             maps.model = QPixmap(w,h);
293             QBitmap bitmap(w,h);
294             bitmap.clear();
295             maps.model.setMask(bitmap);
296             maps.model.fill(Qt::transparent);
297             Expose::DrawData(maps.model, data->GetSamples(), sampleColors, data->GetFlags(), type, data->bProjected, true, dimNames);
298         }
299         painter.setBackgroundMode(Qt::TransparentMode);
300         painter.drawPixmap(geometry(), maps.model);
301     }
302     if(bDisplayInfo && !maps.info.isNull())
303     {
304         //painter.setBackgroundMode(Qt::TransparentMode);
305         //painter.drawPixmap(geometry(), maps.info);
306     }
307     if(bDisplayGrid)
308     {
309         if(maps.grid.isNull())
310         {
311         }
312         painter.setBackgroundMode(Qt::TransparentMode);
313         painter.drawPixmap(geometry(), maps.grid);
314     }
315 }
316
317 void Canvas::PaintVariable(QPainter &painter, int type, fvec params)
318 {
319     painter.setBackgroundMode(Qt::OpaqueMode);
320     painter.setBackground(Qt::white);
321     painter.fillRect(geometry(),Qt::white);
322
323     if(maps.samples.isNull())
324     {
325         int w = width();
326         int h = height();
327         maps.samples = QPixmap(w,h);
328         QBitmap bitmap(w,h);
329         bitmap.clear();
330         maps.samples.setMask(bitmap);
331         maps.samples.fill(Qt::transparent);
332         Expose::DrawVariableData(maps.samples, data->GetSamples(), data->GetLabels(), type, params, data->bProjected);
333     }
334     painter.setBackgroundMode(Qt::TransparentMode);
335     painter.drawPixmap(geometry(), maps.samples);
336
337     if(maps.trajectories.isNull())
338     {
339         int w = width();
340         int h = height();
341         maps.trajectories = QPixmap(w,h);
342         QBitmap bitmap(w,h);
343         bitmap.clear();
344         maps.trajectories.setMask(bitmap);
345         maps.trajectories.fill(Qt::transparent);
346     }
347     painter.setBackgroundMode(Qt::TransparentMode);
348     painter.drawPixmap(geometry(), maps.trajectories);
349
350     if(maps.model.isNull() && sampleColors.size())
351     {
352         int w = width();
353         int h = height();
354         maps.model = QPixmap(w,h);
355         QBitmap bitmap(w,h);
356         bitmap.clear();
357         maps.model.setMask(bitmap);
358         maps.model.fill(Qt::transparent);
359         Expose::DrawVariableData(maps.model, data->GetSamples(), sampleColors, type, params, data->bProjected);
360     }
361     painter.setBackgroundMode(Qt::TransparentMode);
362     painter.drawPixmap(geometry(), maps.model);
363
364 }
365 void Canvas::paintEvent(QPaintEvent *event)
366 {
367         if(bDrawing) return;
368         bDrawing = true;
369         QPainter painter(this);
370     if(!canvasType) PaintStandard(painter);
371     else if(canvasType <= 4) PaintMultivariate(painter, canvasType-1);
372     else
373     {
374         fvec params;
375         params.push_back(xIndex);
376         params.push_back(yIndex);
377         params.push_back(zIndex);
378         PaintVariable(painter, canvasType-5, params);
379     }
380
381         bDrawing = false;
382 }
383
384 QPointF Canvas::toCanvasCoords(fvec sample)
385 {
386     if(sample.size() < center.size()) return QPointF(0,0);
387     //else if(sample.size() > center.size()) center = fvec(sample.size(), 0);
388         sample -= center;
389         QPointF point(sample[xIndex]*(zoom*zooms[xIndex]*height()),sample[yIndex]*(zoom*zooms[yIndex]*height()));
390         point += QPointF(width()/2, height()/2);
391         return point;
392 }
393
394 QPointF Canvas::toCanvas(fVec sample)
395 {
396         sample -= center;
397         QPointF point(sample[xIndex]*(zoom*zooms[xIndex]*height()),sample[yIndex]*(zoom*zooms[yIndex]*height()));
398         point += QPointF(width()/2, height()/2);
399         return point;
400 }
401
402 QPointF Canvas::toCanvasCoords(float x, float y)
403 {
404         x -= center[xIndex];
405         y -= center[yIndex];
406         QPointF point(x*(zoom*zooms[xIndex]*height()),y*(zoom*zooms[yIndex]*height()));
407         point += QPointF(width()/2, height()/2);
408         return point;
409 }
410
411 fvec Canvas::fromCanvas(QPointF point)
412 {
413         int dim = data->GetDimCount();
414         fvec sample(dim);
415         point -= QPointF(width()/2.f,height()/2.f);
416         sample[xIndex] = point.x()/(zoom*zooms[xIndex]*height());
417         sample[yIndex] = point.y()/(zoom*zooms[yIndex]*height());
418         sample += center;
419         return sample;
420 }
421
422 fvec Canvas::fromCanvas(float x, float y)
423 {
424         int dim = data->GetDimCount();
425         fvec sample(dim);
426         x -= width()/2.f;
427         y -= height()/2.f;
428         sample[xIndex] = x/(zoom*zooms[xIndex]*height());
429         sample[yIndex] = y/(zoom*zooms[yIndex]*height());
430         sample += center;
431         return sample;
432 }
433
434 fvec Canvas::toSampleCoords(QPointF point)
435 {
436         int dim = data->GetDimCount();
437         fvec sample(dim);
438         point -= QPointF(width()/2.f,height()/2.f);
439         sample[xIndex] = point.x()/(zoom*zooms[xIndex]*height());
440         sample[yIndex] = point.y()/(zoom*zooms[yIndex]*height());
441         sample += center;
442         return sample;
443 }
444
445 fvec Canvas::toSampleCoords(float x, float y)
446 {
447         int dim = data->GetDimCount();
448         fvec sample(dim);
449         x -= width()/2.f;
450         y -= height()/2.f;
451         sample[xIndex] = x/(zoom*zooms[xIndex]*height());
452         sample[yIndex] = y/(zoom*zooms[yIndex]*height());
453         sample += center;
454         return sample;
455 }
456
457 fvec Canvas::canvasTopLeft()
458 {
459         return toSampleCoords(0,0);
460 }
461
462 fvec Canvas::canvasBottomRight()
463 {
464         return toSampleCoords(width()-1,height()-1);
465 }
466
467 QRectF Canvas::canvasRect()
468 {
469         fvec tl = canvasTopLeft();
470         fvec br = canvasBottomRight();
471         return QRectF(tl[xIndex], tl[yIndex], (br-tl)[xIndex], (br-tl)[yIndex]);
472 }
473
474 void Canvas::SetZoom(float zoom)
475 {
476         if(this->zoom == zoom) return;
477         this->zoom = zoom;
478 //      int dim = data->GetDimCount();
479 //      zooms = fvec(dim,1.f);
480         maps.grid = QPixmap();
481         maps.model = QPixmap();
482         maps.confidence = QPixmap();
483         //maps.reward = QPixmap();
484         maps.info = QPixmap();
485         ResetSamples();
486         bNewCrosshair = true;
487         //repaint();
488 }
489
490 void Canvas::SetZoom(fvec zooms)
491 {
492         if(this->zooms == zooms) return;
493         this->zooms = zooms;
494         zoom = 1.f;
495         maps.grid = QPixmap();
496         maps.model = QPixmap();
497         maps.confidence = QPixmap();
498         //maps.reward = QPixmap();
499         maps.info = QPixmap();
500         ResetSamples();
501         bNewCrosshair = true;
502         //repaint();
503 }
504
505 void Canvas::SetCenter(fvec center)
506 {
507         if(this->center == center) return;
508         this->center = center;
509         maps.grid = QPixmap();
510         maps.model = QPixmap();
511         maps.confidence = QPixmap();
512         //maps.reward = QPixmap();
513         maps.info = QPixmap();
514         ResetSamples();
515         bNewCrosshair = true;
516         //repaint();
517 }
518
519 void Canvas::SetDim(int xIndex, int yIndex, int zIndex)
520 {
521         bool bChanged = false;
522         if(this->xIndex != xIndex)
523         {
524                 bChanged = true;
525                 this->xIndex = xIndex;
526         }
527         if(this->yIndex != yIndex)
528         {
529                 bChanged = true;
530                 this->yIndex = yIndex;
531         }
532     this->zIndex = zIndex;
533         if(bChanged)
534         {
535                 maps.grid = QPixmap();
536                 maps.model = QPixmap();
537                 maps.confidence = QPixmap();
538                 //maps.reward = QPixmap();
539                 maps.info = QPixmap();
540                 ResetSamples();
541                 bNewCrosshair = true;
542                 //repaint();
543         }
544 }
545
546 void Canvas::FitToData()
547 {
548         if(!data->GetCount() && !data->GetTimeSeries().size())
549         {
550                 center = fvec(2,0);
551                 SetZoom(1);
552         //qDebug() << "nothing to fit";
553                 return;
554         }
555         int dim = data->GetDimCount();
556         center = fvec(dim,0);
557     //qDebug() << "fit to data, dim: " << dim;
558
559         // we go through all the data and find the boundaries
560     std::pair<fvec,fvec> bounds = data->GetBounds();
561     fvec mins = bounds.first, maxes = bounds.second;
562         vector<fvec> samples = data->GetSamples();
563
564     vector<TimeSerie>& series = data->GetTimeSeries();
565         FOR(i, series.size())
566         {
567                 TimeSerie& serie = series[i];
568                 mins[0] = 0;
569                 maxes[0] = 1;
570                 center[0] = 0.5f;
571                 FOR(j, serie.size())
572                 {
573                         int dim = serie[j].size();
574                         FOR(d,dim)
575                         {
576                                 if(mins[d+1] > serie[j][d]) mins[d+1] = serie[j][d];
577                                 if(maxes[d+1] < serie[j][d]) maxes[d+1] = serie[j][d];
578                         }
579                 }
580         }
581         fvec diff = maxes - mins;
582
583         center = mins + diff/2;
584
585         /*
586         float diffX = diff[xIndex]*1.04; // add a small margin
587         float diffY = diff[yIndex]*1.04; // add a small margin
588         float aspectRatio = width() / (float)height();
589         diffX /= aspectRatio;
590         SetZoom(min(1/diffY,1/diffX));
591         */
592
593     zooms = fvec(dim, 1.f);
594     FOR(d, dim) zooms[d] = 1.f / diff[d];
595     SetZoom(1.f);
596 }
597
598 void Canvas::DrawAxes(QPainter &painter)
599 {
600         int w = width();
601         int h = height();
602         // we find out how 'big' the space is
603         QRectF bounding = canvasRect();
604         // we round up the size to the closest decimal
605         float scale = bounding.height();
606     if(scale <= 1e-10) return;
607         float mult = 1;
608         if(scale > 10)
609         {
610                 while(scale / mult > 10 && mult != 0) mult *= 2.5f; // we want at most 10 lines to draw
611         }
612         else
613         {
614                 while(scale / mult < 5 && mult != 0) mult /= 2.f; // we want at least 5 lines to draw
615         }
616         if(mult == 0) mult = 1;
617
618         // we now have the measure of the ticks, we can draw this
619         painter.setRenderHint(QPainter::TextAntialiasing);
620         painter.setFont(QFont("Lucida Grande", 9));
621         for(float x = (int)(bounding.x()/mult)*mult; x < bounding.x() + bounding.width(); x += mult)
622         {
623                 float canvasX = toCanvasCoords(x,0).x();
624                 if(canvasX < 0 || canvasX > w) continue;
625                 painter.setPen(QPen(Qt::black, 0.5, Qt::DotLine));
626                 painter.drawLine(canvasX, 0, canvasX, h);
627                 painter.setPen(QPen(Qt::black, 0.5));
628                 painter.drawText(canvasX, h-5, QString("%1").arg((int)(x/mult)*mult));
629         }
630         // we now have the measure of the ticks, we can draw this
631         for(float y = (int)(bounding.y()/mult)*mult; y < bounding.y() + bounding.height(); y += mult)
632         {
633                 float canvasY = toCanvasCoords(0,y).y();
634                 if(canvasY < 0 || canvasY > w) continue;
635                 painter.setPen(QPen(Qt::black, 0.5, Qt::DotLine));
636                 painter.drawLine(0, canvasY, w, canvasY);
637                 painter.setPen(QPen(Qt::black, 0.5));
638                 painter.drawText(2, canvasY, QString("%1").arg((int)(y/mult)*mult));
639         }
640 }
641
642 void Canvas::RedrawAxes()
643 {
644         int w = width();
645         int h = height();
646         maps.grid = QPixmap(w,h);
647         QBitmap bitmap(w,h);
648         bitmap.clear();
649         maps.grid.setMask(bitmap);
650         maps.grid.fill(Qt::transparent);
651
652         QPainter painter(&maps.grid);
653         DrawAxes(painter);
654 }
655
656 void Canvas::DrawSamples(QPainter &painter)
657 {
658         int radius = 10;
659         painter.setRenderHint(QPainter::Antialiasing, true);
660         painter.setRenderHint(QPainter::HighQualityAntialiasing);
661         for(int i=0; i<data->GetCount(); i++)
662         {
663                 if(data->GetFlag(i) == _TRAJ) continue;
664                 int label = data->GetLabel(i);
665                 QPointF point = toCanvasCoords(data->GetSample(i));
666                 Canvas::drawSample(painter, point, (data->GetFlag(i)==_TRAJ)?5:radius, bDisplaySingle ? 0 : label);
667         }
668 }
669
670 void Canvas::DrawSampleColors(QPainter &painter)
671 {
672     int radius = 10;
673     painter.setRenderHint(QPainter::Antialiasing, true);
674     painter.setRenderHint(QPainter::HighQualityAntialiasing);
675     for(int i=0; i<data->GetCount(); i++)
676     {
677         if(i >= sampleColors.size()) continue;
678         QColor color = sampleColors[i];
679         QPointF point = toCanvasCoords(data->GetSample(i));
680         painter.setBrush(color);
681         painter.setPen(Qt::black);
682         painter.drawEllipse(QRectF(point.x()-radius/2.,point.y()-radius/2.,radius,radius));
683     }
684 }
685
686 void Canvas::DrawSamples()
687 {
688         int radius = 10;
689         if(!data->GetCount())
690         {
691                 int w = width();
692                 int h = height();
693                 maps.samples = QPixmap(w,h);
694                 QBitmap bitmap(w,h);
695                 bitmap.clear();
696                 maps.samples.setMask(bitmap);
697                 maps.samples.fill(Qt::transparent);
698                 drawnSamples = 0;
699                 return;
700         }
701         if(drawnSamples == data->GetCount()) return;
702         if(drawnSamples > data->GetCount()) drawnSamples = 0;
703
704         if(!drawnSamples || maps.samples.isNull())
705         {
706                 int w = width();
707                 int h = height();
708                 maps.samples = QPixmap(w,h);
709                 QBitmap bitmap(w,h);
710                 bitmap.clear();
711                 maps.samples.setMask(bitmap);
712                 maps.samples.fill(Qt::transparent);
713                 drawnSamples = 0;
714         }
715         QPainter painter(&maps.samples);
716         painter.setRenderHint(QPainter::Antialiasing, true);
717         painter.setRenderHint(QPainter::HighQualityAntialiasing);
718         for(int i=drawnSamples; i<data->GetCount(); i++)
719         {
720                 if(data->GetFlag(i) == _TRAJ) continue;
721                 int label = data->GetLabel(i);
722         fvec sample = data->GetSample(i);
723         QPointF point = toCanvasCoords(sample);
724                 Canvas::drawSample(painter, point, (data->GetFlag(i)==_TRAJ)?5:radius, bDisplaySingle ? 0 : label);
725         }
726         drawnSamples = data->GetCount();
727 }
728
729 void Canvas::DrawTargets(QPainter &painter)
730 {
731         painter.setRenderHint(QPainter::Antialiasing, true);
732         FOR(i, targets.size())
733         {
734                 QPointF point = toCanvasCoords(targets[i]);
735                 QPointF delta1 = QPointF(1,1);
736                 QPointF delta2 = QPointF(1,-1);
737                 painter.setBrush(Qt::NoBrush);
738                 painter.setPen(QPen(Qt::black, 1.5));
739                 int r = 8, p = 2;
740                 painter.drawEllipse(point,r,r);
741                 painter.drawLine(point+delta1*r, point+delta1*r+delta1*p);
742                 painter.drawLine(point-delta1*r, point-delta1*r-delta1*p);
743                 painter.drawLine(point+delta2*r, point+delta2*r+delta2*p);
744                 painter.drawLine(point-delta2*r, point-delta2*r-delta2*p);
745         }
746 }
747
748 QPainterPath Canvas::DrawObstacle(Obstacle o)
749 {
750         QPointF point;
751         float aX = o.axes[0];
752         float aY = o.axes[1];
753         float angle = o.angle;
754         float pX = o.power[0];
755         float pY = o.power[1];
756         QPainterPath obstaclePath;
757         QPointF firstPoint;
758         // first we draw the obstacle
759         for(float theta=-PIf; theta < PIf + 0.1; theta += 0.1f)
760         {
761                 float X, Y;
762                 X = aX * cosf(theta);
763                 //Y = aY * sinf(theta);
764                 Y = aY * (theta>=0?1.f:-1.f) * powf((1-powf(cosf(theta),2.f*pX)),1./(2*pY));
765
766                 float RX = + X * cosf(angle) - Y * sinf(angle);
767                 float RY = + X * sinf(angle) + Y * cosf(angle);
768
769                 point = QPointF(RX*(zoom*zooms[xIndex]*height()),RY*(zoom*zooms[yIndex]*height()));
770                 if(theta==-PIf)
771                 {
772                         firstPoint = point;
773                         obstaclePath.moveTo(point);
774                         continue;
775                 }
776                 obstaclePath.lineTo(point);
777         }
778         obstaclePath.lineTo(firstPoint);
779         return obstaclePath;
780 }
781
782 void Canvas::DrawObstacles(QPainter &painter)
783 {
784         painter.setRenderHint(QPainter::Antialiasing);
785         painter.setRenderHint(QPainter::HighQualityAntialiasing);
786         // we draw the obstacles
787         if(!data->GetObstacles().size()) return;
788         QList<QPainterPath> paths;
789         QList<QPainterPath> safeties;
790         FOR(i, data->GetObstacles().size())
791         {
792                 QPainterPath obstaclePath = DrawObstacle(data->GetObstacle(i));
793                 obstaclePath.translate(toCanvasCoords(data->GetObstacle(i).center));
794                 paths.push_back(obstaclePath);
795                 obstaclePath = DrawObstacle(data->GetObstacle(i));
796
797                 QMatrix scalingMatrix;
798                 QPointF t = toCanvasCoords(data->GetObstacle(i).center);
799                 scalingMatrix.scale(data->GetObstacle(i).repulsion[0], data->GetObstacle(i).repulsion[1]);
800                 obstaclePath = scalingMatrix.map(obstaclePath);
801                 obstaclePath.translate(toCanvasCoords(data->GetObstacle(i).center));
802                 safeties.push_back(obstaclePath);
803         }
804         FOR(i, paths.size())
805         {
806                 painter.setBrush(Qt::white);
807                 painter.setPen(QPen(Qt::black, 1,Qt::SolidLine));
808                 painter.drawPath(paths[i]);
809                 painter.setBrush(Qt::NoBrush);
810                 painter.setPen(QPen(Qt::black, 1,Qt::DotLine));
811                 painter.drawPath(safeties[i]);
812         }
813 }
814
815 void Canvas::DrawObstacles()
816 {
817         int w = width();
818         int h = height();
819         maps.obstacles = QPixmap(w,h);
820         QBitmap bitmap(w,h);
821         bitmap.clear();
822         maps.obstacles.setMask(bitmap);
823         maps.obstacles.fill(Qt::transparent);
824
825         QPainter painter(&maps.obstacles);
826         DrawObstacles(painter);
827 }
828
829 void Canvas::DrawRewards()
830 {
831         return;
832         int w = width();
833         int h = height();
834         maps.reward= QPixmap(w,h);
835         QBitmap bitmap(w,h);
836         bitmap.clear();
837         maps.reward.setMask(bitmap);
838         maps.reward.fill(Qt::transparent);
839
840         if(!data->GetReward()->rewards) return;
841
842         QPainter painter(&maps.reward);
843         painter.setRenderHint(QPainter::Antialiasing);
844         painter.setRenderHint(QPainter::HighQualityAntialiasing);
845
846         int radius = 10;
847         int stepsW = w/radius;
848         int stepsH = h/radius;
849         //int radius = min(w,h) / steps;
850         // we draw the rewards
851         QColor color;
852         fvec sample(2);
853         FOR(i, stepsH)
854         {
855                 float y = i/(float)stepsH*h;
856                 FOR(j, stepsW)
857                 {
858                         float x = j/(float)stepsW*w;
859                         float value = data->GetReward()->ValueAt(toSampleCoords(x,y));
860                         if(value > 0) color = QColor(255, 255 - (int)(max(0.f,min(1.f, value)) * 255), 255 - (int)(max(0.f,min(1.f, value)) * 255));
861                         else color = QColor(255 - (int)(max(0.f,min(1.f, -value)) * 255),255 - (int)(max(0.f,min(1.f, -value)) * 255),255);
862                         painter.setBrush(color);
863                         painter.setPen(Qt::black);
864                         painter.drawEllipse(QRectF(x-radius/2.,y-radius/2.,radius,radius));
865                 }
866         }
867 }
868
869 void Canvas::DrawTrajectories(QPainter &painter)
870 {
871         int w = width();
872         int h = height();
873         int count = data->GetCount();
874
875         bool bDrawing = false;
876
877         vector<ipair> sequences = data->GetSequences();
878         int start=0, stop=0;
879         if(data->GetFlag(count-1) == _TRAJ)
880         {
881                 if(sequences.size()) stop = sequences[sequences.size()-1].second;
882                 if(stop < count-1) // there's an unfinished trajectory
883                 {
884                         stop++;
885                         for(start=count-1; start >= stop && data->GetFlag(start) == _TRAJ; start--);
886                         sequences.push_back(ipair(start+(sequences.size() ? 1 : 0),count-1));
887                         bDrawing = true;
888                 }
889         }
890
891         painter.setRenderHint(QPainter::Antialiasing);
892         painter.setRenderHint(QPainter::HighQualityAntialiasing);
893
894         vector<fvec> samples = data->GetSamples();
895
896         map<int,int> counts;
897         centers.clear();
898         if(trajectoryCenterType)
899         {
900                 FOR(i, sequences.size())
901                 {
902                         int index = sequences[i].first;
903                         if(trajectoryCenterType==1) // end
904                         {
905                                 index = sequences[i].second;
906                         }
907                         int label = data->GetLabel(index);
908                         if(!centers.count(label))
909                         {
910                                 fvec center(2,0);
911                                 centers[label] = center;
912                                 counts[label] = 0;
913                         }
914                         centers[label] += samples[index];
915                         counts[label]++;
916                 }
917
918                 for(map<int,int>::iterator p = counts.begin(); p!=counts.end(); ++p)
919                 {
920                         int label = p->first;
921                         centers[label] /= p->second;
922                 }
923         }
924
925         // do the interpolation
926         vector< vector<fvec> > trajectories;
927         vector<fvec> diffs;
928         ivec trajLabels;
929         FOR(i, sequences.size())
930         {
931                 start = sequences[i].first;
932                 stop = sequences[i].second;
933                 int label = data->GetLabel(start);
934                 fvec diff(2,0);
935                 if(trajectoryCenterType && (i < sequences.size()-1 || !bDrawing))
936                 {
937                         diff = centers[label] - samples[trajectoryCenterType==1?stop:start];
938                 }
939                 vector<fvec> trajectory(stop-start+1);
940                 int pos = 0;
941                 for (int j=start; j<=stop; j++)
942                 {
943                         trajectory[pos++] = samples[j] + diff;
944                 }
945                 switch (trajectoryResampleType)
946                 {
947                 case 0: // do nothing
948                         break;
949                 case 1: // uniform resampling
950                 {
951                         if(i < sequences.size()-1 || !bDrawing)
952                         {
953                                 trajectory = interpolate(trajectory, trajectoryResampleCount);
954                         }
955                 }
956                         break;
957                 case 2: // spline resampling
958                 {
959                         if(i < sequences.size()-1 || !bDrawing)
960                         {
961                                 trajectory = interpolateSpline(trajectory, trajectoryResampleCount);
962                         }
963                 }
964                         break;
965                 }
966                 trajectories.push_back(trajectory);
967                 trajLabels.push_back(data->GetLabel(start));
968         }
969
970         // let's draw the trajectories
971         FOR(i, trajectories.size())
972         {
973                 fvec oldPt = trajectories[i][0];
974                 int count = trajectories[i].size();
975                 int label = trajLabels[i];
976                 FOR(j, count-1)
977                 {
978                         fvec pt = trajectories[i][j+1];
979                         painter.setPen(QPen(Qt::black, 0.5));
980                         painter.drawLine(toCanvasCoords(pt), toCanvasCoords(oldPt));
981                         if(j<count-2) Canvas::drawSample(painter, toCanvasCoords(pt), 5, bDisplaySingle ? 0 : label);
982                         oldPt = pt;
983                 }
984                 painter.setBrush(Qt::NoBrush);
985                 painter.setPen(Qt::green);
986                 painter.drawEllipse(toCanvasCoords(trajectories[i][0]), 5, 5);
987                 if(!bDrawing)
988                 {
989                         painter.setPen(Qt::red);
990                         painter.drawEllipse(toCanvasCoords(trajectories[i][count-1]), 5, 5);
991                 }
992         }
993 }
994
995 void Canvas::DrawTrajectories()
996 {
997         int w = width();
998         int h = height();
999         int count = data->GetCount();
1000         if(!count || (!data->GetSequences().size() && (data->GetFlag(count-1) != _TRAJ)))
1001         {
1002                 maps.trajectories = QPixmap(w,h);
1003                 QBitmap bitmap(w,h);
1004                 bitmap.clear();
1005                 maps.trajectories.setMask(bitmap);
1006                 maps.trajectories.fill(Qt::transparent);
1007                 drawnTrajectories = 0;
1008         }
1009
1010         bool bDrawing = false;
1011
1012         vector<ipair> sequences = data->GetSequences();
1013         int start=0, stop=0;
1014         if(data->GetFlag(count-1) == _TRAJ)
1015         {
1016                 if(sequences.size()) stop = sequences.back().second;
1017                 if(stop < count-1) // there's an unfinished trajectory
1018                 {
1019                         stop++;
1020                         for(start=count-1; start >= stop && data->GetFlag(start) == _TRAJ; start--);
1021                         sequences.push_back(ipair(start+(sequences.size() ? 1 : 0),count-1));
1022                         bDrawing = true;
1023                 }
1024         }
1025         if(!bDrawing && drawnTrajectories == sequences.size()) return;
1026         if(drawnTrajectories > sequences.size()) drawnTrajectories = 0;
1027
1028         if(!drawnTrajectories || maps.trajectories.isNull())
1029         {
1030                 maps.trajectories = QPixmap(w,h);
1031                 QBitmap bitmap(w,h);
1032                 bitmap.clear();
1033                 maps.trajectories.setMask(bitmap);
1034                 maps.trajectories.fill(Qt::transparent);
1035                 drawnTrajectories = 0;
1036         }
1037
1038         QPainter painter(&maps.trajectories);
1039         painter.setRenderHint(QPainter::Antialiasing);
1040         painter.setRenderHint(QPainter::HighQualityAntialiasing);
1041
1042         ivec trajLabels(sequences.size());
1043         FOR(i, sequences.size())
1044         {
1045                 trajLabels[i] = data->GetLabel(sequences[i].first);
1046         }
1047         vector< vector<fvec> > trajectories = data->GetTrajectories(trajectoryResampleType, trajectoryResampleCount, trajectoryCenterType, 0.1, true);
1048         if(bDrawing)
1049         {
1050                 vector<fvec> trajectory;
1051                 for(int i=sequences.back().first; i<sequences.back().second; i++)
1052                 {
1053                         trajectory.push_back(data->GetSample(i));
1054                 }
1055                 if(trajectory.size()) trajectories.push_back(trajectory);
1056         }
1057         // let's draw the trajectories
1058         for(int i=drawnTrajectories; i<trajectories.size(); i++)
1059         {
1060                 fvec oldPt = trajectories[i][0];
1061                 int count = trajectories[i].size();
1062                 int label = trajLabels[i];
1063                 FOR(j, count-1)
1064                 {
1065                         fvec pt = trajectories[i][j+1];
1066             int dim = pt.size();
1067             float x = pt[xIndex];
1068             float y = pt[yIndex];
1069                         painter.setPen(QPen(Qt::black, 0.5));
1070             QPointF point = toCanvasCoords(pt);
1071             QPointF oldPoint = toCanvasCoords(oldPt);
1072             painter.drawLine(point, toCanvasCoords(oldPt));
1073             if(j<count-2) Canvas::drawSample(painter, point, 5, bDisplaySingle ? 0 : label);
1074                         oldPt = pt;
1075                 }
1076                 painter.setBrush(Qt::NoBrush);
1077                 painter.setPen(Qt::green);
1078                 painter.drawEllipse(toCanvasCoords(trajectories[i][0]), 5, 5);
1079                 if(!bDrawing)
1080                 {
1081                         painter.setPen(Qt::red);
1082                         painter.drawEllipse(toCanvasCoords(trajectories[i][count-1]), 5, 5);
1083                 }
1084         }
1085         drawnTrajectories = !bDrawing ? sequences.size() : sequences.size()-1;
1086 }
1087
1088 void Canvas::DrawLiveTrajectory(QPainter &painter)
1089 {
1090         if(!liveTrajectory.size() || !liveTrajectory[0].size()) return;
1091         int w = width();
1092         int h = height();
1093         fvec oldPt = liveTrajectory[0];
1094         int count = liveTrajectory.size();
1095         FOR(j, count-1)
1096         {
1097                 fvec pt = liveTrajectory[j+1];
1098                 if(!pt.size()) break;
1099                 int label = 1;
1100                 if(false && bDisplayMap)
1101                 {
1102                         painter.setPen(QPen(Qt::white, 3));
1103                         painter.drawLine(toCanvasCoords(pt), toCanvasCoords(oldPt));
1104                         painter.setPen(QPen(Qt::black, 1));
1105                         painter.drawLine(toCanvasCoords(pt), toCanvasCoords(oldPt));
1106                 }
1107                 else
1108                 {
1109                         painter.setPen(QPen(Qt::magenta, 2));
1110                         painter.drawLine(toCanvasCoords(pt), toCanvasCoords(oldPt));
1111                 }
1112                 //if(j<count-2) Canvas::drawSample(painter, QPoint(pt[0]*w, pt[1]*h), 5, label);
1113                 oldPt = pt;
1114         }
1115         painter.setBrush(Qt::NoBrush);
1116         painter.setPen(Qt::green);
1117         painter.drawEllipse(toCanvasCoords(liveTrajectory[0]), 5, 5);
1118         painter.setPen(Qt::red);
1119         painter.drawEllipse(toCanvasCoords(liveTrajectory[count-1]), 5, 5);
1120 }
1121
1122 void Canvas::DrawTimeseries()
1123 {
1124         int w = width();
1125         int h = height();
1126         if(!drawnTimeseries || maps.timeseries.isNull())
1127         {
1128                 maps.timeseries = QPixmap(w,h);
1129                 QBitmap bitmap(w,h);
1130                 bitmap.clear();
1131                 maps.timeseries.setMask(bitmap);
1132                 maps.timeseries.fill(Qt::transparent);
1133                 drawnTimeseries = 0;
1134         }
1135
1136         vector<TimeSerie> timeseries = data->GetTimeSeries();
1137         if((!timeseries.size() && drawnTimeseries) || (timeseries.size() == drawnTimeseries)) return;
1138
1139         if(drawnTimeseries > timeseries.size()) drawnTimeseries = 0;
1140
1141         QPainter painter(&maps.timeseries);
1142         painter.setRenderHint(QPainter::Antialiasing);
1143         painter.setRenderHint(QPainter::HighQualityAntialiasing);
1144
1145         //qDebug() << "drawing: " << timeseries.size() << "series";
1146         // we draw all the timeseries, each with its own color
1147         for(int i=drawnTimeseries; i < timeseries.size(); i++)
1148         {
1149                 painter.setPen(QPen(SampleColor[i%(SampleColorCnt-1)+1],0.5));
1150                 TimeSerie &t = timeseries[i];
1151                 if(t.size() < 2) continue;
1152                 QPointF p0,p1;
1153                 float count = t.timestamps.size();
1154                 p0 = toCanvasCoords(t.timestamps[0] / count, t.data[0][yIndex-1]);
1155                 FOR(j, t.size()-1)
1156                 {
1157                         float value = t.data[j+1][yIndex-1];
1158                         p1 = toCanvasCoords(t.timestamps[j+1] / count, value);
1159                         if(t.timestamps[j] == -1 || t.timestamps[j+1] == -1) continue;
1160                         painter.drawLine(p0, p1);
1161                         p0 = p1;
1162                 }
1163         }
1164         drawnTimeseries = timeseries.size();
1165 }
1166
1167 void Canvas::ResizeEvent()
1168 {
1169     if(!canvasType && (width() != parentWidget()->width() || height() != parentWidget()->height())) resize(parentWidget()->size());
1170         bNewCrosshair = true;
1171         if(!maps.reward.isNull())
1172         {
1173                 QPixmap newReward(width(), height());
1174                 newReward = maps.reward.scaled(newReward.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
1175         }
1176     if(!canvasType) RedrawAxes();
1177 }
1178
1179 void Canvas::mousePressEvent( QMouseEvent *event )
1180 {
1181         int x = event->x();
1182         int y = event->y();
1183
1184         fvec sample = toSampleCoords(x,y);
1185
1186         int label = 0;
1187         if(event->button()==Qt::LeftButton) label = 1;
1188         if(event->button()==Qt::RightButton) label = 0;
1189
1190     if(canvasType == 0)
1191     {
1192         if(event->modifiers()==Qt::AltModifier)
1193         {
1194             mouseAnchor = event->pos();
1195             return;
1196         }
1197         emit Drawing(sample, label);
1198     }
1199 }
1200
1201 void Canvas::mouseReleaseEvent( QMouseEvent *event )
1202 {
1203         int x = event->x();
1204         int y = event->y();
1205
1206         fvec sample = toSampleCoords(x,y);
1207
1208         int label = 0;
1209         if(event->button()==Qt::LeftButton) label = 1;
1210         if(event->button()==Qt::RightButton) label = 0;
1211
1212     if(canvasType == 0)
1213     {
1214         mouseAnchor = QPoint(-1,-1);
1215         if(x > 0 && x < width() && y>0 && y<height()) bShowCrosshair = true;
1216         //emit Drawing(sample, label);
1217         emit Released();
1218     }
1219 }
1220
1221 void Canvas::enterEvent(QEvent *event)
1222 {
1223         bShowCrosshair = true;
1224         repaint();
1225 }
1226
1227 void Canvas::focusOutEvent(QFocusEvent *event)
1228 {
1229         bShowCrosshair = false;
1230         bNewCrosshair = true;
1231         repaint();
1232 }
1233
1234 void Canvas::leaveEvent(QEvent *event)
1235 {
1236         bShowCrosshair = false;
1237         bNewCrosshair = true;
1238         //mouseAnchor = QPoint(-1,-1);
1239         repaint();
1240 }
1241
1242 void Canvas::wheelEvent(QWheelEvent *event)
1243 {
1244     if(canvasType) return;
1245         if(event->modifiers() == Qt::ShiftModifier)
1246         {
1247                 zooms[xIndex] += event->delta()/1000.f;
1248                 qDebug() << "zooms[" << xIndex << "]: " << zooms[xIndex];
1249
1250                 maps.grid = QPixmap();
1251                 maps.model = QPixmap();
1252                 maps.confidence = QPixmap();
1253                 //maps.reward = QPixmap();
1254                 maps.info = QPixmap();
1255                 ResetSamples();
1256                 bNewCrosshair = true;
1257                 repaint();
1258
1259                 emit(Navigation(fVec(-1,0.001)));
1260                 return;
1261         }
1262         float d = 0;
1263         if (event->delta() > 100) d = 1;
1264         if (event->delta() < 100) d = -1;
1265         if(d!=0) emit Navigation(fVec(-1,d));
1266 }
1267
1268 void Canvas::mouseMoveEvent( QMouseEvent *event )
1269 {
1270     if(canvasType) return;
1271         int x = event->x();
1272         int y = event->y();
1273         mouse = QPoint(x,y);
1274         fvec sample = toSampleCoords(x,y);
1275
1276         // we navigate in our environment
1277         if(event->modifiers() == Qt::AltModifier && event->buttons() == Qt::LeftButton)
1278         {
1279                 fVec d = (fromCanvas(mouseAnchor) - fromCanvas(event->pos()));
1280                 if(d.x == 0 && d.y == 0) return;
1281                 SetCenter(center + d);
1282                 mouseAnchor = event->pos();
1283                 bShowCrosshair = false;
1284                 emit CanvasMoveEvent();
1285                 return;
1286         }
1287
1288         if(event->buttons() != Qt::LeftButton && event->buttons() != Qt::RightButton )
1289         {
1290                 emit Navigation(sample);
1291                 repaint();
1292         }
1293         else
1294         {
1295                 int label = 0;
1296                 if(event->buttons()==Qt::LeftButton) label = 1;
1297                 if(event->buttons()==Qt::RightButton) label = 0;
1298                 emit Drawing(sample, label);
1299         }
1300 }
1301
1302 bool Canvas::SaveScreenshot( QString filename )
1303 {
1304         QPixmap screenshot = GetScreenshot();
1305         return screenshot.save(filename);
1306 }
1307
1308 QPixmap Canvas::GetScreenshot()
1309 {
1310         QPixmap screenshot(width(), height());
1311         QPainter painter(&screenshot);
1312         bool tmp = bShowCrosshair;
1313     bShowCrosshair = false;
1314         painter.setBackgroundMode(Qt::OpaqueMode);
1315         painter.setBackground(Qt::white);
1316     PaintStandard(painter);
1317         bShowCrosshair = tmp;
1318         return screenshot;
1319 }
1320
1321 bool Canvas::DeleteData( QPointF center, float radius )
1322 {
1323         bool anythingDeleted = false;
1324         FOR(i, data->GetCount())
1325         {
1326                 QPointF dataPoint = toCanvasCoords(data->GetSample(i));
1327                 QPointF point = this->mapToParent(QPoint(dataPoint.x(), dataPoint.y()));
1328                 point -= center;
1329                 if(sqrt(point.x()*point.x() + point.y()*point.y()) < radius)
1330                 {
1331                         anythingDeleted = true;
1332                         data->RemoveSample(i);
1333                         i--;
1334                 }
1335         }
1336         FOR(i, data->GetObstacles().size())
1337         {
1338                 QPointF obstaclePoint= toCanvasCoords(data->GetObstacle(i).center);
1339                 QPointF point = this->mapToParent(QPoint(obstaclePoint.x(), obstaclePoint.y()));
1340                 point -= center;
1341                 if(sqrt(point.x()*point.x() + point.y()*point.y()) < radius)
1342                 {
1343                         anythingDeleted = true;
1344                         data->RemoveObstacle(i);
1345                         i--;
1346                 }
1347         }
1348         return anythingDeleted;
1349 }
1350
1351 void Canvas::PaintReward(fvec sample, float radius, float shift)
1352 {
1353         int w = width();
1354         int h = height();
1355         if(maps.reward.isNull())
1356         {
1357                 maps.reward = QPixmap(w,h);
1358                 QBitmap bitmap(w,h);
1359                 bitmap.clear();
1360                 maps.reward.setMask(bitmap);
1361                 maps.reward.fill(Qt::transparent);
1362                 maps.reward.fill(Qt::white);
1363         }
1364         QPainter painter(&maps.reward);
1365         painter.setRenderHint(QPainter::Antialiasing);
1366         painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
1367
1368         QPointF center = toCanvasCoords(sample);
1369         QRadialGradient gradient( center, radius*.75);
1370         if(shift > 0)
1371         {
1372                 gradient.setColorAt(0, QColor(255,0,0,shift*255));
1373                 gradient.setColorAt(1, QColor(255,0,0,0));
1374         }
1375         else
1376         {
1377                 gradient.setColorAt(0, QColor(255,255,255,-shift*255));
1378                 gradient.setColorAt(1, QColor(255,255,255,0));
1379         }
1380         painter.setBrush(gradient);
1381         //if(shift > 0) painter.setBrush(QColor(255,0,0,shift*255));
1382         //else painter.setBrush(QColor(255,255,255,-shift*255));
1383         painter.setPen(Qt::NoPen);
1384         painter.drawEllipse(toCanvasCoords(sample), radius, radius);
1385 }
1386
1387 void Canvas::PaintGaussian(QPointF position, double variance)
1388 {
1389         int w = width();
1390         int h = height();
1391         if(maps.reward.isNull())
1392         {
1393                 maps.reward = QPixmap(w,h);
1394                 QBitmap bitmap(w,h);
1395                 bitmap.clear();
1396                 maps.reward.setMask(bitmap);
1397                 maps.reward.fill(Qt::transparent);
1398                 maps.reward.fill(Qt::white);
1399         }
1400
1401         QImage image(w, h, QImage::Format_ARGB32);
1402         image.fill(qRgb(255,255,255));
1403         fVec pos(position.x()/(float)w, position.y()/(float)h);
1404         fVec point;
1405         float invSigma = 1./(variance*variance);
1406         float a = invSigma*sqrtf(2*PIf);
1407         float value;
1408         float minVal = 1e30, maxVal = -1e30;
1409         qDebug() << "gaussian dropped at position " << position;
1410         FOR(i, w)
1411         {
1412                 point.x = i/(float)w;
1413                 FOR(j, h)
1414                 {
1415                         point.y = j/(float)h;
1416                         value = (pos - point).lengthSquared();
1417                         value = expf(-0.5*value*invSigma);
1418                         value = (1.f - value);
1419                         if(value < minVal) minVal = value;
1420                         if(value > maxVal) maxVal = value;
1421                         int color = 255.f*value;
1422                         //                      if(color > 255) color = 255;
1423                         //                      if(color < -255) color = 0;
1424                         //int color = min(255, max(0, (int)(255.f*(1.f - value))));
1425                         image.setPixel(i,j,qRgba(255, color, color, 255));
1426                 }
1427         }
1428         QPainter painter(&maps.reward);
1429         painter.setRenderHint(QPainter::Antialiasing);
1430         painter.setCompositionMode(QPainter::CompositionMode_Darken);
1431         painter.drawPixmap(0,0,w,h,QPixmap::fromImage(image));
1432 }
1433
1434 void Canvas::PaintGradient(QPointF position)
1435 {
1436         int w = width();
1437         int h = height();
1438         if(maps.reward.isNull())
1439         {
1440                 maps.reward = QPixmap(w,h);
1441                 QBitmap bitmap(w,h);
1442                 bitmap.clear();
1443                 maps.reward.setMask(bitmap);
1444                 maps.reward.fill(Qt::transparent);
1445                 maps.reward.fill(Qt::white);
1446         }
1447         QPainter painter(&maps.reward);
1448         painter.setRenderHint(QPainter::Antialiasing);
1449         painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
1450
1451         QPointF center(w/2.f, h/2.f);
1452         QPointF opposite = center - (position-center);
1453         QLinearGradient gradient(opposite, position);
1454         gradient.setColorAt(0, QColor(255,255,255,255));
1455         gradient.setColorAt(1, QColor(255,0,0,255));
1456         painter.setBrush(gradient);
1457         painter.setPen(Qt::NoPen);
1458         painter.drawRect(maps.reward.rect());
1459 }