Kale
Loading...
Searching...
No Matches
Ray.cpp
Go to the documentation of this file.
1/*
2 Copyright 2022 Rishi Challa
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17#include "Ray.hpp"
18
23
24#include <stdexcept>
25#include <cmath>
26
27using namespace Kale;
28
32Ray::Ray() : origin(0, 0), direction(1, 0) {
33 // Empty Body
34}
35
41Ray::Ray(const Vector2f& origin, const Vector2f& direction) : origin(origin), direction(direction) {
42 // Empty Body
43}
44
49Ray::Ray(const Line& line) : origin(line.point1), direction((line.point2 - line.point1).unit()) {
50 // Empty Body
51}
52
59Ray::Ray(const Vector2f& origin, float angle, AngleUnit unit) : origin(origin) {
60 direction.x = std::cos(unit == AngleUnit::Degree ? degToRad(angle) : angle);
61 direction.y = std::sin(unit == AngleUnit::Degree ? degToRad(angle) : angle);
62}
63
69float Ray::getAngle(AngleUnit unit) const {
70 float angle = std::tan(direction.y / direction.x);
71 if (unit == AngleUnit::Degree) angle = radToDeg(angle);
72 return angle;
73}
74
80bool Ray::isPerpendicular(Ray ray) const {
82}
83
89bool Ray::isPerpendicular(Line line) const {
90 return isFloating0(direction.dot(line.point2 - line.point1));
91}
92
98bool Ray::isParallel(Ray ray) const {
99 return ray.direction == direction;
100}
101
107bool Ray::isParallel(Line line) const {
108 return isFloating0(direction.cross(line.point1 - line.point2));
109}
110
116#ifdef KALE_DEBUG
117 throw std::runtime_error("Cannot find bounding box of a ray - rays are infinite in length");
118#else
119 return Rect();
120#endif
121}
122
128bool Ray::pointCollision(Vector2f point) const {
129 Vector2f po = point - origin;
130 return isFloating0(po.cross(direction)) && po.dot(direction) > 0.0f;
131}
132
139 return lineCollision({rect.point1, rect.point2}) || lineCollision({rect.point2, rect.point3}) ||
140 lineCollision({rect.point3, rect.point4}) || lineCollision({rect.point4, rect.point1});
141}
142
148bool Ray::rectCollision(Rect rect) const {
149 return lineCollision({rect.topLeft, rect.topRight()}) || lineCollision({rect.topRight(), rect.bottomRight}) ||
150 lineCollision({rect.bottomRight, rect.bottomLeft()}) || lineCollision({rect.bottomLeft(), rect.topLeft});
151}
152
158bool Ray::circleCollision(Circle circle) const {
159 return circle.rayCollision(*this);
160}
161
167bool Ray::rayCollision(Ray ray) const {
168 // Rays are parallel in the same direction
169 if (ray.direction == direction) return isFloating0(direction.cross(ray.origin - origin));
170
171 // Rays are parallel in the opposite direction
172 if (-ray.direction == direction)
173 return isFloating0(direction.cross(ray.origin - origin)) && (direction.x > 0.0f ? ray.origin.x >= origin.x : ray.origin.x <= origin.x);
174
175 // Convert both rays to y = ax + b form
176 float a1 = direction.y / direction.x;
177 float a2 = ray.direction.y / ray.direction.x;
178 float b1 = origin.y - a1 * origin.x;
179 float b2 = ray.origin.y - a2 * ray.origin.x;
180
181 // Find collision x
182 float colX = (b2 - b1) / (a1 - a2);
183
184 // Ensure that the x faces in the ray's direction for both rays
185 return sign(colX - origin.x) == sign(direction.x) && sign(colX - ray.origin.x) == sign(ray.direction.x);
186}
187
193bool Ray::lineCollision(Line line) const {
194 // Convert ray & line to y = ax + b form
195 float a1 = direction.y / direction.x;
196 float a2 = (line.point2.y - line.point1.y) / (line.point2.x - line.point2.x);
197
198 // Check for parallel lines
199 float den = a1 - a2;
200 if (isFloating0(den))
201 return isFloating0(direction.cross(line.point1 - origin)) &&
202 (sign(line.point1.x - origin.x) == sign(direction.x) || sign(line.point2.x - origin.x) == sign(direction.x));
203
204 float b1 = origin.y - a1 * origin.x;
205 float b2 = line.point1.y - a2 * line.point1.x;
206
207 // Find collision x
208 float colX = (b2 - b1) / den;
209
210 // Ensure that the collision x faces the ray's direction and is in line's bounds
211 return colX >= line.point1.x && colX <= line.point2.x && sign(colX - origin.x) == sign(direction.x);
212}
T dot(Vector2< T > o) const
Definition Vector.hpp:121
T cross(Vector2< T > o) const
Definition Vector.hpp:122
AngleUnit
Definition Utils.hpp:30
constexpr float radToDeg(float rad)
Definition Utils.hpp:48
bool isFloating0(T num, T epsilon=std::numeric_limits< T >::epsilon())
Definition Utils.hpp:58
int sign(T val)
Definition Utils.hpp:79
constexpr float degToRad(float deg)
Definition Utils.hpp:39
bool rayCollision(Ray ray) const override
Definition Circle.cpp:97
Vector2f point2
Definition Line.hpp:36
Vector2f point1
Definition Line.hpp:31
bool pointCollision(Vector2f point) const override
Definition Ray.cpp:128
Rect getBoundingBox() const override
Definition Ray.cpp:115
Vector2f direction
Definition Ray.hpp:38
Ray()
Definition Ray.cpp:32
bool isPerpendicular(Ray ray) const
Definition Ray.cpp:80
bool isParallel(Ray ray) const
Definition Ray.cpp:98
float getAngle(AngleUnit unit) const
Definition Ray.cpp:69
Vector2f origin
Definition Ray.hpp:33
bool lineCollision(Line line) const override
Definition Ray.cpp:193
bool rayCollision(Ray ray) const override
Definition Ray.cpp:167
bool rectCollision(RotatedRect rect) const override
Definition Ray.cpp:138
bool circleCollision(Circle circle) const override
Definition Ray.cpp:158
Vector2f bottomRight
Definition Rect.hpp:36
Vector2f topRight() const
Definition Rect.cpp:56
Vector2f bottomLeft() const
Definition Rect.cpp:64
Vector2f topLeft
Definition Rect.hpp:31