---
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}$.

[**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)$.

[**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:

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:

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.

```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**]()