ScaleWidget.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/ScaleWidget.cpp
22 */
23 
24 #include "ScaleWidget.h"
25 
26 // TerraLib
27 #include "../../../common/STLUtils.h"
28 #include "../../../maptools/Utils.h"
29 #include "../Utils.h"
30 #include "MapDisplay.h"
31 
32 // Qt
33 #include <QFont>
34 #include <QIcon>
35 #include <QMap>
36 #include <QPainter>
37 
38 //! Definitions
39 #define TD_KM "KILOMETRE"
40 #define TD_MT "METRE"
41 #define TD_DG "DEGREE"
42 #define TD_FT "FEET"
43 #define SD_KM QObject::tr("Kilometers")
44 #define SD_MT QObject::tr("Meters")
45 #define SD_DG QObject::tr("Degrees")
46 #define SD_FT QObject::tr("Feet")
47 
48 /** @name Internally methods.
49 * Methods used internally by the ScaleWidget objects.
50 */
51 //@{
52 
53 /*!
54 \brief Returns the height needed to show the header section.
55 \param font The font to be used.
56 \return
57 */
58 int CalculateHeaderHeight(const QFont& font)
59 {
60  QFontMetrics fm(font);
61 
62  return fm.height();
63 }
64 
65 /*!
66 \brief Returns the height needed to show the ruler section.
67 \param device Device to draw.
68 \param heightMM The ruler height in millimeters.
69 \param printer True if the device is a printer.
70 \return The minimum height needed to show the ruler section.
71 */
72 int CalculateScaleHeight(const QPaintDevice* device, const int& heightMM, const bool& printer)
73 {
74  int mm = heightMM;
75 
76  return te::qt::widgets::MillimetersToPixels(device, mm, printer);
77 }
78 
79 /*!
80 \brief Returns the unit in the formatting being used.
81 \param displayUnit Unit being used in the display.
82 \return The unit with the name used in the scale object.
83 */
84 QString GetScaleUnit(const std::string& displayUnit)
85 {
86  if (displayUnit == TD_KM)
87  return SD_KM;
88 
89  if (displayUnit == TD_MT)
90  return SD_MT;
91 
92  if (displayUnit == TD_DG)
93  return SD_DG;
94 
95  return SD_FT;
96 }
97 
98 /*!
99 \brief Returns the height needed to show the footer section.
100 \param font The font to be used.
101 \param visible True if the footer is visible and false otherwise.
102 \return The minimum height needed to show the footer section.
103 */
104 int CalculateFooterHeight(const QFont& font, const bool& visible)
105 {
106  if (!visible)
107  return 0;
108 
109  QFontMetrics fm(font);
110 
111  return fm.height();
112 }
113 
114 /*!
115 \brief Returns the minimum width required to draw the header section.
116 \param device Device to draw.
117 \param font The font to be used.
118 \param intervals Intervals in millimeters.
119 \param values Intervals in the selected unit of measure.
120 \param printer True if the device is a printer.
121 \return The minimum width required to draw the header section.
122 */
123 int GetMinimumHeaderWidth(const QPaintDevice* device, const QFont& font, const std::vector<double>& intervals, const std::vector<double>& values, const bool& printer)
124 {
125  QFontMetrics fm(font);
126 
127  int iniValue = fm.width(QString::number(values[0])),
128  finalValue = fm.width(QString::number(values[values.size() - 1])),
129  rulerPixels = te::qt::widgets::MillimetersToPixels(device, intervals[intervals.size() - 1], printer);
130 
131  int minW = (iniValue / 2) + (finalValue / 2) + rulerPixels;
132 
133  return minW;
134 }
135 
136 /*!
137 \brief Returns the minimum width required to draw the ruler section.
138 \param device Device to draw.
139 \param intervals Intervals in millimeters.
140 \param printer True if the device is a printer.
141 \return The minimum width required to draw the ruler section.
142 */
143 int GetMinimumScaleWidth(const QPaintDevice* device, const std::vector<double>& intervals, const bool& printer)
144 {
145  int rulerW = te::qt::widgets::MillimetersToPixels(device, intervals[intervals.size() - 1], printer);
146 
147  return rulerW;
148 }
149 
150 /*!
151 \brief Returns the minimum width required to draw the footer section.
152 \param font The font to be used.
153 \param unit The unit of measure being used.
154 \param factor Scaling factor.
155 \return The minimum width required to draw the footer section.
156 */
157 int GetMinimumFooterWidth(const QFont& font, const QString& unit, const int& factor)
158 {
159  QFontMetrics fm(font);
160 
161  QString value = QString("1 : %1 ( %2 )").arg(factor).arg(unit);
162 
163  int pixelsWide = fm.width(value);
164 
165  return pixelsWide;
166 }
167 
168 /*!
169 \brief Returns the minimum width in pixels required by the widget.
170 \param device Device to draw.
171 \param headerFont Font of the header section.
172 \param footerFont Font of the footer section.
173 \param intervals Values of the intervals in millimeters.
174 \param values Values fo the intervals in the unit of measure being used.
175 \param unit The unit fo mesaure being used.
176 \param factor Scaling factor.
177 \param printer True if the device is a printer.
178 \return The minimum width in pixels required by the widget.
179 */
180 int GetMinimumWidth(const QPaintDevice* device, const QFont& headerFont, const QFont& footerFont, const std::vector<double>& intervals, const std::vector<double>& values, const QString& unit,
181  const int& factor, const bool& printer)
182 {
183  int footerW = GetMinimumFooterWidth(footerFont, unit, factor),
184  headerW = GetMinimumHeaderWidth(device, headerFont, intervals, values, printer);
185 
186  if (headerW > footerW)
187  return headerW;
188 
189  return footerW;
190 }
191 
192 /*!
193 \brief Returns the minimum height in pixels required by the widget.
194 \param device Device to draw.
195 \param headerFont Font of the header section.
196 \param footerFont Font of the footer section.
197 \param rulerHeightMM The height of the ruler in millimeters.
198 \param numericScaleVisible Visibility of the footer section.
199 \param printer True if the device is a printer.
200 \return The minimum height in pixels required by the widget.
201 */
202 int GetMinimumHeight(const QPaintDevice* device, const QFont& headerFont, const QFont& footerFont, const int& rulerHeightMM,
203  const bool& numericScaleVisible, const bool& printer)
204 {
205  int h_margin = te::qt::widgets::MillimetersToPixels(device, 2., printer);
206 
207  int hh = CalculateHeaderHeight(headerFont),
208  sh = CalculateScaleHeight(device, rulerHeightMM, printer),
209  fh = CalculateFooterHeight(footerFont, numericScaleVisible);
210 
211  int h = hh + sh + h_margin;
212 
213  if (fh > 0)
214  h += fh + h_margin;
215 
216  return h;
217 }
218 
219 /*!
220 \brief Returns the minimum dimensions required to draw the widget.
221 \param device Device to draw.
222 \param headerFont Font of the header section.
223 \param footerFont Font of the footer section.
224 \param heightMM The height of the ruler in millimeters.
225 \param intervals Values of the intervals in millimeters.
226 \param values Values fo the intervals in the unit of measure being used.
227 \param printer True if the device is a printer.
228 \param numericScaleVisible Visibility of the footer section.
229 \param unit The unit fo mesaure being used.
230 \param factor Scaling factor.
231 \return The minimum dimensions required to draw the widget.
232 */
233 QSize GetComponentSize(const QPaintDevice* device, const QFont& headerFont, const QFont& footerFont, const int& heightMM, const std::vector<double>& intervals,
234  const std::vector<double>& values, const bool& printer, const bool& numericScaleVisible, const QString& unit, const int& factor)
235 {
236  return QSize(GetMinimumWidth(device, headerFont, footerFont, intervals, values, unit, factor, printer) + 1,
237  GetMinimumHeight(device, headerFont, footerFont, heightMM, numericScaleVisible, printer) + 1);
238 }
239 
240 /*!
241 \brief Returns a pixmap with the ruler representation of the graphic scale.
242 \param device Device to draw.
243 \param heightMM The height of the ruler in millimeters.
244 \param intervals Values of the intervals in millimeters.
245 \param beginsBlack True if the first interval must be colored, false otherwise.
246 \param color The color to be used.
247 \param printer True if the device is a printer.
248 \return A pixmap with the ruler representation of the graphic scale.
249 */
250 QPixmap* GetDashedScale(const QPaintDevice* device, const int& heightMM, const std::vector<double>& intervals, const bool& beginsBlack, const QColor& color, const bool& printer)
251 {
252  int w = GetMinimumScaleWidth(device, intervals, printer),
253  h = CalculateScaleHeight(device, heightMM, printer);
254 
255  QPixmap* pix = new QPixmap(w + 1, h + 1);
256 
257  pix->fill(Qt::transparent);
258 
259  QPainter p(pix);
260 
261  QRect rect(0, 0, w, h);
262 
263  p.fillRect(rect, Qt::white);
264 
265  QPen pen(color, 1);
266 
267  p.setPen(pen);
268 
269  for (size_t i = (beginsBlack) ? 0 : 1; i < intervals.size() - 1; i+=2)
270  {
271  int x = te::qt::widgets::MillimetersToPixels(device, intervals[i], printer),
272  next_x = te::qt::widgets::MillimetersToPixels(device, intervals[i+1], printer);
273 
274  QPoint topLeft(x, 0),
275  bottomRight(next_x, h);
276 
277  QRect r(topLeft, bottomRight);
278 
279  p.fillRect(r, color);
280  }
281 
282  p.drawRect(rect);
283 
284  return pix;
285 }
286 
287 /*!
288 \brief Returns a representation of two dashed scales one on top of the other with opposite begining intervals.
289 \param device Device to draw.
290 \param heightMM The height of the ruler in millimeters.
291 \param intervals Values of the intervals in millimeters.
292 \param beginsBlack True if the first interval must be colored, false otherwise.
293 \param color The color to be used.
294 \param printer True if the device is a printer.
295 \return A representation of two dashed scales one on top of the other with opposite begining intervals.
296 */
297 QPixmap* GetDoubleDashedScale(const QPaintDevice* device, const int& heightMM, const std::vector<double> intervals, const bool& beginsBlack, const QColor& color, const bool& printer)
298 {
299 // double widthMM = intervals[intervals.size() - 1];
300  double hMM = (heightMM <= 1) ? 2 : heightMM;
301 
302 // int w = GetMinimumScaleWidth(device, intervals, printer),
303 // h = CalculateScaleHeight(device, hMM, printer);
304 
305  QPixmap* p1 = GetDashedScale(device, static_cast<int>(hMM / 2), intervals, beginsBlack, color, printer);
306  QPixmap* p2 = GetDashedScale(device, static_cast<int>(hMM / 2), intervals, !beginsBlack, color, printer);
307 
308  QPixmap* pix = new QPixmap(p1->width(), p1->height() + p2->height() - 1);
309 
310  QPainter p(pix);
311 
312  p.setCompositionMode(QPainter::CompositionMode_SourceOver);
313 
314  p.drawPixmap(0, 0, *p1);
315  p.drawPixmap(0, p1->height() - 1, *p2);
316 
317  delete p1;
318  delete p2;
319 
320  return pix;
321 }
322 
323 /*!
324 \brief Returns a ruler representation graphic scale.
325 \param device Device to draw.
326 \param heightMM The height of the ruler in millimeters.
327 \param intervals Values of the intervals in millimeters.
328 \param color The color to be used.
329 \param printer True if the device is a printer.
330 \return A ruler representation graphic scale.
331 */
332 QPixmap* GetRulerScale(const QPaintDevice* device, const double& heightMM, const std::vector<double>& intervals, const QColor& color, const bool& printer)
333 {
334  int hMM = static_cast<int>(heightMM);
335 
336  if (hMM < 1)
337  hMM = 1;
338 
339 // double widthMM = intervals[intervals.size()- 1];
340 
341  int w = GetMinimumScaleWidth(device, intervals, printer),
342  h = CalculateScaleHeight(device, hMM, printer);
343 
344  QPixmap* pix = new QPixmap(w + 1, h + 1);
345 
346  pix->fill(Qt::transparent);
347 
348  int xf = w,
349  y = h;
350 
351  QPainter p(pix);
352 
353  QPen pen(color, 1);
354 
355  p.setPen(pen);
356 
357  p.drawLine(0, y, xf, y);
358 
359  for (size_t i = 0; i < intervals.size(); i++)
360  {
361  int ini = te::qt::widgets::MillimetersToPixels(device, intervals[i], printer);
362 
363  p.drawLine(ini, 0, ini, y);
364  }
365 
366  return pix;
367 }
368 
369 
370 /*!
371 \brief Returns a rounded value of interval in unit measure.
372 \param factor Scaling factor.
373 \return A rounded value of interval in unit measure.
374 \note The value, in the most of times, is greater then the measure represented by 1cm.
375 */
376 double GetSweetGapValue(const double& factor)
377 {
378  double www = factor;
379  double dx = www / 9.; // Why???
380  long idx = static_cast<long>(dx);
381  double f = 0;
382  double fa = 1.;
383 
384  int conta = 1000;
385 
386  if (idx > 0)
387  {
388  while (--conta)
389  {
390  dx /= 10.;
391  fa *= 10.;
392  idx = static_cast<long>(dx);
393  if (idx == 0)
394  {
395  idx = static_cast<long>(dx * 10.);
396  f = idx * fa / 10.;
397  break;
398  }
399  }
400  }
401  else
402  {
403  while (--conta)
404  {
405  dx *= 10.;
406  fa /= 10.;
407  idx = static_cast<long>(dx);
408  if (idx > 0)
409  {
410  f = idx * fa;
411  break;
412  }
413  }
414  }
415 
416  if (conta == 0)
417  return 0;
418 
419  return f * 10;
420 }
421 
422 /*!
423 \brief Returns the calculated intervals in millimeters and in unit of measure.
424 \param breaks Number of values that determines the intervals on the ruler.
425 \param[out] values Values of the intervals in the current unit of measure.
426 \param[out] intervals Values of intervals in millimeters.
427 \param unitsPerInterval Number of units of scaling will be used in intervals.
428 \param factor Scaling factor.
429 */
430 void GetIntervals(const int& breaks, std::vector<double>& values, std::vector<double>& intervals, const int& unitsPerInterval, const double& factor)
431 {
432  double gap = GetSweetGapValue(factor) * unitsPerInterval;
433  double gapMM = 10 * gap / factor; // Giving the scale in centimeters.
434  double value = 0,
435  interval = 0;
436 
437  values.push_back(value);
438 
439  intervals.push_back(interval);
440 
441  for (int i = 1; i < breaks; i++)
442  {
443  value = i * gapMM;
444  interval = i * gap;
445 
446  values.push_back(value);
447  intervals.push_back(interval);
448  }
449 }
450 
451 /*!
452 \brief Returns a pixmap with the header section of the graphic scale.
453 \param device Device to draw.
454 \param font Header font.
455 \param color Header color.
456 \param intervals Values of intervals in millimeters.
457 \param values Values of intervals in units of measure.
458 \param showAllValues True to show intermediary values ont the header section, false otherwise.
459 \param printer True if the device is a printer.
460 \param[out] pixmapOffset Half of the width of the first value. This value is returned to be used to draw the ruler section in the correct position.
461 \param toLong If the values of the header are long type values. (If unit is "Degrees" turn off this argument).
462 \return A pixmap with the header section of the graphic scale.
463 */
464 QPixmap* MakeHeader(const QPaintDevice* device, const QFont& font, const QColor& color, const std::vector<double>& intervals, const std::vector<double>& values, const bool& showAllValues,
465  const bool& printer, int& pixmapOffset, const bool& toLong)
466 {
467  int w = GetMinimumHeaderWidth(device, font, intervals, values, printer),
468  h = CalculateHeaderHeight(font);
469 
470  QPixmap* pix = new QPixmap(w+1, h+1);
471 
472  pix->fill(Qt::transparent);
473 
474  QFontMetrics fm(font);
475 
476  int sub_w,
477  sub_h = fm.height() + 1;
478 
479  std::vector<QPixmap*> sub_pixs;
480 
481  QPainter p;
482  QPen pen(color, 2);
483 
484  // Create legend pixmaps
485  for (size_t i = 0; i < values.size(); i++)
486  {
487  QString v = (toLong) ? QString::number(static_cast<long>(values[i])) : QString::number(values[i]);
488 
489  // Width in pixels of the value
490  sub_w = fm.width(v);
491 
492  // Draw the value of legend
493  QPixmap* sub_pix = new QPixmap(sub_w + 1, sub_h + 1);
494 
495  sub_pix->fill(Qt::transparent);
496  p.begin(sub_pix);
497 
498  p.setPen(pen);
499  p.setFont(font);
500 
501  p.drawText(QRect(0, 0, sub_w, sub_h), Qt::AlignLeft, v);
502 
503  sub_pixs.push_back(sub_pix);
504 
505  p.end();
506  }
507 
508  pixmapOffset = (sub_pixs[0]->width() / 2);
509 
510  p.begin(pix);
511 
512 
513  // 1st element
514  QPixmap* sub_pix = sub_pixs[0];
515  QRect rec = sub_pix->rect();
516 
517  p.drawPixmap(rec, *sub_pix);
518  // ============================
519 
520  // lst element
521  sub_pix = sub_pixs[values.size() - 1];
522  rec = sub_pix->rect();
523 
524  int offset = te::qt::widgets::MillimetersToPixels(device, intervals[intervals.size() - 1], printer) + pixmapOffset;
525 
526  QPoint c(offset, rec.height() / 2);
527 
528  rec.moveCenter(c);
529 
530  p.drawPixmap(rec, *sub_pix);
531  //============================
532 
533  if (showAllValues)
534  {
535  // Draw sub pixmaps centralized
536  for (size_t i = 1; i < intervals.size() - 1; i++)
537  {
538  sub_pix = sub_pixs[i];
539  rec = sub_pix->rect();
540 
541  int offset = te::qt::widgets::MillimetersToPixels(device, intervals[i], printer) + pixmapOffset;
542 
543  QPoint c(offset, rec.height() / 2);
544 
545  rec.moveCenter(c);
546 
547  p.drawPixmap(rec, *sub_pix);
548  }
549  }
550 
551  te::common::FreeContents(sub_pixs);
552 
553  return pix;
554 }
555 
556 /*!
557 \brief Returns a pixmap with the footer section of the graphic scale.
558 \param factor Scaling factor.
559 \param unit Unit of measure being used.
560 \param font Footer font.
561 \param color Footer color.
562 \return A pixmap with the footer section of the graphic scale.
563 */
564 QPixmap* MakeFooter(const int& factor, const QString& unit, const QFont& font, const QColor& color)
565 {
566  QFontMetrics fm(font);
567 
568  QString value = QString("1 : %1 ( %2 )").arg(factor).arg(unit);
569 
570  int pixelsWide = fm.width(value),
571  pixelsHigh = fm.height();
572 
573  QPixmap* pix = new QPixmap(pixelsWide + 1, pixelsHigh + 1);
574 
575  pix->fill(Qt::transparent);
576 
577  QPainter p(pix);
578  QPen pen(color, 1);
579 
580  p.setPen(pen);
581 
582  p.setFont(font);
583 
584  p.drawText(QRect(0, 0, pixelsWide, pixelsHigh), Qt::AlignLeft, value);
585 
586  return pix;
587 }
588 
589 /*!
590 \brief Repaints the widget.
591 \param device Device to draw.
592 \param headerFont Font of the header section.
593 \param headerColor Color of the header section.
594 \param allHeaderVisible True to show intermediary values ont the header section, false otherwise.
595 \param rulerColor Color of the ruler section.
596 \param intervals Values of intervals in millimeters.
597 \param values Values of intervals in units of measure.
598 \param heightMM Height of the ruler in millimeters.
599 \param showNumericScale True to show the footer section, false otherwise.
600 \param footerFont Font of the footer section.
601 \param footerColor Color of the footer section.
602 \param unit Unit of measure to be used.
603 \param factor Scaling factor.
604 \param printer True if the device is a printer.
605 \param type The type of the ruler to be drawed.
606 */
607 void RepaintWidget(QPaintDevice* device, const QFont& headerFont, const QColor& headerColor, const bool& allHeaderVisible, const QColor& rulerColor, const std::vector<double>& intervals,
608  const std::vector<double>& values, const int& heightMM, const bool& showNumericScale, const QFont& footerFont, const QColor& footerColor, const QString& unit, const double& factor,
609  const bool& printer, const te::qt::widgets::ScaleWidget::ScaleTypes& type)
610 {
611  int margin = te::qt::widgets::MillimetersToPixels(device, 1., printer), // vertical margin in pixels
612  pixOffset;
613 
614  QPixmap* header = MakeHeader(device, headerFont, headerColor, intervals, values, allHeaderVisible, printer, pixOffset, (unit != SD_DG));
615 
616  QPixmap* gScale = nullptr;
617 
618  QPixmap* footer = nullptr;
619 
620  switch (type)
621  {
623  gScale = GetDashedScale(device, heightMM, intervals, false, rulerColor, printer);
624  break;
625 
627  gScale = GetDashedScale(device, heightMM, intervals, true, rulerColor, printer);
628  break;
629 
631  gScale = GetRulerScale(device, heightMM, intervals, rulerColor, printer);
632  break;
633 
635  gScale = GetDoubleDashedScale(device, heightMM, intervals, true, rulerColor, printer);
636  break;
637 
639  gScale = GetDoubleDashedScale(device, heightMM, intervals, false, rulerColor, printer);
640  break;
641 
643  break;
644  }
645 
646  if (showNumericScale)
647  footer = MakeFooter(static_cast<int>(factor), unit, footerFont, footerColor);
648 
649  QPainter p(device);
650 
651  int centerX = device->width() / 2,
652  centerY = header->height() / 2;
653 
654  // Header
655  QRect hR = header->rect();
656  hR.moveCenter(QPoint(centerX, centerY));
657  p.drawPixmap(hR, *header);
658  // =============================
659 
660  // Ruler
661  int x = hR.x() + pixOffset,
662  y = hR.height() + margin;
663 
664  QRect sR = gScale->rect();
665 
666  sR.moveTo(QPoint(x, y));
667 
668  p.drawPixmap(sR, *gScale);
669  // =============================
670 
671  // Footer
672  if (footer != nullptr)
673  {
674  QRect fR = footer->rect();
675 
676  x = centerX;
677  y = header->height() + margin + gScale->height() + margin + (fR.height() / 2);
678 
679  fR.moveCenter(QPoint(x, y));
680 
681  p.drawPixmap(fR, *footer);
682  }
683  // =============================
684 
685  delete header;
686  delete gScale;
687  delete footer;
688 }
689 
690 /*!
691 \brief Returns the width of \a env in meters.
692 \param fromUnit Unit of measure being used by the display.
693 \param env The bounding rectangle to be transformed.
694 \param srid The identifier of the projection being used by the display.
695 \return The width of \a env in meters.
696 */
697 double ToMeters(const std::string& fromUnit, const te::gm::Envelope& env, const int& srid)
698 {
699  double w = env.getWidth();
700 
701  if (fromUnit == TD_MT)
702  return w;
703 
704  if (fromUnit == TD_DG)
705  {
706  if (env.getLowerLeftX() < -180. ||
707  env.getLowerLeftY() < -80. ||
708  env.getUpperRightX() > 180. ||
709  env.getUpperRightY() > 80.)
710  {
711  w = env.getWidth() * 111133.;
712  }
713  else
714  {
715  try
716  {
717  te::gm::Envelope planarEnvelope = te::map::GetWorldBoxInPlanar(env, srid);
718 
719  w = planarEnvelope.getWidth();
720  }
721  catch (...)
722  {
723  w = env.getWidth() * 111133.;
724  }
725  }
726 
727  return w;
728  }
729 
730  if (fromUnit == TD_KM)
731  return (w * 1000);
732 
733  return w * (12. * 25.4);
734 }
735 
736 /*!
737 \brief Returns the width of the \a env, that is in meters, to the destination unit of measure.
738 \param toUnit The destination unit of measure.
739 \param env The bounding rectangle to be transformed.
740 \param srid The identifier of the projection being used by the display.
741 \return The width of the \a env, that is in meters, to the destination unit of measure.
742 */
743 double GetWidthInUnit(const QString& toUnit, const te::gm::Envelope& env, const int& srid)
744 {
745  te::common::UnitOfMeasurePtr unitPtr = te::srs::SpatialReferenceSystemManager::getInstance().getUnit(static_cast<unsigned int>(srid));
746 
747  if (unitPtr == nullptr)
748  return env.getWidth();
749 
750  QString displayUnit = GetScaleUnit(unitPtr->getName());
751 
752  if (displayUnit == toUnit)
753  return env.getWidth();
754 
755  double w = ToMeters(unitPtr->getName(), env, srid);
756 
757  if (toUnit == SD_MT)
758  return w;
759 
760  if (toUnit == SD_DG)
761  return (w / 111133.);
762 
763  if (toUnit == SD_KM)
764  return (w / 1000);
765 
766  return w / (12. * 25.4);
767 }
768 
769 /*!
770 \brief Comparies the scale unit and the display unit and returns \a true if it is and \a false otherwise.
771 \param scaleUnit The scale unit selected.
772 \param displaySRID SRID being used in the display.
773 \return \a True if the units are equals and \a false otherwise.
774 */
775 bool CompareUnit(const QString& scaleUnit, const int& displaySRID)
776 {
777  te::common::UnitOfMeasurePtr unitPtr = te::srs::SpatialReferenceSystemManager::getInstance().getUnit(static_cast<unsigned int>(displaySRID));
778 
779  if (unitPtr == nullptr)
780  return false;
781 
782  QString dsUnit = GetScaleUnit(unitPtr->getName());
783 
784  return (dsUnit == scaleUnit);
785 }
786 
787 /*!
788 \brief Returns the scaling factor of the current visualized area in the display.
789 \param display The display being used.
790 \param unit Unit of measure to be used.
791 \param printer True if the device is a printer.
792 \return The scaling factor of the current visualized area in the display.
793 */
794 //@}
795 double GetScale(const te::qt::widgets::MapDisplay& display, const QString& unit, const bool& printer)
796 {
797  te::gm::Envelope world = display.getExtent();
798 
799  double ww = (CompareUnit(unit, display.getSRID())) ? world.getWidth() : GetWidthInUnit(unit, world, display.getSRID()), //world width
800  vw = display.width(), //viewport width
801  dpiX = (printer) ? display.physicalDpiX() : display.logicalDpiX(),
802  dpiY = (printer) ? display.physicalDpiY() : display.logicalDpiY(),
803  dotsPerMillimeter = (dpiX > dpiY) ? dpiX / 25.4 : dpiY / 25.4,
804  vwMM = vw / dotsPerMillimeter;
805 
806  double scale = 10 * ww / vwMM; // 1cm : scale
807 
808  return scale;
809 }
810 
811 void GetScalesIcons(QMap<int, QIcon>& icons, QStringList& typesNames, const QPaintDevice* device, const QColor& color)
812 {
813  std::vector<double> intervals;
814 
815  intervals.push_back(0);
816  intervals.push_back(2.);
817  intervals.push_back(4.);
818 
819  QSize size(32, 16);
820 
821  //RULER
822  QPixmap* pix = GetRulerScale(device, 2., intervals, color, false);
823  icons[te::qt::widgets::ScaleWidget::RULER] = QIcon(*pix);
824  typesNames.append(QObject::tr("Ruler"));
825 
826  delete pix;
827 
828  //DASHED
829  pix = GetDashedScale(device, 2., intervals, false, color, false);
830  icons[te::qt::widgets::ScaleWidget::DASHED] = QIcon(*pix);
831  typesNames.append(QObject::tr("Dashed"));
832 
833  delete pix;
834 
835  //DASHED_BEGIN_BLACK
836  pix = GetDashedScale(device, 2., intervals, true, color, false);
838  typesNames.append(QObject::tr("Dashed begins black"));
839 
840  delete pix;
841  //DOUBLE_DASHED
842  pix = GetDoubleDashedScale(device, 2., intervals, false, color, false);
843  icons[te::qt::widgets::ScaleWidget::DOUBLE_DASHED] = QIcon(*pix);
844  typesNames.append(QObject::tr("Double dashed"));
845 
846  delete pix;
847 
848  //DOUBLE_DASHED_BEGIN_BLACK
849  pix = GetDoubleDashedScale(device, 2., intervals, true, color, false);
851  typesNames.append(QObject::tr("Double dashed begins black"));
852 
853  delete pix;
854 
855  //CUSTOM
856 }
857 
858 te::qt::widgets::ScaleWidget::ScaleWidget(MapDisplay* parent, const bool& interactive) :
859 QFrame(parent, Qt::SubWindow),
860 m_bckGround(nullptr),
861 m_footerFont(QFont("times", 5)),
862 m_showNumericScale(true),
863 m_factor(50),
864 m_unit(SD_MT),
865 m_numberOfIntervals(3),
866 m_type(RULER),
867 m_rulerColor(Qt::black),
868 m_bckGrd(Qt::white),
869 m_interactionEnabled(interactive),
870 m_display(parent),
871 m_headerColor(m_rulerColor),
872 m_headerFont(m_footerFont),
873 m_headerAllVisible(true),
874 m_unitsPerGap(3),
875 m_footerColor(m_rulerColor),
876 m_rulerHeightMM(3)
877 {
878  m_footerFont.setPointSize(m_headerFont.pointSize() * 2);
879 
880  setAttribute(Qt::WA_TranslucentBackground);
881 
883 }
884 
886 {
887  delete m_bckGround;
888 }
889 
891 {
892  return m_interactionEnabled;
893 }
894 
896 {
897  return m_headerColor;
898 }
899 
901 {
902  return m_rulerColor;
903 }
904 
906 {
907  return m_footerColor;
908 }
909 
911 {
912  return m_headerFont;
913 }
914 
916 {
917  return m_footerFont;
918 }
919 
920 
922 {
923  return m_unit;
924 }
925 
927 {
928  return m_type;
929 }
930 
932 {
933  return m_showNumericScale;
934 }
935 
937 {
938  return m_headerAllVisible;
939 }
940 
942 {
943  return m_unitsPerGap;
944 }
945 
947 {
948  return m_rulerHeightMM;
949 }
950 
952 {
953  return m_numberOfIntervals;
954 }
955 
957 {
958  if (m_display == nullptr)
959  return;
960 
961  QRect dr = m_display->rect(), // Display rectangle
962  sr = QFrame::geometry(); // Scale rectangle
963 
964  if (m_interactionEnabled && dr.contains(sr))
965  return;
966 
967  int twoMM = te::qt::widgets::MillimetersToPixels(this, 2., false); // 2MM vertical margin
968 
969  int newCenterX = dr.center().x(),
970  newCenterY = dr.height() - (sr.height() / 2) - twoMM;
971 
972  sr.moveCenter(QPoint(newCenterX, newCenterY));
973 
974  QFrame::setGeometry(sr);
975 }
976 
978 {
979  te::common::UnitOfMeasurePtr unitPtr = te::srs::SpatialReferenceSystemManager::getInstance().getUnit(static_cast<unsigned int>(SRID));
980 
981  if (unitPtr == nullptr)
982  return;
983 
984  setUnit(GetScaleUnit(unitPtr->getName()));
985 }
986 
988 {
989  m_interactionEnabled = state;
990 
991  setAttribute(Qt::WA_TransparentForMouseEvents, !state);
992 
993  redoWidget();
994 }
995 
997 {
998  m_factor = GetScale(m_display, m_unit, false);
999 
1000  redoWidget();
1001 }
1002 
1004 {
1005  m_headerColor = color;
1006 
1007  redoWidget();
1008 }
1009 
1011 {
1012  m_rulerColor = color;
1013 
1014  redoWidget();
1015 }
1016 
1018 {
1019  m_footerColor = color;
1020 
1021  redoWidget();
1022 }
1023 
1024 
1026 {
1027  m_bckGrd = color;
1028 
1029  redoWidget();
1030 }
1031 
1033 {
1034  m_headerFont = font;
1035 
1036  redoWidget();
1037 }
1038 
1040 {
1041  m_footerFont = font;
1042 
1043  redoWidget();
1044 }
1045 
1046 void te::qt::widgets::ScaleWidget::setUnit(const QString& unit)
1047 {
1048  m_unit = unit;
1049 
1050  redoWidget();
1051 }
1052 
1054 {
1055  m_type = static_cast<ScaleTypes>(type);
1056 
1057  redoWidget();
1058 }
1059 
1061 {
1062  m_showNumericScale = visible;
1063 
1064  redoWidget();
1065 }
1066 
1068 {
1069  m_headerAllVisible = visible;
1070 
1071  redoWidget();
1072 }
1073 
1075 {
1076  m_unitsPerGap = units;
1077 
1078  redoWidget();
1079 }
1080 
1082 {
1083  m_rulerHeightMM = hMM;
1084 
1085  redoWidget();
1086 }
1087 
1089 {
1090  m_numberOfIntervals = v;
1091 
1092  redoWidget();
1093 }
1094 
1096 {
1097  m_intervals.clear();
1098  m_values.clear();
1099 
1100  m_factor = GetScale(*m_display, m_unit, false);
1101 
1103 
1105  static_cast<int>(m_factor));
1106 
1107  setFixedSize(s);
1108  setMinimumSize(s);
1109 
1110  m_bckGround = GetCleanImage(s, (m_interactionEnabled) ? m_bckGrd : Qt::transparent);
1111 
1113  m_unit, m_factor, false, m_type);
1114 
1115  update();
1116 
1118 }
1119 
1121 {
1122  QPainter p(this);
1123 
1124  p.drawPixmap(0, 0, *m_bckGround);
1125 
1126  QFrame::paintEvent(event);
1127 }
1128 
1130 {
1131  emit aboutToBeclosed();
1132 
1133  QFrame::closeEvent(event);
1134 }
int GetMinimumWidth(const QPaintDevice *device, const QFont &headerFont, const QFont &footerFont, const std::vector< double > &intervals, const std::vector< double > &values, const QString &unit, const int &factor, const bool &printer)
Returns the minimum width in pixels required by the widget.
QString getUnit() const
Returns the unit being used to present the graphic scale.
#define TD_DG
Definition: ScaleWidget.cpp:41
void paintEvent(QPaintEvent *event)
Reimplementation of the QFrame method.
Alternated rectangles and alternated colors, beginning with a colored one, whith two rulers...
Definition: ScaleWidget.h:114
void setFooterColor(const QColor &color)
Changes the color of the footer.
QFont getFooterFont() const
Returns the value of the font of the footer.
void setRulerColor(const QColor &color)
Changes the color of the ruler.
bool m_interactionEnabled
Flag for enabling / disabling the interactive mode.
Definition: ScaleWidget.h:407
QFont m_footerFont
Font of the footer section.
Definition: ScaleWidget.h:397
static te::dt::Date dx(2010, 12, 31)
void setScaleType(const int &type)
Sets the type of ruler to be presented.
void setFooterFont(const QFont &font)
Changes the font of the footer.
std::vector< double > m_intervals
Values of the intervals in millimeters.
Definition: ScaleWidget.h:401
double GetScale(const te::qt::widgets::MapDisplay &display, const QString &unit, const bool &printer)
Returns the scaling factor of the current visualized area in the display.
ScaleWidget(MapDisplay *parent, const bool &interactive=false)
Constructor.
int m_rulerHeightMM
Height of the ruler in millimeters.
Definition: ScaleWidget.h:414
const double & getUpperRightX() const
It returns a constant refernce to the x coordinate of the upper right corner.
void GetScalesIcons(QMap< int, QIcon > &icons, QStringList &typesNames, const QPaintDevice *device, const QColor &color)
Returns icons and the respective names for the types of rulers that can be used to present the graphi...
bool m_showNumericScale
Flag for enabling / disabling visibility of the footer section.
Definition: ScaleWidget.h:398
int getScaleType() const
Returns the ruler type being used.
QFont getHeaderFont() const
Returns the value of the font of the header.
QColor getFooterColor() const
Returns the value of the color of the footer.
void setRulerHeightMM(const int &hMM)
Updates the heightness of the ruler.
QColor m_bckGrd
Background color.
Definition: ScaleWidget.h:406
const double & getLowerLeftY() const
It returns a constant refernce to the y coordinate of the lower left corner.
void RepaintWidget(QPaintDevice *device, const QFont &headerFont, const QColor &headerColor, const bool &allHeaderVisible, const QColor &rulerColor, const std::vector< double > &intervals, const std::vector< double > &values, const int &heightMM, const bool &showNumericScale, const QFont &footerFont, const QColor &footerColor, const QString &unit, const double &factor, const bool &printer, const te::qt::widgets::ScaleWidget::ScaleTypes &type)
Repaints the widget.
double getWidth() const
It returns the envelope width.
void closeEvent(QCloseEvent *event)
Reimplementation of the QFrame method.
A widget to control the display of a set of layers.
A Qt4 widget to control the display of a set of layers.
const double & getUpperRightY() const
It returns a constant refernce to the x coordinate of the upper right corner.
int CalculateHeaderHeight(const QFont &font)
Returns the height needed to show the header section.
Definition: ScaleWidget.cpp:58
int m_numberOfIntervals
Number of intervals of the ruler.
Definition: ScaleWidget.h:403
std::vector< double > m_values
Values of the intervals in the selected unit of measure.
Definition: ScaleWidget.h:402
ScaleTypes m_type
Type of the ruler to be presented.
Definition: ScaleWidget.h:404
void setUnitsPerGap(const int &units)
Changes the number of units to used per interval.
int m_unitsPerGap
Number of units to be used by each interval.
Definition: ScaleWidget.h:412
Alternated rectangles and alternated colors, beginning with a white one.
Definition: ScaleWidget.h:111
bool CompareUnit(const QString &scaleUnit, const int &displaySRID)
Comparies the scale unit and the display unit and returns true if it is and false otherwise...
int GetMinimumHeaderWidth(const QPaintDevice *device, const QFont &font, const std::vector< double > &intervals, const std::vector< double > &values, const bool &printer)
Returns the minimum width required to draw the header section.
QPixmap * GetDoubleDashedScale(const QPaintDevice *device, const int &heightMM, const std::vector< double > intervals, const bool &beginsBlack, const QColor &color, const bool &printer)
Returns a representation of two dashed scales one on top of the other with opposite begining interval...
QPixmap * GetDashedScale(const QPaintDevice *device, const int &heightMM, const std::vector< double > &intervals, const bool &beginsBlack, const QColor &color, const bool &printer)
Returns a pixmap with the ruler representation of the graphic scale.
int GetMinimumScaleWidth(const QPaintDevice *device, const std::vector< double > &intervals, const bool &printer)
Returns the minimum width required to draw the ruler section.
#define TD_MT
Definition: ScaleWidget.cpp:40
int CalculateFooterHeight(const QFont &font, const bool &visible)
Returns the height needed to show the footer section.
static SpatialReferenceSystemManager & getInstance()
It returns a reference to the singleton instance.
int CalculateScaleHeight(const QPaintDevice *device, const int &heightMM, const bool &printer)
Returns the height needed to show the ruler section.
Definition: ScaleWidget.cpp:72
QPixmap * GetRulerScale(const QPaintDevice *device, const double &heightMM, const std::vector< double > &intervals, const QColor &color, const bool &printer)
Returns a ruler representation graphic scale.
Alternated rectangles and alternated colors, beginning with a colored one.
Definition: ScaleWidget.h:112
An Envelope defines a 2D rectangular region.
QColor getHeaderColor() const
Returns the value of the color of the header.
#define SD_DG
Definition: ScaleWidget.cpp:45
QColor m_footerColor
Color of the footer section.
Definition: ScaleWidget.h:413
void setBackgroundColor(const QColor &color)
Changes the color of the background.
void redoWidget()
Recalculates and redraw the graphic scale based on the values of its internal attributes.
virtual int getSRID() const
It return the Spatial Reference System used by the Map Display.
QFont m_headerFont
Font of the header section.
Definition: ScaleWidget.h:410
int getUnitsPerGap() const
Returns the number of units used in each gap.
QPixmap * m_bckGround
Background pixmap.
Definition: ScaleWidget.h:396
bool getAllHeaderIsVisible() const
Returns the visibilty of the intermediary values on the header section.
virtual const te::gm::Envelope & getExtent() const
It returns the world extent showned by the MapDisplay.
void GetIntervals(const int &breaks, std::vector< double > &values, std::vector< double > &intervals, const int &unitsPerInterval, const double &factor)
Returns the calculated intervals in millimeters and in unit of measure.
int GetMinimumHeight(const QPaintDevice *device, const QFont &headerFont, const QFont &footerFont, const int &rulerHeightMM, const bool &numericScaleVisible, const bool &printer)
Returns the minimum height in pixels required by the widget.
#define SD_MT
Definition: ScaleWidget.cpp:44
bool getInteractionHandle() const
Returns the value of the interaction mode.
void setUnit(const int &SRID)
Sets the unit using SRID.
te::gm::Polygon * p
QPixmap * MakeFooter(const int &factor, const QString &unit, const QFont &font, const QColor &color)
Returns a pixmap with the footer section of the graphic scale.
MapDisplay * m_display
Pointer to the display where to present the widget.
Definition: ScaleWidget.h:408
QSize GetComponentSize(const QPaintDevice *device, const QFont &headerFont, const QFont &footerFont, const int &heightMM, const std::vector< double > &intervals, const std::vector< double > &values, const bool &printer, const bool &numericScaleVisible, const QString &unit, const int &factor)
Returns the minimum dimensions required to draw the widget.
#define SD_FT
Definition: ScaleWidget.cpp:46
void setAllHeaderVisible(const bool &visible)
Enable / disable intermediary values of the header.
double ToMeters(const std::string &fromUnit, const te::gm::Envelope &env, const int &srid)
Returns the width of env in meters.
int GetMinimumFooterWidth(const QFont &font, const QString &unit, const int &factor)
Returns the minimum width required to draw the footer section.
bool getNumericScaleIsVisible() const
Returns the visibility of the footer section.
double m_factor
Factor of scaling being used.
Definition: ScaleWidget.h:399
int getNumberOfIntervals() const
Returns the number of intervals being used by ruler.
boost::shared_ptr< UnitOfMeasure > UnitOfMeasurePtr
ScaleTypes
Defines the different types of rulers we can use to present the graphical scale.
Definition: ScaleWidget.h:108
QPixmap * GetCleanImage(const QSize &s, const QColor &c)
Returns a transparent pixmap of size s.
double GetSweetGapValue(const double &factor)
Returns a rounded value of interval in unit measure.
#define TD_KM
Definitions.
Definition: ScaleWidget.cpp:39
QColor getRulerColor() const
Returns the value of the color of the ruler.
const double & getLowerLeftX() const
It returns a constant reference to the x coordinate of the lower left corner.
void updateScalePosition()
Changes the current position of the widget, centralizing it in the display.
QColor m_headerColor
Color of the header section.
Definition: ScaleWidget.h:409
bool m_headerAllVisible
Flag do enabling / disabling of the intermediary values of the header.
Definition: ScaleWidget.h:411
void setNumberOfIntervals(const int &v)
Updates the number of intervals of the ruler.
QString GetScaleUnit(const std::string &displayUnit)
Returns the unit in the formatting being used.
Definition: ScaleWidget.cpp:84
double GetWidthInUnit(const QString &toUnit, const te::gm::Envelope &env, const int &srid)
Returns the width of the env, that is in meters, to the destination unit of measure.
TEQTWIDGETSEXPORT int MillimetersToPixels(const QPaintDevice *device, const double &mm, const bool &printer)
Returns the size in pixels.
void FreeContents(boost::unordered_map< K, V * > &m)
This function can be applied to a map of pointers. It will delete each pointer in the map...
Definition: BoostUtils.h:55
QPixmap * MakeHeader(const QPaintDevice *device, const QFont &font, const QColor &color, const std::vector< double > &intervals, const std::vector< double > &values, const bool &showAllValues, const bool &printer, int &pixmapOffset, const bool &toLong)
Returns a pixmap with the header section of the graphic scale.
void setHeaderColor(const QColor &color)
Changes the color of the header.
QString m_unit
Unit of measure being used.
Definition: ScaleWidget.h:400
void setNumericScaleVisble(const bool &visible)
Enable / disable the visibility of the footer or the numeric scale.
void setHeaderFont(const QFont &font)
Changes the font of the header.
Alternated rectangles and alternated colors, beginning with a white one, whith two rulers...
Definition: ScaleWidget.h:113
int getRulerHeightMM() const
Returns the lenght of the ruler in millimeters.
Contains an implementation of a graphic scale.
void updateScaleFactor()
Updates the scale values.
TEMAPEXPORT te::gm::Envelope GetWorldBoxInPlanar(const te::gm::Envelope &worldBox, int srid)
It gets the requested envelope on a UTM planar projection.
void setInteractionHandle(const bool &state)
Enable / disable the interaction mode.
QColor m_rulerColor
Color of the ruler section.
Definition: ScaleWidget.h:405
#define SD_KM
Definition: ScaleWidget.cpp:43