Orbiter 2022
Combinatorial Objects
tree_node.cpp
Go to the documentation of this file.
1// tree_node.cpp
2//
3// Anton Betten
4//
5// moved here from tree.cpp: October 12, 2013
6//
7// February 7, 2003
8
9#include "foundations.h"
10
11
12using namespace std;
13
14
15#define DONT_DRAW_ROOT_NODE 0
16
17namespace orbiter {
18namespace layer1_foundations {
19namespace graphics {
20
21
22
24{
25 parent = NULL;
26 depth = 0;
27 f_value = FALSE;
28 value = 0;
29
31 color = 0;
32
33 //label;
34
35 nb_children = 0;
36 children = NULL;
37
38
39 weight = 0;
40 placement_x = 0;
41 placement_y = 0;
42 width = 0;
43
44 DFS_rank = 0;
45}
46
48{
49}
50
51void tree_node::init(int depth, tree_node *parent, int f_value, int value,
52 int f_has_color, int color, std::string &label,
53 int verbose_level)
54{
55 int f_v = (verbose_level >= 1);
56 //int f_vv = (verbose_level >= 2);
57
58 if (f_v) {
59 cout << "tree_node::init depth=" << depth << " value=" << value << endl;
60 }
63
66
69
70 tree_node::label.assign(label);
71
72 nb_children = 0;
73 children = NULL;
74}
75
77{
78 if (parent) {
80 }
81 if (f_value)
82 cout << value << " ";
83}
84
86{
87 int i;
88
89 cout << "depth " << depth << " : ";
90 print_path();
91#if 0
92 if (f_value) {
93 cout << value;
94 }
95#endif
96 cout << " : ";
97 cout << weight;
98 cout << " : (";
99 cout << placement_x << "," << placement_y << "," << width << ")";
100 cout << " : ";
101 if (f_has_color) {
102 cout << color;
103 }
104 cout << " : ";
105 cout << label;
106 cout << endl;
107 for (i = 0; i < nb_children; i++) {
109 }
110}
111
113{
114 int i;
115
116 DFS_rank = rk;
117 rk++;
118 for (i = 0; i < nb_children; i++) {
120 }
121}
122
123int tree_node::find_node(int &DFS_rk, int *path, int sz, int verbose_level)
124{
125 int f_v = (verbose_level >= 1);
126
127 if (f_v) {
128 cout << "tree_node::find_node ";
129 cout << "my_path = ";
130 Int_vec_print(cout, path, sz);
131 cout << " value=" << value << endl;
132 }
133 int i;
134
135 if (value == path[0]) {
136 if (sz == 1) {
137 DFS_rk = DFS_rank;
138 return TRUE;
139 }
140 else {
141 for (i = 0; i < nb_children; i++) {
142 if (children[i]->find_node(DFS_rk, path + 1, sz - 1, verbose_level)) {
143 return TRUE;
144 }
145 }
146 cout << "tree_node::find_node did not find node" << endl;
147 exit(1);
148 }
149 }
150 else {
151 return FALSE;
152 }
153}
154
155int tree_node::find_node_and_path(std::vector<int> &Rk, int *path, int sz, int verbose_level)
156{
157 int f_v = (verbose_level >= 1);
158
159 if (f_v) {
160 cout << "tree_node::find_node_and_path ";
161 cout << "my_path = ";
162 Int_vec_print(cout, path, sz);
163 cout << " value=" << value << endl;
164 }
165 int i;
166
167 if (value == path[0]) {
168 Rk.push_back(DFS_rank);
169 if (sz == 1) {
170 return TRUE;
171 }
172 else {
173 for (i = 0; i < nb_children; i++) {
174 if (children[i]->find_node_and_path(Rk, path + 1, sz - 1, verbose_level)) {
175 return TRUE;
176 }
177 }
178 cout << "tree_node::find_node_and_path did not find node" << endl;
179 exit(1);
180 }
181 }
182 else {
183 return FALSE;
184 }
185}
186
187
188void tree_node::get_coordinates(int &idx, int *coord_xy)
189{
190 int i;
191
192 coord_xy[idx * 2 + 0] = placement_x;
193 coord_xy[idx * 2 + 1] = placement_y;
194 idx++;
195 for (i = 0; i < nb_children; i++) {
196 children[i]->get_coordinates(idx, coord_xy);
197 }
198}
199
200void tree_node::get_coordinates_and_width(int &idx, int *coord_xyw)
201{
202 int i;
203
204 coord_xyw[idx * 3 + 0] = placement_x;
205 coord_xyw[idx * 3 + 1] = placement_y;
206 coord_xyw[idx * 3 + 2] = width;
207 idx++;
208 for (i = 0; i < nb_children; i++) {
209 children[i]->get_coordinates_and_width(idx, coord_xyw);
210 }
211}
212
214{
215 int i;
216
217 weight = 1;
218 for (i = 0; i < nb_children; i++) {
219 children[i]->calc_weight();
220 weight += children[i]->weight;
221 }
222}
223
224void tree_node::place_xy(int left, int right, int ymax, int max_depth)
225{
226 int i, w, w0, w1, lft, rgt;
227 double dx;
228
229 placement_x = (left + right) >> 1;
230 placement_y = calc_y_coordinate(ymax, depth, max_depth);
231 w = weight;
232 width = right - left;
233 dx = (double) width / (double) (w - 1);
234 // the node itself counts for the weight, so we subtract one
235 w0 = 0;
236
237 for (i = 0; i < nb_children; i++) {
238 w1 = children[i]->weight;
239 lft = left + (int)((double)w0 * dx);
240 rgt = left + (int)((double)(w0 + w1) * dx);
241 children[i]->place_xy(lft, rgt, ymax, max_depth);
242 w0 += w1;
243 }
244}
245
246void tree_node::place_on_circle(int xmax, int ymax, int max_depth)
247{
248 int i, dy;
249 double x, y;
250 double x1, y1;
251
252 x = placement_x;
253 y = placement_y;
254 dy = (int)((double)ymax / (double)(max_depth + 1));
255 y = ymax - y;
256 y -= dy * 0.5;
257 y /= ymax;
258 x /= (double) xmax;
259 x *= 2. * M_PI;
260 x -= M_PI;
261 x1 = y * cos(x) * xmax * 0.5 + xmax * 0.5;
262 y1 = y * sin(x) * ymax * 0.5 + ymax * 0.5;
263 placement_x = (int) x1;
264 placement_y = (int) y1;
265 for (i = 0; i < nb_children; i++) {
266 children[i]->place_on_circle(xmax, ymax, max_depth);
267 }
268}
269
271 int depth, int *path, int color, std::string &label,
272 int verbose_level)
273{
274 int i, idx;
275 int f_v = (verbose_level >= 1);
276 int f_vv = (verbose_level >= 2);
277
278 if (f_v) {
279 cout << "tree_node::add_node depth=" << depth << " : ";
280 Int_vec_print(cout, path, l);
281 cout << endl;
282 }
283 if (l == 0) {
284 if (f_vv) {
285 cout << "tree_node::add_node node of length 0" << endl;
286 }
287 init(0, NULL, TRUE, -1, TRUE, color, label, verbose_level);
288 return;
289 }
290 idx = find_child(path[depth]);
291 if (f_vv) {
292 cout << "tree_node::add_node find_child for " << path[depth] << " returns " << idx << endl;
293 }
294 if (idx == -1) {
295 tree_node **new_children = new ptree_node[nb_children + 1];
296 for (i = 0; i < nb_children; i++) {
297 new_children[i] = children[i];
298 }
299 new_children[nb_children] = new tree_node;
300 if (nb_children) {
301 delete [] children;
302 }
303 children = new_children;
304 nb_children++;
305 if (f_vv) {
306 cout << "tree_node::add_node nb_children increased to " << nb_children << endl;
307 }
308
309 if (l == depth + 1) {
310 if (f_vv) {
311 cout << "tree_node::add_node initializing terminal node" << endl;
312 }
313 children[nb_children - 1]->init(depth + 1, this,
314 TRUE, path[depth], TRUE, color, label,
315 verbose_level);
316 return;
317 }
318 else {
319 if (f_vv) {
320 cout << "initializing intermediate node" << endl;
321 }
322 children[nb_children - 1]->init(depth + 1, this,
323 TRUE, path[depth], FALSE, 0, label,
324 verbose_level);
325 idx = nb_children - 1;
326 }
327 }
328 if (f_vv) {
329 cout << "searching deeper" << endl;
330 }
331 children[idx]->add_node(l, depth + 1, path, color, label, verbose_level);
332}
333
335{
336 int i;
337
338 for (i = 0; i < nb_children; i++) {
339 if (children[i]->value == val) {
340 return i;
341 }
342 }
343 return -1;
344}
345
346void tree_node::get_values(int *v, int verbose_level)
347{
348 int f_v = (verbose_level >= 1);
349
350 if (f_v) {
351 cout << "tree_node::get_values" << endl;
352 cout << "get_values depth=" << depth << " value=" << value << endl;
353 }
354 if (depth) {
355 v[depth - 1] = value;
356 parent->get_values(v, verbose_level);
357 }
358 if (f_v) {
359 cout << "tree_node::get_values done" << endl;
360 }
361}
362
364 tree_draw_options *Tree_draw_options,
366 int f_has_parent, int parent_x, int parent_y, int max_depth,
367 tree *T, int verbose_level)
368{
369 int f_v = (verbose_level >= 1);
370
371 if (f_v) {
372 cout << "tree_node::draw_edges" << endl;
373 }
374 //int rad = 20;
375 //int dx = rad; // / sqrt(2);
376 //int dy = dx;
377 int x, y, i;
378 int Px[3], Py[3];
379
380
381 int f_circle_text = TRUE;
382
383 if (Opt->f_nodes_empty) {
384 f_circle_text = FALSE;
385 }
386
387
388#if DONT_DRAW_ROOT_NODE
389 if (!f_has_parent) {
390 x = placement_x;
391 y = placement_y;
392 for (i = 0; i < nb_children; i++) {
393 children[i]->draw_edges(G, rad, f_circletext, TRUE, x, y, max_depth, f_edge_labels,
394 f_has_draw_vertex_callback, draw_vertex_callback, T);
395 }
396 return;
397 }
398#endif
399 x = placement_x;
400 y = placement_y;
401 // calc_y_coordinate(y, depth, max_depth);
402
403
404
405 cout << "{" << x << "," << y << "}, // depth " << depth << " ";
406 print_path();
407 cout << endl;
408
409 Px[1] = x;
410 Py[1] = y;
411
412 int f_show = FALSE;
413
414 if (Tree_draw_options->f_select_path) {
415 int rk;
416
417 rk = DFS_rank;
418 if (f_v) {
419 cout << "tree_node::draw_edges DFS_rank = " << rk << endl;
420 }
421 if (T->f_node_select[rk]) {
422 f_show = TRUE;
423 }
424 }
425 else {
426 f_show = TRUE;
427 }
428
429 if (f_show) {
430
431 if (f_has_parent
433 && depth >= 2
434#endif
435 ) {
436 Px[0] = parent_x;
437 Py[0] = parent_y;
438 G.polygon2(Px, Py, 0, 1);
439
440#if 0
441 if (Opt->f_edge_labels && char_data) {
442 Px[2] = (x + parent_x) >> 1;
443 Py[2] = (y + parent_y) >> 1;
444 G.aligned_text(Px[2], Py[2], "" /*"tl"*/, char_data);
445 }
446#endif
447 }
448 }
449
450
451 for (i = 0; i < nb_children; i++) {
452 children[i]->draw_edges(G, Tree_draw_options, Opt, TRUE, x, y, max_depth, T, verbose_level);
453 }
454
455 if (f_v) {
456 cout << "tree_node::draw_edges done" << endl;
457 }
458}
459
461 tree_draw_options *Tree_draw_options,
463 int f_has_parent, int parent_x, int parent_y, int max_depth,
464 tree *T, int verbose_level)
465{
466 int f_v = (verbose_level >= 1);
467
468 if (f_v) {
469 cout << "tree_node::draw_vertices" << endl;
470 }
471 int dx = Opt->rad;
472 int dy = dx;
473 int x, y, i;
474 int Px[3], Py[3];
475 char str[1000];
476 int *v;
477
478#if DONT_DRAW_ROOT_NODE
479 if (!f_has_parent) {
480 x = placement_x;
481 y = placement_y;
482 for (i = 0; i < nb_children; i++) {
483 children[i]->draw_vertices(G, rad, f_circletext, f_i, TRUE, x, y, max_depth, f_edge_labels,
484 f_has_draw_vertex_callback, draw_vertex_callback, T);
485 }
486 return;
487 }
488#endif
489 x = placement_x;
490 y = placement_y;
491 // calc_y_coordinate(y, depth, max_depth);
492
493 v = NEW_int(depth + 1);
494 get_values(v, verbose_level);
495
496#if 0
497 if (Opt->rad > 0) {
498 if (Opt->f_circle) {
499 if (depth == 0) {
500 G.nice_circle(x, y, (int) (Opt->rad * 1.2));
501 }
502 G.nice_circle(x, y, Opt->rad);
503 }
504 }
505#endif
506
507 int f_show = FALSE;
508
509 if (Tree_draw_options->f_select_path) {
510 int rk;
511
512 rk = DFS_rank;
513 if (f_v) {
514 cout << "tree_node::draw_vertices DFS_rank = " << rk << endl;
515 }
516 if (T->f_node_select[rk]) {
517 f_show = TRUE;
518 }
519 }
520 else {
521 f_show = TRUE;
522 }
523
524 if (f_show) {
525 if (f_has_color) {
526 if (Opt->f_nodes_empty) {
527 G.sf_color(color);
528 //G.sf_interior(color /* fill_interior*/);
529 G.nice_circle(x, y, Opt->rad);
530 }
531 else {
532 sprintf(str, "%d", value);
533 G.aligned_text(x, y, "", str);
534 }
535 //snprintf(str, 1000, "%d", color);
536 //G.aligned_text(Px[1], Py[1], "tl", str);
537 }
538 else {
539 sprintf(str, "%d", value);
540 G.aligned_text(x, y, "", str);
541 }
542
543
544
545 if (Tree_draw_options->f_has_draw_vertex_callback) {
546 cout << "calling draw_vertex_callback" << endl;
547 (*Tree_draw_options->draw_vertex_callback)(T, &G, v, depth, this, x, y, dx, dy);
548 }
549
550 }
551 FREE_int(v);
552
553
554 cout << "{" << x << "," << y << "}, // depth " << depth << " ";
555 print_path();
556 cout << endl;
557
558 Px[1] = x;
559 Py[1] = y;
560 if (f_has_parent
562 && depth >= 2
563#endif
564 ) {
565 Px[0] = parent_x;
566 Py[0] = parent_y;
567 //G.polygon2(Px, Py, 0, 1);
568
569 }
570
571
572 if (T->f_count_leaves) {
573 if (nb_children == 0) {
574
575 int dy, x0, y0;
576
577 x0 = placement_x;
578 y0 = placement_y;
579
580 dy = parent->placement_y - y0;
581 y0 -= dy;
582
583
584 snprintf(str, 1000, "L%d", T->leaf_count);
585
586 T->leaf_count++;
587 G.aligned_text(x0, y0, "", str);
588
589 }
590 }
591
592 for (i = 0; i < nb_children; i++) {
593 children[i]->draw_vertices(G, Tree_draw_options, Opt, TRUE, x, y, max_depth, T, verbose_level);
594 }
595
596#if 0
597 if (f_value) {
598 snprintf(str, 1000, "%d", value);
599 }
600 else {
601 snprintf(str, 1000, " ");
602 }
603
604 if (!Opt->f_nodes_empty) {
605 //G.circle_text(x, y, str);
606 G.aligned_text(x, y, "", str);
607 }
608 else {
609 //G.aligned_text(x, y, 1, "tl", str);
610 }
611#endif
612
613 if (f_v) {
614 cout << "tree_node::draw_vertices done" << endl;
615 }
616
617}
618
619void tree_node::draw_sideways(mp_graphics &G, int f_circletext, int f_i,
620 int f_has_parent, int parent_x, int parent_y, int max_depth, int f_edge_labels)
621{
622 int x, y, i;
623 int xx, yy;
624 int Px[3], Py[3];
625 char str[1000];
626 //int rad = 50;
627
628#if DONT_DRAW_ROOT_NODE
629 if (!f_has_parent) {
630 x = placement_x;
631 y = placement_y;
632 xx = 10000 - y;
633 yy = 10000 - x;
634 for (i = 0; i < nb_children; i++) {
635 children[i]->draw(G, f_circletext, f_i, TRUE, xx, yy, max_depth, f_edge_labels);
636 }
637 return;
638 }
639#endif
640 x = placement_x;
641 y = placement_y;
642 xx = 10000 - y;
643 yy = 10000 - x;
644 // calc_y_coordinate(y, depth, max_depth);
645
646 //G.circle(xx, yy, 20);
647
648 cout << "{" << xx << "," << yy << "}, // depth " << depth << " ";
649 print_path();
650 cout << endl;
651
652 Px[1] = xx;
653 Py[1] = yy;
654 if (f_has_parent
656 && depth >= 2
657#endif
658 ) {
659 Px[0] = parent_x;
660 Py[0] = parent_y;
661 G.polygon2(Px, Py, 0, 1);
662
663 if (f_edge_labels && label.length()) {
664 Px[2] = (xx + parent_x) >> 1;
665 Py[2] = (yy + parent_y) >> 1;
666 G.aligned_text(Px[2], Py[2], "" /*"tl"*/, label.c_str());
667 }
668 }
669
670 for (i = 0; i < nb_children; i++) {
671 children[i]->draw_sideways(G, f_circletext, f_i, TRUE, xx, yy, max_depth, f_edge_labels);
672 }
673 if (f_value) {
674 snprintf(str, 1000, "%d", value);
675 }
676 else {
677 snprintf(str, 1000, " ");
678 }
679 if (f_circletext) {
680#if 0
681 //G.circle_text(xx, yy, str);
682 G.sf_interior(100);
683 G.sf_color(0); // 1 = black, 0 = white
684 G.circle(xx, yy, rad);
685 G.sf_interior(0);
686 G.sf_color(1); // 1 = black, 0 = white
687 G.circle(xx, yy, rad);
688#endif
689 G.aligned_text(Px[1], Py[1], "" /*"tl"*/, str);
690 }
691 else {
692 //G.aligned_text(xx, yy, 1, "tl", str);
693 }
694 if (f_i && f_circletext && f_has_color) {
695 snprintf(str, 1000, "%d", color);
696 G.aligned_text(Px[1], Py[1], "tl", str);
697 }
698}
699
700
701int tree_node::calc_y_coordinate(int ymax, int l, int max_depth)
702{
703 int dy, y;
704
705 dy = (int)((double)ymax / (double)(max_depth + 1));
706 y = (int)(dy * ((double)l + 0.5));
707 y = ymax - y;
708 return y;
709}
710
711
712}}}
713
options for drawing an object of type layered_graph
Definition: graphics.h:457
a general 2D graphical output interface (metapost, tikz, postscript)
Definition: graphics.h:545
void aligned_text(int x, int y, const char *alignment, const char *p)
void polygon2(int *Px, int *Py, int i1, int i2)
void(* draw_vertex_callback)(tree *T, mp_graphics *G, int *v, int layer, tree_node *N, int x, int y, int dx, int dy)
Definition: graphics.h:1524
part of the data structure tree
Definition: graphics.h:1547
void draw_edges(mp_graphics &G, tree_draw_options *Tree_draw_options, layered_graph_draw_options *Opt, int f_has_parent, int parent_x, int parent_y, int max_depth, tree *T, int verbose_level)
Definition: tree_node.cpp:363
void draw_sideways(mp_graphics &G, int f_circletext, int f_i, int f_has_parent, int parent_x, int parent_y, int max_depth, int f_edge_labels)
Definition: tree_node.cpp:619
void get_values(int *v, int verbose_level)
Definition: tree_node.cpp:346
int find_node(int &DFS_rk, int *path, int sz, int verbose_level)
Definition: tree_node.cpp:123
void place_xy(int left, int right, int ymax, int max_depth)
Definition: tree_node.cpp:224
int calc_y_coordinate(int ymax, int l, int max_depth)
Definition: tree_node.cpp:701
void place_on_circle(int xmax, int ymax, int max_depth)
Definition: tree_node.cpp:246
void get_coordinates_and_width(int &idx, int *coord_xyw)
Definition: tree_node.cpp:200
void draw_vertices(mp_graphics &G, tree_draw_options *Tree_draw_options, layered_graph_draw_options *Opt, int f_has_parent, int parent_x, int parent_y, int max_depth, tree *T, int verbose_level)
Definition: tree_node.cpp:460
void add_node(int l, int depth, int *path, int color, std::string &label, int verbose_level)
Definition: tree_node.cpp:270
int find_node_and_path(std::vector< int > &Rk, int *path, int sz, int verbose_level)
Definition: tree_node.cpp:155
void init(int depth, tree_node *parent, int f_value, int value, int f_has_color, int color, std::string &label, int verbose_level)
Definition: tree_node.cpp:51
void get_coordinates(int &idx, int *coord_xy)
Definition: tree_node.cpp:188
#define FREE_int(p)
Definition: foundations.h:640
#define NEW_int(n)
Definition: foundations.h:625
#define TRUE
Definition: foundations.h:231
#define FALSE
Definition: foundations.h:234
#define M_PI
Definition: foundations.h:237
#define Int_vec_print(A, B, C)
Definition: foundations.h:685
the orbiter library for the classification of combinatorial objects
#define DONT_DRAW_ROOT_NODE
Definition: tree_node.cpp:15