Primero, el esquema anterior.
Según la ilustración, el segmento de línea a se representa como los puntos finales a1 y a2, y el segmento de línea b se representa como los puntos finales b1 y b2. Para utilizar la relación de producto cruzado de los vectores, los puntos finales del segmento de línea se consideran como cuatro vectores, y los vectores se representan en negrita a continuación. De acuerdo con las operaciones vectoriales Se puede ver que
a = a2-a1,
b = b2-b1.
Exprese el segmento de recta como una ecuación paramétrica:
a = a1 + ta
b = b1 + ub
donde los parámetros t, u toman el valor [0,1]
La intersección de dos segmentos de línea tiene la siguiente relación:
a1 + ta = b1 + ub
. Multiplica ambos lados de la ecuación anterior por b al mismo tiempo para obtener:
(a1 + ta) xb = (b1 + ub) xb
Dado que bxb = 0, podemos obtener
a1 xb + taxb = b1 xb
resuelve el parámetro t
t = (b1-a1) xb / (axb) lo
mismo, resuelve el parámetro u
u = ax (a1-b1) / (axb)
Cuando 0 <= t <= 1 y 0 <= u <= 1, los dos segmentos de recta tienen intersecciones.
Sustituyendo en la ecuación paramétrica del segmento de recta a, puede obtener las coordenadas de intersección del segmento de recta:
a1 + ta
usa el intermedio variable en la fórmula anterior La representación del punto final del segmento de línea original puede obtener el punto de intersección representado por el punto final del segmento de línea.
codigo 1
// Devuelve 1 si las líneas se cruzan, en caso contrario 0. Además, si las líneas
// se cruzan, el punto de intersección puede almacenarse en los flotadores i_x e i_y.
char get_line_intersection (float p0_x, float p0_y, float p1_x, float p1_y,
float p2_x, float p2_y, float p3_x, float p3_y, float * i_x, float * i_y)
{ float s1_x, s1_y, s2_y; s1_x = p1_x - p0_x; s1_y = p1_y - p0_y; s2_x = p3_x - p2_x; s2_y = p3_y - p2_y;
float s, t;
s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);
if (s> = 0 && s <= 1 && t> = 0 && t <= 1)
{ // Colisión detectada if (i_x! = NULL) * i_x = p0_x + (t * s1_x); if (i_y! = NULL) * i_y = p0_y + (t * s1_y); return 1; }
return 0; // Sin colisión
}
código 2
Versión optimizada para excluir segmentos de línea paralelos y evitar errores de precisión
int get_line_intersection (float p0_x, float p0_y, float p1_x, float p1_y,
float p2_x, float p2_y, float p3_x, float p3_y, float * i_x, float * i_y)
{ float s02_x, s02x, s10_y, s_n , t_numer, denom, t; s10_x = p1_x - p0_x; s10_y = p1_y - p0_y; s32_x = p3_x - p2_x; s32_y = p3_y - p2_y;
denom = s10_x * s32_y-s32_x * s10_y;
if (denom == 0) //
Retorno paralelo o colineal 0; //
Colineal bool denomPositive = denom> 0;
s02_x = p0_x-p2_x;
s02_y = p0_y-p2_y;
s_numer = s10_x * s02_y-s10_y * s02_x;
if ((s_numer <0) == denomPositive) // Los parámetros deben ser mayores o iguales a 0 y menores o iguales a 1, y el numerador y el denominador deben ser el mismo Número y el numerador es menor o igual que el denominador
devuelve 0; // Sin colisión
t_numer = s32_x * s02_y - s32_y * s02_x;
if ((t_numer <0) == denomPositive)
return 0; // No hubo colisión
if (fabs (s_numer)> fabs (denom) || fabs (t_numer)> fabs (denom))
return 0; // Sin colisión
// Colisión detectada
t = t_numer / denom;
si (i_x! = NULL)
* i_x = p0_x + (t * s10_x);
if (i_y! = NULL)
* i_y = p0_y + (t * s10_y);
return 1;
}