Как я могу узнать, находится ли точка в треугольнике в 3D? - PullRequest
1 голос
/ 01 декабря 2011

Мне нужен алгоритм (3D), который бы определял, принадлежит ли точка треугольнику.А также, если это так, я хочу знать расстояние между некоторой точкой в ​​треугольнике и другой точкой.Треугольники можно слегка повернуть, но если точка находится за пределами вертикального охвата треугольников, то ее не следует рассматривать как внутри треугольника.

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

enter image description here

Отображаются серые линии, в каком направлении фактически стоит треугольник.


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

Ответы [ 3 ]

2 голосов
/ 01 декабря 2011

Это похоже на трехмерный эквивалент структуры данных для точек запроса, которые лежат внутри треугольника . Вы можете использовать тот же метод в 3D: в 3D плоскость разрезает пространство на две половины: точка находится либо на одной стороне плоскости, либо на другой стороне. Форма клина представляет собой набор плоскостей: просто объедините информацию which_side_of_the_plane для данной точки со всеми плоскостями, которые составляют клин .

1 голос
/ 02 декабря 2011

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

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

Если наш треугольник равен ABC (невырожденный),тогда N = (B-A)x(C-A) (перекрестное произведение) является нормалью к (уникальной) плоскости, определенной треугольником.Назовите точку, которую мы хотим проверить P.

Теперь вычислите значение a' = N . ((P-B) x (P-C)) (где . - это скалярное произведение).a' - это обычная барицентрическая координата, умноженная на N.N (что положительно).

Аналогично, мы находим b' = N . ((P-C) x (P-A)) и c' = N . ((P-A) x (P-B)).Если все три из «a», «b» и «c» не неотрицательны, то проекция P находится внутри треугольника (если вы хотите исключить сам треугольник, то все три должны быть строго положительными).

0 голосов
/ 06 декабря 2015

Это можно разделить на 2 задачи.

  1. Проверьте, чтобы точка внутри 3-х плоскостей определялась сторонами треугольника.
  2. Найти расстояние до плоскости, определенной нормалью треугольника.
    (и использовать собственную логику для проверки, считается ли это расстояние близким или нет) .

В приведенном ниже примере вы можете выполнить проверку, например:

if (isect_point_tri_prism_v3(p, v1, v2, v2) and
    (dist_signed_squared_point_tri_plane_v3(p, v1, v2, v2) < (eps * eps)):

    # do stuff

... где eps - расстояние, на которое необходимо рассмотреть точки 'на треугольнике' .

В этом примере кода используется функциональный Python, поэтому его легко перенести на другие языки, он использует только простую арифметику, без sqrt или сложных функций. # ---------------- # helper functions def sub_v3v3(v0, v1): return (v0[0] - v1[0], v0[1] - v1[1], v0[2] - v1[2]) def dot_v3v3(v0, v1): return ((v0[0] * v1[0]) + (v0[1] * v1[1]) + (v0[2] * v1[2])) def cross_v3v3(v0, v1): return ((v0[1] * v1[2]) - (v0[2] * v1[1]), (v0[2] * v1[0]) - (v0[0] * v1[2]), (v0[0] * v1[1]) - (v0[1] * v1[0])) def closest_to_line_v3(p, l0, l1): """ Return the closest point to p on the line defined by (l0, l1) """ u = sub_v3v3(l1, l0) h = sub_v3v3(p, l0) l = dot_v3v3(u, h) / dot_v3v3(u, u) return (l0[0] + u[0] * l, l0[1] + u[1] * l, l0[2] + u[2] * l) def point_in_slice_v3(p, v, l0, l1): cp = closest_to_line_v3(v, l0, l1) q = sub_v3v3(cp, v) rp = sub_v3v3(p, v) # For languages which allow divide-by-zero, # this is taken into account and returns false. h = dot_v3v3(q, rp) / dot_v3v3(q, q) return (h >= 0.0 and h <= 1.0) # -------------- # main functions def isect_point_tri_prism_v3(p, v0, v1, v2): """ Return True when the point is inside the triangular prism. Zero area triangles always return false. """ return (point_in_slice_v3(p, v0, v1, v2) and point_in_slice_v3(p, v1, v2, v0) and point_in_slice_v3(p, v2, v0, v1)) def dist_signed_squared_point_tri_plane_v3(p, v0, v1, v2): """ Return the squared distance to the triangle, positive values are 'in-front' of the triangle, negative behind. (using CCW coordinate system - OpenGL). Remove the 'copysign' call for the non-signed version. (if you don't need to know which side of the triangle the point is on). """ from math import copysign n = cross_v3v3(sub_v3v3(v2, v1), sub_v3v3(v0, v1)) rp = sub_v3v3(p, v1) len_sq = dot_v3v3(n, n) side = dot_v3v3(rp, n) fac = side / len_sq return copysign(len_sq * (fac * fac), side)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...