retrieve perimeter points relative to center point in grid - grid

Given p(0,0), how do I retrieve points{(0,1),(1,1),(1,0),(1,-1),(0,-1),(-1,-1),(-1,0),(-1,1)} which are the perimeter points relative to p offset by 1.

for(x = p.x -1; x <= p.x + 1; x++) {
for(y = p.y -1; y <= p.y + 1; y++) {
// Do some stuff with each p
}
}
Generic code here. Alter for your programming language and how you store the points.

Related

How to apply an effect to an image using the mouse coordinates?

I coded a program on Processing where all the pixels on the screen are scrambled, but around the cursor. The code works by replacing the pixels with a random pixel between 0 and the pixel the loop is currently on. To find that pixel, I used the code (y*width+x)-1. This code, however, is taking pixels from the entire screen. I want the code to instead take the pixels from a 40m square around the mouse coordinates. How can I do this?
import processing.video.*;
Capture video;
void setup() {
size(640, 480);
video = new Capture(this, 640, 480);
video.start();
}
void draw() {
loadPixels();
if (video.available()){
video.read();
video.loadPixels();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
pixels[y*width+x] = video.pixels[y*video.width+(width-x-1)];
// the code should only be applied 20 pixels around the mouse
if (dist(mouseX, mouseY, x, y) < 20){
int d = int(random(0, y*width+x-1));
pixels[y*width+x] = video.pixels[d];
}
}
}
}
updatePixels();
}
You don't need to iterate through all the pixels to only change a few.
Luckily your sketch is the same size as the webcam feed, so you're on the right track using the x + (y + width) arithmetic to convert from a 2D array index to the 1D pixels[] index. Remember that you're sampling from a 1D array currently (random 0, coords). Even if you upate the start/end index that's still a range that will span a few full image rows which means pixels to the left and right of the effect selection. I recommend picking the random x, y indices in 2D, then converting these random values to 1D (as opposed to a single index from the 1D array).
Here's what I mean:
import processing.video.*;
Capture video;
void setup() {
size(640, 480);
video = new Capture(this, 640, 480);
video.start();
}
void draw() {
loadPixels();
if (video.available()) {
video.read();
video.loadPixels();
//for (int y = 0; y < height; y++) {
// for (int x = 0; x < width; x++) {
// pixels[y*width+x] = video.pixels[y*video.width+(width-x-1)];
// // the code should only be applied 20 pixels around the mouse
// if (dist(mouseX, mouseY, x, y) < 20) {
// int d = int(random(0, y*width+x-1));
// pixels[y*width+x] = video.pixels[d];
// }
// }
//}
// mouse x, y shorthand
int mx = mouseX;
int my = mouseY;
// random pixels effect size
int size = 40;
// half of size
int hsize = size / 2;
// 2D pixel coordinates of the effect's bounding box
int minX = mx - hsize;
int maxX = mx + hsize;
int minY = my - hsize;
int maxY = my + hsize;
// apply the effect only where the bounding can be applied
// e.g. avoid a border (of hsize) around edges of the image
if (mx >= hsize && mx < width - hsize &&
my >= hsize && my < height - hsize) {
for(int y = minY; y < maxY; y++){
for(int x = minX; x < maxX; x++){
// pick random x,y coordinates to sample a pixel from
int rx = (int)random(minX, maxX);
int ry = (int)random(minY, maxY);
// convert the 2D random coordinates to a 1D pixel[] index
int ri = rx + (ry * width);
// replace current pixel with randomly sampled pixel (within effect bbox)
pixels[x + (y * width)] = video.pixels[ri];
}
}
}
}
updatePixels();
}
(Note that the above isn't tested, but hopefully the point gets across)

How to check if a circle is "outside" of a polygon?

I'm trying to write a function to check if a circle is contained inside a polygon.
My algorithm is:
if they intersect, return false
if the circle is "outside" of the polygon, return false
return true
by outside, I mean something like this:
I thought about creating a line segment between the center of the circle and the center of the polygon, and if they intersect an edge on the polygon then the circle is outside of the polygon.
But is there another way to do it?
If the centre of the circle is inside the polygon, the circle is either overlapping or inside it.
If any point of the polygon lies on or inside the circle, they are overlapping.
If any line-segment of the polygon is intersecting the circle, they are overlapping.
Otherwise the circle is outside the polygon.
Something like this should work (C++):
#include <iostream>
#include <vector>
#include <cmath>
namespace math
{
struct Point
{
int x;
int y;
};
bool PointInCircle(Point p, Point center, std::size_t radius)
{
return ((p.x - center.x) * (p.x - center.x) + (p.y - center.y) * (p.y - center.y)) < (radius * radius);
}
bool PointOnCircle(Point p, Point center, std::size_t radius)
{
return ((p.x - center.x) * (p.x - center.x) + (p.y - center.y) * (p.y - center.y)) == (radius * radius);
}
bool LineIntersectsCircle(int ax, int by, int c, Point center, std::size_t radius)
{
// radius == distance = touching/tangent
// radius > distance = not intersecting
// radius < distance = intersecting
int distance = (std::abs(ax * center.x + by * center.y + c)) / sqrt(ax * ax + by * by);
return distance <= radius;
}
bool PointInPolygon(Point p, std::vector<Point> poly)
{
bool result = false;
std::size_t j = poly.size();
for (std::size_t i = 0; i < poly.size(); ++i)
{
if (((poly[i].y <= p.y && p.y < poly[j].y) || (poly[j].y <= p.y && p.y < poly[i].y))
&&
p.x < ((poly[j].x - poly[i].x) * (p.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x))
{
result = !result;
}
j = i;
}
return result;
}
bool CircleInsidePolygon(Point center, std::size_t radius, std::vector<Point> poly)
{
// Circle with radius 0 isn't a circle
if (radius == 0)
{
return false;
}
// If the center of the circle is not within the polygon,
// then the circle may overlap, but it'll never be "contained"
// so return false
if (!PointInPolygon(center, poly))
{
return false;
}
for (std::size_t i = 0; i < poly.size(); ++i)
{
// If any point of the polygon is within the circle,
// the circle is not "contained"
// so return false
if (PointInCircle(poly[i], center, radius))
{
return false;
}
}
for (std::size_t i = 0; i < poly.size(); ++i)
{
// If any line-segment of the polygon intersects the circle,
// the circle is not "contained"
// so return false
Point P1 = i == 0 ? poly[0] : poly[i];
Point P2 = i == 0 ? poly[poly.size() - 1] : poly[i + 1];
int X1 = P1.x;
int X2 = P2.x;
int Y1 = P1.y;
int Y2 = P2.y;
int A = Y1 - Y2;
int B = X2 - X1;
int C = (X1 * Y2) - (X2 * Y1);
if (LineIntersectsCircle(A, B, C, center, radius))
{
return false;
}
}
return true;
}
bool CircleOutsidePolygon(Point center, std::size_t radius, std::vector<Point> poly)
{
// Circle with radius 0 isn't a circle
if (radius == 0)
{
return false;
}
// If the center of the circle is within the polygon,
// the circle is not outside of the polygon completely.
// so return false.
if (PointInPolygon(center, poly))
{
return false;
}
for (std::size_t i = 0; i < poly.size(); ++i)
{
// If any point of the polygon is within the circle,
// or any point of the polygon lies on the circle,
// the circle is not outside of the polygon
// so return false.
if (PointInCircle(poly[i], center, radius) || PointOnCircle(poly[i], center, radius))
{
return false;
}
}
for (std::size_t i = 0; i < poly.size(); ++i)
{
// If any line-segment of the polygon intersects the circle,
// the circle is not outside the polygon, it is overlapping,
// so return false
Point P1 = i == 0 ? poly[0] : poly[i];
Point P2 = i == 0 ? poly[poly.size() - 1] : poly[i + 1];
int X1 = P1.x;
int X2 = P2.x;
int Y1 = P1.y;
int Y2 = P2.y;
int A = Y1 - Y2;
int B = X2 - X1;
int C = (X1 * Y2) - (X2 * Y1);
if (LineIntersectsCircle(A, B, C, center, radius))
{
return false;
}
}
return true;
}
}
int main()
{
std::size_t radius = 1;
math::Point p = {-2, -2};
std::vector<math::Point> poly = {
{0, 0},
{100, 0},
{100, 100},
{0, 100}
};
bool is_inside = math::CircleInsidePolygon(p, radius, poly);
bool is_outside = math::CircleOutsidePolygon(p, radius, poly);
bool is_intersecting = !is_inside && !is_outside;
std::cout<<"Circle In Polygon: "<<std::boolalpha<<is_inside<<"\n";
std::cout<<"Circle Outside Polygon: "<<std::boolalpha<<is_outside<<"\n";
std::cout<<"Circle Intersecting Polygon: "<<std::boolalpha<<is_intersecting<<"\n";
return 0;
}
You have a polygon defined by a list of points A0, A1, A2, ..., Ak, and a circle defined by a center C and a radius r.
Possible algorithm:
Find whether the center C is inside the polygon or not;
If C is outside the polygon, return False.
Else, find the point P on the polygon which is closest to the circle center C;
Compare the distance PC with the radius r.
Return the boolean value r < PC.
This leaves us with two sub-problems to solve:
How to find whether point C is inside the polygon;
How to find the closest point on the polygon.
Related questions solving these sub-problems:
Distance from a point to a polygon;
javascript: How can I find closest point on a polygon from a point?;
How can I determine whether a 2D Point is within a Polygon?;
javascript: Check if Point Is Inside A Polygon;
C: Point in polygon algorithm;
python matplotlib: What's the fastest way of checking if a point is inside a polygon in python.

Calculating rotation of equally spaced items tangent to spiral

I'd like to programmatically draw a shape like this where there is an underlying spiral and equally spaced objects along it, placed tangent to the spiral as shown in this sketch:
I found an example of how to determine equally spaced points along the spiral here and am now trying to place hemispheres along the spiral. However, I'm not sure how to calculate the angle the shape needs to be rotated.
This is what I have so far (viewable here):
var totalSegments = 235,hw = 320,hh = 240,segments;
var len = 15;
points = [];
function setup(){
createCanvas(640,480);
smooth();
colorMode(HSB,255,100,100);
stroke(0);
noFill();
//println("move cursor vertically");
}
function draw(){
background(0);
translate(hw,hh);
segments = floor(totalSegments);
points = getTheodorus(segments,len);
angles = getAngles(segments, len);
for(var i = 0 ; i < segments ; i++){
let c = color('blue');
fill(c);
noStroke();
// draw shape
if(i % 2){
// console.log(i, ' ', angles[i]);
// try rotating around the object's center
push();
// translate(points[i].x, points[i].y)
rotate(PI/angles[i]);
arc(points[i].x, points[i].y, len*3, len*3, 0, 0 + PI);
pop();
}
// draw spiral
strokeWeight(20);
stroke(0,0,100,(20+i/segments));
if(i > 0) line(points[i].x,points[i].y,points[i-1].x,points[i-1].y);
}
}
function getAngles(segment, len){
let angles = [];
let radius = 0;
let angle = 0;
for(var i =0; i < segments; i++){
radius = sqrt(i+1);
angle += asin(1/radius);
angles[i] = angle;
}
return angles;
}
function getTheodorus(segments,len){
var result = [];
var radius = 0;
var angle = 0;
for(var i = 0 ; i < segments ; i++){
radius = sqrt(i+1);
angle += asin(1/radius);
result[i] = new p5.Vector(cos(angle) * radius*len,sin(angle) * radius*len);
}
return result;
}
Note that your drawing shows Archimedean spiral while link refers to Theodorus one.
Archimedean spiral is described by equation in polar coordinates (rho-theta)
r = a + b * Theta
where a is initial angle, b is scale value (describes distance between arms), r is radius.
And angle Theta + Pi/2 describes normal to spiral in point at parameter Theta
If you need an approximation to divide spiral into (almost) equal segments - use Clackson formula (example here)
theta = 2 * Pi * Sqrt(2 * s / b)
for arc length s

Using Recursion for 3D Array Manipulation -- Causing StackOverflow (not Infinite!)

I recently posted a question yesterday about a similar issue, but I have coded up something a little different and now have a different problem. Here is my code that is causing a StackOverflow.
** Note that the 3D grid array is upwards of 1 million elements and can reach up to around 64 million elements (stores enums).
** Also note that this is not going into infinity. On small data sets, this algorithm works fine.
Is this likely caused by the extreme recursion? How do I handle this (this is an essential part of my algorithm!)? I've done some research and have heard using a queue, for even just massive for-loops.
What will reduce the likelihood of causing a stackoverflow?
Thank you!
/**
* Fills all void cells in the 3D grid of Atom.
*
* #param x
* The starting x coordinate
* #param y
* The starting y coordinate
* #param z
* The starting z coordinate
*/
private void fillAllVoidCells(int x, int y, int z)
{
// Base case -- If not BLOATED_ATOM, BOUNDING_BOX,
// or VOID then must be a cavity (only 4 CellType
// enum types.
if ((grid[x][y][z] == CellType.BLOATED_ATOM)
|| grid[x][y][z] == CellType.BOUNDING_BOX
|| grid[x][y][z] == CellType.VOID)
{
// Pop off runtime stack
return;
}
else
{
// Set to void then check all surrounding cells.
grid[x][y][z] = CellType.VOID;
fillAllVoidCells(x + 1, y, z); // right
fillAllVoidCells(x - 1, y, z); // left
fillAllVoidCells(x, y + 1, z); // in front
fillAllVoidCells(x, y - 1, z); // behind
fillAllVoidCells(x, y, z + 1); // above
fillAllVoidCells(x, y, z - 1); // below
}
}
===== EDIT ====== New Method Implemented Using a Stack (per Roee Gavirel help)
Would this be a correct implementation?
// ----------------------------------------------------------
/**
* Fills all void cells in the 3D grid of Atom.
*
* #param x
* The starting x coordinate
* #param y
* The starting y coordinate
* #param z
* The starting z coordinate
*/
private void fillAllVoidCells(int x, int y, int z)
{
Point p = new Point(x, y, z);
stack.push(p);
while (!stack.isEmpty())
p = stack.top();
stack.pop();
// Base case -- If not BLOATED_ATOM, BOUNDING_BOX,
// or VOID then must be a cavity (only 4 CellType
// enum types.
CellType state = grid[p.x][p.y][p.z];
if ((state == CellType.BLOATED_ATOM) || state == CellType.BOUNDING_BOX
|| state == CellType.VOID)
{
return;
}
else
{
// Set to void then check all surrounding cells.
grid[p.x][p.y][p.z] = CellType.VOID;
Point tempP = p;
tempP.x = p.x - 1;
stack.push(tempP);
tempP.x = p.x + 1;
stack.push(tempP);
tempP.x = p.x; // return to original x coordinate
tempP.y = p.y - 1;
stack.push(tempP);
tempP.y = p.y + 1;
stack.push(tempP);
tempP.y = p.y; // return to original y coordiante
tempP.z = p.z - 1;
stack.push(tempP);
tempP.z = p.z + 1;
stack.push(tempP);
tempP.z = p.z; // return to original z coordinate
}
}
This is most likely to cause an overflow. what you can (and should) do to avoid it is to use your own stack for the data and avoid recursion.
In you case:
1. have a stack of relevant points (x,y,z) which have the point you initially called fillAllVoidCells with.
2. while the stack is not empty you should do your checks
3. If it's cavity add the surrounding points to the stack.
==EDIT==
something like that:
struct point {
int x,y,z;
}
private void fillAllVoidCells(int x, int y, int z)
{
std::list<point> Ps;
point p;
p.x = x;
p.y = y;
p.z = z;
Ps.push_back(p);
while (!Ps.empty())
p = Ps.back();
Ps.pop_back();
// Base case -- If not BLOATED_ATOM, BOUNDING_BOX,
// or VOID then must be a cavity (only 4 CellType
// enum types.
auto state = grid[p.x][p.y][p.z];
if ((state == CellType.BLOATED_ATOM)
|| state == CellType.BOUNDING_BOX
|| state == CellType.VOID)
{
continue;
}
else
{
// Set to void then check all surrounding cells.
grid[p.x][p.y][p.z] = CellType.VOID;
point tempP = p;
tempP.x = P.x - 1;
Ps.push_back(tempP);
tempP.x = P.x + 1;
Ps.push_back(tempP);
tempP.y = P.y - 1;
Ps.push_back(tempP);
tempP.y = P.y + 1;
Ps.push_back(tempP);
tempP.z = P.z - 1;
Ps.push_back(tempP);
tempP.z = P.z + 1;
Ps.push_back(tempP);
}
}
}

How to check intersection between 2 rotated rectangles?

Can someone explain how to check if one rotated rectangle intersect other rectangle?
For each edge in both polygons, check if it can be used as a separating line. If so, you are done: No intersection.
If no separation line was found, you have an intersection.
/// Checks if the two polygons are intersecting.
bool IsPolygonsIntersecting(Polygon a, Polygon b)
{
foreach (var polygon in new[] { a, b })
{
for (int i1 = 0; i1 < polygon.Points.Count; i1++)
{
int i2 = (i1 + 1) % polygon.Points.Count;
var p1 = polygon.Points[i1];
var p2 = polygon.Points[i2];
var normal = new Point(p2.Y - p1.Y, p1.X - p2.X);
double? minA = null, maxA = null;
foreach (var p in a.Points)
{
var projected = normal.X * p.X + normal.Y * p.Y;
if (minA == null || projected < minA)
minA = projected;
if (maxA == null || projected > maxA)
maxA = projected;
}
double? minB = null, maxB = null;
foreach (var p in b.Points)
{
var projected = normal.X * p.X + normal.Y * p.Y;
if (minB == null || projected < minB)
minB = projected;
if (maxB == null || projected > maxB)
maxB = projected;
}
if (maxA < minB || maxB < minA)
return false;
}
}
return true;
}
For more information, see this article: 2D Polygon Collision Detection - Code Project
NB: The algorithm only works for convex polygons, specified in either clockwise, or counterclockwise order.
In javascript, the exact same algorithm is (for convenience):
/**
* Helper function to determine whether there is an intersection between the two polygons described
* by the lists of vertices. Uses the Separating Axis Theorem
*
* #param a an array of connected points [{x:, y:}, {x:, y:},...] that form a closed polygon
* #param b an array of connected points [{x:, y:}, {x:, y:},...] that form a closed polygon
* #return true if there is any intersection between the 2 polygons, false otherwise
*/
function doPolygonsIntersect (a, b) {
var polygons = [a, b];
var minA, maxA, projected, i, i1, j, minB, maxB;
for (i = 0; i < polygons.length; i++) {
// for each polygon, look at each edge of the polygon, and determine if it separates
// the two shapes
var polygon = polygons[i];
for (i1 = 0; i1 < polygon.length; i1++) {
// grab 2 vertices to create an edge
var i2 = (i1 + 1) % polygon.length;
var p1 = polygon[i1];
var p2 = polygon[i2];
// find the line perpendicular to this edge
var normal = { x: p2.y - p1.y, y: p1.x - p2.x };
minA = maxA = undefined;
// for each vertex in the first shape, project it onto the line perpendicular to the edge
// and keep track of the min and max of these values
for (j = 0; j < a.length; j++) {
projected = normal.x * a[j].x + normal.y * a[j].y;
if (isUndefined(minA) || projected < minA) {
minA = projected;
}
if (isUndefined(maxA) || projected > maxA) {
maxA = projected;
}
}
// for each vertex in the second shape, project it onto the line perpendicular to the edge
// and keep track of the min and max of these values
minB = maxB = undefined;
for (j = 0; j < b.length; j++) {
projected = normal.x * b[j].x + normal.y * b[j].y;
if (isUndefined(minB) || projected < minB) {
minB = projected;
}
if (isUndefined(maxB) || projected > maxB) {
maxB = projected;
}
}
// if there is no overlap between the projects, the edge we are looking at separates the two
// polygons, and we know there is no overlap
if (maxA < minB || maxB < minA) {
CONSOLE("polygons don't intersect!");
return false;
}
}
}
return true;
};
Hope this helps someone.
Here's the same algorithm in Java if anybody is interested.
boolean isPolygonsIntersecting(Polygon a, Polygon b)
{
for (int x=0; x<2; x++)
{
Polygon polygon = (x==0) ? a : b;
for (int i1=0; i1<polygon.getPoints().length; i1++)
{
int i2 = (i1 + 1) % polygon.getPoints().length;
Point p1 = polygon.getPoints()[i1];
Point p2 = polygon.getPoints()[i2];
Point normal = new Point(p2.y - p1.y, p1.x - p2.x);
double minA = Double.POSITIVE_INFINITY;
double maxA = Double.NEGATIVE_INFINITY;
for (Point p : a.getPoints())
{
double projected = normal.x * p.x + normal.y * p.y;
if (projected < minA)
minA = projected;
if (projected > maxA)
maxA = projected;
}
double minB = Double.POSITIVE_INFINITY;
double maxB = Double.NEGATIVE_INFINITY;
for (Point p : b.getPoints())
{
double projected = normal.x * p.x + normal.y * p.y;
if (projected < minB)
minB = projected;
if (projected > maxB)
maxB = projected;
}
if (maxA < minB || maxB < minA)
return false;
}
}
return true;
}
Check out the method designed by Oren Becker to detect intersection of rotated rectangles with form:
struct _Vector2D
{
float x, y;
};
// C:center; S: size (w,h); ang: in radians,
// rotate the plane by [-ang] to make the second rectangle axis in C aligned (vertical)
struct _RotRect
{
_Vector2D C;
_Vector2D S;
float ang;
};
And calling the following function will return whether two rotated rectangles intersect or not:
// Rotated Rectangles Collision Detection, Oren Becker, 2001
bool check_two_rotated_rects_intersect(_RotRect * rr1, _RotRect * rr2)
{
_Vector2D A, B, // vertices of the rotated rr2
C, // center of rr2
BL, TR; // vertices of rr2 (bottom-left, top-right)
float ang = rr1->ang - rr2->ang, // orientation of rotated rr1
cosa = cos(ang), // precalculated trigonometic -
sina = sin(ang); // - values for repeated use
float t, x, a; // temporary variables for various uses
float dx; // deltaX for linear equations
float ext1, ext2; // min/max vertical values
// move rr2 to make rr1 cannonic
C = rr2->C;
SubVectors2D(&C, &rr1->C);
// rotate rr2 clockwise by rr2->ang to make rr2 axis-aligned
RotateVector2DClockwise(&C, rr2->ang);
// calculate vertices of (moved and axis-aligned := 'ma') rr2
BL = TR = C;
/*SubVectors2D(&BL, &rr2->S);
AddVectors2D(&TR, &rr2->S);*/
//-----------------------------------
BL.x -= rr2->S.x/2; BL.y -= rr2->S.y/2;
TR.x += rr2->S.x/2; TR.y += rr2->S.y/2;
// calculate vertices of (rotated := 'r') rr1
A.x = -(rr1->S.y/2)*sina; B.x = A.x; t = (rr1->S.x/2)*cosa; A.x += t; B.x -= t;
A.y = (rr1->S.y/2)*cosa; B.y = A.y; t = (rr1->S.x/2)*sina; A.y += t; B.y -= t;
//---------------------------------------
//// calculate vertices of (rotated := 'r') rr1
//A.x = -rr1->S.y*sina; B.x = A.x; t = rr1->S.x*cosa; A.x += t; B.x -= t;
//A.y = rr1->S.y*cosa; B.y = A.y; t = rr1->S.x*sina; A.y += t; B.y -= t;
t = sina*cosa;
// verify that A is vertical min/max, B is horizontal min/max
if (t < 0)
{
t = A.x; A.x = B.x; B.x = t;
t = A.y; A.y = B.y; B.y = t;
}
// verify that B is horizontal minimum (leftest-vertex)
if (sina < 0) { B.x = -B.x; B.y = -B.y; }
// if rr2(ma) isn't in the horizontal range of
// colliding with rr1(r), collision is impossible
if (B.x > TR.x || B.x > -BL.x) return 0;
// if rr1(r) is axis-aligned, vertical min/max are easy to get
if (t == 0) {ext1 = A.y; ext2 = -ext1; }
// else, find vertical min/max in the range [BL.x, TR.x]
else
{
x = BL.x-A.x; a = TR.x-A.x;
ext1 = A.y;
// if the first vertical min/max isn't in (BL.x, TR.x), then
// find the vertical min/max on BL.x or on TR.x
if (a*x > 0)
{
dx = A.x;
if (x < 0) { dx -= B.x; ext1 -= B.y; x = a; }
else { dx += B.x; ext1 += B.y; }
ext1 *= x; ext1 /= dx; ext1 += A.y;
}
x = BL.x+A.x; a = TR.x+A.x;
ext2 = -A.y;
// if the second vertical min/max isn't in (BL.x, TR.x), then
// find the local vertical min/max on BL.x or on TR.x
if (a*x > 0)
{
dx = -A.x;
if (x < 0) { dx -= B.x; ext2 -= B.y; x = a; }
else { dx += B.x; ext2 += B.y; }
ext2 *= x; ext2 /= dx; ext2 -= A.y;
}
}
// check whether rr2(ma) is in the vertical range of colliding with rr1(r)
// (for the horizontal range of rr2)
return !((ext1 < BL.y && ext2 < BL.y) ||
(ext1 > TR.y && ext2 > TR.y));
}
inline void AddVectors2D(_Vector2D * v1, _Vector2D * v2)
{
v1->x += v2->x; v1->y += v2->y;
}
inline void SubVectors2D(_Vector2D * v1, _Vector2D * v2)
{
v1->x -= v2->x; v1->y -= v2->y;
}
inline void RotateVector2DClockwise(_Vector2D * v, float ang)
{
float t, cosa = cos(ang), sina = sin(ang);
t = v->x;
v->x = t*cosa + v->y*sina;
v->y = -t*sina + v->y*cosa;
}
In Python:
def do_polygons_intersect(a, b):
"""
* Helper function to determine whether there is an intersection between the two polygons described
* by the lists of vertices. Uses the Separating Axis Theorem
*
* #param a an ndarray of connected points [[x_1, y_1], [x_2, y_2],...] that form a closed polygon
* #param b an ndarray of connected points [[x_1, y_1], [x_2, y_2],...] that form a closed polygon
* #return true if there is any intersection between the 2 polygons, false otherwise
"""
polygons = [a, b];
minA, maxA, projected, i, i1, j, minB, maxB = None, None, None, None, None, None, None, None
for i in range(len(polygons)):
# for each polygon, look at each edge of the polygon, and determine if it separates
# the two shapes
polygon = polygons[i];
for i1 in range(len(polygon)):
# grab 2 vertices to create an edge
i2 = (i1 + 1) % len(polygon);
p1 = polygon[i1];
p2 = polygon[i2];
# find the line perpendicular to this edge
normal = { 'x': p2[1] - p1[1], 'y': p1[0] - p2[0] };
minA, maxA = None, None
# for each vertex in the first shape, project it onto the line perpendicular to the edge
# and keep track of the min and max of these values
for j in range(len(a)):
projected = normal['x'] * a[j][0] + normal['y'] * a[j][1];
if (minA is None) or (projected < minA):
minA = projected
if (maxA is None) or (projected > maxA):
maxA = projected
# for each vertex in the second shape, project it onto the line perpendicular to the edge
# and keep track of the min and max of these values
minB, maxB = None, None
for j in range(len(b)):
projected = normal['x'] * b[j][0] + normal['y'] * b[j][1]
if (minB is None) or (projected < minB):
minB = projected
if (maxB is None) or (projected > maxB):
maxB = projected
# if there is no overlap between the projects, the edge we are looking at separates the two
# polygons, and we know there is no overlap
if (maxA < minB) or (maxB < minA):
print("polygons don't intersect!")
return False;
return True
Maybe it will help someone. The same algorithm in PHP:
function isPolygonsIntersecting($a, $b) {
$polygons = array($a, $b);
for ($i = 0; $i < count($polygons); $i++) {
$polygon = $polygons[$i];
for ($i1 = 0; $i1 < count($polygon); $i1++) {
$i2 = ($i1 + 1) % count($polygon);
$p1 = $polygon[$i1];
$p2 = $polygon[$i2];
$normal = array(
"x" => $p2["y"] - $p1["y"],
"y" => $p1["x"] - $p2["x"]
);
$minA = NULL; $maxA = NULL;
for ($j = 0; $j < count($a); $j++) {
$projected = $normal["x"] * $a[$j]["x"] + $normal["y"] * $a[$j]["y"];
if (!isset($minA) || $projected < $minA) {
$minA = $projected;
}
if (!isset($maxA) || $projected > $maxA) {
$maxA = $projected;
}
}
$minB = NULL; $maxB = NULL;
for ($j = 0; $j < count($b); $j++) {
$projected = $normal["x"] * $b[$j]["x"] + $normal["y"] * $b[$j]["y"];
if (!isset($minB) || $projected < $minB) {
$minB = $projected;
}
if (!isset($maxB) || $projected > $maxB) {
$maxB = $projected;
}
}
if ($maxA < $minB || $maxB < $minA) {
return false;
}
}
}
return true;
}
You can also use Rect.IntersectsWith().
For example, in WPF if you have two UIElements, with RenderTransform and placed on a Canvas, and you want to find out if they intersect you can use something similar:
bool IsIntersecting(UIElement element1, UIElement element2)
{
Rect area1 = new Rect(
(double)element1.GetValue(Canvas.TopProperty),
(double)element1.GetValue(Canvas.LeftProperty),
(double)element1.GetValue(Canvas.WidthProperty),
(double)element1.GetValue(Canvas.HeightProperty));
Rect area2 = new Rect(
(double)element2.GetValue(Canvas.TopProperty),
(double)element2.GetValue(Canvas.LeftProperty),
(double)element2.GetValue(Canvas.WidthProperty),
(double)element2.GetValue(Canvas.HeightProperty));
Transform transform1 = element1.RenderTransform as Transform;
Transform transform2 = element2.RenderTransform as Transform;
if (transform1 != null)
{
area1.Transform(transform1.Value);
}
if (transform2 != null)
{
area2.Transform(transform2.Value);
}
return area1.IntersectsWith(area2);
}
A Type(Java)Script implementation with a toggle to (ex)include "Touch" situations:
class Position {
private _x: number;
private _y: number;
public constructor(x: number = null, y: number = null) {
this._x = x;
this._y = y;
}
public get x() { return this._x; }
public set x(value: number) { this._x = value; }
public get y() { return this._y; }
public set y(value: number) { this._y = value; }
}
class Polygon {
private _positions: Array<Position>;
public constructor(positions: Array<Position> = null) {
this._positions = positions;
}
public addPosition(position: Position) {
if (!position) {
return;
}
if (!this._positions) {
this._positions = new Array<Position>();
}
this._positions.push(position);
}
public get positions(): ReadonlyArray<Position> { return this._positions; }
/**
* https://stackoverflow.com/a/12414951/468910
*
* Helper function to determine whether there is an intersection between the two polygons described
* by the lists of vertices. Uses the Separating Axis Theorem
*
* #param polygonToCompare a polygon to compare with
* #param allowTouch consider it an intersection when polygons only "touch"
* #return true if there is any intersection between the 2 polygons, false otherwise
*/
public isIntersecting(polygonToCompare: Polygon, allowTouch: boolean = true): boolean {
const polygons: Array<ReadonlyArray<Position>> = [this.positions, polygonToCompare.positions]
const firstPolygonPositions: ReadonlyArray<Position> = polygons[0];
const secondPolygonPositions: ReadonlyArray<Position> = polygons[1];
let minA, maxA, projected, i, i1, j, minB, maxB;
for (i = 0; i < polygons.length; i++) {
// for each polygon, look at each edge of the polygon, and determine if it separates
// the two shapes
const polygon = polygons[i];
for (i1 = 0; i1 < polygon.length; i1++) {
// grab 2 vertices to create an edge
const i2 = (i1 + 1) % polygon.length;
const p1 = polygon[i1];
const p2 = polygon[i2];
// find the line perpendicular to this edge
const normal = {
x: p2.y - p1.y,
y: p1.x - p2.x
};
minA = maxA = undefined;
// for each vertex in the first shape, project it onto the line perpendicular to the edge
// and keep track of the min and max of these values
for (j = 0; j < firstPolygonPositions.length; j++) {
projected = normal.x * firstPolygonPositions[j].x + normal.y * firstPolygonPositions[j].y;
if (!minA || projected < minA || (!allowTouch && projected === minA)) {
minA = projected;
}
if (!maxA || projected > maxA || (!allowTouch && projected === maxA)) {
maxA = projected;
}
}
// for each vertex in the second shape, project it onto the line perpendicular to the edge
// and keep track of the min and max of these values
minB = maxB = undefined;
for (j = 0; j < secondPolygonPositions.length; j++) {
projected = normal.x * secondPolygonPositions[j].x + normal.y * secondPolygonPositions[j].y;
if (!minB || projected < minB || (!allowTouch && projected === minB)) {
minB = projected;
}
if (!maxB || projected > maxB || (!allowTouch && projected === maxB)) {
maxB = projected;
}
}
// if there is no overlap between the projects, the edge we are looking at separates the two
// polygons, and we know there is no overlap
if (maxA < minB || (!allowTouch && maxA === minB) || maxB < minA || (!allowTouch && maxB === minA)) {
return false;
}
}
}
return true;
}
Lua implementation built in love2d framework. Collision detection function works in pure lua anyway
math.inf = 1e309
function love.load()
pol = {{0, 0}, {30, 2}, {8, 30}}
pol2 = {{60, 60}, {90, 61}, {98, 100}, {80, 100}}
end
function love.draw()
for k,v in ipairs(pol) do
love.graphics.line(pol[k][1], pol[k][2], pol[k % #pol + 1][1], pol[k % #pol + 1][2])
end
for k,v in ipairs(pol2) do
love.graphics.line(pol2[k][1], pol2[k][2], pol2[k % #pol2 + 1][1], pol2[k % #pol2 + 1][2])
end
end
function love.update(dt)
pol[1][1] = love.mouse.getX()
pol[1][2] = love.mouse.getY()
pol[2][1] = pol[1][1] + 30
pol[2][2] = pol[1][2] + 2
pol[3][1] = pol[1][1] + 8
pol[3][2] = pol[1][2] + 30
--lazy way to see that's function works
print(doPolygonsIntersect(pol, pol2))
end
-------------------------------------------------------------------------
function doPolygonsIntersect(a,b)
polygons = {a,b}
for i=1, #polygons do
polygon = polygons[i]
for i1=1, #polygon do
i2 = i1 % #polygon + 1
p1 = polygon[i1]
p2 = polygon[i2]
nx,ny = p2[2] - p1[2], p1[1] - p2[1]
minA = math.inf
maxA = -math.inf
for j=1, #a do
projected = nx * a[j][1] + ny * a[j][2]
if projected < minA then minA = projected end
if projected > maxA then maxA = projected end
end
minB = math.inf
maxB = -math.inf
for j=1, #b do
projected = nx * b[j][1] + ny * b[j][2]
if projected < minB then minB = projected end
if projected > maxB then maxB = projected end
end
if maxA < minB or maxB < minA then return false end
end
end
return true
end
Took Sri's JavaScript and made it work with Phaser 3 Polygons.
/// Checks if the two Phaser 3 polygons are intersecting.
gameScene.doPolygonsIntersect=function(a, b) {
// https://stackoverflow.com/questions/10962379/how-to-check-intersection-between-2-rotated-rectangles#10965077
/**
* Helper function to determine whether there is an intersection between the two polygons described
* by the lists of vertices. Uses the Separating Axis Theorem
*
* #param a an array of connected points [{x:, y:}, {x:, y:},...] that form a closed polygon
* #param b an array of connected points [{x:, y:}, {x:, y:},...] that form a closed polygon
* #return true if there is any intersection between the 2 polygons, false otherwise
*/
var polygons = [a, b];
var minA, maxA, projected, i, i1, j, minB, maxB;
for (i = 0; i < polygons.length; i++) {
// for each polygon, look at each edge of the polygon, and determine if it separates
// the two shapes
var polygon = polygons[i];
for (i1 = 0; i1 < polygon.points.length; i1++) {
// grab 2 vertices to create an edge
var i2 = (i1 + 1) % polygon.points.length;
var p1 = polygon.points[i1];
var p2 = polygon.points[i2];
// find the line perpendicular to this edge
var normal = { x: p2.y - p1.y, y: p1.x - p2.x };
minA = maxA = undefined;
// for each vertex in the first shape, project it onto the line perpendicular to the edge
// and keep track of the min and max of these values
for (j = 0; j < a.points.length; j++) {
projected = normal.x * a.points[j].x + normal.y * a.points[j].y;
if (!isDef(minA) || projected < minA) {
minA = projected;
}
if (!isDef(maxA) || projected > maxA) {
maxA = projected;
}
}
// for each vertex in the second shape, project it onto the line perpendicular to the edge
// and keep track of the min and max of these values
minB = maxB = undefined;
for (j = 0; j < b.points.length; j++) {
projected = normal.x * b.points[j].x + normal.y * b.points[j].y;
if (!isDef(minB) || projected < minB) {
minB = projected;
}
if (!isDef(maxB) || projected > maxB) {
maxB = projected;
}
}
// if there is no overlap between the projects, the edge we are looking at separates the two
// polygons, and we know there is no overlap
if (maxA < minB || maxB < minA) {
console.log("polygons don't intersect!");
return false;
}
}
}
return true;
};
Here it is in LUA, hope it will help somebody when they need it:
function doPolygonsIntersect(a, b)
local polygons = { a, b };
local minA, maxA, projected, i, i1, j, minB, maxB;
for i = 1, #polygons do
--// for each polygon, look at each edge of the polygon, and determine if it separates
--// the two shapes
local polygon = polygons[i];
for i1 = 0, (#polygon-1) do
--// grab 2 vertices to create an edge
local i2 = (i1 + 1) % (#polygon);
local p1 = polygon[i1+1];
local p2 = polygon[i2+1];
--// find the line perpendicular to this edge
local normal = { x = p2.y - p1.y, y = p1.x - p2.x };
minA = nil;
maxA = nil;
--// for each vertex in the first shape, project it onto the line perpendicular to the edge
--// and keep track of the min and max of these values
for j = 1, #a do
projected = normal.x * a[j].x + normal.y * a[j].y;
if (minA == nil or projected < minA) then
minA = projected;
end
if (maxA == nil or projected > maxA) then
maxA = projected;
end
end
--// for each vertex in the second shape, project it onto the line perpendicular to the edge
--// and keep track of the min and max of these values
minB = nil;
maxB = nil;
for j = 1, #b do
projected = normal.x * b[j].x + normal.y * b[j].y;
if (minB == nil or projected < minB) then
minB = projected;
end
if (maxB == nil or projected > maxB) then
maxB = projected;
end
end
if (maxA < minB or maxB < minA) then
return false;
end
end
end
return true;
end
The accepted algorithm in Go.
func isPolygonIntersecting(a *Polygon, b *Polygon) bool {
for _, polygon := range []*Polygon{a, b} {
for i1 := 0; i1 < len(*polygon); i1++ {
i2 := (i1 + 1) % len(*polygon)
p1 := (*polygon)[i1]
p2 := (*polygon)[i2]
normal := pixel.V(p2.Y-p1.Y, p1.X-p2.X)
minA := math.MaxFloat64
maxA := math.MaxFloat64
for _, p := range *a {
projected := normal.X*p.X + normal.Y*p.Y
if minA == math.MaxFloat64 || projected < minA {
minA = projected
}
if maxA == math.MaxFloat64 || projected > maxA {
maxA = projected
}
}
minB := math.MaxFloat64
maxB := math.MaxFloat64
for _, p := range *b {
projected := normal.X*p.X + normal.Y*p.Y
if minB == math.MaxFloat64 || projected < minB {
minB = projected
}
if maxB == math.MaxFloat64 || projected > maxB {
maxB = projected
}
}
if maxA < minB || maxB < minA {
return false
}
}
}
return true
}
type Polygon []struct {
X float64
Y float64
}
Matlab implementation:
function isIntersecting = IsPolygonsIntersecting(polyVertices1, polyVertices2)
isIntersecting = ...
IsPolygon1Intersecting2( polyVertices1, polyVertices2 ) && ...
IsPolygon1Intersecting2( polyVertices2, polyVertices1 );
end
function isIntersecting = IsPolygon1Intersecting2(polyVertices1,polyVertices2)
nVertices = size(polyVertices1,1);
isIntersecting = true;
for i1 = 1:nVertices
% Current edge vertices:
i2 = mod(i1, nVertices) + 1;
p1 = polyVertices1(i1,:);
p2 = polyVertices1(i2,:);
% Project the polygon vertices on the edge normal and find the extreme values:
normal = [p2(2) - p1(2); p1(1) - p2(1)];
minA = min(polyVertices1 * normal);
maxA = max(polyVertices1 * normal);
minB = min(polyVertices2 * normal);
maxB = max(polyVertices2 * normal);
if (maxA < minB || maxB < minA)
isIntersecting = false;
return;
end
end
end
#dabs's answer https://stackoverflow.com/a/56962827/11846040 converted to Dart:
// `CustomPoint` is just a class holding two x/y or y/x values
class Polygon {
final CustomPoint<num> nw;
final CustomPoint<num> ne;
final CustomPoint<num> se;
final CustomPoint<num> sw;
Polygon(this.nw, this.ne, this.se, this.sw);
List<CustomPoint<num>> get points => [nw, ne, se, sw];
}
bool overlap(Polygon a, Polygon b) {
for (int x = 0; x < 2; x++) {
final Polygon polygon = (x == 0) ? a : b;
for (int i1 = 0; i1 < polygon.points.length; i1++) {
final int i2 = (i1 + 1) % polygon.points.length;
final CustomPoint<num> p1 = polygon.points[i1];
final CustomPoint<num> p2 = polygon.points[i2];
final CustomPoint<num> normal =
CustomPoint<num>(p2.y - p1.y, p1.x - p2.x);
double minA = double.infinity;
double maxA = double.negativeInfinity;
for (CustomPoint<num> p in a.points) {
final num projected = normal.x * p.x + normal.y * p.y;
if (projected < minA) minA = projected.toDouble();
if (projected > maxA) maxA = projected.toDouble();
}
double minB = double.infinity;
double maxB = double.negativeInfinity;
for (CustomPoint<num> p in b.points) {
final num projected = normal.x * p.x + normal.y * p.y;
if (projected < minB) minB = projected.toDouble();
if (projected > maxB) maxB = projected.toDouble();
}
if (maxA < minB || maxB < minA) return false;
}
}
return true;
}
I searched for months to find this answer, but couldn't find it. Enjoy your gift, whoever's looking at this in 15 years time!

Resources