Ale*_*nov 8 c# wpf layout visualization graph
我想呈现漂亮的径向树布局,有点笨拙的弯曲边缘.问题在于,源点和目标点之间的角度不同,边缘的绘制方式也不同.提供的图片来自单个图表,因此您可以看到它们对于不同的边缘方向有何不同.我认为关键在于beizer曲线控制点生成,我只是无法理解如何修复它们.
无论边缘的方向是什么,我希望它们以相同的方式绘制.
我如何在Pic1中实现这一目标?我如何在Pic2中实现这一目标?
像这里:https://bl.ocks.org/mbostock/4063550
谢谢!
码:
//draw using DrawingContext of the DrawingVisual
//gen 2 control points
double dx = target.X - source.X, dy = target.Y - source.Y;
var pts = new[]
{
new Point(source.X + 2*dx/3, source.Y),
new Point(target.X - dx/8, target.Y - dy/8)
};
//get geometry
var geometry = new StreamGeometry { FillRule = FillRule.EvenOdd };
using (var ctx = geometry.Open())
{
ctx.BeginFigure(START_POINT, false /* is filled */, false /* is closed */);
ctx.BezierTo(pts[0], pts[1], END_POINT, true, false);
}
geometry.Freeze();
//draw it
dc.DrawGeometry(DrawingBrush, DrawingPen, geometry);Run Code Online (Sandbox Code Playgroud)
更新1: 我使用以下公式获得弧度中前一个顶点和源之间的角度:Math.Atan2(prev.Y - source.Y,source.X - prev.X); 但我仍然像Pic.4中那样得到了优势.
更新2 branchAngle计算 的prev顶点pos 是不准确的,因此我决定将分支中所有边之间的平均角度作为branchAngle.当一个brach的边缘在180度标记附近并且分支可以具有像175,176的边缘角度时,这种方法失败了.-176!我使用这段代码使它们都是积极的:
var angle = Math.Atan2(point1.Y - point2.Y, point1.X - point2.X);
while (angle < 0d)
angle += Math.PI*2;
Run Code Online (Sandbox Code Playgroud)
但现在角度可以是350,359 .. 2 !!! 非常难以计算平均值:)你能告诉我如何解决这个问题吗?
从您提供的链接查看图形,树中的每个分支都有自己的角度,用于声明分支的控制点。这branchAngle与从第一个节点到前一个节点的向量相同(每个分支可以依次生成多个分支)。第一个分支的角度(第一个节点 = 前一个节点 = 中心)似乎在 -60\xc2\xb0 左右。
设置曲线类型可以通过补偿树中所有分支的分支角度(0\xc2\xb0、-90\xc2\xb0、-180\xc2\xb0,...)来完成。结果用于controlAngle布置控制点。
生成控制点,同时考虑角度:
\n\n//gen per branch\n double branchAngle = 30 * Math.PI / 180; //e.g., calc vector angle here\n double cosB = Math.Cos(branchAngle);\n double sinB = Math.Sin(branchAngle); \n //depending on the desired curve compensate -90\xc2\xb0, -180\xc2\xb0,...\n double controlAngle = branchAngle - (90 * Math.PI / 180); \n double cosA = Math.Cos(controlAngle);\n double sinA = Math.Sin(controlAngle);\n\n//gen 2 control points\n //calculate dx dy after rotation with branchAngle\n double dxbase = target.X - source.X, dybase = target.Y - source.Y;\n double dx = dxbase*sinB - dybase*cosB\n double dy = dxbase*cosB + dybase*sinB\n //control points based on controlAngle\n var pts = new[]\n {\n new Point(source.X + (2*dx/3)*cosA , source.Y + (2*dx/3)*sinA),\n new Point(target.X - (dx/8)*cosA + (dy/8)*sinA, target.Y - (dx/8)*sinA - (dy/8)*cosA)\n };\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n快速检查 \nbranchAngle = 30\xc2\xb0 &\n补偿 = -90\xc2\xb0 ->\ncontrolAngle = -60\xc2\xb0
\n