--- tags: geometry, lines --- # Líneas ## Definición :::info :information_source: **Definición:** Una **línea** es el conjunto de puntos que se mueven en una dirección determinada y de forma indefinida en sus ambos extremos. ::: Existen varias formas de representar una línea matemáticamente, las tres más comunes son: - Punto-pendiente: $y=mx+b$. - Forma general: $ax+by=c$. - Forma paramétrica o vectorial: $\vec{r} = \vec{a} + t\vec{v}$, donde $\vec{r}=(x,y)$ es el vector de posición de toda la línea. Por comodidad y por la facilidad de uso que ofrece, usaremos la tercer forma de aquí en adelante. Supongamos que la línea pasa por un punto fijo $\vec{a}$ y un vector paralelo a ella es $\vec{v}$. Vemos que la tarea de $\vec{a}$ es trasladar la línea y la tarea de $\vec{v}$ es darle la dirección a la línea. Sea $\vec{r}$ el vector de posición de cada uno de los puntos de la línea, es decir, su flecha barrerá toda la línea. Como solo podemos movernos en la dirección de $\vec{v}$, cualquier múltiplo escalar de $\vec{v}$ estará sobre la línea. Entonces, $\vec{r} = \vec{a} + t\vec{v}$, para toda $t \in \mathbb{R}$. ![](https://i.imgur.com/wwDremM.png) [**Ejemplo interactivo**](https://www.geogebra.org/classic/vafkgwqk) Ahora supongamos que en lugar de un punto y un vector paralelo, nos dan dos puntos distintos $A$ y $B$ y queremos hallar la ecuación de la línea que pasa por ellos. Un vector paralelo es simplemente el vector de desplazamiento $\overrightarrow{AB}$, es decir, $\vec{v} = \vec{B} - \vec{A}$. Podemos tomar tanto a $\vec{A}$ como a $\vec{B}$ como puntos fijos. Por lo tanto, la ecuación de la línea queda como $\vec{r} = \vec{A} + t\left(\vec{B} - \vec{A}\right)$. ![](https://i.imgur.com/HOlKyXw.png) [**Ejemplo interactivo**](https://www.geogebra.org/classic/gy9q5bdx) Por último, es fácil ver que una ecuación de la forma $y=mx+b$ es equivalente a $\vec{r}=(x,y)=(x,mx+b)=(x,mx)+(0,b)=\underbrace{x}_{t}\underbrace{(1,m)}_{\vec{v}}+\underbrace{(0,b)}_{\vec{a}}$. De forma similar, la ecuación $ax+by=c$ es equivalente a $\vec{r}=(0, \frac{c}{b}) + t(-b, a)$ si $b \neq 0$. ## Proyección y reflexión ### Proyección Si tenemos un punto $P$ y una línea $\vec{r} = \vec{a} + t\vec{v}$, hallar la proyección de $P$ sobre dicha línea es fácil, pues ya sabemos cómo proyectar un vector sobre otro, solo hay que hacer unos pequeños ajustes: ![](https://i.imgur.com/ZAzXdKe.png) Sea $P'$ la proyección de $P$ sobre la línea. Vemos que realmente lo que hay que proyectar es el vector de desplazamiento $\overrightarrow{aP}$ sobre el vector $\vec{v}$, pero eso es justamente $\vec{p} = proy_{\hat{v}} \left(\overrightarrow{aP}\right)$. Finalmente, para obtener $\vec{P'}$ solo hay que sumar el punto $\vec{a}$ con el desplazamiento $\vec{p}$, o sea: $\vec{P'} = \vec{a} + proy_{\hat{v}} \left(\overrightarrow{aP}\right)$. Usando la función ``proj()`` que ya teníamos, programar esto es muy sencillo: ```cpp point proj_line(point a, point v, point p){ return a + proj(p - a, v); } ``` ### Reflexión Ahora supongamos que la línea es un espejo y queremos hallar un punto $P'$ tal que esté del otro lado y tenga la misma distancia a la línea que el punto original. Entonces diremos que $P'$ es la reflexión de $P$ sobre esta línea: ![](https://i.imgur.com/D15nEyr.png) Casi es el mismo dibujo que el que usamos en la proyección, solo invertimos el sentido de $\vec{d}$ y lo dibujamos dos veces para ver en dónde quedará $\vec{P'}$. Del dibujo vemos que $\vec{d} = \vec{p} - \overrightarrow{aP}$. Ya tenemos $\vec{p}$, y del dibujo vemos que $\vec{P'} = \vec{a} + \vec{p} + \vec{d}$, entonces $\vec{P'} = 2\vec{a} - \vec{P} + 2proy_{\hat{v}} \left(\overrightarrow{aP}\right)$. De nuevo, programar esto es muy sencillo: ```cpp point reflection_line(point a, point v, point p){ return a*2 - p + proj(p - a, v)*2; } ``` ## Distancia punto-línea Ahora queremos hallar la mínima distancia de un punto $P$ a la recta $\vec{r} = \vec{a} + t\vec{v}$. Realmente ya lo tenemos, pues de los dos dibujos anteriores, es simplemente la longitud del vector $\vec{d}$, el cual era $\vec{d}=proy_{\hat{v}} \left(\overrightarrow{aP}\right) - \overrightarrow{aP}$. Entonces, el código queda así: ```cpp double distance_point_line(point a, point v, point p){ return (proj(p - a, v) - (p - a)).length(); } ``` Pero resulta que hay una manera más fácil: si nos fijamos en el triángulo rectángulo que se forma y si $\theta$ es el ángulo entre el vector $\vec{v}$ y el vector $\overrightarrow{aP}$, por definición de seno tenemos que $\left\lVert{\vec{d}}\right\rVert = \left\lVert{\overrightarrow{aP}}\right\rVert \sin \theta$. Y si combinamos la propiedad del producto cruz, es decir, $\vec{v} \times \overrightarrow{aP} = \left\lVert{\vec{v}}\right\rVert \left\lVert{\overrightarrow{aP}}\right\rVert \sin \theta$, entonces $\left\lVert{\vec{d}}\right\rVert = \dfrac{\vec{v} \times \overrightarrow{aP}}{\left\lVert{\vec{v}}\right\rVert}$. La expresión anterior puede ser negativa si $\vec{P}$ está del lado derecho de la línea, por lo que se le conoce como la **distancia signada**. Su valor absoluto siempre será correcto, así que si solo queremos la distancia, simplemente sacamos valor absoluto. ```cpp double distance_point_line(point a, point v, point p){ return abs(v.cross(p - a)) / v.length(); } double signed_distance_point_line(point a, point v, point p){ return v.cross(p - a) / v.length(); } ``` ## Ordenar puntos respecto a una línea Dada una línea $\vec{r} = \vec{a} + t\vec{v}$ y varios puntos que **pertenecen** a ella, vamos a determinar en qué orden aparecen, es decir, los vamos a ordenar tal como vayan apareciendo sobre la línea, siguiendo la dirección de $\vec{v}$. Para esto nos sirve el valor de $t$ asociado a cada punto. Supongamos que existe alguna $t_i$ tal que $\vec{p_i} = \vec{a} + t_i\vec{v}$, entonces $t_i = \dfrac{\left(\vec{p_i} - \vec{a}\right) \cdot \vec{v}}{\vec{v} \cdot \vec{v}}$. Es decir, un punto $p_i$ aparecerá antes que $p_j$ si y solo si $t_i < t_j$. Pero resulta que para efectos de comparación, solo necesitamos el valor de $\vec{p_i} \cdot \vec{v}$, pues tanto $-\vec{a} \cdot \vec{v}$ como $\vec{v} \cdot \vec{v}$ son constantes y no afectan el orden. ![](https://i.imgur.com/iEwB9p2.png) ```cpp void sort_along_line(point a, point v, vector<point> & points){ sort(points.begin(), points.end(), [](point u, point w){ return u.dot(v) < w.dot(v); }); } ``` **Pregunta:** ¿Cómo se comporta la función anterior si los puntos no pertenecen a la línea? :::spoiler **Respuesta** Notemos que $t_i$ no es más que la proyección del punto $\vec{p_i}$ sobre la línea, entonces esta función ordenará los puntos de acuerdo a cómo sus proyecciones vayan apareciendo sobre la línea. ::: [**Ejemplo interactivo**](https://www.geogebra.org/classic/jyzg38rr) ## Intersección de líneas Sean $\vec{r_1} = \vec{a_1} + t\vec{v_1}$ y $\vec{r_2} = \vec{a_2} + u\vec{v_2}$ dos líneas (notemos que usamos dos distintos parámetros, $t$ y $u$, para que se dibujen de forma independiente). Queremos saber si se intersectan, y si lo hacen, en qué punto. Vamos a tratar de igualar ambas expresiones para hallar dicho punto: $$ \begin{align} \vec{a_1} + t\vec{v_1} &= \vec{a_2} + u\vec{v_2} \\ \vec{a_1} \times \vec{v_2} + t\vec{v_1} \times \vec{v_2} &= \vec{a_2} \times \vec{v_2} + u\vec{v_2} \times \vec{v_2} \\ t\vec{v_1} \times \vec{v_2} &= \left(\vec{a_2} - \vec{a_1}\right)\times \vec{v_2} \\ t &= \dfrac{\left(\vec{a_2} - \vec{a_1}\right) \times \vec{v_2}}{\vec{v_1} \times \vec{v_2}} \end{align} $$ Ya que tenemos el valor de $t$, lo sustituimos en $\vec{r_1}$ para hallar el punto de intersección. Sin embargo, si $\vec{v_1} \times \vec{v_2} = 0$, habría división entre cero. Geométricamente significa que las dos líneas son paralelas, entonces puede que nunca se intersecten o se intersecten infinitamente (son la misma línea). - Es fácil ver que si $\overrightarrow{a_1 a_2} \times \vec{v_2} = 0$ las dos líneas son en realidad la misma, por lo que en este caso hay infinitos puntos de intersección. - En caso de que $\overrightarrow{a_1 a_2} \times \vec{v_2} \neq 0$, las dos líneas son paralelas y nunca se intersectan. Programemos dos funciones: una que solo nos diga cuántas intersecciones hay entre dos líneas, y otra que nos diga el punto de intersección asumiendo que existe y es único. ```cpp int intersectLinesInfo(point a1, point v1, point a2, point v2){ double det = v1.cross(v2); if(det == 0){ if((a2 - a1).cross(v2) == 0){ return -1; //infinity points }else{ return 0; //no points } }else{ return 1; //single point } } point intersectLines(point a1, point v1, point a2, point v2){ return a1 + v1 * ((a2 - a1).cross(v2) / v1.cross(v2)); } ``` [**Ejemplo interactivo**]()