2016-08-21 1 views
8

멋진 방사형 트리 레이아웃을 렌더링하고 곡선 가장자리로 넘어지기를 원합니다. 문제는 원점과 목표점 사이의 각도가 다를 때 가장자리가 다르게 그려지는 것입니다. 제공되는 사진은 하나의 그래프에 있으므로 가장자리 방향에 따라 사진의 차이점을 확인할 수 있습니다. 요점은 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 (이전 : 나는 다음과 같은 공식을 사용하여 라디안으로 이전 정점과 소스 사이의 각도를 가지고있다. Y - source.Y, source.X - prev.X); 하지만 여전히 그림 4와 같이 가장자리가 생깁니다.

UPDATE 2 branchAngle 계산을위한 이전 정점 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 ...이 될 수 있습니다! : 나는 그들 모두가 긍정적 만들기 위해이 코드를 사용 계산하기가 꽤 어렵다 :) 나는 이것을 어떻게 할 수 있는지 조언 해 주시겠습니까?

PIC1은 Beizer curve edges - up

PIC2 Beizer curve edges - left

Pic3 enter image description here

enter image description here

답변

1

(pic4)와 당신이 트리의 각 지점을 제공하는 링크에서 그래프를 보면 그것은 자신의 각도입니다했다 , 그것은 contro를 선언하는 데 사용됩니다 지점의 l 점. 이 branchAngle은 첫 번째 노드에서 이전 노드로가는 벡터 중 하나와 같습니다 (모든 분기가 차례로 여러 분기를 생성 할 수 있음). 첫 번째 분기의 각도 (첫 번째 노드 = 이전 노드 = 중심)는 약 -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 calc에서 실수했습니다. sinB를 cosB로 바꾸고 그 반대도 마찬가지입니다. – Funk

+0

편집에 오타가있는 것 같습니다. branchAngle은'Math.Atan2 (prev.Y - source.Y, prev.X - source.X)'이어야합니다. – Funk