【问题标题】:Getting length of a PathGeometry (lines) in C#/WPF在 C#/WPF 中获取 PathGeometry(行)的长度
【发布时间】:2011-07-09 01:34:08
【问题描述】:

如果我有一个封闭的路径,我可以使用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 步,你会遇到很长的时间来近似。在我的测试机器上,每个方法调用需要几秒钟。

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

【问题讨论】:

  • 解决方案见here

标签: c# wpf path pathgeometry


【解决方案1】:

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

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

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

【讨论】:

  • 如果我需要更准确的数字,这可能是未来移动的方式。我一直在寻找最简单的方法来抓住并继续获得长度。贝塞尔曲线只能近似,但我确信有比我的蛮力更准确和有效的方法来获得这种近似。
【解决方案2】:

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

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

【讨论】:

  • 正是我想要的。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-08
  • 2011-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-15
相关资源
最近更新 更多