2009-11-19 10 views
7

Estoy tratando de hacer una herramienta 'pincel' en AS3 (pura, no Flex) que simula la escritura, haciendo que los trazos sean suaves en lugar de arrinconados. Luego, la traza debe reducirse a curvas de bezier cúbicas que se pueden arrastrar y deformar, afectando la trayectoria dibujada previamente (como la herramienta de pluma del ilustrador).Haciendo una ruta fluida desde un número irregular de puntos x, y para simular la escritura

Estoy siguiendo el movimiento del mouse para obtener un conjunto de puntos para dibujar la ruta. Hasta donde yo sé, necesito hacer una ruta B-Spline usando ese conjunto de puntos. Entonces debería reducirlo a curvas de bezier cúbicas (agregando la funcionalidad 'pluma herramienta' a la ruta).

Ya he desarrollado la herramienta de pluma, utilizando un algoritmo que reduce los Beziers cúbicos a los Beziers cuadráticos (y luego usa la función Flash curveTo). Pero no tengo idea de cómo crear una B-Spline (u otra simplificación), y luego reducirla a curvas de Bezier.

¿Conoces alguna forma de lograr esto?

+0

estoy buscando lo mismo pero javascript, ¿conoces alguna? – igor

Respuesta

7

El jhotdraw es un proyecto de código abierto en Java para dibujar. Convierte dibujos a mano alzada en curvas de bezier cúbicas. La fuente está disponible: descargar y traducir. No se asustan en el tamaño del proyecto: se necesita sólo un par de clases, a saber:

org.jhotdraw.geom.Bezier 
org.jhotdraw.geom.BezierPath 
org.jhotdraw.geom.Geom 

Al traducir inicio cambiando todas las declaraciones de recogida a las matrices (vectores de uso si se dirigen sólo a los usuarios FP10) . Tengo algunas expresiones regulares que puede encontrar útiles en la conversión. Puedo publicarlas si lo desea.


Aquí hay una lista de expresiones regulares que puede serte útiles. En cada par, pegue el primero en el área de texto de búsqueda y el segundo en el área de reemplazo, marque la casilla de verificación de expresiones regulares y use los botones Buscar y Reemplazar. No utiliceReplace All- ninguno de estos se garantiza que sea infalible.

Reemplazar todos int/double name declaraciones con var name:Number

\b(double|int)\s+(\w+)\b 

var $2:Number 

Reemplazar todos Point2D.Double name declaraciones con var name:Point

\bPoint2D\.Double\s+(\w+)\b 

var $1:Point 

Reemplazar todos int/double name declaraciones en las firmas de función con name:Number

\(([^)]*)\b(?:double|int)\s+(\w+)\b([^)]*?)\) 

($1$2:Number$3) 

Reemplazar todos Point2D.Double name declaraciones en las firmas de función con name:Point

\(([^)]*)\b(?:Point2D\.Double)\s+(\w+)\b([^)]*?)\) 

($1$2:Point$3) 

Antes de cambiar firmas de método, asegúrese de que todos los métodos son estáticos:

(public|private)\s+(?!static) 

Reemplazar firmas de los métodos a AS formato

(public|private)\s+static\s+(\w+)\s+(\w+)\s*\(([^)]*)\) 

$1 static function $3($4):$2 

Reemplace ArrayList.get (index) con array [index] // Advertencia: falla para list.get (list.size() - 1)

(\w+)\.get\(([^)]+)\) 

$1[$2] 

//avoid the() failure 

(\w+)\.get\(([^)]*(?:\([^)]*\))[^)]*)\) 

$1[$2] 

Reemplazar ArrayList.set(index, element) con array[index] = element // Advertencia: falla por list.set (i, list.size())

(\w+)\.set\(([^,]+)\s*,\s*([^)]+)\) 

$1[$2] = $3 


/*the above regex successfully made the following replacement*/ 

cleaned.set(cleaned.size() - 1, digitizedPoints[digitizedPoints.size() - 1]) 

cleaned[cleaned.size() - 1] = digitizedPoints[digitizedPoints.size() - 1] 

Reemplazar arraylist.add(object) con array.push(object)

//would fail if object contains ')' 
//add(index, object) should be done with splice 

(\w+)\.add\(([^)]+)\) 

$1.push($2) 

//too many failures - fail safe version - 
//still fails for nested parenthesis list.add(new Point(a.first(), a.last())) 
//- only three such cases - the effort to match parenthesis wouldn't be worth it 
//works for list.add(new Point(3, 4)) - there were many similar cases 

(\w+)\.add\(([^)]*(?:\([^)]*\))[^)]*)\) 

$1.push($2) 

Reemplace las firmas de los métodos al formato AS (métodos no estáticos)

(public|private)\s+(?!function)(\w+)\s+(\w+)\s*\(([^)]*)\) 

$1 function $3($4):$2 

Reemplazar todos int/double/point/boolean name declaraciones en las firmas de función con name:type

\(([^)]*)\b(\w+)\s+(\w+)\b([^)]*?)\) 

($1$3:$2$4) 

Reemplazar todas las declaraciones de variables en su propia línea con un formato de AS = a

^(\s+)(\w+)\s+(\w+)\s*=\s*(.+?)\s*;(\s*)$ 

$1var $3:$2 = $4;$5 

cambio de colocación de aparatos de ortodoncia.

^(\t)(\s*)([^\n]+)\{\s*(\n)\s+ 

$1$2$3$4$1$2{$4$1$2 

cambio } else en } \n else

^([ \t]+)}[ \t]*else\b([^\n]*)(\n) 

$1}$3$1else$2$3 

Sustitución 4 declaraciones de variables en una sola línea a AS en diferentes líneas

^(\t+)(\w+)\s+(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*;[ \t]*(\n) 

$1var $3:$2;$7$1var $4:$2;$7$1var $5:$2;$7$1var $6:$2;$7 

Reemplazar declaraciones de matrices

^(\s+)\w+\[\]\s*(\w+)\b 

$1 var $2:Array 

Eliminar() Modelos - AS compilador no les gustaría

(?:\(\w+\)\s*)([^ ,*+;/)><=\-]) 

$1 

Reemplazar max etc en Math.max - AS no tiene importaciones estáticas

(?<!Math\.)\b(max|min|abs|sqrt|PI|cos|sin|atan2)\(

Math.$1(
+0

He revisado la biblioteca y se ve increíble. La aplicación de muestra de dibujo hace exactamente lo que quiero. Gracias por la referencia. – yizzreel

+0

Aquí están los regexes de los que estaba hablando. – Amarghosh

+0

¡Qué trabajo tan maravilloso! Ya comencé a portar el código de Java a AS3, no parece ser una tarea difícil, pero esto acelerará el proceso tremendamente. Muchas gracias. – yizzreel

1

he usado esta función una vez.

 

    public function multicurve(g: Graphics, args: Array, closed: Boolean): void {   
      var mid: Array = args.slice(); //make dublicate 
      var i: uint; 
      var point: Point; 
      var nextPoint: Point; 
      var numPoints: uint = mid.length; 

      if (numPoints == 2) { 
       g.moveTo(mid[0].x, mid[0].y); 
       g.lineTo(mid[1].x, mid[1].y); 
       return; 
      } 

      var Xpoint: Array = new Array(); 
      var Ypoint: Array = new Array(); 
      for (i = 1; i < numPoints - 2; i++) { 
       point = mid[i]; 
       nextPoint = mid[i+1]; 
       Xpoint[i] = 0.5*(nextPoint.x + point.x); 
       Ypoint[i] = 0.5*(nextPoint.y + point.y); 
      } 
      if (closed) { 
       Xpoint[0] = 0.5*(mid[1].x + mid[0].x); 
       Ypoint[0] = 0.5*(mid[1].y + mid[0].y); 
       Xpoint[i] = 0.5*(mid[i+1].x + mid[i].x); 
       Ypoint[i] = 0.5*(mid[i+1].y + mid[i].y); 
       Xpoint[i+1] = 0.5*(mid[i+1].x + mid[0].x); 
       Ypoint[i+1] = 0.5*(mid[i+1].y + mid[0].y); 
       mid.push(new Point(mid[0].x, mid[0].y)); 
       Xpoint[i+2] = Xpoint[0]; 
       Ypoint[i+2] = Ypoint[0]; 
      } else { 
       Xpoint[0] = mid[0].x; 
       Ypoint[0] = mid[0].y; 
       Xpoint[i] = mid[i+1].x; 
       Ypoint[i] = mid[i+1].y; 
       mid.pop(); 
       numPoints--; 
      } 
      g.moveTo(Xpoint[0], Ypoint[0]); 
      for (i = 1; i < numPoints; i++) { 
       point = mid[i]; 
       g.curveTo(point.x, point.y, Xpoint[i], Ypoint[i]); 
      } 
      if (closed) { 
       g.curveTo(mid[0].x, mid[0].y, Xpoint[i], Ypoint[i]); 
      } 
     } 

 
1

Existe un algoritmo en la biblioteca de corriente alterna que hace lo que está pidiendo: http://tog.acm.org/resources/GraphicsGems/gems/FitCurves.c

Este es un algoritmo bastante complejo que simplifica su geometría al convertir una lista de muchos puntos en una lista de algunas curvas de bezier ajustadas, convirtiendo esencialmente garabatos en curvas muy suaves. Tiene una cantidad ajustable de holgura, y funciona al encontrar la menor cantidad de curvas de bezier que se ajustan a su conjunto de puntos dentro de cierta holgura. Por lo tanto, cuanto más establezca la holgura del algoritmo, más suave (pero potencialmente menos precisa) obtendrá su escritura.

+0

¡Oye! ¡Gracias! esto se ve bien !. Ya estoy usando el algoritmo jHotDraw (simplificado) y funciona de manera muy similar al código que me vinculó. Sin embargo, echaré un vistazo profundo a este también. Y parece que hay más fuentes en el sitio web donde está el archivo. Gracias de nuevo por la referencia! – yizzreel

+0

Actualización rápida: la biblioteca de FitCurves funcionaba, pero si volvía a plantear el problema, lo abordaría de manera diferente. En primer lugar, tuve que retocar la biblioteca para manejar la escritura rápida y la escritura rápida parece ser una buena forma de poner a prueba dicho algoritmo. Sin embargo, más importante aún, crearía un algoritmo de tiempo real que computa una curva a la vez al dibujar. Mantendré la parte central de FitCurves, que es un algoritmo que devuelve una curva única que mejor se ajusta a un conjunto de puntos, y personalizo el resto. –

+0

Enlace ahora muerto. Archivada aquí: https://web.archive.org/web/20090805204502/http://tog.acm.org/resources/GraphicsGems/gems/FitCurves.c y esto se ve como el nuevo enlace oficial: https://github.com/erich666/GraphicsGems/blob/master/gems/FitCurves.c /* un algoritmo para las curvas de montaje digitalizados automáticamente por Philip J. Schneider de gráficos "Gemas", Academic Press, 1990 * / – murkle

Cuestiones relacionadas