Difference between these 2 functions? - objective-c

I have 2 degree-to-radian functions pre-defined using #define:
Function 1:
#define degreesToRadians(degrees) (M_PI * degrees / 180.0)
Function 2:
#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
Only the 2nd function returns correct answer, while the first one provides weird answer. What are the differences between them?

Non of the two "functions" mentioned above is a functions, they are macros, and the first macro is not safe, for example, expanding the macro degreesToRadians(10 + 10) gives (M_PI * 10 + 10 / 180.0), which is interpreted as ((M_PI * 10) + (10 / 180.0)) and this is clearly wrong. While expanding DEGREES_TO_RADIANS(10 + 10) gives ((10 + 10 ) / 180.0 * M_PI) which is correct.
The other difference is that M_PI * degreess might overflow the double boundaries, and thus give a wrong answer (but this requires a rather high value in degrees)

The calculations are pretty much identical, notwithstanding floating point limitations. However, you have angle surrounded with parentheses in the second macro, which is the right thing to do.
In the first macro, if you do:
x = degreesToRadians(a + 45);
then, remembering that macros are simple text substitutions, you'll end up with:
x = (M_PI * a + 45 / 180.0);
which will not end well, since it will be calculated as if you'd written:
x = (M_PI * a) + (45 / 180.0);
In other words, you simply multiply the angle by PI and add a constant 0.25.
If instead you change the first one to be:
#define degreesToRadians(degrees) (M_PI * (degrees) / 180.0)
then it should begin to behave a little better.
The other difference has to do with either large or small values of the angle. A divide-then-multiply on a small angle (and I mean really small like 10-308, approaching the IEEE754 limits) may result in a zero result while a multiply-then-divide on a large angle (like 10308) may give you overflow.
My advice would be to ensure you use "normal" angles (or normalise them before conversion). Provided you do that, the different edge conditions of each method shouldn't matter.
And, in all honesty, you probably shouldn't even be using macros for this. With insanely optimising compilers and enumerations, macros should pretty much be relegated to conditional compilation nowadays. I'd simply rewrite it as a function along the lines of:
double degreesToRadians(double d) {
return M_PI * d / 180.0;
}
Or, you could even adjust the code so as to not worry about small or large angles (if you're paranoid):
double degreesToRadians(double d) {
if ((d > -1) && (d < 1))
return (M_PI * d) / 180.0;
return (d / 180.0) * M_PI;
}

Related

Calculating Collision Times Between Two Circles - Physics

I keep stumbling into game/simulation solutions for finding distance while time is running, and it's not what I'm looking for.
I'm looking for an O(1) formula to calculate the (0 or 1 or 2) clock time(s) in which two circles are exactly r1+r2 distance from each other. Negative time is possible. It's possible two circles don't collide, and they may not have an intersection (as in 2 cars "clipping" each other while driving too close to the middle of the road in opposite directions), which is messing up all my mx+b solutions.
Technically, a single point collision should be possible.
I'm about 100 lines of code deep, and I feel sure there must be a better way, and I'm not even sure whether my test cases are correct or not. My initial setup was:
dist( x1+dx1*t, y1+dy1*t, x2+dx2*t, y2+dy2*t ) == r1+r2
By assuming the distance at any time t could be calculated with Pythagoras, I would like to know the two points in time in which the distance from the centers is precisely the sum of the radii. I solved for a, b, and c and applied the quadratic formula, and I believe that if I'm assuming they were phantom objects, this would give me the first moment of collision and the final moment of collision, and I could assume at every moment between, they are overlapping.
I'm working under the precondition that it's impossible for 2 objects to be overlapping at t0, which means infinite collision of "stuck inside each other" is not possible. I'm also filtering out and using special handling for when the slope is 0 or infinite, which is working.
I tried calculating the distance when, at the moment object 1 is at the intersection point, it's distance from object 2, and likewise when o2 is at the intersection point, but this did not work as it's possible to have collision when they are not at their intersection.
I'm having problems for when the slopes are equal, but different magnitude.
Is there a simple physics/math formula for this already?
Programming language doesn't matter, pseudcode would be great, or any math formula that doesn't have complex symbols (I'm not a math/physics person)... but nothing higher order (I assume python probably has a collide(p1, p2) method already)
There is a simple(-ish) solution. You already mentioned using the quadratic formula which is a good start.
First define your problem where the quadratic formula can be useful, in this case, distance between to centers, over time.
Let's define our time as t
Because we are using two dimensions we can call our dimensions x & y
First let's define the two center points at t = 0 of our circles as a & b
Let's also define our velocity at t = 0 of a & b as u & v respectively.
Finally, assuming a constant acceleration of a & b as o & p respectively.
The equation for a position along any one dimension (which we'll call i) with respect to time t is as follows: i(t) = 1 / 2 * a * t^2 + v * t + i0; with a being constant acceleration, v being initial velocity, and i0 being initial position along dimension i.
We know the distance between two 2D points at any time t is the square root of ((a.x(t) - b.x(t))^2 + (a.y(t) - b.y(t))^2)
Using the formula of position along a dimensions we can substitute everything in the distance equation in terms of just t and the constants we defined earlier. For shorthand we will call the function d(t);
Finally using that equation, we will know that the t values where d(t) = a.radius + b.radius are where collision starts or ends.
To put this in terms of quadratic formula we move the radius to the left so we get d(t) - (a.radius + b.radius) = 0
We can then expand and simplify the resulting equation so everything is in terms of t and the constant values that we were given. Using that solve for both positive & negative values with the quadratic formula.
This will handle errors as well because if you get two objects that will never collide, you will get an undefined or imaginary number.
You should be able to translate the rest into code fairly easily. I'm running out of time atm and will write out a simple solution when I can.
Following up on #TinFoilPancakes answer and heavily using using WolframAlpha to simplify the formulae, I've come up with the following pseudocode, well C# code actually that I've commented somewhat:
The Ball class has the following properties:
public double X;
public double Y;
public double Xvel;
public double Yvel;
public double Radius;
The algorithm:
public double TimeToCollision(Ball other)
{
double distance = (Radius + other.Radius) * (Radius + other.Radius);
double a = (Xvel - other.Xvel) * (Xvel - other.Xvel) + (Yvel - other.Yvel) * (Yvel - other.Yvel);
double b = 2 * ((X - other.X) * (Xvel - other.Xvel) + (Y - other.Y) * (Yvel - other.Yvel));
double c = (X - other.X) * (X - other.X) + (Y - other.Y) * (Y - other.Y) - distance;
double d = b * b - 4 * a * c;
// Ignore glancing collisions that may not cause a response due to limited precision and lead to an infinite loop
if (b > -1e-6 || d <= 0)
return double.NaN;
double e = Math.Sqrt(d);
double t1 = (-b - e) / (2 * a); // Collison time, +ve or -ve
double t2 = (-b + e) / (2 * a); // Exit time, +ve or -ve
// b < 0 => Getting closer
// If we are overlapping and moving closer, collide now
if (t1 < 0 && t2 > 0 && b <= -1e-6)
return 0;
return t1;
}
The method will return the time that the Balls collide, which can be +ve, -ve or NaN, NaN means they won't or didn't collide.
Further points to note are, we can check the discriminant against <zero to bail out early which will be most of the time, and avoid the Sqrt. Also since I'm using this in a continuous collision detection system, I'm ignoring collisions (glancing) that will have little or no impact since it's possible the response to the collision won't change the velocities and lead to the same situation being checked infinitely, freezing the simulation.
The 'b' variable can used for this check since luckily it's similar to the dot product. If b is >-1e-6 ie. they're not moving closer fast enough we return NaN, ie. they don't collide. You can tweak this value to avoid freezes, smaller will allow closer glancing collisions but increase the chance of a freeze when they happen like when a bunch of circles are packed tightly together. Likewise to avoid Balls moving through each other we signal an immediate collison if they're already overlapping and moving closer.

Gps distance between two points

I am developing a Meter app (in android). I am calculating distance between two points by formula (in back ground)
double calculateDistancs(double lat1, double long1, double lat2,
double long2) {
double earthRadius = 6371000; // meters
double dLat = Math.toRadians(lat2 - lat1);
double dLng = Math.toRadians(long2 - long1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(Math.toRadians(lat1))
* Math.cos(Math.toRadians(lat2)) * Math.sin(dLng / 2)
* Math.sin(dLng / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
float dist = (float) (earthRadius * c);
return dist;
}
I am not getting same and accurate distance between my home to metro station .
Provide other approach if available in android.
So second option is use google api for getting rout distance bn two latlong but in this case it will hit api many times.I want t know which approach is best.
I am getting different latlong at same place, may some one please make me understand for this.
The problem most probably is not caused by the function you posted.
Probably you are summing up jumping gps locations.
Just summing up the distance from one location to the other is not sufficient, especially at low speeds, like walking speed.
However there are weak points in the formula:
float dist = (float) (earthRadius * c);
You are always using double, and then downgrade to the lower precision float, but return the double. This is makes no sense.
Fix that with:
double dist = earthRadius * c;

tan ( pi/2 ) in objective-c (math.h) not undefined

I wrote this test code:
NSLog(#"%g", tan(M_PI / 2.0));
and the output of the console is:
1.63312e+16
The issues is about approximation, right? Did I make some mistakes or the tan function of math.h really doesn't handle this case itself (returning me INFINITY) ? shall I handle theese input cases myself (example: when I get pi/2 input value I return an error message) or is there a better (more elegant) way to get the correct value ?
Thanks
Its because M_PI != real pi because it cannot be represented, so what you get from M_PI is approximation of pi, which its tangent is what you get.
Edit: the following:
printf("cos(M_PI / 2) = %.30f\nsin(M_PI / 2) = %.30f\n",
cos(M_PI / 2), sin(M_PI / 2));
will print
cos(M_PI / 2) = 0.000000000000000061232339957368
sin(M_PI / 2) = 1.000000000000000000000000000000
Which shows cos(pi / 2) is non-zero.
Doing the division will give
1.63312393531953E16
which is exactly what you get.

Objective C - Creating Angles From Current Time

I'm trying to write code to draw a clock on the screen of an iOS device. I need to get the angle of a line (seconds, minutes, hours hands of clock) from the current time. My code accurately grabs the time, but for some reason, all of the angles I receive end up being the same (no matter what time it is).
If it helps, the angle I am constantly receiving is:
-1.5707963267948966
Here is the code I use to get the angles:
secondsTheta = ((seconds/60) * (2 * M_PI)) - (M_PI / 2);
minutesTheta = ((minutes/60) + (seconds/3600)) * (2 * M_PI) - (M_PI / 2);
hoursTheta = ((hours/12) + (minutes/720) + (seconds/43200)) * (2 * M_PI) - (M_PI / 2);
My thought is that something is funky with M_PI, but I don't know what would be...but as I said, the seconds, minutes, and hours variables are correct. They are declared in my header file as ints, and I know that [NSDateComponents seconds](etc) returns an NSInteger, but I don't think that should matter for this basic math.
Since the seconds, minutes, and hours variables are declared as ints the division will not give you the correct values. An int divided by another init will result in an int, what is needed for the result is a float. In order to have the compiler use floating point arithmetic it is necessary that one of the operands be a floating point format number (float).
Example: 10 seconds divided by 60 (10/60) will use integer math and result in 0.
Example: 10.0 seconds divided by 60 (10/60) will use floating point math and result in 0.1.66666667.
Example:
secondsTheta = ((seconds/60.0) * (2 * M_PI)) - (M_PI / 2);
or
secondsTheta = (((float)seconds/60) * (2 * M_PI)) - (M_PI / 2);
Your seconds, minutes and hours are ints. Dividing ints by ints does integer arithmetic and truncates the values, so
seconds/60
will always give you 0. Objective C inherits this behavior from C and this is fairly common behavior among programming languages.

Fast formula for a "high contrast" curve

My inner loop contains a calculation that profiling shows to be problematic.
The idea is to take a greyscale pixel x (0 <= x <= 1), and "increase its contrast". My requirements are fairly loose, just the following:
for x < .5, 0 <= f(x) < x
for x > .5, x < f(x) <= 1
f(0) = 0
f(x) = 1 - f(1 - x), i.e. it should be "symmetric"
Preferably, the function should be smooth.
So the graph must look something like this:
.
I have two implementations (their results differ but both are conformant):
float cosContrastize(float i) {
return .5 - cos(x * pi) / 2;
}
float mulContrastize(float i) {
if (i < .5) return i * i * 2;
i = 1 - i;
return 1 - i * i * 2;
}
So I request either a microoptimization for one of these implementations, or an original, faster formula of your own.
Maybe one of you can even twiddle the bits ;)
Consider the following sigmoid-shaped functions (properly translated to the desired range):
error function
normal CDF
tanh
logit
I generated the above figure using MATLAB. If interested here's the code:
x = -3:.01:3;
plot( x, 2*(x>=0)-1, ...
x, erf(x), ...
x, tanh(x), ...
x, 2*normcdf(x)-1, ...
x, 2*(1 ./ (1 + exp(-x)))-1, ...
x, 2*((x-min(x))./range(x))-1 )
legend({'hard' 'erf' 'tanh' 'normcdf' 'logit' 'linear'})
Trivially you could simply threshold, but I imagine this is too dumb:
return i < 0.5 ? 0.0 : 1.0;
Since you mention 'increasing contrast' I assume the input values are luminance values. If so, and they are discrete (perhaps it's an 8-bit value), you could use a lookup table to do this quite quickly.
Your 'mulContrastize' looks reasonably quick. One optimization would be to use integer math. Let's say, again, your input values could actually be passed as an 8-bit unsigned value in [0..255]. (Again, possibly a fine assumption?) You could do something roughly like...
int mulContrastize(int i) {
if (i < 128) return (i * i) >> 7;
// The shift is really: * 2 / 256
i = 255 - i;
return 255 - ((i * i) >> 7);
A piecewise interpolation can be fast and flexible. It requires only a few decisions followed by a multiplication and addition, and can approximate any curve. It also avoids the courseness that can be introduced by lookup tables (or the additional cost in two lookups followed by an interpolation to smooth this out), though the lut might work perfectly fine for your case.
With just a few segments, you can get a pretty good match. Here there will be courseness in the color gradients, which will be much harder to detect than courseness in the absolute colors.
As Eamon Nerbonne points out in the comments, segmentation can be optimized by "choos[ing] your segmentation points based on something like the second derivative to maximize detail", that is, where the slope is changing the most. Clearly, in my posted example, having three segments in the middle of the five segment case doesn't add much more detail.