LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
tikz_node_renderer.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012-2026, QORE Lab, Imperial College London
3 * All rights reserved.
4 */
5#ifndef LINE_IO_TIKZ_TIKZ_NODE_RENDERER_H
6#define LINE_IO_TIKZ_TIKZ_NODE_RENDERER_H
7
8/**
9 * @file
10 * @ingroup line_io
11 * Port of `jline.io.tikz.TikZNodeRenderer`: the preamble with the node styles,
12 * and one TikZ node per network node.
13 *
14 * The shape follows the node's KIND, in the JAR's `instanceof` order: a Delay
15 * is a green box marked infinity, a Queue a buffer with its discipline beneath
16 * and a server circle carrying the server count, a Source/Sink a small
17 * white/black circle with an arrival/departure stub, Fork/Join diamonds, a
18 * Router a hexagon, a ClassSwitch a trapezium, a Cache a grey box with three
19 * level lines, a Logger a brown box, a Place a circle, a Transition a black bar.
20 * Any other kind (a Region) falls back to a plain circle.
21 */
22
23#include <cmath>
24#include <sstream>
25#include <string>
26
29
30namespace line {
31namespace io {
32
33/** `TikZNodeRenderer.getPreamble`, byte for byte. */
34inline std::string tikz_preamble(const TikzOptions& opt) {
35 std::ostringstream sb;
36 sb << "\\documentclass[tikz,border=" << opt.border_padding << "pt]{standalone}\n";
37 sb << "\\usepackage{tikz}\n";
38 sb << "\\usetikzlibrary{arrows.meta,positioning,shapes.geometric,shapes.misc,calc,"
39 "decorations.pathreplacing}\n";
40 sb << "\n";
41 sb << "\\tikzset{\n";
42 sb << " % Queue: Rectangle buffer\n"
43 " queue/.style={\n"
44 " rectangle,\n"
45 " draw=black,\n"
46 " minimum width=1.1cm,\n"
47 " minimum height=0.72cm,\n"
48 " fill=white\n"
49 " },\n";
50 sb << " % Server circle\n"
51 " server/.style={\n"
52 " circle,\n"
53 " draw=black,\n"
54 " minimum size=0.6cm,\n"
55 " fill=white\n"
56 " },\n";
57 sb << " % Delay: Vertical rectangle (infinite server)\n"
58 " delay/.style={\n"
59 " rectangle,\n"
60 " draw=black,\n"
61 " minimum width=0.8cm,\n"
62 " minimum height=1.5cm,\n"
63 " fill=green!10\n"
64 " },\n";
65 sb << " % Source: Small circle (white)\n"
66 " source/.style={\n"
67 " circle,\n"
68 " draw=black,\n"
69 " minimum size=0.3cm,\n"
70 " fill=white\n"
71 " },\n";
72 sb << " % Sink: Small circle (black)\n"
73 " sink/.style={\n"
74 " circle,\n"
75 " draw=black,\n"
76 " minimum size=0.3cm,\n"
77 " fill=black\n"
78 " },\n";
79 sb << " % Fork: Diamond\n"
80 " fork/.style={\n"
81 " diamond,\n"
82 " draw=black,\n"
83 " minimum size=1cm,\n"
84 " fill=orange!20,\n"
85 " aspect=1.5\n"
86 " },\n";
87 sb << " % Join: Diamond\n"
88 " joinnode/.style={\n"
89 " diamond,\n"
90 " draw=black,\n"
91 " minimum size=1cm,\n"
92 " fill=purple!20,\n"
93 " aspect=1.5\n"
94 " },\n";
95 sb << " % Router: Hexagon\n"
96 " router/.style={\n"
97 " regular polygon,\n"
98 " regular polygon sides=6,\n"
99 " draw=black,\n"
100 " minimum size=1cm,\n"
101 " fill=cyan!10\n"
102 " },\n";
103 sb << " % ClassSwitch: Trapezium\n"
104 " classswitch/.style={\n"
105 " trapezium,\n"
106 " draw=black,\n"
107 " trapezium left angle=70,\n"
108 " trapezium right angle=110,\n"
109 " minimum width=1.5cm,\n"
110 " minimum height=0.8cm,\n"
111 " fill=pink!20\n"
112 " },\n";
113 sb << " % Cache: Stacked rectangle\n"
114 " cache/.style={\n"
115 " rectangle,\n"
116 " draw=black,\n"
117 " minimum width=1.5cm,\n"
118 " minimum height=1.2cm,\n"
119 " fill=gray!20\n"
120 " },\n";
121 sb << " % Logger: Rectangle with lines\n"
122 " logger/.style={\n"
123 " rectangle,\n"
124 " draw=black,\n"
125 " minimum width=1.2cm,\n"
126 " minimum height=0.8cm,\n"
127 " fill=brown!10\n"
128 " },\n";
129 sb << " % Place (Petri net): Circle\n"
130 " place/.style={\n"
131 " circle,\n"
132 " draw=black,\n"
133 " minimum size=0.8cm,\n"
134 " fill=white\n"
135 " },\n";
136 sb << " % Transition (Petri net): Rectangle\n"
137 " transition/.style={\n"
138 " rectangle,\n"
139 " draw=black,\n"
140 " minimum width=0.2cm,\n"
141 " minimum height=1cm,\n"
142 " fill=black\n"
143 " },\n";
144 sb << " % Connection arrow\n"
145 " conn/.style={\n"
146 " ->,\n"
147 " >=Stealth,\n"
148 " thick\n"
149 " },\n";
150 sb << " % Probability label\n"
151 " problabel/.style={\n"
152 " font=\\footnotesize,\n"
153 " midway,\n"
154 " above,\n"
155 " sloped\n"
156 " },\n";
157 sb << " % Node name label\n"
158 " nodelabel/.style={\n"
159 " font=\\small\n"
160 " }\n";
161 sb << "}\n";
162 return sb.str();
163}
164
165namespace tikz_detail {
166
167/** `\node[style] (id) at (x,y) {body};` followed by the name label the options ask for. */
168inline std::string styled_node(const std::string& style, const std::string& id, double x, double y,
169 const std::string& body, const TikzNode& nd, const TikzOptions& opt) {
170 std::string s = "\\node[" + style + "] (" + id + ") at (" + java_fixed(x, 2) + "," +
171 java_fixed(y, 2) + ") {" + body + "};\n";
172 if (opt.show_node_names)
173 s += "\\node[nodelabel,above=2pt of " + id + "] {" + escape_latex(nd.name) + "};\n";
174 return s;
175}
176
177/** `String.valueOf(queue.getNumberOfServers())`, the JAR's `Integer.MAX_VALUE` pool being infinity. */
178inline std::string server_label(double c) {
179 if (std::isinf(c) || c >= 2147483647.0) return "$\\infty$";
180 std::ostringstream o;
181 o << static_cast<long long>(c);
182 return o.str();
183}
184
185} // namespace tikz_detail
186
187/** `TikZNodeRenderer.renderNode`. */
188inline std::string tikz_render_node(const TikzNode& nd, double x, double y, const TikzOptions& opt) {
189 using lang::NodeType;
191 const std::string id = tikz_detail::sanitize_id(nd.name);
192 std::string s;
193 switch (nd.type) {
194 case NodeType::Delay:
195 return styled_node("delay", id, x, y, "$\\infty$", nd, opt);
196 case NodeType::Queue:
197 s = styled_node("queue", id, x, y, "", nd, opt);
198 if (opt.show_scheduling && !nd.sched.empty())
199 s += "\\node[font=\\tiny,below=2pt of " + id + "] {" + nd.sched + "};\n";
200 if (opt.show_server_count)
201 s += "\\node[server,anchor=west] (" + id + "_server) at (" + id + ".east) {" +
203 return s;
204 case NodeType::Source:
205 s = styled_node("source", id, x, y, "", nd, opt);
206 s += "\\draw[conn] ([xshift=-0.6cm]" + id + ".west) -- (" + id + ".west);\n";
207 return s;
208 case NodeType::Sink:
209 s = styled_node("sink", id, x, y, "", nd, opt);
210 s += "\\draw[conn] (" + id + ".east) -- ([xshift=0.6cm]" + id + ".east);\n";
211 return s;
212 case NodeType::Fork:
213 return styled_node("fork", id, x, y, "", nd, opt);
214 case NodeType::Join:
215 return styled_node("joinnode", id, x, y, "", nd, opt);
216 case NodeType::Router:
217 return styled_node("router", id, x, y, "", nd, opt);
218 case NodeType::ClassSwitch:
219 return styled_node("classswitch", id, x, y, "", nd, opt);
220 case NodeType::Cache:
221 s = styled_node("cache", id, x, y, "", nd, opt);
222 s += "\\draw ([yshift=-0.3cm]" + id + ".north west) -- ([yshift=-0.3cm]" + id +
223 ".north east);\n";
224 s += "\\draw (" + id + ".west) -- (" + id + ".east);\n";
225 s += "\\draw ([yshift=0.3cm]" + id + ".south west) -- ([yshift=0.3cm]" + id +
226 ".south east);\n";
227 return s;
228 case NodeType::Logger:
229 return styled_node("logger", id, x, y, "", nd, opt);
230 case NodeType::Place:
231 return styled_node("place", id, x, y, "", nd, opt);
232 case NodeType::Transition:
233 return styled_node("transition", id, x, y, "", nd, opt);
234 default:
235 return styled_node("draw,circle,minimum size=0.8cm", id, x, y, "", nd, opt);
236 }
237}
238
239} // namespace io
240} // namespace line
241
242#endif // LINE_IO_TIKZ_TIKZ_NODE_RENDERER_H
std::string escape_latex(std::string t)
TikZNodeRenderer.escapeLatex, applied in the SAME sequence of whole-string replacements,...
Definition tikz_graph.h:161
std::string sanitize_id(const std::string &name)
name.replaceAll("[^a-zA-Z0-9]", "_"): one underscore per CODE POINT, so a UTF-8 sequence is one chara...
Definition tikz_graph.h:134
std::string server_label(double c)
String.valueOf(queue.getNumberOfServers()), the JAR's Integer.MAX_VALUE pool being infinity.
std::string java_fixed(double v, int prec)
Java's String.format("%." + prec + "f", v).
Definition tikz_graph.h:79
std::string styled_node(const std::string &style, const std::string &id, double x, double y, const std::string &body, const TikzNode &nd, const TikzOptions &opt)
\node[style] (id) at (x,y) {body}; followed by the name label the options ask for.
std::string tikz_preamble(const TikzOptions &opt)
TikZNodeRenderer.getPreamble, byte for byte.
std::string tikz_render_node(const TikzNode &nd, double x, double y, const TikzOptions &opt)
TikZNodeRenderer.renderNode.
NodeType
Node kinds, with the values of MATLAB NodeType.
Definition lang_types.h:326
Conservation laws of a layered queueing network, enumerated from its structure.
Definition aoi_dist2ph.h:52
One node as the TikZ exporter sees it.
Definition tikz_graph.h:46
std::string sched
Java SchedStrategy.name() of a Queue (FCFSPRIO is HOL, as in MATLAB), empty when none.
Definition tikz_graph.h:49
lang::NodeType type
Definition tikz_graph.h:48
double servers
a Queue's server count, infinite for an unbounded pool
Definition tikz_graph.h:50
std::string name
Definition tikz_graph.h:47
Layout and rendering options of the network TikZ exporter (TikZOptions).
The part of a network the TikZ exporter draws, and the text helpers the JAR's exporter uses to write ...
Port of jline.io.tikz.TikZOptions: the knobs of the network TikZ exporter.