64 nd.
name.find(
"_to_") != std::string::npos;
75 return "\\draw[conn] (" +
id +
"_server.north) -- ++(0,0.6) -- ++(-1.8,0) -- ++(0,-0.6) -- (" +
77 return "\\draw[conn] (" +
id +
".north) -- ++(0,0.5) -- ++(-0.8,0) -- ++(0,-0.5) -- (" +
id +
83 return ::stat(p.c_str(), &st) == 0 && S_ISREG(st.st_mode);
86inline bool ends_with(
const std::string& s,
const std::string& suf) {
87 return s.size() >= suf.size() && s.compare(s.size() - suf.size(), suf.size(), suf) == 0;
90inline void write_text(
const std::string& path,
const std::string& text) {
91 std::ofstream out(path.c_str(), std::ios::binary);
92 if (!out)
throw InputError(
"tikz: cannot write '" + path +
"'");
94 if (!out)
throw InputError(
"tikz: failed writing '" + path +
"'");
97inline void copy_file(
const std::string& from,
const std::string& to) {
98 std::ifstream in(from.c_str(), std::ios::binary);
99 if (!in)
throw InputError(
"tikz: cannot read '" + from +
"'");
100 std::ofstream out(to.c_str(), std::ios::binary);
101 if (!out)
throw InputError(
"tikz: cannot write '" + to +
"'");
103 if (!out)
throw InputError(
"tikz: failed writing '" + to +
"'");
114 if (
util::capture({
"pdflatex",
"--version"}, 60,
true).exitCode != 0)
115 throw Error(
"pdflatex is not available. Please install TeX Live or MiKTeX.");
116 const std::string texfile = dir.
file(
"network.tex");
117 const std::string pdffile = dir.
file(
"network.pdf");
120 {
"pdflatex",
"-interaction=nonstopmode",
"-output-directory=" + dir.
path(), texfile},
123 throw Error(
"pdflatex did not finish within " + std::to_string(
kToolTimeout) +
" s");
125 throw Error(
"pdflatex compilation failed:\n" + r.
out);
134 const std::size_t n = g.
nodes.size();
135 std::ostringstream sb;
137 sb <<
"\\begin{document}\n\\begin{tikzpicture}\n\n";
139 std::vector<std::size_t> visible;
140 std::vector<bool> is_visible(n,
false);
141 for (std::size_t v = 0; v < n; ++v)
143 visible.push_back(v);
144 is_visible[v] =
true;
151 sb <<
"% Connections\n";
153 for (std::size_t from : visible) {
155 std::vector<bool> seen(n,
false), target(n,
false);
156 std::vector<std::size_t> queue;
157 for (std::size_t j = 0; j < n; ++j)
158 if (g.
conn[from][j] && !seen[j]) {
162 for (std::size_t q = 0; q < queue.size(); ++q) {
163 const std::size_t cur = queue[q];
164 if (is_visible[cur]) {
168 for (std::size_t j = 0; j < n; ++j)
169 if (g.
conn[cur][j] && !seen[j]) {
175 for (std::size_t to = 0; to < n; ++to) {
176 if (!target[to])
continue;
184 std::numeric_limits<double>::quiet_NaN(),
opt);
187 sb <<
"\n\\end{tikzpicture}\n\\end{document}\n";
205 return util::capture({
"pdflatex",
"--version"}, 60,
true).exitCode == 0;
224 std::string stem = path;
226 stem.resize(stem.size() - 4);
232 return stem +
".pdf";
247 util::capture({
"pdftoppm",
"-png",
"-r", std::to_string(dpi),
"-singlefile", pdf,
248 png.substr(0, png.size() - 4)},
256namespace tikz_detail {
260 const char* p = std::getenv(
"PATH");
261 if (p ==
nullptr)
return std::string();
262 std::stringstream ss(p);
264 while (std::getline(ss, dir,
':')) {
265 const std::string f = (dir.empty() ? std::string(
".") : dir) +
"/" + cmd;
266 if (
file_exists(f) && ::access(f.c_str(), X_OK) == 0)
return f;
268 return std::string();
273 const pid_t pid = ::fork();
274 if (pid < 0)
return false;
277 if (::fork() != 0) ::_exit(0);
278 const int devnull = ::open(
"/dev/null", O_RDWR);
280 ::dup2(devnull, STDIN_FILENO);
281 ::dup2(devnull, STDOUT_FILENO);
282 ::dup2(devnull, STDERR_FILENO);
283 if (devnull > STDERR_FILENO) ::close(devnull);
285 util::detail::exec_never_returns(argv);
288 ::waitpid(pid, &status, 0);
289 return WIFEXITED(status) && WEXITSTATUS(status) == 0;
294 static const char*
const viewers[] = {
"evince",
"okular",
"mupdf",
"zathura",
"qpdfview",
"acroread"};
295 for (
const char* v : viewers)
298 const char* desktop =
"open";
300 const char* desktop =
"xdg-open";
307namespace tikz_detail {
340 }
catch (
const Error& e) {
341 std::cerr <<
"Failed to generate visualization: " << e.what() <<
"\n";
345 res.
path =
"network-diagram.tex";
347 std::cout <<
"TikZ code saved to: " << res.
path <<
"\nCompile manually with: pdflatex " << res.
path
356 std::cout <<
"Could not open PDF viewer. File saved at: " << res.
path <<
"\n";
Base error for the multiprecision C++ port.
Error(const std::string &what)
std::vector< TikzPoint > compute_waypoints(std::size_t from, std::size_t to)
computeWaypoints: empty when the straight segment is clear, and for a self-loop.
A network plus its refreshed NetworkStruct.
A queueing network under construction.
const NetworkStruct< T > & get_struct()
The refreshed struct, MATLAB's model.getStruct().
NetworkStruct< T > & raw_struct()
The struct WITHOUT refreshing it, for a caller that is still building.
std::string file(const std::string &name) const
A file inside it.
void keep()
Leave the directory in place, for a caller that wants to inspect it.
const std::string & path() const
The directory itself, with no trailing separator.
The exception types the port throws.
std::string compile_pdf(const std::string &tex, const util::TempDir &dir)
exportToPDF: compile tex in a fresh directory and return the PDF path.
void write_text(const std::string &path, const std::string &text)
const std::string & model_name(const TikzGraph &g)
bool spawn_detached(const std::vector< std::string > &argv)
Start argv detached (own session, std streams on /dev/null, double fork so no zombie); false if it ca...
bool file_exists(const std::string &p)
bool display_pdf(const std::string &pdf)
TikZViewer.displayPDF: a standalone viewer first, then the desktop default; false when neither is fou...
std::string output_anchor(const TikzNode &nd, const TikzOptions &opt)
getOutputAnchor: a Queue's arrows leave its server circle when one is drawn; every other node,...
std::string self_loop(const std::string &id, const TikzNode &nd, const TikzOptions &opt)
renderSelfLoop: the wide loop from the server circle of a Queue that draws one, the plain-node loop o...
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...
std::string find_on_path(const std::string &cmd)
The first executable named cmd on PATH, empty when there is none (TikZViewer.isCommandAvailable).
void copy_file(const std::string &from, const std::string &to)
constexpr int kToolTimeout
Seconds a pdflatex or pdftoppm run may take before it is killed; a TikZ picture needs a few.
bool ends_with(const std::string &s, const std::string &suf)
bool is_auto_generated(const TikzNode &nd)
isAutoGeneratedNode: a ClassSwitch named CS_..._to_..., the name link gives the switch it inserts.
std::string tikz_preamble(const TikzOptions &opt)
TikZNodeRenderer.getPreamble, byte for byte.
bool tikz_pdflatex_available()
Can pdflatex --version run?
TikzLayout tikz_layout(const TikzGraph &g, const TikzOptions &opt)
TikZLayoutEngine.computeLayout.
std::string tikz_render_node(const TikzNode &nd, double x, double y, const TikzOptions &opt)
TikZNodeRenderer.renderNode.
std::string to_tikz(const TikzGraph &g, const TikzOptions &opt=TikzOptions())
TikZExporter.generateTikZ over an extracted graph.
TikzViewResult tikz_view(M &model, const TikzOptions &opt=TikzOptions(), bool open_viewer=true)
MNetwork.tikzView (TikZExporter.display).
std::string export_tikz(M &model, const std::string &path, const TikzOptions &opt=TikzOptions())
Network.exportTikZ: write <stem>.tex and compile it to <stem>.pdf, where the stem is path less a ....
void export_tikz_to_file(M &model, const std::string &tex_path, const TikzOptions &opt=TikzOptions())
Network.exportTikZToFile: the document, written to tex_path as given.
TikzGraph tikz_graph(const qn::NetworkStruct< T > &sn)
The drawable graph of a network struct.
std::string tikz_export_png(M &model, const std::string &path, int dpi=150, const TikzOptions &opt=TikzOptions())
Network.tikzExportPNG(path, dpi): compile the document and rasterise it with pdftoppm -png -r dpi -si...
std::string tikz_render_routed_edge(const std::string &from_id, const std::string &to_id, const std::string &from_anchor, const std::string &to_anchor, const std::vector< TikzPoint > &wp, double prob, const TikzOptions &opt)
TikZEdgeRouter.renderRoutedEdge.
ProcResult capture(const std::vector< std::string > &argv, int timeoutSeconds, bool mergeStderr=false)
Runs a command, capturing stdout and discarding stderr.
Conservation laws of a layered queueing network, enumerated from its structure.
The Network constructor API: Queue, Delay, Source, Sink, Router, ClassSwitch, Cache,...
A queueing network and its refreshed NetworkStruct.
Nodes in model order plus sn.connmatrix over them.
std::vector< std::vector< bool > > conn
conn[i][j]: node i is linked to node j, 0-based
std::vector< TikzNode > nodes
Node positions in cm, indexed like TikzGraph::nodes, and the layers that produced them.
One node as the TikZ exporter sees it.
Layout and rendering options of the network TikZ exporter (TikZOptions).
bool compiled
path is a PDF
bool opened
a viewer was started on it
std::string path
the compiled PDF, or the .tex saved when it could not be compiled
Outcome of a captured command.
int exitCode
Exit status, or -1 when the command could not run.
bool timedOut
True when the deadline expired and the child was killed.
std::string out
Everything the command wrote to stdout.
Running an external command and capturing its output, with a deadline.
A scratch directory for the subprocess wrappers, the port's lineTempName.
Port of jline.io.tikz.TikZEdgeRouter: orthogonal waypoints that keep an edge off the nodes it would o...
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.TikZLayoutEngine: a layered (Sugiyama-style) layout.
Port of jline.io.tikz.TikZNodeRenderer: the preamble with the node styles, and one TikZ node per netw...
Port of jline.io.tikz.TikZOptions: the knobs of the network TikZ exporter.