Search code examples
c++11distancegeometrytrigonometrysqrt

Distance check between two circles without sqrt


I'm trying to do distance checks between two circles without using square roots. According to many sources online (such as this one), the way to do this is to subtract the square of the sum of the circles' radii from the squared distance (using Pythagoras's theorem). However, this doesn't seem to work. According to Wolfram Alpha and my own tests, the check doesn't work like the sqrt version. Here's the two equations compared in Wolfram: http://www.wolframalpha.com/input/?i=sqrt%28d%29+-+%28r1%2Br2%29+%3C+y+%3D%3D+d+-+%28r1%2Br2%29%5E2+%3C+y

As well as the relevant code that fails to comply:

T DistanceTo(Point p) const {
    return sqrt((p.x - x)*(p.x - x) + (p.y - y)*(p.y - y));
}

T DistanceToSq(Point p) const {
    return (p.x - x)*(p.x - x) + (p.y - y)*(p.y - y);
}

float Unit::GetDistanceTo(Unit * tgt)   const {
    auto dist = _pos.DistanceTo(tgt->GetPos());
    dist -= GetRadius() + tgt->GetRadius();
    return dist;
}
float Unit::GetDistanceToSq(Unit * tgt) const {
    auto dist = _pos.DistanceToSq(tgt->GetPos());
    auto radii = (GetRadius() + tgt->GetRadius());
    dist -= radii * radii;
    return dist;
}

template<typename Func>
void ForEachRange(Unit * owner, float range, Func func = [](Unit * tgt)) {
    auto range_sq = range * range;

    for(Unit * p : m_players) {
        if(owner == p || owner->GetDistanceToSq(p) >= range_sq) {
            if(owner != p && owner->GetDistanceTo(p) < range)
                assert(0);

            continue;
        }

        assert(owner->GetDistanceTo(p) < range);

        func(p);
    }
}

Am I doing something wrong or is the formula simply incorrect?


Solution

  • You asked Wolfram Alpha if sqrt(d) - (r1+r2) < y is equivalent to d - (r1+r2)^2 < y and Alpha said “no”.

    Let's take the first inequality from your query and eliminate the square root using algebra:

    sqrt(d) - (r1 + r2) < y
                sqrt(d) < y + r1 + r2
                      d < (y + r1 + r2)²
    

    Do you see how this is different from your second inequality d - (r1+r2)^2 < y?

    You can follow your gut or you can follow the rules of algebra, but one of them gives better answers. ;^)