Getting length of a PathGeometry (lines) in C#/WPF

谁都会走 提交于 2019-12-22 08:26:32

问题


If I have a closed path, I can use Geometry.GetArea() to approximate the area of my shape. This is great and saves me a lot of time. But is there anything around that will help me find the length of a unclosed path?

The best I've been able to come up with for now is to make sure I am using PathGeometry and call the GetPointAtFractionLength method multiple times, get the points and add up the distance between all those points.

Code:

    public double LengthOfPathGeometry(PathGeometry path, double steps)
    {
        Point pointOnPath;
        Point previousPointOnPath;
        Point tangent;

        double length = 0;

        path.GetPointAtFractionLength(0, out previousPointOnPath, out tangent);

        for (double progress = (1 / steps); progress < 1; progress += (1 / steps))
        {
            path.GetPointAtFractionLength(progress, out pointOnPath, out tangent);
            length += Distance(previousPointOnPath, pointOnPath);
            previousPointOnPath = pointOnPath;
        }
        path.GetPointAtFractionLength(1, out pointOnPath, out tangent);
        length += Distance(previousPointOnPath, pointOnPath);

        return length;
    }

    public static double Distance(Point p0, Point p1)
    {
        return Math.Sqrt((Math.Pow((p1.X - p0.X),2) + Math.Pow((p1.Y - p0.Y),2)));
    }

Usage (XAML):

    <Path Stroke="Beige" StrokeThickness="5" x:Name="Robert">
        <Path.Data>
            <PathGeometry x:Name="Bob">
                <PathGeometry.Figures>
                    <PathFigure StartPoint="20,10" IsClosed="False" IsFilled="False">
                        <PathFigure.Segments>
                            <BezierSegment
                                Point1="100,50"
                                Point2="100,200"
                            Point3="70,200"/>
                            <LineSegment Point="200,300" />
                            <ArcSegment
                                  Size="50,50" RotationAngle="45"
                                  IsLargeArc="True" SweepDirection="Counterclockwise"
                             Point="250,150"/>
                            <PolyLineSegment Points="450,75 190,100" />
                            <QuadraticBezierSegment Point1="50,250" Point2="180,70"/>
                        </PathFigure.Segments>
                    </PathFigure>
                </PathGeometry.Figures>
            </PathGeometry>
        </Path.Data>
    </Path>

Usage (Code):

double length = LengthOfPathGeometry(Bob, 10000);

For this example the result returned should be somewhere around: 1324.37

This seems to work out fine, but has its flaws. If I want a more accurate number for a very large line, I need more steps. And if you get above 100000 steps, you run into a long time to approximate. A couple of seconds per method call on my test machine.

Does anyone know a better way to approximate a length of any shape of line?


回答1:


For a quicker approximation call GetFlattenedPathGeometry, which will convert your path to a series of straight lines, and add up the line lengths.

This is pretty much doing the same thing as your existing code except that it selects the line segments more intelligently (e.g. the number of segments a bezier curve is split into depends on the curvature) so you'll have orders of magnitude fewer points for the same accuracy.




回答2:


Why do you want to approximate the length? Why not calculate the actual length?

A PathGeometry contains a collection of PathFigures. Each PathFigure contains a collection of PathSegments(7 types in total at the moment). You can iterate over everything and calculate the actual lengths and add them up.

Its a one time investment worth doing I think. You'll need to brush up a little geometry but Google makes everything easy these days.



来源:https://stackoverflow.com/questions/5198204/getting-length-of-a-pathgeometry-lines-in-c-wpf

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