1 votos

Determina si un segmento de recta pasa "a través" de un triángulo ...

Gurús de las matemáticas,

Me disculpo porque en un entrada anterior Pregunté cómo determinar si una línea pasa por un triángulo; y me dieron una respuesta. Luego, mientras hacía pruebas, me encontré con el escenario en el que un "segmento" de línea vertical estaba por debajo de la base del triángulo y la respuesta a mi pregunta anterior daba falsos positivos. Esto fue culpa mía porque claramente hay una diferencia entre una línea y un segmento de línea.

A continuación se muestra un diagrama de lo que me gustaría lograr. Se considera que todos los segmentos de la línea verde pasan "a través" del triángulo. Los segmentos de la línea roja (obviamente) no.

enter image description here

Los datos que estoy utilizando tienen valores x, y y z, pero para esta prueba, podemos suponer que el triángulo y el segmento de línea serán coplanares.

El triángulo que estoy utilizando para las pruebas está definido por los puntos:

vo = (2,2,1) v1 = (7,2,1), v2 = (5,6,1)

y cada uno de mis casos de prueba está utilizando estos puntos:

  1. Segmento de línea exterior - sin intersección: p0 = (1,4,1) p1 = (3,7,1)
  2. Intersección en el vértice: p0 = (4,6,1) p1 = (8,6,1)
  3. Intersección a través de 2 aristas: p0 = (4,1,1) p1 = (5,7,1)
  4. La intersección contiene la arista: p0 = (1,2,1) p1 = (5,8,1)
  5. Intersección por 1 vértice y arista: p0 = (5,1,1) p1 = (5,8,1)

¿Existe alguna fórmula específica que proporcione una indicación de "verdadero" / "falso" en cuanto a si un segmento de línea pasa por encima del triángulo como se ha descrito anteriormente?

NO necesito saber el punto de intersección en el caso de un resultado "verdadero" (pero si forma parte de la determinación del resultado, sería un plus).

Gracias de antemano por su ayuda y paciencia.

4voto

Yves Daoust Puntos 30126

Deben cumplirse dos condiciones:

  • la línea de apoyo cruza el triángulo. Esto se puede comprobar contando los vértices del triángulo a ambos lados de la línea, es decir, 3 LeftOf pruebas ( PQV0 , PQV1 , PQV2 ).

  • los dos puntos extremos no pueden estar ambos en el mismo lado de las líneas de apoyo de los lados que se cruzan. Toma 2 o 4 pruebas más de LeftOf (entre PV0V1 , PV1V2 , PV2V0 , QV0V1 , QV1V2 , QV2V0 ; 3 de media).

En el ejemplo, dos vértices están a la derecha de PQ y uno a la izquierda para que la línea se cruce. Cruza los lados naranja y rojo. Entonces P y Q no están en el mismo lado de la línea naranja.

enter image description here

2voto

amd Puntos 2503

Las coordenadas baricéntricas parecen un camino razonable. Para repasar, las coordenadas baricéntricas de un punto $\mathbf p=(x,y)$ relativa a un triángulo con vértices $\mathbf v_0=(x_0,y_0)$ , $\mathbf v_1=(x_1,y_1)$ , $\mathbf v_2=(x_2,y_2)$ son un triple $\mathbf\lambda=[\lambda_0:\lambda_1:\lambda_2]$ tal que $\mathbf p=\lambda_0\mathbf v_0+\lambda_1\mathbf v_1+\lambda_2\mathbf v_2$ y $\lambda_0+\lambda_1+\lambda_2=1$ . Una forma de pensar en estas coordenadas es como las masas que deben colocarse en los vértices del triángulo para que el centro de masa esté en $\mathbf p$ . Podemos eliminar la condición de normalización y trabajar con coordenadas no normalizadas, en cuyo caso $\mathbf p={\lambda_0\mathbf v_0+\lambda_1\mathbf v_1+\lambda_2\mathbf v_2\over\lambda_0+\lambda_1+\lambda_2}$ . Estas coordenadas son homogéneo -lo importante son las relaciones entre ellas, y dos conjuntos de coordenadas que son múltiplos escalares no nulos entre sí representan el mismo punto.

Las características de las coordenadas baricéntricas (normalizadas) que utilizaré son las siguientes:

  • Las coordenadas baricéntricas y cartesianas se relacionan mediante una transformación lineal.
  • Si un punto es interior o está en el triángulo, entonces todas sus coordenadas baricéntricas están en el intervalo cerrado $[0,1]$ .
  • Una coordenada cero indica que el punto se encuentra en la línea lateral opuesta al vértice correspondiente. Una coordenada negativa indica que el punto se encuentra en el lado opuesto de esa línea lateral al vértice. Por ejemplo, si la primera coordenada es negativa, el punto se encuentra en el lado opuesto de la línea que pasa por $v_1$ y $v_2$ al igual que $v_0$ .

El mapeo cartesiano a baricéntrico puede calcularse expresando la definición de coordenadas baricéntricas como la ecuación matricial $$\begin{bmatrix}x_0&x_1&x_2\\y_0&y_1&y_2\\1&1&1\end{bmatrix}\begin{bmatrix}\lambda_0\\\lambda_1\\\lambda_2\end{bmatrix}=\begin{bmatrix}x\\y\\1\end{bmatrix}.$$ The triangle is not degenerate, so that the matrix on the left is nonsingular and thus the barycentric coordinates are found by multiplying $(x,y,1)^T$ by the inverse of that matrix. This $3\times3$ inversion can be reduced to $2\times2$ by rewriting the coordinate equation as $$\begin{bmatrix}\mathbf v_0-\mathbf v_2 & \mathbf v_1-\mathbf v_2\end{bmatrix}\begin{bmatrix}\lambda_0\\\lambda_1\end{bmatrix}=\mathbf p-\mathbf v_2.$$ La tercera coordenada puede calcularse entonces como $\lambda_2=1-\lambda_0-\lambda_1$ .

Otra forma de evitar la inversión de la matriz es utilizar el hecho de que las relaciones de coordenadas baricéntricas son iguales a las relaciones de las áreas con signo de los triángulos formados por el punto y los pares de vértices del triángulo de referencia. Estas áreas pueden calcularse como $$\frac12\begin{vmatrix}x_{i+1} & x_{i+2} & x \\ y_{i+1} & y_{i+2} & y \\ 1&1&1 \end{vmatrix}=\frac12(x_{i+1},y_{i+1},1)\times(x_{i+2},y_{i+2},1)\cdot(x,y,1)$$ con índices que envuelven el mod 3. Recordando que los componentes del producto de una matriz y un vector columna son los productos punto del vector con las filas de la matriz, los cálculos del área pueden escribirse como $$\frac12\begin{bmatrix}(\tilde{\mathbf v}_1\times\tilde{\mathbf v}_2)^T \\ (\tilde{\mathbf v}_2\times\tilde{\mathbf v}_0)^T \\ (\tilde{\mathbf v}_0\times\tilde{\mathbf v}_1)^T \end{bmatrix}\tilde{\mathbf p}.$$ (Las tildes denotan las coordenadas homogéneas obtenidas añadiendo un $1$ al par de coordenadas cartesianas). Estas coordenadas se pueden normalizar dividiendo por el área del triángulo de referencia, de modo que las coordenadas baricéntricas normalizadas de $\mathbf p=(x,y)$ son $$\mathbf\lambda=\frac1{\det\begin{bmatrix}\tilde{\mathbf v}_0&\tilde{\mathbf v}_1&\tilde{\mathbf v}_2\end{bmatrix}}\begin{bmatrix}(\tilde{\mathbf v}_1\times\tilde{\mathbf v}_2)^T \\ (\tilde{\mathbf v}_2\times\tilde{\mathbf v}_0)^T \\ (\tilde{\mathbf v}_0\times\tilde{\mathbf v}_1)^T \end{bmatrix}\tilde{\mathbf p}.$$ (También puede trabajar con coordenadas no normalizadas, pero tendrá que utilizar un intervalo diferente para determinar cuándo un punto está en/sobre el triángulo: las coordenadas deben estar limitadas por $0$ y $\lambda_1+\lambda_2+\lambda_3$ pero esto último podría ser negativo).

Sean las coordenadas baricéntricas de los puntos extremos del segmento de línea $\mathbf P=[\lambda_1:\lambda_2:\lambda_3]$ y $\mathbf Q=[\mu_1:\mu_2:\mu_3]$ . Si cualquiera de estos puntos está en/sobre el triángulo, es decir, $0\le\lambda_1,\lambda_2,\lambda_3\le1$ o $0\le\mu_1,\mu_2,\mu_3\le1$ entonces hemos terminado: el segmento de línea obviamente interseca el triángulo.

Si no, tenemos dos puntos exteriores. Gracias a la linealidad del mapeo cartesiano a baricéntrico, la línea que pasa por $\mathbf P$ y $\mathbf Q$ puede parametrizarse como $(1-t)\,\mathbf P+t\,\mathbf Q$ en ambos sistemas de coordenadas, con $t\in[0,1]$ dando el segmento de línea. Los valores de $t$ para la cual una coordenada baricéntrica de la combinación lineal anterior es $0$ son las intersecciones con las líneas laterales correspondientes. Estos valores de $t$ se encuentran fácilmente $t_i={\lambda_i\over\lambda_i-\mu_i}$ , a menos que $\lambda_i=\mu_i$ en cuyo caso la línea es paralela a ese lado del triángulo. El segmento de línea interseca al triángulo si cualquiera de estos cruces de líneas laterales ocurre en el triángulo. Además, para que un segmento de línea con dos puntos extremos exteriores intersecte al triángulo, debe haber al menos dos cruces de líneas laterales, independientemente de dónde estén esos puntos de cruce.

Por lo tanto, compara las coordenadas baricéntricas correspondientes de $\mathbf P$ y $\mathbf Q$ . Si menos de dos pares tienen signos opuestos, entonces el segmento no interseca al triángulo y hemos terminado. En caso contrario, para cada par de coordenadas $\lambda_i$ y $\mu_i$ calcula el punto de intersección ${\mu_i\over\mu_i-\lambda_i}\mathbf P+{\lambda_i\over\lambda_i-\mu_i}\mathbf Q$ . (Podría ser más conveniente utilizar $1-{\lambda_i\over\lambda_i-\mu_i}$ para el coeficiente de $\mathbf P$ .) Si alguno de estos puntos de intersección se encuentra en el triángulo, entonces el segmento interseca al triángulo.

Los cálculos anteriores fueron para puntos en $\mathbb R^2$ pero estás trabajando en $\mathbb R^3$ . Las transformaciones afines conservan las líneas, sus intersecciones y las longitudes relativas de los segmentos a lo largo de una línea, por lo que el problema puede convertirse en bidimensional mediante una proyección paralela sobre cualquier plano conveniente que no sea ortogonal al plano del triángulo. La proyección sobre uno de los planos de coordenadas es la más sencilla, ya que sólo hay que eliminar una de las coordenadas cartesianas. Si se utiliza el $3\times3$ matriz de transformación de coordenadas, proyectando sobre $z=1$ es conveniente ya que establece la tercera coordenada en $1$ como se requiere para utilizar la matriz.

También es posible evitar una proyección explícita si el plano del triángulo no pasa por el origen. En ese caso, las áreas de los triángulos en el plano son proporcionales a los volúmenes de los tetraedros definidos por los vértices del triángulo y el origen, por lo que podemos utilizar directamente los productos triples de los puntos para calcular las coordenadas baricéntricas. Es decir, podemos calcular $$\mathbf\lambda=\begin{bmatrix}(\mathbf v_1\times\mathbf v_2)^T\\(\mathbf v_2\times\mathbf v_0)^T\\(\mathbf v_0\times\mathbf v_1)^T\end{bmatrix}\mathbf p$$ utilizando los triples de coordenadas en bruto de estos puntos. Si el plano del triángulo pasa por el origen, desplaza todos los puntos una pequeña distancia en una dirección no paralela al plano.

Esta solución es fundamentalmente similar a el que da el Animal Nominal . Sin embargo, el uso de coordenadas baricéntricas permite tratar todos los lados del triángulo de manera uniforme. Además, si lo piensas un poco, verás que estos cálculos son una serie de pruebas de "izquierda", desenrolladas.


La forma de producto cruzado del mapeo cartesiano a baricéntrico me lleva a descartar esto también, aunque dudo que sea tan eficiente como otras soluciones que se han presentado. Aprovecha el hecho de que en $\mathbb{RP}^2$ La línea que pasa por dos puntos y la intersección de dos líneas pueden calcularse tomando productos cruzados de vectores de coordenadas homogéneas. Por lo tanto, la matriz de asignación de coordenadas puede verse como si tuviera las tres líneas laterales del triángulo como sus filas.

Las coordenadas baricéntricas de las tres intersecciones de las líneas laterales pueden calcularse "en bloque" como $B(\tilde{\mathbf p}\times\tilde{\mathbf q})_\times B^T$ , donde $B$ es la matriz de transformación de coordenadas de arriba y la matriz central es la "matriz de producto cruzado" definida como sigue: para cualquier vector $\mathbf w=(w_1,w_2,w_3)T$ , $$\mathbf w_\times=\begin{bmatrix}0&-w_3&w_2\\w_3&0&-w_1\\-w_2&w_1&0\end{bmatrix}.$$ Al igual que antes, tendrás que comprobar si alguno de estos puntos está en el triángulo y también tendrá que comprobar que los candidatos viables para las intersecciones de los triángulos se encuentran entre $\mathbf p$ y $\mathbf q$ . Además, estas coordenadas no estarán normalizadas, por lo que tendrás que tenerlo en cuenta al hacer estas pruebas. También tendrás que lidiar con los puntos en el infinito, que se producirán cuando el segmento sea paralelo a uno de los lados del triángulo. En forma baricéntrica, las coordenadas de los puntos en el infinito suman cero.

0voto

Nominal Animal Puntos 23

Yo sugeriría transformar a coordenadas planas, de manera que los vértices del triángulo sean mapeados a $(0,0)$ , $(1,0)$ y $(1,1)$ .

Digamos que los vértices del triángulo son $( x_0 , y_0 , z_0 )$ , $( x_1 , y_1 , z_1 )$ y $( x_2 , y_2 , z_2 )$ . En primer lugar, calcule $$\begin{array}{l} d_{XY} = x_0 ( y_1 - y_2 ) + x_1 ( y_2 - y_0 ) - x_2 ( y_1 - y_0 ) \\ d_{XZ} = x_0 ( z_1 - z_2 ) + x_1 ( z_2 - z_0 ) - x_2 ( z_1 - z_0 ) \\ d_{YZ} = y_0 ( z_1 - z_2 ) + y_1 ( z_2 - z_0 ) - y_2 ( z_1 - z_0 ) \end{array} \tag{1}\label{1}$$ Dependiendo de cuál de $\eqref{1}$ es de mayor magnitud, calculamos ocho constantes.

  • Si $\lvert d_{XY} \rvert \ge \lvert d_{XZ} \rvert$ y $\lvert d_{XY} \rvert \ge \lvert d_{XZ} \rvert$ entonces $$\begin{array}{ll} U_u = (x_2 y_0 - x_0 y_2) / d_{XY} & V_v = (x_0 y_1 - x_1 y_0) / d_{XY} \\ U_x = (y_2 - y_0) / d_{XY} & V_x = (y_0 - y_1) / d_{XY} \\ U_y = (x_0 - x_2) / d_{XY} & V_y = (x_1 - x_0) / d_{XY} \\ U_z = 0 & V_z = 0 \end{array}$$

  • Por otra parte, si $\lvert d_{XZ} \rvert \ge \lvert d_{XY} \rvert$ y $\lvert d_{XZ} \rvert \ge \lvert d_{YZ} \rvert$ entonces $$\begin{array}{ll} U_u = (x_2 z_0 - x_0 z_2) / d_{XZ} & V_v = (x_0 z_1 - x_1 z_0) / d_{XZ} \\ U_x = (z_2 - z_0) / d_{XZ} & V_x = (z_0 - z_1) / d_{XZ} \\ U_y = 0 & V_y = 0 \\ U_z = (x_0 - x_2) / d_{XZ} & V_z = (x_1 - x_0) / d_{XZ} \end{array}$$

  • Por lo demás, $\lvert d_{YZ} \rvert \ge \lvert d_{XY} \rvert$ y $\lvert d_{YZ} \rvert \ge \lvert d_{XZ} \rvert$ y $$\begin{array}{ll} U_u = (y_2 z_0 - z_2 y_0) / d_{YZ} & V_v = (y_0 z_1 - y_1 z_0) / d_{YZ} \\ U_x = 0 & V_x = 0 \\ U_y = (z_2 - z_0) / d_{YZ} & V_y = (z_0 - z_1) / d_{YZ} \\ U_z = (y_0 - y_2) / d_{YZ} & V_z = (y_1 - y_0) / d_{YZ} \end{array}$$

Utilizando las ocho constantes anteriores, tenemos una función que transforma cualquier $(x, y, z)$ a las coordenadas planas $(u, v)$ : $$\begin{array}{ll} u = U_u + x U_x + y U_y + z U_z \\ v = V_v + x V_x + y V_y + z V_z \end{array}\tag{2}\label{2}$$

Utilice $\eqref{2}$ para transformar las coordenadas del punto final del segmento de la línea, de modo que $( u_0 , v_0 )$ es el punto de partida, y $( u_1 , v_1 )$ es el punto final: $$\begin{array}{l} u_0 = U_u + x_{start} U_x + y_{start} U_y + z_{start} U_z \\ v_0 = V_v + x_{start} V_x + y_{start} V_y + z_{start} V_z \\ u_1 = U_u + x_{end} U_x + y_{end} U_y + z_{end} U_z \\ v_1 = V_v + x_{end} V_x + y_{end} V_y + z_{end} V_z \end{array} \tag{3}\label{3}$$ Tenga en cuenta que sólo son válidos si el segmento de línea es coplanario al triángulo.

Para encontrar el segmento de línea y las intersecciones de las aristas, parametrizamos la línea utilizando $t \in \mathbb{R}$ , $0 \le t \le 1$ para que $t = 0$ en un extremo, y $t = 1$ en el otro. Se trata de una interpolación lineal directa, es decir $$\begin{array}{l} u = (1 - t) u_0 + t u_1 \\ v = (1 - t) v_0 + t v_1 \end{array}$$ Esto es útil, porque sólo tenemos que encontrar (y luego verificar) cada solución en una sola variable, el parámetro de línea $t$ .

El triángulo tiene tres aristas que el segmento de línea puede intersecar. Para verificar el punto de intersección, debemos encontrar el $t$ correspondiente al punto de intersección. Cuando $t$ se conoce, se pueden calcular trivialmente las coordenadas 3D correspondientes a la intersección: $$\begin{array}{ll} x = (1 - t) x_{start} + t x_{end} \\ y = (1 - t) y_{start} + t y_{end} \\ z = (1 - t) z_{start} + t z_{end} \end{array}\tag{4}\label{4}$$

A continuación, comprobamos los posibles casos, de uno en uno (pero en el orden que quieras):

  1. Si $u_0 = u_1 = 0$ el segmento de línea es paralelo a la arista desde $( x_0 , y_0 , z_0 )$ a $( x_2 , y_2 , z_2 )$ .

    Si $v_0 \le 0$ y $v_1 \gt 0$ o si $v_0 \gt 0$ y $v_1 \le 0$ el segmento de línea interseca el triángulo en el vértice $( x_0 , y_0 , z_0 )$ .

    Si $v_0 \le 1$ y $v_1 \gt 1$ o si $v_0 \gt 1$ y $v_1 \le 1$ el segmento de línea interseca el triángulo en el vértice $( x_2 , y_2 , z_2 )$ .

    Si ambos $0 \le v_0 \le 1$ y $0 \le v_1 \le 1$ entonces todo el segmento de línea está contenido en esta arista.
     

  2. Si $v_0 = v_1 = 0$ el segmento de línea es paralelo a la arista desde $( x_0 , y_0 , z_0 )$ a $( x_1 , y_1 , z_1 )$ .

    Si $u_0 \le 0$ y $u_1 \gt 0$ o si $u_0 \gt 0$ y $u_1 \le 0$ el segmento de línea interseca el triángulo en el vértice $( x_0 , y_0 , z_0 )$ .

    Si $u_0 \le 1$ y $u_1 \gt 1$ o si $u_0 \gt 1$ y $u_1 \le 1$ el segmento de línea interseca el triángulo en el vértice $( x_1 , y_1 , z_1 )$ .

    Si ambos $0 \le u_0 \le 1$ y $0 \le u_1 \le 1$ entonces todo el segmento de línea está contenido en esta arista.
     

  3. Si $u_0 + v_0 = 1$ y $u_1 + v_1 = 1$ el segmento de línea es paralelo a la arista de $( x_1 , y_1 , z_1 )$ a $( x_2 , y_2 , z_2 )$ (es decir, $u + v = 1$ ).

    Si $u_0 \lt 0$ y $u_1 \ge 0$ o si $u_0 \ge 0$ y $u_1 \lt 0$ la línea interseca la arista en el vértice $( x_2 , y_2 , z_2 )$ .

    Si $u_0 \gt 1$ y $u_1 \le 1$ o si $u_0 \le 1$ y $u_1 \gt 1$ la línea interseca la arista en el vértice $( x_1 , y_1 , z_1 )$ .

    Si $0 \le u_0 \le 1$ , $0 \le v_0 \le 1$ , $0 \le u_1 \le 1$ y $0 \le v_1 \le 1$ El segmento de línea completo está contenido en esta arista.
     

  4. Si $u_0 \le 0$  y $u_1 \gt 0$ o si $u_0 \ge 0$ y $u_1 \lt 0$ el segmento de línea puede intersecar la arista desde $( x_0 , y_0 , z_0 )$ a $( x_1 , y_1, z_1 )$ (es decir, $u = 0$ ).

    Calcular $$t_u = \frac{ u_0 }{ u_0 - u_1 }$$ Si $$0 \le t_u \le 1$$ y $$0 \le ( 1 - t_u ) v_0 + t_u v_1 \le 1$$ hay una intersección entre el segmento de línea y esta arista, en $t_u$ .
     

  5. Si $v_0 \le 0$ y $v_1 \gt 0$ o si $v_0 \ge 0$ y $v_1 \lt 0$ el segmento de línea puede intersecar la arista desde $( x_0 , y_0 , z_0 )$ a $( x_2 , y_2, z_2 )$ (es decir, $v = 0$ ).

    Calcular $$t_v = \frac{ v_0 }{ v_0 - v_1 }$$ Si $$0 \le t_v \le 1$$ y $$0 \le ( 1 - t_v ) u_0 + t_v u_1 \le 1$$ hay una intersección entre el segmento de línea y esta arista, en $t_v$ .
     

  6. Si $1 - u_0 - v_0 \ge u_1 - u_0 + v_1 - v_0 \gt 0$ o si $u_0 + v_0 - 1 \ge u_0 - u_1 + v_0 - v_1 \gt 0$ el segmento de línea puede intersecar la arista desde $( x_1 , y_1 , z_1 )$ a $( x_2 , y_2 , z_2 )$ (es decir, $u + v = 1$ ).

    Calcular $$t_{uv} = \frac{1 - u_0 - v_0}{u_1 - u_0 + v_1 - v_0}$$ Si $$0 \le t_{uv} \le 1$$ y $$0 \le ( 1 - t_{uv} ) u_0 + t_{uv} u_1 \le 1$$ y $$0 \le ( 1 - t_{uv} ) v_0 + t_{uv} v_1 \le 1$$ hay una intersección entre el segmento de línea y esta arista, en $t_{uv}$ .

Cada parte y paso anterior están escritos de una forma que debería garantizar la estabilidad numérica. Por ejemplo, $(1 - t) u_0 + t u_1 = u_0 + t (u_1 - u_0)$ pero el lado izquierdo da exactamente $u_1$ en $t = 1$ mientras que el lado derecho puede diferir debido a la cancelación del dominio, si $u_1$ y $u_0$ difieren mucho en magnitud.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X