ImageItem.cpp
Go to the documentation of this file.
1 // TerraLib
2 #include "ImageItem.h"
3 #include "AnimationScene.h"
4 #include "Animation.h"
5 #include "../canvas/MapDisplay.h"
6 #include "../canvas/Canvas.h"
7 
8 // Qt
9 #include <QtCore/QPropertyAnimation>
10 #include <QtGui/QPainter>
11 #include <QtGui/QImage>
12 #include <QtCore/QVector>
13 
15  : te::qt::widgets::AnimationItem("", 0),
16  m_image(0)
17 {
18 }
19 
20 te::qt::widgets::ImageItem::ImageItem(const QString& title, const QString& folder, te::qt::widgets::MapDisplay* display)
21  : te::qt::widgets::AnimationItem(title, display),
22  m_image(0)
23 {
24  m_dir = QDir(folder);
25 
26  QFileInfo fi(folder);
27  m_baseFile = fi.completeBaseName();
28  m_suffix = fi.suffix();
29 
30  if (m_suffix.isEmpty())
31  m_suffix = ".bin";
32 
33  for (size_t i = 0; i < 256; ++i)
34  m_lut[(uchar)i] = QColor((int)i, (int)i, (int)i, 255);
35 }
36 
38 {
39 }
40 
41 void te::qt::widgets::ImageItem::setImagePosition(const QPointF& p, const QRectF& dr)
42 {
43  QString f = m_files[0];
44  QString file = m_dir.path() + "/" + f;
45  QImage ima(file);
46 
47  te::gm::Envelope env = m_display->getExtent();
48  QRectF ar(env.m_llx, env.m_lly, env.getWidth(), env.getHeight());
49  double fat = ar.width() / dr.width();
50 
51  QRectF r(0, 0, ((double)ima.rect().width() / 4.) / fat, ((double)ima.rect().height() / 4.) / fat);
52  m_imaRect = m_matrix.inverted().mapRect(r);
53  m_imaRect.moveCenter(p);
54 }
55 
57 {
58  if (getCtlParameters() == false)
59  return false;
60 
61  //m_animationScene->addItem(pi);
62  if (m_animation)
63  delete m_animation;
64  m_animation = new te::qt::widgets::Animation(this, "pos");
65  m_animation->m_spatialExtent = te::gm::Envelope(m_imaRect.x(), m_imaRect.y(), m_imaRect.right(), m_imaRect.bottom());
66  m_animation->setEasingCurve(QEasingCurve::Linear);
67  //m_parallelAnimation->addAnimation(animation);
68 
69  QString suffix = "." + m_suffix;
70  QStringList nameFilter;
71  nameFilter.append("*" + suffix);
72  QStringList files = m_dir.entryList(nameFilter, QDir::Files, QDir::Name);
73  size_t count = files.count();
74 
75  // get time extent
76  te::dt::TimeInstant ti = getTime(m_dir.path() + "/" + files.first());
77  te::dt::TimeInstant tf = getTime(m_dir.path() + "/" + files.last());
78  m_animation->m_temporalExtent = te::dt::TimePeriod(ti, tf);
79 
80  // set data
82  for (size_t i = 0; i < count; ++i)
83  {
84  QString f = files[(int)i];
85  t = getTime(f);
86  m_time.push_back(t);
87  m_files.push_back(f);
88  }
89 
90  generateRoute();
91 
92  return true;
93 }
94 
96 {
97  char buf[2000];
98  QString file(m_dir.path() + "/image.ctl");
99  FILE* fp = fopen(file.toStdString().c_str(), "r");
100  if (fp == 0)
101  return false;
102 
103  fread(buf, 2000, sizeof(char), fp);
104  fclose(fp);
105  QString s, ss(QString(buf).simplified());
106 
107  // validation
108  if (!(ss.contains("suffix ", Qt::CaseInsensitive) && ss.contains("undef", Qt::CaseInsensitive) &&
109  ss.contains("srid", Qt::CaseInsensitive) && ss.contains("llx", Qt::CaseInsensitive) &&
110  ss.contains("lly", Qt::CaseInsensitive) && ss.contains("urx", Qt::CaseInsensitive) &&
111  ss.contains("ury", Qt::CaseInsensitive)))
112  return false;
113 
114  // get suffix
115  size_t pos = ss.indexOf("suffix ", Qt::CaseInsensitive) + strlen("suffix ");
116  ss.remove(0, (int)pos);
117  pos = ss.indexOf(" undef", Qt::CaseInsensitive);
118  s = ss.left((int)pos);
119  m_suffix = s;
120  ss.remove(0, (int)pos);
121 
122  // get undef
123  pos = ss.indexOf("undef ", Qt::CaseInsensitive) + (int)strlen("undef ");
124  ss.remove(0, (int)pos);
125  pos = ss.indexOf(" srid", Qt::CaseInsensitive);
126  s = ss.left((int)pos);
127  m_undef = atof(s.toStdString().c_str());
128  ss.remove(0, (int)pos);
129 
130  // get srid
131  pos = ss.indexOf("srid ", Qt::CaseInsensitive) + (int)strlen("srid ");
132  ss.remove(0, (int)pos);
133  pos = ss.indexOf(" llx", Qt::CaseInsensitive);
134  s = ss.left((int)pos);
135  m_SRID = atoi(s.toStdString().c_str());
136  ss.remove(0, (int)pos);
137 
138  // get llx
139  pos = ss.indexOf("llx ", Qt::CaseInsensitive) + strlen("llx ");
140  ss.remove(0, (int)pos);
141  pos = ss.indexOf(" lly", Qt::CaseInsensitive);
142  s = ss.left((int)pos);
143  double llx = atof(s.toStdString().c_str());
144  ss.remove(0, (int)pos);
145 
146  // get lly
147  pos = ss.indexOf("lly ", Qt::CaseInsensitive) + (int)strlen("lly ");
148  ss.remove(0, (int)pos);
149  pos = ss.indexOf(" urx", Qt::CaseInsensitive);
150  s = ss.left((int)pos);
151  double lly = atof(s.toStdString().c_str());
152  ss.remove(0, (int)pos);
153 
154  // get urx
155  pos = ss.indexOf("urx ", Qt::CaseInsensitive) + strlen("urx ");
156  ss.remove(0, (int)pos);
157  pos = ss.indexOf(" ury", Qt::CaseInsensitive);
158  s = ss.left((int)pos);
159  double urx = atof(s.toStdString().c_str());
160  ss.remove(0, (int)pos);
161 
162  // get ury
163  pos = ss.indexOf("ury ", Qt::CaseInsensitive) + strlen("ury ");
164  ss.remove(0, (int)pos);
165  double ury = atof(ss.toStdString().c_str());
166 
167  double w = urx - llx;
168  double h = ury - lly;
169  m_imaRect = QRectF(llx, lly, w, h);
170 
171  return true;
172 }
173 
175 {
176  if (m_image)
177  delete m_image;
178  m_image = 0;
179 
180  if (m_currentImageFile.isEmpty())
181  return;
182 
183  QString file = m_currentImageFile;
184  m_image = new QImage(file);
185 }
186 
188 {
189  if (m_image == 0)
190  return;
191 
192  painter->save();
193 
194  tryDoReprojectionUsingAffineTransform(painter);
195  QRect r(getRect());
196 
197  if (m_opacity == 255)
198  painter->drawImage(r, *m_image);
199  else
200  {
201  QSize size = m_image->size();
202  int width = size.width();
203  int height = size.height();
204 
205  if (m_image->format() == QImage::Format_ARGB32)
206  {
207  for (int i = 0; i < height; ++i)
208  {
209  unsigned char* u = m_image->scanLine(i);
210  for (int j = 0; j < width; ++j)
211  {
212  QRgb* v = (QRgb*)(u + (j << 2));
213  if (qAlpha(*v) > 50)
214  *v = qRgba(qRed(*v), qGreen(*v), qBlue(*v), m_opacity);
215  }
216  }
217  painter->drawImage(r, *m_image);
218  }
219  else
220  {
221  QImage img(size, QImage::Format_ARGB32);
222  for (int i = 0; i < height; ++i)
223  {
224  unsigned char* u = m_image->scanLine(i);
225  unsigned char* uu = img.scanLine(i);
226 
227  for (int j = 0; j < width; ++j)
228  {
229  QRgb* v = (QRgb*)(u + (j << 2));
230  QRgb* uv = (QRgb*)(uu + (j << 2));
231  if (qAlpha(*v) > 50)
232  *uv = qRgba(qRed(*v), qGreen(*v), qBlue(*v), m_opacity);
233  }
234  }
235  painter->drawImage(r, img);
236  }
237  }
238  delete m_image;
239  m_image = 0;
240 
241  painter->restore();
242 }
243 
245 {
246  // If the projection is different, try do reprojection using affine transform.
247  // Note: For small areas it gives a good result, however, for larger areas the result is not good.
248  if (m_display->getSRID() != TE_UNKNOWN_SRS && m_display->getSRID() != m_SRID)
249  {
250  // get width, height and rotation
252  line.setPoint(0, m_imaRect.x(), m_imaRect.y());
253  line.setPoint(1, m_imaRect.x(), m_imaRect.y() + m_imaRect.height());
254  line.setPoint(2, m_imaRect.x() + m_imaRect.width(), m_imaRect.y() + m_imaRect.height());
255  line.setPoint(3, m_imaRect.x() + m_imaRect.width(), m_imaRect.y());
256  line.setPoint(4, m_imaRect.center().x(), m_imaRect.center().y());
257  line.setPoint(5, m_imaRect.x(), m_imaRect.center().y());
258  line.setPoint(6, m_imaRect.x() + m_imaRect.width(), m_imaRect.center().y());
259  line.setPoint(7, m_imaRect.center().x(), m_imaRect.y());
260  line.setPoint(8, m_imaRect.center().x(), m_imaRect.y() + m_imaRect.height());
261  line.transform(m_display->getSRID());
262 
263  // transform to device coordinate
264  QPointF p0 = m_matrix.map(QPointF(line.getPointN(0)->getX(), line.getPointN(0)->getY()));
265  QPointF p1 = m_matrix.map(QPointF(line.getPointN(1)->getX(), line.getPointN(1)->getY()));
266  QPointF p2 = m_matrix.map(QPointF(line.getPointN(2)->getX(), line.getPointN(2)->getY()));
267  QPointF p3 = m_matrix.map(QPointF(line.getPointN(3)->getX(), line.getPointN(3)->getY()));
268  QPointF c = m_matrix.map(QPointF(line.getPointN(4)->getX(), line.getPointN(4)->getY()));
269  QPointF p5 = m_matrix.map(QPointF(line.getPointN(5)->getX(), line.getPointN(5)->getY()));
270  QPointF p6 = m_matrix.map(QPointF(line.getPointN(6)->getX(), line.getPointN(6)->getY()));
271  QPointF p7 = m_matrix.map(QPointF(line.getPointN(7)->getX(), line.getPointN(7)->getY()));
272  QPointF p8 = m_matrix.map(QPointF(line.getPointN(8)->getX(), line.getPointN(8)->getY()));
273  QPointF ph(p8 - p7);
274  QPointF ph1(p0 - p1);
275  QPointF ph2(p3 - p2);
276  QPointF pw(p6 - p5);
277  QPointF pw1(p2 - p1);
278  QPointF pw2(p3 - p0);
279  QPointF prot(p6 - c);
280 
281  double w = fabs(pw.x());
282  double h = fabs(ph.y());
283 
284  double PI = 3.14159265;
285  double rad = 0;
286  painter->translate(c.toPoint());
287 
288  if (prot.x() == 0)
289  {
290  if (prot.y() >= 0)
291  rad = PI / 2.;
292  else
293  rad = -PI / 2.;
294  }
295  else if (prot.y() == 0)
296  {
297  if (prot.x() >= 0)
298  rad = 0;
299  else
300  rad = -PI;
301  }
302  else
303  {
304  rad = atan(prot.y() / prot.x());
305  if (prot.x() < 0)
306  {
307  if (prot.y() < 0)
308  rad -= PI;
309  else
310  rad += PI;
311  }
312  }
313 
314  // set scale indirectly - calculate a new image rect
315  if (rad != 0)
316  {
317  w /= fabs(cos(rad));
318  h /= fabs(cos(PI + rad));
319  }
320 
321  QRect r(0, 0, w, h);
322  r.moveCenter(c.toPoint()); // move to center
323 
324  if (ph1.x() != 0 && ph2.x() != 0 && ph1.y() == ph2.y()) // make horizontal shear
325  {
326  double horiz = (ph1.x() + ph2.x()) / 1.35;
327  painter->shear(horiz / w, 0);
328  }
329  else if (pw1.y() != 0 && pw2.y() != 0 && pw1.x() == pw2.x()) // make vertical shear
330  {
331  double vert = (pw1.y() + pw2.y()) / 1.35;
332  painter->shear(0, vert / h);
333  }
334  else if (rad != 0) // make rotation
335  {
336  double degree = rad * 180. / PI;
337  painter->rotate(degree);
338  }
339  painter->translate(-c.toPoint());
340  }
341 }
342 
344 {
346  m_animationFiles.clear();
347 
348  te::dt::TimeInstant iTime = m_animation->m_temporalAnimationExtent.getInitialTimeInstant();
349  te::dt::TimeInstant fTime = m_animation->m_temporalAnimationExtent.getFinalTimeInstant();
350 
351  size_t ini = 0;
352  size_t size = m_time.size();
353  size_t fim = size;
354  for (int i = 0; i < (int)size; ++i)
355  {
356  if (m_time[i] == iTime || m_time[i] > iTime)
357  {
358  ini = i;
359  break;
360  }
361  }
362  for (int i = (int)size - 1; i >= 0; --i)
363  {
364  if (m_time[i] == fTime || m_time[i] < fTime)
365  {
366  fim = i;
367  break;
368  }
369  }
370  //size = fim - ini + 1;
371  size = fim - ini;
372  size_t tfim = ini + size;
373 
374  size_t count = m_files.count();
375  if (tfim > count)
376  tfim = count;
377 
378  for (int i = (int)ini; i < (int)tfim; ++i)
379  {
380  QString f = m_files[i];
381  m_animationFiles.push_back(f);
382  }
383 }
384 
385 void te::qt::widgets::ImageItem::paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*)
386 {
387  unsigned int curTime = m_animation->currentTime();
388  if (m_curTimeDuration == curTime)
389  return;
390 
391  drawForward(curTime);
392 }
393 
394 void te::qt::widgets::ImageItem::drawForward(const unsigned int& curTime)
395 {
396  m_pos = pos(); // image position
397  m_curTimeDuration = curTime;
398  calculateCurrentFile(curTime);
399  m_display->update();
400 }
401 
402 void te::qt::widgets::ImageItem::erase(const unsigned int& curTime)
403 {
404  drawForward(curTime);
405 }
406 
408 {
409  calculateCurrentFile(m_curTimeDuration);
410  m_display->update();
411 }
412 
413 void te::qt::widgets::ImageItem::calculateCurrentFile(const unsigned int& curTime)
414 {
415  double nt = (double)curTime / (double)m_duration;
416  int ind = m_animation->getAnimationDataIndex(nt);
417  if (ind >= 0 && ind < m_animationFiles.count())
418  {
419  QString f = m_animationFiles[ind];
420  m_currentImageFile = m_dir.path() + "/" + f;
421  }
422  else
423  m_currentImageFile.clear();
424 
425  m_curTimeDuration = curTime;
426 }
427 
429 {
430  QRectF r = m_imaRect;
431  if (m_display->getSRID() != TE_UNKNOWN_SRS && m_display->getSRID() != m_SRID)
432  {
433  te::gm::Envelope e(r.x(), r.y(), r.x() + r.width(), r.y() + r.height());
434  e.transform(m_SRID, m_display->getSRID());
435  r.setRect(e.getLowerLeftX(), e.getLowerLeftY(), e.getWidth(), e.getHeight());
436  }
437 
438  return m_matrix.mapRect(r).toRect();
439 }
440 
441 void te::qt::widgets::ImageItem::setLUT(const std::vector<std::pair<int, QColor> >& tab)
442 {
443  size_t i = 0;
444  std::vector<std::pair<int, QColor> >::const_iterator it = tab.begin();
445  size_t v = (*it).first;
446  QColor c = (*it).second;
447  while (i < 256)
448  {
449  while (i <= v)
450  m_lut[(uchar)i++] = c;
451 
452  ++it;
453  if (it == tab.end())
454  break;
455 
456  v = (*it).first;
457  c = (*it).second;
458  }
459 
460  while (i < 256)
461  m_lut[(uchar)i++] = c;
462 
463 }
464 
466 {
467  size_t count = m_files.count();
468  m_route = new te::gm::LineString(count, te::gm::LineStringType, m_SRID);
469 
470  // crie valores não repetitivos e nem muito grandes ou pequenos
471  QPointF pos(m_animation->m_spatialExtent.m_llx, m_animation->m_spatialExtent.m_lly);
472  double w = m_animation->m_spatialExtent.getWidth();
473  double h = m_animation->m_spatialExtent.getHeight();
474  int tam = 8;
475  double dw = w / (double)tam;
476  double dh = h / (double)tam;
477  size_t i = 0;
478  while (i < count)
479  {
480  m_route->setPoint(i, pos.x(), pos.y());
481  if (i++ & tam)
482  pos -= QPointF(dw, dh);
483  else
484  pos += QPointF(dw, dh);
485  }
486 }
void setImagePosition(const QPointF &p, const QRectF &dr)
Definition: ImageItem.cpp:41
virtual void drawCurrentImage(QPainter *p)
Get current image.
Definition: ImageItem.cpp:187
#define PI
Definition: Canvas.h:29
std::map< uchar, QColor > m_lut
LUT.
Definition: ImageItem.h:203
void calculateCurrentFile(const unsigned int &curTime)
Calculate current file.
Definition: ImageItem.cpp:413
Point * getPointN(std::size_t i) const
It returns the specified point in this LineString.
Definition: LineString.cpp:323
ImageItem()
Empty Constructor.
Definition: ImageItem.cpp:14
double getWidth() const
It returns the envelope width.
Definition: Envelope.h:443
virtual void loadCurrentImage()
Get current image.
Definition: ImageItem.cpp:174
A widget to control the display of a set of layers.
Definition: MapDisplay.h:66
virtual bool loadData()
Load temporal raster data.
Definition: ImageItem.cpp:56
virtual ~ImageItem()
Destructor It destructs a Image Item.
Definition: ImageItem.cpp:37
A class to represent time instant.
Definition: TimeInstant.h:55
void draw()
Draw the current image item.
Definition: ImageItem.cpp:407
double m_llx
Lower left corner x-coordinate.
Definition: Envelope.h:344
This file defines a class for a Animation Scene.
LineString is a curve with linear interpolation between points.
Definition: LineString.h:62
const double & getY() const
It returns the Point y-coordinate value.
Definition: Point.h:150
void setPoint(std::size_t i, const double &x, const double &y)
It sets the value of the specified point.
Definition: LineString.cpp:353
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
virtual bool getCtlParameters()
Get control parameters.
Definition: ImageItem.cpp:95
virtual void adjustDataToAnimationTemporalExtent()
Adjust data for a given time animation period.
void tryDoReprojectionUsingAffineTransform(QPainter *painter)
It try do reprojection using affine transfom. For small areas it gives a good result, however, for larger areas the result is not good.
Definition: ImageItem.cpp:244
URI C++ Library.
void adjustDataToAnimationTemporalExtent()
Adjust data for a given time animation period.
Definition: ImageItem.cpp:343
QRect getRect()
It gets image rect in device coordinate.
Definition: ImageItem.cpp:428
QDir m_dir
The image data directory.
Definition: ImageItem.h:192
double m_lly
Lower left corner y-coordinate.
Definition: Envelope.h:345
A class to represent time period.
Definition: TimePeriod.h:54
This file defines a class for a Trajectory Animation.
void generateRoute()
It generate the raster route.
Definition: ImageItem.cpp:465
This file defines a abstarct class for a Image Item.
QString m_baseFile
Base file name.
Definition: ImageItem.h:200
An abstract class for Animation Item.
Definition: AnimationItem.h:62
void drawForward(const unsigned int &curTime)
Draw current image item. curTime The animation current time.
Definition: ImageItem.cpp:394
void erase(const unsigned int &curTime)
Draw current image item. curTime The animation current time.
Definition: ImageItem.cpp:402
QString m_suffix
File suffix.
Definition: ImageItem.h:201
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
double getHeight() const
It returns the envelope height.
Definition: Envelope.h:448
const double & getX() const
It returns the Point x-coordinate value.
Definition: Point.h:136
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
Paint a image item.
Definition: ImageItem.cpp:385
void transform(int srid)
It converts the coordinate values of the linestring to the new spatial reference system.
Definition: LineString.cpp:181
void setLUT(const std::vector< std::pair< int, QColor > > &tab)
Sets the LUT. tab The LUT information.
Definition: ImageItem.cpp:441