Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Axis refactor v13b - Multiple origo #630

Open
wants to merge 9 commits into
base: axis_refactor_v13
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@

- Separate Channel properties to AxisChannel properties at config.
- Channels 'set' rewrite doesn't clear AxisChannel properties.
- Split charts
- axis line multiplication.
- axis labels multiplication.
- axis range interpretation differently for all split part.
- negative values are handled correctly.
- align center / stretch fix.

### Added

Expand Down
3 changes: 2 additions & 1 deletion src/base/math/range.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ template <std::floating_point T = double> struct Range

[[nodiscard]] bool includes(const T &value) const
{
return !less(value, min) && !less(max, value);
return !is_lt(std::weak_order(value, min))
&& !is_lt(std::weak_order(max, value));
}

[[nodiscard]] T rescale(const T &value, T def = 0.5) const
Expand Down
152 changes: 106 additions & 46 deletions src/chart/generator/axis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,8 @@ interpolate(const SplitAxis &op0, const SplitAxis &op1, double factor)
interpolate(static_cast<const Axis &>(op0),
static_cast<const Axis &>(op1),
factor);
if (!op0.parts.empty() && !op1.parts.empty()) {
if (!op0.parts.empty() && !op1.parts.empty()
&& op0.seriesName() == op1.seriesName()) {
using PartPair = const decltype(res.parts)::value_type;
Alg::union_foreach(
op0.parts,
Expand All @@ -360,69 +361,128 @@ interpolate(const SplitAxis &op0, const SplitAxis &op1, double factor)
switch (type) {
case Alg::union_call_t::only_left: {
auto from = lhs->second.range.min;
res.parts[lhs->first] = {
.weight = interpolate(lhs->second.weight,
0.0,
factor),
.range = interpolate(lhs->second.range,
Math::Range<>{from, from},
factor)};
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[rhs->first] = {
.weight = interpolate(0.0,
rhs->second.weight,
factor),
.range =
interpolate(Math::Range<>{from, from},
rhs->second.range,
factor)};
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[lhs->first] =
interpolate(lhs->second, rhs->second, factor);
res.parts.insert({lhs->first,
interpolate(lhs->second,
rhs->second,
factor)});
break;
}
}
},
res.parts.value_comp());

return res;
}
else if (!op0.parts.empty()) {
auto begin = op0.parts.begin();
res.parts[begin->first] = {
.weight = interpolate(begin->second.weight, 1.0, factor),
.range = interpolate(begin->second.range,
Math::Range<>{0, 1},
factor)};
while (++begin != op0.parts.end()) {
res.parts[begin->first] = {
.weight =
interpolate(begin->second.weight, 0.0, factor),
.range = interpolate(begin->second.range,
Math::Range<>{0, 1},
factor)};

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()) {
auto begin = op1.parts.begin();
res.parts[begin->first] = {
.weight = interpolate(1.0, begin->second.weight, factor),
.range = interpolate(Math::Range<>{0, 1},
begin->second.range,
factor)};
while (++begin != op1.parts.end()) {
res.parts[begin->first] = {
.weight =
interpolate(0.0, begin->second.weight, factor),
.range = interpolate(Math::Range<>{0, 1},
begin->second.range,
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)}});
}
}
}
else if (!op0.parts.empty()
&& op0.seriesName() != op1.seriesName())
res.parts.insert({std::nullopt, {.weight = factor}});

return res;
}
Expand Down
4 changes: 3 additions & 1 deletion src/chart/generator/axis.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,12 +202,14 @@ struct SplitAxis : Axis
{
double weight{1.0};
Math::Range<> range{0, 1};
Math::Range<> measureRange{0, 1};

[[nodiscard]] bool operator==(
const Part &other) const = default;
};

using Parts = std::map<std::size_t, Part>;
using Parts =
std::multimap<std::optional<Data::SliceIndex>, Part>;
Parts parts;

[[nodiscard]] bool operator==(
Expand Down
Loading