2010-04-11 1 views
2

При использовании обычных формул для вычисления пересечения между двумя 2D-сегментами, то есть here, если вы округлите результат до целого числа, вы получите несимметричные результаты.вычислять пересечение между двумя сегментами симметричным способом.

То есть, из-за ошибок округления, я получаю это intersection(A,B)!=intersection(B,A).

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

Моим лучшим решением на данный момент было использование некоторого полного порядка на сегментах в плоскости и иметь intersection, чтобы всегда сравнивать меньший сегмент с большим сегментом.

Есть ли лучший способ? Я что-то упускаю?

+1

Любой причину, по которой вы можете» t использовать, скажем, симметричное пересечение (A, B) = (пересечение (A, B) + пересечение (B, A))/2? Смещение с плавающей запятой является коммутативным. – brainjam

+0

@brainjam, это действительно хорошо и математически звучит, но для этого требуется, чтобы я дважды вычислил пересечение и полагался на округление с плавающей запятой, поэтому я не уверен, что это намного лучше, чем заказать на сегментах на практике. В любом случае палец вверх! Понравилось. –

+0

@brainjam, когда ошибка ползет, любая операция может усилить ошибку. Так что, если уже сравнение 'X' ==' Y' получилось ложным, 'X' ==' (X + Y)/2', скорее всего, также будет ошибочным. Более того, в случаях, когда 'X' ==' Y' может получиться истинным, 'X' ==' (X + Y)/2' может получиться ложным (например, когда 'X' и' Y' могут быть представлены без ошибок, но 'X + Y' больше не может быть представлен без ошибок.) – vladr

ответ

1

Вы не хотите сравнивать длину сегмента.

Кроме того, я полагаю, что при сравнении с intersection(A',B')intersection(B",A") следует понимать, что A' «координаты s являются идентичными representationally к A"» ы (Мет для B' и B"), либо нет никакого решения.

Это сказанное, рассмотрим сегменты [PQ] и [RS], где P, Q, R и S являются точки на плоскости. Вы хотите пересечения сегментов:

  • [PQ][RS]
  • [QP][RS]
  • [PQ][SR]
  • [QP][SR]
  • [RS][PQ]
  • [SR][PQ]
  • [RS][QP]
  • [SR][QP]

... всегда возвращает тот же пары координат.

заказ, первый из конечных точек на каждый сегменте, а затем из сегментов сам (на основе каждых сегменты мере конечной точки), является единственным решением, которое гарантирует воспроизводимые результаты. Само упорядочение может быть вычислительно тривиальным, например. P<Q тогда и только тогда P.x < Q.x || P.x == Q.x && P.y < Q.y, хотя ветвление может дорого обойтись, если имеет дело с миллионами сегментов (посмотреть, как вы можете использовать SIMD для замены сегмента координаты на месте, если это возможно, чтобы произвести заказ.)

+0

Спасибо, это то, о чем я думал. Однако, если был метод, который всегда выбирает вычислительный путь, который дает наименьшую точность ошибки, которая была бы симметричной и уменьшала бы точность ошибки. Возможно, это невозможно сделать. –

+0

@ Vlad, Вы начинаете с «Вы не хотите сравнивать длину сегмента». Почему ты это сказал? Это вычислительная стоимость или что-то еще? – brainjam

+0

@brainjam, в то время как я не могу говорить за Влада, я думаю, что он не хочет, чтобы потерянная точность и вычислительная стоимость функции квадратного корня. –