allow for boxes!

release/4.3a0
Frank Dellaert 2022-01-27 12:53:27 -05:00
parent 87eeb0d27e
commit c0f6cd247b
7 changed files with 22 additions and 11 deletions

View File

@ -44,7 +44,7 @@ void BayesNet<CONDITIONAL>::dot(std::ostream& os,
// Create nodes for each variable in the graph // Create nodes for each variable in the graph
for (Key key : this->keys()) { for (Key key : this->keys()) {
auto position = writer.variablePos(key); auto position = writer.variablePos(key);
writer.DrawVariable(key, keyFormatter, position, &os); writer.drawVariable(key, keyFormatter, position, &os);
} }
os << "\n"; os << "\n";

View File

@ -39,15 +39,18 @@ void DotWriter::digraphPreamble(ostream* os) const {
<< "\";\n\n"; << "\";\n\n";
} }
void DotWriter::DrawVariable(Key key, const KeyFormatter& keyFormatter, void DotWriter::drawVariable(Key key, const KeyFormatter& keyFormatter,
const boost::optional<Vector2>& position, const boost::optional<Vector2>& position,
ostream* os) { ostream* os) const {
// Label the node with the label from the KeyFormatter // Label the node with the label from the KeyFormatter
*os << " var" << keyFormatter(key) << "[label=\"" << keyFormatter(key) *os << " var" << keyFormatter(key) << "[label=\"" << keyFormatter(key)
<< "\""; << "\"";
if (position) { if (position) {
*os << ", pos=\"" << position->x() << "," << position->y() << "!\""; *os << ", pos=\"" << position->x() << "," << position->y() << "!\"";
} }
if (boxes.count(key)) {
*os << ", shape=box";
}
*os << "];\n"; *os << "];\n";
} }

View File

@ -24,6 +24,7 @@
#include <iosfwd> #include <iosfwd>
#include <map> #include <map>
#include <set>
namespace gtsam { namespace gtsam {
@ -43,7 +44,7 @@ struct GTSAM_EXPORT DotWriter {
* Variable positions can be optionally specified and will be included in the * Variable positions can be optionally specified and will be included in the
* dor file with a "!' sign, so "neato" can use it to render them. * dor file with a "!' sign, so "neato" can use it to render them.
*/ */
std::map<gtsam::Key, Vector2> variablePositions; std::map<Key, Vector2> variablePositions;
/** /**
* The position hints allow one to use symbol character and index to specify * The position hints allow one to use symbol character and index to specify
@ -52,6 +53,9 @@ struct GTSAM_EXPORT DotWriter {
*/ */
std::map<char, double> positionHints; std::map<char, double> positionHints;
/** A set of keys that will be displayed as a box */
std::set<Key> boxes;
explicit DotWriter(double figureWidthInches = 5, explicit DotWriter(double figureWidthInches = 5,
double figureHeightInches = 5, double figureHeightInches = 5,
bool plotFactorPoints = true, bool plotFactorPoints = true,
@ -69,9 +73,9 @@ struct GTSAM_EXPORT DotWriter {
void digraphPreamble(std::ostream* os) const; void digraphPreamble(std::ostream* os) const;
/// Create a variable dot fragment. /// Create a variable dot fragment.
static void DrawVariable(Key key, const KeyFormatter& keyFormatter, void drawVariable(Key key, const KeyFormatter& keyFormatter,
const boost::optional<Vector2>& position, const boost::optional<Vector2>& position,
std::ostream* os); std::ostream* os) const;
/// Create factor dot. /// Create factor dot.
static void DrawFactor(size_t i, const boost::optional<Vector2>& position, static void DrawFactor(size_t i, const boost::optional<Vector2>& position,

View File

@ -135,7 +135,7 @@ void FactorGraph<FACTOR>::dot(std::ostream& os,
// Create nodes for each variable in the graph // Create nodes for each variable in the graph
for (Key key : keys()) { for (Key key : keys()) {
writer.DrawVariable(key, keyFormatter, boost::none, &os); writer.drawVariable(key, keyFormatter, boost::none, &os);
} }
os << "\n"; os << "\n";

View File

@ -130,6 +130,7 @@ class DotWriter {
std::map<gtsam::Key, gtsam::Vector2> variablePositions; std::map<gtsam::Key, gtsam::Vector2> variablePositions;
std::map<char, double> positionHints; std::map<char, double> positionHints;
std::set<Key> boxes;
}; };
#include <gtsam/inference/VariableIndex.h> #include <gtsam/inference/VariableIndex.h>

View File

@ -111,7 +111,7 @@ void NonlinearFactorGraph::dot(std::ostream& os, const Values& values,
// Create nodes for each variable in the graph // Create nodes for each variable in the graph
for (Key key : keys) { for (Key key : keys) {
auto position = writer.variablePos(values, min, key); auto position = writer.variablePos(values, min, key);
writer.DrawVariable(key, keyFormatter, position, &os); writer.drawVariable(key, keyFormatter, position, &os);
} }
os << "\n"; os << "\n";

View File

@ -91,18 +91,21 @@ TEST(SymbolicBayesNet, Dot) {
DotWriter writer; DotWriter writer;
writer.positionHints.emplace('a', 2); writer.positionHints.emplace('a', 2);
writer.positionHints.emplace('x', 1); writer.positionHints.emplace('x', 1);
writer.boxes.emplace(A(1));
writer.boxes.emplace(A(2));
auto position = writer.variablePos(A(1)); auto position = writer.variablePos(A(1));
CHECK(position); CHECK(position);
EXPECT(assert_equal(Vector2(1, 2), *position, 1e-5)); EXPECT(assert_equal(Vector2(1, 2), *position, 1e-5));
string actual = bn.dot(DefaultKeyFormatter, writer); string actual = bn.dot(DefaultKeyFormatter, writer);
bn.saveGraph("bn.dot", DefaultKeyFormatter, writer);
EXPECT(actual == EXPECT(actual ==
"digraph {\n" "digraph {\n"
" size=\"5,5\";\n" " size=\"5,5\";\n"
"\n" "\n"
" vara1[label=\"a1\", pos=\"1,2!\"];\n" " vara1[label=\"a1\", pos=\"1,2!\", shape=box];\n"
" vara2[label=\"a2\", pos=\"2,2!\"];\n" " vara2[label=\"a2\", pos=\"2,2!\", shape=box];\n"
" varx1[label=\"x1\", pos=\"1,1!\"];\n" " varx1[label=\"x1\", pos=\"1,1!\"];\n"
" varx2[label=\"x2\", pos=\"2,1!\"];\n" " varx2[label=\"x2\", pos=\"2,1!\"];\n"
" varx3[label=\"x3\", pos=\"3,1!\"];\n" " varx3[label=\"x3\", pos=\"3,1!\"];\n"