Domanda

Sto cercando di fare uno strumento 'pennello' in AS3 (puro, non Flex) che simula scrittura a mano, facendo colpi per essere liscia, invece di spalle al muro. Poi, la traccia deve essere ridotta alle curve di Bezier cubiche che possono essere trascinati e deformate, influenzare il percorso precedentemente disegnato (come strumento penna dell'illustratore).

Sono monitoraggio del movimento del mouse per ottenere un insieme di punti per disegnare il percorso. Per quanto ne so, ho bisogno di fare un percorso B-Spline utilizzando tale insieme di punti. Poi ho dovuto ridurlo a curve di Bezier cubi (aggiungendo la funzionalità 'strumento penna' al percorso).

ho già sviluppato lo strumento penna, utilizzando un algoritmo che riduce Beziers cubi a quadratica Beziers (e quindi usando la funzione Flash curveTo). Ma non ho idea di come creare una B-Spline (o un altro la semplificazione), uno poi ridurlo a curve di Bezier.

Conoscete qualche modo per ottenere questo?

È stato utile?

Soluzione

Il jhotdraw è un progetto opensource in Java per il disegno. Converte disegni a mano libera in curve di Bezier cubiche. La sorgente è disponibile - scaricare e tradurre. 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 si stanno prendendo di mira solo gli utenti FP10). Ho alcune espressioni regolari che potreste trovare utili nella conversione - posso postare se vuoi

.

Ecco un elenco di espressioni regolari che potreste trovare utile. In ogni coppia, incollare la prima nella ricerca di testo e la seconda in sostituzione zona, selezionare la casella di controllo regex e utilizzare Trova e sostituisci pulsanti. Non utilizzare Replace All -. Nessuno di questi sono garantiti per essere a prova di errore

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

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

var $2:Number

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

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

var $1:Point

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

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

($1$2:Number$3)

Sostituire tutte le dichiarazioni Point2D.Double name 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

Sostituire ArrayList.get (indice) con array [index] // Attenzione: non riesce per list.get (list.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 metodo firme per il formato (i metodi non statici)

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

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

Sostituire tutte le dichiarazioni int/double/point/boolean name nelle firme di funzione con name:type

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

($1$3:$2$4)

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

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

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

cambiamento immissione di parentesi graffe.

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

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

Sostituire le dichiarazioni di matrice

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

$1 var $2:Array

Rimuovi () casting - AS compilatore non piacciono

(?:\(\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(

Altri suggerimenti

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]);
            }
        }


C'è un algoritmo in una libreria C 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 un elenco di molti punti in una lista di alcuni stretti curve di Bezier montaggio, essenzialmente trasformando scarabocchi in curve molto morbide. Ha una quantità regolabile di allentamento, e opere di trovare il minor numero di curve di Bezier che misura il vostro insieme di punti entro un certo allentamento. Così il più alto si imposta il gioco dell'algoritmo, il più agevole (ma potenzialmente meno preciso) la tua scrittura diventa.

Non è sicuro se si specificamente bisogno di Beziers, ma questo strumento spline Catmull-ROM è abbastanza grande: http://www.motiondraw.com/md/as_samples/t/ CatmullRomSpline / tween.html

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top