![]() |
|
|
![]()
|
|
| dr.ZmeY |
|
||||||
|
Политолог ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3892 Регистрация: 26.3.2002 Где: ..::STALINGRAD::. . Репутация: нет Всего: 60 |
Попробую изложить алгоритм... Просто мозги уже кипят и отказываются работать... Чем дальше углубляюсь в проект, тем хуже, возникает куча задач, доселе мною не решённых, и от наступания на грабли - уже лоб весь в шишках
ЗАДАЧА Имеется 3D тело (замкнутая поверхность), состоящее из полигонов (кусочков/треугольников) с координатами углов x1[i] y1[i] z1[i], x2[i] y2[i] z2[i], x3[i] y3[i] z3[i] ( где i - номер полигона). Необходимо определить, точка простарнстава с координатами x0 y0 z0 находится внутри тела (замкнутой поверхности) или вне его... ====== ОБЩАЯ ТЕОРИЯ (научное обоснование Предполагаю, что если провести от этой точки (назовём её P) луч (L) в любую сторону, то, если он будет иметь чётное число пересечений с многогранником М, то это значит, что точка Р лежит вне объекта М, в противном случае - она внутри него, т.е. принадлежит ему и имеет нечётное число пересечений. Луч из точки Р наиболее удобно пускать параллельно какой-либо координате, скажем y... Т.е. имеем луч L (x>x0, y=y0, z=z0). Однако, решать задачу пересечения луча и ограниченной треугольником плоскости - трудоёмко, стоит упростить до пересечения полуплоскости (П) и граней многогранника. Как я сказал, точка Р лежит внутри многогранника, если луч, исходящий из Р, пересекает нечётное число его граней. Прямая L пересекается с многогранником, если она имеет непустое пересечение с какой-либо из его граней. Проведём через луч L плоскость, этот луч делит её на 2 части, вот одна из них и есть полуплоскость П (x>x0, y>y0, z=z0). Есои полуплоскость П не проходит через вершины многогранника М, то прямая L не пересекает этот многогранник тогда и только тогда, когда для каждой грани М полуплоскость П пересекает чётное (0,2,4,6,...) число её рёбер... Так проще, т.к. оперируем одновременно в 3 раза меньшим числом координат, и алгоритм работает быстрее, нежели, если сравнивать луч и грань. попробую изобразить теперь алгоритм, пока что пересечения прямой L и многогранника М: Просматриваем рёбра М, и с ними проводим тест на пересечение с полуплоскостью П. Если ребро и полуплоскость имеют общую точку, то в счётчике граней, которым ребро принадлежит, прибавляется 1 (предварительно счётчик - массив, имеющий ту же размерность, что и список граней, - обнуляется). Если после просмотра всех рёбер хотя бы в одном из счётчиков нечётное число, то L и М пересекаются. Основным в данном алгоритме является тест на пересечение ребра (отрезка) и полуплоскости. Массив координат может быть задан любым способом, это может быть и сплошной массив, где каждые три члена - три координаты узла грани многогранника, а т.к. грань - треугольник, то каждые 9 членов - это грань. Может быть задан списком TList, где каждый член - это x, y, z: GLFloat, как удобно... хоть тремя массивами... Структура многогранника задаётся массивом S рамерности 4*Е, где Е - число рёбер. Здесь S[1, i] и S[2, i] - номера вершин многогранника, являющиеся концами i-го ребра, а S[3, i] и S[4, i] - номера граней, для которых i-е ребро является общим. F - число граней, = V div 3, где V - список, и = V div 9 где V - массив координат (в зависимости от того, как представлять массив, писал выше)... IND[i] = счётчик. Т.е. имеем нечто (Листинг №1):
Теперь, основная задача - принадлежность точки Р многограннику М. Как известно из вышесказанного вот теперь, я подошёл и к алгоритму нахождения решения принадлежности точки к многограннику Сначала проводим тест на пересечение граничных плоскостей Пk и луча L, формируем список признаков INTR(k), где INTR(k):= -1, если пересечения нет, INTR(k):= 0, если Пk пересекает L вблизи точки Р (точность задаётся), и INTR(k):= 1, если пересечение есть. Далее просматриваются рёбра М и , если встречается ребро Еk, у которого только одна из плоскостей Пkj пересеккается с L, проводится тест на пересечение Ek и П. Если пересечение есть, то ребро - отмечается. Подсчитав число отмеченных рёбер (можно брать сумму по mod 2) и определив чётность, выясняется, лежит точка Р вне или внутри М. Тест на пересечение Пk и L примерно так: если уравнение плоскости Пk - следующее x=Bk*y + Ck*z + Dk (такая форма записи всегда возможна, если только L и Пk - непараллельны, а если же они параллельны, то пересечения нет), то L и Пk пересекаются, когда Bk*y0 + Ck*z0 + Dk > x0. Коэффициенты уравнения плоскости, как правило, несложно определить при любом способе многогранника, а по трём точкам (треугольник) плоскость определяется через матрицу. Важно знать, лежит ли Р вблизи границы М с точностью до некоторого числа W. Для граней, у которых INTR(k)=0 нужно завести отдельный счётчик. В случае если ребро пересекается с П и является стороной Fk, прибавить к счётчику Fk единицу. Если на выходе в каком-то из счётчиков - нечет, то Р лежит на этой грани. Добавим к прошлым переменным ещё пару... FP - массив размера 4*F коэффициентов плоскостей, проходящих через грани М. Вот, примерно что должно получиться... (Листинг №2)
SemplaneSegment(П, S[1, i], S[2, i]); - тест на пересечение ребра и полуплоскости. Тут нужно подробнее... Будем рассматривать сучай, когда полуплоскость - суть верхняя полуплоскость 0XY, остальные случаи приводятся к этому вращением пространства. (достаточно 3 вращения вокруг координатных осей, чтобы совместить две полуплоскости) Итак, у нас полуплоскость П: z=z0, y>y0 и ребро Е, задаваемое координаными вершинами V1(x1,y1,z1) и V2(x2,y2,z2). Сопоставим каждой вершине Vi код Сi = 0, 1, 2, 3 по следующему правилу:
Е и П пересекаются, если один из кодов вершин = 0, а другой 3, и могут пересекаться, если С2 = С1 + 2 (mod 4), т.е. (С1, С2) = (0, 2); (2, 0); (1, 3); (3, 1). В остальных случаях - пересечения заведомо нет. Это ж, готовая статья.. нужен только код... У меня мозг полностью отключен... |
||||||
|
|||||||
| Alex |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4147 Регистрация: 25.3.2002 Где: Москва Репутация: нет Всего: 162 |
Модератор: Название темы должно отражать ее суть!
-------------------- Написать можно все - главное четко представлять, что ты хочешь получить в конце. |
|||
|
||||
| Quadr0 |
|
|||
|
Unregistered |
...
Это сообщение отредактировал(а) Quadr0 - 14.7.2011, 22:45 |
|||
|
||||
| dr.ZmeY |
|
|||
|
Политолог ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3892 Регистрация: 26.3.2002 Где: ..::STALINGRAD::. . Репутация: нет Всего: 60 |
Скажем так, фигура представляет собой стокан Добавлено @ 16:06 |
|||
|
||||
| Quadr0 |
|
|||
|
Unregistered |
...
Это сообщение отредактировал(а) Quadr0 - 14.7.2011, 22:45 |
|||
|
||||
| dr.ZmeY |
|
|||
|
Политолог ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3892 Регистрация: 26.3.2002 Где: ..::STALINGRAD::. . Репутация: нет Всего: 60 |
А что, толщина стенок =0? Я об этом не говорил, я сказал "Тело", и "замкнутая поверхность"... Т.е. твой вариант - окажись точка внутри стакана, он покажет её принадлежность ему.... Что в корне не верно. |
|||
|
||||
| Quadr0 |
|
|||
|
Unregistered |
...
Это сообщение отредактировал(а) Quadr0 - 14.7.2011, 22:45 |
|||
|
||||
| dr.ZmeY |
|
||||||||||
|
Политолог ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3892 Регистрация: 26.3.2002 Где: ..::STALINGRAD::. . Репутация: нет Всего: 60 |
По порядку:
Имеем массив вершин в виде списка, задаём его глобально.
Каждая его запись - это (xi, yi, zi) т.к. каждая грань у нас - это треугольник, то считывать массив нужно сразу по три записи:
Чтобы не было иллюзий по поводу объекта - вот разложенный массив (частично, т.к. целиком - оооочень много) очень простого, очень маленького объекта:
Хмммм... Т.е. тут имеем задачу, пересечения отрезка с полуплоскостю. Повторюсь, для каждой вершины ребра задаём коды Сi...
Попробую изобразить алгоритм:
Должно быть нечто подобное... Почему именно такой алгоритм я выбрал, потому что до этого я пытался рассчитать телесный угол. Цикл по всем узлам и рассчитывал телесный угол со всеми гранями ( треугольниками ) тела. Если этот угол равен 4Пи, то узел находится внутри, в противном случае снаружи. Но такой алгоритм работал 12 часов (при том, что у процесса стоял максимальный приоритет)... После чего вешал систему... Очень неопртимальный вариант... Этот должен на порядок быстрее работать. У меня в системе до 10 миллионов узлов. |
||||||||||
|
|||||||||||
| dr.ZmeY |
|
||||
|
Политолог ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3892 Регистрация: 26.3.2002 Где: ..::STALINGRAD::. . Репутация: нет Всего: 60 |
И от куда ты знаешь, какая х левая, а какая правая?
Не факт... возможно кольцо... дело в том, что многогранник может быть абсолютно любым правильным многогранником... Это может быть даже 2 или три многогранника не соприкасающиеся или соприкасающиеся друг с другом... |
||||
|
|||||
| Albinos_x |
|
|||
![]() Evil Skynet ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3288 Регистрация: 28.5.2004 Где: X-6120400 Y-1 4624650 Репутация: нет Всего: 108 |
мда... интересный способ...
а через вектора реализовать не пробовали... -------------------- "Кто владеет информацией, тот владеет миром" Уинстон Черчилль |
|||
|
||||
| Daemon05 |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 18 Регистрация: 26.5.2005 Репутация: нет Всего: 3 |
Могу предложить следующий оригинальны алгоритм.
Окружаем фигуру кубом(не обязательно соприкасающимся, лишь бы вся фигура поместилась в куб) 1. Точку отмечаем флагом 1 2. От нее проверяем все соседние точки на предмет того не пересеклись ли они с кубом, если пересеклись, то точка наружняя, если нет, то отмечаем ее флагом 1. 3. Рекурсивно от полученных точек проверяем все ближайшие точки, которые не имеют флага 1 и повторяем до исчерпания всех точек. Если так никто с кубом и не пересекся, то точка внутри Набросок function Naruzhnyaya(x,y,z:integer):boolean; var b:boolean; begin b:=false; if PereseklasSFiguroy(x,y,z)=1 then flag[x,y,z]=1; if flag[x,y,z]=1 then else begin flag[x,y,z]=1; if PereseklasSKubom(x,y,z) then b=true else b:=Naruzhnyaya(x-1,y,z0) or Naruzhnyaya(x+1,y,z) or Naruzhnyaya(x,y-1,z) or Naruzhnyaya(x1,y+1,z) or Naruzhnyaya(x,y,z-1) or Naruzhnyaya(x,y,z+1) or Naruzhnyaya(x+1,y+1,z) or Naruzhnyaya(x-1,y+1,z) or Naruzhnyaya(x+1,y-1,z) or Naruzhnyaya(x-1,y-1,z) or Naruzhnyaya(x,y+1,z+1) or Naruzhnyaya(x,y-1,z+1) or Naruzhnyaya(x,y+1,z-1) or Naruzhnyaya(x,y-1,z-1) or Naruzhnyaya(x+1,y,z+1) or Naruzhnyaya(x+1,y,z+1) or Naruzhnyaya(x+1,y,z-1) or Naruzhnyaya(x-1,y,z+1) or Naruzhnyaya(x-1,y,z-1) or Naruzhnyaya(x+1,y+1,z+1) or Naruzhnyaya(x+1,y+1,z-1) or Naruzhnyaya(x+1,y-1,z+1) or Naruzhnyaya(x+1,y-1,z-1) or Naruzhnyaya(x-1,y+1,z+1) or Naruzhnyaya(x-1,y+1,z-1) or Naruzhnyaya(x-1,y-1,z+1) or Naruzhnyaya(x-1,y-1,z-1); end; Naruzhnyaya:=b; end; На пальцах логика алгоритма похожа на фильм ужасов, из точки равномерно распространяется во все стороны некая жуткая субстанция заполняя все флагом 1, единственное, что ее может остановить это стенки фигуры или стенки куба, соответсвенно если точка внутри, то субстанция не дойдет до куба, заполнив только внутренность фигуры. |
|||
|
||||
| Quadr0 |
|
|||
|
Unregistered |
...
Это сообщение отредактировал(а) Quadr0 - 15.7.2011, 00:38 |
|||
|
||||
| dr.ZmeY |
|
||||||||
|
Политолог ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3892 Регистрация: 26.3.2002 Где: ..::STALINGRAD::. . Репутация: нет Всего: 60 |
Quadr0, OpenGL тут не причём, да хоть Direct3D... Какая разница... Это же математика, а не графика... Ведь фигуру можно просчитывать, не рисуя её... а представив в виде массива её вершин...
Daemon05, попробуем разобрать то, что ты предлагаешь...
Это понятно... просто ограничиваем пространство вокруг многогранника.
Пусть..
Как точка может с чем-нибудь пересечься? Она же точка! Да и предстваь, что создаётся конечноразнстная сетка 1000000х1000000х1000000 узлов, т.е. это габариты куба.
По любому нужно определить, не то, что точка внутри, или нет куба, а фигуры, сложного многогранника. |
||||||||
|
|||||||||
| dr.ZmeY |
|
|||
|
Политолог ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3892 Регистрация: 26.3.2002 Где: ..::STALINGRAD::. . Репутация: нет Всего: 60 |
А мне непонятно... По какой такой причине это перенесено в раздел "Delphi: Звук, графика и видео"?
|
|||
|
||||
| Daemon05 |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 18 Регистрация: 26.5.2005 Репутация: нет Всего: 3 |
Этот алгоритм не обязан работать в 2D. В доказательство возьми виток толстой спирали, точка в центре, по твоему алгоритму она получается внутри Прошлый алгоритм явно не годится для таких размеров. Попробуем методы аналитической геометрии. Есть еще метод, но тяжело объяснить без рисунков и чертежей Теория: У каждого треугольника есть три других треугольника, с которыми он имеет общую сторону. 1. Сориентируем поверхность, для этого к каждому треугольнику дадим нормаль, направление которой для первого треугольника выбирается произвольно, допустим обходя контур по часовой стрелке и проводя нормаль буравчиком. Для остальных треугольников нормаль выбирается следующим образом. Допустим мы обошли произвольно треугольник ABC, причем в направлении по контуру от A к B, от B к C, от C к A . Тогда треугольник BCD обходим в направлении C>B>D, аналогично соседний к нему треугольник обходим в направлении D>B>E и т.д. Получаем в памяти набор нормалей, количество которых равно количеству треугольников. 2. Возьмем очевидно наружную точку. Допустим возьмем для этого далекую точку. Ищем ближайшую вершину треугольника. Находим ее. Проводим вектор в направлении от вершины до точки и скалярно множим на вектор найденной в п.1. нормали любого из трех треугольников, которому принадлежит эта ближайшая точка. Что получилось при этом умножении неважно - главное знак - плюс или минус. Допустим плюс. 3. Вот и все. Теперь чтобы определить наружность любой точки, просто находим ближайшую к этой точке вершину, проводим вектор в направлении от ближайшей вершины до точки и скалярно множим этот вектор на нормаль любого из трех треугольников которым принадлежит эта вершина. Опять же интересен только знак если плюс - точка снаружи, если минус то внутри. Преимуществалгоритма простота и скорость - ведь пункт 1 и 2 надо выполнить всего один раз, а пункт 3 потом сколько угодно для любой точки. Не знаю поняли ли вы чего из сказанного выше Тот же алгоритм на пальцах: 1. Мы просто раскрашиваем внутренние стороны каждого треугольника в черный цвет, а наружние в красный. При этом не забываем, что можем ошибится и раскрасить наоборот внутренность треугольников в красный а наружность в черный. 2. Теперь смотрим на ближайший треугольник от явно наружней точки и определяем красного или черного цвета стенку мы видим. Допустим черный - ура, значит наружняя сторона покрашена черным 3. Теперь от нужной нам точки смотрим на ближайший треугольник. Если видим черный цвет то точка внутри фигуры если красный, то снаружи. И совсем на пальцах: Если вас посадить в коробку черного цвета, но при этом обитую внутри красным, то увидев красный цвет вы догадаетесь что находитесь внутри Это сообщение отредактировал(а) Daemon05 - 13.7.2005, 02:53 |
|||
|
||||
| dr.ZmeY |
|
|||
|
Политолог ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3892 Регистрация: 26.3.2002 Где: ..::STALINGRAD::. . Репутация: нет Всего: 60 |
Хмммм... Я смотрю тут многие не совсем понимают суть задачи.... Графика в данной задачи - это всего-лишь визуализация решения - и это подзадача далеко не самой высшей сложности и важности.
Поясню на пальцах. Необходимо создать разностную сетку в некоторой прямоугольной области Lx на Ly на Lz размером Nx на Ny на Nz, в которой находится 3D объект (или объекты) - правильный многогранник, каждая грань которого - треугольник. Общее число узлов Nx*Ny*Nz. К примеру Nx=Ny=Nz=100. Общее число узлов 1000000. Нам надо выпускать 10000 (100*100) лучей с какой-либо грани и смотреть перебором какие из треугольников пересечет каждый луч. Для данного луча мы получим набор точек пересечения с многогранником. Эти точки надо будет упорядочить по возрастанию, а затем способом чет-нечет определить, лежит ли узел с координатами x,y,z внутри или вне многогранника. Например мы выпустили луч снизу (из точки xl,yl,0) и нашли, что он пересекает тело в шести точках z1,z2, .... z6. Тогда можно идти по этому лучу через шаг сетки и смотреть, сколько раз перешли точки пересечения. Если 0 или четное число раз, то узел вне многогранника. Иначе внутри. Для надежности можно пустить лучи не с одной грани, а с трех (снизу, сбоку,сзади). Если по лучу снизу узел вне многогранника, а по боковому и заднему внутри, то считать что узел внутри. Это для того, чтобы исправить ошибки конструирования фигуры (многогранника). Иногда могут попасться незамкнутые поверхности, и у нас получиться нечетное число пересечений, чего в реале быть не может. Тут наверняка можно несколько упростить (и одновременно усложнить) алгоритм... Если отказаться от создания полуплоскости, и считать как пересечение луча с треугольником (гранью многогранника). Решение будет состоять из следующих шагов:
Заметим, что значения A,B,C являются компонентами вектора нормали к плоскости, И они у нас есть (есть так же массив, в котором находятся значения векторов нормали ко всем треугольникам). D можно затем получить, подставлив одну из вершин в уравнение плоскости, например A*Pa*x + B*Pa* + C*Pa* = -D Это дает нам выражение для мю, из которого точка пересечения P может быть найдена через уравнение прямой. мю = ( D + A P1x + B P1y + C P1z ) / ( A (P1x - P2x) + B (P1y - P2y) + C (P1z - P2z) ) Если знаменатель выше равен нулю, то прямая параллельна плоскости и пересечения нет. Для того, чтобы точка пересечения лежала на отрезке, мю должно принимать значения от 0 до 1. Ну и в последнюю очередь необходимо установить, лежит ли точка пересечения внутри треугольника, ограниченного Pa, Pb, Pc. Способ, которым мы воспользуемся, опирается на то, что сумма внутренних углов вида вершина-точка-вершина равна 2pi, если точка внутри треугольника. Для точки вне треугольника эта сумма будет меньше. Очевидно, сумма берется для одной точки - точки пересечения линии и плоскости и по всем сочетаниям вершин, как проиллюстрировано на рисунке 2 Если мы вычислим единичные векторы Pa1, Pa2, Pa3 как (мы проверяем точку P на принадлежность треугольнику) Pa1 = (Pa - P) / |(Pa - P)| Pa2 = (Pb - P) / |(Pb - P)| Pa3 = (Pc - P) / |(Pc - P)| углы будут a1 = acos(Pa1 * Pa2) a2 = acos(Pa2 * Pa3) a3 = acos(Pa3 * Pa1) |
|||
|
||||
| dr.ZmeY |
|
|||
|
Политолог ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3892 Регистрация: 26.3.2002 Где: ..::STALINGRAD::. . Репутация: нет Всего: 60 |
||||
|
||||
| dr.ZmeY |
|
|||
|
Политолог ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3892 Регистрация: 26.3.2002 Где: ..::STALINGRAD::. . Репутация: нет Всего: 60 |
||||
|
||||
| dr.ZmeY |
|
|||
|
Политолог ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3892 Регистрация: 26.3.2002 Где: ..::STALINGRAD::. . Репутация: нет Всего: 60 |
Будем обозначать A,B,C - точки плоскости, X,Y - точки прямой(концы отрезка), SP - скалярное произведение, VP - векторное произведение. O - искомое множество точек пересечения
|
|||
|
||||
| Girder |
|
|||
![]() Лентяй 2 ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1993 Регистрация: 12.5.2004 Репутация: нет Всего: 155 |
dr.ZmeY:
1. лудше твои многоугольники привести к треугольникам(триангуляция). 2. Правильно пронумировать узлы... т.е. от ентого будет зависить куда будет направленна нормаль элемента(треугольника). Т.е. нормали должны быть или внутрь тела... или от тела. Например... принимаем что в тело. PS: И не забывать об окрестности(погрешности)... при которой будет считаться что узлы совпадают. 3. Проверить замкнуто ли твое тело или нет. Т.е. имеет ли оно объем... или енто просто сложная поверхность. Не объем: выход. Если объем: 4. Проверить принадлежность точки какому нить элементу(треугольнику). Принадлежит: выход. Нет не принадлежит: 5. Проверить в любом направлении, от точки, нормаль элемента(треугольника). Если он лежит над плоскостью(со стороны точки) перпендикулярной рассматриваемого направления - то точка находиться внутри... иначе с наружи. Если снаружи: 6. Например проверить: точка внутри полости тела или вне его. Это сообщение отредактировал(а) Girder - 13.7.2005, 11:35 -------------------- Как слышим, так и пишим. Истина где-то там... |
|||
|
||||
| dr.ZmeY |
|
||||||||||
|
Политолог ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3892 Регистрация: 26.3.2002 Где: ..::STALINGRAD::. . Репутация: нет Всего: 60 |
Почитай внимательнее, они уже представлены как треугольники (иначе нельзя, ведь импорт идёт из DXF-файла)
Нормаль направлена наружу... Это не сильно относится к задаче... Нормаль определяет больше пложение грани, и её видимость при визуализации в OpenGL или D3D...
А вот это проверить нереально... Считаем, что замкнуто... Если нет, то будет ошибка, или придётся направлять лучи в разные стороны, и проверять, сравнивать результаты... Ошибку это устранит, но алгоритм будет в 4 раза долше работать, что не желательно...
Масло масленное, этот алгоритм я уже и описал, собсвенно... Вот, попробую простенький аналог привести, это вариант с крайними вершинами, как был предложен Quadr0, только для 2D. Тут нужно определить, принадлежит ли точка с координатами (х0,у0) многоугольнику (x[i], y[i]) где i=1,2,3..n.
Как ясно, тут никак нельзя учесть многоугольник с отверстием.... |
||||||||||
|
|||||||||||
| Girder |
|
||||
![]() Лентяй 2 ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1993 Регистрация: 12.5.2004 Репутация: нет Всего: 155 |
Это сообщение отредактировал(а) Girder - 13.7.2005, 15:48 -------------------- Как слышим, так и пишим. Истина где-то там... |
||||
|
|||||
| dr.ZmeY |
|
|||
|
Политолог ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3892 Регистрация: 26.3.2002 Где: ..::STALINGRAD::. . Репутация: нет Всего: 60 |
Вот в этом то и проблема - в определении "ближайшего" треугольника. Хотя идея интересная, красивая... |
|||
|
||||
| dr.ZmeY |
|
|||
|
Политолог ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3892 Регистрация: 26.3.2002 Где: ..::STALINGRAD::. . Репутация: нет Всего: 60 |
Кстати, если рассматривать вариант Quadr0 для определения пересечения луча с гранью, т.е. 2D, можно использовать его гля проекции грани и луча, тогда это будет многоугольник (треугольник) и точка... Хммм...
Добавлено @ 16:52
А что? Одно другому мешает? |
|||
|
||||
| Guest |
|
||||||
|
Unregistered |
К твоей теории про полуплоскости и лучи у меня появились следующие замечания:
Это не так, допустим точка снаружи, проходящий из нее луч касается многогранника, т.е. задевает выступающее ребро или вершину и пошел дальше, пересечение при этом всего одно, т.е. нечетное, можно найти обратные примеры - короче надо отсекать касания а также случай когда луч идет прямо вдоль какой то грани - т.е. прямо по ней. В таких случаях как ни считай это за одно, ноль или много касаний - луч равноправно после такой грани может выйти как наружу так и вовнутрь, в зависимости от конфигурации многогранника.
Ничего трудоемкого. В твоем случае когда луч выходит из точки x0, y0, z0. Идет параллельно оси z, т.е. луч (x=x0, y=y0, z>z0), а треугольник задется набором координат трех его вершин (x1,y1,z1;x2,y2,z2;x3,y3,z3) то вычисляются три числа a1, a2,a3 по следующим формулам: a1=((x2-x0)*(y3-y0)-(y2-y0)*(x3-x0))/D a2=((y1-y0)*(x3-x0)-(x1-x0)*(y3-y0))/D a3=((x1-x0)(y2-y0)-(x2-x0)*(y1-y0))/D где заранее вычисляется D=(x1-x0)*(y2-y0)(z3-z0)+(z1-z0)*(x2-x0)*(y3-y0)+(y1-y0)*(z2-z0)*(x3-x0)-(z1-z0)*(y2-y0)*(x3-x0)-(y1-y0)*(x2-x0)*(z3-z0)-(x1-x0)*(y3-y0)*(z2-z0) Если все три числа a1,a2,a3 неотрицательны, то луч пересекает треугольник, при этом кроме того(что неотрицательны) если одно из чисел равно нулю, то луч пересекает ребро треугольника, если два числа равны нулю, то луч пересекает вершину треугольника. Все три числа равны нулю никак быть не смогут. Если хоть одно или два числа отрицательны, то луч совсем никак не проходит через треугольник. Но если все три числа отрицательны, то луч проходил бы через треугольник если пусть его в точности в обратную сторону. Если D получилось равно нулю, то будет деление на ноль, тут необходимы дополнительные вычисления, но я их приводить не буду. Это означает, что луч может не просто пересечь, но пройти вдоль грани треугольника.
Та же фигня, может быть неверно если полуплоскость коснулась ребра (правда при этом она непременно должна пройти через вершины, ты же упомянул что ч/з вершины полуплоскость не проходит - так что может ты и прав, но что делать если всетки прошла ч/з вершинку какую) |
||||||
|
|||||||
| Daemon05 |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 18 Регистрация: 26.5.2005 Репутация: нет Всего: 3 |
Прошлое сообщение мое было!
|
|||
|
||||
| dr.ZmeY |
|
||||||||
|
Политолог ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3892 Регистрация: 26.3.2002 Где: ..::STALINGRAD::. . Репутация: нет Всего: 60 |
Аааааа.... ты внимательно читал правила?
К тому же проверку можно простую сделать... Пускаем лучи во все 4 стороны
Всё намного проще ЗЫ: А Quadr0 получает +, за то, что сам того не ведая, подкинул хорошую идею |
||||||||
|
|||||||||
| Daemon05 |
|
||||||
|
Новичок Профиль Группа: Участник Сообщений: 18 Регистрация: 26.5.2005 Репутация: нет Всего: 3 |
:_) Думаю, да - но ты носом ткни куды надо, на всякий случай
Здесь не статистика с ошибками эксперимента, здесь математика, а значит можно придумать фигуру настолько кривую, что 3 из 4 будут внутри или все 4 в ребра уйдут
|
||||||
|
|||||||
| Daemon05 |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 18 Регистрация: 26.5.2005 Репутация: нет Всего: 3 |
Я все таки отрабатываю алгоритм, связанный с определением внешних и внутренних сторон треугольника, пока результаты следующие:
Пусть задан набор треугольников образующих фигуру. 1. Обозначим все узлы буквами(в конечной программе соответственно цифрами) т.е. для рисунка 1 это будут узлы A, B, C, D. 2. В задании треугольников расставим узлы в правильном порядке, т.е. допустим треугольники введены в программу в следующем порядке ABC, DAB, BCD, ACD Для этого Возьмем двумерный массив M[N,3], (N - количество треугольников) в который заложим эту информацию Содержимое массива M[4,3] в нашем случае (рис1) будет следующим: [A,B,C] [D,A,B] [B,C,D] [A,C,D] Заведем массив, который назовем потоком, т.к. он будет постепенно заполнятся, а в начале пуст P[N,3,2] (в примере P[4,3,2]) чем он будет заполняться? А вот чем - первый треугольник разбиваем на пары вершин в строгом порядке как они указаны в массиве M т.е. A первым B вторым C третим и формируем пары(для этого последняя размерность массива сделана 2) заполняем P для первого треугольника т.е. элемент P[1,x,x] [AB,BC,CD] Заполняем в P второй треугольник, но при этом проверяем, не встречались ли ранее такие же пары в том же порядке [DA,AB... - опаньки AB уже было, - что тогда делаем - а переставляем во втором треугольнике в массиве M[2,x] A и B местами - получаем M[2,x]=[D,B,A] попробуем еще раз P[2,x,x]=[DB,BA,AD] - классно пары не повторились(теперь не AB а BA) Теперь третий треугольник вводим его пары в P P[3,x,x]=[BC... - опа, опять было!!! переставляем M[3,x]=[C,B,D] и еще разок попробуем P[3,x,x]=[CB,BD,DC] - уффф ничего вроде не повторилось ну и четвертый треугольник P[4,x,x]=[AC,CD,DA] Ну тут повезло с первого раза - ничего не повторилось и соответственно ничего переставлять не надо. итого мы расставили узлы в правильном порядке в массиве М а именно [A,B,C] [D,B,A] [C,B,D] [A,C,D] а возникает вопрос - а на какой это все надо было - а то, что теперь мы по порядку следования узлов в треугольнике можем определить, внешнюю и внутренню сторону - а значит вычислить нормали всегда направленные наружу у всех треугольнико или вовнутрь. Действительно обратите внимание на порядок узлов - если идти от С к B, потом от B к D и наконец от D вернуться к С (рис2) то внешняя сторона треугольника обходится по часовой, а внутренняя против часовой стрелки - и так для всех треугольников - внешняя по часовой. Присоединённый файл ( Кол-во скачиваний: 6 )
_______.gif 3,44 Kb |
|||
|
||||
| dr.ZmeY |
|
||||||
|
Политолог ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3892 Регистрация: 26.3.2002 Где: ..::STALINGRAD::. . Репутация: нет Всего: 60 |
Чем больше ухитряться, тем тормознутее придётся делать алгоритм...
Знаю, но слишком много вычислений... А теперь представь, что 10млн. точек нужно каждую сверить с 50 тыс треугольников... Добавлено @ 04:05
Все нормали известны, все направлены наружу.... (иначе многогранник не построить) |
||||||
|
|||||||
| Амортизатор |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 297 Регистрация: 17.4.2005 Где: в Караганде Репутация: нет Всего: 8 |
Я абсолютно не читал что понаписали выше (нет времени сейчас), но х. сказ-ть, что проблема элементарно разрешается с помощью векторов. Заведи класс, например Vector, реализ. в нем все основные св-ва в-ров, в т ч смеш произведение. Далее из ланной точки проводишь вектор перпендикулярно какой-либо плоскости, если смеш произв этого вект и вывбранных опред образом вект из пл. например с координ xi+1-xi,... положительно, то этои ири в-ра образуют прав торойку и след. нах по ододну сторну плоскости. И так в цикле для всех полоскостей. Если знак везде один, то точка нах по одну сторону от всех плоскостей, те внутри фигуры.
-------------------- Поехали! |
|||
|
||||
| dr.ZmeY |
|
|||
|
Политолог ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3892 Регистрация: 26.3.2002 Где: ..::STALINGRAD::. . Репутация: нет Всего: 60 |
Я так делал... очень долгий алгоритм... Добавлено @ 01:18 Собственно, у меня почти готово.. .потом, как-нибудь, выложу результат... |
|||
|
||||
| Амортизатор |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 297 Регистрация: 17.4.2005 Где: в Караганде Репутация: нет Всего: 8 |
Да, алгоритм оказывается далеко не элементарный, как показалось с первого взгляда.
-------------------- Поехали! |
|||
|
||||
| Дрон |
|
|||
![]() Java-ненавистник :) ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3179 Регистрация: 29.12.2002 Где: Санкт-Петербург Репутация: нет Всего: 93 |
dr.ZmeY
Извини все сообщения "ниасилил". Но почему, например нельзя сделать сечение данного тела горизонтальной плоскостью, проходящей через нужную точку, а потом решать задачу в 2D (собственно так же -- сечением) ? -------------------- Да. Именно так. |
|||
|
||||
| DENNN |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3878 Регистрация: 27.3.2002 Где: Москва Репутация: 1 Всего: 43 |
Вот, хоть один человек движется в правильном направлении. Давйте будем грамотными инженерами и обратимся к книгам А.В.Боресков Е.В.Шикин Г.Е.Шикина "Компьютерная графика: первое знакомство" Москва. "Финансы и Статистика", 1996 страница 93-97 отсканированный фрагмент Это сообщение отредактировал(а) DENNN - 29.7.2005, 15:23 |
|||
|
||||
| DENNN |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3878 Регистрация: 27.3.2002 Где: Москва Репутация: 1 Всего: 43 |
P.S. через пару дней ссылку удалю, так что кому нужно качайте сейчас или как-то это дело на форум перенесите.
Это сообщение отредактировал(а) DENNN - 27.7.2005, 14:12 |
|||
|
||||
| podval |
|
|||
![]() Где я? Кто я? ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 3094 Регистрация: 25.3.2002 Где: СПб Репутация: 18 Всего: 62 |
||||
|
||||
| Guest |
|
|||
|
Unregistered |
А как определить принадлежит или нет точка многограннику, заданному координатами вершин в Maple.
|
|||
|
||||
| podval |
|
|||
![]() Где я? Кто я? ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 3094 Регистрация: 25.3.2002 Где: СПб Репутация: 18 Всего: 62 |
Точно так же, как и не в Мaple.
|
|||
|
||||
| amium |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 19 Регистрация: 2.12.2005 Репутация: нет Всего: нет |
А если многогранник вогнутый!?? Такой вариант не пройдет |
|||
|
||||
| DENNN |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3878 Регистрация: 27.3.2002 Где: Москва Репутация: 1 Всего: 43 |
Читай внимаетльно отсканированные страницы. Там предлагается другое решение. |
|||
|
||||
| amium |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 19 Регистрация: 2.12.2005 Репутация: нет Всего: нет |
Не похоже, чтобы этот алгоритм решал задачу с вогнутым многогранником.
|
|||
|
||||
| DENNN |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3878 Регистрация: 27.3.2002 Где: Москва Репутация: 1 Всего: 43 |
Почему же. Для просто вогнутого ( не берем фигуры "а-ля лабиринт") если точка лежит внутри, то для всех линий, образующих стороны многоугольника, точка будет лежать в полуплоскости с положительным (или отрицательным, как расположишь) знаком.
|
|||
|
||||
| amium |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 19 Регистрация: 2.12.2005 Репутация: нет Всего: нет |
Да и с простой вогнутой фигурой не сработает. Вот изображение. Присоединённый файл ( Кол-во скачиваний: 10 )
mnogogran.JPG 11,73 Kb |
|||
|
||||
| DENNN |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3878 Регистрация: 27.3.2002 Где: Москва Репутация: 1 Всего: 43 |
Да, твоя правда.
|
|||
|
||||
![]()
|
| Правила форума "Алгоритмы" | |
|
|
Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, maxim1000. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Алгоритмы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |