Соединение двух элементов холста WPF линией, без использования якорей?

StackOverflow https://stackoverflow.com/questions/1737509

Вопрос

У меня есть холст для построения диаграмм, и я хочу соединить узлы на диаграмме направленными линиями (концы стрелок).Я попробовал подход привязки, при котором линии прикрепляются только в определенных точках узлов, но у меня это не сработало, выглядело дерьмово.

Я просто хочу провести линию от центра каждого объекта к другому и остановить линию на краю узлов, чтобы конец стрелки отображался должным образом.Но найти край элемента canvas для проверки пересечений оказалось непросто.

Есть какие-нибудь идеи?

Это было полезно?

Решение

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

В принципе, я нахожу ограничивающую рамку элемента в координатах Canvas с помощью:

    private static Rect GetBounds(FrameworkElement element, UIElement visual)
    {
        return new Rect(
            element.TranslatePoint(new Point(0, 0), visual),
            element.TranslatePoint(new Point(element.ActualWidth, element.ActualHeight), visual));
    }

Затем я нахожу пересечение межцентровой линии с каждой из четырех сторон ограничивающей рамки и использую эту точку пересечения, чтобы соединить два элемента линией.

Я нашел код пересечения у сторонних Ninjas:http://thirdpartyninjas.com/blog/2008/10/07/line-segment-intersection/

private void ProcessIntersection()
    {
        float ua = (point4.X - point3.X) * (point1.Y - point3.Y) - (point4.Y - point3.Y) * (point1.X - point3.X);
        float ub = (point2.X - point1.X) * (point1.Y - point3.Y) - (point2.Y - point1.Y) * (point1.X - point3.X);
        float denominator = (point4.Y - point3.Y) * (point2.X - point1.X) - (point4.X - point3.X) * (point2.Y - point1.Y);

        intersection = coincident = false;

        if (Math.Abs(denominator) <= 0.00001f)
        {
            if (Math.Abs(ua) <= 0.00001f && Math.Abs(ub) <= 0.00001f)
            {
                intersection = coincident = true;
                intersectionPoint = (point1 + point2) / 2;
            }
        }
        else
        {
            ua /= denominator;
            ub /= denominator;

            if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1)
            {
                intersection = true;
                intersectionPoint.X = point1.X + ua * (point2.X - point1.X);
                intersectionPoint.Y = point1.Y + ua * (point2.Y - point1.Y);
            }
        }
    }

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

Улучшением этого метода было бы тестирование по фактическому краю самого узла, например, для эллиптических узлов, но мне еще предстоит найти метод WPF, который предоставляет мне геометрию или Контур, с которыми я мог бы протестировать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top