Homework 2: Plotting Example Data
In this step, you will use a Turtle
object to plot a small data set.
The resulting plot will be added to a rectangular patch by using your rect
function from the previous step.
Implementation Steps
Setup and Reading Input Data
You’ll be writing the code for this part in the function plotExampleData()
.
Constant Definitions
Your function should start by declaring the constants from the previous part as well as the following:
constexpr int PLOT_STEP = 1;
constexpr int NUM_DATA_POINTS = 59;
const string INPUT_NAME = "/home/student/data/hw2/us_population_growth.txt";
const string OUTPUT_NAME = "example_data.dst";
(where student
is replaced with your username).
If we have the same constants in two functions, isn't that duplicated code and bad style?
In principle, we can change the values of these constants to be different in the different functions. If, when you're done, you have a constant that is the same everywhere, you can make just one global constant outside of all the functions if you like. But mostly don't worry about it, as the benefit of named constants outweighs the duplication.
Hay! Why are the integer constants
constexpr
but the strings are justconst
? What's up with that?Full-blown C++
std::string
objects are complicated things, and creating one is something that can only be done when the program actually runs. Because it can't be figured out by the compiler ahead of time, it can't be a compile-time constant.There are alternatives to
std::string
that can be figured out at compile time, but we won't go down the rabbit hole of exploring them.
Declaring the Array
Then create a statically-sized array of float
s that is big enough to hold NUM_DATA_POINTS
values.
Reading the Values into the Array
We want to read NUM_DATA_POINTS
values from the file INPUT_NAME
into your array of floats.
The data set you will plot in this part of the assignment is a text file with one floating point value per line. The values represent 59 years of US population growth.
To read values from the text file, you will need to create an ifstream
(short for input file stream) object. You can use the parameterized constructor for the ifstream
class that takes one argument: a string representing the name of the file to read from. The syntax is
ifstream inputFile{"mytextfile.txt"};
Of course you should replace inputFile
and "mytextfile.txt"
with the variable name you prefer and the name of the file you want to read, respectively. Once you have your ifstream
object, the >>
operator will read one value at a time from the file. For example, if we have a float
called myFloat
, the following line would read the first float
from the file and store it in myFloat
:
inputFile >> myFloat;
Once you have read all of the values from the file, you should call the close
member function of your ifstream
object to let the system know that you are done reading from the file.
Normalizing by the Largest Value
When you plot the data, you’ll want it to be appropriately scaled when visualized in your patch. To accomplish this, you’ll normalize the data by its largest value. You’ll also be excluding the rectangular border for the patch from the available visualization space.
Find the Largest Value
You should implement a loop-based approach to finding the largest float
in your array.
Generate Normalized Data
Since the height of your patch is fixed, we want to make sure that all of the data points we plot will fit on the patch. To do that, we will normalize all of the values so that they fall between 0
and the largest available y
-axis value.
- First, calculate the
availableHeight
on the patch: thePATCH_HEIGHT
minus the size of the edge stitching,EDGE_STEP
. - Create a new statically sized array of
float
s to store the normalized data values. - Then scale each float in your array of data values so that it falls between
0
andavailableHeight
.
Plotting the Points
Now you’ll use the Turtle
to draw a border for the plot and plot the data.
Draw the Border
Create a Turtle
object and draw a satin-stitched rectangle that is PATCH_WIDTH
wide, PATCH_HEIGHT
tall, and has a step size of EDGE_STEP
. Be sure to use your rect
function!
Plot the Line
Next you’ll generate a line plot with the values from the normalized array of floats. To plot the data:
- First, calculate how much width is available for each data point, and store that number in a variable. You will use that value to calculate the
x
position for each point in your plot. The total available width for all the points isPATCH_WIDTH - EDGE_STEP
. - Get ready to plot: Lift the pen (so you can jump to the first plot point) and set the
Turtle
’s step size toPLOT_STEP
; satin stitch should still be on. - Loop through the values in your normalized array of floats. For each, have the turtle
gotopoint(x, y)
wherex
is calculated from the available width for each point andy
comes from the array of scaled floats. You’ll likely want the points to start at a slight offset to the right so as not to overlap the rectangle border. It may take some trial and error to get the line plot roughly centered inside the rectangle.
Note: Be sure that after the Turtle
goes to the location of the first data point, the pen is down. Otherwise, you won’t see any of the points you plot! Also, these directions assume the Turtle
’s position at the end of rect()
is the bottom left corner of the rectangle.
Annotate the Plot
We can add labels to interesting points in our plots. For this step, label the peak in the middle of the plot with the year it corresponds to, 1992
, by using gotopoint()
and choosing a point to write the text. Aim to have the beginning of the first 9
of 1992
aligned vertically with the middle peak; again, you'll have to do some experimentation. You can view our example patch below in the next step.
Save the Plot to a File
Save the resulting embroidery pattern to example_data.dst
. Then convert the pattern to example_data.svg
and confirm that it looks right. When you are done, your patch should look something like
Helpful Hints
What were those tips that were on the previous page? I think they still apply!
Don't Forget to Recompile (and Re-convert
!)
Remember that every time you change embroidery.cpp
, you need to recompile it, relink it, run ./homework2
again and regenerate the .svg
file with convert
before you can see the results. (If you fix a bug in the code and the output image doesn’t change, you probably forgot one of these steps.)
Pay Attention to Warnings (from clang++
and cpplint
)
We recommend that you fix compiler warnings immediately, rather than waiting until the end. Even if most warnings are about issues that don’t cause trouble in practice, sometimes warnings reflect very serious errors in your code!
Similarly, cpplint
is pretty picky about how you write your code, so your life will be better if you occasionally run it and correct the formatting as you go, rather than waiting until the end to fix dozens (or for larger programs, hundreds) of small annoying errors.
Visual Studio Code Is Sometimes Clueless
When working on C++ code, sometimes your editor, like VS Code, will try to “help” you. For this assignment, it may complain to you that it does not find turtle-related libraries on your system. This is OK, since VS Code does not really know what is on our server. When you compile on the server, it will definitely be able to find them.
Want to Look at the Provided Data?
The data is located on the server in /home/student/data/hw2/
(with student
replaced with your username). If you want to take a look at it to make sure you are correctly reading data, you can use the cat
command (short for ‘concatenate’). This command concatenates the contents of all the files specified in its arguments and dumps the result to the terminal. So, on the server command line you can try cat /home/student/data/hw2/us_population_growth.txt
Other Useful Unix Commands
Some other useful Unix commands, similar to cat
, for looking at files on the command line are
head
— view the first few lines of a filetail
— view the last few lines of a filemore
— view a file pausing at each screenful
Feel free to try them out to see what they do; for example, run
head /home/student/data/hw2/us_population_growth.txt
tail /home/student/data/hw2/us_population_growth.txt
more /home/student/data/hw2/us_population_growth.txt
Another very useful command is man
, which displays a “manual page” for the command you specify. So, for example, man man
would show you the manpage for man
itself, and man more
shows you the manpage for more
. Manpages show you what options and arguments a command takes, what they do, and sometimes include examples of how to use the command.
(When logged in, completion status appears here.)