Arrays help us to store and work with groups of data of the same type. The data is stored in consecutive memory spaces which can be accessed by using the name of the array and indexes or subscripts that indicate the position where the data is stored. Repetition structures provide us a simple way of accessing the data within an array.
An object is an entity that it is used in many programming languages to integrate the data and the code that operates on it, simplifying the modification of large programs. A common task in programming using C++ is working with arrays of objects. In today’s laboratory experience you will be working with georeferenced data of cities in Puerto Rico, where you will have attributes, such as name of the city, the latitude and longitude of its location, that you will use to illustrate properties in a map.
Dynamically create and manipulate an array of objects.
Code functions that process arrays of objects.
Practice passing arrays of objects as parameters in a function.
Practice the sequential reading of data from a file.
Use modular programming.
Use repetition and decision structures.
Before coming to the laboratory you should have:
Reviewed the concepts related to arrays of objects.
Reviewed the concepts related to functions that use arrays of objects.
Reviewed how to read data from a file.
Studied the concepts and instructions for the laboratory session.
Taken the Pre-Lab quiz that can be found in Moodle.
Working with arrays of objects is a very common task in programming with C++. Once you have read the object’s information from a file or as user input, you should use your algorithmic skills and knowledge of C++ to invoke the adequate methods and functions to process the data correctly.
In this laboratory experience, you 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 physical space. Typically this location are latitude and longitude coordinates. For example, the following is part of a file that contains georeferenced data for some Puerto Rican 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
Figure 1. Part of the content of a file with georeferenced data of cities in Puerto Rico; contains name of the city, coordinates for latitude and longitude.
To calculate the distance between two points in the Euclidean plane, you trace the straight line segment that joins the points and compute its length using the distance formula you studied in your Pre-Calculus course. To calculate the distance between two points in the surface of a sphere you don’t use the straight line segment that joins them, you use the shortest distance between these points measured over the sphere. This distance is called the orthodromic distance. To calculate the orthodromic distance between two points in the earth globe, the latitude and longitude coordinates are used.
GPOI
ClassThe most common way for C++ programmers to encapsulate data to an entity is by using classes. For example, in the case of the georeferenced data, a practical way to encapsulate the information about each city would be to implement a GeoreferencedPointOfInterest
class that contains at least data members (or attributes) 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 attributes.
In this laboratory experience, you are provided a GPOI
class with the following interface methods:
GISPOI()
: the default constructor
GISPOI(QString s, double latitude, double longitude)
: constructor that receives name, longitude and latitude.
double getLat()
, double getLon()
: getters for the latitude, 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
.
!INCLUDE “../../eip-diagnostic/PRMap/en/diag-prmap-01.html”
!INCLUDE “../../eip-diagnostic/PRMap/en/diag-prmap-02.html”
!INCLUDE “../../eip-diagnostic/PRMap/en/diag-prmap-03.html”
Load the prMap
project onto Qt by double clicking on the prMap.pro
filein the directory Documents/eip/Arrays-PRMap
of your computer. You may also go to http://bitbucket.org/eip-uprrp/objectsarrays-prmap
to download the ObjectsArrays-PRMap
folder to your computer.
Build and run the program. In its current state, the program simply displays a map of Puerto Rico. This map is provided so that you can visualize the results of your program. You may see some warnings which are due to the fact that some of the functions are incomplete. You will complete them throughout this laboratory experience.
Open the main.cpp
file. This is the file where you will be writing your code. This file contains the following functions:
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 process.
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.
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 you will implement.
void maxDistances(GISPOI A[], int size, int &idxCityA, int &idxCityB)
: Given A
, an array of cities, determines the farthest two cities. Remember that the distance you will calculate is the orthodromic distance. The function returns (by reference) the indices of these cities in the array. This is a function you will implement.
void minDistances(GISPOI A[], int size, int &idxCityA, int &idxCityB)
: Given A
, an array of cities, determines the closest two cities. Remember that the distance you will compute is the orthodromic distance. The function returns (by reference) the indices of these cities in the array. This is a function you will implement.
double cycleDistance(GISPOI A[], int size, int P[])
: Given an array of cities A
, the size of the array, and an array P
with a permutation of the integers in [0, size-1]
, computes and returns the distance to travel the cycle of cities A[P[0]]
$$\rightarrow$$ A[P[1]]
$$\rightarrow \cdots \rightarrow$$ A[P[size-1]]
. Remember that the distance you will calculate is the orthodromic distance.
For example, if the cities read from the file where Mayaguez, Ponce, Yauco and San Juan (in that order) and the permutation P
is $$(3, 1, 0, 2$$, 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 you will implement.
There are two additional functions that you need to know:
void MainWindow::drawLine(const GISPOI &city01, const GISPOI &city02)
: Given a reference to two GISPOI
objects, the function draws a line between them.
void drawPoints(GISPOI* gisLocations, unsigned int size);
: Given an array of GISPOI
objects and their size, displays their locations as points in the map.
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.
In the main()
function, add the necessary instructions to open the file that contains the georeferenced city information. The file that you will use first is pr10.txt
and it is 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 successfully opened for reading.
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.
Dynamically create an array as big as the number of lines in the file.
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.
In the main()
function invoke the readFileToArray
function, passing the reference to the file, the array you created in step 3, and its size.
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.
Invoke the method drawPoints(GISPOI* gisLocations, unsigned int size)
on the w
object so that a point will be shown in the map for each city: w.drawPoints(A, size)
(assuming that A
is the name of your array). You should obtain something similar to the next figure.
Once you have the information of georeferenced cities in the array of objects, you can start processing them in many interesting ways. We will start with some basic operations.
Read the documentation and implement the function void maxDistances(GISPOI A[], int size, int &idxCityA, int &idxCityB)
. Invoke the function from main()
.
Use the void drawLine(const GISPOI &city01, const GISPOI &city02)
method of the w
object to draw 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).
Read the documentation and implement the function void minDistances(GISPOI A[], int size, int &idxCityA, int &idxCityB)
. Invoke the function from main()
.
Use the void drawLine(const GISPOI &city01, const GISPOI &city02)
method of the w
object to draw a line connecting the two closest cities.
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:
pr.txt
file. Validate your results and wonder at your great achievement!Use “Deliverables” in Moodle to hand in the main.cpp
file. Remember to use good programming techniques, include the name of the programmers involved, and document your program.