Skip to content

Commit

Permalink
Merge pull request #581 from vizzuhq/add_axisid
Browse files Browse the repository at this point in the history
Add axisId
  • Loading branch information
schaumb authored Oct 1, 2024
2 parents b98eb87 + 4603ff3 commit 03d9b39
Show file tree
Hide file tree
Showing 17 changed files with 140 additions and 84 deletions.
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

0 comments on commit 03d9b39

Please sign in to comment.