Invariant stroke thickness of Path regardless of the scale

橙三吉。 提交于 2019-12-18 11:45:46

问题


We are using wpf to develop a cad like application where drawings placed on the canvas using the Path object. I just ran into a slight issue that whenver i scale/zoom my canvas, all the elements in the canvas get scaled and this is the behaviour i wanted but this also increases the stroke thickness of the Path.

Is there a way by which i increase/scale/zoom the objects but still i maintain the same stroke thickness of the path.

Any help in this regard will be very useful for me.


回答1:


A better solution would be to use one or more System.Windows.Media.Geometry object to store your paths, points etc.

This geometry can be drawn with a Pen, so you could indeed change the stroke thickness when you zoom, but more flexible is to use the Transform property.

Using the transform, you can "zoom" the actual coordinates of the geometric representation and not the visualization - so when you draw it, you don't need to fiddle with render transforms.

To compute the transform, I use the following code like:

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

where the fromPosition Rect should contain the untransformed bounds, and the toPosition Rect should contain the transformed bounds. This also trivially allows for scaling X and Y separately, which is often necessary for plotting.

It's easy to compute the bounds of your geometry:

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

And of course WPF can tell you which bounds you need to render into, should that be necessary. Putting it together, you could do something like

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

The advantage of using this solution is that you don't need to mess with RenderTransforms, you're free to use transforms that shear and/or scale X and Y independently without getting weird distortions in your lines, and you can treat the Pen as an opaque object (i.e. easier to customize from the UI - if you select Pen width or whatnot, no further correction is necessary).




回答2:


Finally I got the workaround for the above solution. I did it by setting the StrokeThickness of the Path relative to the scaling of the Canvas.

Like this:

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

This only works if ScaleX and ScaleY are uniform.




回答3:


I think you needed YourPathObject.RenderedGeometry.Transform property




回答4:


I've been back here several times, but this idea just occurred to me, how about just wrapping it in a Viewbox?

You can try this: messing with the Height/Width shouldn't change the ratio of thickness to size. Maybe it does other bad things that I haven't discovered yet...

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


来源:https://stackoverflow.com/questions/724139/invariant-stroke-thickness-of-path-regardless-of-the-scale

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!