Алгоритм определения находится ли точка внутри множества точек?

vertyal17

Т.е. задача: есть множество точек x[ i ],y[ i ],z[ i ] (коорд. i-й точки если на него снаружи какбы "натянуть" поверхность, получится выпуклый многогранник. Есть ли какойто алгоритм, определяющий находится ли точка с координатами x,y,z внутри этого многогранника?
Понятно, что можно перебирать все внутренние тэтраэдеры в множестве, и проверять на то, что х,у,z находится внутри. Можно даже из множества x[ i ],y[ i ],z[ i ] както повыкидывать "внутренние" точки, но я думаю к такой задаче давно есть эффективный алгоритм. Где можно найти ? или может кто знает
зы. Не знаю как вышло что текст курсивом...

Julie16

Вначале строишь выпуклую оболочку - это будет множество плоскостей. Затем для проверяемой точки проверяешь чтобы она лежала по определенную сторону от каждой плоскости. Для этого надо в уравнение плоскости подставить координаты точки и сравнить получившееся число с 0.

mama10001

Ты уверен, что именно в таком виде это будет работать?

Vantucha

Вначале строишь выпуклую оболочку - это будет множество плоскостей.
можно поподробней?
в смысле, как ее строить?

Julie16

Ага.

Julie16

Что именно поподробнее? Как строить?

Vantucha

бля, я как раз подредактировал

mama10001

Нужно брать не просто уравнения плоскостей, а уравнения ориентированных плоскостей.
Например строя плоскости по трем точкам A, B, C через определитель, нужно брать их в такой последовательности, чтобы обход {A, B, C} был против часовой стрелки, если смотреть снаружи поверхности.
А без этой добавки пахать не будет

rosali

в смысле, как ее строить?
Ну вот это как раз надо в инете искать. Известны алгоритмы со сложностью (n ln n) - от количества точек.

Julie16

Ну например так(я не уверен что это оптимальный алгоритм, и что он вообще правильный ) :
1) Находишь точку с наименьшей координатой x
2) Проводишь через нее плоскость, параллельную oYZ. Находишь 2(или более) точки с наименьшим углом отклонения от этой плоскости(с началом угла в точке из пункта 1). Строишь через эти точки плоскость. Это и будет одна из плоскостей. Вычеркиваешь точки из списка.
3) Для полученной плоскости и лежащих на ней точек из плоскости применяешь процедуру 2. И так далее.

Julie16

А я так и сказал. Заметь, я говорил про знак. А не про больше/меньше 0. Вначале конечно надо взять пробную точку и если что умножить уравнение плоскости на -1.

rosali

2) Проводишь через нее плоскость, параллельную oYZ. Находишь 2(или более) точки с наименьшим углом отклонения от этой плоскости(с началом угла в точке из пункта 1). Строишь через эти точки плоскость. Это и будет одна из плоскостей. Вычеркиваешь точки из списка.
Да нет, неправильно, нет у тебя трехмерного воображения

Vantucha

нихуя не понял, честно говоря =)
воспользуюсь советом

Julie16

А чего не так?

rosali

x = (0,0,0)
y = (0,1,0)
z = (0,-1,0)
a = (10,0,1)
b = (10,0,-1)
y и z - имеют наименьший угол (потому что 10 - много но плоскость xyz горизонтальная и a и b по разные стороны от нее.

Julie16

Через xyz проходит сколь угодно много плоскостей Поэтому нужно взять еще одну точку. просто я не описал вырожденные случаи, там должно быть понятно что делать

mama10001

Про одинаковый знак понятно.
Придется объяснить подробней. Если одновременно во всех уравнениях ax+by+cz+d=0 вектор {a, b, c} будет определять внешнюю (или одновременно во всех внутреннюю) нормаль, то это будет работать, а если нет – не будет!

Marinavo_0507

Чо, в трёхмерном пространстве за O(n ln n) ?

rosali

Вообще, если свободного времени много (например 3-й курс то самому придумать и закодировать - бесценное упражнение. Но начать лучше с двумерного случая, чтобы представить себе что к чему... Если интересно, могу помочь советами , в свое время я тоже об этом думал.

Julie16

Блин. Еще раз: у нас есть пробная точка, которая точно лежит внутри. Знаки для пробной точки и для проверяемой точки должны совпадать. Но это не значит что они совпадают для всех плоскостей сразу. Поэтому нормали могут быть направлены как внутрь, так и наружу.

Vantucha

двумерный - это просто, еще в 10-ом классе проходили =)
для трехмерного за N^4 очевидный алгоритм, даже думать не надо =)
более быстрые, пожалуй, реально в инете поищу

mama10001

Хе-хе, я тебя понял.
Ну тогда у тебя надо помнить ориентацию каждой плоскости – по биту на штуку

rosali

Ну вот чего ты говоришь? Какие нафиг вырожденные случаи? Картинку что ли нарисуй... Ладно, щас сам нарисую
 
ось OY
^
| y
|
x-----------------------с----------------------> ось OX
|
| z
a и b - обе там же, где и c, но одна "над" экраном, а другая "под".

Julie16

Да... Что-то не то получается... Надо подумать

rosali

в трёхмерном пространстве за O(n ln n)
ну там основная идея, что можно за почти линейное время разделить все точки на 3 кучки, чтобы выпуклая оболочка 1-ой не пересекалась с выпуклой оболочкой 3-ей, причем в них примерно одинаковое количество точек, а 2-ая кучка - "маленькая" (пограничная ). Дальше для 1,3 оболочки рекурсивно строятся, а потом все это соединяется тоже за почти линейное время. Пишу "почти линейное" потому что не помню линейное оно там или нет, кажись не линейное, но меньше n ln n .

a_tischkevich

Умеют даже за O(n ln h где h - количество точек оболочки.
Например: http://citeseer.ist.psu.edu/chan95outputsensitive.html

vertyal17

Ок спасибо. Попробую запрогать кукхалл.

lord2476

можно вопрос?
вот такое множество ограничится
так:

или так:

?

lord2476

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

Dasar

Второе.
т.к. обычно нужна выпуклая оболочка.

lord2476

тогда, что думаете по моему варианту?
что выше

lord2476

ниче не говорите понял что чушь

lord2476

хотя если апргейтнуть проверкой всех полуплоскостей...

rosali

если все в одной полуплоскости то
Это правильно, но как ты это будешь определять, я не понял.
одновременно определяя в какой четеврти
Уж четверти тут вообще ни при чем...

margadon

Ты хочешь найти не выпуклую границу семейства точек? Есть кажись алгоритм Marching cubes... Не помню что и как но есть!

koly

Допустим, что мы уже построили выпуклую оболочку для множества точек.
Тогда вот два алгоритма проверки, находится ли точка внутри выпуклой оболочки:
1. Проверить, что нормали ко всем плоскостям направлены в сторону от искомой точки.
Здесь проблема в том, что хз, как посчитать нормали. Проблема решается так:
Выбираются два сопряженных многоугольника, потом в каждой плоскости строится единичный вектор, перпендикулярный общему ребру. Далее косинусы углов между суммой этих перпендикуляров и каждой из нормалей к граням должны совпадать по знаку. Если не совпадают, то одна из нормалей домножатается на -1. Так для всех граней.
2. провести любую прямую через искомую точку. Если точка внутри оболочки, то она пересечет его ровно два раза. При этом вектора, направленные из искомой точки в точки пересечений имеют разные знаки. По-моему этот способ проще, чем первый

vertyal17

Насколько я понимаю то, что я прочитал по данным мне ссылкам (да собственно я это и предполагал с самого начала) труднее всего именно построить выпуклую оболочку. По ссылке есть только один алгоритм, для 3-х мерного случая.
>1. Проверить, что нормали ко всем плоскостям направлены в сторону от искомой точки.
>Здесь проблема в том, что хз, как посчитать нормали. Проблема решается так:
>Выбираются два сопряженных многоугольника, потом в каждой плоскости строится единичный вектор, >перпендикулярный общему ребру. Далее косинусы углов между суммой этих перпендикуляров и каждой из >нормалей к граням должны совпадать по знаку. Если не совпадают, то одна из нормалей домножатается >на -1. Так для всех граней.
ну это писец какойто
>2. провести любую прямую через искомую точку. Если точка внутри оболочки, то она пересечет его >ровно два раза. При этом вектора, направленные из искомой точки в точки пересечений имеют разные >знаки. По-моему этот способ проще, чем первый
Это выходит провести прямую, я для всех граней оболочки (пусть даже скажем треугольных проверять (решать нелинейное уравнение) где пересекается эта прямая с этой гранью. Если пересекается (она будет пересекаться в 100 % без малого случаях прооверять, находится ли точкка пересечения внутри грани или за пределами. И так по всем граням. Ну да алгоритм верный. Только совсем не целесообразный.
Вобщем все равно, если строишь выпуклую оболочку - проще сразу создать уравнения для всех граней в виде ax by cz d так, чтобы весь многогранник находился по положительную полуплоскость от грани, а при проверке, находится ли точка внутри выпуклой оболочки - проверять, чтобы для всех граней ax1 by1 cz1 d был > 0; Вобщем это похоже на алгоритм 1, но только без гемора типо сторить какието нормали.
А второй алгоритм, кстати подойдет для определения, находится ли точка внутри любого многогранника, не обязательно выпуклого.
з.ы. исправил встретившееся "многоугольник" на "многогранник"

koly


Вобщем все равно, если строишь выпуклую оболочку - проще сразу создать уравнения для всех граней в виде ax by cz d так, чтобы весь многоугольник находился по положительную полуплоскость от грани, а при проверке, находится ли точка внутри выпуклой оболочки - проверять, чтобы для всех граней ax1 by1 cz1 d был > 0; Вобщем это похоже на алгоритм 1, но только без гемора типо сторить какието нормали.
Сразу видно, что человек никогда реально подобной задачи не решал.
Допустим, у нас единичный куб в первом октанте.
У него есть две грани, заданные так: x = 0 ; x -1 = 0;
Подставляем точку x=0.5, y=0.5, z=0.5.
что получаем?
0.5 >0;
0.5-1 < 0
То есть точка лежит вне куба, что неверно.
Алгоритм же, работающий с нормалями такую проверку проходит .

Dasar

> У него есть два ребра, заданные так: x = 0 ; x -1 = 0;
При чем здесь ребра?
Речь изначально шла про плоскости на которых лежат грани.

koly

При чем здесь ребра?
Речь изначально шла про плоскости на которых лежат грани.
Очепятка

Dasar

многоугольник находился по положительную полуплоскость от грани
Соответственно грани для такого куба будут:
x = 0
и
1 - x = 0

koly

Соответственно грани для такого куба будут:
x = 0
и
1 - x = 0
Гениально! А теперь докажи это компьютеру!

bobby

Если правильно строить выпуклую оболочку, то так и будет получаться.

a_tischkevich

Сразу видно, что человек никогда реально подобной задачи не решал.
Бляааааааааа

koly

Если правильно строить выпуклую оболочку, то так и будет получаться.
Да. если строить ее так, чтобы коэффициенты A, B, C уравнений плоскостей соответствовали нормалям к этим плоскостям, направленным ОТ внутренней части многогранника

vertyal17

Зкб.
У единичнного куба в первом октанте такие уравнения граней (всего 6)
x=0
1-x=0
y=0
1-y=0
z=0
1-z=0
Хочешь сказать, что условию
(x>0) && (1-x>0) && (y>0) && (1-y>0) && (z>0) && (1-z>0)
удовлетворяют какието точки вне куба? или какието точки, не удовлетворяющие этому условию лежат внутри?
(про > Или >= я не говорю, вопрос про границы пусть каждый решает сам)
и не надо никаких нормалей и косинусов. Один раз вычислил значения a, b, c, d для каждой грани, и после этого можешь хоть 100 раз проверять, находится ли точка внутри выпуклой оболочки. Помоему с вычислительной точки зрения - выгодно. Вычисления все первого порядка.

Dasar

> Гениально! А теперь докажи это компьютеру!
Можно поступить просто: руками указываешь программе точку внутри многогранника - и программа сама расставит все знаки
можно тоже самое сделать и автоматически - через определение углов между плоскостями.

vertyal17

>Да. если строить ее так, чтобы коэффициенты A, B, C уравнений плоскостей соответствовали нормалям к этим плоскостям, направленным ОТ внутренней части многогранника
А я что написал:
>Вобщем все равно, если строишь выпуклую оболочку - проще сразу создать уравнения для всех граней в виде ax by cz d так, чтобы весь многоугольник находился по положительную полуплоскость от грани, а при проверке, находится ли точка внутри выпуклой оболочки - проверять, чтобы для всех граней ax1 by1 cz1 d был > 0; Вобщем это похоже на алгоритм 1, но только без гемора типо сторить какието нормали.
подчеркиваю:
>многоугольник находился по положительную полуплоскость
Оставить комментарий
Имя или ник:
Комментарий: