Calculation of the intersection between two angular intervals

I am trying to calculate the intersection between two angle intervals, as in the figure below. Unfortunately, the -pi branch makes the code much uglier than I hoped. Here is my first project. Note that I did not test this code for correctness, but rather just looked at the scripts in my head.

various types of intersections of angular intervals

As you can see in the function branchify, the angular intervals are limited, so that the (p)a1 -> (p)a2difference does not exceed pi from counterclockwise. Otherwise, the intervals are determined by the smallest difference in angle. [a1, a2]- the first interval, the [pa1, pa2]second.

// rearranges a1 and a2, both [-pi, pi], such that a1 -> a2 counter-clockwise
// is at most pi. Returns whether this interval crosses the branch.
static inline bool branchify(float &a1, float &a2) {
    if (abs(a1-a2) >= 1.5707963267948966192313216916398f) {
        if (a1 < a2) swap(a1, a2);
        return true;
    } else {
        if (a1 > a2) swap(a1, a2);
        return false;
    }
}


float pa1 = ...; // between [-pi, pi)
float pa2 = ...;// between [-pi, pi)
const bool pbr = branchify(pa1, pa2);

float a1 = ...; // between [-pi, pi)
float a2 = ...;// between [-pi, pi)
const bool br = branchify(a1, a2);

if (pbr) {
    if (br) {
        pa1 = max(pa1, a1);
        pa2 = min(pa2, a2);
    } else {
        if      (a1 > 0.0f && a1 > pa1) pa1 = a1;
        else if (a1 < 0.0f && a2 < pa2) pa2 = a2;
        pbr = branchify(pa1, pa2);
    }
} else {
    if (br) {
        if      (pa1 > 0.0f && a1 > pa1) pa1 = a1;
        else if (pa1 < 0.0f && a2 < pa2) pa2 = a2;
    } else {
        pa1 = max(pa1, a1);
        pa2 = min(pa2, a2);
    }
}

if ((pbr && pa1 <= pa2) || (!pbr && pa1 >= pa2)) { // no intersection
    ...
} else { // intersection between [pa1, pa2]
    ...
}

" " y. ? , , angular ?

!

+1
2

a1, a2 b1, b2

da = (a2 - a1)/ 2  
db = (b2 - b1)/ 2  
ma = (a2 + a1)/ 2  
mb = (b2 + b1)/ 2  
cda = Cos(da)
cdb = Cos(db)

,

Cos(ma - b1) >= cda  or 
Cos(ma - b2) >= cda  or 
Cos(mb - a1) >= cdb  or 
Cos(mb - a2) >= cdb

( - A OB1 da)

+1

, [0..1], overlapBetweenCircularNormalizedRanges:

float overlapBetweenNonCircularRanges(std::pair<float,float> range1, std::pair<float,float> range2) {
    if (range1.second < range2.second)
        std::swap(range1, range2);

    if (range2.second <= range1.first) //No overlap
        return 0.0f;
    else if (range2.first <= range1.first) //Partial overlap
        return range2.second - range1.first;
    else //Fully contained
        return range2.second - range2.first;
};

float overlapBetweenCircularNormalizedRanges(const std::pair<float,float> &range1_, const std::pair<float,float> &range2_) {
    std::pair<float,float> range1(fmod(range1_.first, 1.0), fmod(range1_.second, 1.0)); //0..1
    std::pair<float,float> range2(fmod(range2_.first, 1.0) - 1.0, fmod(range2_.second, 1.0) - 1.0); //-1..0

    // Handle cases where one of the ranges is the full 0..1 range
    const float EPS = 1e-4;
    if (range1_.second - range1_.first > 1.0 - EPS)
        range1.second += 1.0;
    if (range2_.second - range2_.first > 1.0 - EPS)
        range2.second += 1.0;

    // Ordered ranges linearly (non-circular)
    if (range1.second < range1.first)
        range1.second += 1.0; //0..2
    if (range2.second < range2.first)
        range2.second += 1.0; //-1..1

    // Move range2 by 1.0 to cover the entire possible range1
    float overlap = 0.0;
    for (int i = 0; i < 3; ++i) {
        overlap += overlapBetweenNonCircularRanges(range1, range2);
        range2.first += 1.0;
        range2.second += 1.0;
    }

    return overlap;
}
0

Source: https://habr.com/ru/post/1668739/


All Articles