Connecting two WPF canvas elements by a line, without using anchors?

拈花ヽ惹草 提交于 2019-12-18 07:12:22

问题


I have a canvas for diagramming, and want to join nodes in the diagram by directed lines (arrow ends). I tried the anchor approach, where lines only attach at specific points on the nodes but that did not work for me, it looked like crap.

I simply want a line from the centre of each object to the other, and stop the line at the nodes' edge in order for the arrow end to show properly. But finding the edge of a canvas element to test intersections against has proven difficult.

Any ideas?


回答1:


I got a method working using the bounding box of the element. It is not perfect, since my elements are not perfectly rectangular, but it looks OK.

Basically I find the bounding box of the element in Canvas coordinates by:

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

Then I find the intersection of the centre-to-centre line against each of the four sides of the bounding box, and use that intersection point to connect the two elements by a Line shape.

I found the intersection code at Third Party 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);
            }
        }
    }

And voilá! The lines are now drawn as if they go from the centre of each node to the other, but stops approximately at the node's edge so the arrow end is visible.

An improvement of this method would be to test against the actual edge of the node itself, such as for elliptical nodes, but I have yet to find a WPF method that provides me with a Geometry or Path that I can test against.



来源:https://stackoverflow.com/questions/1737509/connecting-two-wpf-canvas-elements-by-a-line-without-using-anchors

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!