Check if a polygon overlaps with a rectangle: Difference between revisions
Content added Content deleted
(New post.) |
(New post.) |
||
Line 305: | Line 305: | ||
poly and rect1 overlap? false |
poly and rect1 overlap? false |
||
poly and rect2 overlap? true |
poly and rect2 overlap? true |
||
</pre> |
|||
=={{header|C++}}== |
|||
This is just a special case of the [[Check if two polygons overlap]] task where one of the polygons is a rectangle. |
|||
This example shows the standard method of dealing with such a special case. The rectangle is converted to a polygon |
|||
and then the existing code for checking if two polygons overlap is invoked. A similar process can be used for |
|||
determining if two rectangles overlap, or two triangles overlap,or a triangle and rectangle overlap, etc. |
|||
<syntaxhighlight lang="c++"> |
|||
#include <iostream> |
|||
#include <limits> |
|||
#include <string> |
|||
#include <vector> |
|||
class Point { |
|||
public: |
|||
float x; |
|||
float y; |
|||
}; |
|||
class Projection { |
|||
public: |
|||
float min; |
|||
float max; |
|||
const bool overlaps(const Projection& other) { |
|||
return ! ( max < other.min || other.max < min ); |
|||
} |
|||
}; |
|||
class Vector { |
|||
public: |
|||
float x; |
|||
float y; |
|||
const float scalarProduct(const Vector& other) { |
|||
return x * other.x + y * other.y; |
|||
} |
|||
const Vector edgeWith(const Vector& other) { |
|||
return Vector(x - other.x, y - other.y); |
|||
} |
|||
const Vector perpendicular() { |
|||
return Vector(-y, x); |
|||
} |
|||
const std::string to_string() { |
|||
return "(" + std::to_string(x) + ", " + std::to_string(y) + ") "; |
|||
} |
|||
}; |
|||
class Polygon { |
|||
public: |
|||
Polygon(const std::vector<Point>& points) { |
|||
computeVertices(points); |
|||
computeAxes(); |
|||
} |
|||
const bool overlaps(Polygon& other) { |
|||
std::vector<Vector> allAxes = axes; |
|||
allAxes.insert(allAxes.end(), other.axes.begin(), other.axes.end()); |
|||
for ( Vector& axis : allAxes ) { |
|||
Projection projection1 = projectionOnAxis(axis); |
|||
Projection projection2 = other.projectionOnAxis(axis); |
|||
if ( ! projection1.overlaps(projection2) ) { |
|||
return false; |
|||
} |
|||
} |
|||
return true; |
|||
} |
|||
const Projection projectionOnAxis(Vector& axis) { |
|||
float min = std::numeric_limits<float>::infinity(); |
|||
float max = -std::numeric_limits<float>::infinity(); |
|||
for ( const Vector& vertex : vertices ) { |
|||
double p = axis.scalarProduct(vertex); |
|||
if ( p < min ) { |
|||
min = p; |
|||
} |
|||
if ( p > max ) { |
|||
max = p; |
|||
} |
|||
} |
|||
return Projection(min, max); |
|||
} |
|||
const std::string to_string() { |
|||
std::string result = "[ "; |
|||
for ( Vector& vertex : vertices ) { |
|||
result += vertex.to_string(); |
|||
} |
|||
result += "]"; |
|||
return result; |
|||
} |
|||
private: |
|||
void computeVertices(const std::vector<Point>& points) { |
|||
for ( const Point& point : points ) { |
|||
vertices.emplace_back(Vector(point.x, point.y)); |
|||
} |
|||
} |
|||
void computeAxes() { |
|||
for ( size_t i = 0; i < vertices.size(); i++ ) { |
|||
Vector vertex1 = vertices[i]; |
|||
Vector vertex2 = vertices[( i + 1 ) % vertices.size()]; |
|||
Vector edge = vertex1.edgeWith(vertex2); |
|||
axes.emplace_back(edge.perpendicular()); |
|||
} |
|||
} |
|||
std::vector<Vector> vertices; |
|||
std::vector<Vector> axes; |
|||
}; |
|||
class Rectangle { |
|||
public: |
|||
float x; |
|||
float y; |
|||
float width; |
|||
float height; |
|||
}; |
|||
Polygon rectangleToPolygon(const Rectangle& rectangle) { |
|||
return Polygon(std::vector<Point> { Point(rectangle.x, rectangle.y), |
|||
Point(rectangle.x + rectangle.width, rectangle.y), |
|||
Point(rectangle.x + rectangle.width, rectangle.y + rectangle.height), |
|||
Point(rectangle.x, rectangle.y + rectangle.height) }); |
|||
} |
|||
int main() { |
|||
Polygon polygon(std::vector<Point> { Point(0.0, 0.0), Point(0.0, 2.0), Point(1.0, 4.0), |
|||
Point(2.0, 2.0), Point(2.0, 0.0) } ); |
|||
Rectangle rectangle1(4.0, 0.0, 2.0, 2.0); |
|||
Rectangle rectangle2(1.0, 0.0, 8.0, 2.0); |
|||
Polygon polygon1 = rectangleToPolygon(rectangle1); |
|||
Polygon polygon2 = rectangleToPolygon(rectangle2); |
|||
std::cout << "polygon: " << polygon.to_string() << std::endl; |
|||
std::cout << "rectangle1: " << polygon1.to_string() << std::endl; |
|||
std::cout << "rectangle2: " << polygon2.to_string() << std::endl; |
|||
std::cout << std::boolalpha << std::endl; |
|||
std::cout << "polygon and polygon2 overlap? " << polygon.overlaps(polygon1) << std::endl; |
|||
std::cout << "polygon and polygon3 overlap? " << polygon.overlaps(polygon2) << std::endl; |
|||
} |
|||
</syntaxhighlight> |
|||
{{ out }} |
|||
<pre> |
|||
polygon: [ (0.000000, 0.000000) (0.000000, 2.000000) (1.000000, 4.000000) (2.000000, 2.000000) (2.000000, 0.000000) ] |
|||
rectangle1: [ (4.000000, 0.000000) (6.000000, 0.000000) (6.000000, 2.000000) (4.000000, 2.000000) ] |
|||
rectangle2: [ (1.000000, 0.000000) (9.000000, 0.000000) (9.000000, 2.000000) (1.000000, 2.000000) ] |
|||
polygon and polygon2 overlap? false |
|||
polygon and polygon3 overlap? true |
|||
</pre> |
</pre> |
||