Skip to main content

Section 4.14 Case Study: Point Rotation

Subsection 4.14.1 The problem

When drawing graphics, computers generally work with polygons defined by points. To draw an object as if it is far away, or rotated, the computer can transform the points before drawing the shape. We want to do a simple version of transforming a point. Given the point A at (2, 4), we would like to write a program that says where that point ends up if it is rotated by a certain number of degrees (\(ΞΈ\) - pronounced β€œtheta”) around the origin (0, 0).
The figure below illustrates what we are trying to do. Use the slider to change \(ΞΈ\text{,}\) and it will show you the new location of A as A’.
Figure 4.14.1. Rotation of the point \(A (2, 4)\text{.}\) Drag the \(ΞΈ\) slider to see the point rotate around the origin.

Subsection 4.14.2 Making a Plan

Let us start with the same questions as last time:
β€œWhat data you will start with?”
a number of degrees
β€œWhat values you want to calculate?”
x and y position after (2, 4) is rotated
β€œHow will you calculate those values?”
Some searching revealed these formulas:
\begin{gather*} x' = x * cos(ΞΈ) - y * sin(ΞΈ)\\ y' = x * sin(ΞΈ) + y * cos(ΞΈ) \end{gather*}
Before we start writing code, we should test these formulas. We can do that by hand. If we rotate the point (2, 4) by 90 degrees, I get (-4, 2). If we rotate it by 45 degrees, we should get (-1.41, 4.24). Those values seem to match what the animation shows. This confirms that we know how to do the math and will allow us to check the results of our code.

Subsection 4.14.3 Checking Our Tools

If we haven’t used a function like sin before, it makes sense to test it out and ensure that we know that it works correctly. So I am going to start with that. I will not worry about reading input yet, I will just hard code in a test value. Here is my first attempt:
Listing 4.14.2.
Although 45 could be stored into an int, there is no reason theta needs to be a whole number. So it makes sense to use a double as its type. And I can’t use the symbol, so I have spelled out its name.
When I run this program, I get sinValue: 0.850904. That does not look right. I expected to get approximately 0.707.
The sin function in C++ expects the angle to be in radians, not degrees. So I need to convert the degrees to radians before I can use the sin function. I can do that by multiplying the degrees by \(Ο€/180\text{.}\) Here is my next attempt:
Listing 4.14.3.
Note that since Ο€ should never change, I have made it a const double. And, as is convention for constants, I have named it using all uppercase. I have also renamed what used to be theta to thetaDegrees to clearly indicate what it stores and differentiate it from thetaRadians.
This version seems to work better. Now I feel confident about trying to solve the actual problem.

Subsection 4.14.4 Calculating x2

Now let’s try to calculate the new location of x. In the formula, it is written as \(x'\) (pronounced β€œx prime”) but we can’t use that symbol in a variable name, so we will call it x2. I also need to set some values for the original x and y.
Listing 4.14.4.
This seems to work, or at least the answer matches what I calculated by hand.

Checkpoint 4.14.1.

Subsection 4.14.5 Calculating y2

Now let’s add code to calculate y2. Add the following two lines to the program above (right after the lines that calculate x2) and then run it.
Listing 4.14.5.
double y2 = x * sinValue + y * cosValue;
cout << "y2: " << y2 << endl;

Checkpoint 4.14.2.

Subsection 4.14.6 Wrapping up

Now that we have the code working, we can add code to read in the value of theta from the user. Here is the final version of the program:
Listing 4.14.6.
We might also choose to condense the code a bit. We could avoid storing the variables sinValue and cosValue by calculating sin and cos of theta where they are needed like this:
Listing 4.14.7.
...
double thetaRadians = thetaDegrees * numbers::pi / 180;

double x = 2;
double y = 4;

double x2 = x * cos(thetaRadians) - y * sin(thetaRadians);
cout << "x2: " << x2 << endl;
double y2 = x * sin(thetaRadians) + y * cos(thetaRadians);
cout << "y2: " << y2 << endl;
However, I am choosing to leave them in place. Using the variables makes it easier to go back and check the values of those calculations if I realize there is a bug. It also avoids redoing the work of calculating sin and cos of theta.

Note 4.14.1.

Again, we have worked on this program one piece at a time. This is the most effective way to write code. Write a bit, test what you have, and do not continue building on that until you are sure it is working.

Checkpoint 4.14.3.

You have attempted of activities on this page.