7

AS3(Flexではなく純粋)で手書きをシミュレートする「ブラシ」ツールを作成しようとしています。これにより、ストロークがコーナリングではなくスムーズになります。次に、トレースをドラッグして変形できる3次ベジェ曲線に縮小し、以前に描画したパスに影響を与える必要があります(イラストレーターのペンツールのように)。

マウスの動きを追跡して、パスを描画するための一連のポイントを取得しています。私の知る限り、そのポイントのセットを使用してBスプラインパスを実行する必要があります。次に、それを3次ベジェ曲線に縮小する必要があります(パスに「ペンツール」機能を追加します)。

私はすでに、3次ベジエを2次ベジエに減らすアルゴリズムを使用して(そしてFlashcurveTo関数を使用して)ペンツールを開発しました。しかし、Bスプライン(または別の簡略化)を作成し、それをベジェ曲線に縮小する方法がわかりません。

これを達成する方法を知っていますか?

4

4 に答える 4

6

jhotdrawは、描画用のJavaのオープンソースプロジェクトです。フリーハンドの描画を3次ベジェ曲線に変換します。ソースが利用可能です-ダウンロードして翻訳してください。プロジェクトのサイズを恐れないでください。必要なクラスは2つだけです。

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

翻訳中は、すべてのコレクション宣言を配列に変更することから始めます(FP10ユーザーのみを対象とする場合はベクトルを使用します)。変換に役立つ可能性のある正規表現がいくつかあります。必要に応じて投稿できます。


これはあなたが役に立つと思うかもしれない正規表現のリストです。各ペアで、最初のペアを検索テキスト領域に貼り付け、2番目のペアを置換領域に貼り付け、正規表現のチェックボックスをオンにして、[検索]ボタンと[置換]ボタンを使用します。使用しないでください Replace All -これらのどれも絶対確実であることが保証されていません。

int/double nameすべての宣言を次のように置き換えますvar name:Number

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

var $2:Number

Point2D.Double nameすべての宣言を次のように置き換えますvar name:Point

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

var $1:Point

int/double name関数シグニチャのすべての宣言を次のように置き換えますname:Number

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

($1$2:Number$3)

Point2D.Double name関数シグニチャのすべての宣言を次のように置き換えますname:Point

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

($1$2:Point$3)

メソッドシグネチャを変更する前に、すべてのメソッドが静的であることを確認してください。

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

メソッドシグネチャをAS形式に置き換えます

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

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

ArrayList.get(index)をarray [index]に置き換えます//警告:list.get(list.size()-1)で失敗します

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

$1[$2]

//avoid the () failure 

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

$1[$2]

ArrayList.set(index, element)//警告に置き換えarray[index] = element ます: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]

に置き換えarraylist.add(object)ます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)

メソッドシグネチャをAS形式に置き換えます(非静的メソッド)

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

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

int/double/point/boolean name関数シグニチャのすべての宣言を次のように置き換えますname:type

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

($1$3:$2$4)

独自の行のすべての変数宣言を=toAS形式に置き換えます

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

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

中括弧の配置を変更します。

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

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

に変更} elseします} \n else

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

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

1行の4つの変数宣言を別の行のASに置き換えます

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

配列宣言を置き換えます

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

$1 var $2:Array

削除()キャスト-ASコンパイラはそれらを好きではありません

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

$1

maxなどをMath.maxに置き換えます-ASには静的インポートがありません

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

Math.$1(
于 2009-11-19T17:11:30.953 に答える
1

この機能を1回使用しました。


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


于 2009-11-20T16:49:31.687 に答える
0

あなたが求めていることを行うacライブラリのアルゴリズムがあります:http: //tog.acm.org/resources/GraphicsGems/gems/FitCurves.c

これはかなり複雑なアルゴリズムであり、多くのポイントのリストをいくつかの近似ベジェ曲線のリストに変換し、基本的に落書きを非常に滑らかな曲線に変換することで、ジオメトリを単純化します。たるみの量を調整でき、特定のたるみ内のポイントのセットに適合するベジェ曲線の量を最小限に抑えることで機能します。したがって、アルゴリズムのスラックを高く設定するほど、書き込みはスムーズになります(ただし、精度が低下する可能性があります)。

于 2011-01-27T03:26:59.830 に答える
0

特にベジエが必要かどうかはわかりませんが、このcatmull-romスプラインツールは非常に優れています: http ://www.motiondraw.com/md/as_samples/t/CatmullRomSpline/tween.html

于 2009-12-01T19:13:21.140 に答える