Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cpp/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
EXE := run_me # name of the output executable
SRCS := $(wildcard *.cpp) # SRCS holds the names of all *.cpp files
SRCS := $(wildcard *.cpp) $(wildcard src/*.cpp) # SRCS holds the names of all *.cpp files
OBJS := $(SRCS:.cpp=.o) # OBJS holds the same but with .cpp replaced by .o


Expand Down
4 changes: 3 additions & 1 deletion cpp/solution.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@
* - A function isColliding() that can take in any two Robots.
*/


#include "src/CircularRobot.hpp"
#include "src/RectangularRobot.hpp"
#include "src/collision.hpp"
6 changes: 6 additions & 0 deletions cpp/src/CircularRobot.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "CircularRobot.hpp"

CircularRobot::CircularRobot(double center_x, double center_y, double radius) : Robot(center_x, center_y)
{
this->radius = radius;
}
10 changes: 10 additions & 0 deletions cpp/src/CircularRobot.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once
#include "Robot.hpp"

class CircularRobot : public Robot
{
public:
double radius;
CircularRobot(double x, double y, double radius);
~CircularRobot() = default;
};
7 changes: 7 additions & 0 deletions cpp/src/RectangularRobot.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "RectangularRobot.hpp"

RectangularRobot::RectangularRobot(double center_x, double center_y, double length, double width) : Robot(center_x, center_y)
{
this->length = length;
this->width = width;
}
11 changes: 11 additions & 0 deletions cpp/src/RectangularRobot.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once
#include "Robot.hpp"

class RectangularRobot : public Robot
{
public:
double length;
double width;
RectangularRobot(double center_x, double center_y, double length, double width);
~RectangularRobot() = default;
};
7 changes: 7 additions & 0 deletions cpp/src/Robot.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "Robot.hpp"

Robot::Robot(double center_x, double center_y)
{
this->center_x = center_x;
this->center_y = center_y;
}
12 changes: 12 additions & 0 deletions cpp/src/Robot.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

class Robot
{
public:
double center_x;
double center_y;
Robot(double center_x, double center_y);
virtual ~Robot() = default;


};
61 changes: 61 additions & 0 deletions cpp/src/collision.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include "collision.hpp"
#include <stdexcept>
#include <cmath>

// Dispatches to the right helper depending on data type
// dynamic_cast returns nullptr if the cast fails, so we can check all combinations :)
bool isColliding(const Robot& a, const Robot& b)
{
const CircularRobot* ca = dynamic_cast<const CircularRobot*>(&a);
const CircularRobot* cb = dynamic_cast<const CircularRobot*>(&b);
const RectangularRobot* ra = dynamic_cast<const RectangularRobot*>(&a);
const RectangularRobot* rb = dynamic_cast<const RectangularRobot*>(&b);
if (ca && cb) return circleVsCircle(*ca, *cb);
if (ra && rb) return rectVsRect(*ra, *rb);
if (ca && rb) return circleVsRect(*ca, *rb);
if (ra && cb) return circleVsRect(*cb, *ra); // flip order to match signature

throw std::invalid_argument("unhandled robot type combination");
}

// Euclidean distance between two robot centers.
double getCenterDistance(const Robot& a, const Robot& b)
{
double dx = a.center_x - b.center_x;
double dy = a.center_y - b.center_y;
return sqrt(dx*dx + dy*dy);
}

// Two circles collide if the distance between centers is less than the sum of their radii.
bool circleVsCircle(const CircularRobot& ca, const CircularRobot& cb)
{
return (ca.radius + cb.radius) >= getCenterDistance(ca, cb);
}

// rectangles collide if they overlap on both the x and y axes independently.
bool rectVsRect(const RectangularRobot& ra, const RectangularRobot& rb)
{
double dx = std::abs(ra.center_x - rb.center_x);
double dy = std::abs(ra.center_y - rb.center_y);
return (ra.width + rb.width) / 2 >= dx && (ra.length + rb.length) / 2 >= dy;
}

// finds the closest point between the circle and a line
double findClosest(const double &circle, const double &rMin, const double &rMax)
{
if (circle >= rMin && circle <= rMax) return circle;
else if (circle < rMin) return rMin;
else return rMax;
}

// Find the closest point on the rectangle to the circle center, then check if that distance is within the circle's radius.
bool circleVsRect(const CircularRobot& ca, const RectangularRobot& rb)
{
double closest_x = findClosest(ca.center_x, rb.center_x - rb.length/2, rb.center_x + rb.length/2);
double closest_y = findClosest(ca.center_y, rb.center_y - rb.width/2, rb.center_y + rb.width/2);

double dx = closest_x - ca.center_x;
double dy = closest_y - ca.center_y;

return std::sqrt(dx*dx + dy*dy) <= ca.radius;
}
11 changes: 11 additions & 0 deletions cpp/src/collision.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once
#include "CircularRobot.hpp"
#include "RectangularRobot.hpp"

bool isColliding(const Robot& a, const Robot& b);
bool circleVsCircle(const CircularRobot& ca, const CircularRobot& cb);
bool rectVsRect(const RectangularRobot& ra, const RectangularRobot& rb);
bool circleVsRect(const CircularRobot& ca, const RectangularRobot& rb);

double getCenterDistance(const Robot& a, const Robot& b);
double findClosest(double& circle, double& rMin, double& rMax);