4

如果我有一条封闭的路径,我可以用它Geometry.GetArea()来近似我的形状区域。这很棒,节省了我很多时间。但是周围有什么可以帮助我找到未闭合路径的长度吗?

我现在能想到的最好的方法是确保我多次使用PathGeometry并调用该方法,获取点并添加所有这些点之间的距离。GetPointAtFractionLength

代码:

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

用法(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>

用法(代码):

double length = LengthOfPathGeometry(Bob, 10000);

对于这个例子,返回的结果应该在某个地方:1324.37

这似乎很好,但有其缺陷。如果我想要一个非常大的线的更准确的数字,我需要更多的步骤。如果你超过 100000 步,你会遇到很长的时间来近似。在我的测试机器上,每个方法调用需要几秒钟。

有谁知道更好的方法来近似任何形状的线的长度?

4

2 回答 2

7

要获得更快的近似值,请调用 GetFlattenedPathGeometry,它将您的路径转换为一系列直线,并将线长相加。

这几乎与您现有的代码做同样的事情,除了它更智能地选择线段(例如,贝塞尔曲线分割成的段数取决于曲率),因此您将有数量级更少的点相同的准确性。

于 2011-03-04T20:07:42.900 回答
2

为什么要近似长度?为什么不计算实际长度?

PathGeometry 包含PathFigures的集合。每个 PathFigure 都包含一组PathSegments(目前共有 7 种类型)。您可以遍历所有内容并计算实际长度并将它们相加。

我认为这是一次值得做的投资。您需要重新学习一些几何图形,但如今 Google 让一切变得简单。

于 2011-03-04T19:32:50.443 回答