#include "map.h" #include #include #include #include #include "gispoi.h" QPointF centroid(const QPolygonF &poly) { float A = 0.0f; float Cx = 0.0f; float Cy = 0.0f; QVector VA; //VA.resize(poly.size()); int size = poly.size(); int ip1; float prodDif; for (int i = 0; i < size; i++) { ip1 = (i + 1)%size; prodDif = poly.at(i).x() * poly.at(ip1).y() - poly.at(i).y() * poly.at(ip1).x(); A += prodDif; Cx += ( poly.at(i).x() + poly.at(ip1).x()) * prodDif; Cy += ( poly.at(i).y() + poly.at(ip1).y()) * prodDif; } A = A / 2.0; Cx = Cx / (6.0 * A); Cy = Cy / (6.0 * A); return QPointF(Cx,Cy); } Map::Map(QWidget *parent) : QWidget(parent) { srand(time(NULL)); // Create country object and read data from the json file qDebug() << "Reading the Json..."; myCountry = new Country; myCountry->readInfoFromJSON(":/data/pr.geo.json"); qDebug() << "...done, read " << myCountry->Cities.size(); cityColorMap = NULL; gisLocations = NULL; drawRoutes = false; // Compute the limits of the coordinates qDebug() << "Computing limits..."; myCountry->limits(); // Create the main widget and resize according to the map aspect ratio QDesktopWidget widget; QRect mainScreenSize = widget.availableGeometry(widget.primaryScreen()); double diffX = myCountry->maxX - myCountry->minX > 0 ? myCountry->maxX - myCountry->minX : myCountry->minX - myCountry->maxX; double diffY = myCountry->maxY - myCountry->minY > 0 ? myCountry->maxY - myCountry->minY : myCountry->minY - myCountry->maxY; if (diffX > diffY) resize(mainScreenSize.width() * 0.5 , 0.5 * mainScreenSize.width()*(diffY/diffX)); else resize(mainScreenSize.width() * 0.5, 0.5 * mainScreenSize.width()*(diffX/diffY)); } Map::~Map() { if (myCountry != NULL) delete myCountry; if (cityColorMap != NULL) delete cityColorMap; if (gisLocations != NULL) delete [] gisLocations; } // These are used during the map drawing. QPoint **qpA = new QPoint*[100]; unsigned int qpASize = 0; void Map::paintEvent(QPaintEvent *) { this->setWindowTitle("PR Visualization"); QDesktopWidget widget; QRect mainScreenSize = widget.availableGeometry(widget.primaryScreen()); // Creating the arrays that will hold the points for the cities if (qpASize == 0) { for (int i = 0; i < 100; i++) { qpA[i] = new QPoint[20000]; } } // the QPainter is the 'canvas' to which we will draw // the QPen is the pen that will be used to draw to the 'canvas QPainter *p = new QPainter(this); QPen myPen; myPen.setWidth(1); myPen.setColor(QColor(0x100000)); myPen.setBrush(QBrush(Qt::black)); p->setPen(myPen); double factorX, factorY; // Computing the factors by which we'll scale the x and y coordinates. double diffX = myCountry->maxX - myCountry->minX > 0 ? myCountry->maxX - myCountry->minX : myCountry->minX - myCountry->maxX; double diffY = myCountry->maxY - myCountry->minY > 0 ? myCountry->maxY - myCountry->minY : myCountry->minY - myCountry->maxY; if (diffX > diffY) resize(mainScreenSize.width() * 0.5 , 0.5 * mainScreenSize.width()*(diffY/diffX)); else resize(mainScreenSize.width() * 0.5, 0.5 * mainScreenSize.width()*(diffX/diffY)); factorX = this->width() / diffX; factorY = this->height() / diffY; int colorCtr = 0; QMap::iterator it; unsigned int randColor; int cityCounter = 0; for (it = myCountry->Cities.begin() ; it != myCountry->Cities.end(); ++it) { QPolygonF *c = it.value(); int x1 ,y1, x2, y2; x1 = factorX * (c->at(0).x() - myCountry->minX); y1 = height() - factorY*(c->at(0).y() - myCountry->minY) ; QPointF p1 = c->at(0); QPointF p2; int ctr = 0; QPoint *qp = qpA[cityCounter]; QPoint *qpBegin = qp; // if no color map provided, we'll just color every city white. randColor = 0xffffff; if (cityColorMap) randColor = (cityColorMap->find(it.key()) == cityColorMap->end()) ? 0xffffff : (*cityColorMap)[it.key()]; for(int i = 0; i < c->size() + 1; i++) { p2 = c->at((i+1)%c->size()); x2 = factorX * (p2.x() - myCountry->minX); y2 = height() - factorY*(p2.y() - myCountry->minY) ; if (p2.x() != 0 && p1.x() != 0) { qp->setX(x2); qp->setY(y2); ctr++; qp++; } else if (p2.x() == 0) { QPolygon yourPoly; for (int i = 0; i < ctr; i++) yourPoly.push_back(qpBegin[i]); QPainterPath tmpPath; tmpPath.addPolygon(yourPoly); p->fillPath(tmpPath,QBrush(randColor)); p->drawPolygon(qpBegin,ctr); ctr = 0; qpBegin = qp; } x1 = x2; y1 = y2; p1 = p2; } QPolygon yourPoly; for (int i = 0; i < ctr; i++) yourPoly.push_back(qpBegin[i]); QPainterPath *tmpPath = new QPainterPath; tmpPath->addPolygon(yourPoly); p->fillPath(*tmpPath,QBrush(randColor)); p->drawPolygon(qpBegin,ctr,Qt::WindingFill); delete tmpPath; colorCtr++; cityCounter++; } qpASize = cityCounter; // Draw the city centers int circleRadius = (this->height() > this->width()) ? this->width()/20 : this->height()/20 ; int cX, cY, pX, pY; cX = cY = pX = pY = -1; /* myPen.setWidth(2); myPen.setColor(QColor(0x100000)); myPen.setBrush(QBrush(Qt::black)); p->setBrush(Qt::SolidPattern); p->setBrush(QBrush(0xff0000)); QMap::iterator itc = this->myCountry->Cities.begin(); for (; itc != this->myCountry->Cities.end(); itc++) { QPointF cent = centroid(*(itc.value())); cX = factorX * (cent.x() - myCountry->minX); cY = height() - factorY*(cent.y() - myCountry->minY); p->drawEllipse(static_cast(cX) - circleRadius/2, static_cast(cY)- circleRadius/2, circleRadius, circleRadius); qDebug() << itc.key() << cent.y() << cent.x(); } */ if(gisLocations) { myPen.setWidth(2); myPen.setColor(QColor(0x100000)); myPen.setBrush(QBrush(Qt::black)); p->setPen(myPen); for (unsigned int i = 0; i < numLocations; i++) { qDebug() << "name from locations:" << gisLocations[i].getName(); cX = factorX * (gisLocations[i].getLon() - myCountry->minX); cY = height() - factorY*(gisLocations[i].getLat() - myCountry->minY); p->setBrush(Qt::SolidPattern); p->setBrush(QBrush(0xff0000)); p->drawEllipse(cX, cY, circleRadius, circleRadius); p->setBrush(Qt::NoBrush); if (drawRoutes && pX > 0) { p->drawLine(pX+circleRadius/2,pY+circleRadius/2,cX+circleRadius/2,cY+circleRadius/2); } pX = cX; pY = cY; } } // Draws any lines between the cities which have been added using // the drawLine method. QVector < QPair > ::iterator vit = this->cityLines.begin(); for (; vit != this->cityLines.end(); vit++) { cX = factorX * (vit->first->getLon() - myCountry->minX); cY = height() - factorY*(vit->first->getLat() - myCountry->minY); pX = factorX * (vit->second->getLon() - myCountry->minX); pY = height() - factorY*(vit->second->getLat() - myCountry->minY); p->drawLine(pX+circleRadius/2,pY+circleRadius/2,cX+circleRadius/2,cY+circleRadius/2); } //c++11 way /* for (QPair linePair: this->cityLines) { // qDebug() << "A line from " << linePair.first->getName() << " to " << linePair.second->getName() << endl; cX = factorX * (linePair.first->getLon() - myCountry->minX); cY = height() - factorY*(linePair.first->getLat() - myCountry->minY); pX = factorX * (linePair.second->getLon() - myCountry->minX); pY = height() - factorY*(linePair.second->getLat() - myCountry->minY); p->drawLine(pX+circleRadius/2,pY+circleRadius/2,cX+circleRadius/2,cY+circleRadius/2); } */ delete p; }