---
# System prepended metadata

title: Producto punto
tags: [geometry, ' dot-product']

---

---
tags: geometry, dot-product
---

# Producto punto

## Definición
Además de la multiplicación por un escalar, existen otras dos operaciones básicas entre vectores que también tienen que ver con "productos". De hecho, estos productos son igual o incluso más importantes que las operaciones que ya vimos.

:::info
:information_source: **Definición:** Sean $\vec{a}=(a_x, a_y)$ y $\vec{b}=(b_x, b_y)$ dos vectores. Definimos al **producto punto** o **producto escalar** de $\vec{a}$ con $\vec{b}$ como:
$$
\vec{a} \cdot \vec{b} = a_x b_x + a_y b_y
$$
:::

Es decir, sumamos los productos de las coordenadas correspondientes entre los dos vectores. Hay que notar que **el resultado es un escalar, no otro vector**. Pero, ¿para qué me servirá tener un producto definido así? Ya lo veremos, pero primero veamos la implementación.

## Implementación
Vamos a agregar a nuestra estructura ``point`` un método para que calcule el producto punto con otro vector:
```cpp
double dot(const point & p) const{return x * p.x + y * p.y;}
```

Preguntas:
- Si los dos vectores tienen coordenadas enteras, ¿su producto punto también lo será?
:::spoiler **Respuesta**
Sí, ya que solo estamos multiplicando y sumando.
:::
- Si el valor absoluto de las coordenadas de los vectores es menor o igual a $M$, ¿podemos poner también un límite en el producto punto entre ellos? ¿Esto qué consecuencias tiene al escoger el tipo de dato para las coordenadas?
:::spoiler **Respuesta**
Se cumple que $\lvert \vec{a} \cdot \vec{b} \rvert \leq 2M^2$, y se logra con $\vec{a}=(M,M)$ y $\vec{b}=(M,M)$, o con $\vec{a}=(-M,-M)$ y $\vec{b}=(M,M)$. Esto quiere decir que si guardamos las coordenadas de los puntos en un cierto tipo de dato, el producto punto necesitará el doble de capacidad para almacenarse. Por ejemplo, es común ver en los límites que $\lvert M \rvert \leq 10^9$, entonces lo recomendable es almacenar las coordenadas en un ``long long int`` para evitar desbordamientos al usar el producto punto.
:::

Ejemplo:
```cpp
point a(2, 3), b(-1, 4);
cout << a.dot(b) << "\n"; // Debería imprimir 10
```

## Propiedades
El producto punto cumple con las siguientes propiedades:
- **Conmutativa:** $\vec{a} \cdot \vec{b} = \vec{b} \cdot \vec{a}$
- **Distributiva:** $\left( s\vec{a} + t\vec{b} \right) \cdot \vec{c} = s\left( \vec{a} \cdot \vec{c} \right) + t \left( \vec{b} \cdot \vec{c} \right)$
- $\vec{a} \cdot \vec{a} \geq 0$. Además $\vec{a} \cdot \vec{a} = 0$ si y solo si $\vec{a} = \vec{0}$
- $\vec{0} \cdot \vec{a} = 0$
- $\left\lVert{\vec{a}}\right\rVert = \sqrt{\vec{a} \cdot \vec{a}}$. Esta propiedad es muy útil y nos da un primer acercamiento a alguna interpretación geométrica del producto punto. Es muy común que en los problemas se use la propiedad equivalente: $\vec{a} \cdot \vec{a} = \left\lVert{\vec{a}}\right\rVert^2$.

## Ángulo entre vectores
Sean $\vec{a}$ y $\vec{b}$ dos vectores. Consideremos el siguiente triángulo $\triangle ABC$ formado por los vectores $\vec{a}$, $\vec{b}$ y $\vec{a}-\vec{b}$, donde $\theta$ es el ángulo entre los vectores $\vec{a}$ y $\vec{b}$:

![](https://i.imgur.com/sAYZMvS.png)

Al aplicar ley de cosenos tenemos que:
$$
\begin{align}
\left\lVert{\vec a - \vec b}\right\rVert^2 &= \left\lVert{\vec a }\right\rVert^2 + \left\lVert{\vec b}\right\rVert^2 - 2 \left\lVert{\vec a }\right\rVert \left\lVert{\vec b }\right\rVert \cos\theta \\
\left(\vec a - \vec b \right) \cdot \left(\vec a - \vec b \right) &= \vec a  \cdot \vec a + \vec b \cdot \vec b - 2\left\lVert{\vec a}\right\rVert \left\lVert{\vec b}\right\rVert \cos\theta \\
\vec a \cdot \vec a - 2\vec a \cdot \vec b + \vec b \cdot \vec b &= \vec a \cdot \vec a + \vec b \cdot \vec b - 2\left\lVert{\vec a}\right\rVert \left\lVert{\vec b}\right\rVert \cos\theta \\
-2\vec a \cdot \vec b &= -2\left\lVert{\vec a}\right\rVert \left\lVert{\vec b}\right\rVert \cos\theta \\
\vec a \cdot \vec b &= \left\lVert{\vec a}\right\rVert \left\lVert{\vec b}\right\rVert \cos\theta
\end{align}
$$

La relación que obtuvimos ahora sí nos dice la verdadera interpretación geométrica del producto punto entre dos vectores, pues relaciona sus longitudes y el ángulo entre ellos.

- Podemos despejar el coseno del ángulo entre los vectores: $\cos \theta = \dfrac{\vec{a} \cdot \vec{b}}{\left\lVert{\vec a}\right\rVert \left\lVert{\vec b}\right\rVert}$. Y como el rango de la función $\arccos(x)$ es $[0, \pi]$, usando esta fórmula siempre obtendremos el ángulo correcto (hay que notar que por lo general siempre hay dos ángulos entre cualquier par de vectores, pero siempre nos quedamos con el menor, que es menor o igual a $180^\circ$).
- Un caso especial es cuando $\theta=90^\circ$, es decir, los dos vectores forman un ángulo recto entre ellos. En este caso $\vec{a} \cdot \vec{b} = 0$, y decimos que $\vec{a}$ y $\vec{b}$ son **ortogonales**.
- Es por eso que el producto punto mide qué tan "paralelos" son dos vectores.

## Proyección de un vector sobre otro
Veamos otra aplicación del producto punto:
- Sea $\vec{a}$ un vector y $\hat{v}$ un vector unitario. Queremos hallar la *proyección* $\vec{p}$ de $\vec{a}$ sobre la línea que genera la dirección de $\hat{v}$.

![](https://i.imgur.com/C56Jw41.png)

- Primero vamos a hallar la longitud de $\vec{p}$. Por definición de coseno en el triángulo rectángulo que se forma, tenemos que $\left\lVert{\vec{p}}\right\rVert = \left\lVert{\vec{a}}\right\rVert \cos \theta$.
- Pero por la propiedad del producto punto, sabemos que $\cos \theta = \dfrac{\vec{a} \cdot \hat{v}}{\left\lVert{\vec{a}}\right\rVert \left\lVert{\hat{v}}\right\rVert}$.
- Combinando, tenemos que $\left\lVert{\vec{p}}\right\rVert = \vec{a} \cdot \hat{v}$.
- Por último, de la figura vemos que la dirección de $\vec{p}$ es la misma que la de $\hat{v}$, así que podemos determinar completamente el vector $\vec{p}$ y queda como: $\vec{p} = \left\lVert{\vec{p}}\right\rVert \hat{v} = \left(\vec{a} \cdot \hat{v}\right) \hat{v}$.

:::info
:information_source: **Definición:** Sean $\vec{a}$ y $\hat{v}$ vectores. Definimos a la **proyección de $\vec{a}$ sobre $\hat{v}$** como $proy_{\hat{v}}(\vec{a}) = \left(\vec{a} \cdot \hat{v}\right) \hat{v}$.
:::

- Pregunta, ¿cómo sería la fórmula si $\vec{v}$ no fuera unitario?
:::spoiler **Respuesta**
Si $\vec{v}$ no es unitario, basta con hallar su vector unitario: $\hat{v}=\dfrac{\vec{v}}{\left\lVert{\vec{v}}\right\rVert}$, y sustituirlo en la fórmula anterior:
$$
\begin{align}
proy_{\hat{v}}(\vec{a}) &= \left( \vec{a} \cdot \dfrac{\vec{v}}{\left\lVert{\vec{v}}\right\rVert} \right) \dfrac{\vec{v}}{\left\lVert{\vec{v}}\right\rVert} \\
&= \left(\dfrac{\vec{a} \cdot \vec{v}}{\left\lVert{\vec{v}}\right\rVert^2}\right)\vec{v}
\end{align}
$$
:::

[**Ejemplo interactivo**](https://www.geogebra.org/classic/bmfcrtnr)

## Implementación parte 2
Ángulo entre $\vec{a}$ y $\vec{b}$:
```cpp
double angleBetween(point a, point b){
	double x = a.dot(b) / a.length() / b.length();
	return acos(max(-1.0, min(1.0, x)));
}
```

Verificar si $\vec{a}$ y $\vec{b}$ son ortogonales:
```cpp
bool isPerp(point a, point b){
	return a.dot(b) == 0;
}
```

Proyección de $\vec{a}$ sobre la dirección de $\vec{v}$:
```cpp
point proj(point a, point v){
	v = v / v.unit();
	return v * a.dot(v);
}
```


