]> granicus.if.org Git - graphviz/commitdiff
tests: test_edge_node_overlap_utilities: support arrowhead/arrowtail
authorMagnus Jacobsson <Magnus.Jacobsson@berotec.se>
Mon, 5 Sep 2022 10:57:17 +0000 (12:57 +0200)
committerMagnus Jacobsson <Magnus.Jacobsson@berotec.se>
Thu, 22 Sep 2022 08:21:14 +0000 (10:21 +0200)
tests/svg_element.cpp
tests/test_edge_node_overlap_utilities.cpp
tests/test_edge_node_overlap_utilities.h

index 42c0a77f8dd7bca1bb47d764c94e03f75198daa4..1fe892799c1b9312239c5a8eb72e45c678f0cd14 100644 (file)
@@ -314,6 +314,7 @@ SVG::SVGRect SVG::SVGElement::outline_bbox(bool throw_if_bbox_not_defined) {
         }
         break;
       }
+      // FIXME: this throws for the `curve` and `icurve` edge arrows
       throw std::runtime_error(
           "paths other than straight vertical, straight horizontal or the "
           "cylinder special case are currently not supported");
index a2284ccd0105d16f2f596bb692b74951154053b4..e4349bb3705f2c3ead15587486d04fd560b72981 100644 (file)
@@ -5,6 +5,7 @@
 #include <catch2/catch.hpp>
 #include <cmath>
 #include <fmt/format.h>
+#include <unordered_map>
 
 #include "svg_analyzer.h"
 #include "test_edge_node_overlap_utilities.h"
@@ -277,7 +278,8 @@ static bool check_analyzed_svg(SVGAnalyzer &svg_analyzer,
     // check maximum overlap of edge stem and arrowhead
     if (check_options.check_max_edge_stem_arrow_overlap) {
       const auto max_edge_stem_arrowhead_overlap =
-          check_options.max_edge_stem_arrow_overlap;
+          check_options.max_edge_stem_arrow_overlap.at(
+              graph_options.primitive_arrowhead_shape);
       DO_CHECK(edge_stem_arrowhead_overlap <=
                max_edge_stem_arrowhead_overlap +
                    check_options.svg_rounding_error * 2);
@@ -307,7 +309,8 @@ static bool check_analyzed_svg(SVGAnalyzer &svg_analyzer,
     // check maximum overlap of edge stem and arrowtail
     if (check_options.check_max_edge_stem_arrow_overlap) {
       const auto max_edge_stem_arrowtail_overlap =
-          check_options.max_edge_stem_arrow_overlap;
+          check_options.max_edge_stem_arrow_overlap.at(
+              graph_options.primitive_arrowtail_shape);
       DO_CHECK(edge_stem_arrowtail_overlap <=
                max_edge_stem_arrowtail_overlap +
                    check_options.svg_rounding_error * 2);
@@ -393,15 +396,20 @@ static bool has_corner_in_rank_direction_unknown_during_layout(
 static std::string generate_dot(const graph_options &graph_options) {
   // use a semi-transparent color to easily see overlaps
   const auto color = "\"#00000060\"";
-  return fmt::format("digraph g1 {{"
-                     "  graph [rankdir={}]"
-                     "  node [penwidth={} shape={} color={} fontname=Courier]"
-                     "  edge [penwidth={} color={} dir={}]"
-                     "  a -> b"
-                     "}}",
-                     graph_options.rankdir, graph_options.node_penwidth,
-                     graph_options.node_shape, color,
-                     graph_options.edge_penwidth, color, graph_options.dir);
+  const auto arrowhead = fmt::format("{}{}", graph_options.arrowhead_modifier,
+                                     graph_options.primitive_arrowhead_shape);
+  const auto arrowtail = fmt::format("{}{}", graph_options.arrowtail_modifier,
+                                     graph_options.primitive_arrowtail_shape);
+  return fmt::format(
+      "digraph g1 {{"
+      "  graph [rankdir={}]"
+      "  node [penwidth={} shape={} color={} fontname=Courier]"
+      "  edge [penwidth={} color={} dir={} arrowhead={} arrowtail={}]"
+      "  a -> b"
+      "}}",
+      graph_options.rankdir, graph_options.node_penwidth,
+      graph_options.node_shape, color, graph_options.edge_penwidth, color,
+      graph_options.dir, arrowhead, arrowtail);
 }
 
 void test_edge_node_overlap(const graph_options &graph_options,
@@ -423,6 +431,44 @@ void test_edge_node_overlap(const graph_options &graph_options,
   const double graphviz_max_svg_rounding_error =
       std::pow(10, -graphviz_num_decimals_in_svg) / 2;
 
+  const std::unordered_map<std::string_view, double>
+      max_edge_stem_arrow_overlap = {
+          {"box",
+           graph_options.edge_penwidth / 2 + graphviz_bezier_clip_margin},
+          {"crow",
+           // FIXME: adjust this when `crow` is fixed for penwidth
+           graph_options.edge_penwidth / 2 + graphviz_bezier_clip_margin},
+          {"curve",
+           // FIXME: adjust this when `curve` is fixed for penwidth
+           graph_options.edge_penwidth / 2 + graphviz_bezier_clip_margin},
+          {"diamond",
+           // FIXME: adjust this when `diamond` is fixed for penwidth
+           graph_options.edge_penwidth / 2 + graphviz_bezier_clip_margin},
+          {"dot",
+           // FIXME: adjust this when `dot` is fixed for penwidth
+           graph_options.edge_penwidth / 2 + graphviz_bezier_clip_margin},
+          {"icurve",
+           // FIXME: adjust this when `icurve` is fixed for penwidth
+           graph_options.edge_penwidth / 2 + graphviz_bezier_clip_margin},
+          {"inv",
+           [&]() { // FIXME: calculate this accurately for normal/inv arrow
+             const auto tip_scale = 2 * 1.5135442928; // empirical value
+             return graph_options.edge_penwidth / 2 * tip_scale +
+                    graphviz_bezier_clip_margin;
+           }()},
+          {"none",
+           // FIXME: adjust this when `none` is fixed for penwidth
+           graph_options.edge_penwidth / 2 + graphviz_bezier_clip_margin},
+          {"normal",
+           graph_options.edge_penwidth / 2 + graphviz_bezier_clip_margin},
+          {"tee",
+           // FIXME: adjust this when `tee` is fixed for penwidth
+           graph_options.edge_penwidth / 2 + graphviz_bezier_clip_margin},
+          {"vee",
+           // FIXME: adjust this when `vee` is fixed for penwidth
+           graph_options.edge_penwidth / 2 + graphviz_bezier_clip_margin},
+      };
+
   const auto extra_max_node_edge_overlap =
       has_corner_in_rank_direction_unknown_during_layout(
           graph_options.node_shape, graph_options.rankdir)
@@ -445,8 +491,7 @@ void test_edge_node_overlap(const graph_options &graph_options,
       .max_node_edge_overlap =
           graphviz_bezier_clip_margin + extra_max_node_edge_overlap,
       .min_node_edge_overlap = 0,
-      .max_edge_stem_arrow_overlap =
-          graph_options.edge_penwidth / 2 + graphviz_bezier_clip_margin,
+      .max_edge_stem_arrow_overlap = max_edge_stem_arrow_overlap,
       .min_edge_stem_arrow_overlap = 0,
       .svg_rounding_error = graphviz_max_svg_rounding_error,
   };
index 03b7690648caf54ec1b77511d5f457279f0d91fe..2f7d85309c6806c4f34cabe9647c693448f33425 100644 (file)
@@ -1,5 +1,6 @@
 #include <string>
 #include <string_view>
+#include <unordered_map>
 
 #include "svg_analyzer.h"
 
@@ -30,8 +31,9 @@ struct check_options {
   double max_node_edge_overlap;
   /// minimum required overlap between edge and node
   double min_node_edge_overlap;
-  /// maximum allowed overlap between edge stem and arrow
-  double max_edge_stem_arrow_overlap;
+  /// map between primitive arrow shape and maximum allowed overlap between edge
+  /// stem and arrow
+  std::unordered_map<std::string_view, double> max_edge_stem_arrow_overlap;
   /// minimum required overlap between edge stem and arrow
   double min_edge_stem_arrow_overlap;
   /// rounding error caused by limited precision in SVG attribute values
@@ -44,6 +46,10 @@ struct graph_options {
   double node_penwidth = 1;
   std::string_view dir = "forward";
   double edge_penwidth = 1;
+  std::string_view primitive_arrowhead_shape = "normal";
+  std::string_view primitive_arrowtail_shape = "normal";
+  std::string_view arrowhead_modifier = "";
+  std::string_view arrowtail_modifier = "";
 };
 
 struct write_options {