暫無描述

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #include "map.h"
  2. #include <QDebug>
  3. #include <QDesktopWidget>
  4. #include <QPainter>
  5. #include <QPen>
  6. #include "gispoi.h"
  7. QPointF centroid(const QPolygonF &poly) {
  8. float A = 0.0f;
  9. float Cx = 0.0f;
  10. float Cy = 0.0f;
  11. QVector<float> VA;
  12. //VA.resize(poly.size());
  13. int size = poly.size();
  14. int ip1;
  15. float prodDif;
  16. for (int i = 0; i < size; i++) {
  17. ip1 = (i + 1)%size;
  18. prodDif = poly.at(i).x() * poly.at(ip1).y() - poly.at(i).y() * poly.at(ip1).x();
  19. A += prodDif;
  20. Cx += ( poly.at(i).x() + poly.at(ip1).x()) * prodDif;
  21. Cy += ( poly.at(i).y() + poly.at(ip1).y()) * prodDif;
  22. }
  23. A = A / 2.0;
  24. Cx = Cx / (6.0 * A);
  25. Cy = Cy / (6.0 * A);
  26. return QPointF(Cx,Cy);
  27. }
  28. Map::Map(QWidget *parent) :
  29. QWidget(parent)
  30. {
  31. srand(time(NULL));
  32. // Create country object and read data from the json file
  33. qDebug() << "Reading the Json...";
  34. myCountry = new Country;
  35. myCountry->readInfoFromJSON(":/data/pr.geo.json");
  36. qDebug() << "...done, read " << myCountry->Cities.size();
  37. cityColorMap = NULL;
  38. gisLocations = NULL;
  39. drawRoutes = false;
  40. // Compute the limits of the coordinates
  41. qDebug() << "Computing limits...";
  42. myCountry->limits();
  43. // Create the main widget and resize according to the map aspect ratio
  44. QDesktopWidget widget;
  45. QRect mainScreenSize = widget.availableGeometry(widget.primaryScreen());
  46. double diffX = myCountry->maxX - myCountry->minX > 0 ? myCountry->maxX - myCountry->minX : myCountry->minX - myCountry->maxX;
  47. double diffY = myCountry->maxY - myCountry->minY > 0 ? myCountry->maxY - myCountry->minY : myCountry->minY - myCountry->maxY;
  48. if (diffX > diffY) resize(mainScreenSize.width() * 0.5 , 0.5 * mainScreenSize.width()*(diffY/diffX));
  49. else resize(mainScreenSize.width() * 0.5, 0.5 * mainScreenSize.width()*(diffX/diffY));
  50. }
  51. Map::~Map() {
  52. if (myCountry != NULL) delete myCountry;
  53. if (cityColorMap != NULL) delete cityColorMap;
  54. if (gisLocations != NULL) delete [] gisLocations;
  55. }
  56. // These are used during the map drawing.
  57. QPoint **qpA = new QPoint*[100];
  58. unsigned int qpASize = 0;
  59. void Map::paintEvent(QPaintEvent *) {
  60. this->setWindowTitle("PR Visualization");
  61. QDesktopWidget widget;
  62. QRect mainScreenSize = widget.availableGeometry(widget.primaryScreen());
  63. // Creating the arrays that will hold the points for the cities
  64. if (qpASize == 0) {
  65. for (int i = 0; i < 100; i++) {
  66. qpA[i] = new QPoint[20000];
  67. }
  68. }
  69. // the QPainter is the 'canvas' to which we will draw
  70. // the QPen is the pen that will be used to draw to the 'canvas
  71. QPainter *p = new QPainter(this);
  72. QPen myPen;
  73. myPen.setWidth(1);
  74. myPen.setColor(QColor(0x100000));
  75. myPen.setBrush(QBrush(Qt::black));
  76. p->setPen(myPen);
  77. double factorX, factorY;
  78. // Computing the factors by which we'll scale the x and y coordinates.
  79. double diffX = myCountry->maxX - myCountry->minX > 0 ?
  80. myCountry->maxX - myCountry->minX : myCountry->minX - myCountry->maxX;
  81. double diffY = myCountry->maxY - myCountry->minY > 0 ?
  82. myCountry->maxY - myCountry->minY : myCountry->minY - myCountry->maxY;
  83. if (diffX > diffY) resize(mainScreenSize.width() * 0.5 , 0.5 * mainScreenSize.width()*(diffY/diffX));
  84. else resize(mainScreenSize.width() * 0.5, 0.5 * mainScreenSize.width()*(diffX/diffY));
  85. factorX = this->width() / diffX;
  86. factorY = this->height() / diffY;
  87. int colorCtr = 0;
  88. QMap<QString,QPolygonF*>::iterator it;
  89. unsigned int randColor;
  90. int cityCounter = 0;
  91. for (it = myCountry->Cities.begin() ; it != myCountry->Cities.end(); ++it) {
  92. QPolygonF *c = it.value();
  93. int x1 ,y1, x2, y2;
  94. x1 = factorX * (c->at(0).x() - myCountry->minX);
  95. y1 = height() - factorY*(c->at(0).y() - myCountry->minY) ;
  96. QPointF p1 = c->at(0);
  97. QPointF p2;
  98. int ctr = 0;
  99. QPoint *qp = qpA[cityCounter];
  100. QPoint *qpBegin = qp;
  101. // if no color map provided, we'll just color every city white.
  102. randColor = 0xffffff;
  103. if (cityColorMap)
  104. randColor = (cityColorMap->find(it.key()) == cityColorMap->end()) ?
  105. 0xffffff : (*cityColorMap)[it.key()];
  106. for(int i = 0; i < c->size() + 1; i++) {
  107. p2 = c->at((i+1)%c->size());
  108. x2 = factorX * (p2.x() - myCountry->minX);
  109. y2 = height() - factorY*(p2.y() - myCountry->minY) ;
  110. if (p2.x() != 0 && p1.x() != 0) {
  111. qp->setX(x2);
  112. qp->setY(y2);
  113. ctr++;
  114. qp++;
  115. }
  116. else if (p2.x() == 0) {
  117. QPolygon yourPoly;
  118. for (int i = 0; i < ctr; i++) yourPoly.push_back(qpBegin[i]);
  119. QPainterPath tmpPath;
  120. tmpPath.addPolygon(yourPoly);
  121. p->fillPath(tmpPath,QBrush(randColor));
  122. p->drawPolygon(qpBegin,ctr);
  123. ctr = 0;
  124. qpBegin = qp;
  125. }
  126. x1 = x2;
  127. y1 = y2;
  128. p1 = p2;
  129. }
  130. QPolygon yourPoly;
  131. for (int i = 0; i < ctr; i++) yourPoly.push_back(qpBegin[i]);
  132. QPainterPath *tmpPath = new QPainterPath;
  133. tmpPath->addPolygon(yourPoly);
  134. p->fillPath(*tmpPath,QBrush(randColor));
  135. p->drawPolygon(qpBegin,ctr,Qt::WindingFill);
  136. delete tmpPath;
  137. colorCtr++;
  138. cityCounter++;
  139. }
  140. qpASize = cityCounter;
  141. // Draw the city centers
  142. int circleRadius = (this->height() > this->width()) ? this->width()/20 : this->height()/20 ;
  143. int cX, cY, pX, pY;
  144. cX = cY = pX = pY = -1;
  145. /*
  146. myPen.setWidth(2);
  147. myPen.setColor(QColor(0x100000));
  148. myPen.setBrush(QBrush(Qt::black));
  149. p->setBrush(Qt::SolidPattern);
  150. p->setBrush(QBrush(0xff0000));
  151. QMap<QString,QPolygonF*>::iterator itc = this->myCountry->Cities.begin();
  152. for (; itc != this->myCountry->Cities.end(); itc++) {
  153. QPointF cent = centroid(*(itc.value()));
  154. cX = factorX * (cent.x() - myCountry->minX);
  155. cY = height() - factorY*(cent.y() - myCountry->minY);
  156. p->drawEllipse(static_cast<int>(cX) - circleRadius/2, static_cast<int>(cY)- circleRadius/2, circleRadius, circleRadius);
  157. qDebug() << itc.key() << cent.y() << cent.x();
  158. }
  159. */
  160. if(gisLocations) {
  161. myPen.setWidth(2);
  162. myPen.setColor(QColor(0x100000));
  163. myPen.setBrush(QBrush(Qt::black));
  164. p->setPen(myPen);
  165. for (unsigned int i = 0; i < numLocations; i++) {
  166. qDebug() << "name from locations:" << gisLocations[i].getName();
  167. cX = factorX * (gisLocations[i].getLon() - myCountry->minX);
  168. cY = height() - factorY*(gisLocations[i].getLat() - myCountry->minY);
  169. p->setBrush(Qt::SolidPattern);
  170. p->setBrush(QBrush(0xff0000));
  171. p->drawEllipse(cX, cY, circleRadius, circleRadius);
  172. p->setBrush(Qt::NoBrush);
  173. if (drawRoutes && pX > 0) {
  174. p->drawLine(pX+circleRadius/2,pY+circleRadius/2,cX+circleRadius/2,cY+circleRadius/2);
  175. }
  176. pX = cX; pY = cY;
  177. }
  178. }
  179. // Draws any lines between the cities which have been added using
  180. // the drawLine method.
  181. QVector < QPair<const GISPOI *,const GISPOI *> > ::iterator vit = this->cityLines.begin();
  182. for (; vit != this->cityLines.end(); vit++) {
  183. cX = factorX * (vit->first->getLon() - myCountry->minX);
  184. cY = height() - factorY*(vit->first->getLat() - myCountry->minY);
  185. pX = factorX * (vit->second->getLon() - myCountry->minX);
  186. pY = height() - factorY*(vit->second->getLat() - myCountry->minY);
  187. p->drawLine(pX+circleRadius/2,pY+circleRadius/2,cX+circleRadius/2,cY+circleRadius/2);
  188. }
  189. //c++11 way
  190. /*
  191. for (QPair<const GISPOI *, const GISPOI *> linePair: this->cityLines) {
  192. // qDebug() << "A line from " << linePair.first->getName() << " to " << linePair.second->getName() << endl;
  193. cX = factorX * (linePair.first->getLon() - myCountry->minX);
  194. cY = height() - factorY*(linePair.first->getLat() - myCountry->minY);
  195. pX = factorX * (linePair.second->getLon() - myCountry->minX);
  196. pY = height() - factorY*(linePair.second->getLat() - myCountry->minY);
  197. p->drawLine(pX+circleRadius/2,pY+circleRadius/2,cX+circleRadius/2,cY+circleRadius/2);
  198. }
  199. */
  200. delete p;
  201. }