角度クラスが一通り実装できたので解説を。(3年越しだな…)
まずは使い方。
void func( Angle a )
{
...
}
~~~
Angle a(0.5f);
Degree d(180.f);
Radian r(pi);
func(a);
func(d);
func(r);
a += Angle(0.1f);
a += d;
Angle(0.1f) == Angle(0.5f);
Angle(0.1f) < Angle(0.5f);
a.value(1.f);
auto v = a.value();
auto a2 = a.toAngle();
auto d2 = a.toDegree();
auto r2 = a.toRadian();
a = Angle(-0.5f).abs();
a = Angle(1.5f).normalize();
a = Angle(-1.25f).normalize();
a = Angle(-1.25f).signedNormalize();
d = Degree(10.f).distanceFrom( Degree(350.f) );
d = Degree(10.f).reflect( Degree(30.f) );
d = Degree(350.f).reflect( Degree(10.f) );
v = a.sin();
v = a.cos();
v = a.tan();
d = Degree::Zero();
d = Degree::One();
d = Degree::Half();
ざっとこんな感じで。
続いて実装方法。
まずはコアなクラステンプレート部分。
template <typename T, template <typename> class Policy>
class BasicAngles;
Tは値の型。具体的にはfloatやdoubleです。
PolicyはAngle,Degree,Radianの特性を反映する部分ですね。
実際下記のように定義しています。
template <typename T>
struct AnglePolicy
{
static constexpr T kCycle = static_cast<T>(1.0);
};
template <typename T>
struct RadianPolicy
{
static constexpr T kCycle = Konst<T>::pi2;
};
template <typename T>
struct DegreePolicy
{
static constexpr T kCycle = static_cast<T>(360);
};
せっかくポリシー分けたんですけど、見ての通り1周の値しかないです。
まあ、3種類の違いってそこしかないですからね。
で、これらから次の定義をしています。
template <typename T>
using BasicAngle = detail::BasicAngles<T, detail::AnglePolicy>;
template <typename T>
using BasicRadian = detail::BasicAngles<T, detail::RadianPolicy>;
template <typename T>
using BasicDegree = detail::BasicAngles<T, detail::DegreePolicy>;
double型のRadianを作りたかったら、
BasicRadian<double>
を使います。
ここから更に、次の定義をしています。
自分は普段 double を使うことがほとんどないので、
floatが標準として扱いやすいようにですね。
構成としてはstd::stringとstd::basic_stringの関係を意識してます。
using Angle = BasicAngle<float>;
using Radian = BasicRadian<float>;
using Degree = BasicDegree<float>;
型を柔軟に吸収したい場合は次の関数を使います。
template <typename T>
constexpr BasicAngle<T> MakeAngle( T value ) noexcept { return BasicAngle<T>(value); }
template <typename T>
constexpr BasicRadian<T> MakeRadian( T value ) noexcept { return BasicRadian<T>(value); }
template <typename T>
constexpr BasicDegree<T> MakeDegree( T value ) noexcept { return BasicDegree<T>(value); }
ざっと以上ですね。
実装の中身は下記のリンクからどうぞ。
tofu/Angle.hpp at develop · fsawa/tofu · GitHub
tofu/Angle.cpp at develop · fsawa/tofu · GitHub