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

Add axisId #581

Merged
merged 2 commits into from
Oct 1, 2024
Merged
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
64 changes: 43 additions & 21 deletions src/base/refl/auto_enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,29 @@ namespace Detail
{
template <class T> using real_t = std::underlying_type_t<T>;

template <class E, real_t<E> From, real_t<E> To>
requires(!std::same_as<bool, real_t<E>>)
template <class E>
concept UniqueNames = requires {
static_cast<std::string_view>(unique_enum_names(E{}));
};

template <class E>
concept UniqueRange = requires {
static_cast<std::pair<real_t<E>, real_t<E>>>(unique_from_to(E{}));
};

template <class E>
requires(UniqueRange<E>)
consteval std::pair<real_t<E>, real_t<E>> from_to()
{
constexpr auto res = unique_from_to(E{});
static_assert(res.first <= res.second, "Invalid range");
return res;
}

template <class E,
real_t<E> From = real_t<E>{},
real_t<E> To = real_t<E>{}>
requires(!UniqueRange<E> && !std::same_as<bool, real_t<E>>)
consteval std::pair<real_t<E>, real_t<E>> from_to()
{
if constexpr (std::is_signed_v<real_t<E>>
Expand All @@ -44,39 +65,40 @@ consteval std::pair<real_t<E>, real_t<E>> from_to()
return from_to<E, From - 1, To>();
else if constexpr (!Name::name<E, static_cast<E>(To)>().empty())
return from_to<E, From, To + 1>();
else
return {From, To};
else {
static_assert(From != To, "Not found any enum string");
return {From, To - 1};
}
}

template <class E, int, int>
requires(std::same_as<bool, real_t<E>>)
requires(!UniqueRange<E> && std::same_as<bool, real_t<E>>)
consteval std::pair<real_t<E>, real_t<E>> from_to()
{
return {false, false};
constexpr auto has_false =
!Name::name<E, static_cast<E>(false)>().empty();
constexpr auto has_true =
!Name::name<E, static_cast<E>(true)>().empty();
static_assert(has_false || has_true, "Not found any enum string");
return {!has_false, has_true};
}

template <class E>
requires(!std::same_as<bool, real_t<E>>)
consteval real_t<E> count()
{
auto [from, to] = from_to<E, 0, 0>();
return static_cast<real_t<E>>(to - from);
auto [from, to] = from_to<E>();
return static_cast<real_t<E>>(to - from + 1);
}

template <class E>
requires(std::same_as<bool, real_t<E>>)
consteval int count()
{
return Name::name<E, static_cast<E>(false)>().empty()
? 0
: 1 + !Name::name<E, static_cast<E>(true)>().empty();
auto [from, to] = from_to<E>();
return to - from + 1;
}

template <class E>
concept UniqueNames = requires {
static_cast<std::string_view>(unique_enum_names(E{}));
};

template <class E, class F = real_t<E>, F... Ix>
consteval auto whole_array(std::integer_sequence<F, Ix...> = {})
{
Expand All @@ -87,7 +109,7 @@ consteval auto whole_array(std::integer_sequence<F, Ix...> = {})
return res;
}
else {
constexpr auto first = Detail::from_to<E, 0, 0>().first;
constexpr auto first = Detail::from_to<E>().first;
std::array<char,
(Name::name<E, static_cast<E>(Ix + first)>().size() + ...
+ (sizeof...(Ix) - 1))>
Expand All @@ -109,7 +131,7 @@ constexpr std::array enum_name_holder = Detail::whole_array<E>(
Detail::count<E>()>{});

template <class E>
constexpr std::array enum_name_holder<E, true> =
constinit const std::array enum_name_holder<E, true> =
Detail::whole_array<E, int>(
std::make_integer_sequence<int, Detail::count<E>()>{});

Expand Down Expand Up @@ -143,7 +165,7 @@ template <class E> constexpr std::array enum_names = get_names<E>();
template <class Type = std::string_view, class E>
Type enum_name(E name)
{
constexpr auto first = Detail::from_to<E, 0, 0>().first;
constexpr auto first = Detail::from_to<E>().first;
constexpr auto n = std::size(enum_names<E>);
if (static_cast<std::size_t>(
static_cast<Detail::real_t<E>>(name) - first)
Expand All @@ -159,7 +181,7 @@ Type enum_name(E name)

template <class E> constexpr E get_enum(const std::string_view &data)
{
constexpr auto first = Detail::from_to<E, 0, 0>().first;
constexpr auto first = Detail::from_to<E>().first;
Detail::real_t<E> ix{};
for (auto v : enum_names<E>) {
if (v == data) break;
Expand Down Expand Up @@ -204,7 +226,7 @@ struct EnumArray : std::array<V, std::size(enum_names<E>)>
template <class E, class... Args>
requires(std::is_enum_v<E>
&& sizeof...(Args) == Detail::count<E>()
&& Detail::from_to<E, 0, 0>().first == 0)
&& Detail::from_to<E>().first == 0)
struct EnumVariant : std::variant<Args...>
{
using base_variant = std::variant<Args...>;
Expand Down
8 changes: 4 additions & 4 deletions src/chart/animator/planner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,8 +425,8 @@ bool Planner::needVertical() const
!= target->axises.at(Gen::ChannelId::y).measure
|| source->axises.at(Gen::ChannelId::y).dimension
!= target->axises.at(Gen::ChannelId::y).dimension
|| source->guides.at(Gen::ChannelId::y)
!= target->guides.at(Gen::ChannelId::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
Expand Down Expand Up @@ -472,8 +472,8 @@ bool Planner::needHorizontal() const
!= target->axises.at(Gen::ChannelId::x).measure
|| source->axises.at(Gen::ChannelId::x).dimension
!= target->axises.at(Gen::ChannelId::x).dimension
|| source->guides.at(Gen::ChannelId::x)
!= target->guides.at(Gen::ChannelId::x)
|| source->guides.at(Gen::AxisId::x)
!= target->guides.at(Gen::AxisId::x)
|| source->anyAxisSet != target->anyAxisSet
|| source->keepAspectRatio != target->keepAspectRatio
|| (source->markerConnectionOrientation
Expand Down
20 changes: 15 additions & 5 deletions src/chart/generator/axis.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,22 @@ struct Axises
return axises.at(channelType);
}

[[nodiscard]] const Axis &other(ChannelId channelType) const
[[nodiscard]] const Axis &at(AxisId axisType) const
{
switch (channelType) {
case ChannelId::x: return axises.at(ChannelId::y);
case ChannelId::y: return axises.at(ChannelId::x);
default: throw std::logic_error("not an axis channel");
return axises.at(asChannel(axisType));
}

[[nodiscard]] Axis &at(AxisId axisType)
{
return axises.at(asChannel(axisType));
}

[[nodiscard]] const Axis &other(AxisId axisType) const
{
switch (axisType) {
default:
case AxisId::x: return at(AxisId::y);
case AxisId::y: return at(AxisId::x);
}
}

Expand Down
22 changes: 12 additions & 10 deletions src/chart/generator/guides.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include "guides.h"

#include <stdexcept>

#include "base/math/interpolation.h"
#include "chart/options/align.h"
#include "chart/options/channel.h"
Expand Down Expand Up @@ -92,18 +90,22 @@ Guides::Guides(const Options &options)
|| (!yIsMeasure && !yOpt.isEmpty())));
}

GuidesByAxis &Guides::at(ChannelId channel)
GuidesByAxis &Guides::at(AxisId channel)
{
if (channel == ChannelId::x) return x;
if (channel == ChannelId::y) return y;
throw std::out_of_range("guides index out of range");
switch (channel) {
default:
case AxisId::x: return x;
case AxisId::y: return y;
}
}

const GuidesByAxis &Guides::at(ChannelId channel) const
const GuidesByAxis &Guides::at(AxisId channel) const
{
if (channel == ChannelId::x) return x;
if (channel == ChannelId::y) return y;
throw std::out_of_range("guides index out of range");
switch (channel) {
default:
case AxisId::x: return x;
case AxisId::y: return y;
}
}

bool Guides::hasAnyGuides() const
Expand Down
4 changes: 2 additions & 2 deletions src/chart/generator/guides.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ struct Guides
GuidesByAxis y;

explicit Guides(const Options &options);
[[nodiscard]] const GuidesByAxis &at(ChannelId channel) const;
GuidesByAxis &at(ChannelId channel);
[[nodiscard]] const GuidesByAxis &at(AxisId channel) const;
GuidesByAxis &at(AxisId channel);
[[nodiscard]] bool hasAnyGuides() const;
};

Expand Down
2 changes: 1 addition & 1 deletion src/chart/generator/plotbuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ void PlotBuilder::calcDimensionAxis(ChannelId type)

if (scale.isMeasure() || !scale.hasDimension()) return;

auto &&isTypeAxis = isAxis(type);
auto &&isTypeAxis = asAxis(type).has_value();
if (auto merge = scale.labelLevel == 0; isTypeAxis) {
for (const auto &marker : plot->markers) {
if (!marker.enabled) continue;
Expand Down
4 changes: 2 additions & 2 deletions src/chart/main/style.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,9 +363,9 @@ struct PlotParams

struct Plot : Padding, Box, PlotParams
{
[[nodiscard]] const Axis &getAxis(Gen::ChannelId id) const
[[nodiscard]] const Axis &getAxis(Gen::AxisId id) const
{
return id == Gen::ChannelId::x ? xAxis : yAxis;
return id == Gen::AxisId::x ? xAxis : yAxis;
}
};

Expand Down
Empty file.
Empty file.
12 changes: 10 additions & 2 deletions src/chart/options/channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,17 @@
namespace Vizzu::Gen
{

bool isAxis(ChannelId type)
std::optional<AxisId> asAxis(ChannelId type)
{
return type == ChannelId::x || type == ChannelId::y;
return type == ChannelId::x || type == ChannelId::y
? std::make_optional(static_cast<AxisId>(
static_cast<ChannelIdType>(type)))
: std::nullopt;
}

ChannelId asChannel(AxisId type)
{
return static_cast<ChannelId>(static_cast<ChannelIdType>(type));
}

Channel Channel::makeChannel(Type id)
Expand Down
25 changes: 24 additions & 1 deletion src/chart/options/channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,28 @@ enum class ChannelId : std::uint8_t {
y,
noop
};
using ChannelIdType = std::underlying_type_t<ChannelId>;

enum class AxisId : ChannelIdType {
x = static_cast<ChannelIdType>(ChannelId::x),
y = static_cast<ChannelIdType>(ChannelId::y)
};

consteval auto unique_from_to(AxisId)
{
return std::pair{static_cast<ChannelIdType>(AxisId::x),
static_cast<ChannelIdType>(AxisId::y)};
}

static_assert(Refl::enum_names<AxisId>.size() == 2);
static_assert(std::ranges::all_of(Refl::enum_names<AxisId>,
[](std::string_view name)
{
return static_cast<ChannelIdType>(
Refl::get_enum<AxisId>(name))
== static_cast<ChannelIdType>(
Refl::get_enum<ChannelId>(name));
}));

class Channel
{
Expand Down Expand Up @@ -68,7 +90,8 @@ class Channel
Base::AutoParam<double> step{};
};

bool isAxis(ChannelId type);
std::optional<AxisId> asAxis(ChannelId type);
ChannelId asChannel(AxisId type);

}

Expand Down
2 changes: 1 addition & 1 deletion src/chart/options/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const Channel *Options::subAxisOf(ChannelId id) const
if (id == ChannelId::size && channels.anyAxisSet()) {
return &channels.at(ChannelId::size);
}
if (isAxis(id)) {
if (asAxis(id)) {
if (channels.at(id).isDimension() && id == mainAxisType())
return &subAxis();
return &channels.at(ChannelId::size);
Expand Down
2 changes: 0 additions & 2 deletions src/chart/options/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ namespace Vizzu::Gen

class Options
{
using ChannelIdType = std::underlying_type_t<ChannelId>;

public:
enum class LegendId : ChannelIdType {
color = static_cast<ChannelIdType>(ChannelId::color),
Expand Down
Loading