12

次の画像は、私が達成しようとしていることを示しています。

Path基本的に、互いに「接触」する 2 つのオブジェクト (平行パス) を作成したいと考えています。これは、このイメージを生成するために使用される XAML です。

<StackPanel Orientation="Horizontal">
    <StackPanel.LayoutTransform>
        <ScaleTransform CenterX="0" CenterY="0" ScaleX="15" ScaleY="15" />
    </StackPanel.LayoutTransform>
    
    <Grid Margin="-5,0,0,0">
        <Path Stroke="Blue">
            <Path.Data>
                <PathGeometry>M10,10 C20,10 10,20 20,20</PathGeometry>
            </Path.Data>
        </Path>
        <Path Stroke="Red">
            <Path.Data>
                <PathGeometry>M10,11 C19,10.85 9,20.80 20,21</PathGeometry>
            </Path.Data>
        </Path>
    </Grid>
    
    <Grid Margin="-5,0,0,0">
        <Path Stroke="Blue">
            <Path.Data>
                <PathGeometry>M10,10 C20,10 10,20 20,20</PathGeometry>
            </Path.Data>
        </Path>
        <Path Stroke="Red">
            <Path.Data>
                <PathGeometry>M10,11 C19,11 9,21 20,21</PathGeometry>
            </Path.Data>
        </Path>
    </Grid>
</StackPanel>

最初の曲線は手動で最適化されたポイント位置を持ち、2 番目の曲線はストロークの太さを考慮して簡単に計算できるポイント位置を持ちます。2 番目の曲線が完全ではないことがわかります。これは、2 つの曲線の間にスペースがあるためです。すべての曲線を手動で最適化せずに、プログラムで 2 つの完全に「接触する」曲線を作成するにはどうすればよいですか (曲線はコードで生成されるため、実際には不可能です)。

簡単に言えばPath、コードで 1 つの曲線 (resp. ) を生成し、2 つの色が必要です。だから私は 2 番目Pathの平行にすればうまくいくと思ったGeometryのですが、2 番目の調整Path(平行にするため) には問題があることがわかっています。

更新 #1

Charles PetzoldによるParallel Lines and Curvesは、この問題を解決する 1 つの方法かもしれません。実際にはかなりうまく機能しますが、カーブが平坦になり、深くズームすると視覚的なアーティファクトが作成され、もちろんパフォーマンス上の欠点があります.

ただし、このアルゴリズムは、別のベジエ曲線に平行なベジエ曲線を見つけようとしません。代わりに、アルゴリズムは完全にポリラインに基づいています。入力は 1 つまたは複数のポリラインであり、出力は各入力ポリラインの複数のポリラインで構成されます。このため、ParallelPath は入力ジオメトリを「平坦化」する必要があります。つまり、ジオメトリ全体 (円弧とベジエ曲線を含む) をポリライン近似に変換する必要があります。

アップデート #2

そこで、私の友人 (数学博士のインセプター) がこの問題を分析し、(3 次)ベジエ曲線に平行な曲線を作成することは非常に複雑で、計算コストが高くなります。平行曲線の各点について、コンピューターは次のように計算する必要があります。

(degree 3 polynomial) + (degree 2 polynomial) / sqrt(degree 4 polynomial)

この式を最適化する方法はあるかもしれませんが、標準のベジエ曲線よりもはるかに計算コストがかかります (平行曲線は元のベジエ曲線とは完全に異なる曲線であるため)。曲線をアニメーション化できるようにしたいので、このソリューションはおそらく CPU の負荷が高すぎるでしょう。これにより、いくつかのオプションが残ります。

  1. Charles Petzoldの polyline approximationを使用してください。これは驚異的に機能しますが、深くズームすると視覚的な不具合が生じます。

  2. Charles Petzond の近似値に基づいて独自の近似値を導出します。線の代わりにベジエ曲線を使用します (おそらく円弧で十分でしょう)。これでディープ ズームの問題は解決しますが、おそらくコーディングが非常に難しいでしょう (これを行う方法がわかりません)。

  3. 二色ブラシみたいなのも作れそうです。このようにして、1 つだけを使用してPath目的の結果を得ることができます (最初の画像で示されているように)。どこでも見たことがないので、これはおそらくオプションではありません。

アップデート #3

非常に興味深いリンクをいくつか見つけました。

より詳しい情報:

  • Qt フレームワークの QPainterPathStroker は、平行曲線に Thomas F. Hain のアルゴリズムを使用することになっています。
  • このJava Strokerも平行曲線を描くことができるはずです。

たぶん最終的な解決策?(ソースはこちら

...ベジエ曲線理論について知っていることをすべて解決し、フラット化されていないオフセットを正しいものに発展させ、(モンスター)ベジエ曲線の入門書でそれを文書化しました


試み #1

2 番目のパスを少し広くして、Z-Index を使用しながら最初のパスの下にスライドさせます。 http://i51.tinypic.com/2r5vwjk.png

これは機能しませんGeometry。それに応じて を変換する必要があります。

4

6 に答える 6

6

1 つの 4 次ベジエ曲線を使用する代わりに、2 つの 2 次曲線の複合を使用しないのはなぜですか? ベジエ曲線の数学に精通していますか? これらは計算コストが非常に低いため、グラフィックスで好まれます。私は最近、細胞の動きをアニメーション化するプログラムを作成しました(楽しみのためだけに):

ここに画像の説明を入力

このプログラムは、100 個のブロブがアニメートされて動き回る HD モニターでフルスクリーンで簡単に実行できます。そして、それはすべてGDI +でした。

平行ベジエ曲線に関しては、ウィキペディアによると、実際には実行できません: http://en.wikipedia.org/wiki/B%C3%A9zier_curve

したがって、おそらくヒューリスティックなアプローチに満足する必要があります。

編集1:

曲線が完全にランダムにならないように、各曲線の輪郭を作成してからパスを塗りつぶしてみませんか? 一方のパスの「下」のカーブは、もう一方の「上」のカーブになります。

編集2:

わかりました、リクエストに応じて、「線路のような」ソリューションを計算できると私が想像する方法は次のとおりです。

ここに画像の説明を入力

于 2011-04-12T01:05:26.703 に答える
4

互いに接触する 2 つの Path オブジェクトを作成したいと言っていましたが、パスがどのように生成されるかについては述べていません。私の答えは、何らかのアルゴリズムによって既に生成されたパスがあり、これを2つの新しいパスに変えたいと仮定しています。

ストロークの使用から塗りつぶしの使用に切り替えます。2 番目の写真で赤いパスを自動的に作成できる場合は、両方から構成される結合されたパスを均等に作成し、ストロークで描画する代わりに塗りつぶすことができます。次に、同じことを 2 方向に行います。

あなたの例で得た結果は次のようになります。

結合されたパスを示す画像

<StackPanel Orientation="Horizontal">
    <StackPanel.LayoutTransform>
        <ScaleTransform CenterX="0" CenterY="0" ScaleX="15" ScaleY="15" />
    </StackPanel.LayoutTransform>

    <Grid Margin="-5,0,0,0">
        <Path Fill="Blue" Stroke="Transparent">
            <Path.Data>
                <PathGeometry>M10,10 C20,10 10,20 20,20 L20,19 C11,19 21,9 10,9</PathGeometry>
                <!--          |←    original path    →| |←  generated part   →| -->
            </Path.Data>
        </Path>
        <Path Fill="Red" Stroke="Transparent">
            <Path.Data>
                <PathGeometry>M10,10 C20,10 10,20 20,20 L20,21 C9,21 19,11 10,11</PathGeometry>
                <!--          |←    original path    →| |←   generated part   →| -->
            </Path.Data>
        </Path>
    </Grid>
</StackPanel>
于 2011-04-09T21:05:51.377 に答える
1

問題へのわずかに異なるアプローチを検討してください...

ジオメトリ上に「多数」のポイントがあると仮定します。より低いズーム レベルでジオメトリ ポイントをサンプリングすることにより、高品質の内挿法の 1 つを使用することが実行可能である場合があります。ズームが大きくなると、サンプリング レートを上げて、代わりに曲線のサブセットのみをレンダリングできます。このようにして、計算量はすべてのズーム レベルで比較的一定に保たれます。重要なのは、画面上に一定数のピクセルがあり、精度が一定のしきい値を超えたらポイントのサンプリングを開始できることです。

于 2011-04-12T03:08:28.523 に答える
1

これを読んでください... Silverlight - Epic Graphical Fail (2 つの三角形による四角形) :(

アップデート

これを試してください(少しやり過ぎですが、役立つかもしれません)

<Grid Margin="-5,0,0,0">
    <Path Stroke="Blue" Data="M10,10 C20,10 10,20 20,20 M20,21 C9,21 19,11 10,11"
            Fill="Blue" Clip="M10,10 C20,10 10,20 20,20 L20,21 C9,21 19,11 10,11"/>
    <Path Stroke="Blue" Data="M10,10 C20,10 10,20 20,20"/>
    <Path Stroke="Red" Data="M10,11 C19,11 9,21 20,21"/>
</Grid>

ここに画像の説明を入力

于 2011-04-13T11:46:00.417 に答える
0

幅 5 の 2 行が必要だとしましょう。

1 ピクセルの差が大きすぎない場合は、最初に赤で幅 11 の曲線を描き、次に同じパスで幅 1 の青で曲線を描き、側面の 1 つを青で塗りつぶします。

線を半分に分割し、半分に色を付けたはずです。問題は、半分に分割すると1ピクセルかかることです:(

しかし、10 のような均等な幅を選択するとどうなるでしょうか? 中央のピクセルはどこにありますか? たぶん、あなたは何かを悪用することができます...

于 2011-04-13T01:59:46.210 に答える
0

2 番目のパス (生成された) を少し広くして、z-index を使用して最初のパスの下 (後ろ) にスライドさせることは可能ですか? そうすればシームレスに参加できます。

于 2011-04-07T22:14:04.723 に答える