2009-04-07 11 views
21

Pathオブジェクトを使用してキャンバス上に描画されたCADアプリケーションのように、wpfを使用してアプリケーションを開発しています。 キャンバスを拡大/縮小するときに、キャンバス内のすべての要素が拡大縮小され、これが必要な振る舞いですが、これによってもパスの線の太さが増加するというわずかな問題が発生しました。スケールに関係なく、Pathの不変ストロークの厚み

オブジェクトを拡大/拡大/拡大する方法はありますか?それでもパスのストロークの太さは同じです。

この点に関する助けは私にとって非常に役に立ちます。

答えて

6

最後に、私は上記の解決策の回避策を得ました。私はCanvasのスケーリングに対してPathStrokeThicknessを設定することでそれを行いました。このよう

// scale = scaling factor applied to the canvas 
path.StrokeThickness = 1.0/scale; 

のみ動作ScaleXScaleYが均一である場合。

+13

これはあなたのxとyスケールが均一である場合には罰金ですが、スケールが同じでない場合は動作しません。 – Klay

13

より良い解決策は、あなたのパスを保存するために、1つ以上のSystem.Windows.Media.Geometryオブジェクトを使用することであろう、ポイントなど

あなたが実際にストロークを変えることができるように、この形状は、ペンで描画することができますTransformプロパティを使用するのがより柔軟になります。

トランスフォームを使用すると、視覚化ではなく、幾何学的表現の実際の座標を「ズーム」することができます。描画するとき、レンダリング変換を行う必要はありません。 FromPositionがのRectは、形質転換されていない境界を含まなければならない、とtoPositionのRectが変換範囲を含める必要がどこ

public static Matrix TransformShape(Rect fromPosition, Rect toPosition, bool flipVertical) { 
    Matrix translateThenScale = Matrix.Identity; 
    //we first translate to origin since that's just easier 
    translateThenScale.Translate(-fromPosition.X, -fromPosition.Y); 
    //now we scale the graph to the appropriate dimensions 
    translateThenScale.Scale(toPosition.Width/fromPosition.Width, toPosition.Height/fromPosition.Height); 
    //then we flip the graph vertically around the viewport middle since in our graph positive is up, not down. 
    if (flipVertical) 
     translateThenScale.ScaleAt(1.0, -1.0, 0.0, toPosition.Height/2.0); 
    //now we push the graph to the right spot, which will usually simply be 0,0. 
    translateThenScale.Translate(toPosition.X, toPosition.Y); 

    return translateThenScale; 
} 

は、私は次のように次のコードを使用し、変換を計算します。これはまた、XとYを別々にスケーリングすることも可能で、これはしばしばプロットに必要です。

それはあなたの幾何学の限界を計算するのは簡単です:

Geometry graphGeom; 
//[...] 
//the bounds are modified by the transform, so we want no transform!  
graphGeom.Transform = Transform.Identity; 
Rect graphBounds = graphGeom.Bounds; 
//then set the transform again 

//or, if the transform is axis-aligned, the following _should_ work: 
Rect graphBoundsAlt = graphGeom.Transform.Inverse.TransformBounds(graphGeom.Bounds); 

そしてもちろんのWPFは、あなたはそれが必要である必要があり、にレンダリングする必要がある境界たことを伝えることができます。それを一緒に入れて、あなたはこのソリューションを使用することの利点は、あなたが自由に使用するなら、RenderTransformsを台無しにする必要がないことです

public void RecomputeTransform(Rect targetRect, bool flipVertical) { 
    graphGeom.Transform = Transform.Identity; 
    Rect graphBounds = graphGeom.Bounds; 
    Matrix transMat = TransformShape(graphBounds,targetRect,flipVertical); 
    graphGeom.Transform = new MatrixTransform(transMat); 
} 

ような何かを行うことができ、そのせん断および/またはスケールXとYを変換しますあなたのラインに奇妙な歪みが無くても、ペンを不透明なオブジェクトとして扱うことができます(UIからカスタマイズする方が簡単です - ペン幅などを選択した場合、それ以上の修正は必要ありません)。

+0

私は、このソリューションを使用すると、縮尺を変えたいと思わない部分を、メインのキャンバスとは別のものにする必要があると思います。例としては、図面自体が縮尺されているが、アンカーポイントのビジュアルとそのような縮尺は位置的にはあるが太さなどはないベクトル描画アプリケーションです。私はこの前提で正しいですか? – jpierson

+0

申し訳ありませんが、私はあなたの質問をかなり*理解していません...確かに、これは理想化された線や点を気にするベクトル描画のシナリオで行います。この手法は、線幅を変換せずに線画をスケーリング(またはその他の方法で線形変換)します。つまり、あなたは理想化されたジオメトリを変換しているに過ぎず、それをもちろん "ゼロ"の幅の線を持つ "実際の"形状に変換しています。 'Drawing'を変形させるならば、line withsやline joinなどの細部を変えるでしょう。それはそれを明確にしていますか? –

+0

私はそう思っています。私の前提は、図面アプリケーションの中には、図面や、デシメータのようなもののうち、太さの点ではスケールされていないものの、描画線が太さでスケーリングされるが、選択されたオブジェクトに対して示されるアンカーポイントは同じ方法でスケーリングされないInkscapeのようなベクトル描画アプリケーションなど。だから私の前提は、.NETでこれを達成することです。それでも、独立してスケールされた2つの別々のパネルにこれらの部品を配置する必要があります。 – jpierson

0

私はここ数回ここに戻ってきましたが、このアイデアはちょうど私に起こりました。それをViewboxでラップするのはどうですか?

これを試すことができます:高さ/幅をつぶすことは、厚さとサイズの比を変更すべきではありません。たぶんそれは私がまだ発見していない他の悪いことをします...

<Viewbox Height="50" Width="50"> 
    <Path Stroke="Black" Fill="Black" StrokeThickness="0.8" Stretch="Uniform" 
       Data="M0,0 20,20" /> 
</Viewbox> 
関連する問題