# PR Map



### Objectives
Throughout this exercise the students will practice:

* reading a text file sequentially 
* repetition and control structures
* creating and manipulating an array of objects
* writing functions to process arrays of objects
* passing arrays of objects as parameters
* modular programming

### Concepts

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.

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:


```
Arroyo 17.9658 -66.0614
Bayamon 18.3833 -66.15
Caguas 18.2342 -66.0486
Dorado 18.4589 -66.2678
Fajardo 18.3258 -65.6525
```

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. 

### The GPOI class

In this lab, you are provided a **GPOI** class with the following interface:

* `GISPOI()`: the default constructor

* `GISPOI(QString s, double latitude, double longitude)`:  constructor that accepts name, longitude and latitude.

* `double getLat()`, `double getLon()`:  getters for the latutide, longitude.

* ` QString getName()`:  getter for the name.

* `void setAll(string s, double a, double b)`: setter for all the properties (at once)

* `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.


### Exercise 0 - Download and understand the code

1. Download _______.

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.

    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.

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.)

3. Open the `main.cpp` file. This is the file where you will be writing your code. This file contains the following functions:

    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.
    
    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. 

    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**

    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**

    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**

    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]]. 

        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.


        **THIS IS A FUNCTION THAT YOU WILL IMPLEMENT**

There is one additional function that you need to know:

1. `void MainWindow::drawLine(const GISPOI &city01, const GISPOI &city02)`: Given (a reference to) two GISPOI objects, paints a line between them.

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.

### Exercise 1 - read the georeferenced points into an array

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.

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.

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.

3. **Dynamically** create an array as big as the number of lines in the file.

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. 

1. In the main function invoke the `readFileToArray` function, passing the reference to the file, the array you created in step ???, and its size.

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. 

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. 

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. 

    ![](http://demo05.cloudimage.io/s/resize/400/i.imgur.com/7AneJpf.png) 



### Exercise 2 - the max and min functions

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.

1. Read the documentation and implement the function `void maxDistances(GISPOI A[], int size, int &idxCityA, int &idxCityB)`. Invoke the function from `main()`. 

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).

1. Read the documentation and implement the function `void minDistances(GISPOI A[], int size, int &idxCityA, int &idxCityB)`. Invoke the function from `main()`. 

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. 



### Exercise 3 - compute the cycle distance

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:

    1. First with $P = \left(0, 2, 4, 6, 8, 1, 3, 5, 7, 9\right)$
    2. Then with $P = \left(0, 3, 6, 9, 1, 4, 7, 2, 5, 8\right)$ 


### Exercise 4 - more fun

1. Change your code so that it now opens the `pr.txt` file.  Validate your results and wonder at your great achievement.

### Deliverables
