using
convert(32, temperature, Fahrenheit, Celsius)
I get 0, the known freezing point of water in Celsius
using
convert(32, units, Fahrenheit, Celsius)
I get 160/9 approx. 17.778 Celcius
How does Maple get this answer 160/9
I tried this as well...
using
convert(100, temperature, Celsius, Fahrenheit)
I get 212
using
convert(100, units, Celsius, Fahrenheit)
I get 180
This is a "relative" versus "absolute" issue.
In absolute terms, 1 deg C is 33.8 deg F. That's on an absolute scale.
In other words, 1 deg C above the freezing point of water is the same temperature as 1.8 deg F above the freezing point of water. It's an absolute scale; eg. the fixed freezing point where they match at 0 deg C = 32 deg F.
And that leads to the well known relative scale, 1 deg C = 9/5 def F. That means that for every 1 deg C of increase, there is a 9/5 deg F increase. This is a relative scale; there's no fixed reference such as freezing or boiling points.
convert/temperature does the absolute scale temperature conversion.
convert/units does the relative scale "temperature increment" conversion.
Suppose I say to you, what's 10 deg C in Fahrenheit? In your head you might do it like so: Divide by 5 to get 2, multiply by 9 to get 18, and add 32 to get a final result of 50 deg F. You added the 32 deg F at the end, because this was an (absolute scale) temperature question. Now what if I subsequently asked a second question: what's 11 deg C in Fahrenheit? That's 1 deg C more than before. How many deg F do you need to add to the previous answer? It's certainly not 33.8 deg F more that you'd add to the earlier answer. No, you'll just take 1 deg C = 1.8 deg F, since this is an increment. And you'll get 50 deg F + 1.8 deg F = 51.8 deg F. That was a relative increment over the first answer.
Related
I would like to make a rotation using 4x4 matrix in Swift, but it has unexpected behavior: 200 degrees + 45 degrees = 115 degrees, and not 245
let degree200 = Angle(degrees: 200).radians
let degree45 = Angle(degrees: 45).radians
// 200 degrees + 45 degrees
let rotationMatrix = float4x4(simd_quatf(angle: Float(degree200+degree45), axis: SIMD3<Float>(0, 1, 0)))
// it prints 115 degree, and not 245
print(Angle(radians: Double(simd_quatf(rotationMatrix).angle)).degrees)
I assume that's a typo, and you in fact meant -115 degrees? (remainder(245, 360)) When using quaternions & Matrices to express orientations, you can only expect to see values of -180 to +180 degrees when converting those values back to Euler angles.
In general it is impossible to convert back to Euler angles from either a quaternion or matrix and get the original input values back. You either store the original Euler angles and present those to the user, or you will have to have a known starting Euler value and apply an Euler filter to obtain approximately correct results.
The only correct way to get your expected result is to NOT print the value after conversion to quats:
print((degree200 + degree45). degrees)
Well I know 115 and 245 are 360. Just a guess but maybe you're rotating the wrong way?? Maybe try negative values and see what happens.
I'm having trouble understanding what precisely the output of meshgrat means and how this relates to the lat and lon parameters of pcolorm(lat,lon,Z). I have a grid of global data, I'll call Z, at a 1.5 degree latitude x 1.5 degree longitude spatial resolution. Thus I have a matrix that's 120 x 240 (180 degrees of latitude / 1.5 = 120, 360 degrees of longitude / 1.5 = 240). Row 1 is 90 N and column 1 is 180 W (-180).
If I follow the MATLAB documentation, I can use meshgrat to produce the lat and lon arguments that I need to supply to pcolorm as follows.
latlim = [-90 90];
lonlim = [-180 180];
[lat,lon] = meshgrat(latlim,lonlim,[120 240]);
However, I don't understand why the spacing of the output is the way it is. For example, the first five values of lat are [-90.0000, -88.4874, -86.9748,-85.4622,-83.9496...]. The lon values follow the same spacing. The spacing is very close to 1.5 degrees, but it isn't. Why is there a discrepancy? The documentation claims that the paired lat and lon values are the location of the graticule vertices. In that case, these values make some sense, since there will always be one more vertex than actual grid cells. To test this, I made the following adjustment to the meshgrat code by adding one extra row and column:
latlim2 = [-90 90];
lonlim2 = [-180 180];
[lat2,lon2] = meshgrat(latlim2,lonlim2,[121 241]);
This did, indeed, produce the expected output, with the spacing now exactly at 1.5 degrees (i.e [-90.0000, -88.5000, -87.0000, -85.5000, -84.0000...]). Again, this is logical if these are viewed as vertices. But under this scenario lat and lon no longer match Z in size, which goes against how the documentation says to treat lat and lon in this case.
There seems to be a mismatch here: either the spacing in the lat lon grids are not accurate, or the girds are not the same size as the data, which would be fine in my mind as long as MATLAB knows how to interpret them accordingly, but the documentation does not seem to suggest using it this way. I have no detailed knowledge of how the MATLAB functions work at a finer level. Can someone explain to me what I'm missing?
Thus I have a matrix that's 120 x 240 (180 degrees of latitude / 1.5 = 120, 360 degrees of longitude / 1.5 = 240).
180/1.5 is indeed 120. But you also have an element at 0deg (presumably). That's 121.
i need to calculate some expression for all angles from 0 to 90 degrees increments 10 degrees (of cause expression depends on some trigonometrical function).
It looks like:
for alpha = 0:10:90
func(alpha) = c * sin(alpha)
end
Who know how to work with degrees, tell, please
It should be:
for 0:pi/18:pi/2
I know there are a load of other questions on this topic, I think I've read most of them, along with Wikipedia and a bunch of other articles but I am missing (I think) some simple arithmetic to complete my coordinate calculations.
I have this code:
typedef struct {
double startX;
double startY;
double x2;
double y2;
double length;
double angle;
double lastAngle;
} LINE;
void lineCalc(LINE *lp) {
double radians = lp->angle * 3.141592653589793/180.0;
lp->x2 = lp->startX + (lp->length * cos(radians));
lp->y2 = lp->startY + (lp->length * sin(radians));
fprintf (stderr, "lineCalc:startX:%2.3f, startY:%2.3f, length:%2.3g, angle:%2.3f, cos(%2.3f):%2.3f, x2:%2.3f, y2:%2.3f\n", lp->startX, lp->startY, lp->length, lp->angle, lp->angle, cos(radians), lp->x2, lp->y2);
}
int main() {
// Initialise to origin of 250, 250. 0, 0 for initial end point. Length 150, first angle 60 (degrees), l.lastAngle currently not used
LINE l = {250, 250, 0, 0, 150, 60, 0};
lineCalc(&l);
//drawLine(&l);
l.startX = x2; l.startY = y2; // make last end point, new start point. Angle stays at 60 degrees
lineCalc(&l);
//drawLine(&l);
l.startX = x2; l.startY = y2;
lineCalc(&l);
//drawLine(&l);
}
Which calculates the end point of a line given its start point, length and angle. All fine and good, but what I want to be able to do is to draw a shape, a triangle would be a start.
At the moment the code will make the calculation, draw the line (in reality it is generating SVG), make the last end point the next origin, recalculate, draw the next line etc...
The crucial bit that I am missing is how to get angle to be relative to the last line drawn. At the moment, the moving of the origin works fine, but the angle stays the same, thus three lines with angles of 60 degrees will just draw a straight line because the angle is relative to the start rather than relative to the last line.
Just in case it is relevant, with SVG horizontal is zero degrees. Thus a line 50 units long, starting at y100, x100 at an angle of 90 degrees will have an end point of y150, x100.
Could someone point out the obvious thing that I a missing to make the angles correct relative to the last line please?
If you take the angle at which the first line is drawn at as theta:
theta + 180 deg OR theta - 180 deg will face you back down the line you just drew.
Then theta + 180 deg + 60 OR theta - 180 deg + 60 will face you at 60 degrees to the first line.
You need to choose whether to + or - the 180 based on the range of degrees that svg uses (does it go -180 to 180 or 0 to 360) and how big your starting theta is. Also you need to choose + or - 60 degrees based on the side of the first line that you want to draw the second line.
Once you've calculated the angle you're drawing the second line at (theta + 180 + 60 for instance) then you need to take that as your next theta to calculate the angle for the third line.
There are two views:
viewA and viewB. Both are rotated.
The coordinate system for rotation is weird: It goes from 0 to 179,999999 or -179,99999 degrees. So essentially 179,99999 and -179,99999 are very close together!
I want to calculate how much degrees or radians are between these rotations.
For example:
viewA is rotated at 20 degrees
viewB is rotated at 30 degrees
I could just do: rotationB - rotationA = 10.
But the problem with this formula:
viewA is rotated at 179 degrees
viewB is rotated at -179 degrees
that would go wrong: rotationB - rotationA = -179 - 179 = -358
358 is plain wrong, because they are very close together in reality. So one thing I could do maybe is to check if the absolute result value is bigger than 180, and if so, calculate it the other way around to get the short true delta. But I feel this is plain wrong and bad, because of possible floating point errors and unprecision. So if two views are rotated essentially equally at 179,99999999999 degrees I might get a weird 180 or a 0 if I am lucky.
Maybe there's a genius-style math formular with PI, sine or other useful stuff to get around this problem?
EDIT: Original answer (with Mod) was wrong. would have given 180 - right answer in certain circumstances (angles 30 and -20 for example would give answer of 130, not correct answer of 50):
Two correct answers for all scenarios:
If A1 and A2 are two angles (between -179.99999 and 179.99999,
and Abs means take the Absolute Value,
The angular distance between them, is expressed by:
Angle between = 180 - Abs(Abs(A1 - A2) - 180)
Or, using C-style ternary operator:
Angle between = A1 < 180 + A2? A1 - A2: 360 + A1 - A2
Judging from the recent questions you've asked, you might want to read up on the unit circle. This is a fundamental concept in trigonometry, and it is how angles are calculated when doing rotations using CGAffineTransforms or CATransform3Ds.
Basically, the unit circle goes from 0 to 360 degrees, or 0 to 2 * pi (M_PI is the constant used on the iPhone) radians. Any angle greater than 360 degrees is the same as that angle minus a multiple of 360 degrees. For example, 740 degrees is the same as 380 degrees, which is the same as 20 degrees, when it comes to the ending position of something rotated by that much.
Likewise, negative degrees are the same as if you'd added a multiple of 360 degrees to them. -20 degrees is the same as 340 degrees.
There's no magic behind any of these calculations, you just have to pay attention to when something crosses the 0 / 360 degree point on the circle. In the case you describe, you can add 360 to any negative values to express them in positive angles. When subtracting angles, if the ending angle is less than the starting angle, you may also need to add 360 to the result to account for crossing the zero point on the unit circle.
Let's try this again:
There are two angles between A and B. One of them is
θ1 = A - B
The other is
θ2 = 360 - θ1
So just take the minimum of those two.
In addition to Brad Larson's excellent answer I would add that you can do:
CGFloat adjustAngle(angle) { return fmod(angle + 180.0, 360.0); }
...
CGFloat difference = fmod(adjustAngle(angle1) - adjustAngle(angle2), 360.0);
Take the difference, add 360, and mod by 360.