Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

intersection of two circular sectors

Tags:

algorithm

I am trying to solve simple task, but I am not finding any elegant solution.

I basically solving intersection of two circular sectors. Each sector is given by 2 angles (from atan2 func) within (-pi, pi] range. Each selector occupy maximum angle of 179.999. So it can be tell for every two angles where the circular sector is.

The return value should describe mutual intersection based on following:

value <1 if one angle is contained by second one (value represents how much space occupy percentually)

value >1 if first angle (the dotted one) is outside the other one, value represents how much of dotted angle is out of the other one

basic cases and some examples are on image bellow

enter image description here

the problem is that there are so many cases which should be handled and I am looking for some elegant way to solve it.

I can compare two angles only when they are on the right side of unit circle (cos>0) because on the left side, angle numerically bigger is graphically lower. I tried use some projection on the right half:

if(x not in <-pi/2, pi/2>)
{
    c = getSign(x)*pi/2;
    x = c - (x - c);
}

but there is a problem with sectors which occupy part of both halves of unit circle...

There are so many cases... Does somebody know how to solve this elegantly? (I use c++, but any hint or pseudocode is fine)

like image 701
relaxxx Avatar asked Nov 22 '12 19:11

relaxxx


People also ask

How do you find the intersection of two circles?

To do this, you need to work out the radius and the centre of each circle. If the sum of the radii and the distance between the centres are equal, then the circles touch externally. If the difference between the radii and the distance between the centres are equal, then the circles touch internally.

What are intersecting circles called?

A Venn diagram uses circles that overlap or don't overlap to show the commonalities and differences among things or groups of things. Things that have commonalities are shown as overlapping circles while things that are distinct stand alone.

How do you find the intersection area of two circles in C++?

Given the coordinates of the centres of two circles (X1, Y1) and (X2, Y2) as well as the radii of the respective circles R1 and R2. Find the floor of the area of their intersection. Example 1: Input: X1=0,Y1=0,R1=4 X2=6,Y2=0,R2=4 Output: 7 Explanation: The intersecting area equals 7.25298806.

What is the intersection of two spheres?

Therefore, the real intersection of two spheres is a circle. The plane determined by this circle is perpendicular to the line connecting the centers of the spheres and this line passes through the center of this circle.


1 Answers

You can do the following:

  1. normalize each sector to the form (s_start, s_end) where s_start is in (-pi,pi] and s_end in [s_start,s_start+pi).
  2. sort (swap) the sectors such that s0_start < s1_start
  3. now we have only 3 cases (a, b1, b2):

    a) s1_start <= s0_end: intersection, s1_start inside s0

    b) s1_start > s0_end:

    b1) s0_start + 2*pi <= s1_end: intersection, (s0_start + 2*pi) inside s1

    b2) s0_start + 2*pi > s1_end: no intersection

Thus we get the following code:

const double PI = 2.*acos(0.);
struct TSector { double a0, a1; };

// normalized range for angle
bool isNormalized(double a)
{ return -PI < a && a <= PI; }
// special normal form for sector
bool isNormalized(TSector const& s)
{ return isNormalized(s.a0) && s.a0 <= s.a1 && s.a1 < s.a0+PI; }

// normalize a sector to the special form:
// * -PI < a0 <= PI
// * a0 < a1 < a0+PI
void normalize(TSector& s)
{
   assert(isNormalized(s.a0) && isNormalized(s.a1));

   // choose a representation of s.a1 s.t. s.a0 < s.a1 < s.a0+2*PI
   double a1_bigger = (s.a0 <= s.a1) ? s.a1 : s.a1+2*PI;
   if (a1_bigger >= s.a0+PI)
     std::swap(s.a0, s.a1);
   if (s.a1 < s.a0)
     s.a1 += 2*PI;

   assert(isNormalized(s));
}

bool intersectionNormalized(TSector const& s0, TSector const& s1,
                            TSector& intersection)
{
  assert(isNormalized(s0) && isNormalized(s1) && s0.a0 <= s1.a0);

  bool isIntersecting = false;
  if (s1.a0 <= s0.a1) // s1.a0 inside s0 ?
  {
    isIntersecting = true;
    intersection.a0 = s1.a0;
    intersection.a1 = std::min(s0.a1, s1.a1);
  }
  else if (s0.a0+2*PI <= s1.a1) // (s0.a0+2*PI) inside s1 ?
  {
    isIntersecting = true;
    intersection.a0 = s0.a0;
    intersection.a1 = std::min(s0.a1, s1.a1-2*PI);
  }
  assert(!isIntersecting || isNormalized(intersection));

  return isIntersecting;
}

main()
{
  TSector s0, s1;
  s0.a0 = ...
  normalize(s0);
  normalize(s1);
  if (s1.a0 < s0.a0)
    std::swap(s0, s1);
  TSection intersection;
  bool isIntersection = intersectionNormalized(s0, s1, intersection);
}
like image 197
coproc Avatar answered Oct 27 '22 00:10

coproc