Skip to content
This repository has been archived by the owner on Dec 5, 2022. It is now read-only.

Feature/general grid type #124

Open
wants to merge 8 commits into
base: development
Choose a base branch
from
Open
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ set(ROBOTEAM_UTILS_SRC
src/utils/FileLogger.cpp
src/utils/Teams.cpp
src/utils/AIData.cpp
src/utils/FieldRectangle.cpp
src/utils/FastRectangle.cpp
src/utils/Field.cpp
src/utils/Robot.cpp
src/utils/World.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@ namespace rtt {
/* A more optimized rectangle class that is used for representing a field.
Optimized by precalculating many variables that are already known from
the beginning, because field data is often read, but never changed. */
class FieldRectangle : public Rectangle {
class FastRectangle : virtual public Rectangle {
public:
// Creates a simple unit rectangle between (0,0) and (1,1)
FieldRectangle();
FastRectangle();
// Creates a rectangle from the given rectangle
explicit FastRectangle(const Rectangle&);
// Creates a rectangle from a top, right, bottom and left boundary
FieldRectangle(double top, double right, double bottom, double left);
FastRectangle(double top, double right, double bottom, double left);
// Creates a rectangle from any two opposing corners
FieldRectangle(const Vector2& pointA, const Vector2& pointB);
FastRectangle(const Vector2& pointA, const Vector2& pointB);

bool operator==(const FieldRectangle& other) const;
bool operator==(const FastRectangle& other) const;

// Checks if the given point is inside the rectangle
bool contains(const Vector2& point) const override;
Expand Down
16 changes: 8 additions & 8 deletions include/roboteam_utils/Field.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include <roboteam_utils/FieldRectangle.hpp>
#include <roboteam_utils/FastRectangle.hpp>
#include <roboteam_utils/Vector2.h>
#include <roboteam_utils/Grid.h>
#include <roboteam_utils/Circle.h>
Expand All @@ -20,13 +20,13 @@ typedef struct Field {

double boundaryWidth = 0.0; // Width of the area around the play area

FieldRectangle playArea; // The whole field in which robots can drive (excluding goal areas)
FieldRectangle leftPlayArea; // Left side of the field
FieldRectangle rightPlayArea; // Right side of the field
FieldRectangle leftDefenseArea; // Left defense area inside left play area
FieldRectangle rightDefenseArea;// Right defense area inside right play area
FieldRectangle leftGoalArea; // Left goal area outside the play area
FieldRectangle rightGoalArea; // Right goal area outside the play area
FastRectangle playArea; // The whole field in which robots can drive (excluding goal areas)
FastRectangle leftPlayArea; // Left side of the field
FastRectangle rightPlayArea; // Right side of the field
FastRectangle leftDefenseArea; // Left defense area inside left play area
FastRectangle rightDefenseArea;// Right defense area inside right play area
FastRectangle leftGoalArea; // Left goal area outside the play area
FastRectangle rightGoalArea; // Right goal area outside the play area

bool operator== (const Field& other) const;

Expand Down
143 changes: 94 additions & 49 deletions include/roboteam_utils/Grid.h
Original file line number Diff line number Diff line change
@@ -1,55 +1,100 @@
//
// Created by jesse on 18-05-20.
//

#ifndef RTT_GRID_H
#define RTT_GRID_H
#pragma once

#include <vector>

#include "Vector2.h"
#include "FastRectangle.hpp"
#include "LazyRectangle.hpp"

namespace rtt {
class Grid {
public:
/**
* A Grid is a 2D vector of Vector2 points. The points will be evenly spaced and centered in the given range.
* @param offSetX the distance you want to horizontally shift the grid from 0 (where 0 is left edge)
* @param offSetY the distance you want to vertically shift the grid from 0 (where 0 is bottom edge)
* @param regionWidth the width of the region you want the grid to encompass (y-direction)
* @param regionLength the length of the region you want the grid to encompass (x-direction)
* @param numStepsX number of segments to divide the grid into in x direction
* @param numStepsY number of segments to divide the grid into in y direction
*/
Grid(double offSetX, double offSetY, double regionWidth, double regionLength, int numPointsX, int numPointsY);

// A default Grid of 3x3=9 elements, starting at (0, 0)
Grid();

[[nodiscard]] double getOffSetX() const;
[[nodiscard]] double getOffSetY() const;
[[nodiscard]] double getRegionWidth() const;
[[nodiscard]] double getRegionLength() const;
[[nodiscard]] int getNumPointsX() const;
[[nodiscard]] int getNumPointsY() const;
[[nodiscard]] double getStepSizeX() const;
[[nodiscard]] double getStepSizeY() const;
[[nodiscard]] const std::vector<std::vector<Vector2>> &getPoints() const;

private:
/**
* nested vector, first index corresponds to nth x element, second to nth y element
*/
std::vector<std::vector<Vector2>> points;
double offSetX;
double offSetY;
double regionWidth;
double regionLength;
int numPointsX;
int numPointsY;
double stepSizeX;
double stepSizeY;
};
} // namespace rtt

#endif // RTT_GRID_H
class InvalidCellLocation : private std::exception {
public:
explicit InvalidCellLocation(const std::string& message);
const char* what() const noexcept override;
private:
const std::string message;
};
class InvalidGridSizeException : private std::exception {
public:
explicit InvalidGridSizeException(const std::string& message);
const char* what() const noexcept override;
private:
const std::string message;
};

template <typename T>
class Grid : virtual public Rectangle {
public:
virtual ~Grid() = default;

// Gets the cell at the specified location, can throw InvalidCellLocation
virtual const T& getCell(unsigned int row, unsigned int column) const = 0;
// A list of all cells, from left to right, top to bottom
virtual const std::vector<T>& getCells() const = 0;

virtual int getRowSize() const = 0;
virtual int getColumnSize() const = 0;
};

// Fast implementation of a grid. It calculates all properties first, so accessing later takes little time
template <int X, int Y, typename T>
class FastGrid : public Grid<T>, public FastRectangle {
public:
explicit FastGrid(const Rectangle& r) : FastRectangle(r) {
if (X < 1 || Y < 1) throw InvalidGridSizeException("Invalid grid size, cannot be lower than 1");

double cellWidth = this->width() / X;
double cellHeight = this->height() / Y;

for (int row = 0; row < Y; row++) {
for (int column = 0; column < X; column++) {
// Calculate the rectangle of the cell
double cellTop = this->top() - row * cellHeight;
double cellBottom = cellTop - cellHeight;
double cellLeft = this->left() + column * cellWidth;
double cellRight = cellLeft + cellWidth;

// Now create the cell of the correct type and add it
LazyRectangle cellBoundary({cellRight, cellTop}, {cellLeft, cellBottom});
auto cell = T(cellBoundary);
this->cells.push_back(cell);
}
}
}

const T& getCell(unsigned int x, unsigned int y) const override {
if (y >= Y || x >= X) throw InvalidCellLocation("This cell does not exist");
return this->cells[x + y * X];
}
const std::vector<T>& getCells() const override {
return this->cells;
}
void addPoints(std::vector<Vector2>& v) const override {
for (const auto& cell : this->cells) {
cell.addPoints(v);
}
}
int getRowSize() const override { return X; }
int getColumnSize() const override { return Y; }
private:
std::vector<T> cells;
};

// 3 by 3 version of a fast grid. Adds some easy accessibility functions.
template <typename T>
class Grid3x3 : public FastGrid<3, 3, T> {
public:
explicit Grid3x3(const Rectangle& r) : FastGrid<3, 3, T>(r) {}

const T& topLeftCell() const { return this->getCell(0, 0); }
const T& topMiddleCell() const { return this->getCell(1, 0); }
const T& topRightCell() const { return this->getCell(2, 0); }
const T& middleLeftCell() const { return this->getCell(0, 1); }
const T& middleMiddleCell() const { return this->getCell(1, 1); }
const T& middleRightCell() const { return this->getCell(2, 1); }
const T& bottomLeftCell() const { return this->getCell(0, 2); }
const T& bottomMiddleCell() const { return this->getCell(1, 2); }
const T& bottomRightCell() const { return this->getCell(2, 2); }
};

} // namespace rtt
27 changes: 27 additions & 0 deletions include/roboteam_utils/GridCell.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include <vector>
#include "Shape.h"

namespace rtt {
class Vector2;

/*
* This abstract class can be implemented to ensure the derived class can be put into a grid.
* The grid requires the function to be implemented, and that the derived class has a valid
* constructor that takes a rectangle (meant for the boundary of the cell)
*/
class GridCell : public Shape {
public:
virtual ~GridCell() = default;

// Adds the points this shape has to the given vector. (Recursively for containers like grids)
virtual void addPoints(std::vector<Vector2>& points) const = 0;
std::vector<Vector2> getPoints() const {
std::vector<Vector2> points;
this->addPoints(points);
return points;
}
};

} // namespace rtt
6 changes: 5 additions & 1 deletion include/roboteam_utils/LazyRectangle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ class Polygon;
* @date 22-01-2020
* @author Rolf van der Hulst
*/
class LazyRectangle : public Rectangle {
class LazyRectangle : virtual public Rectangle {
public:
/**
* @brief Constructs a rectangle from the given rectangle
*/
explicit LazyRectangle(const Rectangle&);
/**
* @brief Constructs a rectangle from two opposite corners
* @param corner Primary corner
Expand Down
9 changes: 8 additions & 1 deletion include/roboteam_utils/Rectangle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
#include "Shape.h"
#include "Vector2.h"
#include "LineSegment.h"
#include "GridCell.hpp"

namespace rtt {

class Rectangle : public Shape {
class Rectangle : public GridCell {
public:
virtual ~Rectangle() = default;

// Gets the width of the rectangle
[[nodiscard]] virtual double width() const = 0;
// Gets the height of the rectangle
Expand Down Expand Up @@ -40,6 +43,10 @@ class Rectangle : public Shape {
[[nodiscard]] virtual LineSegment rightLine() const = 0;
// Gets the bottom line segment
[[nodiscard]] virtual LineSegment bottomLine() const = 0;

void addPoints(std::vector<Vector2>& points) const override {
points.push_back(this->center());
}
};

} // namespace rtt
2 changes: 2 additions & 0 deletions include/roboteam_utils/Shape.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
namespace rtt {
class Shape {
public:
virtual ~Shape() = default;

virtual bool contains(const Vector2& point) const = 0;

virtual Vector2 project(const Vector2& point) const = 0;
Expand Down
Loading