Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
graphpic.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
174# include <iostream>
175# include <fstream>
176# include <string>
177# include <tpl_dynTreap.H>
178# include <tpl_dynArray.H>
179# include <tpl_sort_utils.H>
180# include <tpl_graph.H>
181# include <treepic_utils.H>
182# include <parse_utils.H>
183# include <eepicgeom.H>
184
185# include <tclap/CmdLine.h>
186
187using namespace std;
188
189# define TERMINATE(n) (save_parameters(), exit(n))
190
191// TODO: corregir tag con los angulos de 45 al punto de intersección con
192// la elipse
193
195{
197 DIGRAPH, GRAPH, // Indica si es grafo o digrafo
201 NODE, // Nodo
202 ARC, // Arco
203 SHADOW_NODE, // Nodo sombreado
204 SHADOW_ARC, // Arco sombreado
205 DASHED_ARC, // Arco punteado
206 DASHED_CURVE_ARC, // Arco curvo punteado
207 CURVE_ARC, // Arco curvo
208 SHADOW_CURVE_ARC, // Arco curvo sombreado
209 NODE_TEXT, // Etiqueta de nodo
210 ARC_TEXT, // Etiqueta de arco
211 TAG, // Etiqueta
212 WITHOUT_NODE, // No dibujar nodo
213 SHADOW_PATH, // Camino sombreado a destacar entre dos nodos
214 PATH, // Camino a destacar entre dos nodos
215 LEFT, RIGHT, // Cadena a escribir en un arco (a su izquierda o derecha)
216 HRADIO, // radio horizontal de un nodo particular
217 VRADIO, // radio vertical de un nodo particular
218 STRING, // Cadena a escribir en un nodo
219 // TAG options
220 NORTH, // N
221 SOUTH, // S
222 EAST, // E
223 WEST, // W
229 INVALID
231
232
233extern bool tiny_keys;
234
235/* valores de distancias por omision */
236double hr = 8; // radio horizontal de la elipse
237double vr = 8; // radio vertical de la elipse
238
239double h_size = 3000; /* longitud horizontal de picture */
240double v_size = 3000; /* longitud vertical de picture */
241
242double zoom_factor = 1;
243
244double hd = 2 * hr; // diametro horizontal de la elipse
245double vd = 2 * vr; // diametro vertical de la elipse
246double x_offset = 0; /* offset horizontal etiqueta */
247double y_offset = 0;
248double x_picture_offset = 0; // offset horizontal para dibujo
249double y_picture_offset = 0; // offset vertical para dibujo
250
251long line_dimension = 100;
252
256
257bool draw_node_mode = true; // dibujar elipses
258
259bool squarize = true; // ajuste automático de la escala del dibujo
260
261bool latex_header = false; // envolver salida con un latex header
262bool ellipses = true; // por omisión dibujar elipses
263bool rectangles = false;
264bool not_nodes = false;
265
266
267const char *parameters_file_name = "./.graphpic";
268
269
270inline
272{
273 cout
274 << "Horizontal radius -x = " << hr << endl
275 << "Vertical radius -y = " << vr << endl
276 << "Horizontal diameter = " << hd << endl
277 << "Vertical diameter = " << vd << endl
278 << "Resolution in mm -l = " << resolution << endl
279 << "Horizontal size -z = " << h_size << endl
280 << "Vertical size -u = " << v_size << endl
281 << "Horizontal offset for key -X = " << x_offset << endl
282 << "Vertical offset for key -Y = " << y_offset << endl
283 << "Horizontal offset for picture -O = " << x_picture_offset << endl
284 << "Vertical offset for picture -P = " << y_picture_offset << endl;
285}
286
287
288inline
290{
291 ofstream output(parameters_file_name, ios::trunc);
292
293 output << hr << " " << vr << " " << hd << " " << vd << " " << resolution
294 << " " << h_size << " " << v_size << " " << x_offset
295 << " " << y_offset << " " << x_picture_offset << " " << y_picture_offset
296 << " " << endl;
297}
298
299
300inline
302{
303 ifstream input(parameters_file_name, ios::in);
304
305 input >> hr >> vr >> hd >> vd >> resolution >> h_size
308}
309
310
311using namespace std;
312
313
315
316typedef double Coord;
317
318struct Tag_Data
319{
320 string tag;
321
323 double xoffset;
324 double yoffset;
325};
326
328{
330 string name;
331 double x, y;
332 double hr, vr;
333 bool shadow;
335
337
339
341 {
342 xoffset = 0;
343 yoffset = 0;
344 // empty
345 }
346};
347
348
349# define X(p) ((p)->get_info().x)
350# define Y(p) ((p)->get_info().y)
351# define HR(p) ((p)->get_info().hr)
352# define VR(p) ((p)->get_info().vr)
353# define SHADOW(p) ((p)->get_info().shadow)
354# define WITHOUT(p) ((p)->get_info().without)
355# define NUMBER(p) ((p)->get_info().number)
356# define STRING(p) ((p)->get_info().name)
357# define XOFFSET(p) ((p)->get_info().xoffset)
358# define YOFFSET(p) ((p)->get_info().yoffset)
359# define TAGS(p) ((p)->get_info().tag_list)
360
361# define DYNARRAY_APPEND(array, item) (array[array.size()] = item)
362
363
364struct Arc_Data
365{
366 string data;
367 double xoffset;
368 double yoffset;
369 bool shadow;
370 bool dashed;
371 bool curve;
372 bool left;
374
376 : xoffset(0), yoffset(0),
378 {
379 // empty
380 }
381};
382
383
384# define STRING_ARC(a) ((a)->get_info().data)
385# define XOFFSET_ARC(a) ((a)->get_info().xoffset)
386# define YOFFSET_ARC(a) ((a)->get_info().yoffset)
387# define SHADOW_ARC(a) ((a)->get_info().shadow)
388# define DASHED_ARC(a) ((a)->get_info().dashed)
389# define CURVE_ARC(a) ((a)->get_info().curve)
390# define CURVE_LEFT(a) ((a)->get_info().left)
391# define CURVE_MID(a) ((a)->get_info().curve_mid)
392
393
395
397
399
401
403
404size_t num_nodes = 0;
405
407
409
410
412{
413 char buffer[Buffer_Size];
414 char *start_addr = buffer;
415 char *end_addr = buffer + Buffer_Size;
416
417 int c;
418
420
421 try
422 {
425 }
426 catch (const std::out_of_range &)
427 {
428 return END_FILE;
429 }
430
431 if (c == EOF)
432 return END_FILE;
433
434 if (not isprint(c))
435 return INVALID;
436
437 if (c == '%')
438 { /* comentario */
439 do
441 while (c != '\n' and c != EOF);
442 return COMMENT;
443 }
444
445 do /* delimita una cadena de caracteres cualquiera delimitada por blancos */
446 {
447 put_char_in_buffer(start_addr, end_addr, c);
449 }
450 while (isgraph(c) and c != '%' and c != EOF);
451
452 close_token_scanning(buffer, start_addr, end_addr);
453
454 if (c == '%') /* Se encontró comentario */
455 /* retroceda, así proxima llamada detectara comentario */
456 input_stream.unget();
457
458 if (strcasecmp(buffer, "NODE") == 0)
459 return NODE;
460
461 if (strcasecmp(buffer, "SHADOW-NODE") == 0)
462 return SHADOW_NODE;
463
464 if (strcasecmp(buffer, "WITHOUT-NODE") == 0)
465 return WITHOUT_NODE;
466
467 if (strcasecmp(buffer, "HRADIO") == 0)
468 return HRADIO;
469
470 if (strcasecmp(buffer, "VRADIO") == 0)
471 return VRADIO;
472
473 if (strcasecmp(buffer, "ARC") == 0)
474 return ARC;
475
476 if (strcasecmp(buffer, "NODE-TEXT") == 0)
477 return NODE_TEXT;
478
479 if (strcasecmp(buffer, "ARC-TEXT") == 0)
480 return ARC_TEXT;
481
482 if (strcasecmp(buffer, "DASHED-ARC") == 0)
483 return DASHED_ARC;
484
485 if (strcasecmp(buffer, "SHADOW-ARC") == 0)
486 return SHADOW_ARC;
487
488 if (strcasecmp(buffer, "CURVE-ARC") == 0)
489 return CURVE_ARC;
490
491 if (strcasecmp(buffer, "ARC-TEXT") == 0)
492 return ARC_TEXT;
493
494 if (strcasecmp(buffer, "SHADOW-CURVE-ARC") == 0)
495 return SHADOW_CURVE_ARC;
496
497 if (strcasecmp(buffer, "DASHED-CURVE-ARC") == 0)
498 return DASHED_CURVE_ARC;
499
500 if (strcasecmp(buffer, "SHADOW-PATH") == 0)
501 return SHADOW_PATH;
502
503 if (strcasecmp(buffer, "TAG") == 0)
504 return TAG;
505
506 if (strcasecmp(buffer, "N") == 0)
507 return NORTH;
508
509 if (strcasecmp(buffer, "S") == 0)
510 return SOUTH;
511
512 if (strcasecmp(buffer, "E") == 0)
513 return EAST;
514
515 if (strcasecmp(buffer, "L") == 0)
516 return LEFT;
517
518 if (strcasecmp(buffer, "R") == 0)
519 return RIGHT;
520
521 if (strcasecmp(buffer, "W") == 0)
522 return WEST;
523
524 if (strcasecmp(buffer, "NE") == 0)
525 return NORTH_EAST;
526
527 if (strcasecmp(buffer, "NW") == 0)
528 return NORTH_WEST;
529
530 if (strcasecmp(buffer, "SE") == 0)
531 return SOUTH_EAST;
532
533 if (strcasecmp(buffer, "SW") == 0)
534 return SOUTH_WEST;
535
536 if (strcasecmp(buffer, "GRAPH") == 0)
537 return GRAPH;
538
539 if (strcasecmp(buffer, "DIGRAPH") == 0)
540 return DIGRAPH;
541
542 if (strcasecmp(buffer, "POLY-DIGRAPH") == 0)
543 return POLY_DIGRAPH;
544
545 if (strcasecmp(buffer, "POLY-GRAPH") == 0)
546 return POLY_GRAPH;
547
548 if (strcasecmp(buffer, "NET-DIGRAPH") == 0)
549 return NET_DIGRAPH;
550
551 if (strcasecmp(buffer, "NET-GRAPH") == 0)
552 return NET_GRAPH;
553
554 if (strcasecmp(buffer, "CROSS-NET-DIGRAPH") == 0)
555 return CROSS_NET_DIGRAPH;
556
557 if (strcasecmp(buffer, "CROSS-NET-GRAPH") == 0)
558 return CROSS_NET_GRAPH;
559
560 return STRING;
561}
562
563
565{
566 try
567 {
568 const int side_size = load_number(input_stream);
569
570 const double arc = load_number(input_stream);
571
572 const Regular_Polygon
573 poly(Point(side_size, side_size), side_size, num_nodes, arc);
574
575 for (size_t i = 0; i < num_nodes; ++i)
576 {
577 Graph::Node *p = nodes[i];
578
579 const Point pt = poly.get_vertex(static_cast<int>(i));
580
581 X(p) = pt.get_x().get_d();
582 Y(p) = pt.get_y().get_d();
583 }
584 }
585
586 catch (const std::domain_error &)
587 {
588 AH_ERROR("Expecting for side-size or an arc");
589 }
590
591 return g;
592}
593
594
595// NET-GRAPH num-nodes num-levels x-dist y-dist
597{
598 try
599 {
600 const int num_levels = load_number(input_stream);
601
602 const double xdist = load_number(input_stream);
603
604 const double ydist = load_number(input_stream);
605
606 const size_t & num_nodes = g->get_num_nodes();
607
608 const size_t nodes_by_level = num_nodes / static_cast<size_t>(num_levels);
609
610 double y = 0;
611 for (int level = 0, i = 0; level < num_levels and static_cast<size_t>(i) < num_nodes; ++level)
612 {
613 double x = 0;
614
615 for (size_t j = 0; j < nodes_by_level and static_cast<size_t>(i) < num_nodes; ++j, ++i)
616 {
617 Graph::Node *p = nodes[i];
618
619 X(p) = x;
620 Y(p) = y;
621
622 x += xdist;
623 }
624
625 y += ydist;
626 }
627 }
628
629 catch (const std::domain_error &)
630 {
631 AH_ERROR("Expecting for num-of-levels or a distance");
632 }
633
634 return g;
635}
636
637
638// CROSS-NET-GRAPH num-nodes nodes-by-level x-dist y-dist
640{
641 try
642 {
644
645 const double xdist = load_number(input_stream);
646
647 const double ydist = load_number(input_stream);
648
649 const size_t & num_nodes = g->get_num_nodes();
650
651 double y = 0;
652 for (size_t i = 0; i < num_nodes; /* nothing */)
653 {
654 double x = xdist / 2;
655
656 for (int j = 0; j < nodes_by_level - 1 and i < num_nodes; ++j, ++i)
657 {
658 Graph::Node *p = nodes[i];
659
660 X(p) = x;
661 Y(p) = y;
662
663 x += xdist;
664 }
665
666 x = 0;
667 y += ydist;
668
669 for (int j = 0; j < nodes_by_level and i < num_nodes; ++j, ++i)
670 {
671 Graph::Node *p = nodes[i];
672
673 X(p) = x;
674 Y(p) = y;
675
676 x += xdist;
677 }
678
679 y += ydist;
680 }
681 }
682
683 catch (const std::domain_error &)
684 {
685 AH_ERROR("Expecting for num-of-levels or a distance");
686 }
687
688 return g;
689}
690
691
692/*
693 GRAPH num-nodes
694
695 POLY-GRAPH num_nodes side-size rotation
696
697 NET-GRAPH num-nodes num-levels x-dist y-dist
698
699 CROSS-NET-GRAPH num-nodes num-levels x-dist y-dist
700*/
702{
704
705 if (token != GRAPH and token != DIGRAPH and
709 print_parse_error_and_exit("Input does not start with GRAPH definition");
710
711 Graph *g = (token == GRAPH or token == POLY_GRAPH or
713 new Graph :
714 new ::Digraph;
715
716 try
717 {
719 }
720 catch (...)
721 {
722 AH_ERROR("Expecting for number of nodes");
723 }
724
725 for (size_t i = 0; i < num_nodes; i++)
726 {
727 Graph::Node *p = new Graph::Node;
728 nodes[i] = g->insert_node(p);
729 string n = to_string(i);
730 p->get_info().name = n;
731 NUMBER(p) = static_cast<int>(i);
732 }
733
734 if (token == GRAPH or token == DIGRAPH)
735 return g;
736
739
741 return build_net_graph(input_stream, g);
742
744}
745
746
748{
750
751 if (node_number < 0 or static_cast<size_t>(node_number) >= num_nodes)
752 AH_ERROR("Node number out of range (%zu)", num_nodes);
753
755
756 return p;
757}
758
759
760/*
761 Node i string x y
762*/
764{
766
767 Node_Data & node_data = p->get_info();
768
770
771 node_table.insert(node_data.name, p);
772
774
776}
777
778// TAG node-number string sentido xoffset yoffset
780{
782
784
787
788 if (tag_data.sense < NORTH or tag_data.sense > SOUTH_WEST)
789 print_parse_error_and_exit("Invalid tag option found");
790
791 tag_data.xoffset = load_number(input_stream); // xoffset
792 tag_data.yoffset = load_number(input_stream); // yoffset
793
794 TAGS(p).append(tag_data);
795}
796
798{
800
801 WITHOUT(p) = true;
802}
803
804
806{
808
809 SHADOW(p) = true;
810}
811
812
813void load_nodes(ifstream & input_stream,
814 Graph::Node *& src_node,
815 Graph::Node *& tgt_node)
816{
818
819 if (num_src < 0 or static_cast<size_t>(num_src) >= num_nodes)
820 AH_ERROR("source node %d out of range (%zu)", num_src, num_nodes);
821
823
824 if (num_tgt < 0 or static_cast<size_t>(num_tgt) >= num_nodes)
825 AH_ERROR("Target node %d out of range (%zu)", num_tgt, num_nodes);
826
827 src_node = nodes[num_src];
828 tgt_node = nodes[num_tgt];
829}
830
831
832/*
833 ARC number-node number-tgt-node
834*/
836{
837 Graph::Node *src_node = nullptr;
838 Graph::Node *tgt_node = nullptr;
839
840 load_nodes(input_stream, src_node, tgt_node);
841
842 Graph::Arc *arc = search_arc(*g, src_node, tgt_node);
843
844 if (arc == nullptr)
845 {
846 Graph::Arc *arc = g->insert_arc(src_node, tgt_node, Arc_Data());
847
849
850 return arc;
851 }
852
853 return arc;
854}
855
856
857/*
858 NODE-TEXT number-node Text xoffset yoffset
859*/
870
871
872/*
873 ARC-TEXT number-node number-tgt-node Text xoffset yoffset
874*/
876{
877 Graph::Node *src_node = nullptr;
878 Graph::Node *tgt_node = nullptr;
879
880 load_nodes(input_stream, src_node, tgt_node);
881
882 Graph::Arc *a = search_arc(*g, src_node, tgt_node);
883
884 if (a == nullptr)
885 AH_ERROR("Arc not found");
886
890
891 return a;
892}
893
894
895/* CURVED-ARC src tgt mid-point sentido */
897{
899
900 CURVE_ARC(arc) = true;
901
903
905
906 if (token == LEFT)
907 CURVE_LEFT(arc) = true;
908 else if (token == RIGHT)
909 CURVE_LEFT(arc) = false;
910 else
911 AH_ERROR("Invalid sense in curved-arc definition");
912
913 return arc;
914}
915
916
918{
920
921 SHADOW_ARC(arc) = true;
922
923 return arc;
924}
925
926
928{
930
931 DASHED_ARC(arc) = true;
932
933 return arc;
934}
935
936
937/* SHADOW-CURVED-ARC src tgt mid-point sentido */
940{
942
943 SHADOW_ARC(arc) = true;
944
945 return arc;
946}
947
948
949/* DASHED-CURVED-ARC src tgt mid-point sentido */
952{
954
955 DASHED_ARC(arc) = true;
956
957 return arc;
958}
959
960
961// HRADIO node-number radio
968
969
970// VRADIO node-number radio
977
978
980{
982
983 try
984 {
985 while (true)
986 switch (get_token(input_stream))
987 {
988 case END_FILE:
989 return g;
990
991 case INVALID:
992 print_parse_error_and_exit("Unrecognized token");
993
994 case COMMENT: break;
995
996 case NODE:
998 break;
999
1000 case TAG:
1002 break;
1003
1004 case WITHOUT_NODE:
1006 break;
1007
1008 case SHADOW_NODE:
1010 break;
1011
1012 case ARC:
1014 break;
1015
1016 case SHADOW_ARC:
1018 break;
1019
1020 case DASHED_ARC:
1022 break;
1023
1024 case NODE_TEXT:
1026 break;
1027
1028 case ARC_TEXT:
1030 break;
1031
1032 case CURVE_ARC:
1034 break;
1035
1036 case SHADOW_CURVE_ARC:
1038 break;
1039
1040 case DASHED_CURVE_ARC:
1042 break;
1043
1044 case HRADIO:
1046 break;
1047
1048 case VRADIO:
1050 break;
1051
1052 default:
1053 print_parse_error_and_exit("Unknown token type");
1054 }
1055 }
1056 catch (exception & e)
1057 {
1058 delete g;
1060 }
1061
1062 return nullptr; // nunca se alcanza
1063}
1064
1065
1067{
1068 time_t t;
1069 time(&t);
1070 output << endl
1071 << "% This LaTeX picture is a graph automatically" << endl
1072 << "% generated by graphpic program" << endl
1073 << endl
1074 << "% Copyright (C) 2007" << endl
1075 << "% UNIVERSITY of LOS ANDES (ULA)" << endl
1076 << "% Merida - REPUBLICA BOLIVARIANA DE VENEZUELA" << endl
1077 << "% Center of Studies in Microelectronics & Distributed Systems"
1078 << " (CEMISID)" << endl
1079 << "% ULA Computer Science Department" << endl
1080 << endl
1081 << "% Leandro Leon - lrleon@ula.ve" << endl
1082 << endl
1083 << "% You must use curves, epic and eepic latex packages" << endl
1084 << "% in your LaTeX application" << endl
1085 << endl
1086 << "% curves Copyright by I.L. Maclaine-cross" << endl
1087 << "% epic Copyright by Sunil Podar" << endl
1088 << "% eepic Copyright by Conrad Kwok" << endl
1089 << "% LaTeX is a collection of TeX macros created by Leslie Lamport"
1090 << endl
1091 << "% TeX was created by Donald Knuth" << endl
1092 << endl
1093 << "% command line: " << endl
1094 << "% " << command_line << endl
1095 << endl
1096 << "% input file: " << input_file_name << endl
1097 << "% output file: " << output_file_name << endl
1098 << endl
1099 << "% Creation date: " << ctime(&t) << endl
1100 << endl;
1101
1102 if (latex_header)
1103 output << "%%%%%%%%%%%%%%%% LATEX Header generated with -a option" << endl
1104 << "\\documentclass[11pt]{article}" << endl
1105 << endl
1106 << "\\usepackage{curves}" << endl
1107 << "\\usepackage{epic}" << endl
1108 << "\\usepackage{eepic}" << endl
1109 << endl
1110 << "\\begin{document}" << endl
1111 << "\\begin{center}" << endl;
1112}
1113
1114
1115// retorna un segmento desde el nodo src hasta el nodo tgt. Los extremos
1116// corresponden con la intersección de la linea con los bordes de la
1117// elipse
1119{
1120 // centros de las elipses de los nodos
1121 const Point src_center(X(src), Y(src));
1122 const Point tgt_center(X(tgt), Y(tgt));
1123
1124 const Segment l(src_center, tgt_center); // segmento entre los centros
1125
1126 // ellipses de nodos
1127 const Ellipse src_el(src_center, HR(src), VR(src));
1128 const Ellipse tgt_el(tgt_center, HR(tgt), VR(tgt));
1129
1130 // calcula las intersecciones de la recta que pasa por los puntos
1131 // centrales de las elipses
1132 const Segment src_sg = src_el.intersection_with(l);
1133 const Segment tgt_sg = tgt_el.intersection_with(l);
1134
1135 // selecciona como punto de intersección el que esté más cercano
1136 // al centro de la elipse opuesta
1137 const Point & src_point = src_sg.nearest_point(tgt_center);
1138
1139 // selecciona el punto de intersección que sea parte del segmento l
1140 // entre los centros de la elipse
1141 const Point & tgt_point = tgt_sg.nearest_point(src_center);
1142
1143 return Segment(src_point, tgt_point);
1144}
1145
1146
1148 Graph::Node *tgt,
1149 const double & dist,
1150 const bool & left)
1151{
1152 // centros de las elipses de los nodos
1153 const Point src_center(X(src), Y(src));
1154 const Point tgt_center(X(tgt), Y(tgt));
1155
1156 const Segment l(src_center, tgt_center); // segmento entre los centros
1157
1158 const Segment perp = l.mid_perpendicular(dist); // perpendicular que
1159 // pasa por el centro
1160
1161 // selecciona según bandera left el punto medio de la curva
1162 const Point & mid = left ? perp.get_tgt_point() : perp.get_src_point();
1163
1164
1165 // cálculo del punto origen -------
1166
1167 const Ellipse src_el(src_center, HR(src), VR(src)); // elipse origen
1168 const Segment src_to_mid(src_center, mid); // segmento centro elipse--mid
1169
1170 // calcular puntos de intersección entre elipse origen y segmento
1171 // hacia punto medio
1172 const Segment src_inter = src_el.intersection_with(src_to_mid); // intersecta
1173
1174 const Point & src_pt = src_inter.nearest_point(mid);
1175
1176
1177 // cálculo del punto destino -------
1178
1179 const Ellipse tgt_el(tgt_center, hr, vr); // elipse destino
1180 const Segment mid_to_tgt(mid, tgt_center); // segmento centro mid--elipse
1181
1182 // calcular puntos de intersección entre segmento desde el punto
1183 // medio y la elipse origen
1184 const Segment tgt_inter = tgt_el.intersection_with(mid_to_tgt); // intersecta
1185
1186 const Point & tgt_pt = tgt_inter.nearest_point(mid);
1187
1188 // calculados los tres puntos, nos resta por construir el polígono
1189 // abierto
1190 Polygon result;
1191
1192 result.add_vertex(src_pt);
1193 result.add_vertex(mid);
1194 result.add_vertex(tgt_pt);
1195
1196 return result;
1197}
1198
1199
1201{
1202 const double & xp = X(p);
1203 const double & yp = Y(p);
1204
1205
1206 for (DynDlist<Tag_Data>::Iterator it(TAGS(p)); it.has_curr(); it.next())
1207 {
1208 const Tag_Data & tag_data = it.get_curr();
1209
1210 Point tag_point(xp, yp);
1211
1212 tag_point += Point(tag_data.xoffset, tag_data.yoffset);
1213
1214 switch (tag_data.sense)
1215 {
1216 case NORTH:
1217 {
1218 tag_point += Polar_Point(VR(p), PI_2);
1219
1221
1222 break;
1223 }
1224
1225 case SOUTH:
1226 {
1227 tag_point += Polar_Point(VR(p), -PI_2);
1228
1230
1231 break;
1232 }
1233
1234 case EAST:
1235 {
1236 tag_point += Polar_Point(HR(p), 0);
1237
1239
1240 break;
1241 }
1242
1243 case WEST:
1244 {
1245 tag_point += Polar_Point(HR(p), PI);
1246
1248
1249 break;
1250 }
1251
1252 case NORTH_EAST:
1253 {
1254 tag_point += Polar_Point(pitag(HR(p), VR(p)), PI_4);
1255
1257
1258 break;
1259 }
1260
1261 case NORTH_WEST:
1262 {
1263 tag_point += Polar_Point(-pitag(HR(p), VR(p)), -PI_4);
1264
1266
1267 break;
1268 }
1269
1270 case SOUTH_EAST:
1271 {
1272 tag_point += Polar_Point(pitag(HR(p), VR(p)), -PI_4);
1273
1275
1276 break;
1277 }
1278
1279 case SOUTH_WEST:
1280 {
1281 tag_point += Polar_Point(-pitag(HR(p), VR(p)), PI_4);
1282
1284
1285 break;
1286 }
1287
1288 default:
1289 AH_ERROR("(internal) invalid tag sense option %ld", tag_data.sense);
1290 }
1291 }
1292}
1293
1294
1296{
1298 {
1299 if (SHADOW(p))
1300 put_in_plane(plane, Thick_Ellipse(Point(X(p), Y(p)), HR(p), VR(p)));
1301 else
1302 put_in_plane(plane, Ellipse(Point(X(p), Y(p)), HR(p), VR(p)));
1303 }
1304
1305 put_in_plane(plane, Center_Text(Point(X(p), Y(p)) + Point(XOFFSET(p), YOFFSET(p)),
1306 STRING(p)));
1307
1308 process_tag_node(plane, p);
1309}
1310
1311
1312void
1314{
1315 const string & text = STRING_ARC(a);
1316
1317 if (text == "")
1318 return;
1319
1320 const Point offset(XOFFSET_ARC(a), YOFFSET_ARC(a));
1321
1322 const Point mid_point = arc_sg.mid_point() + offset;
1323
1324 switch (arc_sg.sense())
1325 {
1326 case Segment::E:
1327 {
1328 const double ydiff = vr / 2;
1329
1330 const Point pos = Point(0, ydiff);
1331
1332 put_in_plane(plane, Center_Text(mid_point + pos, text));
1333
1334 break;
1335 }
1336
1337 case Segment::W:
1338 {
1339 const double ydiff = 0.6 * vr;
1340
1341 const Point pos = Point(0, -ydiff);
1342
1343 put_in_plane(plane, Center_Text(mid_point + pos, text));
1344
1345 break;
1346 }
1347
1348 case Segment::N:
1349 put_in_plane(plane, Left_Text(mid_point, text));
1350
1351 break;
1352
1353 case Segment::S:
1354 put_in_plane(plane, Right_Text(mid_point, text));
1355
1356 break;
1357
1358 case Segment::NE:
1359 case Segment::SE:
1360 case Segment::NW:
1361 case Segment::SW:
1362 {
1363 const double xdiff = vr / 2;
1364
1365 const Point pos = Point(xdiff, 0);
1366
1367 put_in_plane(plane, Left_Text(mid_point + pos, text));
1368
1369 break;
1370 }
1371
1372 default: AH_ERROR("(Internal) invalid sense option");
1373 }
1374}
1375
1376
1378{
1379 if (STRING_ARC(a) == "")
1380 return;
1381
1382 // la idea es calcular un segmento paralelo al que conectaría los
1383 // nodos y luego invocar a la rutina anterior sobre ese segmento
1384 // paralelo
1385 const Vertex & first_vt = trigon.get_first_vertex();
1386
1387 // segmento que conectaría a los nodos si no hubiese un arco
1388 const Segment arc_sg(first_vt, trigon.get_last_vertex());
1389
1390 // punto por donde debe pasar el segmento paralelo
1391 const Point & second_pt = first_vt.next_vertex();
1392
1393 const Geom_Number dist = second_pt.distance_with(arc_sg.mid_point());
1394
1395 const Segment par_sg(arc_sg, dist); // segmento paralelo
1396
1397 process_text_arc(plane, a, par_sg);
1398}
1399
1400
1402{
1403 Graph::Node *src_node = g->get_src_node(a);
1404 Graph::Node *tgt_node = g->get_tgt_node(a);
1405
1406 if (CURVE_ARC(a)) // ¿es el arco una curva?
1407 {
1408 Polygon poly = // determine el trio de puntos que la definen
1409 arc_trigon(src_node, tgt_node, CURVE_MID(a), CURVE_LEFT(a));
1410
1411 process_text_arc(plane, a, poly);
1412
1413 if (g->is_digraph())
1414 {
1415 if (SHADOW_ARC(a))
1416 {
1417 if (DASHED_ARC(a))
1419 else
1420 put_in_plane(plane, Thick_Spline_Arrow(poly));
1421 }
1422 else
1423 {
1424 if (DASHED_ARC(a))
1426 else
1427 put_in_plane(plane, Spline_Arrow(poly));
1428 }
1429 }
1430 else
1431 {
1432 if (SHADOW_ARC(a))
1433 {
1434 if (DASHED_ARC(a))
1435 put_in_plane(plane, Thick_Dash_Polygon(poly));
1436 else
1437 put_in_plane(plane, Thick_Spline(poly));
1438 }
1439 else
1440 {
1441 if (DASHED_ARC(a))
1442 put_in_plane(plane, Dash_Polygon(poly));
1443 else
1444 put_in_plane(plane, Spline(poly));
1445 }
1446 }
1447
1448 return;
1449 }
1450
1451 const Segment sg = arc_segment(src_node, tgt_node);
1452
1453 process_text_arc(plane, a, sg);
1454
1455 if (g->is_digraph())
1456 {
1457 if (SHADOW_ARC(a))
1458 {
1459 if (DASHED_ARC(a))
1460 put_in_plane(plane, Thick_Dash_Arrow(sg));
1461 else
1462 put_in_plane(plane, Thick_Arrow(sg));
1463 }
1464 else
1465 {
1466 if (DASHED_ARC(a))
1467 put_in_plane(plane, Dash_Arrow(sg));
1468 else
1469 put_in_plane(plane, Arrow(sg));
1470 }
1471 }
1472 else
1473 {
1474 if (SHADOW_ARC(a))
1475 {
1476 if (DASHED_ARC(a))
1477 put_in_plane(plane, Thick_Dash_Segment(sg));
1478 else
1479 put_in_plane(plane, Thick_Segment(sg));
1480 }
1481 else
1482 {
1483 if (DASHED_ARC(a))
1484 put_in_plane(plane, Dash_Segment(sg));
1485 else
1486 put_in_plane(plane, sg);
1487 }
1488 }
1489}
1490
1491
1492void generate_picture(ofstream & output, Graph *g)
1493{
1495
1496 for (Graph::Node_Iterator it(*g); it.has_curr(); it.next())
1497 process_node(plane, it.get_current_node());
1498
1499 for (size_t i = 0; i < ::arcs.size(); ++i)
1500 process_arc(plane, g, ::arcs[i]);
1501
1502 plane.zoom(zoom_factor);
1503
1504 plane.draw(output, squarize);
1505}
1506
1507
1509{
1510 if (latex_header)
1511 output << endl
1512 << "\\end{center}" << endl
1513 << "\\end{document}" << endl;
1514}
1515
1516
1517void generate_graph(Graph *g, ofstream & output)
1518{
1520
1522
1524}
1525
1526
1527int main(int argc, char *argv[])
1528{
1529 try
1530 {
1531 TCLAP::CmdLine cmd(
1532 "graphpic - Aleph-w graph visualization tool.\n"
1533 "Generates LaTeX/eepic pictures from graph DSL specifications.\n"
1534 "Copyright (C) 2007-2024 University of Los Andes (ULA)",
1535 ' ', "1.1"
1536 );
1537
1538 // Input/output files
1539 TCLAP::ValueArg<string> inputArg(
1540 "f", "file", "Input graph specification file (required unless -R)", false, "", "file", cmd
1541 );
1542 TCLAP::ValueArg<string> outputArg(
1543 "o", "output", "Output eepic file (default: input.eepic)", false, "", "file", cmd
1544 );
1545
1546 // Node geometry
1547 TCLAP::ValueArg<double> radiusArg(
1548 "r", "radius", "Fit radius for circles (sets both hr and vr)", false, 8, "radius", cmd
1549 );
1550 TCLAP::ValueArg<double> hRadiusArg(
1551 "x", "h-radius", "Horizontal radius of node ellipse", false, 8, "radius", cmd
1552 );
1553 TCLAP::ValueArg<double> vRadiusArg(
1554 "y", "v-radius", "Vertical radius of node ellipse", false, 8, "radius", cmd
1555 );
1556
1557 // Picture dimensions
1558 TCLAP::ValueArg<double> widthArg(
1559 "W", "width", "Picture width", false, 3000, "size", cmd
1560 );
1561 TCLAP::ValueArg<double> heightArg(
1562 "H", "height", "Picture height", false, 3000, "size", cmd
1563 );
1564 TCLAP::ValueArg<double> zoomArg(
1565 "Z", "zoom", "Zoom factor", false, 1.0, "factor", cmd
1566 );
1567 TCLAP::ValueArg<double> resolArg(
1568 "l", "resolution", "Resolution in mm", false, resolution, "mm", cmd
1569 );
1570
1571 // Offsets
1572 TCLAP::ValueArg<double> xOffsetArg(
1573 "X", "key-x-offset", "Horizontal key offset", false, 0, "offset", cmd
1574 );
1575 TCLAP::ValueArg<double> yOffsetArg(
1576 "Y", "key-y-offset", "Vertical key offset", false, 0, "offset", cmd
1577 );
1578 TCLAP::ValueArg<double> xPicOffsetArg(
1579 "O", "x-pic-offset", "X picture offset", false, 0, "offset", cmd
1580 );
1581 TCLAP::ValueArg<double> yPicOffsetArg(
1582 "P", "y-pic-offset", "Y picture offset", false, 0, "offset", cmd
1583 );
1584
1585 // Switches
1586 TCLAP::SwitchArg latexArg(
1587 "a", "latex", "Add LaTeX document header", cmd, false
1588 );
1589 TCLAP::SwitchArg noNodesArg(
1590 "N", "no-nodes", "Do not draw node ellipses", cmd, false
1591 );
1592 TCLAP::SwitchArg noSquareArg(
1593 "S", "no-squarize", "Do not auto-fit picture scale", cmd, false
1594 );
1595 TCLAP::SwitchArg tinyKeysArg(
1596 "t", "tiny-keys", "Use tiny keys", cmd, false
1597 );
1598 TCLAP::SwitchArg printParamsArg(
1599 "R", "print-params", "Print current parameters and exit", cmd, false
1600 );
1601
1602 cmd.parse(argc, argv);
1603
1604 // Store command line for prologue
1606
1607 // Read saved parameters
1609
1610 // Print parameters and exit if requested
1611 if (printParamsArg.getValue())
1612 {
1615 return 0;
1616 }
1617
1618 // Validate input file is provided when not just printing params
1619 if (not inputArg.isSet())
1620 AH_ERROR("Input file (-f) is required");
1621
1622 // Apply command line values (override saved parameters)
1623 if (radiusArg.isSet())
1624 {
1625 hr = vr = radiusArg.getValue();
1626 hd = vd = 2 * hr;
1627 }
1628 if (hRadiusArg.isSet())
1629 {
1630 hr = hRadiusArg.getValue();
1631 hd = 2 * hr;
1632 }
1633 if (vRadiusArg.isSet())
1634 {
1635 vr = vRadiusArg.getValue();
1636 vd = 2 * vr;
1637 }
1638 if (widthArg.isSet())
1639 h_size = widthArg.getValue();
1640 if (heightArg.isSet())
1641 v_size = heightArg.getValue();
1642 if (zoomArg.isSet())
1643 zoom_factor = zoomArg.getValue();
1644 if (resolArg.isSet())
1645 {
1646 resolution = resolArg.getValue();
1647 if (resolution > 10)
1648 cout << "Warning: resolution too big" << endl;
1649 }
1650 if (xOffsetArg.isSet())
1651 x_offset = xOffsetArg.getValue();
1652 if (yOffsetArg.isSet())
1653 y_offset = yOffsetArg.getValue();
1654 if (xPicOffsetArg.isSet())
1655 x_picture_offset = xPicOffsetArg.getValue();
1656 if (yPicOffsetArg.isSet())
1657 y_picture_offset = yPicOffsetArg.getValue();
1658
1659 latex_header = latexArg.getValue();
1660 draw_node_mode = not noNodesArg.getValue();
1661 squarize = not noSquareArg.getValue();
1662 tiny_keys = tinyKeysArg.getValue();
1663
1664 // Process input/output files
1665 input_file_name = inputArg.getValue();
1666
1667 if (outputArg.isSet())
1668 output_file_name = outputArg.getValue();
1669 else
1670 {
1671 size_t pos = input_file_name.rfind(".");
1672 if (pos == string::npos)
1673 output_file_name = input_file_name + ".eepic";
1674 else
1675 output_file_name = input_file_name.substr(0, pos) + ".eepic";
1676 }
1677
1678 // Open input file
1679 ifstream input_stream(input_file_name.c_str());
1680 if (not input_stream)
1681 AH_ERROR("%s file does not exist", input_file_name.c_str());
1682
1683 cout << "graphpic - Aleph-w graph visualization tool\n";
1684 cout << "Input: " << input_file_name << endl;
1685 cout << "Output: " << output_file_name << endl << endl;
1686
1687 // Open output file
1688 ofstream output_stream(output_file_name.c_str(), ios::out);
1689 if (not output_stream)
1690 AH_ERROR("Cannot create output file %s", output_file_name.c_str());
1691
1692 // Process graph
1695
1697
1698 delete g;
1699
1700 return 0;
1701 }
1702 catch (TCLAP::ArgException & e)
1703 {
1704 cerr << "Error: " << e.error() << " for argument " << e.argId() << endl;
1705 return 1;
1706 }
1707 catch (exception & e)
1708 {
1709 cerr << "Error: " << e.what() << endl;
1710 return 1;
1711 }
1712}
#define AH_ERROR(format, args...)
Print an error message (always enabled).
Definition ahDefs.H:271
int main()
Token_Type
Definition btreepic.C:166
Generic directed graph (digraph) wrapper template.
Definition graph-dry.H:3848
Iterator dynamic list.
Dynamic doubly linked list with O(1) size and bidirectional access.
Graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:428
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Definition tpl_graph.H:524
Node Node
The graph type.
Definition tpl_graph.H:432
_Graph_Arc Arc
The node class type.
Definition tpl_graph.H:433
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Definition tpl_graph.H:604
2D canvas for generating EEPIC/LaTeX picture environments.
Definition eepicgeom.H:250
void zoom(const double &factor)
Scale the EEPIC plane in real points (zoom in/out).
Definition eepicgeom.H:395
void draw(std::ostream &output, const bool &squarize=true)
Emits a complete LaTeX picture environment containing the geometric objects.
Definition eepicgeom.H:475
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:731
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:695
bool is_digraph() const noexcept
Return true if the graph this is directed.
Definition graph-dry.H:657
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:737
Rectangular point in the plane.
Definition point.H:156
Polar representation of a 2D point.
Definition point.H:343
A general (irregular) 2D polygon defined by a sequence of vertices.
Definition polygon.H:233
void add_vertex(const Point &point)
Add a vertex to the polygon.
Definition polygon.H:610
A regular polygon defined by center, side length, and vertex count.
Definition polygon.H:829
const Point get_vertex(const size_t &i) const
Get the i-th vertex of the polygon.
Definition polygon.H:895
Fundamental segment defined by two points.
Definition point.H:417
@ SE
Definition point.H:756
@ N
Definition point.H:756
@ NW
Definition point.H:756
@ W
Definition point.H:756
@ E
Definition point.H:756
@ NE
Definition point.H:756
@ SW
Definition point.H:756
@ S
Definition point.H:756
A vertex in a polygon's doubly-linked vertex list.
Definition polygon.H:113
void put_in_plane(Eepic_Plane &plane, const Point &geom_obj)
Definition eepicgeom.C:50
EEPIC/LaTeX geometric drawing utilities.
void save_parameters()
Definition graphpic.C:289
void process_node(Eepic_Plane &plane, Graph::Node *p)
Definition graphpic.C:1295
Graph::Arc * parse_arc_text_definition(ifstream &input_stream, Graph *g)
Definition graphpic.C:875
bool draw_node_mode
Definition graphpic.C:257
const char * parameters_file_name
Definition graphpic.C:267
void parse_hradio_definition(ifstream &input_stream)
Definition graphpic.C:962
void generate_graph(Graph *g, ofstream &output)
Definition graphpic.C:1517
Graph::Arc * parse_shadow_curve_arc_definition(ifstream &input_stream, Graph *g)
Definition graphpic.C:939
Token_Type get_token(ifstream &input_stream)
Definition graphpic.C:411
double y_picture_offset
Definition graphpic.C:249
#define NUMBER(p)
Definition graphpic.C:355
void parse_shadow_node_definition(ifstream &input_stream)
Definition graphpic.C:805
#define TAGS(p)
Definition graphpic.C:359
bool rectangles
Definition graphpic.C:263
void generate_picture(ofstream &output, Graph *g)
Definition graphpic.C:1492
#define SHADOW(p)
Definition graphpic.C:353
Graph::Node * parse_node_text_definition(ifstream &input_stream)
Definition graphpic.C:860
Segment arc_segment(Graph::Node *src, Graph::Node *tgt)
Definition graphpic.C:1118
@ ARC_TEXT
Definition graphpic.C:210
@ ARC
Definition graphpic.C:202
@ POLY_GRAPH
Definition graphpic.C:198
@ DIGRAPH
Definition graphpic.C:197
@ CROSS_NET_GRAPH
Definition graphpic.C:200
@ GRAPH
Definition graphpic.C:197
@ NODE_TEXT
Definition graphpic.C:209
@ SHADOW_PATH
Definition graphpic.C:213
@ NODE
Definition graphpic.C:201
@ NET_GRAPH
Definition graphpic.C:199
@ HRADIO
Definition graphpic.C:216
@ SHADOW_CURVE_ARC
Definition graphpic.C:208
@ VRADIO
Definition graphpic.C:217
@ SOUTH
Definition graphpic.C:221
@ SOUTH_WEST
Definition graphpic.C:227
@ NET_DIGRAPH
Definition graphpic.C:199
@ END_FILE
Definition graphpic.C:228
@ CROSS_NET_DIGRAPH
Definition graphpic.C:200
@ COMMENT
Definition graphpic.C:196
@ TAG
Definition graphpic.C:211
@ EAST
Definition graphpic.C:222
@ DASHED_CURVE_ARC
Definition graphpic.C:206
@ NORTH_WEST
Definition graphpic.C:225
@ WITHOUT_NODE
Definition graphpic.C:212
@ NORTH
Definition graphpic.C:220
@ PATH
Definition graphpic.C:214
@ NORTH_EAST
Definition graphpic.C:224
@ SHADOW_NODE
Definition graphpic.C:203
@ SOUTH_EAST
Definition graphpic.C:226
@ LEFT
Definition graphpic.C:215
@ WEST
Definition graphpic.C:223
@ POLY_DIGRAPH
Definition graphpic.C:198
@ RIGHT
Definition graphpic.C:215
@ INVALID
Definition graphpic.C:229
Graph::Arc * parse_shadow_arc_definition(ifstream &input_stream, Graph *g)
Definition graphpic.C:917
double Coord
Definition graphpic.C:316
#define YOFFSET_ARC(a)
Definition graphpic.C:386
#define CURVE_ARC(a)
Definition graphpic.C:389
void process_tag_node(Eepic_Plane &plane, Graph::Node *p)
Definition graphpic.C:1200
Graph * build_poly_graph(ifstream &input_stream, Graph *g)
Definition graphpic.C:564
#define Y(p)
Definition graphpic.C:350
double hd
Definition graphpic.C:244
#define VR(p)
Definition graphpic.C:352
void generate_epilogue(ofstream &output)
Definition graphpic.C:1508
bool tiny_keys
Global flag to enable tiny font size for keys/labels.
double hr
Definition graphpic.C:236
#define SHADOW_ARC(a)
Definition graphpic.C:387
#define YOFFSET(p)
Definition graphpic.C:358
#define X(p)
Definition graphpic.C:349
#define WITHOUT(p)
Definition graphpic.C:354
string output_file_name
Definition graphpic.C:255
double vr
Definition graphpic.C:237
bool latex_header
Definition graphpic.C:261
#define XOFFSET(p)
Definition graphpic.C:357
size_t num_nodes
Definition graphpic.C:404
double h_size
Definition graphpic.C:239
#define DASHED_ARC(a)
Definition graphpic.C:388
void read_parameters()
Definition graphpic.C:301
double vd
Definition graphpic.C:245
double v_size
Definition graphpic.C:240
Graph * parse_graph_definition(ifstream &input_stream)
Definition graphpic.C:701
#define HR(p)
Definition graphpic.C:351
Graph * read_input_and_build_graph(ifstream &input_stream)
Definition graphpic.C:979
bool squarize
Definition graphpic.C:259
Graph * build_cross_net_graph(ifstream &input_stream, Graph *g)
Definition graphpic.C:639
void process_arc(Eepic_Plane &plane, Graph *g, Graph::Arc *a)
Definition graphpic.C:1401
Graph::Arc * parse_dashed_arc_definition(ifstream &input_stream, Graph *g)
Definition graphpic.C:927
void parse_tag_definition(ifstream &input_stream)
Definition graphpic.C:779
#define CURVE_LEFT(a)
Definition graphpic.C:390
Polygon arc_trigon(Graph::Node *src, Graph::Node *tgt, const double &dist, const bool &left)
Definition graphpic.C:1147
Graph::Arc * parse_dashed_curve_arc_definition(ifstream &input_stream, Graph *g)
Definition graphpic.C:951
DynArray< Graph::Node * > nodes
Definition graphpic.C:406
Graph_Node< Node_Data > Node
Definition graphpic.C:394
#define STRING_ARC(a)
Definition graphpic.C:384
void load_nodes(ifstream &input_stream, Graph::Node *&src_node, Graph::Node *&tgt_node)
Definition graphpic.C:813
#define XOFFSET_ARC(a)
Definition graphpic.C:385
string input_file_name
Definition graphpic.C:254
double zoom_factor
Definition graphpic.C:242
#define DYNARRAY_APPEND(array, item)
Definition graphpic.C:361
string command_line
Definition graphpic.C:253
bool ellipses
Definition graphpic.C:262
void print_parameters()
Definition graphpic.C:271
void parse_vradio_definition(ifstream &input_stream)
Definition graphpic.C:971
double x_offset
Definition graphpic.C:246
Graph::Arc * parse_curve_arc_definition(ifstream &input_stream, Graph *g)
Definition graphpic.C:896
#define STRING(p)
Definition graphpic.C:356
void process_text_arc(Eepic_Plane &plane, Graph::Arc *a, const Segment &arc_sg)
Definition graphpic.C:1313
Graph::Arc * parse_arc_definition(ifstream &input_stream, Graph *g)
Definition graphpic.C:835
void generate_prologue(ofstream &output)
Definition graphpic.C:1066
DynTreapTree< string, Graph::Node * > node_table
Definition graphpic.C:402
void parse_without_node_definition(ifstream &input_stream)
Definition graphpic.C:797
bool not_nodes
Definition graphpic.C:264
#define CURVE_MID(a)
Definition graphpic.C:391
Graph * build_net_graph(ifstream &input_stream, Graph *g)
Definition graphpic.C:596
Graph_Arc< Arc_Data > Arc
Definition graphpic.C:396
void parse_node_definition(ifstream &input_stream)
Definition graphpic.C:763
Token_Type Tag_Option
Definition graphpic.C:314
List_Graph< Node, Arc > Graph
Definition graphpic.C:398
double y_offset
Definition graphpic.C:247
DynArray< Graph::Arc * > arcs
Definition graphpic.C:408
Graph::Node * load_node(ifstream &input_stream)
Definition graphpic.C:747
double x_picture_offset
Definition graphpic.C:248
long line_dimension
Definition graphpic.C:251
GT::Arc * search_arc(const GT &g, typename GT::Node *src, typename GT::Node *tgt, SA sa=SA()) noexcept
Arc filtered searching given two nodes.
Definition tpl_graph.H:2421
const long double offset[]
Offset values indexed by symbol string length (bounded by MAX_OFFSET_INDEX)
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 to_string(const time_t t, const std::string &format)
Format a time_t value into a string using format.
Definition ah-date.H:140
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.
long load_number(std::ifstream &input_stream)
Load an integer number from the input stream.
STL namespace.
Token_Type
Definition ntreepic.C:219
Comprehensive parsing utilities for text processing and compiler construction.
constexpr double PI
Definition point.H:85
constexpr double PI_2
Definition point.H:86
Geom_Number pitag(const Geom_Number &x, const Geom_Number &y)
Return the Euclidean distance.
Definition point.H:104
constexpr double PI_4
Definition point.H:87
Dynamic mapping implemented with treap trees.
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
Node belonging to a graph implemented with a double linked adjacency list.
Definition tpl_graph.H:121
double xoffset
Definition graphpic.C:367
bool curve
Definition graphpic.C:371
bool dashed
Definition graphpic.C:370
int curve_mid
Definition graphpic.C:373
string data
Definition graphpic.C:366
double yoffset
Definition graphpic.C:368
bool left
Definition graphpic.C:372
bool shadow
Definition graphpic.C:369
Segment-drawing variants (types).
Definition eepicgeom.H:1205
double x
Definition graphpic.C:331
double hr
Definition graphpic.C:332
bool without
Definition graphpic.C:334
bool shadow
Definition graphpic.C:333
int number
Definition graphpic.C:329
string name
Definition graphpic.C:330
double yoffset
Definition graphpic.C:336
DynDlist< Tag_Data > tag_list
Definition graphpic.C:338
double y
Definition graphpic.C:331
double vr
Definition graphpic.C:332
double xoffset
Definition graphpic.C:336
double yoffset
Definition graphpic.C:324
string tag
Definition btreepic.C:192
double xoffset
Definition graphpic.C:323
Token_Type sense
Definition graphpic.C:322
Lazy and scalable dynamic array implementation.
Dynamic treap alias.
Generic graph and digraph implementations.
Comprehensive sorting algorithms and search utilities for Aleph-w.
DynList< int > l
Tree picture generation utilities.
long double resolution
ofstream output
Definition writeHeap.C:213