From adb17ecd2dbabf6724a50b2dd0aca2b5f6bf53bc Mon Sep 17 00:00:00 2001 From: Bela Schaum Date: Wed, 11 Dec 2024 13:48:45 +0100 Subject: [PATCH 1/5] refactor union_foreach --- CHANGELOG.md | 3 +- src/base/alg/merge.h | 288 ++++++++++++++++++++++++++++++++++ src/base/alg/union_foreach.h | 213 ------------------------- src/base/math/segmentedfunc.h | 43 ++--- src/chart/generator/axis.cpp | 256 ++++++++++++------------------ src/dataframe/old/types.h | 9 +- 6 files changed, 405 insertions(+), 407 deletions(-) create mode 100644 src/base/alg/merge.h delete mode 100644 src/base/alg/union_foreach.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 040b60e89..eb8f5f732 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ - Fix invalid read/write when animation is contiguous (onFinish callback calls setKeyframe). - Waterfall chart preset not aligned. - Split chart count negative values too. -- Split chart when same dimension on main and sub axis. +- Split chart handled when same dimension on main and sub axis. ### Changed @@ -17,7 +17,6 @@ - axis line multiplication. - axis labels multiplication. - axis range interpretation differently for all split part. - - negative values are handled correctly. - align center / stretch fix. ### Added diff --git a/src/base/alg/merge.h b/src/base/alg/merge.h new file mode 100644 index 000000000..dc12680dc --- /dev/null +++ b/src/base/alg/merge.h @@ -0,0 +1,288 @@ +#ifndef ALG_MERGE_H +#define ALG_MERGE_H + +#include +#include +#include + +namespace Alg +{ + +// closest to std::ranges::merge, but: +// - added new projection parameter to projection both ranges +// - comparison is a three-way comparison which requires weak_order +// on projected values +// - added new transformer_1 and transformer_2 parameters to transform +// the values at left and right side if no merging happens +// - added need_merge parameter to decide if merging is necessary +// of 2 equivalent values or just transforming all values +// - added merger parameter to merge the values if merging happens +// - output argument can be range which used as inserter_iterator +// - arguments are passed as struct to avoid argument swapping +// and used as named arguments + +namespace Merge +{ +struct get_first +{ + template + constexpr auto operator()(T &&t, const Args &...) const noexcept + { + return std::forward(t); + } +}; + +struct always +{ + template + constexpr auto operator()(const Ts &...) const noexcept + { + return res; + } + bool res{true}; +}; + +template +concept comparison_category = + !std::is_void_v>; + +template +concept compares_as = + comparison_category + && std::same_as, Cat>; + +template +concept three_way_order = + std::regular_invocable + && compares_as, Cat>; + +template +concept indirect_three_way_order = + std::indirectly_readable && std::indirectly_readable + && std::copy_constructible + && three_way_order &, + std::iter_value_t &, + Cat> + && three_way_order &, + std::iter_reference_t, + Cat> + && three_way_order, + std::iter_value_t &, + Cat> + && three_way_order, + std::iter_reference_t, + Cat> + && three_way_order, + std::iter_common_reference_t, + Cat>; + +template +concept common_references = + (std::common_reference_with, Ts> + && ...); + +template +concept indirectly_binary_invocable = + std::indirectly_readable && std::indirectly_readable + && std::copy_constructible + && std::invocable &, + std::iter_value_t &> + && std::invocable &, + std::iter_reference_t> + && std::invocable, + std::iter_value_t &> + && std::invocable, + std::iter_reference_t> + && std::invocable, + std::iter_common_reference_t> + && common_references &, + std::iter_value_t &>, + std::invoke_result_t &, + std::iter_reference_t>, + std::invoke_result_t, + std::iter_value_t &>, + std::invoke_result_t, + std::iter_reference_t>>; + +template +concept indirectly_unary_invocable_all = + (std::indirectly_unary_invocable && ...); + +template > +concept insertable_range_or_iterator = + std::weakly_incrementable> + || (std::ranges::range + && std::weakly_incrementable> + && requires(U &cont, + std::ranges::iterator_t i, + const std::ranges::range_value_t &v) { + std::inserter(cont, std::ranges::end(cont)); + i = cont.insert(i, v); + ++i; + }); + +template +struct borrowed_inserter_or_self : + std::conditional, + std::insert_iterator>, + std::ranges::dangling> +{}; + +template + requires(std::weakly_incrementable>) +struct borrowed_inserter_or_self : + std::type_identity> +{}; + +template +using borrowed_inserter_or_self_t = + typename borrowed_inserter_or_self::type; + +template +struct args +{ + [[no_unique_address]] Proj1 projection_1{}; + [[no_unique_address]] Proj2 projection_2{}; + [[no_unique_address]] Proj projection{}; + [[no_unique_address]] Comp comparator{}; + [[no_unique_address]] Transform1 transformer_1{}; + [[no_unique_address]] Transform2 transformer_2{}; + [[no_unique_address]] NeedMerge need_merge{}; + [[no_unique_address]] Merge merger{}; +}; + +template End1, + std::input_iterator It2, + std::sentinel_for End2, + std::weakly_incrementable Out, + std::indirectly_unary_invocable Proj1, + std::indirectly_unary_invocable Proj2, + indirectly_unary_invocable_all, + std::projected> Proj, + indirect_three_way_order< + std::projected, Proj>, + std::projected, Proj>> Comp, + std::indirectly_unary_invocable Transform1, + std::indirectly_unary_invocable Transform2, + std::indirect_binary_predicate NeedMerge, + indirectly_binary_invocable Merge> +constexpr std::ranges::in_in_out_result merge( + It1 first1, + End1 last1, + It2 first2, + End2 last2, + Out result, + args &&args = {}) +{ + while (first1 != last1 && first2 != last2) + if (auto cmp = std::invoke(args.comparator, + std::invoke(args.projection, + std::invoke(args.projection_1, *first1)), + std::invoke(args.projection, + std::invoke(args.projection_2, *first2))); + is_eq(cmp) + && std::invoke(args.need_merge, *first1, *first2)) { + *result = std::invoke(args.merger, *first1, *first2); + ++first1; + ++first2; + ++result; + } + else { + if (is_lteq(cmp)) { + *result = std::invoke(args.transformer_1, *first1); + ++first1; + ++result; + } + if (is_gteq(cmp)) { + *result = std::invoke(args.transformer_2, *first2); + ++first2; + ++result; + } + } + auto copy1 = std::ranges::transform(std::move(first1), + std::move(last1), + std::move(result), + args.transformer_1); + auto copy2 = std::ranges::transform(std::move(first2), + std::move(last2), + std::move(copy1.out), + args.transformer_2); + return {std::move(copy1.in), + std::move(copy2.in), + std::move(copy2.out)}; +} + +template +constexpr std::ranges::in_in_out_result< + std::ranges::borrowed_iterator_t, + std::ranges::borrowed_iterator_t, + borrowed_inserter_or_self_t> +merge(R1 &&range1, + R2 &&range2, + Out &&result, + args &&args = {}) +{ + if constexpr (std::weakly_incrementable< + std::remove_cvref_t>) { + return ::Alg::Merge::merge(std::ranges::begin(range1), + std::ranges::end(range1), + std::ranges::begin(range2), + std::ranges::end(range2), + result, + std::move(args)); + } + else { + return ::Alg::Merge::merge(std::ranges::begin(range1), + std::ranges::end(range1), + std::ranges::begin(range2), + std::ranges::end(range2), + std::inserter(result, std::ranges::end(result)), + std::move(args)); + } +} +} + +using Merge::merge; +template using merge_args = Merge::args; + +} + +#endif diff --git a/src/base/alg/union_foreach.h b/src/base/alg/union_foreach.h deleted file mode 100644 index 7d98574d5..000000000 --- a/src/base/alg/union_foreach.h +++ /dev/null @@ -1,213 +0,0 @@ -#ifndef ALG_UNION_FOREACH_H -#define ALG_UNION_FOREACH_H - -#include -#include -#include - -namespace Alg -{ - -namespace Impl -{ -enum class union_call_t : std::uint8_t { - both, - only_left, - only_right -}; - -struct single_t -{ -} constexpr static single{}; -struct multi_t -{ -} constexpr static multi{}; - -template -concept Property = - std::same_as || std::same_as; - -template ())), - class Ptr2 = decltype(std::to_address(std::declval()))> -concept address_binary_invocable = - std::copy_constructible - && (std::invocable - || std::invocable); - -template -concept insert_value_returns_iterator = requires { - { - std::declval().insert( - std::declval &>()) - } -> std::same_as>; -}; - -template -concept insert_value_returns_pair = requires { - { - std::declval().insert( - std::declval &>()) - } -> std::same_as, bool>>; -}; - -template > -using default_property_t = typename std::conditional_t< - insert_value_returns_iterator, - std::type_identity, - std::enable_if, single_t>>::type; - -template -constexpr void -invoke(Fun &&f, Arg1 &&arg1, Arg2 &&arg2, union_call_t val) -{ - if constexpr (std::invocable) - std::invoke(std::forward(f), - std::forward(arg1), - std::forward(arg2), - val); - else - std::invoke(std::forward(f), - std::forward(arg1), - std::forward(arg2)); -} - -template -constexpr const Arg &assignIfSame([[maybe_unused]] Arg &to, - const Arg &from) -{ - if constexpr (std::same_as) - return to = from; - else - return from; -} - -} - -using Impl::multi; -using Impl::single; -using Impl::union_call_t; - -template End1, - std::forward_iterator It2, - std::sentinel_for End2, - std::indirectly_unary_invocable Proj1 = std::identity, - std::indirectly_unary_invocable Proj2 = std::identity, - std::indirect_strict_weak_order, - std::projected> Comp = std::ranges::less, - Impl::address_binary_invocable Fun, - Impl::Property Prop> -constexpr void union_foreach(It1 first1, - End1 last1, - It2 first2, - End2 last2, - Fun f, - Prop, - Comp comp = {}, - Proj1 proj1 = {}, - Proj2 proj2 = {}) -{ - using enum union_call_t; - using Impl::assignIfSame; - using Impl::invoke; - const std::iter_value_t *lastValid1{}; - const std::iter_value_t *lastValid2{}; - while (first1 != last1 || first2 != last2) - if (first2 == last2 - || (first1 != last1 - && std::invoke(comp, - std::invoke(proj1, *first1), - std::invoke(proj2, *first2)))) - invoke(f, - assignIfSame(lastValid1, - std::to_address(first1++)), - lastValid2, - only_left); - else if (first1 == last1 - || std::invoke(comp, - std::invoke(proj2, *first2), - std::invoke(proj1, *first1))) - invoke(f, - lastValid1, - assignIfSame(lastValid2, - std::to_address(first2++)), - only_right); - else { - auto &&key = std::invoke(proj1, *first1); - invoke(f, - lastValid1 = std::to_address(first1++), - lastValid2 = std::to_address(first2++), - both); - - if constexpr (std::is_same_v) { - while (first1 != last1 && first2 != last2 - && !std::invoke(comp, - key, - std::invoke(proj1, *first1)) - && !std::invoke(comp, - key, - std::invoke(proj2, *first2))) - invoke(f, - lastValid1 = std::to_address(first1++), - lastValid2 = std::to_address(first2++), - both); - - while (first1 != last1 - && !std::invoke(comp, - key, - std::invoke(proj1, *first1))) - invoke(f, - std::to_address(first1++), - lastValid2, - only_left); - - while (first2 != last2 - && !std::invoke(comp, - key, - std::invoke(proj2, *first2))) - invoke(f, - lastValid1, - std::to_address(first2++), - only_right); - - lastValid1 = nullptr; - lastValid2 = nullptr; - } - } -} - -template > Proj = - std::identity, - std::indirect_strict_weak_order< - std::projected, Proj>> Comp = - std::ranges::less, - Impl::address_binary_invocable> Fun, - Impl::Property Prop = Impl::default_property_t> -constexpr void union_foreach(const R &r1, - const R &r2, - Fun f, - Comp comp = {}, - Proj proj = {}, - Prop p = {}) -{ - union_foreach(std::ranges::begin(r1), - std::ranges::end(r1), - std::ranges::begin(r2), - std::ranges::end(r2), - std::move(f), - p, - std::move(comp), - proj, - proj); -} -} - -#endif diff --git a/src/base/math/segmentedfunc.h b/src/base/math/segmentedfunc.h index 4b4519db1..063685b9c 100644 --- a/src/base/math/segmentedfunc.h +++ b/src/base/math/segmentedfunc.h @@ -4,7 +4,7 @@ #include #include -#include "base/alg/union_foreach.h" +#include "base/alg/merge.h" #include "interpolation.h" #include "range.h" @@ -43,32 +43,23 @@ template struct SegmentedFunction { CRTP res; - Alg::union_foreach( - self.stops, + auto &&transformer = [](auto &&another) + { + return [&another](const Stop &item) + { + return Stop{item.pos, item.value + another(item.pos)}; + }; + }; + Alg::merge(self.stops, other.stops, - [&](const Stop *lhs, - const Stop *rhs, - Alg::union_call_t type) - { - switch (type) { - case Alg::union_call_t::only_left: - res.stops.emplace_back(lhs->pos, - lhs->value + other(lhs->pos)); - break; - case Alg::union_call_t::only_right: - res.stops.emplace_back(rhs->pos, - rhs->value + self(rhs->pos)); - break; - case Alg::union_call_t::both: - default: - res.stops.emplace_back(lhs->pos, - lhs->value + rhs->value); - break; - } - }, - {}, - &Stop::pos, - Alg::single); + res.stops, + Alg::merge_args{.projection = &Stop::pos, + .transformer_1 = transformer(other), + .transformer_2 = transformer(self), + .merger = [](const Stop &item1, const Stop &item2) + { + return Stop{item1.pos, item1.value + item2.value}; + }}); return res; } diff --git a/src/chart/generator/axis.cpp b/src/chart/generator/axis.cpp index 5f30bbfd9..824dc7982 100644 --- a/src/chart/generator/axis.cpp +++ b/src/chart/generator/axis.cpp @@ -11,7 +11,7 @@ #include #include -#include "base/alg/union_foreach.h" +#include "base/alg/merge.h" #include "base/anim/interpolated.h" #include "base/geom/point.h" #include "base/math/floating.h" @@ -295,32 +295,46 @@ DimensionAxis interpolate(const DimensionAxis &op0, DimensionAxis res; res.factor = factor; - using Ptr = DimensionAxis::Values::const_pointer; - Alg::union_foreach( - op0.values, + using Val = DimensionAxis::Values::value_type; + + const Val *latest1{}; + const Val *latest2{}; + + auto &&merger = [&](const Val &lhs, const Val &rhs) -> Val + { + latest1 = std::addressof(lhs); + latest2 = std::addressof(rhs); + return {lhs.first, + interpolate(lhs.second, rhs.second, factor)}; + }; + + auto &&one_side = + [&merger](bool first, + DimensionAxis::Item::PosType DimensionAxis::Item::*pos, + const Val *¶mOther) + { + return [&, first, pos](const Val &val) -> Val + { + if (paramOther && paramOther->first == val.first) { + auto &&res = first ? merger(val, *paramOther) + : merger(*paramOther, val); + (res.second.*pos).makeAuto(); + return res; + } + return {val.first, {val.second, first}}; + }; + }; + + Alg::merge(op0.values, op1.values, - [&res](Ptr v1, Ptr v2, Alg::union_call_t type) - { - if (!v2) - res.values.emplace(std::piecewise_construct, - std::tuple{v1->first}, - std::forward_as_tuple(v1->second, true)); - else if (!v1) - res.values.emplace(std::piecewise_construct, - std::tuple{v2->first}, - std::forward_as_tuple(v2->second, false)); - else if (auto &&val = res.values - .emplace(v1->first, - interpolate(v1->second, - v2->second, - res.factor)) - ->second; - type == Alg::union_call_t::only_left) - val.endPos.makeAuto(); - else if (type == Alg::union_call_t::only_right) - val.startPos.makeAuto(); - }, - res.values.value_comp()); + res.values, + Alg::merge_args{.projection = &Val::first, + .transformer_1 = + one_side(true, &DimensionAxis::Item::endPos, latest2), + .transformer_2 = one_side(false, + &DimensionAxis::Item::startPos, + latest1), + .merger = merger}); return res; } @@ -348,141 +362,65 @@ interpolate(const SplitAxis &op0, const SplitAxis &op1, double factor) interpolate(static_cast(op0), static_cast(op1), factor); - if (!op0.parts.empty() && !op1.parts.empty() - && op0.seriesName() == op1.seriesName()) { - using PartPair = const decltype(res.parts)::value_type; - Alg::union_foreach( - op0.parts, - op1.parts, - [&res, &factor](PartPair *lhs, - PartPair *rhs, - Alg::union_call_t type) - { - switch (type) { - case Alg::union_call_t::only_left: { - auto from = lhs->second.range.min; - res.parts.insert({lhs->first, - {.weight = interpolate(lhs->second.weight, - 0.0, - factor), - .range = interpolate(lhs->second.range, - Math::Range<>{from, from}, - factor), - .measureRange = - interpolate(lhs->second.measureRange, - Math::Range<>{0, 1}, - factor)}}); - break; - } - case Alg::union_call_t::only_right: { - auto from = rhs->second.range.min; - res.parts.insert({rhs->first, - {.weight = interpolate(0.0, - rhs->second.weight, - factor), - .range = - interpolate(Math::Range<>{from, from}, - rhs->second.range, - factor), - .measureRange = - interpolate(Math::Range<>{0, 1}, - rhs->second.measureRange, - factor)}}); - break; - } - default: - case Alg::union_call_t::both: { - res.parts.insert({lhs->first, - interpolate(lhs->second, - rhs->second, - factor)}); - break; - } - } - }, - res.parts.value_comp()); - - return res; - } - if (!op0.parts.empty()) { - if (op0.seriesName() != op1.seriesName()) { - for (auto &&[index, part] : op0.parts) - res.parts.insert({index, - {.weight = part.weight * (1 - factor), - .range = part.range, - .measureRange = part.measureRange}}); - } - else { - auto begin = op0.parts.begin(); - res.parts.insert({begin->first, - {.weight = interpolate(begin->second.weight, - 1.0, - factor), - .range = interpolate(begin->second.range, - Math::Range<>{0, 1}, - factor), - .measureRange = - interpolate(begin->second.measureRange, - Math::Range<>{0, 1}, - factor)}}); - while (++begin != op0.parts.end()) { - res.parts.insert({begin->first, - {.weight = interpolate(begin->second.weight, - 0.0, - factor), - .range = interpolate(begin->second.range, - Math::Range<>{0, 1}, - factor), - .measureRange = - interpolate(begin->second.measureRange, - Math::Range<>{0, 1}, - factor)}}); - } - } - } - else if (!op1.parts.empty() - && op0.seriesName() != op1.seriesName()) - res.parts.insert({std::nullopt, {.weight = 1 - factor}}); - - if (!op1.parts.empty()) { - if (op0.seriesName() != op1.seriesName()) { - for (auto &&[index, part] : op1.parts) - res.parts.insert({index, - {.weight = part.weight * factor, - .range = part.range, - .measureRange = part.measureRange}}); - } - else { - auto begin = op1.parts.begin(); - res.parts.insert({begin->first, - {.weight = interpolate(1.0, - begin->second.weight, - factor), - .range = interpolate(Math::Range<>{0, 1}, - begin->second.range, - factor), - .measureRange = interpolate(Math::Range<>{0, 1}, - begin->second.measureRange, - factor)}}); - while (++begin != op1.parts.end()) { - res.parts.insert({begin->first, - {.weight = interpolate(0.0, - begin->second.weight, - factor), - .range = interpolate(Math::Range<>{0, 1}, - begin->second.range, - factor), - .measureRange = - interpolate(Math::Range<>{0, 1}, - begin->second.measureRange, - factor)}}); + using PartPair = SplitAxis::Parts::value_type; + + auto needMerge = op0.seriesName() == op1.seriesName(); + + auto &&merger = [](double factor) + { + return [factor](const PartPair &lhs, + const PartPair &rhs) -> PartPair + { + return {lhs.first, + interpolate(lhs.second, rhs.second, factor)}; + }; + }; + + auto &&one_side = [needMerge](const decltype(merger(0.0)) &merger, + bool needOther) + { + return + [needMerge, &merger, needOther, firstSpecial = needOther]( + const PartPair &val) mutable -> PartPair + { + if (needMerge) { + if (firstSpecial) { + firstSpecial = false; + return merger(val, {{}, {1.0}}); + } + + Math::Range<> range{0.0, 1.0}; + if (!needOther) + range = {val.second.range.max, + val.second.range.max}; + + return merger(val, {{}, {0.0, range}}); } - } - } - else if (!op0.parts.empty() - && op0.seriesName() != op1.seriesName()) - res.parts.insert({std::nullopt, {.weight = factor}}); + return merger(val, + {{}, + {0.0, + val.second.range, + val.second.measureRange}}); + }; + }; + + Alg::merge(op0.parts, + op1.parts, + res.parts, + Alg::merge_args{.projection = &PartPair::first, + .transformer_1 = + one_side(merger(factor), op1.parts.empty()), + .transformer_2 = + one_side(merger(1 - factor), op0.parts.empty()), + .need_merge = {needMerge}, + .merger = merger(factor)}); + + if (!needMerge && op0.parts.empty() != op1.parts.empty() + && (!op0.dimension.empty() || op0.measure.enabled.get()) + && (!op1.dimension.empty() || op1.measure.enabled.get())) + res.parts.insert({std::nullopt, + {.weight = op0.parts.empty() ? 1 - factor : factor}}); return res; } diff --git a/src/dataframe/old/types.h b/src/dataframe/old/types.h index 5684a7c2c..ba313cd9d 100644 --- a/src/dataframe/old/types.h +++ b/src/dataframe/old/types.h @@ -127,13 +127,8 @@ struct SliceIndex std::string column; std::string value; - [[nodiscard]] bool operator<(const SliceIndex &rhs) const - { - return column < rhs.column - || (column == rhs.column && value < rhs.value); - } - - [[nodiscard]] bool operator==(const SliceIndex &) const = default; + [[nodiscard]] auto operator<=>( + const SliceIndex &rhs) const = default; }; struct CellInfo From d08012afcb7e32025e91bfe75b8d11c4adaa2d3f Mon Sep 17 00:00:00 2001 From: Bela Schaum Date: Wed, 11 Dec 2024 15:42:07 +0100 Subject: [PATCH 2/5] fix "empty" channel split, clang-tidy, fix tests --- src/base/alg/merge.h | 1 + src/chart/generator/axis.cpp | 14 ++-- src/chart/generator/axis.h | 1 + src/chart/generator/plotbuilder.cpp | 4 +- .../rendering/markers/connectingmarker.cpp | 4 +- test/e2e/test_cases/test_cases.json | 80 +++++++++---------- test/e2e/tests/fixes.json | 4 +- test/e2e/tests/style_tests.json | 2 +- test/e2e/tests/tickets.json | 2 +- 9 files changed, 60 insertions(+), 52 deletions(-) diff --git a/src/base/alg/merge.h b/src/base/alg/merge.h index dc12680dc..308b8a3d2 100644 --- a/src/base/alg/merge.h +++ b/src/base/alg/merge.h @@ -1,6 +1,7 @@ #ifndef ALG_MERGE_H #define ALG_MERGE_H +#include #include #include #include diff --git a/src/chart/generator/axis.cpp b/src/chart/generator/axis.cpp index 824dc7982..99a68d095 100644 --- a/src/chart/generator/axis.cpp +++ b/src/chart/generator/axis.cpp @@ -295,6 +295,10 @@ DimensionAxis interpolate(const DimensionAxis &op0, DimensionAxis res; res.factor = factor; + res.hasMarker = !Math::Floating::is_zero( + Math::Niebloid::interpolate(op0.hasMarker, + op1.hasMarker, + factor)); using Val = DimensionAxis::Values::value_type; const Val *latest1{}; @@ -387,7 +391,7 @@ interpolate(const SplitAxis &op0, const SplitAxis &op1, double factor) if (needMerge) { if (firstSpecial) { firstSpecial = false; - return merger(val, {{}, {1.0}}); + return merger(val, {}); } Math::Range<> range{0.0, 1.0}; @@ -410,15 +414,15 @@ interpolate(const SplitAxis &op0, const SplitAxis &op1, double factor) res.parts, Alg::merge_args{.projection = &PartPair::first, .transformer_1 = - one_side(merger(factor), op1.parts.empty()), + one_side(merger(factor), op1.parts.size() <= 1), .transformer_2 = - one_side(merger(1 - factor), op0.parts.empty()), + one_side(merger(1 - factor), op0.parts.size() <= 1), .need_merge = {needMerge}, .merger = merger(factor)}); if (!needMerge && op0.parts.empty() != op1.parts.empty() - && (!op0.dimension.empty() || op0.measure.enabled.get()) - && (!op1.dimension.empty() || op1.measure.enabled.get())) + && (op0.dimension.hasMarker || op0.measure.enabled.get()) + && (op1.dimension.hasMarker || op1.measure.enabled.get())) res.parts.insert({std::nullopt, {.weight = op0.parts.empty() ? 1 - factor : factor}}); diff --git a/src/chart/generator/axis.h b/src/chart/generator/axis.h index e0c135cd1..c13e4cb1d 100644 --- a/src/chart/generator/axis.h +++ b/src/chart/generator/axis.h @@ -129,6 +129,7 @@ struct DimensionAxis using Values = std::multimap; double factor{}; + bool hasMarker{}; DimensionAxis() = default; bool add(const Data::SliceIndex &index, diff --git a/src/chart/generator/plotbuilder.cpp b/src/chart/generator/plotbuilder.cpp index 44be48c4f..24c66f149 100644 --- a/src/chart/generator/plotbuilder.cpp +++ b/src/chart/generator/plotbuilder.cpp @@ -426,6 +426,7 @@ void PlotBuilder::calcLegendAndLabel(const Data::DataTable &dataTable) true, merge)) ++count; + calcLegend.dimension.hasMarker = true; } if (auto &&series = plot->getOptions()->labelSeries(type); @@ -448,7 +449,6 @@ void PlotBuilder::calcAxis(const Data::DataTable &dataTable, AxisId type) { const auto &scale = plot->getOptions()->getChannels().at(type); - if (scale.isEmpty()) return; auto &axisProps = plot->getOptions()->getChannels().axisPropsAt(type); @@ -495,6 +495,8 @@ void PlotBuilder::calcAxis(const Data::DataTable &dataTable, {}, false, merge); + + axis.dimension.hasMarker = true; } if (auto &&series = plot->getOptions()->labelSeries(type); !axis.dimension.setLabels(axisProps.step.getValue(1.0)) diff --git a/src/chart/rendering/markers/connectingmarker.cpp b/src/chart/rendering/markers/connectingmarker.cpp index 93a19fa30..ee9f50fbd 100644 --- a/src/chart/rendering/markers/connectingmarker.cpp +++ b/src/chart/rendering/markers/connectingmarker.cpp @@ -55,8 +55,8 @@ ConnectingMarker::ConnectingMarker(const DrawingContext &ctx, linear = !polar || horizontal || Math::FuzzyBool::And( !isHorizontal - && !ctx.plot->axises.at(Gen::AxisId::x) - .dimension.empty(), + && ctx.plot->axises.at(Gen::AxisId::x) + .dimension.hasMarker, ctx.plot->axises.at(Gen::AxisId::x) .measure.enabled.factor(false), !horizontal); diff --git a/test/e2e/test_cases/test_cases.json b/test/e2e/test_cases/test_cases.json index a8e33740b..1e1296f4b 100644 --- a/test/e2e/test_cases/test_cases.json +++ b/test/e2e/test_cases/test_cases.json @@ -461,13 +461,13 @@ "refs": ["7d026fc"] }, "web_content/analytical_operations/compare/area_polar_split": { - "refs": ["c967f87"] + "refs": ["7fd64a3"] }, "web_content/analytical_operations/compare/area_polar_stacked": { "refs": ["68c7e81"] }, "web_content/analytical_operations/compare/area_split_stacked": { - "refs": ["3f72973"] + "refs": ["bf699c0"] }, "web_content/analytical_operations/compare/area_stacked": { "refs": ["8a34995"] @@ -482,10 +482,10 @@ "refs": ["4ec1cee"] }, "web_content/analytical_operations/compare/column_split_stacked_1": { - "refs": ["2fc9d8a"] + "refs": ["648bfcb"] }, "web_content/analytical_operations/compare/column_split_stacked_2": { - "refs": ["5f4919d"] + "refs": ["982866a"] }, "web_content/analytical_operations/compare/column_stacked_1": { "refs": ["ed1ea56"] @@ -536,7 +536,7 @@ "refs": ["365c900"] }, "web_content/analytical_operations/distribute/existingmeasure_scatterplot_split": { - "refs": ["aaa67a5"] + "refs": ["4416d3e"] }, "web_content/analytical_operations/distribute/existingmeasure_treemap_stacked": { "refs": ["24dc9e3"] @@ -545,7 +545,7 @@ "refs": ["a25a78e"] }, "web_content/analytical_operations/distribute/newmeasure_column_split_stacked": { - "refs": ["36d0ba5"] + "refs": ["7cbba14"] }, "web_content/analytical_operations/distribute/newmeasure_column_stacked": { "refs": ["facf971"] @@ -668,7 +668,7 @@ "refs": ["c39a7bd"] }, "web_content/analytical_operations/stretch_to_proportion/column_split_stacked": { - "refs": ["d69242c"] + "refs": ["b9b8f86"] }, "web_content/analytical_operations/stretch_to_proportion/column_stacked": { "refs": ["9ad75d7"] @@ -680,13 +680,13 @@ "refs": ["2c78a47"] }, "web_content/analytical_operations/sum/area_polar_split": { - "refs": ["9afb358"] + "refs": ["e5aac18"] }, "web_content/analytical_operations/sum/area_polar_stacked": { "refs": ["6f4d1f8"] }, "web_content/analytical_operations/sum/area_split": { - "refs": ["9630927"] + "refs": ["b453576"] }, "web_content/analytical_operations/sum/area_stacked": { "refs": ["9078a5a"] @@ -731,7 +731,7 @@ "refs": ["c84d593"] }, "web_content/analytical_operations/sum/column_split_stacked": { - "refs": ["9905d5f"] + "refs": ["2c796ae"] }, "web_content/analytical_operations/sum/column_stacked_1": { "refs": ["3396093"] @@ -746,7 +746,7 @@ "refs": ["f8eee6c"] }, "web_content/analytical_operations/sum/coxcomb_split": { - "refs": ["61a8caf"] + "refs": ["3791909"] }, "web_content/analytical_operations/sum/dotplot": { "refs": ["966a4e8"] @@ -872,7 +872,7 @@ "refs": ["116901e"] }, "web_content/presets/chart/column_splitted": { - "refs": ["46df3f0"] + "refs": ["84258ff"] }, "web_content/presets/chart/column_percentage": { "refs": ["be20c3e"] @@ -896,7 +896,7 @@ "refs": ["ba6b634"] }, "web_content/presets/chart/bar_splitted": { - "refs": ["0d63a84"] + "refs": ["51c12b4"] }, "web_content/presets/chart/bar_percentage": { "refs": ["cfd480a"] @@ -920,7 +920,7 @@ "refs": ["018ddbc"] }, "web_content/presets/chart/area_splitted": { - "refs": ["3959b14"] + "refs": ["b824907"] }, "web_content/presets/graph/stream": { "refs": ["24b7673"] @@ -929,10 +929,10 @@ "refs": ["f675019"] }, "web_content/presets/graph/violin": { - "refs": ["ecbb9f0"] + "refs": ["e149eaf"] }, "web_content/presets/graph/violin_vertical": { - "refs": ["0cf1a64"] + "refs": ["250a499"] }, "web_content/presets/chart/line": { "refs": ["6ce0fa0"] @@ -1205,7 +1205,7 @@ "refs": ["059e2c7"] }, "ww_animTiming/descartes_orientation/03_d-d_o_a-r-a_split": { - "refs": ["751e084"] + "refs": ["90d561a"] }, "ww_animTiming/descartes_orientation/04_d-d_o_l-r-l": { "refs": ["96218ea"] @@ -1538,7 +1538,7 @@ "refs": ["9b65e14"] }, "ww_animTiming_TESTS/descartes_orientation/03_d-d_o_a-r-a_split": { - "refs": ["a88b3ee"] + "refs": ["cf4094c"] }, "ww_animTiming_TESTS/descartes_orientation/04_d-d_o_l-r-l": { "refs": ["d1b4afe"] @@ -1760,7 +1760,7 @@ "refs": ["b31a5a5"] }, "ww_next_steps/next_steps/05_C_R": { - "refs": ["debee42"] + "refs": ["b220986"] }, "ww_next_steps/next_steps/21_C_C_dotplot": { "refs": ["be7bac7"] @@ -1769,10 +1769,10 @@ "refs": ["c99f101"] }, "ww_next_steps/next_steps/28_C_A": { - "refs": ["6e92b9d"] + "refs": ["7ddc5a4"] }, "ww_next_steps/next_steps/35_C_A_violin": { - "refs": ["3a79637"] + "refs": ["8184b1f"] }, "ww_next_steps/next_steps/38_C_L_line": { "refs": ["dd7bb57"] @@ -1790,7 +1790,7 @@ "refs": ["f402f8a"] }, "ww_next_steps/next_steps_Tests/05_C_R": { - "refs": ["ef565bd"] + "refs": ["3a32941"] }, "ww_next_steps/next_steps_Tests/21_C_C_dotplot": { "refs": ["4340228"] @@ -1799,7 +1799,7 @@ "refs": ["d5b3c1f"] }, "ww_next_steps/next_steps_Tests/28_C_A": { - "refs": ["4b29d69"] + "refs": ["17a4056"] }, "ww_next_steps/next_steps_Tests/38_C_L_line": { "refs": ["e97795b"] @@ -1820,13 +1820,13 @@ "refs": ["52d3608"] }, "ww_next_steps/next_steps_byOperations/compare/comparison_05": { - "refs": ["615273e"] + "refs": ["9b0d6e6"] }, "ww_next_steps/next_steps_byOperations/compare/comparison_06": { - "refs": ["acea363"] + "refs": ["f2811e0"] }, "ww_next_steps/next_steps_byOperations/compare/comparison_09": { - "refs": ["3fada11"] + "refs": ["6be8296"] }, "ww_next_steps/next_steps_byOperations/compare/comparison_10": { "refs": ["d7882c8"] @@ -1868,7 +1868,7 @@ "refs": ["f9ee7a4"] }, "ww_next_steps/next_steps_byOperations/distribute/distribution_05": { - "refs": ["e6c5f20"] + "refs": ["9ba32b8"] }, "ww_next_steps/next_steps_byOperations/distribute/distribution_06": { "refs": ["a97aa8c"] @@ -1877,7 +1877,7 @@ "refs": ["c1a4283"] }, "ww_next_steps/next_steps_byOperations/distribute/distribution_08": { - "refs": ["1936a77"] + "refs": ["be93690"] }, "ww_next_steps/next_steps_byOperations/drilldown/drilldown_01": { "refs": ["277fa16"] @@ -1922,7 +1922,7 @@ "refs": ["334220e"] }, "ww_next_steps/next_steps_byOperations/ratio/ratio_03": { - "refs": ["3f5a96b"] + "refs": ["b2c932f"] }, "ww_next_steps/next_steps_byOperations/ratio/ratio_04": { "refs": ["04e508f"] @@ -1976,7 +1976,7 @@ "refs": ["ea1d10f"] }, "ww_next_steps/next_steps_byOperations/sum_aggregate/sum_aggregate_10": { - "refs": ["1210df0"] + "refs": ["b1a68f4"] }, "ww_next_steps/next_steps_byOperations/sum_aggregate/sum_aggregate_11": { "refs": ["3ac4f8c"] @@ -1997,7 +1997,7 @@ "refs": ["1e1c654"] }, "ww_next_steps/next_steps_byOperations/sum_aggregate/sum_aggregate_18": { - "refs": ["0683d47"] + "refs": ["aedc373"] }, "ww_next_steps/next_steps_byOperations/sum_aggregate/sum_aggregate_19": { "refs": ["1468471"] @@ -2291,7 +2291,7 @@ "refs": ["d676cb2"] }, "ww_noFade/wNoFade_Tests/2_des_pol-without/area-rectangle/10_d-w_are_temporal_bubble": { - "refs": ["4be7a2b"] + "refs": ["c6f3677"] }, "ww_noFade/wNoFade_Tests/2_des_pol-without/area/03_d-w_are": { "refs": ["207f46e"] @@ -2453,7 +2453,7 @@ "refs": ["e5678fa"] }, "ww_noFade/wNoFade_Tests/Marker_transition_problem/area_column_time_sum": { - "refs": ["28a03ad"] + "refs": ["ce2af48"] }, "ww_noFade/wNoFade_Tests/Marker_transition_problem/area_orientation": { "refs": ["8c0d580"] @@ -2660,7 +2660,7 @@ "refs": ["96441e2"] }, "ww_noFade/wNoFade_cases/2_des_pol-without/area-rectangle/10_d-w_are_temporal_bubble": { - "refs": ["38f5864"] + "refs": ["f6b34c1"] }, "ww_noFade/wNoFade_cases/2_des_pol-without/area/03_d-w_are": { "refs": ["a1b0278"] @@ -2678,7 +2678,7 @@ "refs": ["07a2162"] }, "ww_noFade/wNoFade_cases/2_des_pol-without/area/10_d-w_are_temporal_bubble": { - "refs": ["f98805f"] + "refs": ["9675022"] }, "ww_noFade/wNoFade_cases/2_des_pol-without/area_V1/03_d-w_are_V1": { "refs": ["965630f"] @@ -2987,7 +2987,7 @@ "refs": ["116901e"] }, "ww_samples_for_presets/cartesian_coo_sys/05_C_R_split_column_chart": { - "refs": ["66db5a8"] + "refs": ["a3de9d1"] }, "ww_samples_for_presets/cartesian_coo_sys/06_C_R_100_stacked_column_chart": { "refs": ["7c3feaa"] @@ -3023,7 +3023,7 @@ "refs": ["ba6b634"] }, "ww_samples_for_presets/cartesian_coo_sys/16_C_R_splitted_bar_chart": { - "refs": ["87c022d"] + "refs": ["f8b027b"] }, "ww_samples_for_presets/cartesian_coo_sys/17_C_R_100_stacked_bar_chart": { "refs": ["0f0f014"] @@ -3062,7 +3062,7 @@ "refs": ["a745467"] }, "ww_samples_for_presets/cartesian_coo_sys/31_C_A_splitted_area_chart": { - "refs": ["3086495"] + "refs": ["c388671"] }, "ww_samples_for_presets/cartesian_coo_sys/32_C_A_stream_graph": { "refs": ["f4d215c"] @@ -3071,10 +3071,10 @@ "refs": ["f128560"] }, "ww_samples_for_presets/cartesian_coo_sys/34_C_A_violin_graph": { - "refs": ["66407dd"] + "refs": ["6b5fac8"] }, "ww_samples_for_presets/cartesian_coo_sys/35_C_A_violin_graph_vert": { - "refs": ["149b38a"] + "refs": ["579646a"] }, "ww_samples_for_presets/cartesian_coo_sys/36_C_A_range_area_chart": { "refs": ["a17416d"] diff --git a/test/e2e/tests/fixes.json b/test/e2e/tests/fixes.json index 5390cf423..1535d0a81 100644 --- a/test/e2e/tests/fixes.json +++ b/test/e2e/tests/fixes.json @@ -8,7 +8,7 @@ "refs": ["1732a49"] }, "143": { - "refs": ["3f9e324"] + "refs": ["816136d"] }, "144": { "refs": ["fde02e4"] @@ -44,7 +44,7 @@ "refs": ["aa3b84c"] }, "530": { - "refs": ["1467e41"] + "refs": ["cabba39"] }, "536": { "refs": ["5b502cd"] diff --git a/test/e2e/tests/style_tests.json b/test/e2e/tests/style_tests.json index e44243ac5..9936fa2aa 100644 --- a/test/e2e/tests/style_tests.json +++ b/test/e2e/tests/style_tests.json @@ -356,7 +356,7 @@ "refs": ["bcfbd92"] }, "plot/spacing": { - "refs": ["cb2894b"] + "refs": ["598a9fc"] }, "plot/xAxis/color/hexa/animated_yellowCustom_0.25-blueCustom_0.75": { "refs": ["77b26be"] diff --git a/test/e2e/tests/tickets.json b/test/e2e/tests/tickets.json index d1498de98..177dd0c62 100644 --- a/test/e2e/tests/tickets.json +++ b/test/e2e/tests/tickets.json @@ -11,7 +11,7 @@ "refs": ["1928a0a"] }, "146": { - "refs": ["fccca41"] + "refs": ["03052cb"] }, "255": { "refs": ["29b4a25"] From cfb881f5106eb58e2307eb977ee5670f3437169d Mon Sep 17 00:00:00 2001 From: Bela Schaum Date: Wed, 11 Dec 2024 19:47:45 +0100 Subject: [PATCH 3/5] tryp-to-fix clang-format --- src/base/alg/merge.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/base/alg/merge.h b/src/base/alg/merge.h index 308b8a3d2..1807c3bd4 100644 --- a/src/base/alg/merge.h +++ b/src/base/alg/merge.h @@ -167,7 +167,7 @@ template -struct args +struct merge_args { [[no_unique_address]] Proj1 projection_1{}; [[no_unique_address]] Proj2 projection_2{}; @@ -201,7 +201,7 @@ constexpr std::ranges::in_in_out_result merge( It2 first2, End2 last2, Out result, - args &&args = {}) + merge_args &&args = {}) { if constexpr (std::weakly_incrementable< std::remove_cvref_t>) { @@ -282,7 +282,7 @@ merge(R1 &&range1, } using Merge::merge; -template using merge_args = Merge::args; +using Merge::merge_args; } From dec4e97a151bb1bc7fe8cab7d41bb05fdccc2f9c Mon Sep 17 00:00:00 2001 From: Bela Schaum Date: Thu, 12 Dec 2024 11:58:46 +0100 Subject: [PATCH 4/5] fix clang-16 compiler --- src/base/math/segmentedfunc.h | 25 ++++++++++++++++++------ src/chart/generator/axis.cpp | 36 +++++++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/base/math/segmentedfunc.h b/src/base/math/segmentedfunc.h index 063685b9c..79cda4260 100644 --- a/src/base/math/segmentedfunc.h +++ b/src/base/math/segmentedfunc.h @@ -43,7 +43,12 @@ template struct SegmentedFunction { CRTP res; - auto &&transformer = [](auto &&another) + auto merger = [](const Stop &item1, const Stop &item2) + { + return Stop{item1.pos, item1.value + item2.value}; + }; + + auto &&transformer = [](const CRTP &another) { return [&another](const Stop &item) { @@ -53,13 +58,21 @@ template struct SegmentedFunction Alg::merge(self.stops, other.stops, res.stops, - Alg::merge_args{.projection = &Stop::pos, + Alg::merge_args + // { Remove when clang-16 not used + + // } + {.projection = &Stop::pos, .transformer_1 = transformer(other), .transformer_2 = transformer(self), - .merger = [](const Stop &item1, const Stop &item2) - { - return Stop{item1.pos, item1.value + item2.value}; - }}); + .merger = merger}); return res; } diff --git a/src/chart/generator/axis.cpp b/src/chart/generator/axis.cpp index 99a68d095..3bfddd73f 100644 --- a/src/chart/generator/axis.cpp +++ b/src/chart/generator/axis.cpp @@ -304,7 +304,7 @@ DimensionAxis interpolate(const DimensionAxis &op0, const Val *latest1{}; const Val *latest2{}; - auto &&merger = [&](const Val &lhs, const Val &rhs) -> Val + auto merger = [&](const Val &lhs, const Val &rhs) -> Val { latest1 = std::addressof(lhs); latest2 = std::addressof(rhs); @@ -332,7 +332,18 @@ DimensionAxis interpolate(const DimensionAxis &op0, Alg::merge(op0.values, op1.values, res.values, - Alg::merge_args{.projection = &Val::first, + Alg::merge_args + // { Remove when clang-16 not used + + // } + {.projection = &Val::first, .transformer_1 = one_side(true, &DimensionAxis::Item::endPos, latest2), .transformer_2 = one_side(false, @@ -381,8 +392,9 @@ interpolate(const SplitAxis &op0, const SplitAxis &op1, double factor) }; }; - auto &&one_side = [needMerge](const decltype(merger(0.0)) &merger, - bool needOther) + using MergerType = decltype(merger(0.0)); + auto &&one_side = + [needMerge](const MergerType &merger, bool needOther) { return [needMerge, &merger, needOther, firstSpecial = needOther]( @@ -391,7 +403,8 @@ interpolate(const SplitAxis &op0, const SplitAxis &op1, double factor) if (needMerge) { if (firstSpecial) { firstSpecial = false; - return merger(val, {}); + return merger(val, + PartPair{std::nullopt, SplitAxis::Part{}}); } Math::Range<> range{0.0, 1.0}; @@ -412,7 +425,18 @@ interpolate(const SplitAxis &op0, const SplitAxis &op1, double factor) Alg::merge(op0.parts, op1.parts, res.parts, - Alg::merge_args{.projection = &PartPair::first, + Alg::merge_args + // { Remove when clang-16 not used + PartPair::*, + decltype(std::weak_order), + decltype(one_side(merger({}), {})), + decltype(one_side(merger({}), {})), + Alg::Merge::always, + const MergerType &> + // } + {.projection = &PartPair::first, .transformer_1 = one_side(merger(factor), op1.parts.size() <= 1), .transformer_2 = From c71aaf3afb728f062a3edcb9dfad00a728452553 Mon Sep 17 00:00:00 2001 From: Bela Schaum Date: Sat, 14 Dec 2024 17:18:42 +0100 Subject: [PATCH 5/5] only max+min measure ; tests --- src/base/math/range.h | 11 +- src/chart/generator/axis.cpp | 75 ++++++---- src/chart/generator/axis.h | 9 ++ src/chart/rendering/drawaxes.cpp | 22 ++- src/chart/rendering/drawguides.cpp | 12 +- src/chart/rendering/drawguides.h | 2 + src/chart/rendering/drawinterlacing.cpp | 62 +++++++-- src/chart/rendering/drawinterlacing.h | 7 +- test/e2e/test_cases/test_cases.json | 176 ++++++++++++------------ test/e2e/tests/docs.json | 2 +- test/e2e/tests/fixes.json | 2 +- test/e2e/tests/style_tests.json | 2 +- test/e2e/tests/tickets.json | 2 +- 13 files changed, 234 insertions(+), 150 deletions(-) diff --git a/src/base/math/range.h b/src/base/math/range.h index 7bf88afad..64c05f17f 100644 --- a/src/base/math/range.h +++ b/src/base/math/range.h @@ -46,7 +46,7 @@ template struct Range && !is_lt(std::weak_order(max, value)); } - [[nodiscard]] T rescale(const T &value, T def = 0.5) const + [[nodiscard]] T rescale(const T &value, T def = T{0.5}) const { auto s = size(); return is_zero(s) ? def : (value - min) / s; @@ -64,7 +64,7 @@ template struct Range [[nodiscard]] T normalize(const T &value) const { - return is_zero(max) ? 0 : value / max; + return is_zero(max) ? T{} : value / max; } bool operator==(const Range &other) const @@ -97,14 +97,15 @@ template struct Range return {min / factor, max / factor}; } - Range operator*(const Transform &transf) + [[nodiscard]] Range operator*(const Transform &transf) const { return *this * transf.factor + transf.shift; } - Transform operator/(const Range range) + [[nodiscard]] Transform operator/(const Range range) const { - auto factor = range.size() != 0 ? size() / range.size() : 0; + auto factor = + is_zero(range.size()) ? T{} : size() / range.size(); auto shift = min - range.min * factor; return Transform{factor, shift}; } diff --git a/src/chart/generator/axis.cpp b/src/chart/generator/axis.cpp index 3bfddd73f..db1a4fbb1 100644 --- a/src/chart/generator/axis.cpp +++ b/src/chart/generator/axis.cpp @@ -380,7 +380,8 @@ interpolate(const SplitAxis &op0, const SplitAxis &op1, double factor) using PartPair = SplitAxis::Parts::value_type; - auto needMerge = op0.seriesName() == op1.seriesName(); + auto needMerge = op0.seriesName() == op1.seriesName() + && op0.measure.unit == op1.measure.unit; auto &&merger = [](double factor) { @@ -393,27 +394,20 @@ interpolate(const SplitAxis &op0, const SplitAxis &op1, double factor) }; using MergerType = decltype(merger(0.0)); - auto &&one_side = - [needMerge](const MergerType &merger, bool needOther) + auto &&one_side = [](const MergerType &merger, + bool needOther, + const Math::Range<>::Transform &transform) { - return - [needMerge, &merger, needOther, firstSpecial = needOther]( - const PartPair &val) mutable -> PartPair + return [&merger, &transform, needOther]( + const PartPair &val) -> PartPair { - if (needMerge) { - if (firstSpecial) { - firstSpecial = false; - return merger(val, - PartPair{std::nullopt, SplitAxis::Part{}}); - } - - Math::Range<> range{0.0, 1.0}; - if (!needOther) - range = {val.second.range.max, - val.second.range.max}; - - return merger(val, {{}, {0.0, range}}); - } + if (needOther) + return merger(val, + {{}, + {0.0, + (Math::Range<>{0, 1} * transform), + (val.second.measureRange * 1.000001 + * transform)}}); return merger(val, {{}, {0.0, @@ -431,24 +425,45 @@ interpolate(const SplitAxis &op0, const SplitAxis &op1, double factor) std::identity, const std::optional PartPair::*, decltype(std::weak_order), - decltype(one_side(merger({}), {})), - decltype(one_side(merger({}), {})), + decltype(one_side(merger({}), {}, {})), + decltype(one_side(merger({}), {}, {})), Alg::Merge::always, const MergerType &> // } {.projection = &PartPair::first, - .transformer_1 = - one_side(merger(factor), op1.parts.size() <= 1), - .transformer_2 = - one_side(merger(1 - factor), op0.parts.size() <= 1), + .transformer_1 = one_side(merger(factor), + needMerge && op1.parts.empty(), + (op0.measure.range - op0.measure.range.min) + / (op1.measure.range - op1.measure.range.min)), + .transformer_2 = one_side(merger(1 - factor), + needMerge && op0.parts.empty(), + (op1.measure.range - op1.measure.range.min) + / (op0.measure.range - op0.measure.range.min)), .need_merge = {needMerge}, .merger = merger(factor)}); - if (!needMerge && op0.parts.empty() != op1.parts.empty() + if (op0.parts.empty() != op1.parts.empty() && (op0.dimension.hasMarker || op0.measure.enabled.get()) - && (op1.dimension.hasMarker || op1.measure.enabled.get())) - res.parts.insert({std::nullopt, - {.weight = op0.parts.empty() ? 1 - factor : factor}}); + && (op1.dimension.hasMarker || op1.measure.enabled.get())) { + if (needMerge) { + const auto &ref = + (op0.parts.empty() ? op1.parts : op0.parts) + .begin() + ->second.range; + res.parts + .insert( + merger(op0.parts.empty() + ? 1 - factor + : factor)({{}, {0.0, ref}}, {{}, {}})) + ->second.unique = true; + } + else + res.parts + .insert({std::nullopt, + {.weight = + op0.parts.empty() ? 1 - factor : factor}}) + ->second.unique = true; + } return res; } diff --git a/src/chart/generator/axis.h b/src/chart/generator/axis.h index c13e4cb1d..e9fb0ea6c 100644 --- a/src/chart/generator/axis.h +++ b/src/chart/generator/axis.h @@ -204,9 +204,18 @@ struct SplitAxis : Axis double weight{1.0}; Math::Range<> range{0, 1}; Math::Range<> measureRange{0, 1}; + bool unique{}; [[nodiscard]] bool operator==( const Part &other) const = default; + + [[nodiscard]] consteval static auto members() + { + return std::tuple{&Part::weight, + &Part::range, + &Part::measureRange, + std::ignore}; + } }; using Parts = diff --git a/src/chart/rendering/drawaxes.cpp b/src/chart/rendering/drawaxes.cpp index 6f35c5cab..f499f5a1b 100644 --- a/src/chart/rendering/drawaxes.cpp +++ b/src/chart/rendering/drawaxes.cpp @@ -57,10 +57,12 @@ void DrawAxes::drawGeometries() const DrawInterlacing{*this}.drawGeometries(Gen::AxisId::y, ySplit.measureRange, + xSplit.measureRange, tr, weight); DrawInterlacing{*this}.drawGeometries(Gen::AxisId::x, xSplit.measureRange, + ySplit.measureRange, tr, weight); @@ -79,10 +81,12 @@ void DrawAxes::drawGeometries() const DrawGuides{*this}.draw(Gen::AxisId::x, xSplit.measureRange, + ySplit.measureRange, tr, weight); DrawGuides{*this}.draw(Gen::AxisId::y, ySplit.measureRange, + xSplit.measureRange, tr, weight); } @@ -90,30 +94,34 @@ void DrawAxes::drawGeometries() const void DrawAxes::drawLabels() const { - for (auto &&ySplit : std::views::values(splits[Gen::AxisId::y])) { + auto &&yValues = std::views::values(splits[Gen::AxisId::y]); + for (auto &&ySplit : yValues) { const Geom::AffineTransform tr{1, 0.0, - 0, + 0.0, 0.0, ySplit.range.size(), ySplit.range.min}; DrawInterlacing{*this}.drawTexts(Gen::AxisId::y, ySplit.measureRange, tr, - ySplit.weight); + ySplit.weight, + yValues.size() > 1 && !ySplit.unique); } - for (auto &&xSplit : std::views::values(splits[Gen::AxisId::x])) { + auto &&xValues = std::views::values(splits[Gen::AxisId::x]); + for (auto &&xSplit : xValues) { const Geom::AffineTransform tr{xSplit.range.size(), 0.0, xSplit.range.min, 0.0, - 1, - 0}; + 1.0, + 0.0}; DrawInterlacing{*this}.drawTexts(Gen::AxisId::x, xSplit.measureRange, tr, - xSplit.weight); + xSplit.weight, + xValues.size() > 1 && !xSplit.unique); } drawDimensionLabels(Gen::AxisId::x); diff --git a/src/chart/rendering/drawguides.cpp b/src/chart/rendering/drawguides.cpp index 2dca1bcfc..9a017fdfd 100644 --- a/src/chart/rendering/drawguides.cpp +++ b/src/chart/rendering/drawguides.cpp @@ -16,6 +16,7 @@ namespace Vizzu::Draw { void DrawGuides::draw(Gen::AxisId axisId, const Math::Range<> &filter, + const Math::Range<> &otherFilter, const Geom::AffineTransform &tr, double w) { @@ -31,6 +32,7 @@ void DrawGuides::draw(Gen::AxisId axisId, for (const auto &sep : parent.getSeparators(axisId, filter)) drawGuide(axisId, sep.position, + otherFilter, tr, baseColor * Math::FuzzyBool::And(w, @@ -43,15 +45,15 @@ void DrawGuides::draw(Gen::AxisId axisId, void DrawGuides::drawGuide(Gen::AxisId axisId, double val, + const Math::Range<> &otherFilter, const Geom::AffineTransform &tr, const Gfx::Color &color) { - auto ident = Geom::Point::Ident(orientation(axisId)); - auto normal = Geom::Point::Ident(!orientation(axisId)); - auto relMax = ident * val; - + auto o = orientation(axisId); parent.canvas.setLineColor(color); - auto line = tr(Geom::Line{relMax, relMax + normal}); + auto line = + tr(Geom::Line{Geom::Point::Coord(o, val, otherFilter.min), + Geom::Point::Coord(o, val, otherFilter.max)}); if (auto &&eventTarget = Events::Targets::axisGuide(axisId); parent.rootEvents.draw.plot.axis.guide->invoke( Events::OnLineDrawEvent(*eventTarget, {line, true}))) { diff --git a/src/chart/rendering/drawguides.h b/src/chart/rendering/drawguides.h index 44ea8ebad..6b6512036 100644 --- a/src/chart/rendering/drawguides.h +++ b/src/chart/rendering/drawguides.h @@ -12,6 +12,7 @@ class DrawGuides public: void draw(Gen::AxisId axisId, const Math::Range<> &filter, + const Math::Range<> &otherFilter, const Geom::AffineTransform &tr, double w); @@ -20,6 +21,7 @@ class DrawGuides private: void drawGuide(Gen::AxisId axisId, double val, + const Math::Range<> &otherFilter, const Geom::AffineTransform &tr, const Gfx::Color &color); }; diff --git a/src/chart/rendering/drawinterlacing.cpp b/src/chart/rendering/drawinterlacing.cpp index 3d9324d85..b27482476 100644 --- a/src/chart/rendering/drawinterlacing.cpp +++ b/src/chart/rendering/drawinterlacing.cpp @@ -30,16 +30,19 @@ namespace Vizzu::Draw void DrawInterlacing::drawGeometries(Gen::AxisId axisIndex, const Math::Range<> &filter, + const Math::Range<> &otherFilter, const Geom::AffineTransform &tr, double w) const { const auto &guides = parent.plot->guides.at(axisIndex); const auto &axisStyle = parent.rootStyle.plot.getAxis(axisIndex); if (axisStyle.interlacing.color->isTransparent() - || guides.interlacings == false) + || guides.interlacings == false + || Math::Floating::is_zero(otherFilter.size())) return; - auto otherWeights = getInterlacingWeights(!axisIndex); + auto otherWeights = + getInterlacingWeights(!axisIndex, otherFilter); auto &&otherInterlacingColor = *parent.rootStyle.plot.getAxis(!axisIndex).interlacing.color; @@ -101,7 +104,8 @@ void DrawInterlacing::drawGeometries(Gen::AxisId axisIndex, void DrawInterlacing::drawTexts(Gen::AxisId axisIndex, const Math::Range<> &filter, const Geom::AffineTransform &tr, - double w) const + double w, + bool onlyOne) const { const auto &axis = parent.getAxis(axisIndex).measure; auto orientation = !Gen::orientation(axisIndex); @@ -123,10 +127,45 @@ void DrawInterlacing::drawTexts(Gen::AxisId axisIndex, if (!needText && !needTick) return; + std::array, 2> + latests{}; + + if (needText && onlyOne) + for (const auto &sep : + parent.getSeparators(axisIndex, filter)) { + if (!sep.label) continue; + if (auto &&cmp = std::weak_order(*sep.label, 0.0); + !is_eq(cmp) + && (!latests[is_lt(cmp)][0] + || std::abs(*latests[is_lt(cmp)][0]->label) + < std::abs(*sep.label))) { + auto &[f, s] = latests[is_lt(cmp)]; + if (!s) + s = std::addressof(sep); + else if (std::abs(*s->label) < std::abs(*sep.label)) { + if (Math::AddTolerance(s->weight + sep.weight) + == 1.0) + f = s; + else if (f + && Math::AddTolerance( + f->weight + sep.weight) + > 1.0) + f = nullptr; + s = std::addressof(sep); + } + else if (Math::AddTolerance(s->weight + sep.weight) + == 1.0) + f = std::addressof(sep); + } + } + for (const auto &sep : parent.getSeparators(axisIndex, filter)) { auto tickPos = Geom::Point::Coord(orientation, origo, sep.position); - if (needText && sep.label) + if (needText && sep.label + && (!onlyOne || &sep == latests[0][0] + || &sep == latests[0][1] || &sep == latests[1][0] + || &sep == latests[1][1])) drawDataLabel(axis.enabled, axisIndex, tickPos, @@ -280,9 +319,11 @@ void DrawInterlacing::drawSticks(double tickLength, } std::map DrawInterlacing::getInterlacingWeights( - Gen::AxisId axisIndex) const + Gen::AxisId axisIndex, + const Math::Range<> &filter) const { - std::map weights{{0.0, 0.0}, {1.0, 0.0}}; + std::map weights{{filter.min, 0.0}, + {filter.max, 0.0}}; auto &&guides = parent.plot->guides.at(axisIndex); auto &&axisStyle = parent.rootStyle.plot.getAxis(axisIndex); @@ -291,9 +332,12 @@ std::map DrawInterlacing::getInterlacingWeights( return weights; for (auto &&interval : parent.getIntervals(axisIndex)) { - if (Math::Floating::is_zero(interval.isSecond)) continue; - auto min = std::max(interval.range.min, 0.0); - auto max = std::min(interval.range.max, 1.0); + if (Math::Floating::is_zero(interval.isSecond) + || !interval.range.intersects(filter)) + continue; + auto min = std::max(interval.range.min, filter.min); + auto max = std::min(interval.range.max, filter.max); + auto mprev = std::prev(weights.upper_bound(min)); auto mnext = weights.lower_bound(max); diff --git a/src/chart/rendering/drawinterlacing.h b/src/chart/rendering/drawinterlacing.h index 524ffb342..07b9b8e77 100644 --- a/src/chart/rendering/drawinterlacing.h +++ b/src/chart/rendering/drawinterlacing.h @@ -12,12 +12,14 @@ class DrawInterlacing public: void drawGeometries(Gen::AxisId axisIndex, const Math::Range<> &filter, + const Math::Range<> &otherFilter, const Geom::AffineTransform &tr, double w) const; void drawTexts(Gen::AxisId axisIndex, const Math::Range<> &filter, const Geom::AffineTransform &tr, - double w) const; + double w, + bool onlyOne) const; const DrawAxes &parent; @@ -41,7 +43,8 @@ class DrawInterlacing const Geom::AffineTransform &tr) const; [[nodiscard]] std::map getInterlacingWeights( - Gen::AxisId axisIndex) const; + Gen::AxisId axisIndex, + const Math::Range<> &filter) const; [[nodiscard]] static Gfx::Color getCrossingInterlacingColor( const Gfx::Color &mainColor, diff --git a/test/e2e/test_cases/test_cases.json b/test/e2e/test_cases/test_cases.json index 1e1296f4b..61d9eaff7 100644 --- a/test/e2e/test_cases/test_cases.json +++ b/test/e2e/test_cases/test_cases.json @@ -113,13 +113,13 @@ "refs": ["69db5d4"] }, "basic_animations/someOtherTests/merge_split_area_stream_2dis_1con": { - "refs": ["ac444ed"] + "refs": ["deaa0e5"] }, "basic_animations/someOtherTests/total_time_area_bar": { - "refs": ["5c623b7"] + "refs": ["0695d89"] }, "basic_animations/someOtherTests/total_time_area_column": { - "refs": ["bf507c7"] + "refs": ["22d2591"] }, "basic_animations/someOtherTests/total_time_bar_line": { "refs": ["a8a1f7c"] @@ -305,16 +305,16 @@ "refs": ["4c39423"] }, "operations/split_merge_tutorial_data/area_split_merge": { - "refs": ["8c5355a"] + "refs": ["2c807ca"] }, "operations/split_merge_tutorial_data/circle_split_merge": { - "refs": ["f205ff9"] + "refs": ["ddafb11"] }, "operations/split_merge_tutorial_data/line_split_merge": { - "refs": ["780edd6"] + "refs": ["eff2301"] }, "operations/split_merge_tutorial_data/rectangle_split_merge": { - "refs": ["c218798"] + "refs": ["5f5bb45"] }, "shorthands/column_shorthands": { "refs": ["01a9469"] @@ -461,13 +461,13 @@ "refs": ["7d026fc"] }, "web_content/analytical_operations/compare/area_polar_split": { - "refs": ["7fd64a3"] + "refs": ["ee41856"] }, "web_content/analytical_operations/compare/area_polar_stacked": { "refs": ["68c7e81"] }, "web_content/analytical_operations/compare/area_split_stacked": { - "refs": ["bf699c0"] + "refs": ["d9b4900"] }, "web_content/analytical_operations/compare/area_stacked": { "refs": ["8a34995"] @@ -476,16 +476,16 @@ "refs": ["d74c70f"] }, "web_content/analytical_operations/compare/column_groupped_1": { - "refs": ["ce66d34"] + "refs": ["4388cca"] }, "web_content/analytical_operations/compare/column_groupped_2": { - "refs": ["4ec1cee"] + "refs": ["362f392"] }, "web_content/analytical_operations/compare/column_split_stacked_1": { - "refs": ["648bfcb"] + "refs": ["f656048"] }, "web_content/analytical_operations/compare/column_split_stacked_2": { - "refs": ["982866a"] + "refs": ["8eb8fb0"] }, "web_content/analytical_operations/compare/column_stacked_1": { "refs": ["ed1ea56"] @@ -494,19 +494,19 @@ "refs": ["9704152"] }, "web_content/analytical_operations/compare/coxcomb_1": { - "refs": ["8b3d305"] + "refs": ["5e82a64"] }, "web_content/analytical_operations/compare/coxcomb_2": { "refs": ["3760392"] }, "web_content/analytical_operations/compare/line": { - "refs": ["7430ac6"] + "refs": ["3896128"] }, "web_content/analytical_operations/compare/line_polar": { - "refs": ["a7bec0e"] + "refs": ["2fa52c6"] }, "web_content/analytical_operations/compare/stream_stacked": { - "refs": ["a938ce6"] + "refs": ["1bc4de2"] }, "web_content/analytical_operations/compare/waterfall": { "refs": ["6c43732"] @@ -536,7 +536,7 @@ "refs": ["365c900"] }, "web_content/analytical_operations/distribute/existingmeasure_scatterplot_split": { - "refs": ["4416d3e"] + "refs": ["011f8ac"] }, "web_content/analytical_operations/distribute/existingmeasure_treemap_stacked": { "refs": ["24dc9e3"] @@ -545,13 +545,13 @@ "refs": ["a25a78e"] }, "web_content/analytical_operations/distribute/newmeasure_column_split_stacked": { - "refs": ["7cbba14"] + "refs": ["15cce51"] }, "web_content/analytical_operations/distribute/newmeasure_column_stacked": { "refs": ["facf971"] }, "web_content/analytical_operations/distribute/newmeasure_dotplot_1": { - "refs": ["0d49b62"] + "refs": ["56ad687"] }, "web_content/analytical_operations/distribute/newmeasure_dotplot_2": { "refs": ["082147a"] @@ -638,28 +638,28 @@ "refs": ["5ad66da"] }, "web_content/analytical_operations/split/area_polar_stacked": { - "refs": ["d83146e"] + "refs": ["eb79bdf"] }, "web_content/analytical_operations/split/area_stacked": { - "refs": ["857519e"] + "refs": ["8b9e1ad"] }, "web_content/analytical_operations/split/column_100percent_stacked": { - "refs": ["8b3ffda"] + "refs": ["863552b"] }, "web_content/analytical_operations/split/column_stacked": { - "refs": ["6295378"] + "refs": ["5abe72e"] }, "web_content/analytical_operations/split/coxcomb": { - "refs": ["f74e883"] + "refs": ["ddd904a"] }, "web_content/analytical_operations/split/radial_stacked": { "refs": ["7f5bc17"] }, "web_content/analytical_operations/split/scatterplot_1": { - "refs": ["73ca0bf"] + "refs": ["10ec52c"] }, "web_content/analytical_operations/split/scatterplot_2": { - "refs": ["2200420"] + "refs": ["f05b64a"] }, "web_content/analytical_operations/stretch_to_proportion/area_stacked": { "refs": ["8681c04"] @@ -668,7 +668,7 @@ "refs": ["c39a7bd"] }, "web_content/analytical_operations/stretch_to_proportion/column_split_stacked": { - "refs": ["b9b8f86"] + "refs": ["e53b0bc"] }, "web_content/analytical_operations/stretch_to_proportion/column_stacked": { "refs": ["9ad75d7"] @@ -680,13 +680,13 @@ "refs": ["2c78a47"] }, "web_content/analytical_operations/sum/area_polar_split": { - "refs": ["e5aac18"] + "refs": ["a7cd049"] }, "web_content/analytical_operations/sum/area_polar_stacked": { "refs": ["6f4d1f8"] }, "web_content/analytical_operations/sum/area_split": { - "refs": ["b453576"] + "refs": ["83f5b25"] }, "web_content/analytical_operations/sum/area_stacked": { "refs": ["9078a5a"] @@ -731,7 +731,7 @@ "refs": ["c84d593"] }, "web_content/analytical_operations/sum/column_split_stacked": { - "refs": ["2c796ae"] + "refs": ["0340969"] }, "web_content/analytical_operations/sum/column_stacked_1": { "refs": ["3396093"] @@ -746,7 +746,7 @@ "refs": ["f8eee6c"] }, "web_content/analytical_operations/sum/coxcomb_split": { - "refs": ["3791909"] + "refs": ["a671c22"] }, "web_content/analytical_operations/sum/dotplot": { "refs": ["966a4e8"] @@ -770,7 +770,7 @@ "refs": ["4e1f1e8"] }, "web_content/analytical_operations/sum/stream_stacked": { - "refs": ["165e7dc"] + "refs": ["60f9e3a"] }, "web_content/analytical_operations/sum/treemap": { "refs": ["bfa16c8"] @@ -782,13 +782,13 @@ "refs": ["b2b0648"] }, "web_content_removed/animated/composition_percentage_area_stream_3dis_1con": { - "refs": ["3735590"] + "refs": ["2860680"] }, "web_content_removed/animated/composition_percentage_column_3dis_1con": { - "refs": ["2cc5f01"] + "refs": ["3601146"] }, "web_content_removed/animated/composition_percentage_column_stream_3dis_1con": { - "refs": ["8bd46e2"] + "refs": ["b46f65f"] }, "web_content_removed/animated/distribution_relationship_dotplot_dotplot": { "refs": ["d005bda"] @@ -800,10 +800,10 @@ "refs": ["8a45f1d"] }, "web_content_removed/animated/merge_split_area_stream_3dis_1con": { - "refs": ["b7744ef"] + "refs": ["0579d95"] }, "web_content_removed/animated/merge_split_bar": { - "refs": ["d95ae70"] + "refs": ["d720787"] }, "web_content_removed/animated/merge_split_radial_stacked_rectangle_2dis_1con": { "refs": ["dd1e39d"] @@ -860,7 +860,7 @@ "refs": ["205401d"] }, "web_content/infinite": { - "refs": ["283c824"] + "refs": ["331494a"] }, "web_content/presets/chart/column": { "refs": ["4f73d47"] @@ -872,7 +872,7 @@ "refs": ["116901e"] }, "web_content/presets/chart/column_splitted": { - "refs": ["84258ff"] + "refs": ["89ef0a6"] }, "web_content/presets/chart/column_percentage": { "refs": ["be20c3e"] @@ -896,7 +896,7 @@ "refs": ["ba6b634"] }, "web_content/presets/chart/bar_splitted": { - "refs": ["51c12b4"] + "refs": ["a1986ae"] }, "web_content/presets/chart/bar_percentage": { "refs": ["cfd480a"] @@ -920,7 +920,7 @@ "refs": ["018ddbc"] }, "web_content/presets/chart/area_splitted": { - "refs": ["b824907"] + "refs": ["e49a67b"] }, "web_content/presets/graph/stream": { "refs": ["24b7673"] @@ -929,10 +929,10 @@ "refs": ["f675019"] }, "web_content/presets/graph/violin": { - "refs": ["e149eaf"] + "refs": ["448d031"] }, "web_content/presets/graph/violin_vertical": { - "refs": ["250a499"] + "refs": ["15e5d8b"] }, "web_content/presets/chart/line": { "refs": ["6ce0fa0"] @@ -1205,13 +1205,13 @@ "refs": ["059e2c7"] }, "ww_animTiming/descartes_orientation/03_d-d_o_a-r-a_split": { - "refs": ["90d561a"] + "refs": ["85e708c"] }, "ww_animTiming/descartes_orientation/04_d-d_o_l-r-l": { "refs": ["96218ea"] }, "ww_animTiming/descartes_orientation/04_d-d_o_l-r-l_stacked": { - "refs": ["0dedf8a"] + "refs": ["b9d4386"] }, "ww_animTiming/descartes_orientation/05_d-d_o_r-c-r": { "refs": ["7360223"] @@ -1538,13 +1538,13 @@ "refs": ["9b65e14"] }, "ww_animTiming_TESTS/descartes_orientation/03_d-d_o_a-r-a_split": { - "refs": ["cf4094c"] + "refs": ["44b714a"] }, "ww_animTiming_TESTS/descartes_orientation/04_d-d_o_l-r-l": { "refs": ["d1b4afe"] }, "ww_animTiming_TESTS/descartes_orientation/04_d-d_o_l-r-l_stacked": { - "refs": ["10b62af"] + "refs": ["376117e"] }, "ww_animTiming_TESTS/descartes_orientation/05_d-d_o_r-c-r": { "refs": ["b2045df"] @@ -1757,25 +1757,25 @@ "refs": ["37f0b4b"] }, "ww_next_steps/next_steps/04_C_R": { - "refs": ["b31a5a5"] + "refs": ["56e1367"] }, "ww_next_steps/next_steps/05_C_R": { - "refs": ["b220986"] + "refs": ["bc2b2bb"] }, "ww_next_steps/next_steps/21_C_C_dotplot": { - "refs": ["be7bac7"] + "refs": ["3b9e03b"] }, "ww_next_steps/next_steps/22_C_C": { - "refs": ["c99f101"] + "refs": ["b32c6f0"] }, "ww_next_steps/next_steps/28_C_A": { - "refs": ["7ddc5a4"] + "refs": ["fad0e20"] }, "ww_next_steps/next_steps/35_C_A_violin": { - "refs": ["8184b1f"] + "refs": ["2be8882"] }, "ww_next_steps/next_steps/38_C_L_line": { - "refs": ["dd7bb57"] + "refs": ["514124d"] }, "ww_next_steps/next_steps_Tests/02_C_R": { "refs": ["2c12152"] @@ -1787,22 +1787,22 @@ "refs": ["e5e38b9"] }, "ww_next_steps/next_steps_Tests/04_C_R": { - "refs": ["f402f8a"] + "refs": ["93cf681"] }, "ww_next_steps/next_steps_Tests/05_C_R": { - "refs": ["3a32941"] + "refs": ["b06a411"] }, "ww_next_steps/next_steps_Tests/21_C_C_dotplot": { - "refs": ["4340228"] + "refs": ["3b0a653"] }, "ww_next_steps/next_steps_Tests/22_C_C": { - "refs": ["d5b3c1f"] + "refs": ["2f2eac1"] }, "ww_next_steps/next_steps_Tests/28_C_A": { - "refs": ["17a4056"] + "refs": ["8f76348"] }, "ww_next_steps/next_steps_Tests/38_C_L_line": { - "refs": ["e97795b"] + "refs": ["406aa18"] }, "ww_next_steps/next_steps_Tests/axisLabel_problem": { "refs": ["6e22ebb"] @@ -1820,13 +1820,13 @@ "refs": ["52d3608"] }, "ww_next_steps/next_steps_byOperations/compare/comparison_05": { - "refs": ["9b0d6e6"] + "refs": ["e291cb3"] }, "ww_next_steps/next_steps_byOperations/compare/comparison_06": { - "refs": ["f2811e0"] + "refs": ["6221b93"] }, "ww_next_steps/next_steps_byOperations/compare/comparison_09": { - "refs": ["6be8296"] + "refs": ["b87249d"] }, "ww_next_steps/next_steps_byOperations/compare/comparison_10": { "refs": ["d7882c8"] @@ -1835,25 +1835,25 @@ "refs": ["c227840"] }, "ww_next_steps/next_steps_byOperations/components/components_01": { - "refs": ["0a8b12c"] + "refs": ["1d80493"] }, "ww_next_steps/next_steps_byOperations/components/components_02": { - "refs": ["bb80f7f"] + "refs": ["0fb9d3d"] }, "ww_next_steps/next_steps_byOperations/components/components_03": { - "refs": ["c15ea98"] + "refs": ["547b49d"] }, "ww_next_steps/next_steps_byOperations/components/components_04": { - "refs": ["584e2a2"] + "refs": ["bf76476"] }, "ww_next_steps/next_steps_byOperations/components/components_05": { - "refs": ["8eb3d42"] + "refs": ["634189b"] }, "ww_next_steps/next_steps_byOperations/components/components_06": { - "refs": ["b449fc6"] + "refs": ["48c2503"] }, "ww_next_steps/next_steps_byOperations/components/components_07": { - "refs": ["b4c76b1"] + "refs": ["071bc63"] }, "ww_next_steps/next_steps_byOperations/distribute/distribution_01": { "refs": ["f89236a"] @@ -1868,16 +1868,16 @@ "refs": ["f9ee7a4"] }, "ww_next_steps/next_steps_byOperations/distribute/distribution_05": { - "refs": ["9ba32b8"] + "refs": ["b375722"] }, "ww_next_steps/next_steps_byOperations/distribute/distribution_06": { - "refs": ["a97aa8c"] + "refs": ["18fc830"] }, "ww_next_steps/next_steps_byOperations/distribute/distribution_07": { "refs": ["c1a4283"] }, "ww_next_steps/next_steps_byOperations/distribute/distribution_08": { - "refs": ["be93690"] + "refs": ["0832835"] }, "ww_next_steps/next_steps_byOperations/drilldown/drilldown_01": { "refs": ["277fa16"] @@ -1922,7 +1922,7 @@ "refs": ["334220e"] }, "ww_next_steps/next_steps_byOperations/ratio/ratio_03": { - "refs": ["b2c932f"] + "refs": ["4b0bfe2"] }, "ww_next_steps/next_steps_byOperations/ratio/ratio_04": { "refs": ["04e508f"] @@ -1937,7 +1937,7 @@ "refs": ["8095c4a"] }, "ww_next_steps/next_steps_byOperations/remove/remove_03": { - "refs": ["3e45a82"] + "refs": ["fde6d71"] }, "ww_next_steps/next_steps_byOperations/remove/remove_04": { "refs": ["2406eab"] @@ -1976,7 +1976,7 @@ "refs": ["ea1d10f"] }, "ww_next_steps/next_steps_byOperations/sum_aggregate/sum_aggregate_10": { - "refs": ["b1a68f4"] + "refs": ["6336a69"] }, "ww_next_steps/next_steps_byOperations/sum_aggregate/sum_aggregate_11": { "refs": ["3ac4f8c"] @@ -1997,7 +1997,7 @@ "refs": ["1e1c654"] }, "ww_next_steps/next_steps_byOperations/sum_aggregate/sum_aggregate_18": { - "refs": ["aedc373"] + "refs": ["877a268"] }, "ww_next_steps/next_steps_byOperations/sum_aggregate/sum_aggregate_19": { "refs": ["1468471"] @@ -2291,7 +2291,7 @@ "refs": ["d676cb2"] }, "ww_noFade/wNoFade_Tests/2_des_pol-without/area-rectangle/10_d-w_are_temporal_bubble": { - "refs": ["c6f3677"] + "refs": ["4f9a69c"] }, "ww_noFade/wNoFade_Tests/2_des_pol-without/area/03_d-w_are": { "refs": ["207f46e"] @@ -2453,7 +2453,7 @@ "refs": ["e5678fa"] }, "ww_noFade/wNoFade_Tests/Marker_transition_problem/area_column_time_sum": { - "refs": ["ce2af48"] + "refs": ["f09c183"] }, "ww_noFade/wNoFade_Tests/Marker_transition_problem/area_orientation": { "refs": ["8c0d580"] @@ -2615,7 +2615,7 @@ "refs": ["e1bbbe9"] }, "ww_noFade/wNoFade_cases/1_des_pol/rectangle/09_rec_TemporalDistribution": { - "refs": ["6d6ac0a"] + "refs": ["8c5d1bb"] }, "ww_noFade/wNoFade_cases/1_des_pol/rectangle_V1/05b_rec_2c_V1": { "refs": ["017ef35"] @@ -2660,7 +2660,7 @@ "refs": ["96441e2"] }, "ww_noFade/wNoFade_cases/2_des_pol-without/area-rectangle/10_d-w_are_temporal_bubble": { - "refs": ["f6b34c1"] + "refs": ["7773f5b"] }, "ww_noFade/wNoFade_cases/2_des_pol-without/area/03_d-w_are": { "refs": ["a1b0278"] @@ -2678,7 +2678,7 @@ "refs": ["07a2162"] }, "ww_noFade/wNoFade_cases/2_des_pol-without/area/10_d-w_are_temporal_bubble": { - "refs": ["9675022"] + "refs": ["625cddf"] }, "ww_noFade/wNoFade_cases/2_des_pol-without/area_V1/03_d-w_are_V1": { "refs": ["965630f"] @@ -2987,7 +2987,7 @@ "refs": ["116901e"] }, "ww_samples_for_presets/cartesian_coo_sys/05_C_R_split_column_chart": { - "refs": ["a3de9d1"] + "refs": ["7f622fb"] }, "ww_samples_for_presets/cartesian_coo_sys/06_C_R_100_stacked_column_chart": { "refs": ["7c3feaa"] @@ -3023,7 +3023,7 @@ "refs": ["ba6b634"] }, "ww_samples_for_presets/cartesian_coo_sys/16_C_R_splitted_bar_chart": { - "refs": ["f8b027b"] + "refs": ["aa36a69"] }, "ww_samples_for_presets/cartesian_coo_sys/17_C_R_100_stacked_bar_chart": { "refs": ["0f0f014"] @@ -3062,7 +3062,7 @@ "refs": ["a745467"] }, "ww_samples_for_presets/cartesian_coo_sys/31_C_A_splitted_area_chart": { - "refs": ["c388671"] + "refs": ["3e301a8"] }, "ww_samples_for_presets/cartesian_coo_sys/32_C_A_stream_graph": { "refs": ["f4d215c"] @@ -3071,10 +3071,10 @@ "refs": ["f128560"] }, "ww_samples_for_presets/cartesian_coo_sys/34_C_A_violin_graph": { - "refs": ["6b5fac8"] + "refs": ["17ec530"] }, "ww_samples_for_presets/cartesian_coo_sys/35_C_A_violin_graph_vert": { - "refs": ["579646a"] + "refs": ["35fe511"] }, "ww_samples_for_presets/cartesian_coo_sys/36_C_A_range_area_chart": { "refs": ["a17416d"] diff --git a/test/e2e/tests/docs.json b/test/e2e/tests/docs.json index 7e3e83c0b..e199545da 100644 --- a/test/e2e/tests/docs.json +++ b/test/e2e/tests/docs.json @@ -44,7 +44,7 @@ "refs": ["981e902"] }, "orientation_split_polar": { - "refs": ["00c4ea3"] + "refs": ["3f79f32"] }, "shorthands_store": { "refs": ["df4002a"] diff --git a/test/e2e/tests/fixes.json b/test/e2e/tests/fixes.json index 1535d0a81..1315406ed 100644 --- a/test/e2e/tests/fixes.json +++ b/test/e2e/tests/fixes.json @@ -8,7 +8,7 @@ "refs": ["1732a49"] }, "143": { - "refs": ["816136d"] + "refs": ["5594d09"] }, "144": { "refs": ["fde02e4"] diff --git a/test/e2e/tests/style_tests.json b/test/e2e/tests/style_tests.json index 9936fa2aa..3398387dd 100644 --- a/test/e2e/tests/style_tests.json +++ b/test/e2e/tests/style_tests.json @@ -356,7 +356,7 @@ "refs": ["bcfbd92"] }, "plot/spacing": { - "refs": ["598a9fc"] + "refs": ["a464984"] }, "plot/xAxis/color/hexa/animated_yellowCustom_0.25-blueCustom_0.75": { "refs": ["77b26be"] diff --git a/test/e2e/tests/tickets.json b/test/e2e/tests/tickets.json index 177dd0c62..9892fb628 100644 --- a/test/e2e/tests/tickets.json +++ b/test/e2e/tests/tickets.json @@ -11,7 +11,7 @@ "refs": ["1928a0a"] }, "146": { - "refs": ["03052cb"] + "refs": ["d58fde8"] }, "255": { "refs": ["29b4a25"]