From e63649e5e8f0702ed192b863189df467158a216a Mon Sep 17 00:00:00 2001 From: Magnus Jacobsson Date: Mon, 5 Sep 2022 12:57:17 +0200 Subject: [PATCH] tests: test_edge_node_overlap_utilities: support arrowhead/arrowtail --- tests/svg_element.cpp | 1 + tests/test_edge_node_overlap_utilities.cpp | 71 ++++++++++++++++++---- tests/test_edge_node_overlap_utilities.h | 10 ++- 3 files changed, 67 insertions(+), 15 deletions(-) diff --git a/tests/svg_element.cpp b/tests/svg_element.cpp index 42c0a77f8..1fe892799 100644 --- a/tests/svg_element.cpp +++ b/tests/svg_element.cpp @@ -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"); diff --git a/tests/test_edge_node_overlap_utilities.cpp b/tests/test_edge_node_overlap_utilities.cpp index a2284ccd0..e4349bb37 100644 --- a/tests/test_edge_node_overlap_utilities.cpp +++ b/tests/test_edge_node_overlap_utilities.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #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 + 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, }; diff --git a/tests/test_edge_node_overlap_utilities.h b/tests/test_edge_node_overlap_utilities.h index 03b769064..2f7d85309 100644 --- a/tests/test_edge_node_overlap_utilities.h +++ b/tests/test_edge_node_overlap_utilities.h @@ -1,5 +1,6 @@ #include #include +#include #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 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 { -- 2.40.0