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.
|
||||
template <typename T, size_t S>
|
||||
@ -324,14 +343,54 @@ namespace cruft {
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T> using region2 = region<2,T>;
|
||||
template <typename T> using region3 = region<3,T>;
|
||||
/// Returns a region rotated clockwise about the base point in `steps`
|
||||
/// 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>;
|
||||
using region2i = region2<int>;
|
||||
using region2f = region2<float>;
|
||||
using region2d = region2<double>;
|
||||
case 1:
|
||||
return region2<T> {
|
||||
point2<T> {
|
||||
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);
|
||||
}
|
||||
|
||||
// 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 ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user