Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ntreepic.C
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
152# include <iostream>
153# include <fstream>
154# include <string>
155# include <tpl_dynArray.H>
156# include <tpl_dynDlist.H>
157# include <tpl_tree_node.H>
158#include <utility>
159
160# include <argp.h>
161
162# include "parse_utils.H"
163# include "treepic_utils.H"
164# include "ah-errors.H"
165
166/*
167
168 TODO:
169
170 opcion connexion complementaria a dashed-connexion
171
172 URGENTE:
173 -. Pasos de diferentes árboles
174 -. Notación de Deway pura
175
176 -. Mejorar heurística de cálculo de longitud string para que
177 considere saltos de línea
178 -. Conversión en representación árbol binario
179 -. Dibujar flecha
180 -. Opcion que dibuje lineas punteadas cuando se ejecute opcion que
181 dibuje reptresentacion con listas
182*/
183
184
185# define BLANK " "
186
187
188/* valores de distancias por omision */
189long double hr = 70; // radio horizontal de la elipse
190long double vr = 70; // radio vertical de la elipse
191long double hd = 2 * hr; // diametro horizontal de la elipse
192long double vd = 2 * vr; // diametro vertical de la elipse
193long double xgap = 70; // separacion horizontal entre nodos
194long double ygap = 100; // separacion vertical entre nodos
195long double tree_gap = 90; // separacion horizontal entre arboles
196long double h_size = 0; /* longitud horizontal de picture */
197double v_size = 0; /* longitud vertical de picture */
198long double x_offset = 0; /* offset horizontal etiqueta */
199long double y_offset = font_height() / 2.0; /* offset vertical etiqueta */
200long double x_picture_offset = 0; // offset horizontal para dibujo
201long double y_picture_offset = 0; // offset vertical para dibujo
202
203std::string command_line;
204std::string input_file_name;
206
207
208bool latex_header = false; // envolver salida con un latex header
209bool ellipses = true; // por omisión dibujar elipses
210bool rectangles = false;
213bool not_nodes = false;
214
215
216# include <cassert>
217using namespace std;
218
236
237
239
240struct Tree_Data; /* declaración adelantada */
241
243
244struct Tag_Data
245{
246 string tag; // el string a escribir
247 Tag_Option tag_option; // orientacion de tag en sentido horario
248 long double x_offset;
249 long double y_offset;
250
251 Tag_Data() = default;
252
253 Tag_Data(string str, const Tag_Option option)
254 : tag(std::move(str)), tag_option(option)
255 {
256 // empty
257 }
258};
259
260
261struct Arc_Data
262{
264 bool is_dashed;
265
267 { /* empty */
268 }
269};
270
271
282
283
285{
286 long double x, y; /* coordenadas x,y definitivas del nodo */
287
288 long double pre, mod; /* valores x temporales empleados por algoritmo
289 dibujado */
290
291 long double sum_mod; /* acumulado de mod desde la raiz hasta el
292 nodo. Usado por el recorrido prefijo para colocar
293 los valores definitivos de x */
294
295 long double xr, yr; /* radios de elipse */
296
297 long double xd, yd; /* diametros de elipse */
298
299 long double max_child_yr; /* máximo radio vertical de sus hijos. Usado
300 para reajustar coordenadas y de los hijos si
301 algunos de los diametros son variables */
302
303 long double yr_gap; /* máximo radio entre los hermanos. Usado para
304 calcular separación vertical de los hijos de este
305 nodo de modo que queden alineados con el mayor
306 radio */
307
308 string str; /* cadena asociada al nodo */
309
310 long double xoffset, yoffset; /* offsets de posicion de cadena */
311
314
315 bool shadow;
317 bool with_arc; /* indica si hay arco desde el nodo padre */
318 bool dashed_arc; /* indica si el arco es punteado */
319
320 int position; /* posicion infija del nodo como si fuera un arbol binario */
321
323
325
327
328 int level;
329 int child_number; /* de izquierda a derecha */
330
332 : x(0), y(0), pre(0), mod(0), sum_mod(0),
333 xr(hr), yr(vr), xd(2 * xr), yd(2 * yr), max_child_yr(0),
334 xoffset(0), yoffset(0),
337 {
339 }
340};
341
342
343# define X(p) ((p)->get_key().x)
344# define Y(p) ((p)->get_key().y)
345# define PRE(p) ((p)->get_key().pre)
346# define MOD(p) ((p)->get_key().mod)
347# define SUMMOD(p) ((p)->get_key().sum_mod)
348# define STRING(p) ((p)->get_key().str)
349# define ISELLIPSE(p) ((p)->get_key().ellipse)
350# define ISRECTANGLE(p) ((p)->get_key().rectangle)
351# define XOFFSET(p) ((p)->get_key().xoffset)
352# define YOFFSET(p) ((p)->get_key().yoffset)
353# define XR(p) ((p)->get_key().xr)
354# define YR(p) ((p)->get_key().yr)
355# define XD(p) ((p)->get_key().xd)
356# define YD(p) ((p)->get_key().yd)
357# define POS(p) ((p)->get_key().position)
358# define MAXCHILDYR(p) ((p)->get_key().max_child_yr)
359# define YRGAP(p) ((p)->get_key().yr_gap)
360# define LEVEL(p) ((p)->get_key().level)
361# define CHILDNUMBER(p) ((p)->get_key().child_number)
362# define WIDTH(p) ((p)->get_key().xd)
363# define HEIGHT(p) ((p)->get_key().yd)
364# define SHADOW(p) ((p)->get_key().shadow)
365# define WITHOUTNODE(p) ((p)->get_key().without_node)
366# define WITHARC(p) ((p)->get_key().with_arc)
367# define DASHEDARC(p) ((p)->get_key().dashed_arc)
368# define ARCS(p) ((p)->get_key().arc_list)
369# define CONNEXIONS(p) ((p)->get_key().connexion_list)
370# define TAGS(p) ((p)->get_key().tag_list)
371
372
373inline
375 int deway_array[], size_t deway_array_size)
376{
379
380 int deway_index = 0;
382 char *start_addr = &deway_string[0];
383 char *end_addr = &deway_string[Buffer_Size];
384 while (true)
385 {
386 const int c = read_char_from_stream(input_stream);
387
388 if (isdigit(c))
389 {
390 put_char_in_buffer(start_addr, end_addr, c);
391 continue;
392 }
393
394 if (c == '.' or isspace(c))
395 {
396 put_char_in_buffer(start_addr, end_addr, '\0');
397
399 ah_overflow_error_if(true) << "Deway number is too long";
400
403
404 if (isspace(c))
405 break;
406 else
407 continue;
408 }
409
410 input_stream.unget();
411 ah_invalid_argument_if(true) << "Unexpected character in deway number";
412 }
413
415 ah_overflow_error_if(true) << "Internal deway array size is not enough";
417}
418
419
421{
422 char buffer[Buffer_Size];
423 char * start_addr = buffer;
424 char * end_addr = buffer + Buffer_Size;
425
426 int c;
427
429
430 try
431 {
434 }
435 catch (const std::out_of_range &)
436 {
437 return END_FILE;
438 }
439
440 if (c == EOF)
441 return END_FILE;
442
443 if (not isprint(c))
444 return INVALID;
445
446 if (c == '%')
447 { /* comentario */
448 do
450 while (c != '\n' and c != EOF);
451 return COMMENT;
452 }
453
454 do /* delimita una cadena de caracteres cualquiera delimitada por blancos */
455 {
456 put_char_in_buffer(start_addr, end_addr, c);
458 }
459 while (isgraph(c) and c != '%' and c != EOF);
460
461 close_token_scanning(buffer, start_addr, end_addr);
462
463 if (c == '%') /* Se encontró comentario */
464 /* retroceda, así proxima llamada detectara comentario */
465 input_stream.unget();
466
467 if (strcasecmp(buffer, "ROOT") == 0)
468 return ROOT;
469
470 if (strcasecmp(buffer, "NODE") == 0)
471 return NODE;
472
473 if (strcasecmp(buffer, "TAG") == 0)
474 return TAG;
475
476 if (strcasecmp(buffer, "SHADOW") == 0)
477 return SHADOW;
478
479 if (strcasecmp(buffer, "WITHOUT-NODE") == 0)
480 return WITHOUT_NODE;
481
482 if (strcasecmp(buffer, "WITHOUT-ARC") == 0)
483 return WITHOUT_ARC;
484
485 if (strcasecmp(buffer, "ARC") == 0)
486 return ARC;
487
488 if (strcasecmp(buffer, "DASHED-ARC") == 0)
489 return DASHED_ARC;
490
491 if (strcasecmp(buffer, "HRADIO") == 0)
492 return HRADIO;
493
494 if (strcasecmp(buffer, "VRADIO") == 0)
495 return VRADIO;
496
497 if (strcasecmp(buffer, "XOFFSET") == 0)
498 return XOFFSET;
499
500 if (strcasecmp(buffer, "YOFFSET") == 0)
501 return YOFFSET;
502
503 if (strcasecmp(buffer, "N") == 0)
504 return NORTH;
505
506 if (strcasecmp(buffer, "S") == 0)
507 return SOUTH;
508
509 if (strcasecmp(buffer, "E") == 0)
510 return EAST;
511
512 if (strcasecmp(buffer, "L") == 0)
513 return LEFT;
514
515 if (strcasecmp(buffer, "R") == 0)
516 return RIGHT;
517
518 if (strcasecmp(buffer, "W") == 0)
519 return WEST;
520
521 if (strcasecmp(buffer, "NE") == 0)
522 return NORTH_EAST;
523
524 if (strcasecmp(buffer, "NW") == 0)
525 return NORTH_WEST;
526
527 if (strcasecmp(buffer, "SE") == 0)
528 return SOUTH_EAST;
529
530 if (strcasecmp(buffer, "SW") == 0)
531 return SOUTH_WEST;
532
533 if (strcasecmp(buffer, "ARC") == 0)
534 return ARC;
535
536 if (strcasecmp(buffer, "DASHED-CONNEXION") == 0)
537 return DASHED_CONNEXION;
538
539 if (strcasecmp(buffer, "ELLIPSE") == 0)
540 return ELLIPSE;
541
542 if (strcasecmp(buffer, "RECTANGLE") == 0)
543 return RECTANGLE;
544
545 return STRING;
546}
547
548/*
549 Aparta memoria para un nuevo nodo con string str
550*/
551EepicNode * allocate_node(const string & str)
552{
553 auto *node = new EepicNode;
554 STRING(node) = str;
555 return node;
556}
557
558
559/*
560 Lee un numero de deway y retorna el correspondiente nodo dentro del
561 árbol root. Retorna nullptr si el nodo no existe
562*/
564{
566
568
570
571 if (parent_node == nullptr)
572 print_parse_error_and_exit("Deway number doesn't match an existing node");
573
574 return parent_node;
575}
576
577
579{
580 const string str = load_string(input_stream);
581
582 return allocate_node(str);
583}
584
585
587{
589 print_parse_error_and_exit("Input file doesn't start with ROOT "
590 "definition");
591
593}
594
595
597{
599
600 EepicNode *last_root = root->get_last_tree();
601
602 last_root->insert_tree_to_right(new_tree);
603}
604
605
607{
609
611
612 parent_node->insert_rightmost_child(new_node);
613}
614
615/*
616 opcion HRADIO deway-number %-horizontal-radius-factor
617
618 El radio horizontal actual de la elipse se multiplica por
619 horizontal-radius-factor en porcentaje
620*/
622{
624
625 XR(p) *= load_number(input_stream) / 100.0;
626 XD(p) = 2 * XR(p);
627}
628
629
630/*
631 opcion VRADIO deway-number %-vertical-radius-factor
632
633 El radio vertical actual de la elipse se multiplica por
634 vertical-radius-factor en porcentaje
635*/
637{
639
640 YR(p) *= load_number(input_stream) / 100.0;
641 YD(p) = 2 * YR(p);
642}
643
644
645/*
646 opcion WITHOUT-NODE deway-number
647
648 El radio vertical actual de la elipse se multiplica por
649 vertical-radius-factor en porcentaje
650*/
652{
654
655 WITHOUTNODE(p) = true;
656}
657
658
659/*
660 opcion WITHOUT-NODE deway-number
661
662 El radio vertical actual de la elipse se multiplica por
663 vertical-radius-factor en porcentaje
664*/
666{
668
670
671 if (tgt->get_parent() != src)
672 print_parse_error_and_exit("target node does not match with parent in"
673 " WITHOUT-ARC");
674 WITHARC(tgt) = false;
675}
676
677
678/*
679 opcion XOFFSET deway-number offset
680*/
687
688
689/*
690 opcion YOFFSET deway-number offset
691*/
698
699/*
700 opcion SHADOW deway-number
701*/
703{
705
706 SHADOW(p) = true;
707}
708
709/*
710 TAG deway-number string orientation xoffset yoffset
711*/
713{
715
717
719
720 tag_data.tag_option = get_token(input_stream);
721
722 if (tag_data.tag_option < NORTH or tag_data.tag_option > SOUTH_WEST)
723 print_parse_error_and_exit("Invalid tag option");
724
727
728 TAGS(p).append(tag_data);
729}
730
731
733{
736
737 if (tgt == src) /* arco hacia si mismo */
738 print_parse_error_and_exit("an arc to itself");
739
740 if (tgt->get_parent() == src)
741 { /* arco natural (padre a hijo). Imprimimos warning y nos vamos */
742 print_parse_warning("declared an arc from parent to child");
743 return;
744 }
745
747
748 arc_data.target_node = tgt;
749 arc_data.is_dashed = false;
750
751 ARCS(src).append(arc_data);
752}
753
754
756{
759
760 if (tgt == src) /* arco hacia si mismo */
761 print_parse_error_and_exit("an dashed arc to itself");
762
764
765 arc_data.target_node = tgt;
766 arc_data.is_dashed = true;
767
768 ARCS(src).append(arc_data);
769}
770
771
773{
776
777 const Token_Type token = get_token(input_stream);
778
779 if (token != LEFT and token != RIGHT)
780 print_parse_error_and_exit("Expected L or R");
781
783
785 connexion_data.is_dashed = true;
786 connexion_data.is_left = token == LEFT;
787
788 CONNEXIONS(src).append(connexion_data);
789}
790
791
793{
795
796 ISELLIPSE(p) = true;
797 ISRECTANGLE(p) = false;
798}
799
800
802{
804
805 ISELLIPSE(p) = false;
806 ISRECTANGLE(p) = true;
807}
808
809
811{
813
814 try
815 {
816 while (true)
817 switch (get_token(input_stream))
818 {
819 case ROOT:
821 break;
822
823 case NODE:
825 break;
826
827 case END_FILE:
828 return root;
829
830 case INVALID:
831 print_parse_error_and_exit("Unrecognized token");
832
833 case COMMENT: break;
834
835 case HRADIO:
837 break;
838
839 case VRADIO:
841 break;
842
843 case WITHOUT_NODE:
845 break;
846
847 case WITHOUT_ARC:
849 break;
850
851 case XOFFSET:
853 break;
854
855 case YOFFSET:
857 break;
858
859 case SHADOW:
861 break;
862
863 case TAG:
865 break;
866
867 case ARC:
869 break;
870
871 case DASHED_ARC:
873 break;
874
875 case DASHED_CONNEXION:
877 break;
878
879 case ELLIPSE:
881 break;
882
883 case RECTANGLE:
885 break;
886
887 default:
888 print_parse_error_and_exit("Unknown token type");
889 }
890 }
891 catch (exception & e)
892 {
895 }
896 return nullptr; // nunca se alcanza
897}
898
899/* ***************************************************************
900
901 Las siguientes rutinas implantan la versión mejorada de Kozo
902 Sugiyama del algoritmo de Walker
903
904*/
905
906/*
907 Busca por profundidad en nodo más a la derecha en el nivel level a
908 partir del árbol con raíz root. Retorna en sum el acumulado de MOD
909 desde root hasta el padre del nodo encontrado.
910
911 Retorna el nodo más a la derecha o nullptr si no existe
912*/
914 long double & sum)
915{
916 sum += MOD(root);
917 for (EepicNode *p = root->get_right_child(); p != nullptr;
918 p = p->get_left_sibling())
919 {
920 if (LEVEL(p) == level)
921 return p;
922
924
925 if (q != nullptr)
926 return q;
927 }
928
929 sum -= MOD(root);
930
931 return nullptr;
932}
933
934/*
935 wrapper de iniciación para llamada recursiva
936*/
938 long double & sum)
939{
940 sum = 0;
941 if (LEVEL(root) == level)
942 return root;
943
945}
946
947
948/*
949 idem al anterior pero para el nodo más a la izquierda
950*/
952 long double & sum)
953{
954 sum += MOD(root);
955 for (EepicNode *p = root->get_left_child(); p != nullptr;
956 p = p->get_right_sibling())
957 {
958 if (LEVEL(p) == level)
959 return p;
960
962
963 if (q != nullptr)
964 return q;
965 }
966
967 sum -= MOD(root);
968
969 return nullptr;
970}
971
972/*
973 wrapper de iniciación para llamada recursiva
974*/
976 long double & sum)
977{
978 sum = 0;
979 if (LEVEL(root) == level)
980 return root;
981
983}
984
985
986/*
987 Esta rutina revisa los subarboles izquierdo de p y verifica que las
988 separaciones de los hermanos izquierdos sean correctas. Por cada nivel,
989 el algoritmo revisa la posicion de la hoja mas a la izquierda de p y la
990 compara con la hoja mas a la derecha de su hermano izquierdo
991 (left_sibling). Si no corresponden a la separacion minima, entonces se
992 realiza los ajustes sobre PRE(p) y MOD(p).
993
994 La rutina maneja el valor total de desplazamiento hacia la derecha
995 denominado compensated.
996
997 La rutina asume que los hermanos izquierdos de p y los descendientes
998 de p ya fueron procesados. Esto es plausible porque los valores de
999 PRE(p) y MOD(p) son calculados en sufijo.
1000*/
1002{
1003 assert(p->get_left_sibling() != nullptr);
1004 assert(not p->is_leftmost());
1005
1006 /* Procesar cada hermano izquierdo de p */
1007 for (EepicNode *left_sibling = p->get_left_sibling();
1008 left_sibling != nullptr;
1009 left_sibling = left_sibling->get_left_sibling())
1010 {
1011 assert(p->get_parent() == left_sibling->get_parent());
1013 /*
1014 Tenemos 2 subarboles en los cuales debemos verificar que su
1015 separacion no se sobrelape. El subarbol izquierdo es left_sibling
1016 y el subarbol derecho es p. Inspeccionaremos el extremo derecho de
1017 left_sibling con el extremo derecho de p. Si no estan
1018 adecuadamente separados, entonces alejamos MOD(p) de manera tal
1019 que el ajuste final no los sobrelape. r será el extremo derecho de
1020 left_sibling y l sera el extremo izquierdo en p. l y r siempre se
1021 corresponderan con el mismo nivel. La revision y eventual ajuste
1022 se realiza por cada nivel hasta que se alcance una hoja en
1023 cualquiera de los dos subarboles
1024 */
1025 /* valores acumulados parciales de MOD por cada extremo */
1026 int level = LEVEL(p) + 1;
1027 long double r_sum_mod; /* acumulado de mod del extremo derecho */
1028 long double l_sum_mod; /* acumulado de mod del extremo izquierdo */
1029
1030 /*
1031 Note que en posición r debe estar antes que l. Así que no
1032 confundir el sentido
1033
1034 root
1035 / \
1036 / \
1037 left_sibling p
1038 \ /
1039 \ /
1040 r l
1041 */
1042
1044 r_sum_mod);
1046
1047 /* coordenada x del extremo izquierdo */
1048 /* coordenada x del extremo derecho */
1049 /* distancia minima de separacion entre l
1050 y r */
1051
1052 while (l != nullptr and r != nullptr)
1053 {
1054 // calcula futuras coordenadas de los extremos
1055 const long double rx = PRE(r) + r_sum_mod; // coordenada x de r
1056 const long double lx = PRE(l) + l_sum_mod; // coordenada x de l
1057
1058 const long double current_separation = lx - rx;
1059
1060 if (const long double min_separation = tree_gap + XR(r) + XR(l); current_separation < min_separation)
1061 { /* l y r se están superponiendo */
1062 const long double compensation = min_separation - current_separation;
1063 PRE(p) += compensation;
1064 MOD(p) += compensation;
1065 }
1066
1067 /* avanza al siguiente nivel */
1068 level++; /* proximo nivel a comparar */
1071 }
1072 }
1073
1074 // TODO: Ajuste sugerido por Sigiyama causa colisiones entre nodos. Revisar
1075 /*
1076 si p fue desplazado en el paso anterior, entonces es posible que se
1077 forme una brecha desprorporcionada entre p y sus hermanos
1078 izquierdos. Esta fase se encarga de dispersar la brecha de la forma
1079 más uniforme posible entre los hermanos izquierdos de p sin
1080 incluir el más a la izquierda.
1081 */
1082}
1083
1084
1085/*
1086 Esta funcion es invocada por el recorrido sufijo cada vez se visita
1087 un nodo. El rol de la funcion es calcular los valores pre y mod
1088 segun el algoritmo de Walker variante de Sugiyama
1089*/
1090void precompute_x_for_node(EepicNode *p, const int level, const int child)
1091{
1092 if (p->is_leaf() and p->is_leftmost()) // hoja mas a la izquierda
1093 PRE(p) = MOD(p) = 0;
1094 else if (p->is_leaf() and p->is_root()) // p es un árbol de un solo nodo
1095 {
1096 PRE(p) = xgap + WIDTH(p) / 2.0;
1097 MOD(p) = 0;
1098 }
1099 else
1100 {
1101 EepicNode *left_sibling = p->get_left_sibling();
1102
1103 if (p->is_leaf()) // p es hoja y no es el mas izquierdo
1104 {
1105 PRE(p) =
1106 PRE(left_sibling) + xgap + (WIDTH(left_sibling) + WIDTH(p)) / 2.0;
1107 MOD(p) = 0;
1108 }
1109 else // p no es hoja
1110 {
1111 EepicNode *left_child = p->get_left_child();
1112 EepicNode *right_child = p->get_right_child();
1113
1114 if (p->is_leftmost() or p->is_root())
1115 {
1116 PRE(p) = (PRE(left_child) + PRE(right_child)) / 2.0;
1117 MOD(p) = 0;
1118 }
1119 else
1120 {
1121 PRE(p) = PRE(left_sibling) + xgap +
1122 (WIDTH(left_sibling) + WIDTH(p)) / 2.0;
1123 MOD(p) = PRE(p) - (PRE(left_child) + PRE(right_child)) / 2.0;
1124 }
1125 } // fin p no es una hoja
1126 } // fin p es hoja y no es el mas izquierdo */
1127
1128 // colocar numero de nivel e hijo
1129 LEVEL(p) = level;
1130 CHILDNUMBER(p) = child;
1131
1132 if (not p->is_root())
1133 { // guardar el mayor radio de elipse vertical
1134 EepicNode *pp = p->get_parent();
1135 MAXCHILDYR(pp) = std::max(MAXCHILDYR(pp), YR(p));
1136 }
1137
1138 if (not p->is_leftmost() and not p->is_root())
1140}
1141
1142/*
1143 Estos valores son calculados para luego determinar el tama~o del
1144 dibujo -del ambiente picture
1145*/
1146long double x_max = 0; /* maximo centro x visto */
1147long double y_max = 0; /* maximo centro y visto */
1148
1149
1150/*
1151 Esta funcion es invocada por el recorrido prefijo cada vez que se visita
1152 un nodo. Su rol es calcular las coordenadas definitivas x,y
1153
1154 X(P) = suma de MOD desde raíz hasta padre de p + PRE(p)
1155
1156 Y(p) = Y(pp) + YR(pp) + ygap + YR(p) excepto en raíz que es YR(root)
1157*/
1158void
1160{
1161 EepicNode *pp = p->get_parent();
1162
1163 long double parent_sum_mod; /* almacena sum MOD(ascendientes) */
1164
1165 if (pp == nullptr) /* p es la raiz */
1166 {
1167 parent_sum_mod = 0;
1168 YRGAP(p) = YR(p);
1169 Y(p) = YR(p);
1170 }
1171 else
1172 {
1174 SUMMOD(p) += parent_sum_mod + MOD(p); /* acumulado para uso de los
1175 hijos de p */
1176 YRGAP(p) = MAXCHILDYR(pp);
1177 Y(p) = Y(pp) + YRGAP(pp) + ygap + MAXCHILDYR(pp);
1178 }
1179
1180 X(p) = PRE(p) + parent_sum_mod; /* posicion definitiva x */
1181
1182 /* verificacion de maxima coordenada x */
1183 if (X(p) + XR(p) > x_max)
1184 x_max = X(p) + XR(p);
1185
1186 /* verificacion de maxima coordenada y */
1187 if (Y(p) + YR(p) > y_max)
1188 y_max = Y(p) + YR(p);
1189}
1190
1191
1192inline
1197
1198
1205
1206
1207/*
1208 La siguiente rutina desplaza un árbol hacia la derecha en una
1209 distancia shift_size puntos
1210*/
1211long double shift_size = 0;
1212
1214{
1215 X(p) += shift_size;
1216}
1217
1218
1220{
1221 /* calcula coordenadas del primer árbol */
1223 h_size = x_max;
1224
1225 /* recorre el resto de arboles pertenecientes a la arborescencia */
1226 for (root = root->get_right_tree(); root != nullptr;
1227 root = root->get_right_tree())
1228 {
1229 /* Desplazamiento del siguiente arbol es respecto al ancho del
1230 arbol anterior */
1231 const long double increment =
1232 XR(root->get_left_tree()) + x_max + tree_gap + XR(root);
1233
1234 /* Desplazamiento es lo anterior mas incremento calculado */
1236
1237 // shift_size += XR(root->get_left_tree()) + x_max + tree_gap + XR(root);
1238
1240
1241 /* desplaza todos los nodos del arbol en shift_size */
1243
1244 h_size += increment;
1245 }
1246 v_size = y_max; /* el mayor entre todos los árboles */
1247}
1248
1249
1251{
1252 static int counter = 0;
1253
1254 if (root == nullptr)
1255 return;
1256
1257 infix_tree(root->get_left_child());
1258 POS(root) = counter++;
1259 infix_tree(root->get_right_sibling());
1260}
1261
1262
1264{
1265 if (root == nullptr)
1266 return;
1267
1268 output << POS(root) << " ";
1269
1270 generate_prefix_traversal(output, root->get_left_child());
1271 generate_prefix_traversal(output, root->get_right_sibling());
1272}
1273
1274
1276{
1277 if (root == nullptr)
1278 return;
1279
1280 generate_infix_traversal(output, root->get_left_child());
1281
1282 output << "\"" << STRING(root) << "\" ";
1283
1284 generate_infix_traversal(output, root->get_right_sibling());
1285}
1286
1287
1289{
1291
1292 output << "start-prefix ";
1293
1295
1296 output << endl
1297 << endl
1298 << "start-key ";
1299
1301
1302 output << endl;
1303}
1304
1306{
1307 time_t t;
1308 time(&t);
1309 output << endl
1310 << "% This LaTeX picture is a tree automatically" << endl
1311 << "% generated by ntreepic program" << endl
1312 << endl
1313 << "% Copyright (C) 2002, 2003, 2004, 2007" << endl
1314 << "% UNIVERSITY of LOS ANDES (ULA)" << endl
1315 << "% Merida - REPUBLICA BOLIVARIANA DE VENEZUELA" << endl
1316 << "% Center of Studies in Microelectronics & Distributed Systems"
1317 << " (CEMISID)" << endl
1318 << "% ULA Computer Science Department" << endl
1319 << endl
1320 << "% Created by Leandro Leon - lrleon@ula.ve" << endl
1321 << endl
1322 << "% This program uses the Sugiyama variation of Walker" << endl
1323 << "% algorithm for general trees drawing" << endl
1324 << endl
1325 << "% You must use epic and eepic latex packages" << endl
1326 << "% in your LaTeX application" << endl
1327 << endl
1328 << "% epic Copyright by Sunil Podar" << endl
1329 << "% eepic Copyright by Conrad Kwok" << endl
1330 << "% LaTeX is a collection of TeX macros created by Leslie Lamport"
1331 << endl
1332 << "% TeX was created by Donald Knuth" << endl
1333 << endl
1334 << "% command line: " << endl
1335 << "% " << command_line << endl
1336 << endl
1337 << "% input file: " << input_file_name << endl
1338 << "% output file: " << output_file_name << endl
1339 << endl
1340 << "% Creation date: " << ctime(&t) << endl
1341 << endl;
1342
1343 if (latex_header)
1344 output << "\\documentclass[11pt]{article}" << endl
1345 << endl
1346 << "\\usepackage{epic}" << endl
1347 << "\\usepackage{eepic}" << endl
1348 << endl
1349 << "\\begin{document}" << endl
1350 << "\\begin{center}" << endl;
1351
1352 output << endl
1353 << "\\setlength{\\unitlength}{" << resolution << "mm}" << endl
1354 << "\\filltype{" << fill_type << "}" << endl
1355 << endl
1356 << "\\begin{picture}(" << h_size << "," << v_size << ")"
1357 << "(" << x_picture_offset << "," << y_picture_offset << ")" << endl;
1358}
1359
1360
1362{
1363 output << endl
1364 << endl
1365 << "\\end{picture}" << endl;
1366
1367 if (latex_header)
1368 output << endl
1369 << "\\end{center}" << endl
1370 << "\\end{document}" << endl;
1371}
1372
1374
1375
1376/*
1377 Hay cuatro casos
1378
1379 x
1380
1381 (1) src ------- tgt
1382
1383 (2)
1384 tgt
1385 x /
1386 /
1387 /
1388 src
1389
1390 (3)
1391 src
1392 \
1393 \ x
1394 \
1395 tgt
1396
1397 (4) src
1398 |
1399 | x
1400 |
1401 tgt
1402
1403 La rutina genera una curva src--x--tgt. El punto x se determina según
1404 que el parámetro left sea true o false. En los casos pictorizados
1405 left==true
1406
1407 La primera parte de la rutina determina src y tgt
1408
1409*/
1410void generate_curve(ofstream & output,
1411 EepicNode *p,
1412 EepicNode *q,
1413 const bool left = false,
1414 const bool is_dashed = true)
1415{
1416 const long double & px = X(p); // coordenadas de p
1417 const long double & py = Y(p);
1418
1419 const long double & qx = X(q); // coordenadas de q
1420 const long double & qy = Y(q);
1421
1422 long double srcx, srcy, // punto origen
1423 mx, my, // punto intermedio
1424 tgtx, tgty; // punto destino
1425
1426 EepicNode *src, *tgt; // puntos origen y destino
1427
1428 // determinación de puntos inicial y final
1429 if (px < qx)
1430 {
1431 src = p;
1432 tgt = q;
1433 srcx = px;
1434 srcy = py;
1435 tgtx = qx;
1436 tgty = qy;
1437 }
1438 else
1439 {
1440 src = q;
1441 tgt = p;
1442 srcx = qx;
1443 srcy = qy;
1444 tgtx = px;
1445 tgty = py;
1446 }
1447
1448 // determinación de punto medio
1449 if (fabsl(srcx - tgtx) < hr) // caso (4) ?
1450 {
1451 my = (srcy + tgty) / 2.0;
1452
1453 if (left)
1454 {
1455 srcx -= XR(src);
1456 tgtx -= XR(tgt);
1457 mx = srcx - xgap / 2.5;
1458 }
1459 else
1460 {
1461 srcx += XR(src);
1462 tgtx += XR(tgt);
1463 mx = srcx + xgap / 2.5;
1464 }
1465 }
1466 else if (fabsl(srcy - tgty) < vr) // caso (1)
1467 {
1468 mx = (srcx + tgtx) / 2.0;
1469 srcx += XR(src);
1470 tgtx -= XR(tgt);
1471 my = srcy + (left ? -ygap : ygap) / 2.0;
1472 }
1473 else
1474 {
1475 srcx += XR(src);
1476 tgtx -= XR(tgt);
1477
1478 const long double xfourth = (tgtx - srcx) / 4.0;
1479
1480 if (tgty < srcy) // caso (2)
1481 {
1482 const long double yfourth = (srcy - tgty) / 4.0;
1483
1484 if (left)
1485 {
1486 mx = srcx + xfourth;
1487 my = tgty + 3.0 * yfourth;
1488 }
1489 else
1490 {
1491 mx = srcx + 3.0 * xfourth;
1492 my = tgty + yfourth;
1493 }
1494
1496 }
1497 else // caso (3)
1498 {
1499 const long double yfourth = (tgty - srcy) / 4.0;
1500
1501 if (left)
1502 {
1503 mx = srcx + 3.0 * xfourth;
1504 my = srcy + 3.0 * yfourth;
1505 }
1506 else
1507 {
1508 mx = srcx + xfourth;
1509 my = srcy + yfourth;
1510 }
1511
1512 assert(my >= srcy and my <= tgty);
1513 }
1514
1515 assert(mx >= srcx and mx <= tgtx);
1516 }
1517
1518 output << "\\linethickness{0.05mm}" << endl;
1519
1520 if (is_dashed)
1521 output << "\\curvedashes[1mm]{1,1}" << endl;
1522
1523 output << "\\curve(" << srcx << "," << YPIC(srcy) << ","
1524 << mx << "," << YPIC(my) << ","
1525 << tgtx << "," << YPIC(tgty) << ")";
1526}
1527
1528void generate_tree(ofstream & output, EepicNode *p, int level, int child_index)
1529{
1530 if (p == nullptr)
1531 return;
1532
1533 if (p->is_root())
1534 output << endl
1535 << "% This the tree number " << tree_number++
1536 << " inside a forest ";
1537
1538 assert(LEVEL(p) == level and CHILDNUMBER(p) == child_index);
1539
1540 long double x = X(p);
1541 long double y = Y(p);
1542
1543 /* Imprimir comentario cabecera de nodo */
1544 output << endl
1545 << endl
1546 << "% Node at level " << level << ". It's the "
1547 << child_index << " child with key = " << STRING(p);
1548
1549 /* dibujar nodo */
1551 {
1552 output << endl;
1553 if (ISELLIPSE(p))
1554 output << "% Ellipse" << endl
1555 << "\\put(" << x << "," << YPIC(y) << ")"
1556 << (SHADOW(p) ? "{\\ellipse*{" : "{\\ellipse{") << WIDTH(p)
1557 << "}{" << HEIGHT(p) << "}}";
1558 else
1559 output << "% Rectangle" << endl
1560 << "\\path(" << x - XR(p) << "," << YPIC(y - YR(p)) << ")"
1561 << "(" << x + XR(p) << "," << YPIC(y - YR(p)) << ")"
1562 << "(" << x + XR(p) << "," << YPIC(y + YR(p)) << ")"
1563 << "(" << x - XR(p) << "," << YPIC(y + YR(p)) << ")"
1564 << "(" << x - XR(p) << "," << YPIC(y - YR(p)) << ")";
1565 } { /* imprimir el contenido del nodo */
1566 long double dx = center_string(STRING(p), WIDTH(p));
1567 put_string(output, x - dx + XOFFSET(p), y + y_offset + YOFFSET(p),
1568 "Key text= " + STRING(p), STRING(p));
1569 }
1570
1571 /* imprimir las etiquetas -TAGs- del nodo */
1572 if (not TAGS(p).is_empty())
1573 {
1574 long double tx, ty; /* coordenadas de la tag */
1576 long double r = std::max(XR(p), YR(p)) + 2.0 / resolution; // 2mm
1577 long double dr = sin_45 * r; /* radius r at 45 degrees */
1578 long double dy = font_height();
1579 string comment;
1580
1582 itor.has_curr(); itor.next())
1583 {
1584 tag_data = itor.get_curr();
1585
1586 switch (tag_data.tag_option)
1587 {
1588 case NORTH:
1589 comment = "North tag: ";
1590 tx = x + tag_data.x_offset;
1591 ty = y - r + tag_data.y_offset;
1592 break;
1593 case SOUTH:
1594 comment = "South tag: ";
1595 tx = x + tag_data.x_offset;
1596 ty = y + r + tag_data.y_offset + dy;
1597 break;
1598 case EAST:
1599 comment = "East tag: ";
1600 tx = x + r + tag_data.x_offset;
1601 ty = y + tag_data.y_offset;
1602 break;
1603 case WEST:
1604 comment = "West tag: ";
1605 tx = x - r + tag_data.x_offset - string_width(tag_data.tag);
1606 ty = y + tag_data.y_offset;
1607 break;
1608 case NORTH_EAST:
1609 comment = "Northeast tag: ";
1610 tx = x + dr + tag_data.x_offset;
1611 ty = y - dr + tag_data.y_offset;
1612 break;
1613 case NORTH_WEST:
1614 comment = "Northwest tag: ";
1615 tx = x - dr + tag_data.x_offset - string_width(tag_data.tag);
1616 ty = y - dr + tag_data.y_offset;
1617 break;
1618 case SOUTH_EAST:
1619 comment = "Southeast tag: ";
1620 tx = x + dr + tag_data.x_offset;
1621 ty = y + dr + tag_data.y_offset;
1622 break;
1623 case SOUTH_WEST:
1624 comment = "Southwest tag: ";
1625 tx = x - dr + tag_data.x_offset - string_width(tag_data.tag);
1626 ty = y + dr + tag_data.y_offset;
1627 break;
1628 default:
1629 print_parse_error_and_exit("Fatal: unexpected tag option");
1630 }
1632 }
1633 }
1634
1635 /* Dibujar arcos adicionales declarados con opción ARC o DASHED-ARC */
1637 itor.next())
1638 {
1639 Arc_Data arc_data = itor.get_curr();
1640
1641 long double lx = X(arc_data.target_node);
1642 long double ly = Y(arc_data.target_node);
1643 long double src_dx, src_dy; // diferencias con nodo origen
1644 if (ISELLIPSE(p))
1645 intersection_ellipse_line(x, y, lx, ly, XR(p), YR(p),
1646 src_dx, src_dy);
1647 else
1648 intersection_rectangle_line(x, y, lx, ly, XR(p), YR(p),
1649 src_dx, src_dy);
1650 long double tgt_dx, tgt_dy; // diferencias con nodo destino
1651 if (ISELLIPSE(arc_data.target_node))
1652 intersection_ellipse_line(lx, ly, x, y, XR(arc_data.target_node),
1653 YR(arc_data.target_node), tgt_dx, tgt_dy);
1654 else
1655 intersection_rectangle_line(lx, ly, x, y, XR(arc_data.target_node),
1656 YR(arc_data.target_node), tgt_dx, tgt_dy);
1657 if (lx < x)
1658 src_dx = -src_dx;
1659 else
1660 tgt_dx = -tgt_dx;
1661
1662 /* dibujar arco adicional */
1663 output << endl
1664 << "% Additional arc to child with key " <<
1665 STRING(arc_data.target_node) << endl;
1666 draw_arc(output, x + src_dx, y + src_dy, lx + tgt_dx, ly - tgt_dy,
1667 arc_data.is_dashed, with_arrow);
1668 }
1669
1672
1673 // dibujar conexiones
1675 itor.has_curr(); itor.next())
1676 {
1677 Connexion_Data connexion_data = itor.get_curr();
1678
1679 generate_curve(output, p, connexion_data.target_node,
1680 connexion_data.is_left);
1681
1682# ifdef tmp
1683
1685 output << "\\curve(" << x - dx << "," << YPIC(y + dy) << ","
1686 << px + dx << "," << YPIC(y + h) << ","
1687 << px + dx << "," << YPIC(py + dy) << ")";
1688
1689# endif
1690 }
1691
1692
1694 /* dibujar arcos correspondientes a hijos y visitarlos */
1695 for (EepicNode *c = p->get_left_child(); c != nullptr;
1696 c = c->get_right_sibling())
1697 {
1698 if (WITHARC(c))
1699 { /* dibujar arco */
1700 long double lx = X(c);
1701 long double ly = Y(c);
1702 long double src_dx, src_dy; // diferencias con nodo origen
1703 if (ISELLIPSE(p))
1704 intersection_ellipse_line(x, y, lx, ly, XR(p), YR(p),
1705 src_dx, src_dy);
1706 else
1707 intersection_rectangle_line(x, y, lx, ly, XR(p), YR(p),
1708 src_dx, src_dy);
1709 long double tgt_dx, tgt_dy; // diferencias con nodo destino
1710 if (ISELLIPSE(c))
1711 intersection_ellipse_line(lx, ly, x, y, XR(c), YR(c),
1712 tgt_dx, tgt_dy);
1713 else
1714 intersection_rectangle_line(lx, ly, x, y, XR(c), YR(c),
1715 tgt_dx, tgt_dy);
1716 if (lx < x)
1717 src_dx = -src_dx;
1718 else
1719 tgt_dx = -tgt_dx;
1720
1721 output << endl
1722 << "% Arc to child " << CHILDNUMBER(c)
1723 << " with key " << STRING(c) << endl;
1724
1725 draw_arc(output, x + src_dx, y + src_dy, lx + tgt_dx, ly - tgt_dy,
1726 DASHEDARC(c), with_arrow);
1727 }
1728
1729 /* ahora dibuje recursivamente el proximo nodo */
1730 generate_tree(output, c, level + 1, CHILDNUMBER(c));
1731 }
1732 else
1733 {
1734 EepicNode *c = p->get_left_child();
1735 if (c != nullptr)
1736 {
1737 long double lx = X(c);
1738 long double ly = Y(c);
1739 long double src_dx, src_dy; // diferencias con nodo origen
1740 if (ISELLIPSE(p))
1741 intersection_ellipse_line(x, y, lx, ly, XR(p), YR(p),
1742 src_dx, src_dy);
1743 else
1744 intersection_rectangle_line(x, y, lx, ly, XR(p), YR(p),
1745 src_dx, src_dy);
1746 long double tgt_dx, tgt_dy; // diferencias con nodo destino
1747 if (ISELLIPSE(c))
1748 intersection_ellipse_line(lx, ly, x, y, XR(c), YR(c),
1749 tgt_dx, tgt_dy);
1750 else
1751 intersection_rectangle_line(lx, ly, x, y, XR(c), YR(c),
1752 tgt_dx, tgt_dy);
1753 if (lx < x)
1754 src_dx = -src_dx;
1755 else
1756 tgt_dx = -tgt_dx;
1757
1758 output << endl
1759 << "% link to leftmost child " << CHILDNUMBER(c)
1760 << " with key " << STRING(c) << endl;
1761
1762 draw_arc(output, x + src_dx, y + src_dy, lx + tgt_dx, ly - tgt_dy,
1763 DASHEDARC(c), with_arrow);
1764
1765 /* ahora dibuje recursivamente el proximo nodo */
1766 generate_tree(output, c, level + 1, CHILDNUMBER(c));
1767 }
1768
1769 if (EepicNode *rs = p->get_right_sibling(); rs != nullptr)
1770 {
1771 long double rx = X(rs);
1772 long double ry = Y(rs);
1773 long double src_dx, src_dy; // diferencias con nodo origen
1774 if (ISELLIPSE(p))
1775 intersection_ellipse_line(x, y, rx, ry, XR(p), YR(p),
1776 src_dx, src_dy);
1777 else
1778 intersection_rectangle_line(x, y, rx, ry, XR(p), YR(p),
1779 src_dx, src_dy);
1780 long double tgt_dx, tgt_dy; // diferencias con nodo destino
1781 if (ISELLIPSE(rs))
1783 tgt_dx, tgt_dy);
1784 else
1786 tgt_dx, tgt_dy);
1787 if (rx < x)
1788 src_dx = -src_dx;
1789 else
1790 tgt_dx = -tgt_dx;
1791
1792 output << endl
1793 << "% link to right sibling " << child_index + 1
1794 << " with key " << STRING(rs) << endl;
1795
1796 draw_arc(output, x + src_dx, y + src_dy, rx + tgt_dx, ry - tgt_dy,
1798
1799 /* ahora dibuje recursivamente el proximo nodo */
1801 }
1802 }
1803
1804 if (p->is_root())
1805 /* avance al proximo arbol dentro de la arborescencia */
1806 generate_tree(output, p->get_right_tree(), 0, 0);
1807}
1808
1809
1816
1817
1819 "ntreepic 1.7 - ALEPH drawer for general rooted trees\n"
1820 "Copyright (C) 2004, 2007 UNIVERSITY of LOS ANDES (ULA)\n"
1821 "Merida - REPUBLICA BOLIVARIANA DE VENEZUELA\n"
1822 "Center of Studies in Microelectronics & Distributed Systems (CEMISID)\n"
1823 "ULA Computer Science Department\n"
1824 "This is free software; There is NO warranty; not even for MERCHANTABILITY\n"
1825 "or FITNESS FOR A PARTICULAR PURPOSE\n"
1826 "\n";
1827
1828
1829const char *argp_program_bug_address = "lrleon@ula.ve";
1830
1831
1832static char doc[] = "ntreepic -- Aleph drawer for general rooted trees";
1833
1834
1835static char arg_doc[] = "-f input-file [-o output-file]\n";
1836
1837
1838static const char *hello =
1839 "ALEPH drawer for general rooted trees\n"
1840 "Copyright (C) 2004, 2007 University of Los Andes (ULA)\n"
1841 "Merida - REPUBLICA BOLIVARIANA DE VENEZUELA\n"
1842 "Center of Studies in Microelectronics & Distributed Systems (CEMISID)\n"
1843 "ULA Computer Science Department\n"
1844 "This is free software; There is NO warranty; not even for MERCHANTABILITY\n"
1845 "or FITNESS FOR A PARTICULAR PURPOSE\n"
1846 "\n";
1847
1848
1849static const char license_text[] =
1850 "ALEPH drawer for general rooted trees. License & Copyright Note\n"
1851 "Copyright (C) 2004, 2007\n"
1852 "UNIVERSITY of LOS ANDES (ULA)\n"
1853 "Merida - REPUBLICA BOLIVARIANA DE VENEZUELA\n"
1854 "Center of Studies in Microelectronics & Distributed Systems (CEMISID)\n"
1855 "ULA Computer Science Department\n"
1856 "This is free software; There is NO warranty; not even for MERCHANTABILITY\n"
1857 "or FITNESS FOR A PARTICULAR PURPOSE\n"
1858 "\n"
1859 " PERMISSION TO USE, COPY, MODIFY AND DISTRIBUTE THIS SOFTWARE AND ITS \n"
1860 " DOCUMENTATION IS HEREBY GRANTED, PROVIDED THAT BOTH THE COPYRIGHT \n"
1861 " NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES OF THE \n"
1862 " SOFTWARE, DERIVATIVE WORKS OR MODIFIED VERSIONS, AND ANY PORTIONS \n"
1863 " THEREOF, AND THAT BOTH NOTICES APPEAR IN SUPPORTING DOCUMENTATION. \n"
1864 "\n"
1865 " This program is distributed in the hope that it will be useful,\n"
1866 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1867 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. \n"
1868 "\n"
1869 " ULA requests users of this software to return to \n"
1870 " Proyecto Aleph - CEMISID Software\n"
1871 " Nucleo Universitario La Hechicera. Ed Ingenieria\n"
1872 " 3er piso, ala Este \n"
1873 " Universidad de Los Andes \n"
1874 " Merida 5101 - REPUBLICA BOLIVARIANA DE VENEZUELA \n"
1875 "\n"
1876 " or to lrleon@ula.ve \n"
1877 "\n"
1878 " any improvements or extensions that they make and grant Universidad \n"
1879 " de Los Andes (ULA) the full rights to redistribute these changes. \n"
1880 "\n"
1881 " This program was granted by: \n"
1882 " - Consejo de Desarrollo Cientifico, Humanistico, Tecnico de la ULA\n"
1883 " (CDCHT)\n";
1884
1885
1886static struct argp_option options[] = {
1887 {"radius", 'r', "radius", OPTION_ARG_OPTIONAL, "fit radius for circles", 0},
1888 {"x-gap", 'w', "sibling gap", OPTION_ARG_OPTIONAL, "sibling separation", 0},
1889 {"y-gap", 'h', "children gap", OPTION_ARG_OPTIONAL, "child separation", 0},
1890 {"t-gap", 't', "tree gap", OPTION_ARG_OPTIONAL, "subtree separation", 0},
1891 {
1892 "bin-tree", 'b', "binary tree", OPTION_ARG_OPTIONAL,
1893 "generate binary tree", 0
1894 },
1895 {
1896 "h-radius", 'x', "horizontal-radius", OPTION_ARG_OPTIONAL,
1897 "horizontal radius", 0
1898 },
1899 {
1900 "v-radius", 'y', "vertical-radius", OPTION_ARG_OPTIONAL,
1901 "vertical radius", 0
1902 },
1903 {"resol", 'l', "resolution", OPTION_ARG_OPTIONAL, "resolution in mm", 0},
1904 {"latex", 'a', 0, OPTION_ARG_OPTIONAL, "add latex header", 0},
1905 {"no-node", 'n', 0, OPTION_ARG_OPTIONAL, "no draw nodes; only arcs", 0},
1906 {
1907 "key-x-offset", 'X', "offset", OPTION_ARG_OPTIONAL,
1908 "horizontal offset for keys", 0
1909 },
1910 {
1911 "key-y-offset", 'Y', "offset", OPTION_ARG_OPTIONAL,
1912 "vertical offset for keys", 0
1913 },
1914 {"input-file", 'i', "input-file", 0, "input file", 0},
1915 {"input-file", 'f', "input-file", OPTION_ALIAS, 0, 0},
1916 {"output", 'o', "output-file", 0, "output file", 0},
1917 {"license", 'C', 0, OPTION_ARG_OPTIONAL, "print license", 0},
1918 {
1919 "x-picture-offset", 'O', "horizontal-picture-offset",
1920 OPTION_ARG_OPTIONAL, "horizontal global picture offset", 0
1921 },
1922 {
1923 "y-picture-offset", 'P', "vertical-picture-offset",
1924 OPTION_ARG_OPTIONAL, "vertical global picture offset", 0
1925 },
1926 {"print", 'R', 0, OPTION_ARG_OPTIONAL, "print current parameters", 0},
1927 {"verbose", 'v', 0, OPTION_ARG_OPTIONAL, "verbose mode", 0},
1928 {
1929 "version", 'V', 0, OPTION_ARG_OPTIONAL,
1930 "Print version information and then exit", 0
1931 },
1932 {"black-fill", 'B', 0, OPTION_ARG_OPTIONAL, "Fill black ellipses", 0},
1933 {"shade-fill", 'S', 0, OPTION_ARG_OPTIONAL, "Fill shade ellipses", 0},
1934 {"ellipses", 'e', 0, OPTION_ARG_OPTIONAL, "draw ellipses as nodes", 0},
1935 {"rectangles", 'q', 0, OPTION_ARG_OPTIONAL, "draw rectangles as nodes", 0},
1936 {
1937 "draw-list", 'L', 0, OPTION_ARG_OPTIONAL,
1938 "draw linked list representation", 0
1939 },
1940 {
1941 "draw-tree", 'T', 0, OPTION_ARG_OPTIONAL,
1942 "draw normal tree representation (or turn off linked list form)", 0
1943 },
1944 {
1945 "arrow-len", 'K', "arrow lenght in points", OPTION_ARG_OPTIONAL,
1946 "arrow lenght", 0
1947 },
1948 {
1949 "arrow-width", 'I', "arrow width in points", OPTION_ARG_OPTIONAL,
1950 "arrow width", 0
1951 },
1952 {"arrows", 'A', 0, OPTION_ARG_OPTIONAL, "draw arcs with arrows", 0},
1953 {"vertical-flip", 'F', 0, OPTION_ARG_OPTIONAL, "Flip tree respect y axe", 0},
1954 {0, 0, 0, 0, 0, 0}
1955 };
1956
1957
1958# define TERMINATE(n) (save_parameters(), exit(n))
1959
1960
1961const char *parameters_file_name = "./.ntreepic";
1962
1963
1964inline
1966{
1967 ofstream output(parameters_file_name, ios::trunc);
1968
1969 output << hr << BLANK << vr << BLANK << hd << BLANK << vd << BLANK
1970 << xgap << BLANK << ygap << BLANK << tree_gap << BLANK
1971 << resolution << BLANK << x_offset << BLANK << y_offset << BLANK
1973}
1974
1975
1976inline
1978{
1979 ifstream input(parameters_file_name, ios::in);
1980
1981 input >> hr >> vr >> hd >> vd >> xgap >> ygap >> tree_gap >> resolution
1983}
1984
1985
1986inline
1988{
1989 cout
1990 << "Global horizontal node radius -x = " << hr << endl
1991 << "Global vertical node radius -y = " << vr << endl
1992 << "Global horizontal node diameter = " << hd << endl
1993 << "Global Vertical node diameter = " << vd << endl
1994 << "Horizontal sibling separation -w = " << xgap << endl
1995 << "Vertical children separation -h = " << ygap << endl
1996 << "Subtree separation -t = " << tree_gap << endl
1997 << "Resolution in mm -l = " << resolution << endl
1998 << "Horizontal global offset for key -X = " << x_offset << endl
1999 << "Vertical global offset for key -Y = " << y_offset << endl
2000 << "Horizontal offset for picture -O = " << x_picture_offset << endl
2001 << "Vertical offset for picture -P = " << y_picture_offset << endl;
2002}
2003
2004
2005static error_t parser_opt(int key, char *arg, struct argp_state *)
2006{
2007 switch (key)
2008 {
2009 case 'r': /* Especificacion de radio */
2010 if (arg == nullptr)
2011 AH_ERROR("Waiting for radius in command line");
2012 hr = vr = atof(arg);
2013 hd = vd = 2 * hr;
2014 break;
2015 case 'w': /* brecha entre hermanos */
2016 if (arg == nullptr)
2017 AH_ERROR("Waiting for sibling gap in command line");
2018 xgap = atof(arg);
2019 break;
2020 case 'h': /* brecha entre hermanos */
2021 if (arg == nullptr)
2022 AH_ERROR("Waiting for sibling gap in command line");
2023 ygap = atof(arg);
2024 break;
2025 case 't': /* brecha entre subárboles */
2026 if (arg == nullptr)
2027 AH_ERROR("Waiting for tree gap in command line");
2028 tree_gap = atof(arg);
2029 break;
2030 case 'x': /* radio horizontal de elipse */
2031 if (arg == nullptr)
2032 AH_ERROR("Waiting for horizontal radius in command line");
2033 hr = atof(arg);
2034 hd = 2 * hr;
2035 break;
2036 case 'y': /* radio vertical de elipse */
2037 if (arg == nullptr)
2038 AH_ERROR("Waiting for vertical radius in command line");
2039 vr = atof(arg);
2040 vd = 2 * vr;
2041 break;
2042 case 'l': /* resolucion en milimetros */
2043 if (arg == nullptr)
2044 AH_ERROR("Waiting for resolution in command line");
2045 resolution = atof(arg);
2046 if (resolution > 10)
2047 cout << "Warning: resolution too big" << endl;
2048 break;
2049 case 'a': /* colocar un encabezado latex */
2050 latex_header = true;
2051 break;
2052 case 'n': /* no dibuja nodos, solo arcos */
2053 hr = vr = resolution / 2;
2054 hd = vd = resolution;
2055 not_nodes = true;
2056 break;
2057 case 'X': /* offset horizontal para letras */
2058 if (arg == nullptr)
2059 AH_ERROR("Waiting for horizontal offset in command line");
2060 x_offset = atof(arg);
2061 break;
2062 case 'Y': /* offset vertical para letras */
2063 if (arg == nullptr)
2064 AH_ERROR("Waiting for vertical offset in command line");
2065 y_offset = atof(arg);
2066 break;
2067 case 'O': /* offset horizontal para dibujo */
2068 if (arg == nullptr)
2069 AH_ERROR("Waiting for horizontal offset in command line");
2071 break;
2072 case 'P': /* offset vertical para dibujo */
2073 if (arg == nullptr)
2074 AH_ERROR("Waiting for vertical offset in command line");
2076 break;
2077 case 'v': /* verbose mode (no implementado) */
2078 break;
2079 case 'i': /* archivo de entrada */
2080 case 'f':
2081 {
2082 if (arg == nullptr)
2083 AH_ERROR("Waiting for input file name");
2085 break;
2086 }
2087 case 'o': /* archivo de salida */
2088 if (arg == nullptr)
2089 AH_ERROR("Waiting for output file name");
2091 break;
2092 case 'b': /* generar árbol binario */
2093 generate_binary_tree = true;
2094 break;
2095 case 'C': /* imprime licencia */
2096 cout << license_text;
2097 TERMINATE(0);
2098 break;
2099 case 'R': /* imprime parametros */
2102 TERMINATE(0);
2103 break;
2104 case 'V': /* imprimir version */
2105 cout << argp_program_version;
2106 TERMINATE(0);
2107 break;
2108 case 'B': /* filltype == black */
2109 fill_type = "black";
2110 break;
2111 case 'S': /* filltype == shade */
2112 fill_type = "shade";
2113 break;
2114 case 'e': /* draw ellipses as nodes */
2115 ellipses = true;
2116 rectangles = false;
2117 break;
2118 case 'q': /* draw ellipses as nodes */
2119 ellipses = false;
2120 rectangles = true;
2121 break;
2122 case 'L': /* draw linked list representation */
2124 with_arrow = true;
2125 break;
2126 case 'T': /* draw forest (no list representation) */
2128 break;
2129 case 'A':
2130 with_arrow = true;
2131 break;
2132 case 'K':
2133 with_arrow = true;
2134 if (arg == nullptr)
2135 AH_ERROR("Waiting for arrow lenght in command line");
2137 break;
2138 case 'I':
2139 with_arrow = true;
2140 if (arg == nullptr)
2141 AH_ERROR("Waiting for arrow width in command line");
2142 arrow_width = atof(arg);
2143 break;
2144 case 'F':
2145 flip_y = true;
2146 break;
2147 default: return ARGP_ERR_UNKNOWN;
2148 }
2149 return 0;
2150}
2151
2152
2153static struct argp arg_defs = {options, parser_opt, arg_doc, doc, 0, 0, 0};
2154
2155int main(int argc, char *argv[])
2156{
2157 if (argc == 1)
2158 {
2159 cout <<
2160 "ntreepic -- General rooted tree visualizer (LaTeX/eepic output)\n"
2161 "\n"
2162 "Reads a textual general rooted tree description (.Tree file) and emits\n"
2163 "LaTeX code using eepic drawing primitives, suitable for inclusion in\n"
2164 "publication-quality documents. Supports n-ary trees, forests, and\n"
2165 "linked-list representations.\n"
2166 "\n"
2167 "Usage:\n"
2168 " ntreepic -f <input.Tree> [-o <output.eepic>] [options]\n"
2169 " ntreepic -i <input.Tree> [-o <output.eepic>] [options]\n"
2170 "\n"
2171 "Required:\n"
2172 " -f, -i <file> Input .Tree file\n"
2173 "\n"
2174 "Common options:\n"
2175 " -o <file> Output file (default: input name + .eepic)\n"
2176 " -r <double> Node circle radius (sets horizontal and vertical)\n"
2177 " -x <double> Horizontal radius of node ellipse\n"
2178 " -y <double> Vertical radius of node ellipse\n"
2179 " -w <double> Horizontal gap between siblings\n"
2180 " -h <double> Vertical gap between levels\n"
2181 " -t <double> Gap between subtrees\n"
2182 " -l <double> Resolution in mm\n"
2183 " -a Wrap output in a full LaTeX header\n"
2184 " -e Draw nodes as ellipses (default)\n"
2185 " -q Draw nodes as rectangles\n"
2186 " -n Minimum-radius mode (no node bodies, arcs only)\n"
2187 " -b Emit textual start-prefix/start-key representation of binary tree (via generate_bin_tree())\n"
2188 " -L Draw linked-list representation (with arrows)\n"
2189 " -T Draw forest layout (no linked-list representation)\n"
2190 " -A Draw arcs with arrows\n"
2191 " -B Fill nodes with black\n"
2192 " -S Fill nodes with shade\n"
2193 " -F Flip tree along the y axis\n"
2194 " -X <double> Horizontal label offset\n"
2195 " -Y <double> Vertical label offset\n"
2196 " -O <double> Horizontal global picture offset\n"
2197 " -P <double> Vertical global picture offset\n"
2198 " -R Print current parameters and exit\n"
2199 " -V Print version and exit\n"
2200 " -C Print license and exit\n"
2201 "\n"
2202 "Example:\n"
2203 " ntreepic -f mytree.Tree -o mytree.eepic -a -e\n"
2204 "\n"
2205 "Run 'ntreepic --help' for the complete list of options.\n";
2206 return 0;
2207 }
2208
2210
2212
2213 argp_parse(&arg_defs, argc, argv, ARGP_IN_ORDER, 0, nullptr);
2214
2215 if (input_file_name.size() == 0)
2216 AH_ERROR("Input file not given");
2217
2218 ifstream input_stream(input_file_name.c_str(), ios::in);
2219
2220 if (not input_stream)
2221 AH_ERROR("%s file does not exist", input_file_name.c_str());
2222
2223 cout << hello;
2224
2225 cout << "input from " << input_file_name << " file " << endl;
2226
2227 if (output_file_name.size() == 0)
2228 {
2230 const int pos = input_file_name.rfind(".");
2231 if (pos != string::npos)
2233 string(input_file_name).replace(pos, input_file_name.size() - pos,
2234 string(""));
2235 output_file_name = output_file_name + (tiny_keys ? ".eepicaux" : ".eepic");
2236 }
2237
2238 ofstream output_stream(output_file_name.c_str(), ios::out);
2239
2240 cout << "output sent to " << output_file_name << " file " << endl << endl;
2241
2243
2246 else
2247 {
2249
2251 }
2252
2254
2256}
Exception handling system with formatted messages for Aleph-w.
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
Definition ah-errors.H:463
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
Definition ah-errors.H:639
#define AH_ERROR(format, args...)
Print an error message (always enabled).
Definition ahDefs.H:271
Token_Type
Definition btreepic.C:166
bool dash_threaded_trees
Definition btreepic.C:423
long double h
Definition btreepic.C:154
Iterator dynamic list.
Dynamic doubly linked list with O(1) size and bidirectional access.
Generic m-ary trees.
bool tiny_keys
Global flag to enable tiny font size for keys/labels.
__gmp_expr< T, __gmp_binary_expr< __gmp_expr< T, U >, unsigned long int, __gmp_root_function > > root(const __gmp_expr< T, U > &expr, unsigned long int l)
Definition gmpfrxx.h:4060
void destroy_tree(Node *root)
Destroys (frees memory) the tree whose root is root.
void tree_postorder_traversal(Node *root, void(*visitFct)(Node *, int, int))
Postorder traversal of a tree.
void tree_preorder_traversal(Node *root, void(*visitFct)(Node *, int, int))
Preorder traversal of a tree.
Node * deway_search(Node *root, int path[], const size_t &size)
Returns a node of a forest given its Dewey number.
static mpfr_t y
Definition mpfr_mul_d.c:3
and
Check uniqueness with explicit hash + equality functors.
void init_token_scanning()
Initialize token scanning by recording current position.
void close_token_scanning(const char *buffer, char *&start_addr, const char *end_addr)
Finalize token scanning by null-terminating and saving the token.
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
int read_char_from_stream(std::ifstream &input_stream)
Read a single character from an input stream with position tracking.
void print_parse_error_and_exit(const std::string &str)
Print a parse error message and terminate the program.
void put_char_in_buffer(char *&start_addr, const char *end_addr, int c)
Append a character to a buffer with bounds checking.
std::string command_line_to_string(int argc, char *argv[])
Convert command line arguments to a single string.
void skip_white_spaces(std::ifstream &input_stream)
Skip whitespace characters in the input stream.
constexpr size_t Buffer_Size
Default buffer size for token parsing.
std::string load_string(std::ifstream &input_stream)
Load a string from the input stream.
void print_parse_warning(const std::string &str)
Print a parse warning message.
long load_number(std::ifstream &input_stream)
Load an integer number from the input stream.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
STL namespace.
void parse_rectangle(ifstream &input_stream, EepicNode *root)
Definition ntreepic.C:801
EepicNode * __advance_to_leftmost_in_level(EepicNode *root, const int level, long double &sum)
Definition ntreepic.C:951
EepicNode * parse_deway_number(ifstream &input_stream, EepicNode *root)
Definition ntreepic.C:563
#define YD(p)
Definition ntreepic.C:356
int tree_number
Definition ntreepic.C:1373
void save_parameters()
Definition ntreepic.C:1965
long double ygap
Definition ntreepic.C:194
void compute_coordinates_for_forest_and_set_picture_size(EepicNode *root)
Definition ntreepic.C:1219
bool draw_list_representation
Definition ntreepic.C:211
const char * parameters_file_name
Definition ntreepic.C:1961
#define MOD(p)
Definition ntreepic.C:346
Token_Type get_token(ifstream &input_stream)
Definition ntreepic.C:420
void generate_tree(ofstream &output, EepicNode *p, int level, int child_index)
Definition ntreepic.C:1528
void adjust_minimal_separation_with_letf_sibling(EepicNode *p)
Definition ntreepic.C:1001
void shift_tree_to_right(EepicNode *p, int, int)
Definition ntreepic.C:1213
#define TAGS(p)
Definition ntreepic.C:370
void parse_xoffset(ifstream &input_stream, EepicNode *root)
Definition ntreepic.C:681
bool rectangles
Definition ntreepic.C:210
void generate_forest(ofstream &output, EepicNode *root)
Definition ntreepic.C:1810
void precompute_x_for_node(EepicNode *p, const int level, const int child)
Definition ntreepic.C:1090
#define YRGAP(p)
Definition ntreepic.C:359
void parse_connexion(ifstream &input_stream, EepicNode *root)
Definition ntreepic.C:772
static error_t parser_opt(int key, char *arg, struct argp_state *)
Definition ntreepic.C:2005
void precompute_x_coordinates_for_tree(EepicNode *root)
Definition ntreepic.C:1193
#define ISRECTANGLE(p)
Definition ntreepic.C:350
#define SHADOW(p)
Definition ntreepic.C:364
#define DASHEDARC(p)
Definition ntreepic.C:367
@ ARC
Definition ntreepic.C:222
@ DASHED_CONNEXION
Definition ntreepic.C:222
@ NODE
Definition ntreepic.C:221
@ ELLIPSE
Definition ntreepic.C:222
@ HRADIO
Definition ntreepic.C:222
@ VRADIO
Definition ntreepic.C:222
@ SOUTH
Definition ntreepic.C:225
@ SOUTH_WEST
Definition ntreepic.C:231
@ DASHED_ARC
Definition ntreepic.C:222
@ END_FILE
Definition ntreepic.C:223
@ COMMENT
Definition ntreepic.C:223
@ TAG
Definition ntreepic.C:222
@ EAST
Definition ntreepic.C:226
@ NORTH_WEST
Definition ntreepic.C:229
@ WITHOUT_NODE
Definition ntreepic.C:221
@ NORTH
Definition ntreepic.C:224
@ ROOT
Definition ntreepic.C:221
@ NORTH_EAST
Definition ntreepic.C:228
@ SOUTH_EAST
Definition ntreepic.C:230
@ LEFT
Definition ntreepic.C:232
@ RECTANGLE
Definition ntreepic.C:223
@ WEST
Definition ntreepic.C:227
@ RIGHT
Definition ntreepic.C:233
@ INVALID
Definition ntreepic.C:234
@ WITHOUT_ARC
Definition ntreepic.C:221
void generate_curve(ofstream &output, EepicNode *p, EepicNode *q, const bool left=false, const bool is_dashed=true)
Definition ntreepic.C:1410
#define HEIGHT(p)
Definition ntreepic.C:363
#define XD(p)
Definition ntreepic.C:355
EepicNode * parse_first_root_definition(ifstream &input_stream)
Definition ntreepic.C:586
void parse_arc(ifstream &input_stream, EepicNode *root)
Definition ntreepic.C:732
void parse_without_arc(ifstream &input_stream, EepicNode *root)
Definition ntreepic.C:665
long double y_offset
Definition ntreepic.C:199
#define Y(p)
Definition ntreepic.C:344
long double h_size
Definition ntreepic.C:196
#define WITHOUTNODE(p)
Definition ntreepic.C:365
void generate_epilogue(ofstream &output)
Definition ntreepic.C:1361
void parse_shadow(ifstream &input_stream, EepicNode *root)
Definition ntreepic.C:702
void generate_prefix_traversal(ofstream &output, EepicNode *root)
Definition ntreepic.C:1263
long double hr
Definition ntreepic.C:189
std::string input_file_name
Definition ntreepic.C:204
#define YOFFSET(p)
Definition ntreepic.C:352
long double vr
Definition ntreepic.C:190
void generate_infix_traversal(ofstream &output, EepicNode *root)
Definition ntreepic.C:1275
#define X(p)
Definition ntreepic.C:343
#define CONNEXIONS(p)
Definition ntreepic.C:369
#define BLANK
Definition ntreepic.C:185
#define POS(p)
Definition ntreepic.C:357
bool latex_header
Definition ntreepic.C:208
long double x_picture_offset
Definition ntreepic.C:200
const char * argp_program_version
Definition ntreepic.C:1818
#define XOFFSET(p)
Definition ntreepic.C:351
void read_parameters()
Definition ntreepic.C:1977
#define LEVEL(p)
Definition ntreepic.C:360
void parse_vradio(ifstream &input_stream, EepicNode *root)
Definition ntreepic.C:636
Tree_Node< Tree_Data > EepicNode
Definition ntreepic.C:242
#define ARCS(p)
Definition ntreepic.C:368
EepicNode * read_input_and_build_tree(ifstream &input_stream)
Definition ntreepic.C:810
long double vd
Definition ntreepic.C:192
double v_size
Definition ntreepic.C:197
#define WIDTH(p)
Definition ntreepic.C:362
void parse_ellipse(ifstream &input_stream, EepicNode *root)
Definition ntreepic.C:792
bool generate_binary_tree
Definition ntreepic.C:212
long double shift_size
Definition ntreepic.C:1211
EepicNode * parse_key_node_and_allocate(ifstream &input_stream)
Definition ntreepic.C:578
EepicNode * allocate_node(const string &str)
Definition ntreepic.C:551
void parse_yoffset(ifstream &input_stream, EepicNode *root)
Definition ntreepic.C:692
static const char license_text[]
Definition ntreepic.C:1849
std::string output_file_name
Definition ntreepic.C:205
#define MAXCHILDYR(p)
Definition ntreepic.C:358
EepicNode * __advance_to_rightmost_in_level(EepicNode *root, const int level, long double &sum)
Definition ntreepic.C:913
#define PRE(p)
Definition ntreepic.C:345
void parse_hradio(ifstream &input_stream, EepicNode *root)
Definition ntreepic.C:621
EepicNode * advance_to_leftmost_in_level(EepicNode *root, const int level, long double &sum)
Definition ntreepic.C:975
void parse_node_definition(ifstream &input_stream, EepicNode *root)
Definition ntreepic.C:606
#define ISELLIPSE(p)
Definition ntreepic.C:349
long double y_max
Definition ntreepic.C:1147
void parse_without_node(ifstream &input_stream, EepicNode *root)
Definition ntreepic.C:651
const char * argp_program_bug_address
Definition ntreepic.C:1829
#define WITHARC(p)
Definition ntreepic.C:366
static char arg_doc[]
Definition ntreepic.C:1835
void compute_coordinates_for_tree(EepicNode *root)
Definition ntreepic.C:1199
long double hd
Definition ntreepic.C:191
void load_deway_number(ifstream &input_stream, int deway_array[], size_t deway_array_size)
Definition ntreepic.C:374
long double x_offset
Definition ntreepic.C:198
static struct argp_option options[]
Definition ntreepic.C:1886
void parse_tag(ifstream &input_stream, EepicNode *root)
Definition ntreepic.C:712
void generate_bin_tree(ofstream &output, EepicNode *root)
Definition ntreepic.C:1288
static const char * hello
Definition ntreepic.C:1838
#define XR(p)
Definition ntreepic.C:353
bool ellipses
Definition ntreepic.C:209
long double xgap
Definition ntreepic.C:193
long double tree_gap
Definition ntreepic.C:195
void print_parameters()
Definition ntreepic.C:1987
void parse_dashed_arc(ifstream &input_stream, EepicNode *root)
Definition ntreepic.C:755
void compute_definitive_coordinates_for_node(EepicNode *p, int, int)
Definition ntreepic.C:1159
long double y_picture_offset
Definition ntreepic.C:201
#define STRING(p)
Definition ntreepic.C:348
void infix_tree(EepicNode *root)
Definition ntreepic.C:1250
void generate_prologue(ofstream &output)
Definition ntreepic.C:1305
#define TERMINATE(n)
Definition ntreepic.C:1958
std::string command_line
Definition ntreepic.C:203
#define CHILDNUMBER(p)
Definition ntreepic.C:361
EepicNode * advance_to_rightmost_in_level(EepicNode *root, const int level, long double &sum)
Definition ntreepic.C:937
bool not_nodes
Definition ntreepic.C:213
static struct argp arg_defs
Definition ntreepic.C:2153
void parse_root_definition(ifstream &input_stream, EepicNode *root)
Definition ntreepic.C:596
Token_Type Tag_Option
Definition ntreepic.C:238
#define SUMMOD(p)
Definition ntreepic.C:347
static char doc[]
Definition ntreepic.C:1832
#define YR(p)
Definition ntreepic.C:354
long double x_max
Definition ntreepic.C:1146
Comprehensive parsing utilities for text processing and compiler construction.
EepicNode * target_node
Definition ntreepic.C:263
bool is_dashed
Definition btreepic.C:223
long target_node
Definition btreepic.C:222
EepicNode * target_node
Definition ntreepic.C:274
long double x_offset
Definition btreepic.C:194
string tag
Definition btreepic.C:192
Tag_Data(string str, const Tag_Option option)
Definition ntreepic.C:253
Tag_Option tag_option
Definition btreepic.C:193
long double y_offset
Definition btreepic.C:195
Tag_Data()=default
int level
Definition ntreepic.C:328
long double mod
Definition ntreepic.C:288
long double yd
Definition ntreepic.C:297
bool shadow
Definition ntreepic.C:315
long double xd
Definition ntreepic.C:297
long double max_child_yr
Definition ntreepic.C:299
long double xr
Definition ntreepic.C:295
int position
Definition ntreepic.C:320
bool rectangle
Definition ntreepic.C:313
long double yr_gap
Definition ntreepic.C:303
int child_number
Definition ntreepic.C:329
bool without_node
Definition ntreepic.C:316
long double x
Definition ntreepic.C:286
bool with_arc
Definition ntreepic.C:317
long double yoffset
Definition ntreepic.C:310
bool ellipse
Definition ntreepic.C:312
DynDlist< Connexion_Data > connexion_list
Definition ntreepic.C:326
long double pre
Definition ntreepic.C:288
DynDlist< Arc_Data > arc_list
Definition ntreepic.C:324
string str
Definition ntreepic.C:308
DynDlist< Tag_Data > tag_list
Definition ntreepic.C:322
bool dashed_arc
Definition ntreepic.C:318
long double y
Definition ntreepic.C:286
long double xoffset
Definition ntreepic.C:310
long double yr
Definition ntreepic.C:295
long double sum_mod
Definition ntreepic.C:291
static long counter
Definition test-splice.C:35
gsl_rng * r
Lazy and scalable dynamic array implementation.
Dynamic doubly linked list implementation.
General tree (n-ary tree) node.
DynList< int > l
Tree picture generation utilities.
void intersection_ellipse_line(long double lx0, long double ly0, long double lx1, long double ly1, long double a, long double b, long double &dx, long double &dy)
long double resolution
void put_string(std::ofstream &output, const long double &x, const long double &y, const std::string &comment, const std::string &str)
long double string_width(const std::string &str)
long double arrow_lenght
bool with_arrow
bool flip_y
void draw_arc(std::ofstream &output, long double src_x, long double src_y, long double tgt_x, long double tgt_y, bool is_dashed, bool with_arrow, bool thick=true)
void intersection_rectangle_line(long double lx0, long double ly0, long double lx1, long double ly1, long double a, long double b, long double &dx, long double &dy)
long double arrow_width
const char * fill_type
long double font_height()
long double YPIC(long double y)
long double center_string(const std::string &str, long double window_size)
const long double sin_45
ofstream output
Definition writeHeap.C:215