Last updated on

Fórmula de Longitud de Arco de una Curva de Bézier

ENNLESPT-BR


La longitud de arco de una curva de Bézier es la distancia total que recorre un punto desde el inicio de la curva hasta el final. Se obtiene integrando la rapidez de ese punto, que es la longitud de la derivada de la curva, a lo largo del rango del parámetro. Una curva de Bézier cuadrática tiene una forma cerrada exacta. Una curva de Bézier cúbica por lo general no la tiene, así que las implementaciones aproximan su longitud con cuadratura numérica. Esta página deriva la fórmula cuadrática, construye la aproximación cúbica y muestra cómo convertir la longitud de arco en una parametrización por longitud que mueve un punto a rapidez constante. El tutorial interactivo de curvas de Bézier cubre la geometría de los puntos de control sobre la que se construye todo lo de aquí.

La longitud de arco es la integral de la rapidez

Una curva de Bézier asigna un punto B(t)B(t) a cada valor del parámetro tt entre 00 y 11. A medida que tt aumenta, ese punto se desliza a lo largo de la curva. Su velocidad es la derivada B′(t)B'(t), un vector que apunta en la dirección del movimiento, y la rapidez es la longitud de ese vector:

∣B′(t)∣=Bx′(t)2+By′(t)2|B'(t)| = \sqrt{B_x'(t)^2 + B_y'(t)^2}

La rapidez mide la distancia recorrida por unidad de tt. La rapidez por un paso infinitesimal dtdt da la distancia cubierta durante ese paso, así que sumar esas piezas pequeñas da el total:

s(t)=∫0t∣B′(τ)∣ dτ,L=s(1)=∫01∣B′(t)∣ dts(t) = \int_0^t |B'(\tau)|,d\tau, \qquad L = s(1) = \int_0^1 |B'(t)|,dt

Aquí tt es el parámetro de la curva, τ\tau es una variable muda de integración, s(t)s(t) es la longitud de arco acumulada desde el inicio hasta el parámetro tt, y LL es la longitud total de la curva. La línea recta entre los extremos siempre es más corta que la curva, y el polígono de control, que conecta los puntos de control con segmentos rectos, siempre es más largo. La longitud verdadera se encuentra entre esos dos límites, y es igual al área bajo la curva de rapidez representada frente a tt.

La consecuencia práctica importante es que tt no es distancia. Pasos iguales en tt producen pasos desiguales en distancia siempre que la rapidez cambie a lo largo de la curva. Un renderizador que muestrea de manera uniforme en tt colocará más puntos donde la curva es lenta y menos donde es rápida.

El panel izquierdo es una curva cuadrática o cúbica editable. El panel derecho representa la rapidez correspondiente ∣B′(t)∣|B'(t)| frente a tt y sombrea el área bajo ella. Esa área sombreada es la longitud de arco impresa en la esquina. Arrastrar un punto de control cambia ambos paneles a la vez: separar los puntos de control eleva la curva de rapidez y agranda el área, mientras que una forma compacta baja la curva y la reduce. Cambia al caso cúbico y la curva de rapidez puede desarrollar varias jorobas, porque la derivada de una cúbica es un polinomio cuadrático cuya longitud cambia con más libertad que la derivada lineal de una cuadrática.

Encontrar la longitud total de una curva de Bézier cuadrática

Una curva de Bézier cuadrática usa tres puntos y la fórmula

B(t)=(1−t)2P0+2(1−t)tP1+t2P2B(t) = (1 - t)^2 P_0 + 2(1 - t)t P_1 + t^2 P_2

Derivar da la velocidad:

B′(t)=2(1−t)(P1−P0)+2t(P2−P1)B'(t) = 2(1 - t)(P_1 - P_0) + 2t(P_2 - P_1)

Esa expresión es lineal en tt, que es la clave de la forma cerrada. Agrupa las partes constante y lineal definiendo dos vectores nuevos:

A=P0−2P1+P2,B=2(P1−P0)A = P_0 - 2P_1 + P_2, \qquad B = 2(P_1 - P_0)

Ahora la velocidad es simplemente

B′(t)=2At+BB'(t) = 2A t + B

Puedes comprobarlo expandiendo 2At+B2At + B: es igual a 2(1−t)(P1−P0)+2t(P2−P1)2(1-t)(P_1 - P_0) + 2t(P_2 - P_1), la derivada de arriba. Como la derivada es una línea recta en tt, su longitud al cuadrado es un polinomio cuadrático:

∣B′(t)∣2=(2At+B)⋅(2At+B)=at2+bt+c|B'(t)|^2 = (2At + B)\cdot(2At + B) = a t^2 + b t + c

con los tres coeficientes escalares

a=4(A⋅A),b=4(A⋅B),c=B⋅Ba = 4(A \cdot A), \qquad b = 4(A \cdot B), \qquad c = B \cdot B

La rapidez es la raíz cuadrada de ese polinomio cuadrático, y la longitud es su integral:

L=∫01at2+bt+c dtL = \int_0^1 \sqrt{a t^2 + b t + c},dt

Para evaluarla, completa el cuadrado dentro de la raíz. Escribe k=b/(2a)k = b / (2a) y m=c/a−k2m = c/a - k^2. Entonces

at2+bt+c=a((t+k)2+m)a t^2 + b t + c = a\left((t + k)^2 + m\right)

Sustituir u=t+ku = t + k convierte la integral en una forma estándar:

L=a∫kk+1u2+m duL = \sqrt{a}\int_k^{k+1} \sqrt{u^2 + m},du

La primitiva de u2+m\sqrt{u^2 + m} para m>0m > 0 es

F(u)=12(uu2+m+mln⁡(u+u2+m))F(u) = \frac{1}{2}\left(u\sqrt{u^2 + m} + m\ln\left(u + \sqrt{u^2 + m}\right)\right)

así que la longitud de arco cuadrática exacta es

L=a (F(k+1)−F(k))L = \sqrt{a},\bigl(F(k+1) - F(k)\bigr)

La cantidad mm nunca es negativa para una curva de Bézier cuadrática. El producto (A⋅B)2(A \cdot B)^2 nunca puede superar a (A⋅A)(B⋅B)(A \cdot A)(B \cdot B) por la desigualdad de Cauchy-Schwarz, y esa es exactamente la condición que hace que m≥0m \ge 0. Cuando AA y BB son paralelos, mm es cero, el logaritmo se vuelve singular y la raíz se simplifica a a ∣t+k∣\sqrt{a},|t + k|. La integral del valor absoluto es fácil de evaluar por tramos.

Ejemplo desarrollado

Toma P0=(0,0)P_0 = (0,0), P1=(1,2)P_1 = (1,2) y P2=(3,0)P_2 = (3,0). Entonces

A=(0,0)−2(1,2)+(3,0)=(1,−4),B=2(1,2)−2(0,0)=(2,4)A = (0,0) - 2(1,2) + (3,0) = (1,-4), \qquad B = 2(1,2) - 2(0,0) = (2,4)

Los coeficientes son a=4(1+16)=68a = 4(1 + 16) = 68, b=4(2−16)=−56b = 4(2 - 16) = -56 y c=4+16=20c = 4 + 16 = 20. El desplazamiento es

k=−562⋅68=−717≈−0.4118k = \frac{-56}{2 \cdot 68} = -\frac{7}{17} \approx -0.4118

y el término constante es

m=2068−(−717)2=36289≈0.1246m = \frac{20}{68} - \left(-\frac{7}{17}\right)^2 = \frac{36}{289} \approx 0.1246

Evaluar FF en los dos extremos da F(1+k)≈0.2169F(1 + k) \approx 0.2169 y F(k)≈−0.2385F(k) \approx -0.2385. Con a≈8.2462\sqrt{a} \approx 8.2462, la longitud es

L≈8.2462×(0.2169+0.2385)≈3.7546L \approx 8.2462 \times (0.2169 + 0.2385) \approx 3.7546

Longitud de arco cuadrática en código

Esta función devuelve la longitud exacta, incluidos los casos de línea recta y de velocidad paralela:

function quadraticArcLength(P0, P1, P2) {
  // A = P0 - 2 P1 + P2 and B = 2 (P1 - P0) make B'(t) = 2 A t + B.
  const ax = P0.x - 2 * P1.x + P2.x;
  const ay = P0.y - 2 * P1.y + P2.y;
  const bx = 2 * (P1.x - P0.x);
  const by = 2 * (P1.y - P0.y);

  const a = 4 * (ax * ax + ay * ay);
  const b = 4 * (ax * bx + ay * by);
  const c = bx * bx + by * by;

  // Constant speed: the curve is a straight line.
  if (a === 0) return Math.sqrt(c);

  const k = b / (2 * a);
  const scale = Math.sqrt(a);
  const disc = b * b - 4 * a * c;

  // A parallel to B: the speed is sqrt(a) * |t + k|.
  if (Math.abs(disc) < 1e-12 * a * c + 1e-30) {
    const abs = (x) => 0.5 * x * Math.abs(x);
    return scale * (abs(1 + k) - abs(k));
  }

  const m = c / a - k * k;
  const F = (u) => 0.5 * (u * Math.sqrt(u * u + m) + m * Math.log(u + Math.sqrt(u * u + m)));
  return scale * (F(1 + k) - F(k));
}

La rama a === 0 se activa cuando P1P_1 es el punto medio de P0P_0 y P2P_2, lo que colapsa la curva en una línea recta. La rama de discriminante casi nulo captura la situación en la que la velocidad permanece sobre una misma recta pero puede invertir su dirección, de modo que la curva va y vuelve. Para el caso común, la forma cerrada se ejecuta en tiempo constante sin muestreo.

Por qué la longitud de arco de una Bézier cúbica no tiene forma cerrada

Una curva de Bézier cúbica usa cuatro puntos:

B(t)=(1−t)3P0+3(1−t)2tP1+3(1−t)t2P2+t3P3B(t) = (1 - t)^3 P_0 + 3(1 - t)^2t P_1 + 3(1 - t)t^2 P_2 + t^3 P_3

Su derivada es

B′(t)=3(1−t)2(P1−P0)+6(1−t)t(P2−P1)+3t2(P3−P2)B'(t) = 3(1 - t)^2 (P_1 - P_0) + 6(1 - t)t (P_2 - P_1) + 3t^2 (P_3 - P_2)

Cada término es un vector multiplicado por un polinomio cuadrático en tt, así que B′(t)B'(t) es un vector de grado dos, y ∣B′(t)∣2|B'(t)|^2 es un único polinomio de cuarto grado en tt. La rapidez es la raíz cuadrada de ese polinomio de cuarto grado. Las integrales de la raíz cuadrada de un cuarto grado general son integrales elípticas, y las integrales elípticas no tienen expresión en funciones elementales. No existe una fórmula logarítmica o con raíces que cubra todas las cúbicas como la fórmula de completar el cuadrado cubre todas las cuadráticas.

Eso no significa que la longitud sea incognoscible. Significa que la longitud debe calcularse en lugar de consultarse, y la herramienta estándar para ese trabajo es la cuadratura gaussiana.

Aproximar la longitud de arco de una Bézier cúbica

La cuadratura de Gauss-Legendre aproxima una integral definida muestreando el integrando en un conjunto pequeño de puntos y tomando una suma ponderada:

∫−11f(x) dx≈∑i=1nwif(xi)\int_{-1}^{1} f(x),dx \approx \sum_{i=1}^{n} w_i f(x_i)

Los puntos xix_i son las raíces del nn-ésimo polinomio de Legendre, y los pesos wiw_i se eligen de modo que la regla sea exacta para todos los polinomios hasta el grado 2n−12n - 1. Nuestro intervalo es [0,1][0,1] en lugar de [−1,1][-1,1], así que sustituye t=(x+1)/2t = (x + 1)/2, lo que da

∫01f(t) dt=12∑i=1nwif ⁣(xi+12)\int_0^1 f(t),dt = \frac{1}{2}\sum_{i=1}^{n} w_i f!\left(\frac{x_i + 1}{2}\right)

Dieciséis puntos hacen que la regla sea exacta para polinomios hasta el grado 31. La rapidez es una raíz cuadrada en lugar de un polinomio, así que la regla no es exacta, pero para una función de rapidez suave 16 puntos ya quedan dentro de unas pocas partes por millón de la longitud verdadera.

// 16-point Gauss-Legendre abscissae and weights on [-1, 1].
const GL_X = [
  -0.989400934991650, -0.944575023073233, -0.865631202387832, -0.755404408355003,
  -0.617876244402644, -0.458016777657227, -0.281603550779259, -0.095012509837637,
   0.095012509837637,  0.281603550779259,  0.458016777657227,  0.617876244402644,
   0.755404408355003,  0.865631202387832,  0.944575023073233,  0.989400934991650,
];
const GL_W = [
  0.027152459411754, 0.062253523938648, 0.095158511682493, 0.124628971255534,
  0.149595988816577, 0.169156519395003, 0.182603415044924, 0.189450610455069,
  0.189450610455069, 0.182603415044924, 0.169156519395003, 0.149595988816577,
  0.124628971255534, 0.095158511682493, 0.062253523938648, 0.027152459411754,
];

function cubicSpeed(t, P) {
  const u = 1 - t;
  const dx = 3 * u * u * (P[1].x - P[0].x) + 6 * u * t * (P[2].x - P[1].x) + 3 * t * t * (P[3].x - P[2].x);
  const dy = 3 * u * u * (P[1].y - P[0].y) + 6 * u * t * (P[2].y - P[1].y) + 3 * t * t * (P[3].y - P[2].y);
  return Math.sqrt(dx * dx + dy * dy);
}

function cubicArcLength(P) {
  let sum = 0;
  for (let i = 0; i < GL_X.length; i++) {
    const t = 0.5 * GL_X[i] + 0.5;
    sum += GL_W[i] * cubicSpeed(t, P);
  }
  return 0.5 * sum;
}

La misma función auxiliar sirve cuando la cuadratura necesita la longitud desde el inicio hasta un parámetro arbitrario tt en lugar de la curva completa. Conserva las abscisas y los pesos, y escala el intervalo a [0,t][0, t]:

function cubicArcLengthTo(t, P) {
  if (t <= 0) return 0;
  let sum = 0;
  for (let i = 0; i < GL_X.length; i++) {
    const s = 0.5 * t * (GL_X[i] + 1);
    sum += GL_W[i] * cubicSpeed(s, P);
  }
  return 0.5 * t * sum;
}

¿Qué precisión tiene la cuadratura?

La tabla compara la regla con una referencia de alta precisión para tres curvas cúbicas. Los errores son absolutos.

Puntos de control de la cúbica Longitud verdadera 8 puntos 16 puntos 24 puntos
(0,0) (1,3) (4,−2) (5,1)(0,0)\ (1,3)\ (4,-2)\ (5,1) 6.214707537 1.9×10−41.9\times10^{-4} 7.1×10−77.1\times10^{-7} 2.2×10−102.2\times10^{-10}
(0,0) (1,1) (2,1) (3,0)(0,0)\ (1,1)\ (2,1)\ (3,0) 3.443380724 6.2×10−86.2\times10^{-8} 1.6×10−141.6\times10^{-14} <10−15<10^{-15}
(0,0) (0,1) (0,−1) (0,0)(0,0)\ (0,1)\ (0,-1)\ (0,0) 1.154700538 1.5×10−21.5\times10^{-2} 3.8×10−33.8\times10^{-3} 2.4×10−32.4\times10^{-3}

Las dos primeras curvas tienen perfiles de rapidez suaves, y 16 puntos son más que suficientes. La tercera curva se regresa sobre sí misma, así que su rapidez cae a cero y la función de rapidez tiene una esquina. La cuadratura converge lentamente en una esquina, y añadir más puntos apenas ayuda. La solución es dividir el rango del parámetro en el punto problemático e integrar cada pieza por separado, o usar el método de subdivisión de abajo.

La subdivisión adaptativa como alternativa

El algoritmo de De Casteljau puede dividir un segmento cúbico en dos segmentos cúbicos más pequeños en cualquier valor del parámetro, y dividir en 0.50.5 es especialmente simple: promedia puntos de control vecinos hasta que quede un solo punto. El polígono de control de una pieza pequeña es casi una línea recta, así que tanto su longitud como la longitud de la cuerda entre extremos se acercan a la longitud de arco verdadera. La diferencia entre ambas mide cuánto se curva todavía la pieza. Cuando la diferencia queda por debajo de una tolerancia, devuelve el promedio de las dos; en caso contrario, divide y recurre.

const distance = (a, b) => Math.hypot(a.x - b.x, a.y - b.y);
const midpoint = (a, b) => ({ x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 });

function adaptiveArcLength(P0, P1, P2, P3, tolerance = 1e-6) {
  const chord = distance(P0, P3);
  const polygon =
    distance(P0, P1) + distance(P1, P2) + distance(P2, P3);
  if (polygon - chord <= tolerance) {
    return (polygon + chord) / 2;
  }

  // Split at t = 0.5 with de Casteljau averaging.
  const p01 = midpoint(P0, P1);
  const p12 = midpoint(P1, P2);
  const p23 = midpoint(P2, P3);
  const p012 = midpoint(p01, p12);
  const p123 = midpoint(p12, p23);
  const mid = midpoint(p012, p123);

  return (
    adaptiveArcLength(P0, p01, p012, mid, tolerance) +
    adaptiveArcLength(mid, p123, p23, P3, tolerance)
  );
}

La subdivisión adaptativa cuesta más evaluaciones que una sola regla de 16 puntos, pero concentra el trabajo donde la curva se dobla y sigue funcionando en curvas con esquinas o casi cúspides. La regla de cuadratura es más rápida para las curvas suaves que aparecen en la mayoría del trabajo de renderizado y animación, y la subdivisión es el respaldo seguro cuando hay que garantizar una tolerancia.

Parametrización por longitud de una curva de Bézier

Todo lo anterior calcula la longitud a partir del parámetro. La pregunta inversa, encontrar el parámetro que corresponde a una distancia dada, es lo que hace posible el movimiento a rapidez constante. Define la función de longitud acumulada

s(t)=∫0t∣B′(τ)∣ dτs(t) = \int_0^t |B'(\tau)|,d\tau

Como la rapidez nunca es negativa, s(t)s(t) aumenta de forma constante de 00 a LL a medida que tt va de 00 a 11, así que puede invertirse. La inversa, escrita t(s)t(s), es la parametrización por longitud: dale una distancia y devuelve el parámetro que sitúa el punto exactamente a esa distancia a lo largo de la curva. La dirección directa tiene una forma cerrada para curvas cuadráticas y una regla de cuadratura para curvas cúbicas, pero ninguna de las dos inversas tiene una expresión elemental en general, así que las implementaciones construyen una tabla e interpolan.

La receta tiene tres pasos. Muestrea s(t)s(t) en muchos valores de tt uniformemente espaciados y guarda los pares. Para convertir una distancia objetivo en un parámetro, busca binariamente en la tabla el par que la rodea y luego interpola linealmente. Como la tabla es solo una aproximación lineal a trozos de una función suave, termina con uno o dos pasos de Newton. El método de Newton encuentra una raíz de s(t)−stargets(t) - s_{\text{target}} usando la derivada s′(t)=∣B′(t)∣s'(t) = |B'(t)|, que es exactamente la rapidez que ya está disponible.

Ambos paneles muestran la misma curva cúbica. El panel izquierdo coloca un punto cada décima parte del rango del parámetro, y el panel derecho coloca un punto cada décima parte de la longitud de arco total. Arrastrar un punto de control remodela ambos paneles a la vez. Donde la curva se mueve despacio, los puntos del parámetro se agolpan, y donde se mueve rápido, se separan. Los puntos de longitud de arco permanecen uniformemente espaciados porque la tabla asigna cada distancia igual al parámetro que la alcanza. Los marcadores rojos recorren ambas curvas en el mismo tiempo. El marcador izquierdo acelera y frena con el parámetro, y el marcador derecho se mueve a un ritmo constante.

Construir e invertir la tabla de longitudes

function buildArcLengthTable(P, samples = 128) {
  const ts = new Float64Array(samples + 1);
  const ss = new Float64Array(samples + 1);
  for (let i = 1; i <= samples; i++) {
    ts[i] = i / samples;
    ss[i] = cubicArcLengthTo(ts[i], P);
  }
  return { ts, ss, length: ss[samples] };
}

function parameterAtLength(table, target, P) {
  const { ts, ss } = table;

  // Binary search for the pair of samples that bracket the target.
  let lo = 0;
  let hi = ts.length - 1;
  while (lo + 1 < hi) {
    const mid = (lo + hi) >> 1;
    if (ss[mid] <= target) lo = mid;
    else hi = mid;
  }

  // Linear interpolation gives a good starting point.
  const span = ss[hi] - ss[lo];
  let t = span > 0 ? ts[lo] + ((target - ss[lo]) / span) * (ts[hi] - ts[lo]) : ts[lo];

  // Newton steps refine the answer to full precision.
  for (let i = 0; i < 3; i++) {
    const speed = cubicSpeed(t, P);
    if (speed < 1e-9) break;
    t -= (cubicArcLengthTo(t, P) - target) / speed;
    t = Math.min(1, Math.max(0, t));
  }

  return t;
}

La tabla se construye una vez por forma de curva. Cambiar un punto de control la invalida, pero mover un punto a lo largo de la curva en tiempo de ejecución solo realiza consultas. Para mover un objeto a rapidez constante vv, avanza la distancia en vv veces el tiempo transcurrido y llama a parameterAtLength con el resultado:

const table = buildArcLengthTable(P);
let travelled = 0;
let previous = performance.now();

function step(now, targetSpeed) {
  travelled += targetSpeed * (now - previous) / 1000;
  previous = now;
  const distance = travelled % table.length;
  const t = parameterAtLength(table, distance, P);
  // Sample the curve at t to place the object.
}

Sin las consultas a la tabla, avanzar el parámetro directamente haría que el objeto diera tumbos por las partes rápidas de la curva y se arrastrara por las lentas.

Comprobar la implementación

Unas pocas aserciones cubren las ramas principales. La forma cerrada cuadrática debería coincidir con la regla de cuadratura en la misma curva, porque la regla de cuadratura es lo bastante precisa a esta escala. El viaje de ida y vuelta por la tabla debería devolver la distancia original tras convertir a un parámetro y volver.

const q = [{ x: 0, y: 0 }, { x: 1, y: 2 }, { x: 3, y: 0 }];
console.assert(Math.abs(quadraticArcLength(q[0], q[1], q[2]) - 3.7546364123) < 1e-9);

// A straight-line quadratic has length equal to its endpoint distance.
console.assert(Math.abs(quadraticArcLength({ x: 0, y: 0 }, { x: 1, y: 1 }, { x: 2, y: 2 }) - Math.SQRT2 * 2) < 1e-9);

const c = [{ x: 0, y: 0 }, { x: 1, y: 3 }, { x: 4, y: -2 }, { x: 5, y: 1 }];
console.assert(Math.abs(cubicArcLength(c) - 6.2147075374) < 1e-5);

const table = buildArcLengthTable(c);
for (let i = 0; i <= 10; i++) {
  const target = (i / 10) * table.length;
  const t = parameterAtLength(table, target, c);
  console.assert(Math.abs(cubicArcLengthTo(t, c) - target) < 1e-6);
}

Casos límite y notas prácticas

Líneas rectas. Cuando un punto de control cuadrático se sitúa exactamente en el punto medio de sus vecinos, la curva colapsa en un segmento recto, y la cuerda entre extremos es la longitud total. La rama cuadrática maneja este caso directamente. Una cúbica cuyos puntos de control son colineales y cuya dirección nunca se invierte también recorre un segmento recto, y la cuadratura devuelve el valor correcto porque la rapidez es constante a lo largo de la línea.

Puntos estacionarios y cúspides. Una curva cúbica puede tener un valor del parámetro en el que su velocidad es cero, lo que ocurre cuando la curva invierte su dirección o forma una cúspide. La función de rapidez toca cero allí y tiene una esquina afilada, y la cuadratura gaussiana pierde precisión. El método de subdivisión adaptativa de arriba es la opción fiable para estas formas.

Autointersecciones. Una cúbica con forma de bucle se cruza a sí misma, pero su longitud de arco sigue contando después del cruce. Eso coincide con la distancia que recorre un punto, que suele ser lo que necesitan la animación y el desplazamiento de curvas. Si en cambio quieres la longitud del contorno visible, divide la curva en el cruce y cuenta cada rama una vez.

Dos dimensiones y tres dimensiones. Las fórmulas solo usan suma de vectores, productos escalares y longitudes, así que el mismo código funciona para puntos de control en 2D y 3D. Un punto de control en 3D simplemente tiene un campo zz, y la rapidez gana un tercer término al cuadrado.

Precalcula cuando la forma es fija. Una tabla de longitudes para una trayectoria estática puede construirse una vez y almacenarse. Una herramienta que solo lee la longitud total puede omitir la tabla por completo y llamar a la cuadratura, que es un puñado de multiplicaciones y raíces cuadradas.

Inversión y simetría de la curva. Invertir el orden de los puntos de control deja la longitud sin cambios, y lo mismo hacen la forma cerrada y la regla de cuadratura. Es una comprobación de sentido útil cuando una curva se construye desde cualquiera de los dos extremos.

Resumen

La longitud de arco de una curva de Bézier es la integral de la rapidez ∣B′(t)∣|B'(t)| sobre el rango del parámetro. Para una curva cuadrática, la velocidad es lineal en tt, así que la rapidez es la raíz cuadrada de un polinomio cuadrático y la integral tiene la forma cerrada L=a(F(k+1)−F(k))L = \sqrt{a}(F(k+1) - F(k)) derivada arriba. Para una curva cúbica, la rapidez es la raíz cuadrada de un polinomio de cuarto grado, que no tiene primitiva elemental, así que una regla de Gauss-Legendre de 16 puntos calcula la longitud con unos seis dígitos significativos, y la subdivisión adaptativa cubre las curvas con esquinas. Invertir la longitud acumulada da la parametrización por longitud, que una tabla de consulta, una búsqueda binaria y unos pocos pasos de Newton implementan para el movimiento a rapidez constante. El tutorial interactivo de curvas de Bézier cubre la geometría de los puntos de control detrás de estas longitudes.