2016-08-21 6 views
8

私は素敵な放射状のツリーレイアウトをレンダリングしたいと思います。問題は、原点と目標点の角度が異なると、エッジが異なるように描画されることです。提供された画像は1つのグラフからのものなので、エッジ方向の違いによってどのように違いがあるかを見ることができます。私はポイントがビーチャカーブのコントロールポイントの世代にあると思うし、私はちょうどそれらを修正する方法を理解することはできません。放射状の木グラフのレイアウト:固定ビアカーブ

エッジの方向が何であっても、同じ方法で描画します。

これを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(前: 私は、次の式を使用してラジアン単位で前の頂点とソースとの間の角度を持っています。 Y - source.Y、source.X - prev.X); しかし、まだ私は図4のようなエッジを取得します。

UPDATE 2 branchAngle計算のための前の頂点posが私はbranchAngleとしてブランチ内のすべてのエッジ間の平均角度を取ることにした不正確です。このアプローチは、1つのbrachからのエッジが180 degマークの周りにあり、ブランチが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

写真2 Beizer curve edges - left

PIC3 enter image description here

PIC4 enter image description here

答えて

1

これはコントロルを宣言するために使用されます枝のl点。このbranchAngleは、最初のノードから前のノードに向かうベクトルのものと同じです(すべてのブランチは順番に複数のブランチを生成できます)。第1の分岐(第1のノード=前のノード=中心)の角度は約-60°と思われる。

カーブのタイプを設定するには、ツリー内のすべての分岐について、この分岐角度(0°、-90°、-180°、...)を補正します。コントロールポイントのレイアウトに使用されるcontrolAngleが発生しました。 - > controlAngle = -60°

//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°を:角度を考慮しながら

制御点の生成

+0

お返事ありがとうございますが、まだ奇妙な結果が出ます。オペアンプのアップデート1をご覧ください。 –

+0

@Alexanderそれを残念に思って、dxとdyの計算に間違いを起こしました。 sinBをcosBに切り替え、その逆も同様です。 – Funk

+0

編集にはタイプミスがあるようですが、branchAngleは 'Math.Atan2(prev.Y - source.Y、prev.X - source.X)'でなければなりません。 – Funk

関連する問題