Actualmente, intento hacer que múltiples beziers tengan puntos equidistantes. Actualmente estoy usando la interpolación cúbica para encontrar los puntos, pero debido a la forma en que trabajan los beziers, algunas áreas son más densas que otras y resultan ser burdas para el mapeo de texturas debido a la distancia variable. ¿Hay alguna forma de encontrar puntos en un bezier por distancia en lugar de por porcentaje? Además, ¿es posible extender esto a múltiples curvas conectadas?Puntos equidistantes en curvas Bezier
Respuesta
distancia entre P_0 y P_3 (en forma cúbica), sí, pero creo que ya lo sabía, es sencillo.
Distancia en una curva es simplemente la longitud de arco:
fig 1 http://www.codecogs.com/eq.latex?%5Cint_%7Bt_0%7D%5E%7Bt_1%7D%20%7B%20|P'(t)|%20dt
donde:
Probablemente, tendría t_0 = 0, = t_1 1.0, y dz (t) = 0 (plano 2d).
Así es como se encuentra la longitud del arco dado el parámetro, pero encontrar puntos equidistantes requiere el inverso de esta función. Pasar de uno a otro no es trivial. @ Christian Romo: ¿cómo lo hiciste? Quiero decir, puedes usar la búsqueda binaria, pero eso sería terriblemente lento (por lo que estoy tratando de hacer, de todos modos). – CromTheDestroyer
Esto se denomina parametrización de "longitud del arco". Escribí un artículo sobre esto hace varios años:
http://www.saccade.com/writing/graphics/RE-PARAM.PDF
La idea es comprobar la validez de calcular una curva de "parametrización", y evaluar la curva través de eso.
No he leído el documento completamente todavía. Pero me gustaría preguntar si hay una mejor manera de definir curvas que no necesitarían ser "convertidas" primero. P.ej. ¿Sabes si usaría NURBS para definir todas las rutas/curvas, soportaría una parametrización de longitud de arco equidistante más rápida? O de alguna otra manera tal vez? Editar: Más rápido me refiero al uso de CPU o GPU. – Ciantic
El uso de NURB no ayudará, el problema fundamental es el mismo. El final del documento muestra un método para componer la curva de re parametrización con el original. Esto produce una nueva curva con la parametrización de la longitud del arco, pero el orden si la curva es más alta, por lo que es más lento de evaluar. –
Sé que esta es una pregunta anterior, pero recientemente me encontré con este problema y creé una extensión UIBezierPath
para resolver una coordenada X
dada una coordenada Y
y viceversa. Escrito a la velocidad
https://github.com/rkotzy/RKBezierMath
extension UIBezierPath {
func solveBezerAtY(start: CGPoint, point1: CGPoint, point2: CGPoint, end: CGPoint, y: CGFloat) -> [CGPoint] {
// bezier control points
let C0 = start.y - y
let C1 = point1.y - y
let C2 = point2.y - y
let C3 = end.y - y
// The cubic polynomial coefficients such that Bez(t) = A*t^3 + B*t^2 + C*t + D
let A = C3 - 3.0*C2 + 3.0*C1 - C0
let B = 3.0*C2 - 6.0*C1 + 3.0*C0
let C = 3.0*C1 - 3.0*C0
let D = C0
let roots = solveCubic(A, b: B, c: C, d: D)
var result = [CGPoint]()
for root in roots {
if (root >= 0 && root <= 1) {
result.append(bezierOutputAtT(start, point1: point1, point2: point2, end: end, t: root))
}
}
return result
}
func solveBezerAtX(start: CGPoint, point1: CGPoint, point2: CGPoint, end: CGPoint, x: CGFloat) -> [CGPoint] {
// bezier control points
let C0 = start.x - x
let C1 = point1.x - x
let C2 = point2.x - x
let C3 = end.x - x
// The cubic polynomial coefficients such that Bez(t) = A*t^3 + B*t^2 + C*t + D
let A = C3 - 3.0*C2 + 3.0*C1 - C0
let B = 3.0*C2 - 6.0*C1 + 3.0*C0
let C = 3.0*C1 - 3.0*C0
let D = C0
let roots = solveCubic(A, b: B, c: C, d: D)
var result = [CGPoint]()
for root in roots {
if (root >= 0 && root <= 1) {
result.append(bezierOutputAtT(start, point1: point1, point2: point2, end: end, t: root))
}
}
return result
}
func solveCubic(a: CGFloat?, var b: CGFloat, var c: CGFloat, var d: CGFloat) -> [CGFloat] {
if (a == nil) {
return solveQuadratic(b, b: c, c: d)
}
b /= a!
c /= a!
d /= a!
let p = (3 * c - b * b)/3
let q = (2 * b * b * b - 9 * b * c + 27 * d)/27
if (p == 0) {
return [pow(-q, 1/3)]
} else if (q == 0) {
return [sqrt(-p), -sqrt(-p)]
} else {
let discriminant = pow(q/2, 2) + pow(p/3, 3)
if (discriminant == 0) {
return [pow(q/2, 1/3) - b/3]
} else if (discriminant > 0) {
let x = crt(-(q/2) + sqrt(discriminant))
let z = crt((q/2) + sqrt(discriminant))
return [x - z - b/3]
} else {
let r = sqrt(pow(-(p/3), 3))
let phi = acos(-(q/(2 * sqrt(pow(-(p/3), 3)))))
let s = 2 * pow(r, 1/3)
return [
s * cos(phi/3) - b/3,
s * cos((phi + CGFloat(2) * CGFloat(M_PI))/3) - b/3,
s * cos((phi + CGFloat(4) * CGFloat(M_PI))/3) - b/3
]
}
}
}
func solveQuadratic(a: CGFloat, b: CGFloat, c: CGFloat) -> [CGFloat] {
let discriminant = b * b - 4 * a * c;
if (discriminant < 0) {
return []
} else {
return [
(-b + sqrt(discriminant))/(2 * a),
(-b - sqrt(discriminant))/(2 * a)
]
}
}
private func crt(v: CGFloat) -> CGFloat {
if (v<0) {
return -pow(-v, 1/3)
}
return pow(v, 1/3)
}
private func bezierOutputAtT(start: CGPoint, point1: CGPoint, point2: CGPoint, end: CGPoint, t: CGFloat) -> CGPoint {
// bezier control points
let C0 = start
let C1 = point1
let C2 = point2
let C3 = end
// The cubic polynomial coefficients such that Bez(t) = A*t^3 + B*t^2 + C*t + D
let A = CGPointMake(C3.x - 3.0*C2.x + 3.0*C1.x - C0.x, C3.y - 3.0*C2.y + 3.0*C1.y - C0.y)
let B = CGPointMake(3.0*C2.x - 6.0*C1.x + 3.0*C0.x, 3.0*C2.y - 6.0*C1.y + 3.0*C0.y)
let C = CGPointMake(3.0*C1.x - 3.0*C0.x, 3.0*C1.y - 3.0*C0.y)
let D = C0
return CGPointMake(((A.x*t+B.x)*t+C.x)*t+D.x, ((A.y*t+B.y)*t+C.y)*t+D.y)
}
// TODO: - future implementation
private func tangentAngleAtT(start: CGPoint, point1: CGPoint, point2: CGPoint, end: CGPoint, t: CGFloat) -> CGFloat {
// bezier control points
let C0 = start
let C1 = point1
let C2 = point2
let C3 = end
// The cubic polynomial coefficients such that Bez(t) = A*t^3 + B*t^2 + C*t + D
let A = CGPointMake(C3.x - 3.0*C2.x + 3.0*C1.x - C0.x, C3.y - 3.0*C2.y + 3.0*C1.y - C0.y)
let B = CGPointMake(3.0*C2.x - 6.0*C1.x + 3.0*C0.x, 3.0*C2.y - 6.0*C1.y + 3.0*C0.y)
let C = CGPointMake(3.0*C1.x - 3.0*C0.x, 3.0*C1.y - 3.0*C0.y)
return atan2(3.0*A.y*t*t + 2.0*B.y*t + C.y, 3.0*A.x*t*t + 2.0*B.x*t + C.x)
}
}
- 1. Algoritmo para "trazar" puntos secuenciales en curvas de bezier
- 2. Curvas rotas en Html5 Lienzo Bezier
- 3. Curvas de bezier cúbicas: obtener Y para X
- 4. ¿Dibujando curvas de bezier con mi dedo en iOS?
- 5. bezier path widening
- 6. ¿Algún algoritmo para encontrar el cuadro delimitador de curvas de bezier cerradas?
- 7. Dibujando curvas de Hermite en OpenGL
- 8. SVG: ¿simplifica la ruta para eliminar curvas?
- 9. recorte de Bezier
- 10. calcular los puntos de control para un camino SVG abreviada/lisa Bezier curva
- 11. detectar "problemillas" en líneas paralelas a las curvas de Bézier
- 12. Animación WPF - Animación de los puntos de la curva de Bezier
- 13. Usando una Curva de Bezier para dibujar una espiral
- 14. ¿Cómo compensar una curva de bezier cúbica?
- 15. Encontrar puntos en una curva bezier basada en la distancia desde otro punto
- 16. Encontrar puntos en las curvas en HTML 5 2d Contexto del lienzo
- 17. Pregunta sobre la implementación de Bezier Curves?
- 18. Detección de curvas en OpenCV
- 19. Arrastre una curva bezier para editarlo
- 20. Esquema de la curva de bezier cúbica trazo
- 21. Biblioteca de ajuste de curvas Java
- 22. Aprendiendo Curvas de Rubí
- 23. Haciendo una ruta fluida desde un número irregular de puntos x, y para simular la escritura
- 24. R/ImageJ: medición de la distancia más corta entre los puntos y las curvas
- 25. ¿Cómo generar este tipo de curvas aleatorias?
- 26. R - ¿Qué algoritmo usa geom_density() y cómo extraer puntos/ecuación de curvas?
- 27. Necesito una biblioteca C++ para ajustar las curvas a los puntos de datos
- 28. Recreación de transiciones CSS3 Curva cúbica-Bezier
- 29. Cálculo del área entre dos curvas
- 30. Objetivo C Bezier Curva Reesformar
Ver también http://math.stackexchange.com/a/61796/589. – lhf