Получение длины PathGeometry (линии) в C # / WPF - PullRequest
4 голосов
/ 04 марта 2011

Если у меня есть замкнутый путь, я могу использовать Geometry.GetArea() для аппроксимации площади моей фигуры. Это здорово и экономит мне много времени. Но есть ли что-нибудь вокруг, что поможет мне найти длину незамкнутого пути?

Лучшее, что я смог придумать на данный момент, это убедиться, что я использую PathGeometry и несколько раз вызываю метод GetPointAtFractionLength, получаю очки и складываю расстояние между всеми этими точками.

Код:

</p> <pre><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))); }

Использование (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 шагов, вы наталкиваетесь на то, чтобы приблизиться. Пара секунд на вызов метода на моей тестовой машине.

Кто-нибудь знает лучший способ приблизить длину любой формы линии?

Ответы [ 2 ]

6 голосов
/ 04 марта 2011

Для более быстрого приближения вызовите GetFlattenPathGeometry, который преобразует ваш путь в серию прямых линий и сложит длины линий.

Это в значительной степени делает то же самое, что и существующий код, за исключением того, что он выбирает отрезки линии более разумно (например, количество сегментов, на которые разбивается кривая Безье, зависит от кривизны), поэтому у вас будет на порядки меньше очки за одинаковую точность.

2 голосов
/ 04 марта 2011

Почему вы хотите приблизить длину?Почему бы не рассчитать фактическую длину?

PathGeometry содержит коллекцию PathFigures .Каждый PathFigure содержит коллекцию PathSegments (всего 7 типов на данный момент).Вы можете перебирать все, вычислять фактические длины и складывать их.

Думаю, это стоит потратить один раз.Вам нужно немного освежить геометрию, но в наши дни Google упрощает все.

...