Terrain Analysis
Background
Aircraft frequently rely on terrain elevation data to help navigate in low visibility conditions, to
reduce pilot workload, to help closely follow terrain at low altitude to avoid radar detection
(sometimes called ground-hugging or terrain-following flight), and to plot a course to avoid
extreme sudden altitude changes (e.g., flying around a mountain, rather than over it). Terrain
elevation data is gathered through terrain-following radar, lidar, satellites, and existing terrain
map
elevation information. Elevation data is especially useful radar or communication services are
not operating.
Elevation data is typically broken down into a grid, where each grid cell represents a square
physical area of uniform size. Because elevation varies
within a cell, the highest elevation in the cell is usually used as the elevation value for that cell
on the grid.
To navigate using elevation data, it’s useful to compute locations of peaks (high points), valleys
(low points), and flat areas (which might be at high or low elevations). To
a specific location is a peak, we\'re interested in discovering whether that
location is a local maximum. To do this, we must examine its eight adjacent locations: left, right,
above, below, and the four diagonal neighbors. If the location we’re analyzing has a higher
elevation than all eight surrounding locations, then the location is clearly a peak. We might
choose to loosen our definition of a peak by saying, for example, that a location is a peak if more
than five of the eight surrounding locations have a lower elevation.
Similarly, to decide if a location is a valley, we determine if it\'s a local minimum by checking to
see if all eight neighboring locations are higher than the location we’re analyzing. If all eight are
higher, we clearly have a valley. Again, we might choose to loosen our valley definition to
identify a valley if more than five surrounding locations are higher than the location we’re
analyzing.
Determining if a location is part of a relatively flat area (a plain for our purposes, but it might
also be a plateau in the real world), we would again examine all eight neighboring locations. If
they are all within a small tolerance in elevation, then we would declare the location to be part of
a plain. Once again, we might choose to loosen our definition of a plain, so that a location
surrounded by more than five locations that have a similar elevation is considered a plain.
Your Assignment
You will develop a C program that creates a two-dimensional array of doubles representing an
elevation grid, populates the array it with elevation data read from an instructor-supplied binary
data file, displays the elevation data numerically, analyzes the data in the array to find the peaks,
valleys, and plains, and displays strings indicating where these peaks, valleys, and plains are.
Terrain elevation values are all assumed to be expressed in meters.
When defining your C functions in this pr.
Terrain AnalysisBackgroundAircraft frequently rely on terrain el.pdf
1. Terrain Analysis
Background
Aircraft frequently rely on terrain elevation data to help navigate in low visibility conditions, to
reduce pilot workload, to help closely follow terrain at low altitude to avoid radar detection
(sometimes called ground-hugging or terrain-following flight), and to plot a course to avoid
extreme sudden altitude changes (e.g., flying around a mountain, rather than over it). Terrain
elevation data is gathered through terrain-following radar, lidar, satellites, and existing terrain
map
elevation information. Elevation data is especially useful radar or communication services are
not operating.
Elevation data is typically broken down into a grid, where each grid cell represents a square
physical area of uniform size. Because elevation varies
within a cell, the highest elevation in the cell is usually used as the elevation value for that cell
on the grid.
To navigate using elevation data, it’s useful to compute locations of peaks (high points), valleys
(low points), and flat areas (which might be at high or low elevations). To
a specific location is a peak, we're interested in discovering whether that
location is a local maximum. To do this, we must examine its eight adjacent locations: left, right,
above, below, and the four diagonal neighbors. If the location we’re analyzing has a higher
elevation than all eight surrounding locations, then the location is clearly a peak. We might
choose to loosen our definition of a peak by saying, for example, that a location is a peak if more
than five of the eight surrounding locations have a lower elevation.
Similarly, to decide if a location is a valley, we determine if it's a local minimum by checking to
see if all eight neighboring locations are higher than the location we’re analyzing. If all eight are
higher, we clearly have a valley. Again, we might choose to loosen our valley definition to
identify a valley if more than five surrounding locations are higher than the location we’re
analyzing.
Determining if a location is part of a relatively flat area (a plain for our purposes, but it might
also be a plateau in the real world), we would again examine all eight neighboring locations. If
they are all within a small tolerance in elevation, then we would declare the location to be part of
a plain. Once again, we might choose to loosen our definition of a plain, so that a location
surrounded by more than five locations that have a similar elevation is considered a plain.
Your Assignment
You will develop a C program that creates a two-dimensional array of doubles representing an
elevation grid, populates the array it with elevation data read from an instructor-supplied binary
2. data file, displays the elevation data numerically, analyzes the data in the array to find the peaks,
valleys, and plains, and displays strings indicating where these peaks, valleys, and plains are.
Terrain elevation values are all assumed to be expressed in meters.
When defining your C functions in this program, you may either define the functions before they
are used by any other functions, or place function prototypes near the top of your code (after all
#include directives), and then define the functions in any order.
Part 1 – Creating and Populating the Elevation Array
Create a new Visual Studio Win32 Console project named terrainmap. Create a new C source
file named project6.c within that project. At the top of the source file, #define
_CRT_SECURE_NO_WARNINGS, and then #include stdio.h and math.h.
Define your main function as usual. Inside the main function, define a local two-dimensional
array of doubles, with 20 rows and 10 columns, initializing it to contain all 0.0 elevation values.
Initialize the array using the initialization list { 0.0 } as discussed in class.
Define two local unsigned integer variables in main, one for the total number of rows, and one
for the total number of columns. Initialize these two variables as follows (where myArray must
be replaced by the actual name of your array of doubles):
Your rows variable must be set to sizeof(myArray) / sizeof(myArray[0]). This is the size of the
array divided by the size of the first column, which yields the number of rows in the array.
Your columns variable must be set to sizeof(myArray[0]) / sizeof(myArray[0][0]). This is the
size of one row of the array divided by the size of one element of the array, which yields the
number of columns in the array.
Add the const keyword to the beginning of these two unsigned integer variable definitions, to
prevent them from being accidentally changed later on. Use these variables in your main
function whenever you need to specify the number of rows or columns in the array, or when you
need to compute the total number of elements in the array (rows times columns).
The data file that you will use to populate this array is a binary file, not a human-readable text
file. Download and extract the instructor-supplied data file for this project and place it into a
known location on your computer or flash drive. Take note of the exact path name of this data
file, including the drive letter, folder(s), and file name. Note that this data file ends with a .RFD
extension, which may or may not appear in your File Explorer, depending on the configuration
of your system.
Still inside the main function, define a FILE pointer variable. Then open the instructor-supplied
data file for reading in binary mode by calling the fopen function, storing the result of fopen into
your FILE pointer variable. When specifying the full path name string in the first parameter to
fopen, don't forget to specify the drive letter, to double each backslash in the path name, and to
specify the .RFD extension.
3. Using an if statement, check to see if the file failed to open. If the FILE pointer returned by
fopen was NULL, display an appropriate error message and return -1 from main.
Otherwise, if the file opened successfully, make just ONE call to the fread function, to read all
the data from the file directly into your array of doubles. You will need to store the result of the
fread call into a local unsigned integer variable, which will be the number of doubles
successfully read from the file.
Pass the following parameters into the fread function:
The address (i.e., the name) of your two-dimensional array, which you defined earlier.
The size of one element of the array (i.e. the number of bytes occupied by one array element).
The total number of elements in the array (number of rows times number of columns).
The FILE pointer you got back from the call to fopen earlier.
Note: The values in the input file are stored in row-major order, the same order in which values
in a C two-dimensional array are stored in memory. This is why it's possible to read the entire
array of values using only a single call to fread. If the values were stored in a different order in
the input file, this approach would not work.
Using an if statement, check to see if the number of doubles successfully read from the file is not
equal to the total number of elements in your array (rows times columns). If the correct number
of elements was not read, print an appropriate error message, close the file using fclose (passing
in the FILE pointer you received from fopen), and return -1 from main.
Part 2 – Displaying Elevation Data
Define a separate C function named PrintMapElevations, which has the following function
prototype:
void PrintMapElevations(const double terrain[][10], const unsigned rows, const unsigned cols);
The goal of this function is to print out the contents of the two-dimensional array. Once inside
this function definition, you will refer to the array by this function's parameter name, terrain.
The function must behave as follows:
Print the heading as shown in the sample output below. Be sure to get the numeric information in
the heading from the rows and cols parameters that were passed into this function.
Start a for loop that runs through all the rows of the array (starting at index 0). This outer loop
will need its own loop variable. Inside the outer loop:
o Start a nested for loop that runs through all the columns (starting at index 0). This inner loop
will need its own loop variable. Inside the inner loop:
There should only be one line of code inside the inner loop, to print one value from the array.
Use a %7.1f format, and be sure to print a newline at the end of each row of data. You may use
array notation or pointer arithmetic to access the array element here.
After the end of the inner loop, print a newline to ensure that the next row will appear on a new
4. line of output.
Print another newline after the end of the outer loop.
In the main function, add a call to the PrintMapElevations function, passing in the address of (the
name of) your two-dimensional array, and the number of rows and number of columns (the local
const integer variables you defined and initialized earlier). Now, build and test your program so
far. Here is the sample output you should see, assuming you are using the instructor-supplied
data file:
Map Elevations (20 x 10):
299.3 332.2 481.1 595.6 622.1 742.9 845.4 1222.1 948.2 1112.3
334.9 335.2 336.1 582.5 793.4 985.5 1342.3 1188.2 1242.1
335.1 336.7 334.8 488.1 694.2 1111.9 1499.5 1542.1 1412.4
336.2 337.3 335.3 524.2 849.9 1341.7 1412.8 1501.7 1398.6
336.2 336.2 336.2 421.1 906.2 1341.6 1341.5 1342.1 1342.5
336.2 336.2 337.9 589.3 984.5 999.9 1298.2 1341.2 1343.1
336.2 336.2 662.2 799.9 1001.2 978.2 1026.4 1342.8 1342.3
337.1 336.5 493.9 1106.4 1307.7 1287.1 989.1 1222.3 1341.1
338.3 985.9 722.6 2049.3 1583.5 1392.9 876.2 1005.4 1298.6
339.4 2166.6 3999.2 3721.1 2684.1 2084.2 1008.3 722.8 1241.3
488.5 3874.3 4033.2 3997.1 3042.6 1788.4 1186.2 865.9 881.1
921.1
891.5
2998.5
4392.2
3721.4
3548.7
1598.2
1243.6
998.3
722.5
1242.7
1563.8
2925.8
2884.7
3121.6
2766.3
1488.7
7. 229.1
Verify that your program is working correctly before proceeding to the next part.
Part 3 – Detecting and Displaying Elevation Features
Define a separate C function named PrintMapFeatures, which has the following function
prototype:
void PrintMapFeatures(const double terrain[][10], const unsigned rows, const unsigned cols);
The goal of this function is to analyze elements of the two-dimensional array and display
information indicating areas of peaks, valleys, and plains. Once inside this function definition,
you will refer to the array by this function's parameter name, terrain. This function must display
an elevation map, but instead of displaying elevation values, it must display one of the following
strings for each element of the array:
??????? (7 question mark characters), if the element is in the first row, first column, last row, or
last column of the array (i.e., an edge).
^^^^^^^ (7 carat characters), if the element is considered a peak.
vvvvvvv (7 lowercase v characters), if the location is considered a valley. _______ (7 underscore
characters), if the location is considered a plain.
....... (7 period characters), if the location is none of the above (i.e., unknown).
The function must behave as follows. (You may use array notation or pointer arithmetic to access
array elements.)
Print the heading as shown in the sample output below. Be sure to get the numeric information in
the heading from the rows and cols parameters that were passed into this function.
Start a for loop that runs through all the rows of the array (starting at index 0). This outer loop
will need its own loop variable. Inside the outer loop:
o Start a nested for loop that runs through all the columns (starting at index 0). This inner loop
will need its own loop variable. Inside the inner loop:
If the row is either the first row or last row, or the column is either the first column or last
column, print the edge indicator discussed earlier.
Otherwise, examine each of the neighboring elevations as follows.
Define three new integer variables: peakCount, valleyCount, and plainCount, and set them all to
0.
Start a for loop that runs from the current row – 1 to the current row + 1. This loop will need its
own loop variable. Inside this loop:
o Start a nested for loop that runs from the current column – 1 to the current column + 1. This
loop will need its own loop variable. Inside this loop, use three independent if statements:
If the center elevation is greater than the neighboring elevation, increment peakCount.
If the center elevation is less than the neighboring elevation, increment valleyCount.
8. If the center elevation is within 4.5 meters (higher or lower) of the neighboring elevation,
increment plainCount. (You can use the abs function, absolute value, to simplify this conditional
test.)
After both of these loops have completed, subtract 1 from the plainCount, so that the center
element is not part of the count.
Use an if-else-if ladder to do the following:
If more than 5 of the 8 surrounding elements have a lower elevation, print the peak indicator
discussed earlier.
Otherwise, if more than 5 of the 8 surrounding elements have a higher elevation, print the valley
indicator discussed earlier.
o Otherwise, if plainCount is greater than 5, print the plain indicator discussed earlier.
o Otherwise, print the unknown indicator discussed earlier.
After the end of the inner loop, print a newline to ensure that the next row will appear on a new
line of output.
Print another newline after the end of the outer loop.
In your main function, add a call to PrintMapFeatures, after all the other calls already present in
the main function. Pass in the address of (name of) your two-dimensional array, and the number
of rows and number of columns.
Here is an example of the output of PrintMapFeatures:
Map Features (20 x 10):
??????????????????????????????????????????????????????????????????????
???????vvvvvvv_______vvvvvvv
.....................
^^^^^^^vvvvvvv???????
???????vvvvvvv^^^^^^^vvvvvvv
.....................
^^^^^^^^^^^^^^???????
???????_______^^^^^^^vvvvvvv
..............
^^^^^^^.......
^^^^^^^???????
???????______________.....................
^^^^^^^..............
???????
???????______________...................................
vvvvvvv???????