region: add rotate method
This commit is contained in:
parent
81a7b83dfe
commit
bf3ae14f25
71
region.hpp
71
region.hpp
@ -201,6 +201,25 @@ namespace cruft {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
template <typename T> using region2 = region<2,T>;
|
||||||
|
template <typename T> using region3 = region<3,T>;
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
using region2u = region2<unsigned>;
|
||||||
|
using region2i = region2<int>;
|
||||||
|
using region2f = region2<float>;
|
||||||
|
using region2d = region2<double>;
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
extern template struct region<2, unsigned>;
|
||||||
|
extern template struct region<2, int>;
|
||||||
|
extern template struct region<2, float>;
|
||||||
|
extern template struct region<2, double>;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
/// constructs the minimal region that encompasses a region and a point.
|
/// constructs the minimal region that encompasses a region and a point.
|
||||||
template <typename T, size_t S>
|
template <typename T, size_t S>
|
||||||
@ -324,14 +343,54 @@ namespace cruft {
|
|||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T> using region2 = region<2,T>;
|
/// Returns a region rotated clockwise about the base point in `steps`
|
||||||
template <typename T> using region3 = region<3,T>;
|
/// multiples of 90 degrees.
|
||||||
|
///
|
||||||
|
/// `steps` must lie in the range [0, 4) so we can avoid an expensive
|
||||||
|
/// modulus in the typical case.
|
||||||
|
template <typename T>
|
||||||
|
cruft::region<2,T>
|
||||||
|
rotate (cruft::region<2,T> obj, int steps)
|
||||||
|
{
|
||||||
|
CHECK_LIMIT (steps, 0, 3);
|
||||||
|
|
||||||
|
switch (steps) {
|
||||||
|
case 0:
|
||||||
|
return obj;
|
||||||
|
|
||||||
using region2u = region2<unsigned>;
|
case 1:
|
||||||
using region2i = region2<int>;
|
return region2<T> {
|
||||||
using region2f = region2<float>;
|
point2<T> {
|
||||||
using region2d = region2<double>;
|
obj.p.x - obj.e.h,
|
||||||
|
obj.p.y
|
||||||
|
},
|
||||||
|
extent2<T> {
|
||||||
|
obj.e.h,
|
||||||
|
obj.e.w,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
return region2<T> {
|
||||||
|
point2<T> {
|
||||||
|
obj.p.x,
|
||||||
|
obj.p.y - obj.e.h,
|
||||||
|
},
|
||||||
|
obj.e,
|
||||||
|
};
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
return region2<T> {
|
||||||
|
obj.p,
|
||||||
|
extent2<T> {
|
||||||
|
obj.e.h,
|
||||||
|
obj.e.w,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -183,5 +183,55 @@ main (int, char **)
|
|||||||
tap.expect_eq (intersection (a, b), res, "region-region interesection: %!", message);
|
tap.expect_eq (intersection (a, b), res, "region-region interesection: %!", message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test rotate behaves as expected.
|
||||||
|
//
|
||||||
|
// It's important that the following constraints apply to the test data:
|
||||||
|
// * no point lies at the origin because we want to catch
|
||||||
|
// rotate-about-point errors that need a translation.
|
||||||
|
// * the size is non-square so we can differentiate between rotated
|
||||||
|
// values
|
||||||
|
// * use floating point values so we can test for loss of precision.
|
||||||
|
{
|
||||||
|
cruft::point2f const base { 1, 2 };
|
||||||
|
cruft::extent2f const size { 3, 4 };
|
||||||
|
cruft::region2f const orig { base, size };
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int rotation;
|
||||||
|
cruft::region2f res;
|
||||||
|
} const TESTS[] {
|
||||||
|
{
|
||||||
|
.rotation = 0,
|
||||||
|
.res = orig,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.rotation = 1,
|
||||||
|
.res = {
|
||||||
|
cruft::point2f { -3, 2 },
|
||||||
|
cruft::extent2f { 4, 3 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.rotation = 2,
|
||||||
|
.res = {
|
||||||
|
cruft::point2f { 1, -2 },
|
||||||
|
cruft::extent2f { 3, 4 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.rotation = 3,
|
||||||
|
.res = {
|
||||||
|
cruft::point2f { 1, 2 },
|
||||||
|
cruft::extent2f { 4, 3 },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto const &obj: TESTS) {
|
||||||
|
auto const computed = rotate (orig, obj.rotation);
|
||||||
|
tap.expect_eq (computed, obj.res, "%! rotation", obj.rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return tap.status ();
|
return tap.status ();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user