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 v1 #589

Merged
merged 8 commits into from
Oct 18, 2024
Merged
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
4 changes: 1 addition & 3 deletions src/base/conv/numtostr.cpp
Original file line number Diff line number Diff line change
@@ -51,9 +51,7 @@ std::string NumberToString::convert(double number)
}

if (number_view.starts_with('-')
&& number_view.find_last_not_of(std::string_view{
std::initializer_list<char>{'0', ',', '.', '\0'}})
== 0) {
&& number_view.find_last_not_of("0,.") == 0) {
number_view.remove_prefix(1);
++begin;
--decimalPoint;
128 changes: 61 additions & 67 deletions src/chart/animator/morph.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "morph.h"

#include <concepts>
#include <memory>
#include <stdexcept>

@@ -16,7 +17,51 @@
namespace Vizzu::Anim::Morph
{

using Math::interpolate;
template <class T> struct interpolatable_t
{
constexpr bool operator()() const
{
using Math::interpolate;
return requires(const T &a, const T &b, double factor) {
{
interpolate(a, b, factor)
} -> std::same_as<T>;
};
}
};

template <class T> concept interpolatable = interpolatable_t<T>{}();

struct interpolate_t
{
template <class T>
constexpr T
operator()(const T &a, const T &b, double factor) const;
};

constexpr inline static interpolate_t interpolate{};

template <class T>
constexpr T
interpolate_t::operator()(const T &a, const T &b, double factor) const
{
if constexpr (interpolatable<T>) {
using Math::interpolate;
return interpolate(a, b, factor);
}
else {
T res;
Refl::visit(
[factor]<class V>(V &res, const V &op0, const V &op1)
{
res = Morph::interpolate(op0, op1, factor);
},
res,
a,
b);
return res;
}
}

AbstractMorph::AbstractMorph(const Gen::Plot &source,
const Gen::Plot &target,
@@ -116,19 +161,9 @@ void Horizontal::transform(const Gen::Plot &source,
Gen::Plot &actual,
double factor) const
{
actual.axises.at(Gen::ChannelId::x).common =
interpolate(source.axises.at(Gen::ChannelId::x).common,
target.axises.at(Gen::ChannelId::x).common,
factor);

actual.axises.at(Gen::ChannelId::x).measure =
interpolate(source.axises.at(Gen::ChannelId::x).measure,
target.axises.at(Gen::ChannelId::x).measure,
factor);

actual.axises.at(Gen::ChannelId::x).dimension =
interpolate(source.axises.at(Gen::ChannelId::x).dimension,
target.axises.at(Gen::ChannelId::x).dimension,
actual.axises.at(Gen::AxisId::x) =
interpolate(source.axises.at(Gen::AxisId::x),
target.axises.at(Gen::AxisId::x),
factor);

actual.keepAspectRatio = interpolate(source.keepAspectRatio,
@@ -191,34 +226,14 @@ void Vertical::transform(const Gen::Plot &source,
Gen::Plot &actual,
double factor) const
{
actual.axises.at(Gen::ChannelId::y).common =
interpolate(source.axises.at(Gen::ChannelId::y).common,
target.axises.at(Gen::ChannelId::y).common,
actual.axises.at(Gen::AxisId::y) =
interpolate(source.axises.at(Gen::AxisId::y),
target.axises.at(Gen::AxisId::y),
factor);

actual.axises.at(Gen::ChannelId::y).measure =
interpolate(source.axises.at(Gen::ChannelId::y).measure,
target.axises.at(Gen::ChannelId::y).measure,
factor);

actual.axises.at(Gen::ChannelId::y).dimension =
interpolate(source.axises.at(Gen::ChannelId::y).dimension,
target.axises.at(Gen::ChannelId::y).dimension,
factor);

actual.axises.at(Gen::ChannelId::size).common =
interpolate(source.axises.at(Gen::ChannelId::size).common,
target.axises.at(Gen::ChannelId::size).common,
factor);

actual.axises.at(Gen::ChannelId::size).measure =
interpolate(source.axises.at(Gen::ChannelId::size).measure,
target.axises.at(Gen::ChannelId::size).measure,
factor);

actual.axises.at(Gen::ChannelId::size).dimension =
interpolate(source.axises.at(Gen::ChannelId::size).dimension,
target.axises.at(Gen::ChannelId::size).dimension,
actual.axises.at(Gen::ChannelId::size) =
interpolate(source.axises.at(Gen::ChannelId::size),
target.axises.at(Gen::ChannelId::size),
factor);

actual.guides.y =
@@ -250,35 +265,14 @@ void Morph::Color::transform(const Gen::Plot &source,
Gen::Plot &actual,
double factor) const
{
actual.axises.at(Gen::ChannelId::color).common =
interpolate(source.axises.at(Gen::ChannelId::color).common,
target.axises.at(Gen::ChannelId::color).common,
actual.axises.at(Gen::ChannelId::color) =
interpolate(source.axises.at(Gen::ChannelId::color),
target.axises.at(Gen::ChannelId::color),
factor);

actual.axises.at(Gen::ChannelId::color).measure =
interpolate(source.axises.at(Gen::ChannelId::color).measure,
target.axises.at(Gen::ChannelId::color).measure,
factor);

actual.axises.at(Gen::ChannelId::color).dimension =
interpolate(source.axises.at(Gen::ChannelId::color).dimension,
target.axises.at(Gen::ChannelId::color).dimension,
factor);

actual.axises.at(Gen::ChannelId::lightness).common = interpolate(
source.axises.at(Gen::ChannelId::lightness).common,
target.axises.at(Gen::ChannelId::lightness).common,
factor);

actual.axises.at(Gen::ChannelId::lightness).measure = interpolate(
source.axises.at(Gen::ChannelId::lightness).measure,
target.axises.at(Gen::ChannelId::lightness).measure,
factor);

actual.axises.at(Gen::ChannelId::lightness).dimension =
interpolate(
source.axises.at(Gen::ChannelId::lightness).dimension,
target.axises.at(Gen::ChannelId::lightness).dimension,
actual.axises.at(Gen::ChannelId::lightness) =
interpolate(source.axises.at(Gen::ChannelId::lightness),
target.axises.at(Gen::ChannelId::lightness),
factor);
}

51 changes: 10 additions & 41 deletions src/chart/animator/planner.cpp
Original file line number Diff line number Diff line change
@@ -352,28 +352,11 @@ bool Planner::positionMorphNeeded() const
bool Planner::needColor() const
{
return (isAnyLegend(Gen::ChannelId::color)
&& (source->axises.at(Gen::ChannelId::color).common
!= target->axises.at(Gen::ChannelId::color)
.common
|| source->axises.at(Gen::ChannelId::color)
.dimension
!= target->axises.at(Gen::ChannelId::color)
.dimension
|| source->axises.at(Gen::ChannelId::color).measure
!= target->axises.at(Gen::ChannelId::color)
.measure))
&& source->axises.at(Gen::ChannelId::color)
!= target->axises.at(Gen::ChannelId::color))
|| (isAnyLegend(Gen::ChannelId::lightness)
&& (source->axises.at(Gen::ChannelId::lightness).common
!= target->axises.at(Gen::ChannelId::lightness)
.common
|| source->axises.at(Gen::ChannelId::lightness)
.dimension
!= target->axises.at(Gen::ChannelId::lightness)
.dimension
|| source->axises.at(Gen::ChannelId::lightness)
.measure
!= target->axises.at(Gen::ChannelId::lightness)
.measure))
&& source->axises.at(Gen::ChannelId::lightness)
!= target->axises.at(Gen::ChannelId::lightness))
|| anyMarker(+[](const Gen::Marker &source,
const Gen::Marker &target) -> bool
{
@@ -419,23 +402,13 @@ bool Planner::verticalBeforeHorizontal() const

bool Planner::needVertical() const
{
return source->axises.at(Gen::ChannelId::y).common
!= target->axises.at(Gen::ChannelId::y).common
|| source->axises.at(Gen::ChannelId::y).measure
!= target->axises.at(Gen::ChannelId::y).measure
|| source->axises.at(Gen::ChannelId::y).dimension
!= target->axises.at(Gen::ChannelId::y).dimension
return source->axises.at(Gen::AxisId::y)
!= target->axises.at(Gen::AxisId::y)
|| source->guides.at(Gen::AxisId::y)
!= target->guides.at(Gen::AxisId::y)
|| (isAnyLegend(Gen::ChannelId::size)
&& (source->axises.at(Gen::ChannelId::size).common
!= target->axises.at(Gen::ChannelId::size).common
|| source->axises.at(Gen::ChannelId::size).measure
!= target->axises.at(Gen::ChannelId::size)
.measure
|| source->axises.at(Gen::ChannelId::size).dimension
!= target->axises.at(Gen::ChannelId::size)
.dimension))
&& source->axises.at(Gen::ChannelId::size)
!= target->axises.at(Gen::ChannelId::size))
|| (source->markerConnectionOrientation
!= target->markerConnectionOrientation
&& (source->markerConnectionOrientation.value_or(
@@ -465,12 +438,8 @@ bool Planner::needVertical() const

bool Planner::needHorizontal() const
{
return source->axises.at(Gen::ChannelId::x).common
!= target->axises.at(Gen::ChannelId::x).common
|| source->axises.at(Gen::ChannelId::x).measure
!= target->axises.at(Gen::ChannelId::x).measure
|| source->axises.at(Gen::ChannelId::x).dimension
!= target->axises.at(Gen::ChannelId::x).dimension
return source->axises.at(Gen::AxisId::x)
!= target->axises.at(Gen::AxisId::x)
|| source->guides.at(Gen::AxisId::x)
!= target->guides.at(Gen::AxisId::x)
|| source->keepAspectRatio != target->keepAspectRatio
18 changes: 2 additions & 16 deletions src/chart/generator/axis.cpp
Original file line number Diff line number Diff line change
@@ -22,17 +22,10 @@
namespace Vizzu::Gen
{

CommonAxis interpolate(const CommonAxis &op0,
const CommonAxis &op1,
double factor)
{
return {interpolate(op0.title, op1.title, factor)};
}

Geom::Point Axises::origo() const
{
return {at(ChannelId::x).measure.origo(),
at(ChannelId::y).measure.origo()};
return {at(AxisId::x).measure.origo(),
at(AxisId::y).measure.origo()};
}

MeasureAxis::MeasureAxis(Math::Range<double> interval,
@@ -64,8 +57,6 @@ double MeasureAxis::origo() const
return -range.getMin() / range.size();
}

void MeasureAxis::track(double value) { trackedRange.include(value); }

MeasureAxis interpolate(const MeasureAxis &op0,
const MeasureAxis &op1,
double factor)
@@ -240,11 +231,6 @@ bool DimensionAxis::setLabels(double step)
return hasLabel;
}

void DimensionAxis::track(const Data::MarkerId &id)
{
(*trackedValues)[id.itemId] = id.label;
}

DimensionAxis interpolate(const DimensionAxis &op0,
const DimensionAxis &op1,
double factor)
39 changes: 25 additions & 14 deletions src/chart/generator/axis.h
Original file line number Diff line number Diff line change
@@ -16,20 +16,34 @@

namespace Vizzu::Gen
{
struct CommonAxis

struct ChannelStats
{
::Anim::String title;
using TrackType = std::variant<Math::Range<double>,
std::vector<std::optional<Data::SliceIndex>>>;

[[nodiscard]] bool operator==(const CommonAxis &) const = default;
};
Refl::EnumArray<ChannelId, TrackType> tracked;

CommonAxis interpolate(const CommonAxis &op0,
const CommonAxis &op1,
double factor);
void track(ChannelId at, const Data::MarkerId &id)
{
auto &vec = std::get<1>(tracked.at(at));
vec[id.itemId] = id.label;
}

void track(ChannelId at, const double &value)
{
std::get<0>(tracked.at(at)).include(value);
}

void setIfRange(AxisId at, const Math::Range<double> &range)
{
if (auto *r = std::get_if<0>(&tracked.at(asChannel(at))))
*r = range;
}
};

struct MeasureAxis
{
Math::Range<double> trackedRange;
::Anim::Interpolated<bool> enabled{false};
Math::Range<double> range = Math::Range<double>::Raw(0, 1);
::Anim::String unit;
@@ -42,8 +56,6 @@ struct MeasureAxis
std::optional<double> step);
bool operator==(const MeasureAxis &other) const;
[[nodiscard]] double origo() const;

void track(double value);
};

MeasureAxis interpolate(const MeasureAxis &op0,
@@ -103,8 +115,6 @@ struct DimensionAxis

bool enabled{false};
std::string category{};
std::shared_ptr<std::vector<std::optional<Data::SliceIndex>>>
trackedValues;

DimensionAxis() = default;
bool add(const Data::SliceIndex &index,
@@ -124,7 +134,6 @@ struct DimensionAxis
return values.cend();
}
bool setLabels(double step);
void track(const Data::MarkerId &id);

private:
Values values;
@@ -136,9 +145,11 @@ DimensionAxis interpolate(const DimensionAxis &op0,

struct Axis
{
CommonAxis common;
::Anim::String title;
MeasureAxis measure;
DimensionAxis dimension;

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

struct Axises
Loading