Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shortest distance between two degree marks on a circle?

I'm looking for a formula to find the shortest distance in degrees between two degree marks on a circle: for instance, 30 degrees and 170 degrees (140 degrees).

The two degree marks can be virtually any real number, and isn't necessarily between 0 and 360 (can be negative, or much greater than 360, for instance -528.2 and 740 (which is 171.8 degrees)). However, the distance should always be <= 180 degrees and >= 0 degrees.

It sounds simple enough. But, I've been trying to find a good solution for this and I've tried a lot of different code but nothing I've found so far works in all the cases I've tried. I'm working in c++. Does anyone have any ideas?

like image 481
Joe Lyga Avatar asked Feb 29 '12 20:02

Joe Lyga


People also ask

How do you find the shortest distance between two points on a circle?

So, the distance between the circle and the point will be the difference of the distance of the point from the origin and the radius of the circle. Using the Distance Formula , the shortest distance between the point and the circle is |√(x1)2+(y1)2−r | .

What is the distance between two points on a circle called?

The area that a chord cuts off is called a segment. The area inside a circle and bounded by two radii is a sector. The length between two points around the circumference of a circle is an arc.

How do you find the shortest distance from a line to a circle?

Solution As discussed earlier, the shortest distance between a line and a circle will be the perpendicular distance of the line from the centre of the circle, minus the radius. The radius of the circle is 1.

What's the shortest distance between two points?

A straight line is the shortest distance between two points.


2 Answers

I had been looking for a microcontroller solution like this for gearbox seeking for an animatronic puppet and I didn't have the grunt to calculate trig properly.

@ruakh's answer was a good basis but I founded that the sign was incorrectly flipped in certain conditions.

Here's the solution that worked for me. This solution works for degree marks in a circle but changing MAX_VALUE allows this to work for an arbitrary max range that's useful when measuring gear encoder pulses.

Tested on Arduino.

#define MAX_VALUE 360

float shortestSignedDistanceBetweenCircularValues(float origin, float target){

  float signedDiff = 0.0;
  float raw_diff = origin > target ? origin - target : target - origin;
  float mod_diff = fmod(raw_diff, MAX_VALUE); //equates rollover values. E.g 0 == 360 degrees in circle

  if(mod_diff > (MAX_VALUE/2) ){
    //There is a shorter path in opposite direction
    signedDiff = (MAX_VALUE - mod_diff);
    if(target>origin) signedDiff = signedDiff * -1;
  } else {
    signedDiff = mod_diff;
    if(origin>target) signedDiff = signedDiff * -1;
  }

  return signedDiff;

}
like image 166
Luke Mcneice Avatar answered Oct 06 '22 08:10

Luke Mcneice


  • Step 1: Get the "raw" difference. For example, given -528.2 and 740.0, this is 1268.2.

    • one way: raw_diff = first > second ? first - second : second - first
    • another way: raw_diff = std::fabs(first - second)
  • Step 2: Subtract a multiple of 360.0 to get a value between 0.0 (inclusive) and 360.0 (exclusive).

    • mod_diff = std::fmod(raw_diff, 360.0)
  • Step 3: If this value is greater than 180.0, subtract it from 360.0.

    • one way: dist = mod_diff > 180.0 ? 360.0 - mod_diff : mod_diff
    • another way: dist = 180.0 - std::fabs(mod_diff - 180.0)

It's probably most readable as a series of statements:

double raw_diff = first > second ? first - second : second - first;
double mod_diff = std::fmod(raw_diff, 360.0);
double dist = mod_diff > 180.0 ? 360.0 - mod_diff : mod_diff;

But if desired, it's not hard to put it all into a single expression:

180.0 - std::fabs(std::fmod(std::fabs(first - second), 360.0) - 180.0)
like image 30
ruakh Avatar answered Oct 06 '22 09:10

ruakh