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("", nullptr),
16  m_image(nullptr)
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(nullptr)
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 void te::qt::widgets::ImageItem::setImagePosition(const QPointF& p, const QRectF& dr)
40 {
41  QString f = m_files[0];
42  QString file = m_dir.path() + "/" + f;
43  QImage ima(file);
44 
46  QRectF ar(env.m_llx, env.m_lly, env.getWidth(), env.getHeight());
47  double fat = ar.width() / dr.width();
48 
49  QRectF r(0, 0, ((double)ima.rect().width() / 4.) / fat, ((double)ima.rect().height() / 4.) / fat);
50  m_imaRect = m_matrix.inverted().mapRect(r);
51  m_imaRect.moveCenter(p);
52 }
53 
55 {
56  if (getCtlParameters() == false)
57  return false;
58 
59  if (m_animation)
60  delete m_animation;
61  m_animation = new te::qt::widgets::Animation(this, "pos");
63  m_animation->setEasingCurve(QEasingCurve::Linear);
64 
65  QString suffix = "." + m_suffix;
66  QStringList nameFilter;
67  nameFilter.append(m_preffix + "*" + suffix);
68  QStringList files = m_dir.entryList(nameFilter, QDir::Files, QDir::Name);
69  size_t count = files.count();
70 
71  // get time extent
72  te::dt::TimeInstant ti = getTime(m_dir.path() + "/" + files.first());
73  te::dt::TimeInstant tf = getTime(m_dir.path() + "/" + files.last());
75 
76  // set data
78  for (size_t i = 0; i < count; ++i)
79  {
80  QString f = files[(int)i];
81  t = getTime(f);
82  m_time.push_back(t);
83  m_files.push_back(f);
84  }
85 
86  generateRoute();
87 
88  return true;
89 }
90 
92 {
93  char buf[500];
94  QString file(m_dir.path() + "/image.ctl");
95  FILE* fp = fopen(te::core::CharEncoding::fromUTF8(file.toUtf8().data()).c_str(), "r");
96  if (fp == nullptr)
97  return false;
98 
99  size_t n = fread(buf, sizeof(char), 500, fp);
100  fclose(fp);
101  buf[n] = 0;
102  QString s, ss(QString(buf).simplified());
103 
104  // validation
105  if (!(ss.contains("suffix ", Qt::CaseInsensitive) && ss.contains("preffix ", Qt::CaseInsensitive) &&
106  ss.contains("undef ", Qt::CaseInsensitive) && ss.contains("srid ", Qt::CaseInsensitive) &&
107  ss.contains("llx ", Qt::CaseInsensitive) && ss.contains("lly ", Qt::CaseInsensitive) &&
108  ss.contains("urx ", Qt::CaseInsensitive) && ss.contains("ury ", Qt::CaseInsensitive)))
109  return false;
110 
111  // get suffix
112  int pos = ss.indexOf("suffix ", Qt::CaseInsensitive) + static_cast<int>(strlen("suffix "));
113  ss.remove(0, pos);
114  pos = ss.indexOf(" preffix", Qt::CaseInsensitive);
115  s = ss.left(pos);
116  m_suffix = s;
117  ss.remove(0, pos);
118 
119  // get preffix
120  pos = ss.indexOf("preffix ", Qt::CaseInsensitive) + static_cast<int>(strlen("preffix "));
121  ss.remove(0, pos);
122  pos = ss.indexOf(" undef", Qt::CaseInsensitive);
123  s = ss.left(pos);
124  m_preffix = s;
125  ss.remove(0, pos);
126 
127  // get undef
128  pos = ss.indexOf("undef ", Qt::CaseInsensitive) + static_cast<int>(strlen("undef "));
129  ss.remove(0, pos);
130  pos = ss.indexOf(" srid", Qt::CaseInsensitive);
131  if (pos != -1)
132  {
133  s = ss.left(pos);
134  m_undef = static_cast<float>(atof(s.toUtf8().data()));
135  ss.remove(0, pos);
136 
137  // get srid
138  pos = ss.indexOf("srid ", Qt::CaseInsensitive) + static_cast<int>(strlen("srid "));
139  ss.remove(0, pos);
140  pos = ss.indexOf(" llx", Qt::CaseInsensitive);
141  s = ss.left(pos);
142  m_SRID = atoi(s.toUtf8().data());
143  ss.remove(0, pos);
144  }
145  else
146  m_SRID = 4326;
147 
148  // get llx
149  pos = ss.indexOf("llx ", Qt::CaseInsensitive) + static_cast<int>(strlen("llx "));
150  ss.remove(0, pos);
151  pos = ss.indexOf(" lly", Qt::CaseInsensitive);
152  s = ss.left(pos);
153  double llx = atof(s.toUtf8().data());
154  ss.remove(0, pos);
155 
156  // get lly
157  pos = ss.indexOf("lly ", Qt::CaseInsensitive) + static_cast<int>(strlen("lly "));
158  ss.remove(0, pos);
159  pos = ss.indexOf(" urx", Qt::CaseInsensitive);
160  s = ss.left(pos);
161  double lly = atof(s.toUtf8().data());
162  ss.remove(0, pos);
163 
164  // get urx
165  pos = ss.indexOf("urx ", Qt::CaseInsensitive) + static_cast<int>(strlen("urx "));
166  ss.remove(0, pos);
167  pos = ss.indexOf(" ury", Qt::CaseInsensitive);
168  s = ss.left(pos);
169  double urx = atof(s.toUtf8().data());
170  ss.remove(0, pos);
171 
172  // get ury
173  pos = ss.indexOf("ury ", Qt::CaseInsensitive) + static_cast<int>(strlen("ury "));
174  ss.remove(0, pos);
175  double ury = atof(ss.toUtf8().data());
176 
177  double w = urx - llx;
178  double h = ury - lly;
179  m_imaRect = QRectF(llx, lly, w, h);
180 
181  // get static representation
182  if (m_dir.exists("staticRepresentation.png"))
183  m_staticRepresentation = QImage(m_dir.path() + "/staticRepresentation.png");
184 
185  return true;
186 }
187 
189 {
190  if (m_image)
191  delete m_image;
192  m_image = nullptr;
193 
194  if (m_currentImageFile.isEmpty())
195  {
196  if (m_staticRepresentation.isNull())
197  {
198  QRect r = getRect();
199  m_image = new QImage(r.size(), QImage::Format_ARGB32);
200  m_image->fill(QColor(0, 0, 255, 100).rgba());
201  QPainter p(m_image);
202  p.setPen(QPen(QColor(255, 0, 0)));
203 
204  QFont font(p.font());
205  int ps = 7;
206  int w = (int)((double)m_image->width() / 1.2);
207  int h = (int)((double)m_image->width() / 5.);
208 
209  font.setPointSize(ps);
210  QFontMetrics fm(font);
211  QRectF rec(fm.boundingRect(m_title));
212 
213  while (rec.width() < w && rec.height() < h)
214  {
215  ++ps;
216  font.setPointSize(ps);
217  QFontMetrics fm(font);
218  rec = fm.boundingRect(m_title);
219  }
220  rec.moveCenter(m_image->rect().center());
221  p.setFont(font);
222  p.drawText(rec.toRect(), Qt::AlignLeft, m_title);
223  }
224  else
225  m_image = new QImage(m_staticRepresentation);
226  }
227  else
228  {
229  QString file = m_currentImageFile;
230  m_image = new QImage(file);
231  }
232 
233  //if (m_image)
234  // delete m_image;
235  //m_image = 0;
236 
237  //if (m_currentImageFile.isEmpty())
238  // return;
239 
240  //QString file = m_currentImageFile;
241  //m_image = new QImage(file);
242 }
243 
245 {
246  if (m_image == nullptr)
247  return;
248 
249  painter->save();
250 
252  QRect r(getRect());
253 
254  if (m_opacity == 255)
255  painter->drawImage(r, *m_image);
256  else
257  {
258  QSize size = m_image->size();
259  int width = size.width();
260  int height = size.height();
261 
262  if (m_image->format() == QImage::Format_ARGB32)
263  {
264  for (int i = 0; i < height; ++i)
265  {
266  unsigned char* u = m_image->scanLine(i);
267  for (int j = 0; j < width; ++j)
268  {
269  QRgb* v = (QRgb*)(u + (j << 2));
270  if (qAlpha(*v) > 50)
271  *v = qRgba(qRed(*v), qGreen(*v), qBlue(*v), m_opacity);
272  }
273  }
274  painter->drawImage(r, *m_image);
275  }
276  else
277  {
278  QImage img(size, QImage::Format_ARGB32);
279  for (int i = 0; i < height; ++i)
280  {
281  unsigned char* u = m_image->scanLine(i);
282  unsigned char* uu = img.scanLine(i);
283 
284  for (int j = 0; j < width; ++j)
285  {
286  QRgb* v = (QRgb*)(u + (j << 2));
287  QRgb* uv = (QRgb*)(uu + (j << 2));
288  if (qAlpha(*v) > 50)
289  *uv = qRgba(qRed(*v), qGreen(*v), qBlue(*v), m_opacity);
290  }
291  }
292  painter->drawImage(r, img);
293  }
294  }
295  delete m_image;
296  m_image = nullptr;
297 
298  painter->restore();
299 }
300 
302 {
303  // If the projection is different, try do reprojection using affine transform.
304  // Note: For small areas it gives a good result, however, for larger areas the result is not good.
306  {
307  // get width, height and rotation
309  line.setPoint(0, m_imaRect.x(), m_imaRect.y());
310  line.setPoint(1, m_imaRect.x(), m_imaRect.y() + m_imaRect.height());
311  line.setPoint(2, m_imaRect.x() + m_imaRect.width(), m_imaRect.y() + m_imaRect.height());
312  line.setPoint(3, m_imaRect.x() + m_imaRect.width(), m_imaRect.y());
313  line.setPoint(4, m_imaRect.center().x(), m_imaRect.center().y());
314  line.setPoint(5, m_imaRect.x(), m_imaRect.center().y());
315  line.setPoint(6, m_imaRect.x() + m_imaRect.width(), m_imaRect.center().y());
316  line.setPoint(7, m_imaRect.center().x(), m_imaRect.y());
317  line.setPoint(8, m_imaRect.center().x(), m_imaRect.y() + m_imaRect.height());
318  line.transform(m_display->getSRID());
319 
320  // transform to device coordinate
321  QPointF p0 = m_matrix.map(QPointF(line.getPointN(0)->getX(), line.getPointN(0)->getY()));
322  QPointF p1 = m_matrix.map(QPointF(line.getPointN(1)->getX(), line.getPointN(1)->getY()));
323  QPointF p2 = m_matrix.map(QPointF(line.getPointN(2)->getX(), line.getPointN(2)->getY()));
324  QPointF p3 = m_matrix.map(QPointF(line.getPointN(3)->getX(), line.getPointN(3)->getY()));
325  QPointF c = m_matrix.map(QPointF(line.getPointN(4)->getX(), line.getPointN(4)->getY()));
326  QPointF p5 = m_matrix.map(QPointF(line.getPointN(5)->getX(), line.getPointN(5)->getY()));
327  QPointF p6 = m_matrix.map(QPointF(line.getPointN(6)->getX(), line.getPointN(6)->getY()));
328  QPointF p7 = m_matrix.map(QPointF(line.getPointN(7)->getX(), line.getPointN(7)->getY()));
329  QPointF p8 = m_matrix.map(QPointF(line.getPointN(8)->getX(), line.getPointN(8)->getY()));
330  QPointF ph(p8 - p7);
331  QPointF ph1(p0 - p1);
332  QPointF ph2(p3 - p2);
333  QPointF pw(p6 - p5);
334  QPointF pw1(p2 - p1);
335  QPointF pw2(p3 - p0);
336  QPointF prot(p6 - c);
337 
338  double w = fabs(pw.x());
339  double h = fabs(ph.y());
340 
341  double PI = 3.14159265;
342  double rad = 0;
343  painter->translate(c.toPoint());
344 
345  if (prot.x() == 0)
346  {
347  if (prot.y() >= 0)
348  rad = PI / 2.;
349  else
350  rad = -PI / 2.;
351  }
352  else if (prot.y() == 0)
353  {
354  if (prot.x() >= 0)
355  rad = 0;
356  else
357  rad = -PI;
358  }
359  else
360  {
361  rad = atan(prot.y() / prot.x());
362  if (prot.x() < 0)
363  {
364  if (prot.y() < 0)
365  rad -= PI;
366  else
367  rad += PI;
368  }
369  }
370 
371  // set scale indirectly - calculate a new image rect
372  if (rad != 0)
373  {
374  w /= fabs(cos(rad));
375  h /= fabs(cos(PI + rad));
376  }
377 
378  QRect r(0, 0, w, h);
379  r.moveCenter(c.toPoint()); // move to center
380 
381  if (ph1.x() != 0 && ph2.x() != 0 && ph1.y() == ph2.y()) // make horizontal shear
382  {
383  double horiz = (ph1.x() + ph2.x()) / 1.35;
384  painter->shear(horiz / w, 0);
385  }
386  else if (pw1.y() != 0 && pw2.y() != 0 && pw1.x() == pw2.x()) // make vertical shear
387  {
388  double vert = (pw1.y() + pw2.y()) / 1.35;
389  painter->shear(0, vert / h);
390  }
391  else if (rad != 0) // make rotation
392  {
393  double degree = rad * 180. / PI;
394  painter->rotate(degree);
395  }
396  painter->translate(-c.toPoint());
397  }
398 }
399 
401 {
403  m_animationFiles.clear();
404 
407 
408  size_t size = m_time.size();
409  te::dt::TimeInstant tinicial = m_time[0];
410  te::dt::TimeInstant tfinal = m_time[(int)size - 1];
411 
412  if (iTime > tfinal || fTime < tinicial) // out of animation time
413  return;
414 
415  size_t ini = 0;
416  if (tinicial > iTime)
417  {
418  for (int i = 0; i < (int)size; ++i)
419  {
420  if (m_time[i] == iTime || m_time[i] > iTime)
421  {
422  ini = i;
423  break;
424  }
425  }
426  }
427 
428  size_t fim = size - 1;
429  if (tfinal > fTime)
430  {
431  for (int i = (int)fim; i > (int)ini; --i)
432  {
433  if (m_time[i] == fTime || m_time[i] < fTime)
434  {
435  fim = i;
436  break;
437  }
438  }
439  }
440 
441  for (int i = (int)ini; i <= (int)fim; ++i)
442  {
443  QString f = m_files[i];
444  m_animationFiles.push_back(f);
445  }
446 }
447 
448 void te::qt::widgets::ImageItem::paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*)
449 {
450  unsigned int curTime = m_animation->currentTime();
451  if (m_curTimeDuration == curTime)
452  return;
453 
454  drawForward(curTime);
455 }
456 
457 void te::qt::widgets::ImageItem::drawForward(const unsigned int& curTime)
458 {
459  m_pos = pos(); // image position
460  m_curTimeDuration = curTime;
461  calculateCurrentFile(curTime);
462  m_display->update();
463 }
464 
465 void te::qt::widgets::ImageItem::erase(const unsigned int& curTime)
466 {
467  drawForward(curTime);
468 }
469 
471 {
473  m_display->update();
474 }
475 
476 void te::qt::widgets::ImageItem::calculateCurrentFile(const unsigned int& curTime)
477 {
478  double nt = (double)curTime / (double)m_duration;
480  if (ind >= 0 && ind < m_animationFiles.count())
481  {
482  QString f = m_animationFiles[ind];
483  m_currentImageFile = m_dir.path() + "/" + f;
484  }
485  else
486  m_currentImageFile.clear();
487 
488  m_curTimeDuration = curTime;
489 }
490 
492 {
493  QRectF r = m_imaRect;
495  {
496  te::gm::Envelope e(r.x(), r.y(), r.x() + r.width(), r.y() + r.height());
498  r.setRect(e.getLowerLeftX(), e.getLowerLeftY(), e.getWidth(), e.getHeight());
499  }
500 
501  return m_matrix.mapRect(r).toRect();
502 }
503 
504 void te::qt::widgets::ImageItem::setLUT(const std::vector<std::pair<int, QColor> >& tab)
505 {
506  size_t i = 0;
507  std::vector<std::pair<int, QColor> >::const_iterator it = tab.begin();
508  size_t v = (*it).first;
509  QColor c = (*it).second;
510  while (i < 256)
511  {
512  while (i <= v)
513  m_lut[(uchar)i++] = c;
514 
515  ++it;
516  if (it == tab.end())
517  break;
518 
519  v = (*it).first;
520  c = (*it).second;
521  }
522 
523  while (i < 256)
524  m_lut[(uchar)i++] = c;
525 
526 }
527 
529 {
530  size_t count = m_files.count();
532 
533  // create non-repetitive values and not too large or small
535  double w = m_animation->m_spatialExtent.getWidth();
536  double h = m_animation->m_spatialExtent.getHeight();
537  int tam = 8;
538  double dw = w / (double)tam;
539  double dh = h / (double)tam;
540  size_t i = 0;
541  while (i < count)
542  {
543  m_route->setPoint(i, pos.x(), pos.y());
544  if (i++ & tam)
545  pos -= QPointF(dw, dh);
546  else
547  pos += QPointF(dw, dh);
548  }
549 }
void setImagePosition(const QPointF &p, const QRectF &dr)
Definition: ImageItem.cpp:39
virtual void drawCurrentImage(QPainter *p)
Get current image.
Definition: ImageItem.cpp:244
QPointF m_pos
The icon position.
QRectF m_imaRect
Image location.
Definition: ImageItem.h:203
#define TE_UNKNOWN_SRS
A numeric value to represent a unknown SRS identification in TerraLib.
virtual te::dt::TimeInstant getTime(QString file)=0
Get time of the raster data.
std::map< uchar, QColor > m_lut
LUT.
Definition: ImageItem.h:204
void calculateCurrentFile(const unsigned int &curTime)
Calculate current file.
Definition: ImageItem.cpp:476
te::gm::Envelope m_spatialExtent
Spatial extent.
Definition: Animation.h:109
std::unique_ptr< Point > getPointN(std::size_t i) const
It returns the specified point in this LineString.
ImageItem()
Empty Constructor.
Definition: ImageItem.cpp:14
double getWidth() const
It returns the envelope width.
virtual void loadCurrentImage()
Get current image.
Definition: ImageItem.cpp:188
A widget to control the display of a set of layers.
virtual bool loadData()
Load temporal raster data.
Definition: ImageItem.cpp:54
This file defines a abstarct class for a Image Item.
virtual ~ImageItem()
Destructor It destructs a Image Item.
static std::string fromUTF8(const std::string &src)
Convert a string in UTF-8 to the current locale encoding.
te::qt::widgets::MapDisplay * m_display
Indicates where the icon item is displayed.
A class to represent time instant.
Definition: TimeInstant.h:55
Animation * m_animation
The animation this item.
unsigned int line
void draw()
Draw the current image item.
Definition: ImageItem.cpp:470
double m_llx
Lower left corner x-coordinate.
int getClosestAnimationDataIndex(const double &trel)
It It gets the closest animation data index.
Definition: Animation.cpp:105
This file defines a class for a Animation Scene.
LineString is a curve with linear interpolation between points.
Definition: LineString.h:62
void setPoint(std::size_t i, const double &x, const double &y)
It sets the value of the specified point.
An Envelope defines a 2D rectangular region.
virtual bool getCtlParameters()
Get control parameters.
Definition: ImageItem.cpp:91
virtual void adjustDataToAnimationTemporalExtent()
Adjust data for a given time animation period.
TimeInstant getFinalTimeInstant() const
It gets the final time instant.
Definition: TimePeriod.cpp:50
virtual int getSRID() const
It return the Spatial Reference System used by the Map Display.
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:301
URI C++ Library.
Definition: Attributes.h:37
TimeInstant getInitialTimeInstant() const
It gets the initial time instant.
Definition: TimePeriod.cpp:45
#define PI
QVector< QString > m_files
The input files.
Definition: ImageItem.h:196
virtual const te::gm::Envelope & getExtent() const
It returns the world extent showned by the MapDisplay.
void adjustDataToAnimationTemporalExtent()
Adjust data for a given time animation period.
Definition: ImageItem.cpp:400
te::gm::Polygon * p
QRect getRect()
It gets image rect in device coordinate.
Definition: ImageItem.cpp:491
float m_undef
undef value.
Definition: ImageItem.h:195
unsigned int m_curTimeDuration
Current time (ms). Its value is between 0 and the total duration.
QImage m_staticRepresentation
Static representation of the animation.
Definition: ImageItem.h:206
QString m_title
The icon item title.
QDir m_dir
The image data directory.
Definition: ImageItem.h:192
double m_lly
Lower left corner y-coordinate.
QString m_currentImageFile
Image to be displayed on paint event animation.
Definition: ImageItem.h:198
A class to represent time period.
Definition: TimePeriod.h:54
This file defines a class for a Trajectory Animation.
QImage * m_image
current image
Definition: ImageItem.h:199
void generateRoute()
It generate the raster route.
Definition: ImageItem.cpp:528
QVector< QString > m_animationFiles
The png files in display projection. It contains only the portions to be animated.
Definition: ImageItem.h:197
te::dt::TimePeriod m_temporalExtent
Total temporal extent.
Definition: Animation.h:110
QString m_baseFile
Base file name.
Definition: ImageItem.h:200
An abstract class for Animation Item.
Definition: AnimationItem.h:64
QString m_preffix
File preffix.
Definition: ImageItem.h:202
void drawForward(const unsigned int &curTime)
Draw current image item. curTime The animation current time.
Definition: ImageItem.cpp:457
void erase(const unsigned int &curTime)
Draw current image item. curTime The animation current time.
Definition: ImageItem.cpp:465
QString m_suffix
File suffix.
Definition: ImageItem.h:201
te::gm::LineString * m_route
The input path in world coordenates.
QMatrix m_matrix
The display transformation matrix.
void transform(int oldsrid, int newsrid)
It will transform the coordinates of the Envelope from the old SRS to the new one.
double getHeight() const
It returns the envelope height.
int m_SRID
The input route srid.
te::dt::TimePeriod m_temporalAnimationExtent
Temporal animation extent. It can be a portion of the total or greater than the total.
Definition: Animation.h:111
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
Paint a image item.
Definition: ImageItem.cpp:448
file(WRITE ${CMAKE_BINARY_DIR}/config_qhelp.cmake"configure_file (${TERRALIB_ABSOLUTE_ROOT_DIR}/doc/qhelp/help.qhcp.in ${CMAKE_BINARY_DIR}/share/terraview/help/help.qhcp @ONLY)") add_custom_command(OUTPUT del_dir COMMAND $
unsigned int m_duration
The duration this item.
void transform(int srid)
It converts the coordinate values of the linestring to the new spatial reference system.
void setLUT(const std::vector< std::pair< int, QColor > > &tab)
Sets the LUT. tab The LUT information.
Definition: ImageItem.cpp:504
QVector< te::dt::TimeInstant > m_time
The input time.