2016-08-21 17 views
8

我想渲染漂亮的径向树布局,有点绊倒弯曲的边缘。问题是,源点和目标点之间的角度不同,边缘绘制方式不同。提供的图片来自单个图表,因此您可以看到它们在不同边缘方向上的差异。我认为这一点是在beizer曲线控制点的一代,我只是不明白如何解决它们。径向树图布局:修复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);

UPDATE 1: 我有先前顶点和源极之间的角度在使用下面的公式弧度:Math.Atan2(PREV。 Y - source.Y,source.X - prev.X); 但我仍然像图4中的边缘。

UPDATE 2branchAngle计算中的一个先前顶点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; 

但是现在的角度可以是350,359。2!相当难以计算平均值:)你能请教我如何能解决这个问题吗?

PIC1 Beizer curve edges - up

PIC2 Beizer curve edges - left

PIC3 enter image description here

PIC4 enter image description here

回答

1

从您在树中提供的每个分支的链接图形看有它自己的角度,用于声明控制l分支。该branchAngle与从第一个节点到前一个节点的矢量相同(每个分支可以依次产生多个分支)。第一个分支(第一个节点=前一个节点=中心)的角度似乎在-60°左右。

设置曲线的类型可以通过补偿树中所有分支的分支角度(0°,-90°,-180°,...)来完成。导致用于布置控制点的controlAngle

生成控制点考虑而考虑角度:

//gen per branch 
double branchAngle = 30 * Math.PI/180; //e.g., calc vector angle here 
double cosB = Math.Cos(branchAngle); 
double sinB = Math.Sin(branchAngle);  
//depending on the desired curve compensate -90°, -180°,... 
double controlAngle = branchAngle - (90 * Math.PI/180); 
double cosA = Math.Cos(controlAngle); 
double sinA = Math.Sin(controlAngle); 

//gen 2 control points 
//calculate dx dy after rotation with branchAngle 
double dxbase = target.X - source.X, dybase = target.Y - source.Y; 
double dx = dxbase*sinB - dybase*cosB 
double dy = dxbase*cosB + dybase*sinB 
//control points based on controlAngle 
var pts = new[] 
{ 
    new Point(source.X + (2*dx/3)*cosA , source.Y + (2*dx/3)*sinA), 
    new Point(target.X - (dx/8)*cosA + (dy/8)*sinA, target.Y - (dx/8)*sinA - (dy/8)*cosA) 
}; 

Branch

快速检查 branchAngle = 30°& 补偿= -90° - > 控制角= -60°

+0

感谢您的回答,但我仍然得到奇怪的结果,请参阅操作中的更新1。 –

+0

@亚历山大对不起,在dx和dy calc中犯了一个错误。用cosB切换sinB,反之亦然。 – Funk

+0

您的编辑似乎存在拼写错误,branchAngle应该是'Math.Atan2(prev.Y - source.Y,prev.X - source.X)'。 – Funk