问题描述
我有一个用于绘制图形的画布,并且希望通过有向线(箭头两端)连接图中的节点.我尝试了锚点方法,该方法仅将线附加在节点上的特定点处,但对我而言不起作用,看起来像胡扯.
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.
有什么想法吗?
推荐答案
我有一种使用元素边界框的方法.这不是完美的,因为我的元素不是完美的矩形,但是看起来还可以.
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.
基本上,我可以通过以下方式在Canvas坐标中找到元素的边界框:
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));
}
然后我找到中心到中心线与边界框四个侧面中的每一个的交点,并使用该交点通过Line形状连接两个元素.
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.
我在第三方忍者"中找到了相交代码: http://thirdpartyninjas.com/blog/2008/10/07 /line-segment-intersection/
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.
对此方法的一种改进是针对节点本身的实际边缘进行测试,例如用于椭圆节点,但是我还没有找到一种WPF方法,可以为我提供可以针对其进行测试的Geometry或Path.
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.
这篇关于通过一条线连接两个WPF画布元素,而无需使用锚点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!