代码之家  ›  专栏  ›  技术社区  ›  angularsen Bcelik

通过一条线连接两个WPF画布元素,而不使用锚?

  •  2
  • angularsen Bcelik  · 技术社区  · 15 年前

    我有一个画布用于绘制图表,并希望通过有向线(箭头端)连接图表中的节点。 我尝试了锚定方法,其中线条只附着在节点上的特定点上,但这对我来说不起作用,它看起来像垃圾。

    我只需要从每个对象的中心到另一个对象的一条线,并在节点的边缘停止该线,以便箭头端正确显示。但要找到画布元素的边缘来测试交叉点已经证明是困难的。

    有什么想法吗?

    1 回复  |  直到 15 年前
        1
  •  4
  •   angularsen Bcelik    15 年前

    我得到了一个使用元素边界框的方法。它不是完美的,因为我的元素不是完全矩形的,但是看起来不错。

    基本上,我在画布坐标中通过以下方式找到元素的边界框:

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

    还有Voice!这些线现在被绘制成从每个节点的中心到另一个节点的样子,但是它们大约停在节点的边缘,因此箭头端可见。

    这种方法的一个改进是针对节点本身的实际边缘进行测试,例如对于椭圆节点,但是我还没有找到一个WPF方法,它为我提供了一个可以测试的几何体或路径。