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.
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.
Un vector u de ℝn es unitario si su norma euclídea vale 1. También se lo denomina vector normalizado.
| Vector | Norma | ¿Es unitario? |
|---|---|---|
| (1, 0) | 1 | Sí |
| (0, −1, 0) | 1 | Sí |
| (3/5, 4/5) | 1 | Sí |
| (1, 1) | √2 | No |
| (0, 0) | 0 | No |
Los vectores canónicos tienen una componente igual a 1 y las demás iguales a cero:
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
Normalizar un vector no nulo v consiste en dividirlo por su norma:
La división significa multiplicar cada componente por 1/||v||. Como la norma es positiva, el sentido del vector original no cambia.
Para v = (3, 4), su norma es 5. Dividimos cada componente por 5:
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
Para v = (2, −3, 6), ||v|| = 7. Su vector unitario asociado es:
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
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]
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.
const cero = [0, 0, 0];
const longitud = Math.hypot(...cero);
if (longitud === 0) {
console.log("El vector cero no tiene una dirección normalizada");
}
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.
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.
Todo vector no nulo puede descomponerse como:
| Parte | Tipo | Significado |
|---|---|---|
| ||v|| | Escalar | Tamaño |
| v̂ | Vector unitario | Dirección y sentido |
Esta separación es fundamental en física, gráficos y simulación.
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.
Una dirección unitaria puede multiplicarse por una rapidez s y un intervalo Δt. El desplazamiento resultante tiene longitud sΔ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]
En el plano, el ángulo θ medido desde el eje x positivo determina el vector unitario:
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
Una convención común utiliza un ángulo horizontal θ y una elevación φ:
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.
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.
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
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:
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.