MapDisplay.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/qt/widgets/canvas/MapDisplay.cpp
22 
23  \brief A Qt4 widget to control the display of a set of layers.
24 */
25 
26 // TerraLib
27 #include "../../../common/STLUtils.h"
28 #include "../../../geometry/Coord2D.h"
29 #include "../../../geometry/Envelope.h"
30 #include "../../../maptools/AbstractLayer.h"
31 #include "../../../maptools/Utils.h"
32 #include "../../../qt/widgets/layer/explorer/AbstractTreeItem.h"
33 #include "../utils/ScopedCursor.h"
34 #include "Canvas.h"
35 #include "MapDisplay.h"
36 
37 // Qt
38 #include <QMimeData>
39 #include <QPaintDevice>
40 #include <QResizeEvent>
41 #include <QTimer>
42 #include <QGraphicsView>
43 
44 te::qt::widgets::MapDisplay::MapDisplay(const QSize& size, QWidget* parent, Qt::WindowFlags f)
45  : QWidget(parent, f),
46  te::map::MapDisplay(),
47  m_displayPixmap(new QPixmap(size)),
48  m_draftPixmap(new QPixmap(size)),
49  m_backgroundColor(Qt::white),
50  m_resizePolicy(te::qt::widgets::MapDisplay::Fixed),
51  m_timer(new QTimer(this)),
52  m_interval(200),
53  m_isDrawing(false)
54 {
55  m_timer->setSingleShot(true);
56  connect(m_timer, SIGNAL(timeout()), this, SLOT(onResizeTimeout()));
57 
59  m_draftPixmap->fill(Qt::transparent);
60 
61  resize(size);
62  setAcceptDrops(true);
63 }
64 
65 te::qt::widgets::MapDisplay::MapDisplay(QWidget* parent, Qt::WindowFlags f)
66 : QWidget(parent, f),
67 te::map::MapDisplay(),
68 m_displayPixmap(new QPixmap(size())),
69 m_draftPixmap(new QPixmap(size())),
70 m_backgroundColor(Qt::white),
71 m_resizePolicy(te::qt::widgets::MapDisplay::Fixed),
72 m_timer(new QTimer(this)),
73 m_interval(200),
74 m_isDrawing(false)
75 {
76  m_timer->setSingleShot(true);
77  connect(m_timer, SIGNAL(timeout()), this, SLOT(onResizeTimeout()));
78 
80  m_draftPixmap->fill(Qt::transparent);
81 
82  setAcceptDrops(true);
83 }
84 
86 {
87  delete m_displayPixmap;
88  delete m_draftPixmap;
89 
90  std::map<te::map::AbstractLayer*, te::qt::widgets::Canvas*>::iterator it;
91  for(it = m_layerCanvasMap.begin(); it != m_layerCanvasMap.end(); ++it)
92  delete it->second;
93 
94  m_layerCanvasMap.clear();
95 }
96 
98 {
99  // limpe todos os canvas antes usados
100  std::map<te::map::AbstractLayer*, te::qt::widgets::Canvas*>::iterator it;
101  for(it = m_layerCanvasMap.begin(); it != m_layerCanvasMap.end(); ++it)
102  {
103  te::map::Canvas* c = getCanvas(it->first);
104  delete c;
105  }
106  m_layerCanvasMap.clear();
107  m_srid = nsrid;
108 
109  if(al.get() == 0)
110  return;
111 
112  std::list<te::map::AbstractLayerPtr> vis, visibleLayers;
113  te::map::GetVisibleLayers(al, vis);
114  // remove folders
115  std::list<te::map::AbstractLayerPtr>::iterator vit;
116  for(vit = vis.begin(); vit != vis.end(); ++vit)
117  {
118  if((*vit)->getType() == "DATASETLAYER" ||
119  (*vit)->getType() == "QUERYLAYER" ||
120  (*vit)->getType() == "RASTERLAYER")
121  {
122  visibleLayers.push_front(*vit);
123  }
124  }
125 
126  setLayerList(visibleLayers);
127 
128  if(m_srid == TE_UNKNOWN_SRS)
129  {
130  // calcule SRID e extent
131  te::gm::Envelope envelope;
132 
133  std::list<te::map::AbstractLayerPtr>::iterator lit;
134  for(lit = visibleLayers.begin(); lit != visibleLayers.end(); ++lit)
135  {
136  te::gm::Envelope env = (*lit)->getExtent();
137 
138  int srid = (*lit)->getSRID();
139  if(m_srid <= 0)
140  m_srid = srid;
141  if(srid != m_srid)
142  env.transform(srid, m_srid);
143 
144  envelope.Union(env);
145  }
146  setExtent(envelope);
147  }
148 }
149 
151 {
152  te::map::MapDisplay::setExtent(e, doRefresh);
153 
154  std::map<te::map::AbstractLayer*, te::qt::widgets::Canvas*>::iterator it;
155  for(it = m_layerCanvasMap.begin(); it != m_layerCanvasMap.end(); ++it)
156  {
157  te::qt::widgets::Canvas* canvas = it->second;
158  canvas->calcAspectRatio(m_extent.m_llx, m_extent.m_lly, m_extent.m_urx, m_extent.m_ury, m_hAlign, m_vAlign);
159  canvas->setWindow(m_extent.m_llx, m_extent.m_lly, m_extent.m_urx, m_extent.m_ury);
160  canvas->clear();
161  e = m_extent;
162  }
163 
164  if(doRefresh)
165  refresh();
166 
167  emit extentChanged();
168 }
169 
171 {
172  ScopedCursor cursor(Qt::WaitCursor);
173 
174  m_isDrawing = true;
175 
176  // Cleaning...
177  m_displayPixmap->fill(m_backgroundColor);
178 
179  QPainter painter(m_displayPixmap);
180 
181  std::list<te::map::AbstractLayerPtr>::iterator it;
182 
183  for(it = m_layerList.begin(); it != m_layerList.end(); ++it) // for each layer
184  draw(it->get(), painter);
185 
186  m_isDrawing = false;
187 
188  update();
189 }
190 
192 {
193  return static_cast<unsigned int>(width());
194 }
195 
197 {
198  return static_cast<unsigned int>(height());
199 }
200 
202 {
203  return static_cast<double>(widthMM());
204 }
205 
207 {
208  return static_cast<double>(heightMM());
209 }
210 
211 void te::qt::widgets::MapDisplay::setSRID(const int& srid, bool doRefresh)
212 {
213  te::map::MapDisplay::setSRID(srid, doRefresh);
214  emit displaySridChanged();
215 }
216 
218 {
219  return m_displayPixmap;
220 }
221 
223 {
224  return m_draftPixmap;
225 }
226 
228 {
229  m_resizePolicy = policy;
230 }
231 
233 {
234  m_interval = msec;
235 }
236 
238 {
239  // Checking the visibility...
240  if(layer->getVisibility() == te::map::NOT_VISIBLE)
241  return;
242 
243  // Recursive draw
244  for(std::size_t i = 0; i < layer->getChildrenCount(); ++i)
245  draw(boost::dynamic_pointer_cast<te::map::AbstractLayer>(layer->getChild(i)).get(), painter);
246 
247  // Retrieves a canvas to current layer
248  te::qt::widgets::Canvas* canvas = getCanvas(layer);
249 
250  // Draw the current layer
251  try
252  {
253  layer->draw(canvas, m_extent, m_srid);
254  }
255  catch(...)
256  {
257  return;
258  }
259 
260  // Compose the result
261  QPaintDevice* device = canvas->getDevice();
262 
263  if(device->devType() == QInternal::Pixmap)
264  painter.drawPixmap(0, 0, *static_cast<QPixmap*>(device));
265  else if(device->devType() == QInternal::Image)
266  painter.drawImage(0, 0, *static_cast<QImage*>(device));
267 }
268 
270 {
271  // Is there a canvas associated with the given layer?
272  std::map<te::map::AbstractLayer*, te::qt::widgets::Canvas*>::iterator it = m_layerCanvasMap.find(layer);
273  if(it != m_layerCanvasMap.end())
274  return it->second;
275 
276  // else, create one!
277  te::qt::widgets::Canvas* canvas = new te::qt::widgets::Canvas(m_displayPixmap->width(), m_displayPixmap->height(), type);
278  canvas->calcAspectRatio(m_extent.m_llx, m_extent.m_lly, m_extent.m_urx, m_extent.m_ury, m_hAlign, m_vAlign);
279  canvas->setWindow(m_extent.m_llx, m_extent.m_lly, m_extent.m_urx, m_extent.m_ury);
280  canvas->clear();
281 
282  m_layerCanvasMap[layer] = canvas;
283 
284  return canvas;
285 }
286 
288 {
289  std::map<te::map::AbstractLayer*, te::qt::widgets::Canvas*>::iterator it;
290  for(it = m_layerCanvasMap.begin(); it != m_layerCanvasMap.end(); ++it)
291  it->second->resize(m_displayPixmap->width(), m_displayPixmap->height());
292 }
293 
295 {
296  QPainter painter(this);
297  painter.drawPixmap(0, 0, *m_displayPixmap);
298 
299  emit displayPaintEvent(&painter);
300 
301  painter.drawPixmap(0, 0, *m_draftPixmap);
302 }
303 
305 {
306  QWidget::resizeEvent(e);
307 
308  if(m_interval == 0)
309  onResizeTimeout();
310  else
311  {
312  // Stores the old size
313  if(!m_oldSize.isValid())
314  e->oldSize().isValid() ? m_oldSize = e->oldSize() : m_oldSize = e->size();
315 
316  // Setups the timer controller
317  m_timer->start(m_interval);
318  }
319 }
320 
321 QPointF te::qt::widgets::MapDisplay::transform(const QPointF& p)
322 {
323  if(m_layerCanvasMap.empty())
324  return QPointF();
325 
326  te::qt::widgets::Canvas* canvas = m_layerCanvasMap.begin()->second;
327  if(canvas == 0)
328  return QPointF();
329 
330  return canvas->getMatrix().inverted().map(p);
331 }
332 
334 {
335  return m_backgroundColor;
336 }
337 
339 {
340  m_backgroundColor = color;
341 }
342 
344 {
345  return m_isDrawing;
346 }
347 
349 {
350  // Rebulding the map display pixmaps
351  delete m_displayPixmap;
352  m_displayPixmap = new QPixmap(size());
353  m_displayPixmap->fill(m_backgroundColor);
354 
355  delete m_draftPixmap;
356  m_draftPixmap = new QPixmap(size());
357  m_draftPixmap->fill(Qt::transparent);
358 
359  // Resizing all canvas
360  resizeAllCanvas();
361 
362  // Adjust the extent based on resize policy
363  adjustExtent(m_oldSize, size());
364 
365  // Invalidate old size
366  m_oldSize = QSize();
367 }
368 
369 void te::qt::widgets::MapDisplay::adjustExtent(const QSize& oldSize, const QSize& size)
370 {
371  if(!m_extent.isValid())
372  {
373  update();
374  return;
375  }
376 
377  te::gm::Envelope e = m_extent;
378  //if(m_resizePolicy == te::qt::widgets::MapDisplay::Fixed)
379  // setExtent(e);
380  if(m_resizePolicy == te::qt::widgets::MapDisplay::Fixed)
381  {
382  setExtent(e);
383  return;
384  }
385 
386  double widthW = e.m_urx - e.m_llx;
387  double heightW = e.m_ury - e.m_lly;
388 
389  double newWidthW = (size.width() * widthW) / oldSize.width();
390  double newHeightW = (size.height() * heightW) / oldSize.height();
391 
392  switch(m_resizePolicy)
393  {
395  {
396  e.m_urx = e.m_llx + newWidthW;
397  e.m_lly = e.m_ury - newHeightW;
398  }
399  break;
400 
402  {
403  te::gm::Coord2D center = e.getCenter();
404  e.m_llx = center.x - (newWidthW * 0.5);
405  e.m_urx = center.x + (newWidthW * 0.5);
406  e.m_lly = center.y - (newHeightW * 0.5);
407  e.m_ury = center.y + (newHeightW * 0.5);
408  }
409  break;
410 
411  default:
412  break;
413  }
414 
415  setExtent(e);
416 }
void clear()
It clears the canvas content and fills with the background color.
Definition: Canvas.cpp:222
A canvas built on top of Qt.
const TreeItemPtr & getChild(std::size_t i) const
It returns the n-th child.
Definition: TreeItem.cpp:75
unsigned int getWidth() const
It returns the MapDisplay current width in pixels.
Definition: MapDisplay.cpp:191
double y
y-coordinate.
Definition: Coord2D.h:114
std::size_t getChildrenCount() const
It returns the number of children of this node.
Definition: TreeItem.cpp:183
This is the base class for layers.
Definition: AbstractLayer.h:76
virtual void refresh()
It updates the contents in the map display.
Definition: MapDisplay.cpp:170
virtual void setBackgroundColor(const QColor &color)
Sets the map display background color.
Definition: MapDisplay.cpp:338
virtual te::qt::widgets::Canvas * getCanvas(te::map::AbstractLayer *layer, int type=QInternal::Pixmap)
It retrieves an associated canvas to the given layer.
Definition: MapDisplay.cpp:269
double x
x-coordinate.
Definition: Coord2D.h:113
double getWidthMM() const
It returns the MapDisplay current width in millimeters.
Definition: MapDisplay.cpp:201
double getHeightMM() const
It returns the MapDisplay current height in millimeters.
Definition: MapDisplay.cpp:206
virtual void paintEvent(QPaintEvent *e)
It assembles the final image and draws the widget.
Definition: MapDisplay.cpp:294
virtual void onResizeTimeout()
Definition: MapDisplay.cpp:348
double m_urx
Upper right corner x-coordinate.
Definition: Envelope.h:346
virtual void clear()=0
It clears the canvas content and fills with the background color.
virtual Visibility getVisibility() const
It returns the layer visibility.
A widget to control the display of a set of layers.
Definition: MapDisplay.h:66
A Qt4 widget to control the display of a set of layers.
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
QPixmap * m_displayPixmap
This pixmap will be the result of all canvas pixmap drawing, i. e., the result of drawing all visible...
Definition: MapDisplay.h:286
virtual void draw(Canvas *canvas, const te::gm::Envelope &bbox, int srid)=0
It draws the layer geographic objects in the given canvas using the informed SRS. ...
virtual void resizeAllCanvas()
It resizes all canvas of map display.
Definition: MapDisplay.cpp:287
void Union(const Envelope &rhs)
It updates the envelop with coordinates of another envelope.
Definition: Envelope.h:555
QMatrix getMatrix()
It returns the matrix.
Definition: Canvas.cpp:2123
virtual void setExtent(te::gm::Envelope &e, bool doRefresh=true)
It sets the world visible area and refreshes the contents in the map display.
Definition: MapDisplay.cpp:68
Coord2D getCenter() const
It returns the rectangle's center coordinate.
Definition: Envelope.cpp:51
MapDisplay()
It initializes a new MapDisplay.
Definition: MapDisplay.cpp:30
void setWindow(const double &llx, const double &lly, const double &urx, const double &ury)
It sets the world (or window) coordinates area (supposing a cartesian reference system).
Definition: Canvas.cpp:147
double m_llx
Lower left corner x-coordinate.
Definition: Envelope.h:344
virtual QPointF transform(const QPointF &p)
Transforms the given point, in screen coordinates, to a point in world coordinates.
Definition: MapDisplay.cpp:321
virtual void setResizePolicy(const ResizePolicy &policy)
Sets the resize policy to this map display.
Definition: MapDisplay.cpp:227
QPaintDevice * getDevice() const
It returns the internal device used to draw geographical objects.
Definition: Canvas.cpp:2099
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:51
#define TE_UNKNOWN_SRS
A numeric value to represent a unknown SRS identification in TerraLib.
Definition: Config.h:41
void calcAspectRatio(double &llx, double &lly, double &urx, double &ury, const te::map::AlignType hAlign=te::map::Center, const te::map::AlignType vAlign=te::map::Center)
It calculates the best aspect ratio for world (or window) coordinates area (supposing a cartesian ref...
Definition: Canvas.cpp:160
virtual void setSRID(const int &srid, bool doRefresh=true)
It sets a new Spatial Reference System to be used by the Map Display.
Definition: MapDisplay.cpp:78
virtual void setResizeInterval(int msec)
Sets the timeout interval in milliseconds to redraw on resize event.
Definition: MapDisplay.cpp:232
virtual void changeData(te::map::AbstractLayerPtr, int nsrid=TE_UNKNOWN_SRS)
Definition: MapDisplay.cpp:97
URI C++ Library.
virtual void draw(te::map::AbstractLayer *layer, QPainter &painter)
It displays the given layer.
Definition: MapDisplay.cpp:237
double m_lly
Lower left corner y-coordinate.
Definition: Envelope.h:345
A canvas built on top of Qt.
Definition: Canvas.h:54
ResizePolicy
Defines the resize policy for map display.
Definition: MapDisplay.h:77
A canvas is an abstraction of a drawing area.
Definition: Canvas.h:91
unsigned int getHeight() const
It returns the MapDisplay current height in pixels.
Definition: MapDisplay.cpp:196
virtual QPixmap * getDraftPixmap() const
It returns the map display draft pixmap.
Definition: MapDisplay.cpp:222
double m_ury
Upper right corner y-coordinate.
Definition: Envelope.h:347
virtual void adjustExtent(const QSize &oldSize, const QSize &size)
It adjusts the map display extent based on resize policy.
Definition: MapDisplay.cpp:369
bool isDrawing() const
Returns if the map display is drawing.
Definition: MapDisplay.cpp:343
virtual void resizeEvent(QResizeEvent *e)
This event handler receives widget resize events wich are passed in the event parameter.
Definition: MapDisplay.cpp:304
QPixmap * m_draftPixmap
The draft pixmap can be used to draw some feedback on map display.
Definition: MapDisplay.h:287
virtual void setSRID(const int &srid, bool doRefresh=true)
It sets a new Spatial Reference System to be used by the Map Display.
Definition: MapDisplay.cpp:211
virtual QColor getBackgroundColor()
Gets the map display background color.
Definition: MapDisplay.cpp:333
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
void transform(int oldsrid, int newsrid)
It will transform the coordinates of the Envelope from the old SRS to the new one.
Definition: Envelope.cpp:92
QColor m_backgroundColor
Background color.
Definition: MapDisplay.h:288
virtual void setExtent(te::gm::Envelope &e, bool doRefresh=true)
It sets the world visible area and refreshes the contents in the map display.
Definition: MapDisplay.cpp:150
virtual ~MapDisplay()
Destructor.
Definition: MapDisplay.cpp:85
An object that when created shows a cursor during its scope.
Definition: ScopedCursor.h:48
QTimer * m_timer
Timer to execute redraw on resize action.
Definition: MapDisplay.h:291
TEMAPEXPORT void GetVisibleLayers(const std::list< te::map::AbstractLayerPtr > &layers, std::list< te::map::AbstractLayerPtr > &visibleLayers)
It gets the visible layers of the given layer list.
Definition: Utils.cpp:248
virtual QPixmap * getDisplayPixmap() const
It returns the map display pixmap.
Definition: MapDisplay.cpp:217