-
Notifications
You must be signed in to change notification settings - Fork 0
/
TreeVisualization.h
135 lines (117 loc) · 3.86 KB
/
TreeVisualization.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#pragma once
// impelement
#include <iostream>
#include <fstream>
#include <cstdlib> // For system()
#include <string>
#include "TreeNode.h"
#include "Tree.h"
#include "Settings.h"
class TreeVisualization
{
private:
void static generateDotHelper(TreeNode *node, std::ofstream &dotFile, int &nullCount)
{
if (!node)
return;
// If the node has a left child, create an edge
if (node->left)
{
dotFile << " \"" << node->key << "\" -> \"" << node->left->key << "\";\n";
generateDotHelper(node->left, dotFile, nullCount);
}
else
{
// Represent null node for left child
dotFile << " null" << nullCount << " [shape=point];\n";
dotFile << " \"" << node->key << "\" -> null" << nullCount << ";\n";
nullCount++;
}
// If the node has a right child, create an edge
if (node->right)
{
dotFile << " \"" << node->key << "\" -> \"" << node->right->key << "\";\n";
generateDotHelper(node->right, dotFile, nullCount);
}
else
{
// Represent null node for right child
dotFile << " null" << nullCount << " [shape=point];\n";
dotFile << " \"" << node->key << "\" -> null" << nullCount << ";\n";
nullCount++;
}
}
void static generateDotFile(const std::string &filename, TreeNode *root)
{
std::ofstream dotFile(filename); // Open file for writing
if (!dotFile.is_open())
{
std::cerr << "Failed to open file: " << filename << std::endl;
return;
}
dotFile << "digraph OBST {\n"; // Start of DOT syntax
// Label for the graph
dotFile << " label=\"" << Settings::getGraphLabel() << "\";\n";
dotFile << " labelloc=\"" << "t" << "\";\n";
dotFile << " fontsize=" << Settings::getGraphFontSize() << ";\n";
// Node properties
dotFile << "node [";
dotFile << "shape=" << Settings::getNodeShape() << ", ";
dotFile << "style=" << Settings::getNodeStyle() << ", ";
dotFile << "color=" << Settings::getNodeColor() << ", ";
dotFile << "fontcolor=" << Settings::getNodeFontColor() << ", ";
dotFile << "fontsize=" << Settings::getNodeFontSize() << ";\n";
dotFile << "];\n";
// Edge properties
std::string edgeColor = Settings::getEdgeColor();
dotFile << "edge [color=" << edgeColor << "];\n";
int nullCount = 0;
if (root)
{
generateDotHelper(root, dotFile, nullCount); // Recursive helper to add nodes/edges
}
dotFile << "}\n"; // Close the DOT graph definition
dotFile.close();
std::cout << "DOT file generated successfully: " << filename << std::endl;
}
void static renderDotFile(const std::string &dotFile, const std::string &outputImage)
{
// Construct the command to execute Graphviz
std::string command = "dot -Tpng " + dotFile + " -o " + outputImage;
int result = system(command.c_str());
if (result == 0)
{
std::cout << "Graph rendered to " << outputImage << std::endl;
}
else
{
std::cerr << "Failed to render graph. Ensure Graphviz is installed and accessible.\n";
}
}
void static openFileWithSystem(const std::string &filename)
{
// Construct the command to open the file with the default application
std::string command = "open " + filename;
// Execute the command
int result = system(command.c_str());
// Check for errors
if (result != 0)
{
std::cerr << "Failed to open the file: " << filename << std::endl;
}
else
{
std::cout << "File opened successfully: " << filename << std::endl;
}
}
public:
void static visualizeTree(const Tree &treeToVisualize, const std::string &dotFile = "tree.dot", const std::string &outputImage = "tree.png", bool openAfterRendering = false)
{
generateDotFile(dotFile, treeToVisualize.getRoot());
renderDotFile(dotFile, outputImage);
if (openAfterRendering)
{
openFileWithSystem(outputImage);
}
}
};