30. Vector unitario

Un vector unitario tiene norma igual a uno y representa una dirección sin incorporar una magnitud específica. Normalizar separa la orientación de un vector de su tamaño.

30.1 Introducción

En muchas aplicaciones interesa conocer hacia dónde apunta un vector sin que su longitud influya. Por ejemplo, una dirección de movimiento debe poder combinarse después con cualquier rapidez.

Los vectores unitarios resuelven este problema: conservan la dirección y el sentido, pero tienen longitud exactamente igual a uno.

u es unitario ⇔ ||u|| = 1

30.2 Definición

Un vector u de ℝn es unitario si su norma euclídea vale 1. También se lo denomina vector normalizado.

VectorNorma¿Es unitario?
(1, 0)1
(0, −1, 0)1
(3/5, 4/5)1
(1, 1)√2No
(0, 0)0No

30.3 Vectores unitarios canónicos

Los vectores canónicos tienen una componente igual a 1 y las demás iguales a cero:

En ℝ2: e1 = (1, 0), e2 = (0, 1)
En ℝ3: e1 = (1, 0, 0), e2 = (0, 1, 0), e3 = (0, 0, 1)
const e1 = [1, 0, 0];
const e2 = [0, 1, 0];
const e3 = [0, 0, 1];

console.log(Math.hypot(...e1), Math.hypot(...e2), Math.hypot(...e3));
// 1, 1, 1

30.4 Normalización de un vector

Normalizar un vector no nulo v consiste en dividirlo por su norma:

v̂ = v / ||v||

La división significa multiplicar cada componente por 1/||v||. Como la norma es positiva, el sentido del vector original no cambia.

Si v = (v1, ..., vn), entonces v̂ = (v1/||v||, ..., vn/||v||).

30.5 Ejemplo de normalización en ℝ2

Para v = (3, 4), su norma es 5. Dividimos cada componente por 5:

v̂ = (3/5, 4/5) = (0.6, 0.8)
||v̂|| = √(0.62 + 0.82) = 1
const v = [3, 4];
const longitud = Math.hypot(...v);
const unitario = v.map(componente => componente / longitud);

console.log(unitario);             // [0.6, 0.8]
console.log(Math.hypot(...unitario)); // 1

30.6 Ejemplo de normalización en ℝ3

Para v = (2, −3, 6), ||v|| = 7. Su vector unitario asociado es:

v̂ = (2/7, −3/7, 6/7)
const v = [2, -3, 6];
const longitud = Math.hypot(...v);
const direccion = v.map(valor => valor / longitud);

console.log(direccion);
console.log(Math.hypot(...direccion)); // aproximadamente 1

30.7 Función para normalizar

Una función reutilizable debe calcular la norma una sola vez y crear un arreglo nuevo para no modificar el vector recibido.

function normalizar(vector) {
  const longitud = Math.hypot(...vector);
  if (longitud === 0) return null;
  return vector.map(valor => valor / longitud);
}

const original = [3, 4];
console.log(normalizar(original)); // [0.6, 0.8]
console.log(original);             // [3, 4]

30.8 El vector cero no puede normalizarse

La norma del vector cero es 0. La fórmula exigiría dividir cada componente por cero, por lo que no existe una dirección unitaria asociada.

0 / ||0|| = 0/0: operación indefinida
const cero = [0, 0, 0];
const longitud = Math.hypot(...cero);

if (longitud === 0) {
  console.log("El vector cero no tiene una dirección normalizada");
}

30.9 Normalización con tolerancia

En cálculos decimales, un vector que debería ser cero puede contener residuos diminutos. Una tolerancia evita amplificar ese ruido al dividir por una norma extremadamente pequeña.

function normalizarSeguro(vector, tolerancia = 1e-12) {
  if (!Array.isArray(vector) || !vector.length || !vector.every(Number.isFinite)) {
    throw new Error("Vector inválido");
  }
  const longitud = Math.hypot(...vector);
  return longitud <= tolerancia
    ? null
    : vector.map(valor => valor / longitud);
}

console.log(normalizarSeguro([1e-15, 0])); // null
console.log(normalizarSeguro([5, 0]));     // [1, 0]

La tolerancia adecuada depende de la escala y las unidades del problema.

30.10 La normalización conserva la dirección

v̂ es un múltiplo positivo de v, por lo que ambos apuntan en la misma dirección y sentido. Solo cambia la longitud.

const v = [-6, 8];
const longitud = Math.hypot(...v);
const unitario = v.map(valor => valor / longitud);

console.log(unitario); // [-0.6, 0.8]
console.log(unitario.map(valor => valor * longitud)); // [-6, 8]

Si se multiplica el unitario por una longitud positiva, se recupera un vector de la misma dirección con el tamaño elegido.

30.11 Separar dirección y magnitud

Todo vector no nulo puede descomponerse como:

v = ||v|| v̂
ParteTipoSignificado
||v||EscalarTamaño
Vector unitarioDirección y sentido

Esta separación es fundamental en física, gráficos y simulación.

30.12 Dirección entre dos puntos

Para obtener una dirección unitaria desde A hasta B, primero se calcula B − A y luego se normaliza.

function direccionEntre(A, B, tolerancia = 1e-12) {
  if (A.length !== B.length) throw new Error("Dimensiones diferentes");
  const desplazamiento = B.map((valor, i) => valor - A[i]);
  const distancia = Math.hypot(...desplazamiento);
  return distancia <= tolerancia
    ? null
    : desplazamiento.map(valor => valor / distancia);
}

console.log(direccionEntre([1, 1], [4, 5])); // [0.6, 0.8]

Si A y B coinciden, no existe una dirección preferente y la función devuelve null.

30.13 Movimiento con rapidez constante

Una dirección unitaria puede multiplicarse por una rapidez s y un intervalo Δt. El desplazamiento resultante tiene longitud sΔt.

posiciónNueva = posición + dirección · rapidez · Δt
function mover(posicion, direccionUnitaria, rapidez, deltaTiempo) {
  return posicion.map(
    (valor, i) => valor + direccionUnitaria[i] * rapidez * deltaTiempo
  );
}

const posicion = [10, 5];
const direccion = [0.6, 0.8];
console.log(mover(posicion, direccion, 5, 2)); // [16, 13]

30.14 Dirección a partir de un ángulo

En el plano, el ángulo θ medido desde el eje x positivo determina el vector unitario:

u(θ) = (cos θ, sen θ)

La identidad cos2θ + sen2θ = 1 garantiza que su norma sea uno.

function direccionDesdeAngulo(grados) {
  const radianes = grados * Math.PI / 180;
  return [Math.cos(radianes), Math.sin(radianes)];
}

const direccion = direccionDesdeAngulo(30);
console.log(direccion);
console.log(Math.hypot(...direccion)); // 1

30.15 Dirección mediante dos ángulos en ℝ3

Una convención común utiliza un ángulo horizontal θ y una elevación φ:

u = (cos φ cos θ, sen φ, cos φ sen θ)
function direccion3D(horizontal, elevacion) {
  const theta = horizontal * Math.PI / 180;
  const phi = elevacion * Math.PI / 180;
  return [
    Math.cos(phi) * Math.cos(theta),
    Math.sin(phi),
    Math.cos(phi) * Math.sin(theta)
  ];
}

const direccion = direccion3D(45, 30);
console.log(direccion);
console.log(Math.hypot(...direccion)); // aproximadamente 1

Los nombres y orientaciones de los ángulos varían entre motores gráficos; siempre debe documentarse la convención.

30.16 Limitar la magnitud de un vector

Para imponer una longitud máxima, se conserva el vector si ya está dentro del límite. Si lo supera, se normaliza y se multiplica por el máximo.

function limitarMagnitud(vector, maximo) {
  if (maximo < 0) throw new Error("El máximo no puede ser negativo");
  const longitud = Math.hypot(...vector);
  if (longitud <= maximo || longitud === 0) return [...vector];
  return vector.map(valor => valor / longitud * maximo);
}

console.log(limitarMagnitud([6, 8], 5)); // [3, 4]

Esta técnica se usa para limitar velocidad, fuerza, aceleración o desplazamiento.

30.17 Comprobar si un vector es unitario

Los errores de punto flotante hacen aconsejable comparar la norma con 1 mediante una tolerancia.

function esUnitario(vector, tolerancia = 1e-10) {
  return vector.length > 0 &&
    vector.every(Number.isFinite) &&
    Math.abs(Math.hypot(...vector) - 1) <= tolerancia;
}

console.log(esUnitario([0.6, 0.8])); // true
console.log(esUnitario([1, 1]));     // false

30.18 Aplicaciones y errores frecuentes

Los vectores unitarios se utilizan para direcciones de cámara, iluminación, normales de superficies, movimiento, rayos, fuerzas con magnitud separada y orientación de objetos.

Errores habituales:

  • Dividir el vector por la norma al cuadrado.
  • Normalizar el vector cero.
  • Calcular la norma nuevamente para cada componente.
  • Suponer que una dirección recibida ya es unitaria.
  • Modificar el vector original sin intención.
  • Usar una tolerancia desconectada de la escala del problema.
  • Confundir dirección unitaria con velocidad completa.

30.19 Qué debes recordar de este tema

  • Un vector unitario tiene norma igual a uno.
  • Normalizar v significa calcular v/||v||.
  • La normalización conserva dirección y sentido.
  • El vector cero no puede normalizarse.
  • Conviene usar una tolerancia para normas muy pequeñas.
  • Todo vector no nulo se descompone como v = ||v||v̂.
  • La dirección desde A hasta B es la normalización de B − A.
  • (cos θ, sen θ) es unitario para cualquier ángulo θ.

30.20 Conclusión

Normalizar permite separar una dirección de su magnitud y reutilizarla con diferentes velocidades, fuerzas o distancias. El tratamiento explícito del vector cero es indispensable para evitar resultados inválidos.

En el próximo tema estudiaremos el producto escalar, que relaciona vectores mediante sus componentes y permite medir alineación y ángulos.