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