恐らくあなたは今自分でそれを理解しました。ない場合は、ここで
double dNodesInDepth = GetNodesInDepth(i).size();
double dAngleSpace = 2 * PI/dNodesInDepth;
あなたはそのレベルで2つのノードだけ、dNodesInDepth = 2
があるとして、あなたの第二のレベルでPI(180 degreees)に角度スペースを設定しています。そのため、ノード20を描画した後、ノード30は180度離れている。その方法は、その角度が小さくなるため、非常に密度の高いツリーの場合は問題ありません。しかし、あなたの場合、角度をできるだけ親の角度に近づけたいと思っています。したがって、レベル2以上のノードの親の角度を取得し、子どもを広げて角度空間がsibilingAngle = min(dAngleSpace, PI/10)
になるようにすることをお勧めします。したがって、最初の子供は親の正確な角度を持ち、残りの子供はお互いからsibilingAngle
です。あなたはそのアイデアを得て、おそらくより良い方法で来るでしょう。私はmin
を使用しています。そのレベルであまりにも多くのノードを持っている場合は、ノードを互いに近づけたいと思っています。
リンク先の記事には、Figure 2 – Tangent and bisector limits for directories
で示されている解決策が使用されています。あなたが子供の絶対角度を決定するのではなく、親に対する場合は、その方法は非常に多くの操作を行おうとまさにん単純/クリーナーソリューションを持つことができるので、私はずっとその方法が好きではありません。
更新:
次のコードは、このイメージを生成します。
私はあなたが簡単に子ノードをセンタリングする方法を見つけ出すとなどができると思います
#include <cairo/cairo.h>
#include <math.h>
#include <vector>
using namespace std;
class Node {
public:
Node() {
parent = 0;
angle = 0;
angleRange = 2*M_PI;
depth = 0;
}
void addChildren(int n) {
for (int i=0; i<n; i++) {
Node* c = new Node;
c->parent = this;
c->depth = depth+1;
children.push_back(c);
}
}
vector<Node*> children;
float angle;
float angleRange;
Node* parent;
int depth;
int x, y;
};
void rotate(float x, float y, float angle, float& nx, float& ny) {
nx = x * cos(angle) - y * sin(angle);
ny = x * sin(angle) + y * cos(angle);
}
void draw(Node* root, cairo_t *cr) {
if (root->parent == 0) {
root->x = root->y = 300;
cairo_arc(cr, root->x, root->y, 3, 0, 2 * M_PI);
}
int n = root->children.size();
for (int i=0; i<root->children.size(); i++) {
root->children[i]->angle = root->angle + root->angleRange/n * i;
root->children[i]->angleRange = root->angleRange/n;
float x, y;
rotate(40 * root->children[i]->depth, 0, root->children[i]->angle, x, y);
root->children[i]->x = 300+x;
root->children[i]->y = 300+y;
cairo_move_to(cr, root->x, root->y);
cairo_line_to(cr, root->children[i]->x, root->children[i]->y);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_stroke(cr);
cairo_arc(cr, 300+x, 300+y, 3, 0, 2 * M_PI);
cairo_set_source_rgb(cr, 1, 1, 1);
cairo_stroke_preserve(cr);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_fill(cr);
draw(root->children[i], cr);
}
}
int main(void) {
Node root;
root.addChildren(4);
root.children[0]->addChildren(3);
root.children[0]->children[0]->addChildren(2);
root.children[1]->addChildren(5);
root.children[2]->addChildren(5);
root.children[2]->children[1]->addChildren(2);
root.children[2]->children[1]->children[1]->addChildren(2);
cairo_surface_t *surface;
cairo_t *cr;
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 600, 600);
cr = cairo_create(surface);
cairo_rectangle(cr, 0.0, 0.0, 600, 600);
cairo_set_source_rgb(cr, 1, 1, 1);
cairo_fill(cr);
cairo_set_line_width(cr, 2);
for (int i=0; i<6; i++) {
cairo_arc(cr, 300, 300, 40*i, 0, 2 * M_PI);
cairo_set_source_rgb(cr, .5, .5, .5);
cairo_stroke(cr);
}
draw(&root, cr);
cairo_surface_write_to_png(surface, "image.png");
cairo_destroy(cr);
cairo_surface_destroy(surface);
return 0;
}
アップデート2: ちょうどここに、あなたのためにそれを容易にするためには、ノードをセンタリングする方法である:
以上人口のツリー表示
for (int i=0; i<root->children.size(); i++) {
float centerAdjust = 0;
if (root->parent != 0) {
centerAdjust = (-root->angleRange + root->angleRange/n)/2;
}
root->children[i]->angle = root->angle + root->angleRange/n * i + centerAdjust;
root->children[i]->angleRange = root->angleRange/n;
:
を
あなたのグラフで(明確にするために)、間違って配置されたのは30ノードだけですか?この場合、 –
、はい。 –
あなたが並べ替えを与えたリンクには、あなたがしようとしているもののコードがあります。それはかなり面倒ですが、限界と二等分線をさまざまなレベルで計算しています。コードの理解に問題がありますか? –