+#include <cassert>
#include <string>
+#include <unordered_set>
#include "graphviz_edge.h"
#include "graphviz_node.h"
return m_svg_g_element.find_child(SVG::SVGElementType::Polygon, index);
}
+static const std::unordered_set<std::string_view>
+ supported_primitive_arrow_shapes = {
+ "inv", //
+ "normal", //
+};
+
+SVG::SVGRect GraphvizEdge::arrowhead_outline_bbox(
+ std::string_view dir, std::string_view primitive_arrow_shape) const {
+ assert((dir == "forward" || dir == "both") &&
+ "no arrowhead for this edge direction");
+
+ if (!supported_primitive_arrow_shapes.contains(primitive_arrow_shape)) {
+ throw std::runtime_error{
+ fmt::format("primitive arrow shape {} is not yet supported",
+ primitive_arrow_shape)};
+ }
+ auto edge_arrowhead = dir == "forward" ? arrow(0) : arrow(1);
+ const auto edge_arrowhead_bbox = edge_arrowhead.outline_bbox();
+
+ return edge_arrowhead_bbox;
+}
+
std::string_view GraphvizEdge::edgeop() const { return m_edgeop; }
std::string GraphvizEdge::fillcolor() const {
/// arrowhead is at index 1. If there's only one, it's at index 0. Throws an
/// exception if there's no arrow at the specified index.
SVG::SVGElement &arrow(std::size_t index = 0) const;
+ /// Return the outline bounding box of the edge arrowhead. The outline
+ /// bounding box is the bounding box with penwidth taken into account.
+ SVG::SVGRect
+ arrowhead_outline_bbox(std::string_view dir,
+ std::string_view primitive_arrow_shape) const;
/// Return the bounding box of the edge
SVG::SVGRect bbox() const;
/// Return the center of the edge's bounding box
const auto rankdir = graph_options.rankdir;
const auto node_shape = graph_options.node_shape;
const auto dir = graph_options.dir;
+ const auto primitive_arrowhead_shape =
+ graph_options.primitive_arrowhead_shape;
REQUIRE(svg_analyzer.graphs().size() == 1);
auto &recreated_graph = svg_analyzer.graphs().back();
// check overlap of edge stem and arrowhead
if (dir == "forward" || dir == "both") {
- auto edge_arrowhead = dir == "forward" ? edge.arrow(0) : edge.arrow(1);
- const auto edge_arrowhead_bbox = edge_arrowhead.outline_bbox();
+ const auto edge_arrowhead_bbox =
+ edge.arrowhead_outline_bbox(dir, primitive_arrowhead_shape);
const auto overlap_bbox = edge_stem_bbox.intersection(edge_arrowhead_bbox);
INFO("Edge stem and arrowhead overlap:");
INFO(fmt::format(" width: {:.3f}", overlap_bbox.width));