To calculate the cosine of an angle with code, use the built-in cosine function of C# see Figure 6-8: adjacent 12.28' Figure 6-8.. This code returns 35.0045438660122.The I]pd*=p]j$% func
Trang 1relation- 0.573576436351046 opposite / hypotenuse We now know that for any right triangle that has a
35-degree angle, the ratio of the opposite side to the hypotenuse will be 0.573576436351046
I know you’re waiting for me to explain how this helps us Let’s assume the hypotenuse of our triangle
is 15 feet long How long is the opposite side?
sine(35°) opposite / hypotenuse
In order to solve for the opposite side, we multiply both sides of this equation by the hypotenuse This effectively negates the hypotenuse in the right side of the equation (see Figure 6-7)
sine(35°) hypotenuse opposite / hypotenuse hypotenuse
0.573576436351046 hypotenuse opposite / hypotenuse hypotenuse
0.573576436351046 hypotenuse opposite
0.573576436351046 15 opposite
opposite 8.60'
Figure 6-7 The sine of our
angle multiplied by the length
of the hypotenuse gives us the length of the opposite side
So there you have it—we just used the sine function to figure out how long the opposite side of a
Trang 2Cosine (Cos)
The cosine function is the ratio of the angle’s adjacent side to the hypotenuse To calculate the cosine
of an angle with code, use the built-in cosine function of C# (see Figure 6-8):
adjacent 12.28'
Figure 6-8 The cosine of our
angle multiplied by the length
of the hypotenuse gives us the length of the adjacent side
You’re becoming a regular math whiz, aren’t you? You used trigonometry to calculate the lengths of two unknown sides on a right triangle! We can check our work by using yet another trigonometric function, called tangent
Trang 3Which gives us the result 0.70020753820971.
Let’s check our calculations by plugging some numbers into our ratio:
tangent opposite / adjacent
tangent 8.60 / 12.28
tangent 0.70032573289902
That’s pretty close! I’m willing to call it pretty accurate given that the final sine and cosine values wererounded off for readability
Arcsine (Asin) and arccosine (Acos)
Arcsine and arccosine are just like sine and cosine, only rather than feeding in an angle and getting back a ratio, you provide the ratio and get back an angle
Arcsine is utilized with the following code:
And the result that’s produced is (drum roll, please) 35 degrees!
To use arccosine, the C# code is the following:
I]pd*=_ko$N]pekEjN]`e]jo%7
If we plug in the ratio from the preceding cosine example and wrap it up in our N]`e]joPk@acnaao$%converter, it looks like this:
Trang 4This code returns 35.0045438660122.
The I]pd*=p]j$% function will return the arctangent of the number provided as a numeric value that is between –pi/2 and pi/2 radians, or in terms you can probably visualize a little more easily, –90 degrees to 90 degrees, as illustrated in Figure 6-9
Figure 6-9 The Math.Atan()
function returns values between
90 and –90 degrees
Looking at Figure 6-9 should leave you with a big question How are you supposed to rotate objects all the way around if the tangent function only provides a set of values that covers 180 degrees? The simple answer is to use I]pd*=p]j.$u(t% to do the calculations
I]pd*=p]j.$u( t% takes two arguments: the measurement of the opposite side and the ment of the adjacent side Notice the specific order of the arguments being passed—the opposite side comes first If we insert the values we calculated earlier, and wrap the =p]j.$% function in our N]`e]joPk@acnaao$% converter method, it looks like this:
measure-N]`e]joPk@acnaao$I]pd*=p]j.$,*13/1320/2/1-,02(,*4-5-1.,00.4455.%%7
And the result we get is 35
=p]j$% also returned a result of 35 when the tangent of our triangle was input So what’s the ence between =p]j$% and =p]j.$%? =p]j.$% returns angles as numeric values between –pi and pi radi-ans, or –180 to 180 degrees Figure 6-10 should help you visualize the rotation a little more clearly
Trang 5differ-Figure 6-10 Math.Atan2(y, x) returns angles from –pi to pi.
Now, we have access to a full range of 360-degree rotation! Since Silverlight will allow you to rotate
to either a positive or negative value, the value returned from the =p]j.$% function can be converted
to degrees and applied to an object
Converting between degrees and radians
Let’s code up a couple of examples to take a look at a few of the concepts we’ve covered so far We’ll begin with a project that will start getting you used to the idea of converting between radians and degrees
1. Open the DegreeRadianRotation project to code along The project contains two circles, each
with a radius of 100 pixels, as well as a couple of TextBlock labels so we can place some back on the screen
feed-2. Start in the I]ejL]ca*t]ih*_o file by creating the @acnaaoPkN]`e]jo$% and N]`e]joPk@acnaao$%functions:
Trang 63. We will need to track two angles and two rotation speeds—one expressed as degrees and the other as radians To position the radius correctly, two Lkejp variables are created to store the center of our circle elements Add the following set of variables just before the I]ejL]ca$%constructor Notice that the N]`e]jOlaa` variable, which will be used to calculate the radian-based rotation, is 01745 This is the equivalent of 1 degree.
2 pixels wide The first one has a blue color applied, and the second is colored red Once the strokes have been defined, the lines are added to the canvas
Trang 75. Immediately following that code, we’ll add some code to initialize our variables with the center values of each circle Remember that a line is defined by two pairs of points A circle’s radius goes from the center of the circle to some point along the circle’s edge Since we have not yet calculated the location of our radius lines, we’ll hide them by setting the start and finish x loca-tions to the center x point, and both the start and finish y locations to the center y point
8. The following code acts to reset our angle If the angle is 360, the endpoint of the line is drawn according to the calculation shown—this draws the line at the correct location (359 degrees) before the angle is actually incremented to 360 degrees The angle is then reset to 0 degrees, effectively skipping 360
The x location of the line coordinate pair is calculated based on the cosine of the angle passed, and the y location is calculated based on the sine function Add this code inside the ikraPeian[?kilhapa`$% event handler function:
++qoao`acnaao
eb$Oej=jcha99/2,%
Trang 810. Type in the following code right after the closing curly brace of the ahoa clause Notice that this works exactly the same, except that the calculations are not converting the angle to radi-ans first Since the angle is already expressed in radian values, there is no reason to convert Radians have a tendency to be a little lengthy on the screen, so the output is formatted to display only two decimal places, though the actual number is not changed The final step is to increment the angle being used for the radius using radians by the N]`e]jOlaa` variable.++qoaon]`e]jo
OejaN]`eqo.*T.9?en_ha.?ajpan*T
'I]pd*?ko$Oej=jcha.%
&?en_ha*Se`pd+.7
Trang 9Figure 6-11 One or both of the radii can be made to rotate counterclockwise.
To change the radian-based radius, simply change the code that increments the angle so that it ments the angle instead:
decre-Oej=jcha.)9N]`e]jOlaa`7
Trang 10To change the degree-based radius, it is necessary to change the code that increments the angle, as well as the conditional eb statement that checks to see if the end value has been reached:
The final code for this project is in the DegreeRadianRotationCompleted project
As you can see from the example, working with an angle as a degree value or a radian value will give the same results, but sticking to radians keeps the code a little cleaner and more straightforward, since
no conversions are taking place This example was fairly basic—you can probably imagine that a plex application with a lot of conversions could get a little tricky to keep track of This is why it’s best
com-to stick with radians in the code as much as possible, as we will be doing moving forward
How does this relate to work you’ve done in Silverlight?
So you’re sitting there looking at all the trigonometry and related functions and wondering how in the world right triangles and circles have anything to do with anything you’ve done in Silverlight Let’s take
an example vector like the one shown in Figure 6-12
Looks familiar, right? A vector is the radius of a circle when it comes to doing calculations, and the start point of a vector (or more accurately, the coordinates of an object traveling along the vector) is the origin Figure 6-13 shows the same vector with a circle drawn for reference
If we drop a line from the endpoint of the vector to the y coordinate
of the vector’s start, and continue that line back to the origin of the
Figure 6-12 An example vector
Trang 11circle, we’ll have a right triangle like the one shown in Figure 6-14 All of a sudden, we can use what we’ve learned to figure out all kinds of useful information about the triangle.
Figure 6-13 A vector is the radius of a circle Figure 6-14 A vector forms a right triangle.
Think back to the spaceship example from Chapter 5 Our spaceship is traveling along a vector, and
we turn the spaceship and hit the thrust button Figure 6-15 shows the triangle and calculations that are used in this case
Figure 6-15 A vector with the spaceship and
trigonometric functions overlaid
Trang 12If I now throw the following code at you, you’ll probably have a much better understanding of what
is happening Angle q is converted to radians, and then the ?ko$% and Oej$% functions are used to determine the acceleration along the x and y axes:
Trang 13reus-3. Since we’re creating a handle that will be used to rotate an object, we’ll need a flag to mine if the mouse has been captured
deter-We’re also going to use three Lkejp variables The first, IkqoaLkoepekj, is used to get the rent mouse position The next, H]opLkoepekj, is used to store the last position of the mouse pointer The last, ?]jr]o?ajpan, is a public variable that will be assigned a value when the object is instantiated and is used to provide easy access to the center coordinate of the canvas container
cur-The final three variables we need are all of type `kq^ha We will be storing a ?qnnajp=jchacalculation, a H]op=jcha calculation, and the difference between the two as =jcha@ahp]
The code for all of the variables is shown in the following listing This code should be added before the I]ejL]ca$% constructor
5. Inside the event handler function for the IkqoaHabp>qppkj@ksj event, add the code shown
in the following listing This code should look somewhat familiar to you We are creating a Bn]iaskngAhaiajp object named Epai, on which the mouse is captured The cursor is changed
to a hand, our Boolean flag that is used to keep track of a drag operation is set to pnqa, and theH]opLkoepekj variable is initialized with the current position of the mouse
Trang 146. The code for the IkqoaHabp>qppkjQl event handler function is used to once again create a Bn]iaskngAhaiajp object named Epai, from which the mouse capture is released The Boolean flag is changed to b]hoa, indicating that the mouse is no longer being captured, and the cursor for the item that was clicked is reset to the default.
D]j`ha*IkqoaIkra'9jasIkqoaArajpD]j`han$D]j`ha[IkqoaIkra%7
9. Inside the event handler function for IkqoaIkra, we’ll do the work of figuring out how much the image should be rotated based on the current location of the mouse pointer The first thing the event handler does is get the current position of the mouse and store it in the IkqoaLkoepekj variable
Then, if the mouse is being dragged, H]op=jcha is calculated by passing the coordinates that result when the center coordinates of the canvas being rotated are subtracted from the last pointer position to the =p]j.$% method Notice that they are passed y and then x
Next, ?qnnajp=jcha is calculated using the same method, but by subtracting the canvas center position from the current mouse position
The difference between the two angles is determined, and the Rotate transform angle of the Canvas object is incremented by the difference after it’s converted to degrees
TheH]opLkoepekj variable is then updated to the current mouse position for the next time the mouse moves
Trang 15TheOuopai*Sej`kso*Ia`e]*Ei]cejc library makes it possible for us to work with bitmaps
11. Before the I]ejL]ca$% constructor, create a new instance of the Nkp]paEpai object called Le_pqna-
lner]paNkp]paEpaiLe_pqna-9jasNkp]paEpai$%7
12. Inside the I]ejL]ca$% constructor, assign the source of the Le_pqna- object’s Image element,
as shown in the following code listing I’ve already added two sample JPGs to the project for you to work with The code tells Silverlight where the I]neckh`*flc image is relative to the application
Thehabp and pkl properties of the Le_pqna- object are then set to 100 to position it near the top-left corner of the root canvas Next, the public ?]jr]o?ajpan property for the object is assigned a value The angle of the object is preset to –15 degrees so it looks interesting when
it loads, and the object is added to the H]ukqpNkkp Canvas
Trang 16Figure 6-16 The ImageRotate project creates images with rotate handles.
When the program runs, the code that does the rotation is essentially saying “Here are the coordinates
of the mouse Draw a line from the center of the canvas to these coordinates, calculate the angle that forms, and then calculate the angle difference between this angle and the last angle.” This code runs constantly as the mouse moves, calculating the angle offsets in real time In the application, the movements can be very small, but Figure 6-17 shows larger-scale movement to illustrate the code functionality
Trang 17Figure 6-17 As the mouse is dragged, the code constantly calculates the new angle based on the distance from
the center of the canvas to the mouse position
Since the Nkp]paEpai user control is completely self-contained, it takes about a minute to add another instance of the object You can add the following code to get a second image in the application
13. Start by declaring a second object, named Le_pqna.:
lner]paNkp]paEpaiLe_pqna.9jasNkp]paEpai$%7
14. Next, set the initial properties for the new object as per the following code listing Be sure to reference the new object (Le_pqna.) when setting the ?]jr]o?ajpan property, or the rotation will give unexpected results
Trang 18If you compile and run the project at this point, you’ll see both of the images drawn, and each can be rotated independently If you’d like to use your own images, add them to the project by right-clicking the project name in Visual Studio’s Solution Explorer and selecting Add¢New Item from the menu, as shown in Figure 6-18 They will then be available for use in the same way as the original two The code
shown in this example is available in the ImageRotateCompleted project.
Figure 6-18 Right-click the project in Solution
Explorer, and select Add¢ New Item to add your own images to the project