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 種類) のコレクションが含まれています。すべてを反復処理し、実際の長さを計算して合計することができます。

私が思うに、その価値のある1回限りの投資です。少しジオメトリをブラッシュアップする必要がありますが、最近では Google がすべてを簡単にしてくれます。

于 2011-03-04T19:32:50.443 に答える