Как определить, когда две движущиеся точки становятся видны друг другу?

Предположим, у меня есть две точки, Point1 и Point2. В любой момент времени эти точки могут находиться в разных положениях — они не обязательно статичны.

Point1 находится в некотором положении в момент времени t, и его положение определяется непрерывными функциями x1(t) и y1(t), задающими координаты x и y в момент времени t. Эти функции не дифференцируемы, они строятся кусочно из отрезков.

Point2 тот же самый, с x2(t) и y2(t), каждая функция имеет одинаковые свойства.

Препятствия, которые могут помешать видимости, представляют собой простые (и неподвижные) полигоны.

Как найти граничные точки видимости?

т. е. есть два вида границ: где точки становятся видимыми, и становятся невидимыми.

Для ставшей видимой границы i существует некоторое ϵ>0, такое что для любого действительного числа a, a ∈ (i-ϵ, i) Point1 и Point2 не видны (т. е. отрезок, соединяющий (x1(a), y1(a)) с (x2(a), y2(x)), пересекает некоторые препятствия).

При b ∈ (i, i+ϵ) они видны.

И наоборот, ибо становится-невидимым.

Но могу ли я найти точную такую ​​границу, и если да, то как?


person Devin Jeanpierre    schedule 05.05.2010    source источник


Ответы (3)


Хорошо, теперь у меня есть более четкое представление о проблеме, и, вдохновленный предложением @walkytalky, вот более подробный ответ.

Вы упомянули, что p1 и p2 перемещаются по отрезкам прямой. Я не знаю, выровнены ли эти сегменты таким образом, что p1 и p2 всегда начинают новые сегменты одновременно. Однако вы всегда можете разрезать отрезок на два отрезка (с одинаковым наклоном), чтобы p1 и p2 всегда начинали новые отрезки одновременно.

Предположим, что p1 движется по линии A-B, а p2 движется (одновременно) по C-D, поскольку параметр t изменяется от 0 до 1. (То есть в момент времени t=0.5 p1 находится в середине A-B, а p2 в середине C-D. .)

Позволив Ax и Ay обозначать координаты x и y точки A (и аналогично для B, C и D), мы можем выразить p1 и p2 как функции t следующим образом:

p1(t) = (Ax + t*(Bx - Ax), Ay + t(By - Ay))
p2(t) = (Cx + t*(Dx - Cx), Cy + t(Dy - Cy))

(Например, когда t=0, Ax + t*(Bx - Ax) оценивается как Ax, а когда t=1 оценивается как Bx.)

Чтобы найти каждую «вершину-проходит-между-p1-и-p2»-время, мы делаем следующее:

Для каждой вершины препятствия v=(Vx, Vy) нам нужно найти t так, чтобы p1(t), p2(t) и v находились на одной линии друг с другом.

Это можно сделать, решив следующие уравнения (два уравнения и два неизвестных, t и k):

Vx=p1(t).x + k*(p2(t).x - p1(t).x)
Vy=p1(t).y + k*(p2(t).y - p1(t).y)`

Если k лежит между 0 и 1, вершина многоугольника v на самом деле между (расширенной) линией A-B и (расширенной) линией C-D. Если t также находится между 0 и 1, то вершина v фактически проходит линию p1-p2 за время прохождения точек по этим отрезкам (поскольку, когда t будет, скажем, 1,3, точки уже будут на новых отрезках).

После того, как все времена «вершина-проходит-между-p1-и-p2» были вычислены, вычислить остальное несложно. (То есть выяснение, является ли это типом прохождения «попадание в поле зрения», «становление вне поля зрения» или «ни то, ни другое»):

Для всех пар t0 и t1 последовательных моментов прохождения вершин вы проверяете, свободна ли линия p1((t1-t0)/2)-p2((t1-t0)/2) от пересечений с ребром полигона. Если он свободен от пересечений, то точки будут находиться на прямой видимости весь период (t0-t1), в противном случае они будут вне поля зрения весь период (поскольку никакие другие вершины не пройдены за этот период времени).

person aioobe    schedule 05.05.2010

Легко проверить, пересекаются ли две линии. Используйте это, чтобы проверить пересечение линии (p1, p2) и каждого ребра полигона. Если у вас есть какое-либо пересечение, линия (p1, p2) перекрывается каким-то препятствием.

Если вам нужен временной интервал (в котором p1 и p2 не находятся на прямой видимости), вы можете выполнить вышеуказанную проверку для разных значений t (желательно с относительно небольшими различиями) и между «видимым-t» и «невидимым -t" вы можете выполнять бинарный поиск, пока не достигнете достаточно малого порога, например, eps.

person aioobe    schedule 05.05.2010
comment
Порог равен нулю, в противном случае решение не является точным и не удовлетворяет граничным критериям (поскольку вы можете выбрать что-либо в пределах неправильной стороны границы ошибки и получить неверный ответ). - person Devin Jeanpierre; 05.05.2010

Изменения видимости могут происходить только тогда, когда вершина препятствия лежит на отрезке линии Point1-Point2. Итак, подсчитайте время всех таких столкновений вершин. (Интуитивно это должен быть относительно простой тест, поскольку конечные точки перемещаются линейно, но мне нужно будет на самом деле проработать его, чтобы проверить. Я попробую позже и вернусь.)

Теперь у вас есть конечный набор коллизий. Для каждого из них проверьте, не пересекает ли сегмент какие-либо другие края препятствий. Если да, то этот край определяет видимость, а время не является границей видимости. Если это не так, вы можете проверить видимость в точках (t-) и (t+), чтобы определить характер изменения.

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

Обновить

Процесс идентификации столкновений вершин действительно достаточно прост, он просто включает в себя решение немного утомительного квадратного уравнения относительно t. Вам нужно сделать это для каждой вершины для каждого кусочного сегмента движения, поэтому я предполагаю, что стоимость будет O(n*m) для n вершин и m периодов времени. (Если временные периоды функций положения не синхронизированы, вам нужно будет разделить их, чтобы они были синхронизированы.)

Рассмотрим только один период времени и шкалу t в диапазоне [0,1]. Каждая функция положения линейна по t, поэтому определите x1(t) = x10 + x1m * t (т. е. x10 — это начальное значение, а x1m — градиент), и аналогично для y1(t), x2(t) и y2(t). Для вершины V = (vx, vy) время (если есть), в которое V лежит на отрезке, соединяющем точки, определяется уравнением At^2 + Bt + C = 0, где:

A = x1m * y2m - x2m * y1m
B = vx * (y1m - y2m) + vy * (x2m - x1m)
     + x10 * y2m - x20 * y1m
     + y20 * x1m - y10 * x2m
C = vx * (y10 - y20) + vy * (x20 - x10)
     + x10 * y20 + x20 * y10

(Или что-то в этом роде. Учитывая вероятность ошибок транскрипции на обратной стороне конверта, я настоятельно рекомендую проверить это самостоятельно перед реализацией!)

Если у этого есть действительное решение в диапазоне [0,1], Боб твой дядя. Если оно уменьшится до 0 = 0 или около того, то точка все время будет на кону, и в этом случае вы должны учитывать свою политику.

person walkytalky    schedule 05.05.2010
comment
Правильно, но у меня нет дискретного количества точек времени, просто время в целом (взяв любое число с плавающей запятой - по общему признанию, числа с плавающей запятой имеют только конечную точность, но...). - person Devin Jeanpierre; 05.05.2010
comment
Времена — это времена пересечения вершин. Если у вас есть бесконечное количество вершин-препятствий или бесконечное количество линейных сегментов в ваших функциях движения, то проблема в любом случае неразрешима. Но над любым конечным сечением вам нужно будет протестировать конечное количество раз. - person walkytalky; 05.05.2010
comment
Хорошее решение. Однако я бы не стал проверять видимость в точках (t-ε) и (t+ε), так как технически никакое ε не является достаточно малым. И я бы не стал использовать наклон, как вы, поскольку вполне может быть, что у вас бесконечный наклон (или близкий к бесконечному, что излишне разрушает точность). (Если я неправильно понял ваше решение.) - person aioobe; 05.05.2010
comment
Пока ε достаточно мало, чтобы не перекрывать предыдущее или следующее время столкновения, состояние видимости будет правильным. Вполне возможно, что может существовать разрыв, который слишком мал, чтобы его можно было обнаружить с любой заданной численной точностью, но я не уверен, что с этим можно что-то сделать. - person walkytalky; 05.05.2010
comment
Что касается наклона или градиента, это параметрическое уравнение в t, а не в декартовой плоскости. Если точки на самом деле не телепортируются, то она не должна быть бесконечной. (Нам говорят, что функции непрерывны.) Точки могут двигаться параллельно одной оси или другой, имея наклон 0 в соответствующей функции. - person walkytalky; 05.05.2010
comment
(Есть неявная апелляция к градиенту XY при выводе квадратичного, но я думаю, что любая ненужная числовая неточность теряется в алгебре. Это потребует проверки, конечно.) - person walkytalky; 05.05.2010
comment
О, градиент x1m — это вектор. Понятно, я думал, что это скаляр... Теперь он мне симпатичнее выглядит =) - person aioobe; 05.05.2010
comment
Нет, это скаляр. x и y определяются независимо через t. Конечно, было бы возможно (и немного изящнее) написать все в терминах векторов, но это должно быть эквивалентным. Я просто пошел с чем-то, приближающимся к нотации исходного вопроса. - person walkytalky; 05.05.2010
comment
В качестве последнего уточнения: мой x10 — это ваш Ax, мой x1m — это ваш (Bx — Ax) и т. д. Эти два метода эквивалентны, но я расширил свой и немного повозился, чтобы поменять местами два ваших неизвестных на квадратичное в одном неизвестный. Я ожидаю получить один и тот же ответ в любом случае, но в целом ваша разработка проще и понятнее! - person walkytalky; 05.05.2010
comment
Ага. Извините за медлительность. Я вижу сейчас. Это, конечно, очень похоже на мои уравнения. Я был немного удивлен, увидев ^ 2 в ваших уравнениях, но когда я думаю об этом, кажется, что он появится в моих уравнениях, если я тоже немного поиграю с ними, как вы это сделали. Вся история, вероятно, могла бы быть написана еще яснее, если бы использовались векторы. (Вероятно, при реализации этого тоже полезно сделать некоторый векторный класс.) - person aioobe; 05.05.2010