summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llmr/text/rotation_range.hpp2
-rw-r--r--src/text/rotation_range.cpp4
-rw-r--r--test/rotation_range.cpp137
-rw-r--r--test/test.gyp13
4 files changed, 153 insertions, 3 deletions
diff --git a/include/llmr/text/rotation_range.hpp b/include/llmr/text/rotation_range.hpp
index 6cc67f323b..e3d3ab6987 100644
--- a/include/llmr/text/rotation_range.hpp
+++ b/include/llmr/text/rotation_range.hpp
@@ -10,7 +10,7 @@
namespace llmr {
-typedef vec2<int16_t> CollisionPoint;
+typedef vec2<float> CollisionPoint;
typedef vec2<float> CollisionAnchor;
typedef std::array<float, 2> PlacementRange;
diff --git a/src/text/rotation_range.cpp b/src/text/rotation_range.cpp
index e276003c81..496b6108f5 100644
--- a/src/text/rotation_range.cpp
+++ b/src/text/rotation_range.cpp
@@ -233,8 +233,8 @@ CollisionRange rotationRange(const CollisionBox &inserting,
const CollisionBox &b = blocker;
// Instead of scaling the boxes, we move the anchors
- CollisionAnchor relativeAnchor{(b.anchor.x - a.anchor.x) * scale,
- (b.anchor.y - a.anchor.y) * scale};
+ CollisionAnchor relativeAnchor{static_cast<float>((b.anchor.x - a.anchor.x) * scale),
+ static_cast<float>((b.anchor.y - a.anchor.y) * scale)};
// Generate a list of collision interval
if (a.rotate && b.rotate) {
diff --git a/test/rotation_range.cpp b/test/rotation_range.cpp
new file mode 100644
index 0000000000..70126f978f
--- /dev/null
+++ b/test/rotation_range.cpp
@@ -0,0 +1,137 @@
+#include <iostream>
+#include "gtest/gtest.h"
+
+#include <llmr/text/rotation_range.hpp>
+
+using namespace llmr;
+
+double deg(double x) { return x / M_PI * 180.0; }
+
+TEST(RotationRange, mergeCollisions) {
+ // merge overlapping ranges
+ EXPECT_EQ(
+ CollisionRange({{1.0 / 8.0 * M_PI, 6.0 / 8.0 * M_PI}}),
+ mergeCollisions(
+ CollisionList(
+ {{CollisionRange({{3.0 / 8.0 * M_PI, 5.0 / 8.0 * M_PI}}),
+ CollisionRange({{4.0 / 8.0 * M_PI, 6.0 / 8.0 * M_PI}}),
+ CollisionRange({{1.0 / 8.0 * M_PI, 2.0 / 8.0 * M_PI}})}}),
+ PlacementRange({{2.0 * M_PI, 0.0}})));
+
+ // ignore collision within ignore range
+ EXPECT_EQ(
+ CollisionRange({{5.0 / 4.0 * M_PI, 6.0 / 4.0 * M_PI}}),
+ mergeCollisions(CollisionList({{CollisionRange({{M_PI / 2, M_PI}}),
+ CollisionRange({{5.0 / 4.0 * M_PI,
+ 6.0 / 4.0 * M_PI}})}}),
+ PlacementRange({{0, M_PI}})));
+
+ // crop collision that ends within ignore range
+ EXPECT_EQ(CollisionRange({{1.0 / 2.0 * M_PI, 3.0 / 4.0 * M_PI}}),
+ mergeCollisions(
+ CollisionList({{CollisionRange({{1.0 / 2.0 * M_PI, M_PI}})}}),
+ PlacementRange({{3.0 / 4.0 * M_PI, 3.0 / 2.0 * M_PI}})));
+
+ // crop collision that starts within ignore range
+ EXPECT_EQ(CollisionRange({{3.0 / 4.0 * M_PI, M_PI}}),
+ mergeCollisions(
+ CollisionList({{CollisionRange({{1.0 / 2.0 * M_PI, M_PI}})}}),
+ PlacementRange({{1.0 / 4.0 * M_PI, 3.0 / 4.0 * M_PI}})));
+}
+
+TEST(RotationRange, rotatingFixedCollisions) {
+ // returns collisions
+
+ auto collisions = rotatingFixedCollisions(
+ CollisionRect{CollisionPoint{-1, 0}, CollisionPoint{0, 1}},
+ CollisionRect{CollisionPoint{1.4142, -10}, CollisionPoint{10, 10}});
+
+ EXPECT_EQ(1, collisions.size());
+ EXPECT_EQ(135, round(deg(collisions.front()[0])));
+ EXPECT_EQ(135, round(deg(collisions.front()[1])));
+}
+
+TEST(RotationRange, cornerBoxCollisions) {
+ {
+ // returns intersections in sorted order as angles 0..2PI
+ CollisionList list;
+ cornerBoxCollisions(
+ std::back_inserter(list), CollisionPoint{1, 1},
+ CollisionCorners{{CollisionPoint{0, 0}, CollisionPoint{0, 10},
+ CollisionPoint{10, 10}, CollisionPoint{10, 0}}});
+ EXPECT_EQ(1, list.size());
+ EXPECT_EQ((CollisionRange{{M_PI / 4.0, M_PI * 7.0 / 4.0}}), list[0]);
+ }
+
+ {
+ // handles no intersections
+ CollisionList list;
+ cornerBoxCollisions(
+ std::back_inserter(list), CollisionPoint{200, 200},
+ CollisionCorners{{CollisionPoint{1, 1}, CollisionPoint{1, 10},
+ CollisionPoint{10, 10}, CollisionPoint{10, 1}}});
+ EXPECT_EQ(0, list.size());
+ }
+}
+
+TEST(RotationRange, circleEdgeCollisions) {
+ {
+ // handles two intersection points
+ CollisionAngles list;
+ circleEdgeCollisions(std::back_inserter(list), CollisionPoint{0, 1}, 1,
+ CollisionPoint{-10, 0}, CollisionPoint{10, 0});
+ std::sort(list.begin(), list.end());
+ EXPECT_EQ(2, list.size());
+ EXPECT_EQ(static_cast<float>(M_PI / 2), list[0]);
+ EXPECT_EQ(static_cast<float>(M_PI * 3.0 / 2.0), list[1]);
+ }
+
+ {
+ // handles one intersection point
+ CollisionAngles list;
+ circleEdgeCollisions(std::back_inserter(list), CollisionPoint{0, 1}, 1,
+ CollisionPoint{0, 0}, CollisionPoint{10, 0});
+ EXPECT_EQ(1, list.size());
+ EXPECT_EQ(static_cast<float>(M_PI / 2), list[0]);
+ }
+
+ {
+ // only returns intersections within the line segment
+ CollisionAngles list;
+ circleEdgeCollisions(std::back_inserter(list), CollisionPoint{0, 1}, 1,
+ CollisionPoint{3, 1}, CollisionPoint{30, 1});
+ EXPECT_EQ(0, list.size());
+ }
+
+ {
+ // doesnt count tangetial intersections as collisions
+ CollisionAngles list;
+ circleEdgeCollisions(std::back_inserter(list), CollisionPoint{0, 1}, 1,
+ CollisionPoint{-10, 1}, CollisionPoint{10, 1});
+ EXPECT_EQ(0, list.size());
+ }
+}
+
+TEST(RotationRange, rotatingRotatingCollisions) {
+ {
+ // basically works
+ CollisionList c = rotatingRotatingCollisions(
+ CollisionRect{{-1, 0}, {1, 0}}, CollisionRect{{-1, 0}, {1, 0}},
+ CollisionAnchor{1, 1});
+
+ EXPECT_EQ(2, c.size());
+ EXPECT_EQ(135, round(deg(c[0][0])));
+ EXPECT_EQ(135, round(deg(c[0][1])));
+ EXPECT_EQ(315, round(deg(c[1][0])));
+ EXPECT_EQ(315, round(deg(c[1][1])));
+ }
+
+ {
+ // checks if the two boxes are close enough to collide at that angle
+ CollisionList c = rotatingRotatingCollisions(
+ CollisionRect{{-1, 0}, {1, 0}}, CollisionRect{{-1, 0}, {1, 0}},
+ CollisionAnchor{2, 2});
+
+ EXPECT_EQ(0, c.size());
+ }
+}
diff --git a/test/test.gyp b/test/test.gyp
index 400310fa10..0cea1a285f 100644
--- a/test/test.gyp
+++ b/test/test.gyp
@@ -4,5 +4,18 @@
'../config.gypi'
],
'targets': [
+ {
+ "target_name": "rotation_range",
+ "product_name": "test_rotation_range",
+ "type": "executable",
+ "sources": [
+ "./main.cpp",
+ "./rotation_range.cpp",
+ ],
+ "dependencies": [
+ "../llmr.gyp:gtest",
+ "../llmr.gyp:llmr-x86"
+ ]
+ },
]
}