次の画像は、私が達成しようとしていることを示しています。
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 の負荷が高すぎるでしょう。これにより、いくつかのオプションが残ります。
Charles Petzoldの polyline approximationを使用してください。これは驚異的に機能しますが、深くズームすると視覚的な不具合が生じます。
Charles Petzond の近似値に基づいて独自の近似値を導出します。線の代わりにベジエ曲線を使用します (おそらく円弧で十分でしょう)。これでディープ ズームの問題は解決しますが、おそらくコーディングが非常に難しいでしょう (これを行う方法がわかりません)。
二色ブラシみたいなのも作れそうです。このようにして、1 つだけを使用して
Path
目的の結果を得ることができます (最初の画像で示されているように)。どこでも見たことがないので、これはおそらくオプションではありません。
アップデート #3
非常に興味深いリンクをいくつか見つけました。
- 三次ベジエ曲線をオフセットする方法は? (ヒューリスティックアルゴリズム)
- 3 次ベジエ曲線のストロークの概要
- ベジエ パス拡張( Python アルゴリズム)
- Offset Bézier Curves (カスタム ポリライン ベジエ曲線近似の Java 実装。実装は Charles Petzold のものとは異なります)
- Parallel Bézier (数学の観点から平行ベジエ曲線が不可能な理由)
- 立方ベジエ パスとオフセット カーブ ペーパーの高速で正確な平坦化 (ダウンロード リンク 1、 ダウンロード リンク 2 )
より詳しい情報:
- Qt フレームワークの QPainterPathStroker は、平行曲線に Thomas F. Hain のアルゴリズムを使用することになっています。
- このJava Strokerも平行曲線を描くことができるはずです。
たぶん最終的な解決策?(ソースはこちら)
...ベジエ曲線理論について知っていることをすべて解決し、フラット化されていないオフセットを正しいものに発展させ、(モンスター)ベジエ曲線の入門書でそれを文書化しました
試み #1
2 番目のパスを少し広くして、Z-Index を使用しながら最初のパスの下にスライドさせます。 http://i51.tinypic.com/2r5vwjk.png
これは機能しませんGeometry
。それに応じて を変換する必要があります。