11#include " axis.h"
22
3+ #include < __compare/compare_three_way.h>
34#include < algorithm>
45#include < cmath>
6+ #include < compare>
7+ #include < cstddef>
58#include < cstdint>
69#include < functional>
710#include < limits>
@@ -46,7 +49,10 @@ void Axises::addLegendInterpolation(double legendFactor,
4649 && target.measure .enabled .get ())
4750 || (!source.dimension .empty ()
4851 && !target.dimension .empty ()))
49- && source.seriesName () != target.seriesName ()) {
52+ && source.seriesName () != target.seriesName ()
53+ && !DimensionAxis::commonDimensionParts (
54+ source.dimension .getValues (),
55+ target.dimension .getValues ())) {
5056 if (!leftLegend[0 ]) leftLegend[0 ].emplace (legendType);
5157 if (!leftLegend[1 ]) leftLegend[1 ].emplace (legendType);
5258
@@ -67,8 +73,11 @@ void Axises::addLegendInterpolation(double legendFactor,
6773 leftLegend[0 ] && leftLegend[1 ]
6874 && leftLegend[0 ]->interpolated
6975 == leftLegend[1 ]->interpolated
70- && leftLegend[0 ]->calc .seriesName ()
71- == leftLegend[1 ]->calc .seriesName ();
76+ && (leftLegend[0 ]->calc .seriesName ()
77+ == leftLegend[1 ]->calc .seriesName ()
78+ || DimensionAxis::commonDimensionParts (
79+ leftLegend[0 ]->calc .dimension .getValues (),
80+ leftLegend[1 ]->calc .dimension .getValues ()));
7281 sameInterpolated && !leftLegend[0 ]->calc .dimension .empty ()
7382 && !leftLegend[1 ]->calc .dimension .empty ()) {
7483
@@ -100,6 +109,19 @@ Geom::Point Axises::origo() const
100109 return {at (AxisId::x).measure .origo (),
101110 at (AxisId::y).measure .origo ()};
102111}
112+ std::size_t DimensionAxis::commonDimensionParts (const Values &lhs,
113+ const Values &rhs)
114+ {
115+ return lhs.empty () || rhs.empty ()
116+ ? 0
117+ : std::ranges::mismatch (lhs.begin ()->first ,
118+ rhs.begin ()->first ,
119+ [](const auto &lhsItem, const auto &rhsItem)
120+ {
121+ return lhsItem.column == rhsItem.column ;
122+ }).in1
123+ - lhs.begin ()->first .begin ();
124+ }
103125
104126MeasureAxis::MeasureAxis (const Math::Range<> &interval,
105127 std::string &&series,
@@ -242,7 +264,7 @@ MeasureAxis interpolate(const MeasureAxis &op0,
242264
243265 return res;
244266}
245- bool DimensionAxis::add (const Data::SliceIndex &index,
267+ bool DimensionAxis::add (const std::vector< Data::SliceIndex> &index,
246268 const Math::Range<> &range,
247269 std::uint32_t position,
248270 const std::optional<ColorBase> &color,
@@ -302,27 +324,57 @@ DimensionAxis interpolate(const DimensionAxis &op0,
302324 factor));
303325 using Val = DimensionAxis::Values::value_type;
304326
327+ std::size_t commonSize =
328+ DimensionAxis::commonDimensionParts (op0.getValues (),
329+ op1.getValues ());
330+ std::size_t maxSize = std::max (
331+ op0.values .empty () ? 0 : op0.values .begin ()->first .size (),
332+ op1.values .empty () ? 0 : op1.values .begin ()->first .size ());
333+
305334 const Val *latest1{};
306335 const Val *latest2{};
307336
308- auto merger = [&](const Val &lhs, const Val &rhs) -> Val
337+ auto merger = [&](const Val &lhs,
338+ const Val &rhs,
339+ const Val::first_type *key = nullptr ) -> Val
340+ {
341+ printf (" %s to %s\n " ,
342+ DimensionAxis::mergedLabels (lhs.first ).c_str (),
343+ DimensionAxis::mergedLabels (rhs.first ).c_str ());
344+ return {key ? *key : lhs.first ,
345+ interpolate (lhs.second , rhs.second , factor)};
346+ };
347+
348+ auto needMerge = [&](const Val &lhs, const Val &rhs)
309349 {
310350 latest1 = std::addressof (lhs);
311351 latest2 = std::addressof (rhs);
312- return {lhs.first ,
313- interpolate (lhs.second , rhs.second , factor)};
352+ return commonSize == maxSize || commonSize == 0 ;
353+ };
354+
355+ auto comparator = [&](const auto &lhs, const auto &rhs)
356+ {
357+ if (commonSize == maxSize || commonSize == 0 )
358+ return std::compare_three_way{}(lhs, rhs);
359+ return std::lexicographical_compare_three_way (lhs.begin (),
360+ lhs.begin () + commonSize,
361+ rhs.begin (),
362+ rhs.begin () + commonSize);
314363 };
315364
316365 auto &&one_side =
317- [&merger ](bool first,
366+ [&](bool first,
318367 DimensionAxis::Item::PosType DimensionAxis::Item::*pos,
319368 const Val *¶mOther)
320369 {
321370 return [&, first, pos](const Val &val) -> Val
322371 {
323- if (paramOther && paramOther->first == val.first ) {
324- auto &&res = first ? merger (val, *paramOther)
325- : merger (*paramOther, val);
372+ if (paramOther
373+ && std::is_eq (
374+ comparator (paramOther->first , val.first ))) {
375+ auto &&res = first
376+ ? merger (val, *paramOther)
377+ : merger (*paramOther, val, &val.first );
326378 (res.second .*pos).makeAuto ();
327379 return res;
328380 }
@@ -334,11 +386,13 @@ DimensionAxis interpolate(const DimensionAxis &op0,
334386 op1.values ,
335387 res.values ,
336388 Alg::merge_args{.projection = &Val::first,
389+ .comparator = comparator,
337390 .transformer_1 =
338391 one_side (true , &DimensionAxis::Item::endPos, latest2),
339392 .transformer_2 = one_side (false ,
340393 &DimensionAxis::Item::startPos,
341394 latest1),
395+ .need_merge = needMerge,
342396 .merger = merger});
343397
344398 return res;
@@ -438,7 +492,7 @@ interpolate(const SplitAxis &op0, const SplitAxis &op1, double factor)
438492 }
439493 else
440494 res.parts
441- .insert ({std:: nullopt ,
495+ .insert ({{} ,
442496 {.weight =
443497 op0.parts .empty () ? 1 - factor : factor}})
444498 ->second .unique = true ;
0 commit comments