2014-08-20 2 views
0

Я пытаюсь выполнить дистанционные проверки между двумя кругами без использования квадратных корней. Согласно многим источникам онлайн (например, this one), способ сделать это - вычесть квадрат суммы радиусов окружностей из квадрата (используя теорему Пифагора). Однако это не работает. Согласно Wolfram Alpha и моим собственным тестам, проверка не работает, как версия sqrt. Вот два уравнения по сравнению с Wolfram: http://www.wolframalpha.com/input/?i=sqrt%28d%29+-+%28r1%2Br2%29+%3C+y+%3D%3D+d+-+%28r1%2Br2%29%5E2+%3C+yПроверка расстояния между двумя кругами без sqrt

Как также соответствующий код, не выполнившей:

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); 
    } 
} 

я делаю что-то неправильно или формула просто неверна?

+0

Что вы пытаетесь найти? абсолютное расстояние между двумя кругами? Если они перекрываются? Оба решения фактически работают одинаково: gap = (расстояние между центрами) - r1 - r2. Если значение отрицательное, они перекрываются. Если вы положите, у вас есть зазор – JonTheMon

+0

Да, я хочу, чтобы пропасть. Но для получения фактического расстояния между центрами требуется квадратный корень. Таким образом, я хочу, чтобы пробел _squared_ между кругами. По мнению других людей, это должно быть «gap^2 = (расстояние между центрами)^2 - (r1 + r2)^2', но это, похоже, не работает. – Cleroth

ответ

1

Вы спросили Вольфрама Альфа, если sqrt(d) - (r1+r2) < y эквивалентен d - (r1+r2)^2 < y и Alpha сказал «нет».

Давайте возьмем первое неравенство из вашего запроса и устранить корень квадратный с помощью алгебры:

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

Вы видите, как это отличается от вашего второго неравенства d - (r1+r2)^2 < y?

Вы можете следить за своей кишкой, или вы можете следовать правилам алгебры, но один из них дает лучшие ответы. ; ^)

+0

А ... Это было не совсем ясно, но теперь я понимаю. Причина, по которой я видел форму d <(r1 + r2)^2, состояла в том, что y был равен нулю (это только проверка на столкновение, а не фактический диапазон). Мне нужно освежить свою алгебру, потому что это сводило меня с ума! Большое спасибо! – Cleroth

0

Цикл for не заканчивается, когда вы находите что-то в радиусе действия. Я думаю, вы хотите break вместо continue. У вас также должно быть что-то, когда цикл не смог найти что-либо в пределах диапазона.

+0

Это 'продолжение', когда расстояние больше, чем 'range_sq'. Проверка 'assert' заключается в том, чтобы обе функции работали одинаково, а это не так. Нет необходимости в перерыве, поскольку это должно выполняться для каждого диапазона «Единица», как предполагает название «ForEachRange». – Cleroth

+0

@ClerothSun, но в этом случае 'continue' ничего не делает, код будет работать одинаково, если его там не было. Поэтому я смущен. –

+0

Он пропускает вызов 'assert' и' func'. Я не уверен, что вы здесь видите. – Cleroth

Смежные вопросы