Browse Source

Initial commit

Jose Ortiz 9 years ago
commit
ce7791269d
18 changed files with 970 additions and 0 deletions
  1. 134
    0
      README.md
  2. 49
    0
      census.cpp
  3. 19
    0
      census.h
  4. 8
    0
      city.cpp
  5. 23
    0
      city.h
  6. 99
    0
      country.cpp
  7. 26
    0
      country.h
  8. 3
    0
      doublepoint.cpp
  9. 14
    0
      doublepoint.h
  10. 16
    0
      gispoi.cpp
  11. 56
    0
      gispoi.h
  12. 132
    0
      main.cpp
  13. 60
    0
      mainwindow.cpp
  14. 29
    0
      mainwindow.h
  15. 24
    0
      mainwindow.ui
  16. 206
    0
      map.cpp
  17. 40
    0
      map.h
  18. 32
    0
      prMap.pro

+ 134
- 0
README.md View File

@@ -0,0 +1,134 @@
1
+# PR Map
2
+
3
+
4
+
5
+### Objectives
6
+Throughout this exercise the students will practice:
7
+
8
+* reading a text file sequentially 
9
+* repetition and control structures
10
+* creating and manipulating an array of objects
11
+* writing functions to process arrays of objects
12
+* passing arrays of objects as parameters
13
+* modular programming
14
+
15
+### Concepts
16
+
17
+Working with arrays of objects is a very common task in C++ programs. Once you have read information about the objects from a file and/or the user, you must relly on your algorithmic and C++ skills to invoke the proper methods and functions in order to correctly process the data.
18
+
19
+In this lab, we will be working with *georeferenced* data about the cities in Puerto Rico.  When a data is georeferenced* it simply means that it has an associated location in pyhsical space. Typically this **location** means latitude and longitude coordinates.  For example, the following is part of file that contains georeferenced data for some Puertorrican cities:
20
+
21
+
22
+```
23
+Arroyo 17.9658 -66.0614
24
+Bayamon 18.3833 -66.15
25
+Caguas 18.2342 -66.0486
26
+Dorado 18.4589 -66.2678
27
+Fajardo 18.3258 -65.6525
28
+```
29
+
30
+As you saw in class, **classes** are the most common way that C++ programmers encapsulate data that is associated to an entity. For example, in the case of the georeferenced points, a practical way to encapsulate the information about each city would be to implement a **GeoreferencedPointOfInterest** class that contains at least data members for: the name of the city, its latitude and longitude.  The **GPOI** class would also need to implement methods to access, modify, and perform computations on its properties. 
31
+
32
+### The GPOI class
33
+
34
+In this lab, you are provided a **GPOI** class with the following interface:
35
+
36
+* `GISPOI()`: the default constructor
37
+
38
+* `GISPOI(QString s, double latitude, double longitude)`:  constructor that accepts name, longitude and latitude.
39
+
40
+* `double getLat()`, `double getLon()`:  getters for the latutide, longitude.
41
+
42
+* ` QString getName()`:  getter for the name.
43
+
44
+* `void setAll(string s, double a, double b)`: setter for all the properties (at once)
45
+
46
+* `double odDistance(const GISPOI &B) const`: given B, another GPOI object, returns the *orthodromic* distance (or the closest distance) between the invoking GPOI and B.
47
+
48
+
49
+### Exercise 0 - Download and understand the code
50
+
51
+1. Download _______.
52
+
53
+2. Open the .pro file. Build the program and run it. In its current state, the program simply displays a map of Puerto Rico. This map is provided so that you can viualize the results of your program.
54
+
55
+    When you complete this program, it will need some text input from the user. Thus, we need to specify in *Qt Creator* that we expect this program to run in a **terminal**, i.e. not on the QtCreator window. To do this, please click of the `Projects` button on the left part of the *QtCreator* window. Then choose `Run` on the tab near the top of the window. Then make sure that the checkbox `Run in terminal` is checked.
56
+
57
+3. Build the program just to determine if there are any outstanding **errors**. You may see some warnings which are due to the fact that some of the functions are incomplete (you will complete throughout this lab.)
58
+
59
+3. Open the `main.cpp` file. This is the file where you will be writing your code. This file contains the following functions:
60
+
61
+    1. `void printArrayOfCities(GISPOI A[], int size)`: Given A, an array of GISPOI objects and its size, prints all the cities in the array. You may use this function as part of your debugging.
62
+    
63
+    2. `int countLinesInFile(ifstream &file)`: Given a reference to the object that represents a file, this function counts and returns the number of lines in the file. 
64
+
65
+    3. `void readFileToArray(ifstream &file, GISPOI A[], int numOfCities)`: Given the ifstream object of a file, an array of cities and the number of records to read from the file, this function reads the values from the file and populates the array with objects. **THIS IS A FUNCTION THAT YOU WILL IMPLEMENT**
66
+
67
+    4. `void maxDistances(GISPOI A[], int size, int &idxCityA, int &idxCityB)` : Given A, the array of cities, determines the farthest two cities. Returns (by reference) the indices of the two cities in the array. **THIS IS A FUNCTION THAT YOU WILL IMPLEMENT**
68
+
69
+    5. `void minDistances(GISPOI A[], int size, int &idxCityA, int &idxCityB)`: Given A, the array of cities, determines the closest two cities. Returns (by reference) the indices of the two cities in the array. **THIS IS A FUNCTION THAT YOU WILL IMPLEMENT**
70
+
71
+    5. `double cycleDistance(GISPOI A[], int size, int P[])`: Given the array of cities, the size of the array and a array (P) with a permutation of the integers [0, size-1] computes and returns the distance to travel the cycle of cities A[P[0]] $\rightarrow$ A[P[1]] $\rightarrow$ .... $\rightarrow$ A[P[size-1]]. 
72
+
73
+        For example, if the cities read from the file where Mayaguez, Ponce, Yauco and San Juan (in that order) and the permutation $P$ is $left\(3, 1, 0, 2\right)$, the function should compute the distance of a cycle from San Juan $\rightarrow$ Ponce $\rightarrow$ Mayaguez $\rightarrow$ Yauco $\rightarrow$ San Juan.
74
+
75
+
76
+        **THIS IS A FUNCTION THAT YOU WILL IMPLEMENT**
77
+
78
+There is one additional function that you need to know:
79
+
80
+1. `void MainWindow::drawLine(const GISPOI &city01, const GISPOI &city02)`: Given (a reference to) two GISPOI objects, paints a line between them.
81
+
82
+2. `void drawPoints(GISPOI* gisLocations, unsigned int size);`: Given an array of GISPOI objects and their size, displays their locations as points in the map.
83
+
84
+### Exercise 1 - read the georeferenced points into an array
85
+
86
+Remember that you will only be changing code in the `main.cpp` file. Your first task will be to add code to read the entire contents of a file into an array of GISPOI objects.
87
+
88
+1. In the main function, add the necessary instructions to open the file that contains the georeferenced city information. The file is `pr10.txt` in the data directory. You need to provide the complete path to the file as a parameter to the `open()`  method of your `ifstream` object. As always, when using files you should verify if the entered name is a file that can be succefully opened for reading.
89
+
90
+2. Invoke the `int countLinesInFile(ifstream &inFile)` function to obtain the number of lines in the file. You may print out the number obtained so that you can validate is your program is working correctly.
91
+
92
+3. **Dynamically** create an array as big as the number of lines in the file.
93
+
94
+3. Modify the `void readFileToArray(ifstream &file, GISPOI A[], int numOfCities)` function so that it reads all the lines in the file to the objects in the array. 
95
+
96
+1. In the main function invoke the `readFileToArray` function, passing the reference to the file, the array you created in step ???, and its size.
97
+
98
+1. After invoking `readFileToArray` you may invoke `void printArrayOfCities(GISPOI A[], int size)` to print the names and georeferences of the points read from the file. 
99
+
100
+1. Ask the user for the name of the text file that contains data in the following format: CityName Latitude Longitude. Here are example files: cities.txt, calif.txt, and pr.txt. 
101
+
102
+1. Invoke the method `drawPoints(GISPOI* gisLocations, unsigned int size)` on the `w` object as follows so that a point will be shown in the map for each city: `w.drawPoints(A, size)` (*assuming that A is your array*). You should obtain something similar to the next figure. 
103
+
104
+    ![](http://demo05.cloudimage.io/s/resize/400/i.imgur.com/7AneJpf.png) 
105
+
106
+
107
+
108
+### Exercise 2 - the max and min functions
109
+
110
+Once we have the information of georeferenced cities in an array of objects, we can start processing them in many interesting ways. We will start with some basic operations.
111
+
112
+1. Read the documentation and implement the function `void maxDistances(GISPOI A[], int size, int &idxCityA, int &idxCityB)`. Invoke the function from `main()`. 
113
+
114
+1. Use the `void drawLine(const GISPOI &city01, const GISPOI &city02)` method of the `w` object to paint a line connecting the two farthest cities.  Notice that the second and third parameters of this method are ** references to the objects that represent the cities** (not their indices in the array).
115
+
116
+1. Read the documentation and implement the function `void minDistances(GISPOI A[], int size, int &idxCityA, int &idxCityB)`. Invoke the function from `main()`. 
117
+
118
+1. Use the `void drawLine(const GISPOI &city01, const GISPOI &city02)` method of the `w` object to paint a line connecting the two closest cities. 
119
+
120
+
121
+
122
+### Exercise 3 - compute the cycle distance
123
+
124
+1. Read the documentation and implement the function `double cycleDistance(GISPOI A[], int size, int P[])`. Invoke the function from `main()` as indicated in the comments inside the main function:
125
+
126
+    1. First with $P = \left(0, 2, 4, 6, 8, 1, 3, 5, 7, 9\right)$
127
+    2. Then with $P = \left(0, 3, 6, 9, 1, 4, 7, 2, 5, 8\right)$ 
128
+
129
+
130
+### Exercise 4 - more fun
131
+
132
+1. Change your code so that it now opens the `pr.txt` file.  Validate your results and wonder at your great achievement.
133
+
134
+### Deliverables

+ 49
- 0
census.cpp View File

@@ -0,0 +1,49 @@
1
+#include "census.h"
2
+#include <QFile>
3
+#include <QJsonDocument>
4
+#include <QJsonArray>
5
+#include <QJsonObject>
6
+#include <qDebug>
7
+
8
+
9
+///
10
+/// \brief
11
+/// Census::readDataFromFile - Populates the Census object with data from a file.
12
+/// at the end we should have Map with (key,value) = (city name, some metric).
13
+/// \param fileName: name of the JSON file
14
+/// \return true if the file was openned and read
15
+///
16
+bool Census::readDataFromFile(QString fileName) {
17
+    QFile loadFile(fileName);
18
+
19
+    if (!loadFile.open(QIODevice::ReadOnly)) {
20
+        qWarning("Couldn't open save file.");
21
+        return false;
22
+    }
23
+
24
+    QByteArray saveData = loadFile.readAll();
25
+    QJsonDocument loadDoc(QJsonDocument::fromJson(saveData));
26
+    QJsonArray topLevelArray = loadDoc.array();
27
+
28
+    int ctr = 1;
29
+
30
+    minValue = maxValue = topLevelArray[0].toObject()["percent_change"].toDouble();
31
+
32
+    foreach(QJsonValue obj, topLevelArray) {
33
+        double value = obj.toObject()["percent_change"].toDouble();
34
+        (*this)[obj.toObject()["city"].toString()] =  value;
35
+        if (value > maxValue) maxValue = value;
36
+        if (value < minValue) minValue = value;
37
+
38
+        ctr++;
39
+    }
40
+
41
+    Census::iterator it = this->begin();
42
+
43
+    for (; it != this->end(); ++it)
44
+        qDebug() << it.key() << it.value();
45
+
46
+    factor = 128.0 / (maxValue - minValue) ;
47
+
48
+}
49
+

+ 19
- 0
census.h View File

@@ -0,0 +1,19 @@
1
+#ifndef CENSUS_H
2
+#define CENSUS_H
3
+
4
+#include <QString>
5
+#include <QMap>
6
+
7
+///
8
+/// \brief The Census class
9
+///
10
+class Census : public QMap<QString, double> {
11
+
12
+public:
13
+    bool readDataFromFile(QString fileName);
14
+    double minValue, maxValue, factor, negFactor;
15
+};
16
+
17
+
18
+
19
+#endif // CENSUS_H

+ 8
- 0
city.cpp View File

@@ -0,0 +1,8 @@
1
+#include "city.h"
2
+
3
+
4
+
5
+void City::pushPoint(double x, double y) {
6
+    geometry->push_back(DoublePoint(x,y));
7
+
8
+}

+ 23
- 0
city.h View File

@@ -0,0 +1,23 @@
1
+#ifndef CITY_H
2
+#define CITY_H
3
+
4
+#include <doublepoint.h>
5
+#include <QVector>
6
+
7
+///
8
+/// \brief The City class
9
+///        This is merely a vector of points, i.e. the points that make up the
10
+///        polygon of the city.
11
+
12
+class City {
13
+public:
14
+    QVector<DoublePoint> *geometry;
15
+    City() {};
16
+    void pushPoint(double x, double y);
17
+
18
+    virtual int getSize() { return geometry->size(); }
19
+    QVector<DoublePoint> *getGeometry() { return geometry; }
20
+    ~City() {delete geometry; }
21
+};
22
+
23
+#endif // CITY_H

+ 99
- 0
country.cpp View File

@@ -0,0 +1,99 @@
1
+#include "country.h"
2
+#include <QFile>
3
+#include <QDebug>
4
+#include <QJsonArray>
5
+#include <QJsonObject>
6
+#include <QJsonDocument>
7
+
8
+void Country::limits(){
9
+    QMap<QString,City*>::iterator it = Cities.begin();
10
+
11
+
12
+
13
+
14
+    minX = maxX = Cities.begin().value()->geometry->at(0).x;
15
+    minY = maxY = Cities.begin().value()->geometry->at(0).y;
16
+
17
+    for (it = Cities.begin() + 1; it != Cities.end(); ++it) {
18
+
19
+        City *c = it.value();
20
+
21
+        for (int i = 0; i < c->getSize(); i++) {
22
+            if (c->geometry->at(i).x != 0.0) {
23
+            if (c->geometry->at(i).x > maxX ) maxX = c->geometry->at(i).x;
24
+            if (c->geometry->at(i).y > maxY ) maxY = c->geometry->at(i).y;
25
+            if (c->geometry->at(i).x < minX ) minX = c->geometry->at(i).x;
26
+            if (c->geometry->at(i).y < minY ) minY = c->geometry->at(i).y;
27
+            }
28
+        }
29
+    }
30
+    qDebug() << minX << minY << maxX << maxY ;
31
+}
32
+
33
+void Country::topLeft(QString &st, DoublePoint &p ) {
34
+    QMap<QString,City*>::iterator it = Cities.begin();
35
+    st = it.key();
36
+    p.x = it.value()->getGeometry()->at(0).x;
37
+    p.y = it.value()->getGeometry()->at(0).y;
38
+
39
+    qDebug() << p.x << ". " << p.y;
40
+    for (it = Cities.begin(); it != Cities.end(); ++it) {
41
+        QVector<DoublePoint> *geometry = it.value()->getGeometry();
42
+        for (int i = 0; i < geometry->size(); i++) {
43
+            if (geometry->at(i).x > p.x && geometry->at(i).y < p.y)  {
44
+                p.x = geometry->at(i).x;
45
+                p.y = geometry->at(i).y;
46
+                st = it.key();
47
+            }
48
+        }
49
+
50
+    }
51
+}
52
+unsigned long  *colorMap;
53
+bool Country::readInfoFromJSON(QString fileName) {
54
+    QFile loadFile(fileName);
55
+
56
+    if (!loadFile.open(QIODevice::ReadOnly)) {
57
+        qWarning("Couldn't open save file.");
58
+        return false;
59
+    }
60
+
61
+    QByteArray saveData = loadFile.readAll();
62
+    QJsonDocument loadDoc(QJsonDocument::fromJson(saveData));
63
+    QJsonArray topLevelArray = loadDoc.array();
64
+
65
+    int ctr = 1;
66
+    foreach(QJsonValue obj, topLevelArray) {
67
+        QVector<DoublePoint> *points = new QVector<DoublePoint>;
68
+        QJsonArray geometryArray = obj.toObject()["geometry"].toObject()["coordinates"].toArray();
69
+        QString polyType = obj.toObject()["geometry"].toObject()["type"].toString();
70
+        if (polyType == "Polygon") {
71
+            for (int i = 0; i < geometryArray[0].toArray().size(); i++) {
72
+                points->push_back(DoublePoint(
73
+                                geometryArray[0].toArray()[i].toArray()[0].toDouble(),
74
+                                geometryArray[0].toArray()[i].toArray()[1].toDouble()));
75
+            }
76
+        }
77
+        else {
78
+            for (int i = 0; i <geometryArray.size() ; i++) {
79
+
80
+                for (int j = 0; j < geometryArray[i].toArray()[0].toArray().size(); j++) {
81
+                    points->push_back(DoublePoint(
82
+                                          geometryArray[i].toArray()[0].toArray()[j].toArray()[0].toDouble(),
83
+                                          geometryArray[i].toArray()[0].toArray()[j].toArray()[1].toDouble()));
84
+
85
+                }
86
+                // I will push a 0,0 between each polygon of a multipolygon to distinguish
87
+                points->push_back(DoublePoint(0,0));
88
+            }
89
+        }
90
+
91
+        QString cityName = obj.toObject()["properties"].toObject()["city"].toString();
92
+
93
+        qDebug() << "Storing: " << cityName;
94
+        Cities[cityName] = new City;
95
+        Cities[cityName]->geometry = points;
96
+
97
+        ctr++;
98
+    }
99
+}

+ 26
- 0
country.h View File

@@ -0,0 +1,26 @@
1
+#ifndef COUNTRY_H
2
+#define COUNTRY_H
3
+
4
+#include <doublepoint.h>
5
+#include <city.h>
6
+#include <QMap>
7
+
8
+
9
+///
10
+/// \brief The Country class
11
+///        A map of (city name, city structure)
12
+///
13
+class Country {
14
+public:
15
+    QMap<QString,City*> Cities;
16
+
17
+    double minX, minY, maxX, maxY;
18
+    Country() {}
19
+    bool readInfoFromJSON(QString fileName);
20
+    void topLeft(QString &st, DoublePoint &p );
21
+    void limits();
22
+    QMap<QString,City*> getCities() { return Cities;}
23
+    //~Country() { delete Cities; }
24
+};
25
+
26
+#endif // COUNTRY_H

+ 3
- 0
doublepoint.cpp View File

@@ -0,0 +1,3 @@
1
+#include "doublepoint.h"
2
+
3
+

+ 14
- 0
doublepoint.h View File

@@ -0,0 +1,14 @@
1
+#ifndef DOUBLEPOINT_H
2
+#define DOUBLEPOINT_H
3
+
4
+class DoublePoint {
5
+public:
6
+    double x, y;
7
+    DoublePoint() {x = 0; y = 0;}
8
+    DoublePoint(double a, double b) {
9
+        x = a; y = b;
10
+    }
11
+
12
+};
13
+
14
+#endif // DOUBLEPOINT_H

+ 16
- 0
gispoi.cpp View File

@@ -0,0 +1,16 @@
1
+#include "gispoi.h"
2
+
3
+GISPOI::GISPOI()
4
+{
5
+}
6
+
7
+// Function odDistance(A,B)
8
+// Given two objects A and B of type GISPOI, uses their longitudes and
9
+// latitudes to compute and return their orthodromic distance in kilometers.
10
+
11
+double GISPOI::odDistance(const GISPOI &B) const {
12
+    return EARTH_RADIUS * acos(
13
+        sin( deg2rad( getLat() ) ) * sin( deg2rad( B.getLat() ) ) +
14
+        cos( deg2rad( getLat() ) ) * cos( deg2rad( B.getLat() ) ) *
15
+        cos( deg2rad( getLon() ) - deg2rad(B.getLon()) ) );
16
+}

+ 56
- 0
gispoi.h View File

@@ -0,0 +1,56 @@
1
+#ifndef GISPOI_H
2
+#define GISPOI_H
3
+#include <QString>
4
+#include <iostream>
5
+#include <QDebug>
6
+#include <cmath>
7
+#include "doublepoint.h"
8
+using namespace std;
9
+
10
+const double EARTH_RADIUS =  6372.8;
11
+const double TWOPI = 2 * acos(-1);
12
+
13
+inline double deg2rad(double deg) {
14
+    return deg/360.0 * TWOPI;
15
+}
16
+
17
+
18
+class GISPOI
19
+{
20
+private:
21
+    QString name;
22
+    double lat, lon;
23
+
24
+public:
25
+    GISPOI();
26
+    GISPOI(QString s, double latitude, double longitude) 
27
+        {name = s; lat = latitude; lon = longitude;}
28
+
29
+    double getLat()   const {return lat;}
30
+    double getLon()   const {return lon;}
31
+    QString getName() const {return name;}
32
+    
33
+    void setAll(QString s, double latitude, double longitude)
34
+        {name = s; lat = latitude; lon = longitude;}
35
+    void setAll(string s, double latitude, double longitude) 
36
+        {name = QString::fromStdString(s); lat = latitude; lon = longitude;}
37
+    
38
+    void print() {
39
+        qDebug() << name << " " << lat  << " "
40
+             << lon << endl;
41
+    }
42
+
43
+    double odDistance(const GISPOI &B) const;
44
+// Function odDistance(A,B)
45
+// Given two objects A and B of type GISPOI, uses their longitudes and
46
+// latitudes to compute and return their orthodromic distance in kilometers.
47
+
48
+ 
49
+
50
+};
51
+
52
+
53
+
54
+
55
+
56
+#endif // GISPOI_H

+ 132
- 0
main.cpp View File

@@ -0,0 +1,132 @@
1
+#include "mainwindow.h"
2
+#include <QApplication>
3
+#include <cmath>
4
+#include <cassert>
5
+#include <fstream>
6
+using namespace std;
7
+
8
+
9
+// Function unitTests:
10
+// Some unit tests for the distance function
11
+
12
+// void unitTests(){
13
+//     GISPOI ny(    "NewYork",   40.7142,  -74.0064 );
14
+//     GISPOI london("London",    51.50,    -0.1167 );
15
+//     GISPOI la(    "LA",        34.0522,  -118.2428);
16
+
17
+//     assert(abs( ny.odDistance(london) - 5576.74) < 10);
18
+//     assert(abs( ny.odDistance(la) -     3940.14) < 10);
19
+//     assert(abs( ny.odDistance(ny) -           0) < 100);
20
+
21
+//     cout << "Passed all unit tests...\n";
22
+// }
23
+
24
+// Function printArrayOfCities(A, size):
25
+// Given A, an array of GISPOI objects and its size, prints
26
+// all the cities in the array.
27
+
28
+void printArrayOfCities(GISPOI A[], int size) {
29
+    for (int i = 0; i < size; i++)
30
+        A[i].print();
31
+}
32
+
33
+// Function countLinesInFile(f)
34
+// Given a reference to the object that represents a file, this function
35
+// counts and returns the number of lines in the file.
36
+
37
+int countLinesInFile(ifstream &file) {
38
+    string dummy;
39
+    int ctr = 0;
40
+
41
+    while( getline(file,dummy)) ctr++;
42
+
43
+    // 'reset' the file, so that it can be reread from the start
44
+    file.clear();
45
+    file.seekg(0, ios::beg) ;
46
+    return ctr;
47
+}
48
+
49
+// Function readFileToArray(file, A, numCities):
50
+// Given the ifstream object of a file, an (empty) array of cities
51
+// and the number of records to read from the file, this function
52
+// reads the values from the file and populates the array with
53
+// objects.
54
+
55
+void readFileToArray(ifstream &file, GISPOI A[], int numOfCities) {
56
+    // your code here
57
+    cout << "Reading the file and storing in array of cities.."
58
+            "(your job)" << endl;
59
+
60
+}
61
+
62
+// Function maxDistances(A, size, idxCityA, idxCityB):
63
+// Given the array of cities, determines the farthest two cities.
64
+// Returns (by reference) the indices of the two cities in the array.
65
+
66
+void maxDistances(GISPOI A[], int size, int &idxCityA, int &idxCityB){
67
+    // your code here
68
+}
69
+
70
+
71
+// Function minDistances(A, size, idxCityA, idxCityB):
72
+// Given the array of cities, determines the closest two cities.
73
+// Returns (by reference) the indices of the two cities in the array.
74
+void minDistances(GISPOI A[], int size, int &idxCityA, int &idxCityB){
75
+    // your code here
76
+    cout << "Computing the two closest cities..." <<
77
+            "(your job)" << endl;
78
+}
79
+
80
+
81
+// Function cycleDistance (A, size, P):
82
+// Given the array of cities, the size of the array and a array (P) with a
83
+// permutation of the integers [0, size-1] computes and returns the distance
84
+// to travel the cycle of cities A[P[0]] -- A[P[1]] -- .... -- A[P[size-1]]
85
+
86
+double cycleDistance(GISPOI A[], int size, int P[]){
87
+    // your code here
88
+    return 0.0;
89
+}
90
+
91
+
92
+// The main program can be summarized with this pseudocode:
93
+// 1. Reads the contents of the file to an array of structures.
94
+// 2. Computes the cities with max distance.
95
+// 3. Computes the cities with min distance.
96
+// 4. Computes the total distance of traveling the cities in a certain order.
97
+
98
+
99
+int main(int argc, char *argv[])
100
+{
101
+    QApplication a(argc, argv);
102
+    MainWindow w;
103
+    w.show();
104
+
105
+    // open the file and check its validity
106
+    // you need to use inFile.open(fileName.c_str()) instead of inFile.open(fileName)
107
+    // since the open method expects a c-type string instead of a c++ string object 
108
+
109
+    // count the number of lines in the file
110
+
111
+    // create an array of GISPOI objects with exactly as many elements as there
112
+    // are lines in the file.
113
+
114
+    // read the data from the file into the array of structures
115
+
116
+
117
+    // paint the points onto the map window
118
+
119
+    // Here: Put the code to invoke the max distance function and show a line
120
+    // in the map between those two cities.
121
+
122
+
123
+    // Here: Put the code to invoke the min distance function and show a line
124
+    // in the map between those two cities.
125
+
126
+
127
+    // Here: Put the code to compute the cycle distance using these permutation
128
+    // P = {0, 2, 4, 6, 8, 1, 3, 5, 7, 9}
129
+    // P = {0, 3, 6, 9, 1, 4, 7, 2, 5, 8}
130
+
131
+    return a.exec();
132
+}

+ 60
- 0
mainwindow.cpp View File

@@ -0,0 +1,60 @@
1
+#include "mainwindow.h"
2
+#include "ui_mainwindow.h"
3
+#include <QPainter>
4
+#include <QPen>
5
+#include <QCoreApplication>
6
+//#include <QJsonDocument>
7
+#include <QFile>
8
+#include <QDebug>
9
+//#include <QJsonArray>
10
+//#include <QJsonObject>
11
+#include <QDesktopWidget>
12
+#include <QVector>
13
+#include <QPoint>
14
+#include <string>
15
+#include <QPolygon>
16
+#include <census.h>
17
+#include <city.h>
18
+#include <country.h>
19
+#include <doublepoint.h>
20
+#include <gispoi.h>
21
+
22
+using namespace std;
23
+
24
+
25
+Country PR;
26
+
27
+MainWindow::MainWindow(QWidget *parent) :
28
+    QMainWindow(parent),
29
+    ui(new Ui::MainWindow)
30
+{
31
+
32
+    srand(time(NULL));
33
+    myMap = new Map(this);
34
+    myMap->show();
35
+
36
+    ui->setupUi(this);
37
+
38
+    // just hidding the toolbars to have a bigger drawing area.
39
+    QList<QToolBar *> toolbars = this->findChildren<QToolBar *>();
40
+    foreach(QToolBar *t, toolbars) t->hide();
41
+    QList<QStatusBar *> statusbars = this->findChildren<QStatusBar *>();
42
+    foreach(QStatusBar *t, statusbars) t->hide();
43
+
44
+    resize(myMap->width(), myMap->height());
45
+}
46
+
47
+void MainWindow::drawPoints(GISPOI* gisLocations, unsigned int size) {
48
+    myMap->drawPoints(gisLocations, size);
49
+}
50
+
51
+void MainWindow::drawLine(const GISPOI &city01, const GISPOI &city02) {
52
+    myMap->drawLine(city01, city02);
53
+}
54
+
55
+MainWindow::~MainWindow()
56
+{
57
+    delete ui;
58
+    if (myMap != NULL) delete myMap;
59
+}
60
+

+ 29
- 0
mainwindow.h View File

@@ -0,0 +1,29 @@
1
+#ifndef MAINWINDOW_H
2
+#define MAINWINDOW_H
3
+
4
+#include <QMainWindow>
5
+#include <census.h>
6
+#include "map.h"
7
+namespace Ui {
8
+class MainWindow;
9
+}
10
+
11
+class MainWindow : public QMainWindow
12
+{
13
+    Q_OBJECT
14
+
15
+public:
16
+    explicit MainWindow(QWidget *parent = 0);
17
+    Map *myMap;
18
+    void drawPoints(GISPOI* gisLocations, unsigned int size);
19
+    void drawLine(const GISPOI &city01, const GISPOI &city02);
20
+    ~MainWindow();
21
+
22
+private:
23
+    Ui::MainWindow *ui;
24
+
25
+protected:
26
+    void paintEventOLD(QPaintEvent *event);
27
+};
28
+
29
+#endif // MAINWINDOW_H

+ 24
- 0
mainwindow.ui View File

@@ -0,0 +1,24 @@
1
+<ui version="4.0">
2
+ <class>MainWindow</class>
3
+ <widget class="QMainWindow" name="MainWindow" >
4
+  <property name="geometry" >
5
+   <rect>
6
+    <x>0</x>
7
+    <y>0</y>
8
+    <width>400</width>
9
+    <height>300</height>
10
+   </rect>
11
+  </property>
12
+  <property name="windowTitle" >
13
+   <string>MainWindow</string>
14
+  </property>
15
+  <widget class="QMenuBar" name="menuBar" />
16
+  <widget class="QToolBar" name="mainToolBar" />
17
+  <widget class="QWidget" name="centralWidget" />
18
+  <widget class="QStatusBar" name="statusBar" />
19
+ </widget>
20
+ <layoutDefault spacing="6" margin="11" />
21
+ <pixmapfunction></pixmapfunction>
22
+ <resources/>
23
+ <connections/>
24
+</ui>

+ 206
- 0
map.cpp View File

@@ -0,0 +1,206 @@
1
+#include "map.h"
2
+#include <QDebug>
3
+#include <QDesktopWidget>
4
+#include <QPainter>
5
+#include <QPen>
6
+
7
+Map::Map(QWidget *parent) :
8
+    QWidget(parent)
9
+{
10
+    srand(time(NULL));
11
+
12
+
13
+    myCountry = new Country;
14
+    myCountry->readInfoFromJSON("/Users/rarce/Dropbox/CCOM3033/2014S/qt/prMap/data/cityLimitsPR.json");
15
+
16
+    cityColorMap = NULL;
17
+    gisLocations = NULL;
18
+    drawRoutes = false;
19
+
20
+    qDebug() << "Computing limits...";
21
+    myCountry->limits();
22
+
23
+    QDesktopWidget widget;
24
+    QRect mainScreenSize = widget.availableGeometry(widget.primaryScreen());
25
+
26
+    double diffX = myCountry->maxX - myCountry->minX > 0 ? myCountry->maxX - myCountry->minX : myCountry->minX - myCountry->maxX;
27
+    double diffY = myCountry->maxY - myCountry->minY > 0 ? myCountry->maxY - myCountry->minY : myCountry->minY - myCountry->maxY;
28
+
29
+    if (diffX > diffY) resize(mainScreenSize.width() * 0.5 , 0.5 * mainScreenSize.width()*(diffY/diffX));
30
+    else               resize(mainScreenSize.width() * 0.5,  0.5 * mainScreenSize.width()*(diffX/diffY));
31
+}
32
+
33
+
34
+Map::~Map() {
35
+    if (myCountry    != NULL)    delete myCountry;
36
+    if (cityColorMap != NULL)    delete cityColorMap;
37
+    if (gisLocations != NULL)    delete [] gisLocations;
38
+}
39
+
40
+QPoint **qpA = new QPoint*[100];
41
+unsigned int qpASize = 0;
42
+
43
+void Map::paintEvent(QPaintEvent *event) {
44
+
45
+    // the QPainter is the 'canvas' to which we will draw
46
+    // the QPen is the pen that will be used to draw to the 'canvas'
47
+
48
+    this->setWindowTitle("PR Visualization");
49
+    QDesktopWidget widget;
50
+    QRect mainScreenSize = widget.availableGeometry(widget.primaryScreen());
51
+
52
+
53
+    if (qpASize == 0) {
54
+        //qDebug() << "creating the arrays " << qpArraySize;
55
+        for (int i = 0; i < 100; i++) {
56
+            qpA[i] = new QPoint[20000];
57
+        }
58
+    }
59
+
60
+    QPainter *p = new QPainter(this);
61
+    QPen myPen;
62
+
63
+    double factorX, factorY;
64
+
65
+    double diffX = myCountry->maxX - myCountry->minX > 0 ? myCountry->maxX - myCountry->minX : myCountry->minX - myCountry->maxX;
66
+    double diffY = myCountry->maxY - myCountry->minY > 0 ? myCountry->maxY - myCountry->minY : myCountry->minY - myCountry->maxY;
67
+
68
+    if (diffX > diffY) resize(mainScreenSize.width() * 0.5 , 0.5 * mainScreenSize.width()*(diffY/diffX));
69
+    else               resize(mainScreenSize.width() * 0.5,  0.5 * mainScreenSize.width()*(diffX/diffY));
70
+
71
+    factorX = this->width()  / diffX;
72
+    factorY = this->height() / diffY;
73
+
74
+    myPen.setWidth(1);
75
+    myPen.setColor(QColor(0x100000));
76
+    myPen.setBrush(QBrush(Qt::black));
77
+
78
+    p->setPen(myPen);
79
+
80
+    int colorCtr = 0;
81
+    QMap<QString,City*>::iterator it;
82
+    unsigned int randColor;
83
+    int cityCounter = 0;
84
+
85
+    for (it = myCountry->Cities.begin() ; it != myCountry->Cities.end(); ++it) {
86
+        City *c = it.value();
87
+
88
+        int x1 ,y1, x2, y2;
89
+        x1 = factorX * (c->getGeometry()->at(0).x - myCountry->minX);
90
+        y1 = height() - factorY*(c->getGeometry()->at(0).y - myCountry->minY)  ;
91
+
92
+        DoublePoint p1 = c->getGeometry()->at(0);
93
+        DoublePoint p2;
94
+        int ctr = 0;
95
+
96
+        QPoint *qp = qpA[cityCounter];
97
+        QPoint *qpBegin = qp;
98
+
99
+        // if no color map provided, we'll just color every city white.
100
+        randColor = 0xffffff;
101
+
102
+        if (cityColorMap)
103
+            randColor = (cityColorMap->find(it.key()) == cityColorMap->end()) ?
104
+                        0xffffff : (*cityColorMap)[it.key()];
105
+
106
+
107
+
108
+        for(int i = 0; i < c->getSize() + 1; i++) {
109
+            p2 = c->getGeometry()->at((i+1)%c->getSize());
110
+
111
+            x2 = factorX * (p2.x - myCountry->minX);
112
+            y2 = height() - factorY*(p2.y - myCountry->minY)  ;
113
+
114
+            if (p2.x != 0 && p1.x != 0) {
115
+                qp->setX(x2);
116
+                qp->setY(y2);
117
+                ctr++;
118
+                qp++;
119
+            }
120
+            else if (p2.x == 0) {
121
+                QPolygon yourPoly;
122
+                for (int i = 0; i < ctr; i++) yourPoly.push_back(qpBegin[i]);
123
+                QPainterPath tmpPath;
124
+                tmpPath.addPolygon(yourPoly);
125
+
126
+
127
+                    p->fillPath(tmpPath,QBrush(randColor));
128
+
129
+                p->drawPolygon(qpBegin,ctr);
130
+                ctr = 0;
131
+                qpBegin = qp;
132
+            }
133
+
134
+            x1 = x2;
135
+            y1 = y2;
136
+            p1 = p2;
137
+
138
+        }
139
+
140
+        QPolygon yourPoly;
141
+        for (int i = 0; i < ctr; i++) yourPoly.push_back(qpBegin[i]);
142
+        QPainterPath *tmpPath = new QPainterPath;
143
+        tmpPath->addPolygon(yourPoly);
144
+
145
+        p->fillPath(*tmpPath,QBrush(randColor));
146
+
147
+        p->drawPolygon(qpBegin,ctr,Qt::WindingFill);
148
+
149
+
150
+
151
+
152
+
153
+        delete tmpPath;
154
+        colorCtr++;
155
+        cityCounter++;
156
+    }
157
+    qpASize = cityCounter;
158
+
159
+
160
+    // Draw the city centers
161
+    int circleRadius = (this->height() > this->width()) ? this->width()/20 : this->height()/20 ;
162
+
163
+    int cX, cY, pX, pY;
164
+    cX = cY = pX = pY = -1;
165
+
166
+    qDebug() << "gisLocations:" << gisLocations << endl;
167
+
168
+    if(gisLocations) {
169
+        myPen.setWidth(2);
170
+        myPen.setColor(QColor(0x100000));
171
+        myPen.setBrush(QBrush(Qt::black));
172
+
173
+        p->setPen(myPen);
174
+        for (int i = 0; i < numLocations; i++) {
175
+            qDebug() << "name from locations:" << gisLocations[i].getName();
176
+
177
+            cX = factorX * (gisLocations[i].getLon() - myCountry->minX);
178
+            cY = height() - factorY*(gisLocations[i].getLat() - myCountry->minY);
179
+            p->setBrush(Qt::SolidPattern);
180
+            p->setBrush(QBrush(0xff0000));
181
+
182
+            p->drawEllipse(cX, cY, circleRadius, circleRadius);
183
+            p->setBrush(Qt::NoBrush);
184
+            if (drawRoutes && pX > 0) {
185
+                p->drawLine(pX+circleRadius/2,pY+circleRadius/2,cX+circleRadius/2,cY+circleRadius/2);
186
+            }
187
+            pX = cX; pY = cY;
188
+        }
189
+    }
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
+}
202
+
203
+
204
+void Map::drawLine(const GISPOI &city01, const GISPOI &city02) {
205
+    this->cityLines.push_back(QPair<const GISPOI *, const GISPOI *> (&city01, &city02));
206
+}

+ 40
- 0
map.h View File

@@ -0,0 +1,40 @@
1
+#ifndef MAP_H
2
+#define MAP_H
3
+
4
+#include <QWidget>
5
+#include <QMap>
6
+#include <QRgb>
7
+#include <census.h>
8
+#include <country.h>
9
+#include <gispoi.h>
10
+#include <QVector>
11
+#include <QPair>
12
+
13
+class Map : public QWidget
14
+{
15
+    Q_OBJECT
16
+public:
17
+    explicit Map(QWidget *parent = 0);
18
+    void setColorMap(QMap<QString,QRgb> *colorMap) {cityColorMap = colorMap;}
19
+    void drawPoints(GISPOI *v, unsigned int size) {gisLocations = v; numLocations = size;}
20
+    void setDrawRoutes(bool r) {drawRoutes = r;}
21
+    void drawLine(const GISPOI &city01, const GISPOI &city02);
22
+    ~Map();
23
+signals:
24
+
25
+private:
26
+    Country *myCountry;
27
+    QMap<QString,QRgb> *cityColorMap;
28
+    GISPOI *gisLocations;
29
+    QVector < QPair<const GISPOI *,const GISPOI *> > cityLines;
30
+    unsigned int numLocations;
31
+    bool drawRoutes;
32
+
33
+protected:
34
+    void paintEvent(QPaintEvent *event);
35
+
36
+public slots:
37
+
38
+};
39
+
40
+#endif // MAP_H

+ 32
- 0
prMap.pro View File

@@ -0,0 +1,32 @@
1
+#-------------------------------------------------
2
+#
3
+# Project created by QtCreator 2014-04-21T21:57:04
4
+#
5
+#-------------------------------------------------
6
+
7
+QT       += core gui
8
+
9
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
10
+
11
+TARGET = prMap
12
+TEMPLATE = app
13
+
14
+
15
+SOURCES += main.cpp\
16
+        mainwindow.cpp \
17
+    census.cpp \
18
+    city.cpp \
19
+    country.cpp \
20
+    doublepoint.cpp \
21
+    map.cpp \
22
+    gispoi.cpp
23
+
24
+HEADERS  += mainwindow.h \
25
+    census.h \
26
+    city.h \
27
+    country.h \
28
+    doublepoint.h \
29
+    map.h \
30
+    gispoi.h
31
+
32
+FORMS    += mainwindow.ui