2009-11-19 7 views
7

Sto provando a creare uno strumento "pennello" in AS3 (puro, non flessibile) che simula la scrittura a mano, rendendo i tratti fluidi anziché angolati. Quindi, la traccia deve essere ridotta a curve cubiche di tipo bezier che possono essere trascinate e deformate, influenzando il tracciato precedentemente disegnato (come lo strumento penna dell'illustratore).Creazione di un percorso uniforme da un numero irregolare di x, y punti per simulare la scrittura a mano

Sto seguendo il movimento del mouse per ottenere una serie di punti per tracciare il percorso. Per quanto ne so, ho bisogno di fare un percorso B-Spline usando quel set di punti. Quindi dovrei ridurlo a curve cubiche di bezier (aggiungendo la funzionalità 'pen tool' al percorso).

Ho già sviluppato lo strumento penna, utilizzando un algoritmo che riduce Beziers cubici in Bezier quadratici (e quindi utilizzando la funzione Curva flash). Ma non ho idea di come creare una B-Spline (o un'altra semplificazione), quindi ridurla alle curve di Bezier.

Conosci qualche modo per realizzare questo?

+0

sto cercando la stessa cosa ma javascript, ne conosci qualcuno? – igor

risposta

7

Il jhotdraw è un progetto opensource in Java per il disegno. Converte i disegni a mano libera in curve cubiche più bezier. La fonte è disponibile - scarica e traduci. Non avere paura alla dimensione del progetto: è necessario solo un paio di classi e cioè:

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

Durante la traduzione di avvio modificando tutte le dichiarazioni di raccolta per array (vettori di uso se ci si rivolge solo agli utenti FP10) . Ho alcune espressioni regolari che potresti trovare utili nella conversione: posso pubblicarle se vuoi.


Ecco un elenco di espressioni regolari che potrebbero essere utili. In ciascuna coppia, incolla il primo nell'area di testo di ricerca e il secondo nell'area di sostituzione, seleziona la casella di controllo regolare e utilizza i pulsanti Trova e sostituisci. Non utilizzareReplace All- nessuno di questi è sicuro di essere infallibile.

sostituire tutte int/double name dichiarazioni con le var name:Number

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

var $2:Number 

Sostituire tutte Point2D.Double name dichiarazioni con le var name:Point

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

var $1:Point 

Sostituire tutte le dichiarazioni in int/double name firme di funzione con name:Number

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

($1$2:Number$3) 

sostituire tutti i Point2D.Double name dichiarazioni nelle firme di funzione con name:Point

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

($1$2:Point$3) 

Prima di cambiare metodo di firme, assicurarsi che tutti i metodi sono statici:

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

Sostituire metodo firme per AS formato

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

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

Sostituisci ArrayList.get (index) con array [index] // Attenzione: fallisce per list.get (lista.size() - 1)

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

$1[$2] 

//avoid the() failure 

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

$1[$2] 

Sostituire ArrayList.set(index, element) con array[index] = element // Attenzione: non riesce per 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] 

Sostituire 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) 

Sostituire le firme del metodo in formato AS (metodi non statici)

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

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

Sostituire tutti int/double/point/boolean name dichiarazioni di firme di funzione con name:type

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

($1$3:$2$4) 

Sostituire tutte dichiarazioni di variabili in una propria linea con un = AS formato

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

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

cambiamento sistemazione di bretelle.

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

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

cambiamento } else in } \n else

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

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

Sostituire 4 dichiarazioni di variabili in una singola linea di AS in diverse linee

^(\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 

dichiarazioni di matrice Sostituire

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

$1 var $2:Array 

Rimuovi() casting - AS compilatore non come loro

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

$1 

Sostituire max ecc in Math.max - AS non ha le importazioni statiche

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

Math.$1(
+0

Ho controllato la libreria e sembra fantastica. L'applicazione di disegno di esempio fa esattamente quello che voglio. Grazie per il riferimento – yizzreel

+0

Ecco le regex di cui stavo parlando. – Amarghosh

+0

Che lavoro fantastico !! Ho già iniziato a portare il codice Java su AS3, non sembra essere un compito difficile, ma questo accelererà enormemente il processo. Molte grazie. – yizzreel

1

Ho usato questa funzione una sola volta.

 

    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

C'è un algoritmo in libreria ac che fa quello che si sta chiedendo: http://tog.acm.org/resources/GraphicsGems/gems/FitCurves.c

Questo è un algoritmo piuttosto complesso che semplifica la geometria convertendo una lista di molti punti in una lista di alcune curve bezier adiacenti, essenzialmente trasformando gli scarabocchi in curve molto lisce. Ha una quantità regolabile di allentamento e funziona trovando la minor quantità di curve di Bezier che si adattano al tuo gruppo di punti all'interno di un certo intervallo. Quindi più alto si imposta il gioco dell'algoritmo, più agevole (ma potenzialmente meno accurato) si ottiene la tua scrittura.

+0

Ehi! Grazie! questo sembra bello !. Sto già usando l'algoritmo jHotDraw (semplificato), e funziona praticamente come il codice che mi hai collegato. Tuttavia, guarderò anche a questo. E sembra che ci siano più fonti nel sito web in cui si trova il file. Grazie ancora per il riferimento! – yizzreel

+0

Aggiornamento rapido: la libreria di FitCurves ha funzionato, ma se avessi risolto il problema, l'approccio sarebbe stato diverso. Prima di tutto ho dovuto modificare la libreria per gestire la scrittura veloce. La scrittura veloce sembra essere un buon modo per mettere alla prova questo algoritmo. Ancora più importante, però, vorrei creare un algoritmo in tempo reale che calcoli una curva alla volta mentre disegni. Manterrei la parte centrale di FitCurves, che è un algoritmo che restituisce una curva singola che si adatta meglio a un insieme di punti e personalizza il resto. –

+0

Link ora morto. Archiviato qui: https://web.archive.org/web/20090805204502/http://tog.acm.org/resources/GraphicsGems/gems/FitCurves.c e questo appare come il nuovo link ufficiale: https://github.com/erich666/GraphicsGems/blob/master/gems/FitCurves.c /* Un algoritmo per automaticamente montaggio Curve digitalizzati di Philip J. Schneider da "grafica Gems", Academic Press, 1990 * / – murkle

Problemi correlati