qt/widgets/canvas/Grid.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 canvas/Grid.cpp
22  */
23 
24 #include "Grid.h"
25 
26 // TerraLib
27 #include "../../../common/StringUtils.h"
28 #include "../../../geometry/Envelope.h"
29 #include "../../../geometry/MultiLineString.h"
30 #include "../../../geometry/Utils.h"
31 #include "../../../maptools/Utils.h"
32 #include "../Utils.h"
33 
34 #include "MapDisplay.h"
35 
36 // Qt
37 #include <QPainter>
38 #include <QPixmap>
39 
40 // STL
41 #include <vector>
42 
43 /*!
44  * \class WorldTransformer
45  *
46  * \brief This class is used to transform coordinates in world coordinate system to the screen coordinate system.
47  */
49 {
50 public:
51 
52  /** @name Constructor and destructor methods.
53  * Methods related to instantiation and destruction.
54  */
55  //@{
56 
57  /*!
58  * \brief Default constructor.
59  */
61 
62  {
63  }
64 
65  /*!
66  * \brief Parameterized constructor.
67  */
68  WorldTransformer(const double& s1llx, const double& s1lly,
69  const double& s1urx, const double& s1ury,
70  double s2width, double s2height) :
71  m_mirroring(true)
72  {
73  te::gm::Envelope system1Box(s1llx, s1lly, s1urx, s1ury);
74  te::gm::Envelope system2Box(0, 0, s2width, s2height);
75 
76  setTransformationParameters(system1Box, system2Box);
77  }
78 
79  /*!
80  * \brief Parameterized constructor.
81  */
82  WorldTransformer(const te::gm::Envelope& system1Box, const te::gm::Envelope& system2Box) :
83  m_mirroring(true)
84  {
85  setTransformationParameters(system1Box, system2Box);
86  }
87 
88  /*!
89  * \brief Copy constructor.
90  *
91  * \param other The object to be copied.
92  */
94  {
95  m_scaleX = other.m_scaleX;
96  m_scaleY = other.m_scaleY;
97  m_translateX = other.m_translateX;
98  m_translateY = other.m_translateY;
99  m_s1llx = other.m_s1llx;
100  m_s1lly = other.m_s1lly;
101  m_s1urx = other.m_s1urx;
102  m_s1ury = other.m_s1ury;
103  m_s1Width = other.m_s1Width;
104  m_s1Height = other.m_s1Height;
105  m_s2llx = other.m_s2llx;
106  m_s2lly = other.m_s2lly;
107  m_s2urx = other.m_s2urx;
108  m_s2ury = other.m_s2ury;
109  m_s2Width = other.m_s2Width;
110  m_s2Height = other.m_s2Height;
111  m_valid = other.m_valid;
112  m_mirroring = other.m_mirroring;
113  }
114 
115  /*!
116  * \brief Destructor.
117  */
118  ~WorldTransformer() = default;
119  //@}
120 
121  /** @name Transformation methods.
122  * Methods used to change coordinates of a coordinate system to another.
123  */
124  //@{
125 
126  /*!
127  * \brief Updates the matrix of transformation to be used.
128  *
129  * \param system1Box Box in world coordinate system.
130  *
131  * \param system2Box Box in screen coordinate system.
132  */
133  void setTransformationParameters(const te::gm::Envelope& system1Box, const te::gm::Envelope& system2Box)
134  {
135  m_valid = true;
136  if ((!system1Box.isValid()) || (!system2Box.isValid()))
137  {
138  m_valid = false;
139  return;
140  }
141 
142  initVariables(system1Box, system2Box);
143 
144  m_scaleX = m_s2Width / m_s1Width; // map units per unit along x-direction
145  m_scaleY = m_s2Height / m_s1Height; // map units per unit along y-direction
146 
149  }
150 
151  /*!
152  * \brief Transforms the coordinate from world system to screen coordinate system.
153  *
154  * \param[out] wx Coordinate in X-axis.
155  *
156  * \param[out] wy Coordinate in Y-axis.
157  */
158  void system1Tosystem2(double& wx, double& wy) const
159  {
160  wx = (m_scaleX * wx) + m_translateX;
161  wy = (m_scaleY * wy) + m_translateY;
162 
163  if (m_mirroring)
164  {
165  double dyCopy = wy;
166  wy = m_s2Height - 1 - dyCopy; // mirror
167  }
168  }
169 
170  /*!
171  * \overload void WorldTransformer::system1Tosystem2(const double& wx, const double& wy, double& dx, double& dy) const
172  *
173  * \param wx Coordinate, in X-axis, to be transformed to screen coordinate system.
174  *
175  * \param wy Coordinate, in Y-axis, to be transformed to screen coordinate system.
176  *
177  * \param[out] dx Coodinate, in X-axis, transformed.
178  *
179  * \param[out] dy Coodinate, in Y-axis, transformed.
180  */
181  void system1Tosystem2(const double& wx, const double& wy, double& dx, double& dy) const
182  {
183  dx = (m_scaleX * wx) + m_translateX;
184  dy = (m_scaleY * wy) + m_translateY;
185 
186  if (m_mirroring)
187  {
188  double dyCopy = dy;
189  dy = m_s2Height - 1 - dyCopy; // mirror
190  }
191  }
192 
193  /*!
194  * \overload void WorldTransformer::system1Tosystem2(const te::gm::Coord2D& c1) const
195  *
196  * \param c1 Coordinate to be transformed.
197  *
198  * \return Returns the coordinate transformed.
199  */
201  {
202  double x2 = 0.;
203  double y2 = 0.;
204 
205  system1Tosystem2(c1.getX(), c1.getY(), x2, y2);
206 
207  te::gm::Coord2D c2(x2, y2);
208  return c2;
209  }
210 
211  /*!
212  * \brief Transforms the coordinate from screen system to world coordinate system.
213  *
214  * \param[out] dx Coordinate in X-axis.
215  *
216  * \param[out] dy Coordinate in Y-axis.
217  */
218  void system2Tosystem1(double& dx, double& dy) const
219  {
220  double dyCopy = dy;
221 
222  if (m_mirroring)
223  {
224  dy = m_s2Height - 1 - dyCopy; // mirror
225  }
226 
227  dx = (dx - m_translateX) / m_scaleX;
228  dy = (dyCopy - m_translateY) / m_scaleY;
229  }
230 
231  /*!
232  * \overload void WorldTransformer::system2Tosystem1(double dx, double dy, double& wx, double& wy) const
233  *
234  * \param dx Coordinate, in X-axis, to be transformed to world coordinate system.
235  *
236  * \param dy Coordinate, in Y-axis, to be transformed to world coordinate system.
237  *
238  * \param[out] wx Coodinate, in X-axis, transformed.
239  *
240  * \param[out] wy Coodinate, in Y-axis, transformed.
241  */
242  void system2Tosystem1(double dx, double dy, double& wx, double& wy) const
243  {
244  double dyCopy = dy;
245 
246  if (m_mirroring)
247  {
248  dyCopy = m_s2Height - 1 - dyCopy; // mirror
249  }
250 
251  wx = (dx - m_translateX) / m_scaleX;
252  wy = (dyCopy - m_translateY) / m_scaleY;
253  }
254  //@}
255 
256  /** @name Getter methods of matrix parameters.
257  * Methods used to retrieve informations about the matrix of transformation.
258  */
259  //@{
260 
261  /*!
262  * \brief Returns the scale in X-axis.
263  *
264  * \return The scale in X-axis.
265  */
266  double getScaleX()
267  {
268  return m_scaleX;
269  }
270 
271  /*!
272  * \brief Returns the scale in Y-axis.
273  *
274  * \return The scale in Y-axis.
275  */
276  double getScaleY()
277  {
278  return m_scaleY;
279  }
280 
281  /*!
282  * \brief Returns the translation in X-axis.
283  *
284  * \return The transation in X-axis.
285  */
286  double getTranslateX()
287  {
288  return m_translateX;
289  }
290 
291  /*!
292  * \brief Returns the translation in Y-axis.
293  *
294  * \return The transation in Y-axis.
295  */
296  double getTranslateY()
297  {
298  return m_translateY;
299  }
300  //@}
301 
302  /** @name Getter parameters of the world box.
303  * Methods used to retrieve informations about the box in world coordinate system.
304  */
305  //@{
306 
307  /*!
308  * \brief Returns the lower left corner x value.
309  *
310  * \return The lower left corner x value.
311  */
312  double getS1llx()
313  {
314  return m_s1llx;
315  }
316 
317  /*!
318  * \brief Returns the lower left corner y value.
319  *
320  * \return The lower left corner y value.
321  */
322  double getS1lly()
323  {
324  return m_s1lly;
325  }
326 
327  /*!
328  * \brief Returns the upper right corner x value.
329  *
330  * \return The upper right corner x value.
331  */
332  double getS1urx()
333  {
334  return m_s1urx;
335  }
336 
337  /*!
338  * \brief Returns the upper right corner y value.
339  *
340  * \return The upper right corner y value.
341  */
342  double getS1ury()
343  {
344  return m_s1ury;
345  }
346 
347  /*!
348  * \brief Returns the width of the world box.
349  *
350  * \return The width of the world box.
351  */
352  double getS1Width()
353  {
354  return m_s1Width;
355  }
356 
357  /*!
358  * \brief Returns the height of the world box.
359  *
360  * \return The height of the world box.
361  */
362  double getS1Height()
363  {
364  return m_s1Height;
365  }
366  //@}
367 
368  /** @name Getter parameters of the device box.
369  * Methods used to retrieve informations about the box in device coordinate system.
370  */
371  //@{
372 
373  /*!
374  * \brief Returns the lower left corner x value.
375  *
376  * \return The lower left corner x value.
377  */
378  double getS2llx()
379  {
380  return m_s2llx;
381  }
382 
383  /*!
384  * \brief Returns the lower left corner y value.
385  *
386  * \return The lower left corner y value.
387  */
388  double getS2lly()
389  {
390  return m_s2lly;
391  }
392 
393  /*!
394  * \brief Returns the upper right corner x value.
395  *
396  * \return The upper right corner x value.
397  */
398  double getS2urx()
399  {
400  return m_s2urx;
401  }
402 
403  /*!
404  * \brief Returns the upper right corner y value.
405  *
406  * \return The upper right corner y value.
407  */
408  double getS2ury()
409  {
410  return m_s2ury;
411  }
412 
413  /*!
414  * \brief Returns the width of the device box.
415  *
416  * \return The width of the device box.
417  */
418  double getS2Width()
419  {
420  return m_s2Width;
421  }
422 
423  /*!
424  * \brief Returns the height of the device box.
425  *
426  * \return The height of the device box.
427  */
428  double getS2Height()
429  {
430  return m_s2Height;
431  }
432  //@}
433 
434  /*!
435  * \brief Returns TRUE if transformation is ok and FALSE otherwise.
436  *
437  * \return True if the transformation is valid and false otherwise.
438  */
439  bool isValid()
440  {
441  if ((m_scaleX <= 0.) && (m_scaleY <= 0.))
442  return false;
443 
444  return true;
445  }
446 
447  /*!
448  * \brief Returns TRUE if transformation is mirrored and FALSE otherwise.
449  *
450  * \return True if the transformation is mirrored and false otherwise.
451  */
452  bool isMirroring()
453  {
454  return m_mirroring;
455  }
456 
457  /*!
458  * \brief Updates mirroring internal attribute.
459  *
460  * \param mirror New mirroring state.
461  */
462  void setMirroring(bool mirror)
463  {
464  m_mirroring = mirror;
465  }
466 
467 protected:
468 
469  /*!
470  * \brief Initializes the transformer using the arguments.
471  *
472  * \param system1Box Box in world coordinate system.
473  *
474  * \param system2Box Box in device coordinate system.
475  */
476  void initVariables(const te::gm::Envelope& system1Box, const te::gm::Envelope& system2Box)
477  {
478  m_scaleX = 0.;
479  m_scaleY = 0.;
480 
481  m_translateX = 0.;
482  m_translateY = 0.;
483 
484  m_s1llx = system1Box.getLowerLeftX();
485  m_s1lly = system1Box.getLowerLeftY();
486  m_s1urx = system1Box.getUpperRightX();
487  m_s1ury = system1Box.getUpperRightY();
488  m_s1Width = system1Box.getWidth();
489  m_s1Height = system1Box.getHeight();
490 
491  m_s2llx = system2Box.getLowerLeftX();
492  m_s2lly = system2Box.getLowerLeftY();
493  m_s2urx = system2Box.getUpperRightX();
494  m_s2ury = system2Box.getUpperRightY();
495  m_s2Width = system2Box.getWidth();
496  m_s2Height = system2Box.getHeight();
497  }
498 
499  double m_scaleX{0.}; //!< Map units per unit along x-direction between
500  //!< Coordinate Systems.
501  double m_scaleY{0.}; //!< Map units per unit along y-direction between
502  //!< Coordinate Systems.
503  double m_translateX{
504  0}; //!< The value corresponds to the X-Axis translation of system 2.
505  double m_translateY{
506  0}; //!< The value corresponds to the Y-Axis translation of system 2.
507  double m_s1llx{0.}; //!< Lower left x-coordinate of the System 1
508  double m_s1lly{0.}; //!< Lower left y-coordinate of the System 1
509  double m_s1urx{0.}; //!< Upper right x-coordinate of the System 1
510  double m_s1ury{0.}; //!< Upper right y-coordinate of the System 1
511  double m_s1Width{0.}; //!< Width of System 1 coordinate system.
512  double m_s1Height{0.}; //!< Height of System 1 coordinate system.
513  double m_s2llx{0.}; //!< Lower left x-coordinate of the System 2
514  double m_s2lly{0.}; //!< Lower left y-coordinate of the System 2
515  double m_s2urx{0.}; //!< Upper right x-coordinate of the System 2
516  double m_s2ury{0.}; //!< Upper right y-coordinate of the System 2
517  double m_s2Width{0.}; //!< Width of System 2 coordinate system.
518  double m_s2Height{0.}; //!< Height of System 2 coordinate system.
519  bool m_valid{false}; //!< Flag specifying the state of validation of the
520  //!< transformation being used.
521  bool m_mirroring{true}; //!< Flag sinalizing the mirroring.
522 };
523 
524 /*!
525  * \brief Giving a box in world coordinate system and another in device coordinates, returns the WorldTransformer.
526  *
527  * \param boxgeo Bounding rectangle in world coordinate system.
528  *
529  * \param boxmm Bounding rectangle in device coordinate system.
530  *
531  * \return The WorldTransformer object.
532  */
534 {
535  WorldTransformer transf; // World Transformer.
536 
537  if (!boxgeo.isValid())
538  return transf;
539 
540  if (!boxmm.isValid())
541  return transf;
542 
543  // Adjust internal renderer transformer
544  transf.setTransformationParameters(boxgeo, boxmm);
545 
546  return transf;
547 }
548 
549 // --------------------------------------------------
550 // Planar Grid functions
551 // --------------------------------------------------
552 
553 /*!
554  * \brief Calculates the initial coordinate in x-axis.
555  *
556  * \param env Bounding rect in world coordinate system.
557  *
558  * \param verticalLineInitial Initial coordinate in y-axis.
559  *
560  * \param verticalLineGap Distance between two grid lines.
561  *
562  * \return The initial value in the x-axis.
563  */
564 double CalculateInitialX(const te::gm::Envelope& env, const double& verticalLineInitial, const double& verticalLineGap)
565 {
566  double xInit = verticalLineInitial;
567 
568  if (xInit < env.getLowerLeftX())
569  {
570  double difx = env.getLowerLeftX() - xInit;
571  int nParts = static_cast<int>(difx / verticalLineGap);
572 
573  xInit = (nParts == 0) ?
574  verticalLineInitial :
575  xInit + (nParts * verticalLineGap);
576  }
577 
578  return xInit;
579 }
580 
581 /*!
582  * \brief Calculates the initial coordinate in y-axis.
583  *
584  * \param env Bounding rect in world coordinate system.
585  *
586  * \param horizontalLineInitial Initial coordinate in X-axis.
587  *
588  * \param horizontalLineGap Distance between two grid lines.
589  *
590  * \return The initial value in the y-axis.
591  */
592 double CalculateInitialY(const te::gm::Envelope& env, const double& horizontalLineInitial, const double& horizontalLineGap)
593 {
594  double yInit = horizontalLineInitial;
595 
596  if (yInit < env.getLowerLeftY())
597  {
598  double dify = env.getLowerLeftY() - yInit;
599  int nParts = static_cast<int>(dify / horizontalLineGap);
600 
601  yInit = (nParts == 0) ?
602  horizontalLineInitial :
603  yInit + (nParts * horizontalLineGap);
604  }
605 
606  return yInit;
607 }
608 
609 /*!
610  * \brief Calculates the lines in y-axis.
611  *
612  * \param planarBox Box in world coordinate system (MUST BE in a planar coordinate system).
613  *
614  * \param verticalLineInitial Inital Y.
615  *
616  * \param verticalLineGap Distance between lines in y-axis.
617  *
618  * \param maxGaps Maximum number of lines to be presented on the grid.
619  *
620  * \return A vector with the calculated lines in y-axis.
621  */
622 std::vector<te::gm::LineString> CalculateVerticalLines(const te::gm::Envelope& planarBox, const double& verticalLineInitial, const double& verticalLineGap,
623  const int& maxGaps)
624 {
625  std::vector<te::gm::LineString> res;
626 
627  //here we check if the gap count would exceed the maximum number of gaps
628  if (planarBox.getWidth() / verticalLineGap > maxGaps)
629  return res;
630 
631  // Getting a suggar initial x.
632  double initialX = CalculateInitialX(planarBox, verticalLineInitial, verticalLineGap);
633 
634  // Calculating the lines.
635  for (; initialX <= planarBox.getUpperRightX(); initialX += verticalLineGap)
636  {
637  if (initialX < planarBox.getLowerLeftX())
638  continue;
639 
641 
642  lineString.setPoint(0, initialX, planarBox.getLowerLeftY());
643  lineString.setPoint(1, initialX, planarBox.getUpperRightY());
644 
645  res.push_back(lineString);
646  }
647 
648  return res;
649 }
650 
651 /*!
652  * \brief Calculates the lines in x-axis.
653  *
654  * \param world Box in world coordinate system (MUST BE in a planar coordinate system).
655  *
656  * \param horizontalLineInitial Inital X.
657  *
658  * \param horizontalLineGap Distance between lines in x-axis.
659  *
660  * \param maxGaps Maximum number of lines to be presented on the grid.
661  *
662  * \return A vector with the calculated lines in x-axis.
663  */
664 std::vector<te::gm::LineString> CalculateHorizontalLines(const te::gm::Envelope& world, const double& horizontalLineInitial, const double& horizontalLineGap,
665  const int& maxGaps)
666 {
667  std::vector<te::gm::LineString> lines;
668 
669  //here we check if the gap count would exceed the maximum number of gaps
670  if (world.getHeight() / horizontalLineGap > maxGaps)
671  return lines;
672 
673  double initialY = CalculateInitialY(world, horizontalLineInitial, horizontalLineGap);
674 
675  for (; initialY <= world.getUpperRightY(); initialY += horizontalLineGap)
676  {
677  if (initialY < world.getLowerLeftY())
678  continue;
679 
681 
682  lineString.setPoint(0, world.getLowerLeftX(), initialY);
683  lineString.setPoint(1, world.getUpperRightX(), initialY);
684 
685  lines.push_back(lineString);
686  }
687 
688  return lines;
689 }
690 
691 /*!
692  * \brief Calculates a suggar initial coordinate in world coordinate system.
693  *
694  * \param initialCoord Initial coordinate.
695  *
696  * \param distance The distance to be used.
697  *
698  * \param[out] gap The value of the distance between lines in axis.
699  *
700  * \return A suggar value for initial coordinate.
701  */
702 double GetInitialCoord(const double& initialCoord, const double& distance, double& gap)
703 {
704  if (distance <= 0)
705  {
706  gap = 0;
707  return 0;
708  }
709 
710  const size_t size = 25;
711  int gaps[size] = { 1000, 1500, 2000, 2500, 5000, 7500, 10000, 12500, 15000, 20000, 25000, 50000, 100000, 125000, 150000, 175000, 200000, 250000, 500000, 750000, 1000000, 1250000, 1500000,
712  1750000, 2000000 };
713  int numberOfIntervals = 5;
714 
715  gap = distance / numberOfIntervals;
716 
717  for (size_t i = 0; i < size; i++)
718  {
719  if (gap <= gaps[i])
720  {
721  if (i > 0)
722  gap = gaps[i - 1];
723 
724  break;
725  }
726  }
727 
728  int interval = static_cast<int>(initialCoord / gap);
729 
730  return interval * gap;
731 }
732 
733 /*!
734  * \brief Giving a box in world coordinate system, calculates the better SRID we must use to transform.
735  *
736  * \param worldBox Box in world coordinate system.
737  *
738  * \return The id of the projection we must use to transform.
739  */
740 int PlanarSRID(const te::gm::Envelope& worldBox)
741 {
742  int srid = TE_UNKNOWN_SRS;
743  int zone = te::map::CalculatePlanarZone(worldBox); // get zone number
744  double hemisphere = worldBox.getCenter().getY(); // lat (y) < 0 is south
745 
746  if (hemisphere > 0)
747  srid = 32600 + zone; // 32600 - WGS 84 / UTM grid system (northern hemisphere)
748  else
749  srid = 32700 + zone; // 32700 - WGS 84 / UTM grid system (southern hemisphere)
750 
751  return srid;
752 }
753 
754 /*!
755  * \brief Returns the dimensions of a text giving a font.
756  *
757  * \param font The font being used for the texts.
758  *
759  * \param text The text analysed.
760  *
761  * \param[out] w The calculated text width.
762  *
763  * \param[out] h The calculated text height.
764  */
765 void GetTextDimensions(const QFont font, const QString& text, int& w, int& h)
766 {
767  QFontMetrics fm(font);
768 
769  w = fm.width(text);
770  h = fm.height();
771 }
772 
773 /*!
774  * \brief Draws the line using the giving painter.
775  *
776  * \param painter The painter being used for rendering.
777  *
778  * \param line The line to be drawed.
779  *
780  * \param txtOffSet Position of the text.
781  *
782  * \param vertical Sinalizes that the line analysed is a vertical or horizontal line.
783  */
784 void DrawLine(QPainter* painter, QLineF& line, const int& txtOffSet, const bool& vertical)
785 {
786  QPaintDevice* device = painter->device();
787 
788  // 1mm of margin of the texts on top and bottom.
789  int oneMMPx = te::qt::widgets::MillimetersToPixels(device, 1, false);
790 
791  int offSet = oneMMPx/2 + txtOffSet;
792 
793  // Calculating the text positions on top and bottom.
794  double x1 = 0,
795  x2 = 0,
796  y1 = 0,
797  y2 = 0;
798 
799  if(vertical)
800  {
801  x1 = line.x1();
802  y1 = offSet;
803  x2 = line.x2();
804  y2 = device->height() - (offSet + oneMMPx + oneMMPx/2);
805  }
806  else
807  {
808  x1 = offSet;
809  y1 = line.y1();
810  x2 = device->width() - offSet;
811  y2 = line.y2();
812  }
813 
814  line.setP1(QPointF(x1, y1));
815  line.setP2(QPointF(x2, y2));
816 
817  painter->drawLine(line);
818 }
819 
820 /*!
821  * \brief Draws lines on painter.
822  *
823  * \param transf The world transformer being used.
824  *
825  * \param painter The painter being used.
826  *
827  * \param lines The set of lines to be drawed
828  *
829  * \param txtOffSet Position of the text.
830  *
831  * \param vertical Sinalizes that the lines being analysed are vertical or horizontal lines.
832  */
833 void DrawLines(WorldTransformer transf, QPainter* painter, const std::vector<te::gm::LineString>& lines, const int& txtOffSet, const bool& vertical)
834 {
835  std::vector<te::gm::LineString>::const_iterator it;
836  QLineF line;
837 
838  double x1 = 0,
839  y1 = 0,
840  x2 = 0,
841  y2 = 0;
842 
843  for(it = lines.cbegin(); it != lines.cend(); ++it)
844  {
845  transf.system1Tosystem2((*it).getPointN(0)->getX(), (*it).getPointN(0)->getY(), x1, y1);
846  transf.system1Tosystem2((*it).getPointN(1)->getX(), (*it).getPointN(1)->getY(), x2, y2);
847 
848  line.setP1(QPointF(x1, y1));
849  line.setP2(QPointF(x2, y2));
850 
851  DrawLine(painter, line, txtOffSet, vertical);
852  }
853 }
854 
855 /*!
856  * \brief Draw horizontal and vertical lines.
857  *
858  * \param transf The world transformer being used.
859  *
860  * \param painter The painter being used.
861  *
862  * \param vlines Set of vertical lines.
863  *
864  * \param hlines Set of horizontal lines.
865  *
866  * \param font The font to be used to render the texts.
867  */
868 void DrawAllLines(WorldTransformer transf, QPainter* painter, const std::vector<te::gm::LineString>& vlines, const std::vector<te::gm::LineString>& hlines,
869  const QFont& font)
870 {
871  int txtW = 0,
872  txtH = 0;
873 
874  GetTextDimensions(font, "0", txtW, txtH);
875 
876  DrawLines(transf, painter, vlines, txtH, true);
877  DrawLines(transf, painter, hlines, txtW, false);
878 }
879 
880 /*!
881  * \brief Returns a pixmap with the text.
882  *
883  * \param txt The text to be drawed.
884  *
885  * \param font The font to be used.
886  *
887  * \param pen The pen being used.
888  *
889  * \return A pixmap with text and dimensions calculated based on \a font parameter.
890  */
891 QPixmap* GetTextPixmap(const QString& txt, const QFont& font, const QPen& pen)
892 {
893  int txtW = 0,
894  txtH = 0;
895  QPainter p;
896  QPixmap* res = nullptr;
897  QRect pixRect;
898  QSize pixDimensions;
899 
900  // Getting the text dimensions
901  GetTextDimensions(font, txt, txtW, txtH);
902 
903  pixDimensions.setWidth(txtW);
904  pixDimensions.setHeight(txtH);
905 
906  res = new QPixmap(pixDimensions);
907  res->fill(Qt::white);
908 
909  pixRect.setWidth(pixDimensions.width());
910  pixRect.setHeight(pixDimensions.height());
911 
912  p.begin(res);
913 
914  p.setPen(pen);
915  p.setFont(font);
916 
917  p.drawText(QRect(0, 0, pixDimensions.width(), pixDimensions.height()), Qt::AlignLeft, txt);
918 
919  return res;
920 }
921 
922 /*!
923  * \brief Returns an image with the headers of the grid.
924  *
925  * \param transf The world transformer being used.
926  *
927  * \param lines The calculated grid lines.
928  *
929  * \param font The font to be used.
930  *
931  * \param pen The pen being used.
932  *
933  * \param vertical Sinalizes that the lines being analysed are vertical or horizontal lines.
934  *
935  * \param displayDimensions Dimensions of the canvas being used.
936  *
937  * \return A pixmap with the header, over some axis, of the grid.
938  */
939 QPixmap* GetTextsPixmap(WorldTransformer transf, const std::vector<te::gm::LineString>& lines, const QFont& font, const QPen& pen, const bool& vertical,
940  const QSize& displayDimensions)
941 {
942  double col = 0,
943  row = 0;
944  int txtW = 0,
945  txtH = 0;
946  long lValue;
947  QPainter p;
948  QPixmap* res = nullptr;
949  QPoint center;
950  QRect subpixRect;
951  QSize pixDimensions;
952  QString sValue;
953  std::vector<te::gm::LineString>::const_iterator it;
954 
955  GetTextDimensions(font, "0", txtW, txtH);
956 
957  if(vertical)
958  {
959  pixDimensions.setWidth(displayDimensions.width());
960  pixDimensions.setHeight(txtH);
961  }
962  else
963  {
964  pixDimensions.setWidth(displayDimensions.height());
965  pixDimensions.setHeight(txtH);
966  }
967 
968  res = new QPixmap(pixDimensions);
969 
970  res->fill(Qt::transparent);
971 
972  p.begin(res);
973 
974  for(it = lines.cbegin(); it != lines.cend(); ++it)
975  {
976  std::unique_ptr<QPixmap> pixValue;
977 
978 
979  transf.system1Tosystem2((*it).getPointN(0)->getX(), (*it).getPointN(0)->getY(), col, row);
980 
981  lValue = (vertical) ?
982  static_cast<long>((*it).getPointN(0)->getX()) :
983  static_cast<long>((*it).getPointN(0)->getY());
984 
985  sValue = QString::number(lValue);
986 
987  pixValue.reset(GetTextPixmap(sValue, font, pen));
988 
989  subpixRect.setSize(pixValue->size());
990 
991  if(vertical)
992  {
993  center.setX(static_cast<int>(col));
994  center.setY(subpixRect.height()/2);
995  }
996  else
997  {
998  center.setX(static_cast<int>(row));
999  center.setY(subpixRect.height()/2);
1000  }
1001 
1002  subpixRect.moveCenter(center);
1003 
1004  p.drawPixmap(subpixRect, *pixValue.get());
1005  }
1006 
1007  return res;
1008 }
1009 
1010 /*!
1011  * \brief Draws all texts of the lines on the grid.
1012  *
1013  * \param transf The world transformer being used.
1014  *
1015  * \param painter The painter being used.
1016  *
1017  * \param vlines Set of vertical lines.
1018  *
1019  * \param hlines Set of vertical lines.
1020  *
1021  * \param font The font being used to draw texts.
1022  */
1023 void DrawTexts(WorldTransformer transf, QPainter* painter, const std::vector<te::gm::LineString>& vlines, const std::vector<te::gm::LineString>& hlines,
1024  const QFont& font)
1025 {
1026  double dx = 0,
1027  dy = 0;
1028  int oneMMPx = te::qt::widgets::MillimetersToPixels(painter->device(), 1, false);
1029  std::unique_ptr<QPixmap> horizontalLabel;
1030  std::unique_ptr<QPixmap> verticalLabel;
1031 
1032  QSize deviceSize(painter->device()->width(), painter->device()->height());
1033 
1034  QRect devR;
1035  devR.setSize(deviceSize);
1036 
1037  // Drawing horizontal labels
1038  horizontalLabel.reset(GetTextsPixmap(transf, vlines, font, painter->pen(), true, deviceSize));
1039  painter->drawPixmap(0, oneMMPx, *horizontalLabel.get());
1040  painter->drawPixmap(0, deviceSize.height() - (oneMMPx+horizontalLabel->height()), *horizontalLabel.get());
1041 
1042  dx = devR.center().x();
1043  dy = devR.center().y();
1044 
1045  // Drawing vertical labels
1046  verticalLabel.reset(GetTextsPixmap(transf, hlines, font, painter->pen(), false, deviceSize));
1047  painter->save();
1048  painter->translate(devR.center());
1049  painter->rotate(90);
1050  painter->translate(-dy, -dx);
1051 
1052  painter->drawPixmap(oneMMPx, 0, *verticalLabel.get());
1053  painter->drawPixmap(oneMMPx, deviceSize.width() - verticalLabel->height(), *verticalLabel.get());
1054 
1055  painter->restore();
1056 }
1057 // --------------------------------------------------
1058 // End planar grid functions
1059 // --------------------------------------------------
1060 
1061 
1062 // --------------------------------------------------
1063 // Geodesic grid functions
1064 // --------------------------------------------------
1065 
1066 /*!
1067  * \brief Transforms the coordinates of an envelope from a system of coordinates to another.
1068  *
1069  * \param worldBox Bounding rectangle.
1070  *
1071  * \param sourceSRID Srid of the bounding rectangle.
1072  *
1073  * \param targetSRID Srid of the new bounding rectangle.
1074  *
1075  * \return The bounding rectangle in the \a targetSRID coordinate system.
1076  */
1077 te::gm::Envelope WorldBoxTo(const te::gm::Envelope& worldBox, const unsigned int& sourceSRID, const unsigned int& targetSRID)
1078 {
1079  te::gm::Envelope copyWorldBox = worldBox;
1080 
1081  // Checks if is Planar Geographic
1082  std::string authName = "EPSG"; // Now: So far it is the only one supported by TerraLib 5. Future: Review this line!
1083  te::srs::SpatialReferenceSystemManager::getInstance().isGeographic(sourceSRID, authName);
1085 
1086  // check if srid exist and worldbox is valid
1087  if (!unitPtr || !copyWorldBox.isValid())
1088  return copyWorldBox;
1089 
1090  // Remapping
1091  copyWorldBox.transform(static_cast<int>(sourceSRID), static_cast<int>(targetSRID));
1092  return copyWorldBox;
1093 }
1094 
1095 /*!
1096  * \brief Transforms a LineString from a coordinate system to another.
1097  *
1098  * \param line Line to be converted.
1099  *
1100  * \param sourceSRID Srid of the line.
1101  *
1102  * \param planarSRID Srid of the output.
1103  */
1104 void RemapToPlanar(te::gm::LineString* line, int sourceSRID, int planarSRID)
1105 {
1106  if (!line)
1107  return;
1108 
1109  /* Optimization so that the convert object is created only once, decreasing the execution time of this method,
1110  since it will no longer use the Envelope::transform method (for each point). */
1111 
1112  std::unique_ptr<te::srs::Converter> converter(new te::srs::Converter());
1113 
1114  try
1115  {
1116  converter->setSourceSRID(sourceSRID);
1117  converter->setTargetSRID(planarSRID);
1118  }
1119  catch (te::common::Exception& /* ex */)
1120  {
1121  return;
1122  }
1123 
1124  // convert the four corners
1125  std::size_t npoints = line->getNPoints();
1126 
1127  std::vector<te::gm::Coord2D> vecValidCoords;
1128 
1129  for (std::size_t i = 0; i < npoints; ++i)
1130  {
1131  double xin = line->getX(i);
1132  double yin = line->getY(i);
1133  double xout = 0;
1134  double yout = 0;
1135 
1136  bool wasConverted = converter->convert(xin, yin, xout, yout);
1137 
1138  if (wasConverted)
1139  {
1140  te::gm::Coord2D coord(xout, yout);
1141  vecValidCoords.push_back(coord);
1142  }
1143  }
1144 
1145  line->makeEmpty();
1146  line->setNumCoordinates(vecValidCoords.size());
1147 
1148  for (std::size_t i = 0; i < vecValidCoords.size(); ++i)
1149  line->setPoint(i, vecValidCoords[i].x, vecValidCoords[i].y);
1150 
1151  line->computeMBR(true);
1152  line->setSRID(planarSRID);
1153 }
1154 
1155 /*!
1156  * \brief Converts the \a line from world coordinate system to device coordinate system.
1157  *
1158  * \param transf WorldTransformer previously created with the both world rectangle and device rectangle.
1159  *
1160  * \param line The line to be converted.
1161  */
1163 {
1164  if(!line)
1165  return;
1166 
1167  std::size_t npoints = line->getNPoints();
1168 
1169  for(std::size_t i = 0 ; i < npoints ; ++i)
1170  {
1171  double currentX = line->getX(i);
1172  double currentY = line->getY(i);
1173 
1174  double x = 0;
1175  double y = 0;
1176 
1177  transf.system1Tosystem2(currentX, currentY, x, y);
1178  line->setPoint(i, x, y);
1179  }
1180 
1181  line->computeMBR(true);
1182  line->setSRID(TE_UNKNOWN_SRS);
1183 }
1184 
1185 /*!
1186  * \brief Calculates the vertical lines of the grid.
1187  *
1188  * \param planarBox Bounding rectangle in planar coordinate system.
1189  *
1190  * \param geographicBox Bounding rectangle in geographic coordinates.
1191  *
1192  * \param boxMM Bounding rectangle of the device in pixel coordinate system.
1193  *
1194  * \param verticalLineInitial Initial coordinate.
1195  *
1196  * \param verticalLineGap Difference between the coordinates.
1197  *
1198  * \param maxGaps Maximum number of lines to be created.
1199  *
1200  * \param planarSRID Srid of a planar coordinate system.
1201  *
1202  * \param geodesicSRID Srid of a geographic coordinate system.
1203  *
1204  * \return A vector with the created lines.
1205  *
1206  * \note If display is in a geographic coordinate system, \a planarBox MUST be an invalid rectangle and \a planarSRID MUST be the value -1. If both weren't correctly passed, this method may not work properly.
1207  */
1208 std::vector<te::gm::LineString> CalculateVerticalLines(const te::gm::Envelope& planarBox, const te::gm::Envelope& geographicBox,
1209  const te::gm::Envelope& boxMM, const double& verticalLineInitial, const double& verticalLineGap,
1210  const int& maxGaps, const int& planarSRID, const int& geodesicSRID)
1211 {
1212  std::vector<te::gm::LineString> verticalLines;
1213 
1214  // Draw a vertical line and the x coordinate change(horizontal)
1215  WorldTransformer transf = GetTransformGeo((planarBox.isValid()) ? planarBox : geographicBox, boxMM);
1216  transf.setMirroring(true);
1217 
1218  if (geodesicSRID == -1)
1219  return verticalLines;
1220 
1221  //here we check if the gap count would exceed the maximum number of gaps
1222  if (geographicBox.getWidth() / verticalLineGap > maxGaps)
1223  return verticalLines;
1224 
1225  //as the geographic grid comes from the result of a reprojection, the geographic box sometimes can be smaller than the planar box, maninly when the distance from equator gets higher.
1226  //when this happens, these calculated lines do not reach the boundaries of the item, and consequently the texts are not drawn in the correct position
1227  //to fix this, we calculate a grid bigger than we need, and then we clip the lines by making an intertection operation with the item
1228  double x1 = CalculateInitialX(geographicBox, verticalLineInitial, verticalLineGap);
1229  double x2 = geographicBox.getUpperRightX();
1230  double y1 = geographicBox.getLowerLeftY();
1231  double y2 = geographicBox.getUpperRightY();
1232 
1233  if (x1 < -178.)
1234  x1 = -178.;
1235  if (x2 > 178.)
1236  x2 = 178.;
1237  if (y1 < -89.)
1238  y1 = -89.;
1239  if (y2 > 89.)
1240  y2 = 89.;
1241 
1242  te::gm::LineString topBorderLine(2, te::gm::LineStringType);
1243  topBorderLine.setPoint(0, boxMM.getLowerLeftX(), boxMM.getUpperRightY());
1244  topBorderLine.setPoint(1, boxMM.getUpperRightX(), boxMM.getUpperRightY());
1245 
1246  te::gm::LineString bottomBorderLine(2, te::gm::LineStringType);
1247  bottomBorderLine.setPoint(0, boxMM.getLowerLeftX(), boxMM.getLowerLeftY());
1248  bottomBorderLine.setPoint(1, boxMM.getUpperRightX(), boxMM.getLowerLeftY());
1249 
1250  for (; x1 <= x2; x1 += verticalLineGap)
1251  {
1252  te::gm::Coord2D c1(x1, y1);
1253  te::gm::Coord2D c2(x1, y2);
1254 
1255  te::gm::LineString line = CreateLine(c1, c2, geodesicSRID, 32);
1256 
1257  // Line curvature: of latlong to planar;
1258  // Draw line: planar to mm
1259  if(planarSRID != -1)
1260  RemapToPlanar(&line, geodesicSRID, planarSRID);
1261 
1262  ConvertToMillimeter(transf, &line);
1263 
1264  //here we clip the line using the boundaries of the item in MM
1265  std::unique_ptr<te::gm::Geometry> rectPolygon(te::gm::GetGeomFromEnvelope(&boxMM, line.getSRID()));
1266  std::unique_ptr<te::gm::Geometry> clippedGeometry(line.intersection(rectPolygon.get()));
1267 
1268  if (clippedGeometry == nullptr || !clippedGeometry->isValid())
1269  continue;
1270 
1271  //as the grid lines are curved, the intersection may result in more than one part for each line. Here we handle it
1272  if (clippedGeometry->getGeomTypeId() == te::gm::LineStringType)
1273  {
1274  te::gm::LineString lineString(*static_cast<te::gm::LineString*>(clippedGeometry.get()));
1275  verticalLines.push_back(lineString);
1276  }
1277  else if (clippedGeometry->getGeomTypeId() == te::gm::MultiLineStringType)
1278  {
1279  te::gm::MultiLineString multiLineString(*static_cast<te::gm::MultiLineString*>(clippedGeometry.get()));
1280 
1281  for (std::size_t i = 0; i < multiLineString.getNumGeometries(); ++i)
1282  verticalLines.push_back(*static_cast<te::gm::LineString*>(multiLineString.getGeometryN(i)));
1283  }
1284  else
1285  continue;
1286  }
1287 
1288  return verticalLines;
1289 }
1290 
1291 /*!
1292  * \brief Calculates the horizontal lines of the grid.
1293  *
1294  * \param planarBox Bounding rectangle in planar coordinate system.
1295  *
1296  * \param geographicBox Bounding rectangle in geographic coordinates.
1297  *
1298  * \param boxMM Bounding rectangle of the device in pixel coordinate system.
1299  *
1300  * \param horizontalLineInitial Initial coordinate.
1301  *
1302  * \param horizontalLineGap Difference between the coordinates.
1303  *
1304  * \param maxGaps Maximum number of lines to be created.
1305  *
1306  * \param planarSRID Srid of a planar coordinate system.
1307  *
1308  * \param geodesicSRID Srid of a geographic coordinate system.
1309  *
1310  * \return A vector with the created lines.
1311  *
1312  * \note If display is in a geographic coordinate system, \a planarBox MUST be an invalid rectangle and \a planarSRID MUST be the value -1. If both weren't correctly passed, this method may not work properly.
1313  */
1314 std::vector<te::gm::LineString> CalculateHorizontalLines(const te::gm::Envelope& planarBox, const te::gm::Envelope& geographicBox,
1315  const te::gm::Envelope& boxMM, const double& horizontalLineInitial, const double& horizontalLineGap,
1316  const int& maxGaps, const int& planarSRID, const int& geodesicSRID)
1317 {
1318  std::vector<te::gm::LineString> horizontalLines;
1319 
1320  // Draw a horizontal line and the y coordinate change(vertical)
1321  WorldTransformer transf = GetTransformGeo((planarBox.isValid()) ? planarBox : geographicBox, boxMM);
1322  transf.setMirroring(true);
1323 
1324  if (geodesicSRID == -1)
1325  return horizontalLines;
1326 
1327  //here we check if the gap count would exceed the maximum number of gaps
1328  if (geographicBox.getHeight() / horizontalLineGap > maxGaps)
1329  return horizontalLines;
1330 
1331  double x1 = geographicBox.getLowerLeftX();
1332  double x2 = geographicBox.getUpperRightX();
1333  double y1 = CalculateInitialY(geographicBox, horizontalLineInitial, horizontalLineGap);
1334  double y2 = geographicBox.getUpperRightY();
1335 
1336  if (x1 < -178.)
1337  x1 = -178.;
1338  if (x2 > 178.)
1339  x2 = 178.;
1340  if (y1 < -89.)
1341  y1 = -89.;
1342  if (y2 > 89.)
1343  y2 = 89.;
1344 
1345  te::gm::LineString leftBorderLine(2, te::gm::LineStringType);
1346  leftBorderLine.setPoint(0, boxMM.getLowerLeftX(), boxMM.getLowerLeftY());
1347  leftBorderLine.setPoint(1, boxMM.getLowerLeftX(), boxMM.getUpperRightY());
1348 
1349  te::gm::LineString rightBorderLine(2, te::gm::LineStringType);
1350  rightBorderLine.setPoint(0, boxMM.getUpperRightX(), boxMM.getLowerLeftY());
1351  rightBorderLine.setPoint(1, boxMM.getUpperRightX(), boxMM.getUpperRightY());
1352 
1353  for (; y1 <= y2; y1 += horizontalLineGap)
1354  {
1355  te::gm::Coord2D c1(x1, y1);
1356  te::gm::Coord2D c2(x2, y1);
1357 
1358  te::gm::LineString line = CreateLine(c1, c2, geodesicSRID, 32);
1359 
1360  // Line curvature: of latlong to planar;
1361  // Draw line: planar to mm
1362  if(planarSRID != -1)
1363  RemapToPlanar(&line, geodesicSRID, planarSRID);
1364 
1365  ConvertToMillimeter(transf, &line);
1366 
1367  //here we clip the line using the boundaries of the item in MM
1368  std::unique_ptr<te::gm::Geometry> rectPolygon(te::gm::GetGeomFromEnvelope(&boxMM, line.getSRID()));
1369  std::unique_ptr<te::gm::Geometry> clippedGeometry(line.intersection(rectPolygon.get()));
1370 
1371  if (clippedGeometry == nullptr || !clippedGeometry->isValid())
1372  continue;
1373 
1374  //as the grid lines are curved, the intersection may result in more than one part for each line. Here we handle it
1375  if (clippedGeometry->getGeomTypeId() == te::gm::LineStringType)
1376  {
1377  te::gm::LineString lineString(*static_cast<te::gm::LineString*>(clippedGeometry.get()));
1378 
1379  horizontalLines.push_back(lineString);
1380  }
1381  else if (clippedGeometry->getGeomTypeId() == te::gm::MultiLineStringType)
1382  {
1383  te::gm::MultiLineString multiLineString(*static_cast<te::gm::MultiLineString*>(clippedGeometry.get()));
1384 
1385  for (std::size_t i = 0; i < multiLineString.getNumGeometries(); ++i)
1386  horizontalLines.push_back(*static_cast<te::gm::LineString*>(multiLineString.getGeometryN(i)));
1387  }
1388  else
1389  continue;
1390  }
1391 
1392  return horizontalLines;
1393 }
1394 
1395 /*!
1396  * \brief Returns a default description for a geodesic coordinate system.
1397  *
1398  * \return Default srid for the geodesic coordinate system. (EPSG:4326)
1399  */
1400 std::string Proj4DescToGeodesic()
1401 {
1402  // EPSG:4326
1403  std::string proj4;
1404 
1405  proj4 += "+proj=longlat";
1406  proj4 += " +datum=WGS84";
1407  proj4 += " +no_defs ";
1408 
1409  return proj4;
1410 }
1411 
1412 /*!
1413  * \brief Returns the unit of measure of the given \a srid.
1414  *
1415  * \param srid Srid of interest.
1416  *
1417  * \return The corresponding unit of measure.
1418  */
1420 {
1422 
1423  // Checks if is Planar Geographic
1424  std::string authName = "EPSG"; // Now: So far it is the only one supported by TerraLib 5. Future: Review this line!
1425  te::srs::SpatialReferenceSystemManager::getInstance().isGeographic(static_cast<unsigned int>(srid), authName);
1426  unitPtr = te::srs::SpatialReferenceSystemManager::getInstance().getUnit(static_cast<unsigned int>(srid), authName);
1427 
1428  return unitPtr;
1429 }
1430 
1431 /*!
1432  * \brief Transforms a bounding rectangle from a srid into another one.
1433  *
1434  * \param worldBox Bounding rectangle in some coordinate system.
1435  *
1436  * \param sourceSRID The srid of the rectangle.
1437  *
1438  * \param targetSRID The srid of the output rectangle.
1439  *
1440  * \return A bounding rectangle in the \a targetSRID coordinate system, or an invalid bounding rectangle, if the operation couldn't be done.
1441  */
1442 te::gm::Envelope WorldBoxTo(const te::gm::Envelope& worldBox, int sourceSRID, int targetSRID)
1443 {
1444  te::gm::Envelope copyWorldBox = worldBox;
1445 
1446  // Checks if is Planar Geographic
1447  std::string authName = "EPSG"; // Now: So far it is the only one supported by TerraLib 5. Future: Review this line!
1448  te::srs::SpatialReferenceSystemManager::getInstance().isGeographic(static_cast<unsigned int>(sourceSRID), authName);
1449  te::common::UnitOfMeasurePtr unitPtr = te::srs::SpatialReferenceSystemManager::getInstance().getUnit(static_cast<unsigned int>(sourceSRID), authName);
1450 
1451  // check if srid exist and worldbox is valid
1452  if (!unitPtr || !copyWorldBox.isValid())
1453  return copyWorldBox;
1454 
1455  // Remapping
1456  copyWorldBox.transform(sourceSRID, targetSRID);
1457 
1458  return copyWorldBox;
1459 }
1460 
1461 /*!
1462  * \brief Calculates the srid for the better planar coordinate system, given a bounding rectangle and it's srid.
1463  *
1464  * \param worldBox Bounding rectangle in a geodesic coordinate system.
1465  *
1466  * \param sourceSRID The srid of the input bounding rectangle.
1467  *
1468  * \return Srid of the better planar coordinate system found.
1469  */
1470 int ToPlanar(const te::gm::Envelope& worldBox, int sourceSRID)
1471 {
1472  int targetSRID = TE_UNKNOWN_SRS;
1473  te::common::UnitOfMeasurePtr unitPtr = UnitMeasure(sourceSRID);
1474 
1475  if (!unitPtr || !worldBox.isValid())
1476  return targetSRID;
1477 
1478  targetSRID = sourceSRID;
1479  std::string unitPtrStr = unitPtr->getName();
1480  unitPtrStr = te::common::Convert2UCase(unitPtrStr);
1481 
1482  if (unitPtrStr.compare("DEGREE") == 0)
1483  // Get the id of the projection of destination
1484  targetSRID = PlanarSRID(worldBox);
1485 
1486  return targetSRID;
1487 }
1488 
1489 /*!
1490  * \brief Calculates the srid for the better geodesic coordinate system, given a bounding rectangle and it's srid.
1491  *
1492  * \param worldBox Bounding rectangle in a planar coordinate system.
1493  *
1494  * \param sourceSRID The srid of the input bounding rectangle.
1495  *
1496  * \return Srid of the geodesic coordinate.
1497  */
1498 int ToGeographic(const te::gm::Envelope& worldBox, int sourceSRID)
1499 {
1500  int targetSRID = TE_UNKNOWN_SRS;
1501  te::gm::Envelope worldBoxPlanar = worldBox;
1502  te::common::UnitOfMeasurePtr unitPtr = UnitMeasure(sourceSRID);
1503 
1504  if (!unitPtr || !worldBoxPlanar.isValid())
1505  return targetSRID;
1506 
1507  targetSRID = sourceSRID;
1508  std::string unitPtrStr = unitPtr->getName();
1509  unitPtrStr = te::common::Convert2UCase(unitPtrStr);
1510 
1511  if (unitPtrStr.compare("DEGREE") != 0)
1512  {
1513  std::string proj4 = Proj4DescToGeodesic();
1514  // Get the id of the projection of destination
1515  std::pair<std::string, unsigned int> projGeographic = te::srs::SpatialReferenceSystemManager::getInstance().getIdFromP4Txt(proj4);
1516 
1517  targetSRID = static_cast<int>(projGeographic.second);
1518  }
1519 
1520  return targetSRID;
1521 }
1522 
1523 /*!
1524  * \brief Transforms a line from a coordinate system to another.
1525  *
1526  * \param transf WorldTransformer created with a planar bounding rectangle and the device bounding rectangle.
1527  *
1528  * \param line A line in device coordinate system.
1529  *
1530  * \param geoSRID The srid of the geodesic coordinate system.
1531  */
1533 {
1534  double x,
1535  y;
1536  size_t nPts = line.getNPoints();
1537 
1538  for(size_t i = 0; i < nPts; i++)
1539  {
1540  transf.system2Tosystem1(line.getPointN(i)->getX(), line.getPointN(i)->getY(), x, y);
1541  line.setPointN(i, te::gm::Point(x, y));
1542  }
1543 
1544  line.transform(geoSRID);
1545 }
1546 
1547 /*!
1548  * \brief Retuns an rounded number. If the decimal part of number is less than \a .5, rounds to the floor, otherwise it will be rounded up.
1549  *
1550  * \param value Value to be calculated.
1551  *
1552  * \return The rounded number.
1553  */
1554 int RoundNumber( const double& value )
1555 {
1556  if (value >= 0)
1557  return static_cast<int>(value+.5);
1558  else
1559  return static_cast<int>(value-.5);
1560 }
1561 
1562 /*!
1563  * \brief Converts a value to a degree-minute-second description. For presentation purposes.
1564  *
1565  * \param value Value to be converted. (MUST be in a geodesic coordinate system)
1566  *
1567  * \param bDegrees True to degrees section to be presented, false otherwise.
1568  *
1569  * \param bMinutes True to minutes section to be presented, false otherwise.
1570  *
1571  * \param bSeconds True to seconds section to be presented, false otherwise.
1572  *
1573  * \param precision Number of the decimals to be used.
1574  *
1575  * \return Returns a text formatted as a degree-minute-second value.
1576  */
1577 std::string ConvertDecimalToDegree(const double& value, bool bDegrees, bool bMinutes, bool bSeconds, int precision)
1578 {
1579  std::string degreeValue;
1580  double dbValue;
1581  double degree;
1582  double sec;
1583  double min;
1584 
1585  degree = static_cast<int>(value);
1586  dbValue = value - degree;
1587 
1588  min = std::fabs((dbValue-static_cast<int>(dbValue)*60.));
1589  sec = std::fabs(std::fabs((min-int(min))*60.));
1590 
1591  if(RoundNumber(sec) >= 60)
1592  {
1593  min++;
1594  sec=0;
1595  }
1596 
1597  min = std::floor(min);
1598 
1599  if(min >= 60.0)
1600  {
1601  min = 0;
1602  dbValue++;
1603  }
1604 
1605  std::string space;
1606 
1607  const QChar degreeChar(0260);
1608 
1609  if (bDegrees)
1610  {
1611  degreeValue = te::common::Convert2String(std::floor(degree), 0) + QString(degreeChar).toStdString();
1612  space = " ";
1613  }
1614  if (bMinutes)
1615  {
1616  degreeValue += space + te::common::Convert2String(std::floor(min), 0) + "'";
1617  space = " ";
1618  }
1619  if (bSeconds)
1620  {
1621  degreeValue += space + te::common::Convert2String(std::fabs(sec), precision) + "''";
1622  }
1623 
1624  if(bDegrees == false && bMinutes == false && bSeconds == false)
1625  degreeValue = te::common::Convert2String(std::floor(degree), 0) + QString(degreeChar).toStdString() + " " + te::common::Convert2String(std::fabs(min), 0) + "' " + te::common::Convert2String(std::fabs(sec), precision) + "''";
1626 
1627  return degreeValue;
1628 }
1629 
1630 /*!
1631  * \brief Returns a pixmap with the values of the coordinates to be presented.
1632  *
1633  * \param transf WorldTransformer object previously created.
1634  *
1635  * \param lines The lines that are being processed
1636  *
1637  * \param painter A QPainter object previously configured with the the color and font to use on presentation.
1638  *
1639  * \param vertical Flag that sinalyzes if the pixmap is for the vertical lines or horizontal. (Depends on what lines are passed)
1640  *
1641  * \param top Flag that sinalyzes in wich side will be placed the pixmap: \a true -> top and right, \a false -> bottom and left.
1642  *
1643  * \param geoSrid The srid of the geodesic coordinate system to be used.
1644  *
1645  * \return The pixmap to be placed on top, bottom, left or right position.
1646  *
1647  * \note If the display is in a geodesic coordinate the \a geoSrid MUST be defined as a valor different of -1.
1648  */
1649 QPixmap* GetTextsPixmap(WorldTransformer transf, const std::vector<te::gm::LineString>& lines, QPainter& painter,
1650  const bool& vertical, const bool& top, const int& geoSrid)
1651 {
1652  double x = 0,
1653  y = 0;
1654  int txtW = 0,
1655  txtH = 0;
1656  double lValue;
1657  QPainter p;
1658  QPixmap* res = nullptr;
1659  QPoint center;
1660  QRect subpixRect;
1661  QSize pixDimensions;
1662  QString sValue;
1663  std::vector<te::gm::LineString>::const_iterator it;
1664  size_t lineIdx;
1665 
1666  GetTextDimensions(painter.font(), "0", txtW, txtH);
1667 
1668  QSize displayDimensions(painter.device()->width(), painter.device()->height());
1669 
1670  if(vertical)
1671  {
1672  pixDimensions.setWidth(displayDimensions.width());
1673  pixDimensions.setHeight(txtH);
1674  }
1675  else
1676  {
1677  pixDimensions.setWidth(displayDimensions.height());
1678  pixDimensions.setHeight(txtH);
1679  }
1680 
1681  res = new QPixmap(pixDimensions);
1682 
1683  res->fill(Qt::transparent);
1684 
1685  p.begin(res);
1686 
1687  for(it = lines.cbegin(); it != lines.cend(); ++it)
1688  {
1689  std::unique_ptr<QPixmap> pixValue;
1690 
1691  te::gm::LineString line = *it;
1692 
1693  size_t nPts = line.getNPoints();
1694 
1695  lineIdx = (top) ?
1696  nPts - 1 :
1697  0;
1698 
1699  if(geoSrid != -1)
1700  {
1701  GetGeographicCoordLine(transf, line, geoSrid);
1702  x = line.getPointN(0)->getX();
1703  y = line.getPointN(0)->getY();
1704  }
1705  else
1706  transf.system2Tosystem1(line.getPointN(0)->getX(), line.getPointN(0)->getY(), x, y);
1707 
1708  lValue = (!vertical) ?
1709  y :
1710  x;
1711 
1712  sValue = QString::fromUtf8(ConvertDecimalToDegree(lValue, true, true, true, 3).c_str());
1713 
1714  pixValue.reset(GetTextPixmap(sValue, painter.font(), painter.pen()));
1715 
1716  subpixRect.setSize(pixValue->size());
1717 
1718  if(vertical)
1719  {
1720  center.setX(static_cast<int>((*it).getPointN(lineIdx)->getX()));
1721  center.setY(subpixRect.height()/2);
1722  }
1723  else
1724  {
1725  center.setX(static_cast<int>((*it).getPointN(lineIdx)->getY()));
1726  center.setY(subpixRect.height()/2);
1727  }
1728 
1729  subpixRect.moveCenter(center);
1730 
1731  p.drawPixmap(subpixRect, *pixValue.get());
1732  }
1733 
1734  return res;
1735 }
1736 
1737 /*!
1738  * \brief Sets the srid of a set of lines.
1739  *
1740  * \param lines The lines to be updated.
1741  *
1742  * \param srid The new srid to be used.
1743  *
1744  * \note This method just sets the srid of the lines. It DOES NOT make any coordinate transformations.
1745  */
1746 void SetSRID(std::vector<te::gm::LineString>& lines, const int& srid)
1747 {
1748  std::vector<te::gm::LineString>::iterator it;
1749 
1750  for(it = lines.begin(); it != lines.end(); ++it)
1751  (*it).setSRID(srid);
1752 }
1753 
1754 // --------------------------------------------------
1755 // End geodesic grid functions
1756 // --------------------------------------------------
1757 
1758 // --------------------------------------------------
1759 // End of utility functions.
1760 // --------------------------------------------------
1761 
1763  QFrame(parent, Qt::SubWindow),
1764  m_display(parent),
1765  m_maxGap(30),
1766  m_verticalGap(0),
1767  m_horizontalGap(0),
1768  m_initialX(0),
1769  m_initialY(0),
1770  m_backGround(nullptr),
1771  m_srid(-1),
1772  m_geoSrid(-1),
1773  m_color(Qt::black),
1774  m_font(QFont("times", 10)),
1775  m_type(PLANAR)
1776 {
1777  setAttribute(Qt::WA_TranslucentBackground);
1778 
1779  initialize();
1780 
1781  redraw();
1782 
1783  connect(m_display, SIGNAL(drawLayersFinished(const QMap<QString, QString>&)), SLOT(redraw()));
1784 }
1785 
1787 {
1788  delete m_backGround;
1789 }
1790 
1792 {
1793  return m_color;
1794 }
1795 
1797 {
1798  return m_font;
1799 }
1800 
1802 {
1803  return m_type;
1804 }
1805 
1806 void te::qt::widgets::Grid::setColor(const QColor& color)
1807 {
1808  m_color = color;
1809 
1810  redraw();
1811 }
1812 
1813 void te::qt::widgets::Grid::setFont(const QFont& font)
1814 {
1815  m_font = font;
1816 
1817  redraw();
1818 }
1819 
1821 {
1822  m_type = static_cast<GridTypes>(type);
1823 
1824  redraw();
1825 }
1826 
1828 {
1829  switch (m_type)
1830  {
1831  case PLANAR:
1832  makePlanarGrid();
1833  break;
1834 
1835  case GEOGRAPHIC:
1837  break;
1838  }
1839 
1840  // Getting the size of the widget.
1841  QSize s = m_display->size();
1842 
1843  // Changing the widget dimensions.
1844  setFixedSize(s);
1845  setMinimumSize(s);
1846 
1847  // Deleting old image.
1848  delete m_backGround;
1849  m_backGround = nullptr;
1850 
1851  // Getting a transparent image.45
1852  m_backGround = GetCleanImage(s, Qt::transparent);
1853 
1854  // Configuring painter
1855  QPen pen(QBrush(m_color), 1);
1856  QPainter p(m_backGround);
1857  p.setPen(pen);
1858  p.setFont(m_font);
1859 
1860  te::gm::Envelope planarBox = m_display->getExtent(),
1861  viewport(0, 0, m_display->width(), m_display->height());
1862 
1863  if (m_display->getSRID() != m_srid)
1864  planarBox.transform(m_display->getSRID(), m_srid);
1865 
1866  WorldTransformer transf = GetTransformGeo(planarBox, viewport);
1867  transf.setMirroring(true);
1868 
1869  if(m_type == PLANAR)
1870  {
1871  DrawAllLines(transf, &p, m_vlines, m_hlines, m_font);
1872  DrawTexts(transf, &p, m_vlines, m_hlines, m_font);
1873  }
1874  else
1875  {
1876  std::vector<te::gm::LineString>::iterator it;
1877  QPainterPath path;
1878 
1879  for(it = m_vlines.begin(); it != m_vlines.end(); ++it)
1880  {
1881  te::gm::LineString line = *it;
1882 
1883  size_t nPts = line.getNPoints();
1884 
1885  for(size_t i = 0; i < nPts; i++)
1886  {
1887  if(i == 0)
1888  path.moveTo(line.getPointN(i)->getX(), line.getPointN(i)->getY());
1889  else
1890  path.lineTo(line.getPointN(i)->getX(), line.getPointN(i)->getY());
1891  }
1892  }
1893 
1894  for(it = m_hlines.begin(); it != m_hlines.end(); ++it)
1895  {
1896  te::gm::LineString line = *it;
1897 
1898  size_t nPts = line.getNPoints();
1899 
1900  for(size_t i = 0; i < nPts; i++)
1901  {
1902  if(i == 0)
1903  path.moveTo(line.getPointN(i)->getX(), line.getPointN(i)->getY());
1904  else
1905  path.lineTo(line.getPointN(i)->getX(), line.getPointN(i)->getY());
1906  }
1907  }
1908 
1911 
1912  p.drawPath(path);
1913 
1914  int oneMMPx = te::qt::widgets::MillimetersToPixels(p.device(), 1, false);
1915 
1916  std::unique_ptr<QPixmap> hori(GetTextsPixmap(transf, m_vlines, p, true, true, m_geoSrid));
1917  std::unique_ptr<QPixmap> hori2(GetTextsPixmap(transf, m_vlines, p, true, false, m_geoSrid));
1918  std::unique_ptr<QPixmap> vert(GetTextsPixmap(transf, m_hlines, p, false, true, m_geoSrid));
1919  std::unique_ptr<QPixmap> vert2(GetTextsPixmap(transf, m_hlines, p, false, false, m_geoSrid));
1920 
1921  p.drawPixmap(0, oneMMPx, *hori.get());
1922  p.drawPixmap(0, s.height() - hori2->height(), *hori2.get());
1923 
1924  double dx = 0,
1925  dy = 0;
1926 
1927  QRect devR;
1928  devR.setSize(s);
1929 
1930  dx = devR.center().x();
1931  dy = devR.center().y();
1932 
1933  // Drawing vertical labels
1934  p.save();
1935  p.translate(devR.center());
1936  p.rotate(90);
1937  p.translate(-dy, -dx);
1938  p.drawPixmap(oneMMPx, 0, *vert.get());
1939 
1940  p.drawPixmap(oneMMPx, 0, *vert.get());
1941  p.drawPixmap(oneMMPx, s.width() - vert2->height(), *vert2.get());
1942 
1943  p.restore();
1944  }
1945 
1946  // Repaint widget
1947  QFrame::update();
1948 }
1949 
1951 {
1952  // Checks if is Geographic
1953  std::string authName = "EPSG"; // Now: So far it is the only one supported by TerraLib 5. Future: Review this line!
1954  bool isGeo = te::srs::SpatialReferenceSystemManager::getInstance().isGeographic(static_cast<unsigned int>(m_display->getSRID()), authName);
1955 
1956  // Storing the better zone to use.
1957  if(m_type == PLANAR)
1958  {
1959  m_srid = (isGeo) ?
1961  m_display->getSRID();
1962  }
1963  else
1964  {
1965  m_srid = (isGeo) ?
1966  m_display->getSRID() :
1968  }
1969 }
1970 
1972 {
1973  initialize();
1974 
1976 
1977  if (m_srid != m_display->getSRID())
1978  bbox.transform(m_display->getSRID(), m_srid);
1979 
1980  m_hlines.clear();
1981  m_vlines.clear();
1982 
1983  // Get the bounding rect of the visible area in planar system of coordinates.
1986 
1987  // Getting the lines to build the grid.
1988  m_vlines = CalculateVerticalLines(bbox, m_initialY, m_verticalGap, m_maxGap);
1990 }
1991 
1993 {
1994  int planarSRID = 0,
1995  geodesicSRID = 0;
1997  int srid = m_display->getSRID();
1998 
1999  initialize();
2000 
2001  bool isGeo = (srid == m_srid);
2002  te::gm::Envelope planarBox;
2003  te::gm::Envelope geographicBox;
2004  te::gm::Envelope referenceBoxMM(0, 0, width(), height());
2005 
2006  if(!isGeo)
2007  {
2008  geodesicSRID = m_srid;
2009  planarSRID = ToPlanar(bbox, srid);
2010  m_geoSrid = geodesicSRID;
2011 
2012  geographicBox = WorldBoxTo(bbox, srid, m_geoSrid);
2013  planarBox = WorldBoxTo(geographicBox, geodesicSRID, planarSRID);
2014  }
2015  else
2016  {
2017  planarSRID = -1;
2018  geodesicSRID = m_srid;
2019  m_geoSrid = geodesicSRID;
2020  geographicBox = bbox;
2021  }
2022 
2023  m_hlines.clear();
2024  m_vlines.clear();
2025 
2026  if (!bbox.isValid())
2027  return;
2028 
2029  // Optimized way to reproject a box, between source and destination projections.
2030  //Box required to draw curvature
2031  if (!geographicBox.isValid())
2032  return;
2033 
2034  // Get the bounding rect of the visible area in planar system of coordinates.
2035  m_initialX = GetInitialCoord(geographicBox.getLowerLeftY(), geographicBox.getHeight(), m_horizontalGap);
2036  m_initialY = GetInitialCoord(geographicBox.getLowerLeftX(), geographicBox.getWidth(), m_verticalGap);
2037 
2038  m_vlines = CalculateVerticalLines(planarBox, geographicBox, referenceBoxMM, m_initialY, m_verticalGap, m_maxGap, planarSRID, geodesicSRID);
2039  m_hlines = CalculateHorizontalLines(planarBox, geographicBox, referenceBoxMM, m_initialX, m_horizontalGap, m_maxGap, planarSRID, geodesicSRID);
2040 }
2041 
2042 void te::qt::widgets::Grid::paintEvent(QPaintEvent* event)
2043 {
2044  QPainter p(this);
2045 
2046  p.drawPixmap(0, 0, *m_backGround);
2047 
2048  QFrame::paintEvent(event);
2049 }
2050 
2051 void te::qt::widgets::Grid::closeEvent(QCloseEvent* event)
2052 {
2053  emit aboutToBeclosed();
2054 
2055  QFrame::closeEvent(event);
2056 }
2057 
double getS1Height()
Returns the height of the world box.
double getS2lly()
Returns the lower left corner y value.
double m_scaleX
Map units per unit along x-direction between Coordinate Systems.
std::size_t getNumGeometries() const
It returns the number of geometries in this GeometryCollection.
double getS1ury()
Returns the upper right corner y value.
std::vector< te::gm::LineString > CalculateHorizontalLines(const te::gm::Envelope &world, const double &horizontalLineInitial, const double &horizontalLineGap, const int &maxGaps)
Calculates the lines in x-axis.
void computeMBR(bool cascade) const
It computes the minimum bounding rectangle for the linestring.
te::common::UnitOfMeasurePtr UnitMeasure(int srid)
Returns the unit of measure of the given srid.
double getS2urx()
Returns the upper right corner x value.
void GetTextDimensions(const QFont font, const QString &text, int &w, int &h)
Returns the dimensions of a text giving a font.
void RemapToPlanar(te::gm::LineString *line, int sourceSRID, int planarSRID)
Transforms a LineString from a coordinate system to another.
int m_geoSrid
Geographic SRID being used to reproject the world box to a geographic coordinate system.
static te::dt::Date dx(2010, 12, 31)
#define TE_UNKNOWN_SRS
A numeric value to represent a unknown SRS identification in TerraLib.
int m_srid
SRID being used to reproject the world box to a planar coordinate system.
double GetInitialCoord(const double &initialCoord, const double &distance, double &gap)
Calculates a suggar initial coordinate in world coordinate system.
void system1Tosystem2(double &wx, double &wy) const
Transforms the coordinate from world system to screen coordinate system.
double m_scaleY
Map units per unit along y-direction between Coordinate Systems.
double m_translateY
The value corresponds to the Y-Axis translation of system 2.
bool m_mirroring
Flag sinalizing the mirroring.
void system2Tosystem1(double &dx, double &dy) const
Transforms the coordinate from screen system to world coordinate system.
void makeEmpty()
It clears all the coordinates.
MapDisplay * m_display
Pointer to a MapDisplay.
void DrawTexts(WorldTransformer transf, QPainter *painter, const std::vector< te::gm::LineString > &vlines, const std::vector< te::gm::LineString > &hlines, const QFont &font)
Draws all texts of the lines on the grid.
const double & getUpperRightX() const
It returns a constant refernce to the x coordinate of the upper right corner.
QFont m_font
Font to be used.
double m_s1Height
Height of System 1 coordinate system.
double getTranslateX()
Returns the translation in X-axis.
virtual Geometry * intersection(const Geometry *const rhs) const _NOEXCEPT_OP(false)
It returns a geometric object that represents the point set intersection with another geometry...
void initialize()
Initializes the object.
std::unique_ptr< Point > getPointN(std::size_t i) const
It returns the specified point in this LineString.
void redraw()
Refresh the grid image. This method MUST BE called when the area of visualization changes in MapDispl...
bool m_valid
Flag specifying the state of validation of the transformation being used.
std::string Convert2UCase(const std::string &value)
It converts a string to upper case.
Definition: StringUtils.h:168
const double & getLowerLeftY() const
It returns a constant refernce to the y coordinate of the lower left corner.
double getWidth() const
It returns the envelope width.
void closeEvent(QCloseEvent *event)
Reimplementation of the QFrame method.
double getScaleY()
Returns the scale in Y-axis.
QColor getColor() const
Returns the current color being used.
void initVariables(const te::gm::Envelope &system1Box, const te::gm::Envelope &system2Box)
Initializes the transformer using the arguments.
A widget to control the display of a set of layers.
A Qt4 widget to control the display of a set of layers.
double m_initialY
Initial coordinate in y-axis.
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
double getY() const
It returns the y-coordinate.
Definition: Coord2D.h:108
double m_s1Width
Width of System 1 coordinate system.
int ToGeographic(const te::gm::Envelope &worldBox, int sourceSRID)
Calculates the srid for the better geodesic coordinate system, given a bounding rectangle and it&#39;s sr...
void ConvertToMillimeter(const WorldTransformer &transf, te::gm::LineString *line)
Converts the line from world coordinate system to device coordinate system.
double CalculateInitialX(const te::gm::Envelope &env, const double &verticalLineInitial, const double &verticalLineGap)
Calculates the initial coordinate in x-axis.
void DrawLines(WorldTransformer transf, QPainter *painter, const std::vector< te::gm::LineString > &lines, const int &txtOffSet, const bool &vertical)
Draws lines on painter.
WorldTransformer(const te::gm::Envelope &system1Box, const te::gm::Envelope &system2Box)
Parameterized constructor.
This class is used to transform coordinates in world coordinate system to the screen coordinate syste...
const double & getUpperRightY() const
It returns a constant refernce to the x coordinate of the upper right corner.
double CalculateInitialY(const te::gm::Envelope &env, const double &horizontalLineInitial, const double &horizontalLineGap)
Calculates the initial coordinate in y-axis.
te::gm::Coord2D system1Tosystem2(const te::gm::Coord2D &c1) const
double getS1urx()
Returns the upper right corner x value.
double m_s1llx
Lower left x-coordinate of the System 1.
void setColor(const QColor &color)
Updates the color of the lines and texts.
const double & getY(std::size_t i) const
It returns the n-th y coordinate value.
void paintEvent(QPaintEvent *event)
Reimplementation of the QFrame method.
double m_horizontalGap
Distance between lines in x-axis.
unsigned int line
int PlanarSRID(const te::gm::Envelope &worldBox)
Giving a box in world coordinate system, calculates the better SRID we must use to transform...
void makeGeographicGrid()
Builds the geographic grid.
QPixmap * m_backGround
Pixmap with the grid image.
std::string Proj4DescToGeodesic()
Returns a default description for a geodesic coordinate system.
WorldTransformer(const double &s1llx, const double &s1lly, const double &s1urx, const double &s1ury, double s2width, double s2height)
Parameterized constructor.
Coord2D getCenter() const
It returns the rectangle&#39;s center coordinate.
void setFont(const QFont &font)
Updates the font of the texts.
int getSRID() const _NOEXCEPT_OP(true)
It returns the Spatial Reference System ID associated to this geometric object.
void SetSRID(std::vector< te::gm::LineString > &lines, const int &srid)
Sets the srid of a set of lines.
LineString is a curve with linear interpolation between points.
Definition: LineString.h:62
void system1Tosystem2(const double &wx, const double &wy, double &dx, double &dy) const
int ToPlanar(const te::gm::Envelope &worldBox, int sourceSRID)
Calculates the srid for the better planar coordinate system, given a bounding rectangle and it&#39;s srid...
static SpatialReferenceSystemManager & getInstance()
It returns a reference to the singleton instance.
A point with x and y coordinate values.
Definition: Point.h:50
void makePlanarGrid()
Builds the planar grid.
void setPoint(std::size_t i, const double &x, const double &y)
It sets the value of the specified point.
double m_s2Height
Height of System 2 coordinate system.
An Envelope defines a 2D rectangular region.
bool isMirroring()
Returns TRUE if transformation is mirrored and FALSE otherwise.
int getType() const
Returns the current type of grid being used.
const double & getX(std::size_t i) const
It returns the n-th x coordinate value.
virtual int getSRID() const
It return the Spatial Reference System used by the Map Display.
int RoundNumber(const double &value)
Retuns an rounded number. If the decimal part of number is less than .5, rounds to the floor...
void GetGeographicCoordLine(WorldTransformer transf, te::gm::LineString &line, const int &geoSRID)
Transforms a line from a coordinate system to another.
void setNumCoordinates(std::size_t size)
It reserves room for the number of coordinates in this LineString.
QColor m_color
Color to be used.
void DrawAllLines(WorldTransformer transf, QPainter *painter, const std::vector< te::gm::LineString > &vlines, const std::vector< te::gm::LineString > &hlines, const QFont &font)
Draw horizontal and vertical lines.
virtual const te::gm::Envelope & getExtent() const
It returns the world extent showned by the MapDisplay.
QPixmap * GetTextPixmap(const QString &txt, const QFont &font, const QPen &pen)
Returns a pixmap with the text.
GridTypes
Defines the types of grid that can be used.
te::gm::Polygon * p
WorldTransformer GetTransformGeo(te::gm::Envelope boxgeo, te::gm::Envelope boxmm)
Giving a box in world coordinate system and another in device coordinates, returns the WorldTransform...
std::size_t getNPoints() const
It returns the number of points (vertexes) in the linestring.
Definition: LineString.h:193
double m_s2lly
Lower left y-coordinate of the System 2.
std::string ConvertDecimalToDegree(const double &value, bool bDegrees, bool bMinutes, bool bSeconds, int precision)
Converts a value to a degree-minute-second description. For presentation purposes.
double getS1llx()
Returns the lower left corner x value.
Grid(MapDisplay *parent)
Constructor.
double m_s1lly
Lower left y-coordinate of the System 1.
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
WorldTransformer(const WorldTransformer &other)
Copy constructor.
double m_s1ury
Upper right y-coordinate of the System 1.
void setGridType(const int &type)
Updates the type of grid: planar or geographic.
double m_s2urx
Upper right x-coordinate of the System 2.
A Converter is responsible for the conversion of coordinates between different Coordinate Systems (CS...
Definition: Converter.h:53
te::gm::Envelope WorldBoxTo(const te::gm::Envelope &worldBox, const unsigned int &sourceSRID, const unsigned int &targetSRID)
Transforms the coordinates of an envelope from a system of coordinates to another.
QPixmap * GetTextsPixmap(WorldTransformer transf, const std::vector< te::gm::LineString > &lines, const QFont &font, const QPen &pen, const bool &vertical, const QSize &displayDimensions)
Returns an image with the headers of the grid.
Geometry * getGeometryN(std::size_t i) const
It returns the n-th geometry in this GeometryCollection.
MultiLineString is a MultiCurve whose elements are LineStrings.
~WorldTransformer()=default
Destructor.
double getS2llx()
Returns the lower left corner x value.
boost::shared_ptr< UnitOfMeasure > UnitOfMeasurePtr
GridTypes m_type
Type of the grid (planar or geographic).
double getTranslateY()
Returns the translation in Y-axis.
double getX() const
It returns the x-coordinate.
Definition: Coord2D.h:102
void setMirroring(bool mirror)
Updates mirroring internal attribute.
std::vector< te::gm::LineString > m_hlines
Grid lines.
QPixmap * GetCleanImage(const QSize &s, const QColor &c)
Returns a transparent pixmap of size s.
double m_s1urx
Upper right x-coordinate of the System 1.
std::vector< te::gm::LineString > m_vlines
Grid lines.
Contains an implementation of a grid.
double m_verticalGap
Distance between lines in y-axis.
const double & getLowerLeftX() const
It returns a constant reference to the x coordinate of the lower left corner.
double m_s2llx
Lower left x-coordinate of the System 2.
void setSRID(int srid)
It sets the Spatial Reference System ID of the linestring.
double getScaleX()
Returns the scale in X-axis.
TEMAPEXPORT int CalculatePlanarZone(te::gm::Envelope latLongBox)
Calculates the UTM zone from a Geographic envelope.
bool isValid()
Returns TRUE if transformation is ok and FALSE otherwise.
QFont getFont() const
Returns the current font being used.
double getS1lly()
Returns the lower left corner y value.
void setPointN(std::size_t i, const Point &p)
It sets the value of the specified point to this new one.
double m_s2ury
Upper right y-coordinate of the System 2.
std::string Convert2String(boost::int16_t value)
It converts a short integer value to a string.
Definition: StringUtils.h:56
void setTransformationParameters(const te::gm::Envelope &system1Box, const te::gm::Envelope &system2Box)
Updates the matrix of transformation to be used.
double getS2Height()
Returns the height of the device box.
WorldTransformer()
Default constructor.
std::vector< te::gm::LineString > CalculateVerticalLines(const te::gm::Envelope &planarBox, const double &verticalLineInitial, const double &verticalLineGap, const int &maxGaps)
Calculates the lines in y-axis.
void DrawLine(QPainter *painter, QLineF &line, const int &txtOffSet, const bool &vertical)
Draws the line using the giving painter.
TEQTWIDGETSEXPORT int MillimetersToPixels(const QPaintDevice *device, const double &mm, const bool &printer)
Returns the size in pixels.
void transform(int oldsrid, int newsrid)
It will transform the coordinates of the Envelope from the old SRS to the new one.
double getS1Width()
Returns the width of the world box.
double m_translateX
The value corresponds to the X-Axis translation of system 2.
double m_s2Width
Width of System 2 coordinate system.
double getHeight() const
It returns the envelope height.
double m_initialX
Initial coordinate in x-axis.
bool isValid() const
It tells if the rectangle is valid or not.
unsigned int col
int m_maxGap
Maximum number of lines to be presented on the grid.
void system2Tosystem1(double dx, double dy, double &wx, double &wy) const
double getS2Width()
Returns the width of the device box.
TEGEOMEXPORT Geometry * GetGeomFromEnvelope(const Envelope *const e, int srid)
It creates a Geometry (a polygon) from the given envelope.
void transform(int srid)
It converts the coordinate values of the linestring to the new spatial reference system.
double getS2ury()
Returns the upper right corner y value.