无论比例如何,Path的不变行程厚度

时间:2009-04-07 04:27:28

标签: wpf path

我们正在使用wpf开发一个类似cad的应用程序,其中绘图使用Path对象放置在画布上。 我只是遇到了一个小问题,当我缩放/缩放画布时,画布中的所有元素都会缩放,这就是我想要的行为,但这也增加了路径的笔触粗细。

有没有办法增加/缩放/缩放对象,但仍保持路径的笔触粗细。

这方面的任何帮助对我都非常有用。

5 个答案:

答案 0 :(得分:13)

更好的解决方案是使用一个或多个System.Windows.Media.Geometry对象来存储路径,点等。

可以使用Pen绘制此几何体,因此在缩放时确实可以更改笔触粗细,但更灵活的是使用“变换”属性。

使用变换,您可以“缩放”几何表示的实际坐标而不是可视化 - 所以当您绘制它时,您不需要使用渲染变换。

要计算变换,我使用以下代码:

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

其中fromPosition Rect应包含未转换的边界,而toPosition Rect应包含转换的边界。这也简单地允许分别缩放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可以告诉你需要渲染哪些边界。把它放在一起,你可以做类似

的事情
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);
}

使用此解决方案的优点是您不需要使用RenderTransforms,您可以自由地使用剪切和/或缩放X和Y的变换,而不会在您的线条中产生奇怪的扭曲,并且您可以对待笔作为不透明对象(即更容易从UI自定义 - 如果选择笔宽或诸如此类,则无需进一步校正)。

答案 1 :(得分:7)

最后,我得到了上述解决方案的解决方法。我是通过相对于StrokeThickness的缩放设置Path的{​​{1}}来完成的。

像这样:

Canvas

仅当// scale = scaling factor applied to the canvas path.StrokeThickness = 1.0 / scale; ScaleX统一时才有效。

答案 2 :(得分:1)

有同样的问题,解决方法非常简单。

  1. 使用几何定义要创建的图形
  2. 让路径形状呈现您的几何形状
  3. 将变换应用于您的几何图形,路径形状将自动更新

例如:

// Create your geometry
var rectGeometry = new RectangleGeometry(new Rect(0, 0, 200, 200));
// Let the Path Shape paint your geometry
var path = new Path();
path.Data = rectGeometry;
path.StrokeThickness = 2;
// Modify your geometry, NOT the Path shape
var scaleTransform = new ScaleTransform();
rectGeometry.Transform = scaleTransform;
scaleTransform.ScaleX = 2;
scaleTransform.ScaleY = 1.5;

答案 3 :(得分:0)

我已经多次回到这里,但这个想法刚刚发生在我身上,如何将它包装在Viewbox中呢?

你可以试试这个:弄乱高度/宽度不应该改变厚度与尺寸的比例。也许它还有其他我尚未发现的坏事......

<Viewbox Height="50" Width="50">
    <Path Stroke="Black" Fill="Black" StrokeThickness="0.8" Stretch="Uniform" 
                 Data="M0,0 20,20" />
</Viewbox>

答案 4 :(得分:0)

我认为您需要YourPathObject.RenderedGeometry.Transform属性