From: Magnus Jacobsson Date: Thu, 6 Oct 2022 10:36:48 +0000 (+0200) Subject: arrows: arrow_length_tee: take edge penwidth into account when calculating length X-Git-Tag: 7.0.1~3^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5ed480a52ddbf89ad5697376d93b95635eb38230;p=graphviz arrows: arrow_length_tee: take edge penwidth into account when calculating length The test_edge_node_overlap_tee_edge_arrow test case now succeeds, so the expectancy that it should fail is removed. Towards https://gitlab.com/graphviz/graphviz/-/issues/372. --- diff --git a/CHANGELOG.md b/CHANGELOG.md index dc55cfb99..8dc98dd73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Failure of arrowhead and arrowtail to respect penwidth #372 \ - Fixed also for the `diamond` [edge arrow shape](https://graphviz.org/doc/info/arrows.html#primitive-shapes). + Fixed also for the `diamond` and `tee` + [edge arrow shapes](https://graphviz.org/doc/info/arrows.html#primitive-shapes). - The CMake build system no longer uses the final install location as the staging area for example graphs and templates during `cpack`. This bug was introduced in Graphviz 4.0.0. #2232 diff --git a/lib/common/arrows.c b/lib/common/arrows.c index d6bf26a1e..7811d29f1 100644 --- a/lib/common/arrows.c +++ b/lib/common/arrows.c @@ -126,6 +126,7 @@ static pointf arrow_type_gap(GVJ_t * job, pointf p, pointf u, double arrowsize, static double arrow_length_generic(double lenfact, double arrowsize, double penwidth, int flag); static double arrow_length_normal(double lenfact, double arrowsize, double penwidth, int flag); +static double arrow_length_tee(double lenfact, double arrowsize, double penwidth, int flag); static double arrow_length_box(double lenfact, double arrowsize, double penwidth, int flag); static double arrow_length_diamond(double lenfact, double arrowsize, double penwidth, int flag); static double arrow_length_dot(double lenfact, double arrowsize, double penwidth, int flag); @@ -133,7 +134,7 @@ static double arrow_length_dot(double lenfact, double arrowsize, double penwidth static const arrowtype_t Arrowtypes[] = { {ARR_TYPE_NORM, 1.0, arrow_type_normal, arrow_length_normal}, {ARR_TYPE_CROW, 1.0, arrow_type_crow, arrow_length_generic}, - {ARR_TYPE_TEE, 0.5, arrow_type_tee, arrow_length_generic}, + {ARR_TYPE_TEE, 0.5, arrow_type_tee, arrow_length_tee}, {ARR_TYPE_BOX, 1.0, arrow_type_box, arrow_length_box}, {ARR_TYPE_DIAMOND, 1.2, arrow_type_diamond, arrow_length_diamond}, {ARR_TYPE_DOT, 0.8, arrow_type_dot, arrow_length_dot}, @@ -1054,6 +1055,33 @@ static double arrow_length_normal(double lenfact, double arrowsize, return full_length - overlap; } +static double arrow_length_tee(double lenfact, double arrowsize, + double penwidth, int flag) { + (void)flag; + + // The `tee` arrow shape normally begins and ends with a polyline which + // doesn't extend visually beyond its starting point, so we only have to + // take penwidth into account if the polygon part visually extends the + // polyline part at the start or end points. + + const double nominal_length = lenfact * arrowsize * ARROW_LENGTH; + double length = nominal_length; + + // see the 'arrow_type_tee' function for the magical constants used below + + const double polygon_extend_over_polyline_at_start = penwidth / 2 - (1 - 0.6) * nominal_length; + if (polygon_extend_over_polyline_at_start > 0) { + length += polygon_extend_over_polyline_at_start; + } + + const double polygon_extend_over_polyline_at_end = penwidth / 2 - 0.2 * nominal_length; + if (polygon_extend_over_polyline_at_start > 0) { + length += polygon_extend_over_polyline_at_end; + } + + return length; +} + static double arrow_length_box(double lenfact, double arrowsize, double penwidth, int flag) { (void)flag; diff --git a/tests/test_edge_node_overlap_tee_edge_arrow.cpp b/tests/test_edge_node_overlap_tee_edge_arrow.cpp index 383ca97c7..6bc6f074d 100644 --- a/tests/test_edge_node_overlap_tee_edge_arrow.cpp +++ b/tests/test_edge_node_overlap_tee_edge_arrow.cpp @@ -6,8 +6,8 @@ #include "test_utilities.h" TEST_CASE("Edge node overlap for 'tee' arrow", - "[!shouldfail] An edge connected to a node shall touch that node and " - "not overlap it too much") { + "An edge connected to a node shall touch that node and not overlap " + "it too much") { const std::string_view primitive_arrow_shape = "tee";