Estoy tratando de calcular dónde están los puntos en una curva bezier y estoy usando la fórmula estándar para hacerlo. Eso es:
x = (1 - t) * (1 - t) * x1 + 2 * (1 - t) * t * cpX + t * t * x2; y = (1 - t) * (1 - t) * y1 + 2 * (1 - t) * t * cpY + t * t * y2;Sin embargo, estoy bastante confundido por los resultados. He desarrollado una demostración de lo que estoy hablando a continuación:
let c = document.querySelector("canvas"); let ctx = c.getContext("2d"); let x1 = 25; let y1 = 25; let cpX = 35; let cpY = 35; let x2 = 200; let y2 = 25; let f = 0; function calcX(t) { return (1 - t) * (1 - t) * x1 + 2 * (1 - t) * t * cpX + t * t * x2; } function calcY(t) { return (1 - t) * (1 - t) * y1 + 2 * (1 - t) * t * cpY + t * t * y2; } function drawCurve() { ctx.beginPath(); ctx.moveTo(x1, y1); ctx.quadraticCurveTo(cpX, cpY, x2, y2); ctx.stroke(); } function drawLoop(elapsed) { c.width = 600; c.height = 600; let x = calcX(f); let y = calcY(f); drawCurve(); ctx.beginPath(); ctx.rect(x, y, 3, 3); ctx.stroke(); f = f < 1 ? f + 0.001 : 0; document.querySelector(".debug").innerHTML = f.toFixed(2); requestAnimationFrame(drawLoop); } drawLoop(0); .debug { position: absolute; left: 9px; top: 6px; } <canvas></canvas> <div class="debug"></div>Como puede ver, la marca del 50% parece demasiado a la izquierda:
Entiendo que hay una curva, pero la marca de la mitad todavía parece demasiado a la izquierda. Es decir, si le preguntaras a un grupo de personas dónde está la mitad de esa curva, creo que todos dirían más a la derecha.
Esto puede ser una posibilidad remota, pero ¿existe otra fórmula para calcular dónde están los puntos en las curvas de Bézier que es más "cercana al mundo real"?
Editar: acabo de pensar en otra forma de articular más concretamente este fenómeno. Notará que si establece los valores de las variables cpX y cpY en cualquier número arbitrario y luego ejecuta la simulación, el marcador cuadrado se mueve a diferentes velocidades a lo largo de diferentes partes de la curva. Es decir, puede moverse rápidamente al principio, luego disminuir la velocidad y luego volver a acelerar hacia el final de la curva.
Lo que estoy buscando es una fórmula tal que el marcador cuadrado tenga una velocidad más constante a lo largo de toda la curva y nunca acelere o desacelere en el camino. es posible?
Terminé creando una función basada en el comentario de Chris G que precalcula todos estos puntos a lo largo de la curva de Bézier. Alguien más podría encontrarlo útil:
function calcPoints() { const step = 0.001; const segments = []; for (let i = 0; i <= 1 - step; i += step) { let dx = this.calcX(i) - this.calcX(i + step); let dy = this.calcY(i) - this.calcY(i + step); segments.push(Math.sqrt(dx * dx + dy * dy)); } const len = segments.reduce((a, c) => a + c, 0); let result = []; let l = 0; let co = 0; for (let i = 0; i < segments.length; i++) { l += segments[i]; co += step; result.push({ t: l / len, co }); } return result; } // Example pseudo-code: let pointCache = calcPoints(); let co = binarySearch(pointCache, 0.5).co; let x = this.calcX(co); let y = this.calcY(co);Creo que esto funciona? Simplemente busca binariamente en la matriz resultante el valor que está buscando. La función solo necesita ejecutarse una vez si su curva no cambia después.