2012-11-06 14 views
6

スケルトン変換をシェイプに適用するときに、誰かがWPFシェイプレンダリングのデフォルトの動作をオーバーライドできるかどうかは疑問です。デフォルトの振る舞いでは、ストロークを含むシェイプ描画全体が変換されますが、ジオメトリの縮尺を変更したいだけです。難しいのは、私のシェイプが異なるレベル(2Dシーングラフのようなものですが、WPFビジュアルツリーのようなもの)にレンダリング変換を適用したビジュアル階層に存在することです。これは変更できません(!)。私はさまざまな場所で、レンダリングトランスフォームのトランスフォームを取り消し、代わりにジオメトリに配置するカスタムシェイプを作成することが可能であると読んでいます。ストロークに影響を与えずにWPFシェイプのジオメトリスケーリング

明確に明らかなように
public sealed class MyPath : Shape 
{ 
    // This class has a Data property of type Geometry just like the normal Path class 

    protected override Geometry DefiningGeometry 
    { 
     get 
     { 
      Geometry data = Data; 

      if (data == null) 
      { 
       data = Geometry.Empty; 
      } 

      return data; 
     } 
    } 

    protected override void OnRender(DrawingContext drawingContext) 
    { 
     Transform tr = RenderedGeometry.Transform; 
     Geometry geomToDraw = RenderedGeometry.Clone(); 
     geomToDraw.Transform = new MatrixTransform(tr.Value * tr.Value); 
     Matrix trInv = tr.Value; trInv.Invert(); 
     drawingContext.PushTransform(new MatrixTransform(trInv)); 
     drawingContext.DrawGeometry(Brushes.Transparent, new Pen() { Brush = Brushes.Black, Thickness = 1 }, geomToDraw); 
    } 
} 

、私はこれに非常に新しいですし、上記のコードは、おそらく完全に台無しにされています。現時点では私のようなものを持っています。私は最終的に得られるジオメトリ変換を変更せずに行列をジオメトリに転送しようとしていました。したがって、tr.Value * tr.ValueとtrInv。しかし、それは私が望むように動作しません。私はこのトランスフォーム変換技法が理論的には動作することを知っています。(Geometry.Transformをxで4倍にスケールし、0.25倍でスケールxにトランスフォームをプッシュするテストを行いましたが、結果のシェイプ描画は適用されませんでしたストレッチ=塗りつぶし、私は頼りにしている)。だから私はレンダリング変換に欠けているものがなければなりません。

動作していないテストシナリオはこれです:

  • 私はレンダリングスケールはXAMLでscaleXプロパティ= 4とscaleY = 1で変換を適用します。
  • 組み込みのPathクラスは、y方向よりもx方向の幅が4倍大きくなるように図面全体を拡大/縮小します。
  • 私はMyPathにストロークではなくジオメトリのみを拡大縮小します。 < - これは動作していません!
    • 何が起こるか:ジオメトリは正確にスケールされ、ストロークはx方向に4倍、y方向に4倍にスケーリングされます。なにが問題ですか? RenderedGeometry.Transformだけで作業するべきではないという気持ちがありますが、代わりに何を使うべきですか?私は、レンダリングトランスフォームとstretch =を塗りつぶすことが必要です。私のレンダートランスフォーム階層には、スケール、回転、および翻訳が混在している場合があります。そのため、ソリューションは、軸に沿ったスケーリングだけでなく、あらゆる変換を処理するのに十分一般的でなければなりません。

注:私はOnRenderのジオメトリを作成するために悪いです知っているが、私はそれをクリーンアップの時間を費やす前に作業を取得したいです。ところで

、私はこの記事をお読みください。

Invariant stroke thickness of Path regardless of the scale

問題を前に述べたように、私は考慮にトランスフォームをレンダリング取らなければならないと私は、そのソリューションを適応する方法を確認していないということですそれらと一緒に働く。

答えて

3

私が質問を正しく理解していれば、レンダリング変換の効果をペン上でキャンセルできますが、ジオメトリ上ではキャンセルしたくありません。

これは、反転を使用して変換を取り消したいアイテムに対するコントロールの変換を取得して、ペンの効果をキャンセルすることによって達成できます。 (たとえばP1/P2/P3/UrShapeの階層を持ち、P1、P2、P3にすべての変換があり、それらのすべてがあなたのペンに影響しないようにするには、P1の相対的な変換を取得する必要がありますUrShapeへ)。その後、変形をあなたの形状に再適用することができます。

var brush = new SolidColorBrush(Colors.Red); 
var pen = new Pen(brush, 5); 
//Instead of the direct parent you could walk up the visual tree to the root from where you want to cancel the transform 

var rootTransform = (MatrixTransform)this.TransformToAncestor((Visual)this.Parent); 

var inverserRootTransform = (MatrixTransform)rootTransform.Inverse; 

//We cancel out the transformation from the parent 
drawingContext.PushTransform(inverserRootTransform); 

var renderGeometry = this.Geometry.Clone(); 
// We apply the parent transform to the shape only, and group it with the original transform that was present on the shape 
// we do this to honor any transformation that was set on the shape. 
renderGeometry.Transform = new TransformGroup() 
{ 
    Children = 
    { 
     rootTransform, 
     this.Geometry.Transform 
    } 
}; 

//We draw the shape, the pen size will have the correct size since we canceled out the transform from the parent 
// but the shape now has the transformation directly on it. 
drawingContext.DrawGeometry(brush, pen, renderGeometry); 
drawingContext.Pop(); 
関連する問題