Help with rotation stuff

I’ve been working on this a while and I just can’t figure it out. Bare bones, I am trying to detect if a point is inside a rotated rectangle. The starting values that I have is:

  • Rotation amount in degrees
  • Center point of the rectangle
  • Width and height of the rectangle
  • x,y values of the point

The simplest approach I can think of is to first find the 4 corners of the rectangle then go from there, but I can’t even figure out how to do that.

I tried putting what I have into openprocessnig. I don’t really use this so I hope this worked:
https://www.openprocessing.org/sketch/563832

Note: In reality I will be using an image eventually so that is why it is based off rectangle centerpoint, because it made image rotation smoother

1 Like

This is more a math question than a coding question. I don’t know how to do this off the top of my head, but if I were you I would start with a google search of “point inside rotated rectangle” which returns a bunch of promising results.

Here are a couple that I would start with:

1 Like

***EDIT: I just notice this is a p5.js question. Below is the concept demonstrated using processing java.

This is an excellent case that demonstrates one reference frame is more convenient than another one. In fact, this not only applies to points but also to circles when checking for coincidence against other geometries. Instead of applying the rotating to the rectangle, you can calculate the coordinates of your point in the rotated frame of the rectangle and then test if it is inside of it. That is, instead of rotating the rectangle theta degrees, you rotated the point. In Cartesian coordinate system, you rotate the position of the point -theta degrees (notice the minus sign).

In Processing, you need to watch for the inversion of the y dimension. I correct for this using explicit inversion via scale() function. Notice that mouseX/mouseY is not affected by transformations on your sketch, so you have to apply those transformations manually to it.

In the following code, you can choose where to place your point using mouseX/Y. When pressing the mouse, the rectangle is shown with no rotation and the point is transformed. Code below.

I used straight simple geometry to calculate the angle. you can use heading() from PVector, which is shown and commented out in the code.

Kf

point_inside_rotated_rectangle

//===========================================================================
// FINAL FIELDS:
final color ORANGE=color(250,150,0);
final color GREEN=color(0,250,0);
final color BLUE=color(0,0,250);

//===========================================================================
// GLOBAL VARIABLES:
float x, y;
float theta=30; //Rectangle rotation, in degrees


//===========================================================================
// PROCESSING DEFAULT FUNCTIONS:

void settings() {
  size(600, 400);
}

void setup() {

  //textAlign(CENTER, CENTER);
  rectMode(CENTER);
  textSize(18);

  x=width*0.4;
  y=0;
}



void draw() {
  background(0);
  translate(width/2, height/2);

  drawHelpingLines();

  pushMatrix();
  scale(1, -1);  //Invert y axis to match cartesian system
  
  
  if (!mousePressed) {
    //Draws user point and rotated rectangle
    surface.setTitle("Hold mouse down to see transformed point, unrotated rect");    

    x=mouseX-width/2;
    y=-mouseY+height/2;  //Invert mouse

    
    drawPoint(x,y,GREEN); 

    rotate(radians(theta));    
    drawRectangle();
    
  } else {

    //calculates original angle of giving coordinate point
    float phi= x!=0 ? atan2(y, x) : 0;  //Value in radians, checks for zero div!
    float hyp=sqrt(x*x+y*y);
    float nx=hyp*cos(phi-radians(theta));
    float ny=hyp*sin(phi-radians(theta));
    surface.setTitle("Ref frame theta:"+theta+" Phi:"+nf(degrees(phi), 0, 1));
    
    ////ANOTHER way to calculate the angle
    //PVector v=new PVector(x,y);
    //println(v.heading()+" "+phi);  //Same value

    //Draws un-rotated rectangle and transformed user point    
    drawPoint(nx,ny,ORANGE);    
    drawRectangle();
  }
  popMatrix();


  text("User point [X,Y] \n " +x+","+y, width*0.2, -height*0.4);
}



//===========================================================================
// OTHER FUNCTIONS:

void drawRectangle() {
  noStroke();
  fill(255, 125);
  rect(0, 0, width/2, height/4);
}

void drawPoint(float xx, float yy, color c) {
  strokeWeight(16);
  stroke(c);    
  point(xx,yy);
}

void drawHelpingLines() {
  strokeWeight(1);
  stroke(BLUE); 
  line(-width/2, 0, width/2, 0);
  line(0, -height/2, 0, height/2);

  stroke(255, 0, 0, 180); //red
  noFill();
  float hyp=sqrt(x*x+y*y);
  ellipse(0, 0, 2*hyp, 2*hyp);
}

3 Likes

I won’t be home all day but this looks pretty good. I’ll try it out as soon as I can

@kfrajer’s approach is a more elegant use of frames of reference in processing. If you wanted a more general purpose approach, you could treat your rotated-rectangle as an arbitrary polygon.

Then do compute polygon-point collision detection to find whether x,y is inside the vertex list.

boolean polyPoint(PVector[] vertices, float px, float py)

For detailed example with discussion, see:

http://www.jeffreythompson.org/collision-detection/poly-point.php

1 Like

If the point P you are interested in is [px,py], the centre of the rectangle is [cx, cy], the size of the rectangle is [w, h] and the angle of rotation is [a] radians then a simple algorithm to see if P is inside the algorithm is

  1. Calculate the position [px - cx, py - cy]
  2. Rotate this position -a radians about the origin [0. 0]
  3. See if this position is inside the equivalent unrotated, untranslated rectangle

This sketch demonstrates this algorithm

float cx, cy, w, h, a;

void setup() {
  size(400, 360);
  cursor(CROSS);
  cx = width/2;
  cy = height/2;
  a = PI / 8.27;
  w = 280;
  h = 75;
}

void draw() {
  background(0);
  a += 0.01;
  drawRect();
  drawPoint(mouseX, mouseY);
}

void drawPoint(float px, float py) {
  float dx = px - cx;
  float dy = py - cy;
  float nx = dx*cos(-a) - dy*sin(-a);
  float ny = dy*cos(-a) + dx*sin(-a);
  boolean inside = (abs(nx) < w/2) && (abs(ny) < h/2);
  if (inside) {
    fill(255, 0, 0);
  } else {
    fill(0, 255, 0);
  }
  noStroke();
  ellipse(px, py, 10, 10);
}

void drawRect() {
  fill(255, 255, 200);
  stroke(255, 255, 0);
  pushMatrix();
  translate(cx, cy);
  rotate(a);
  rect(-w/2, -h/2, w, h);
  popMatrix();
}
2 Likes

I have uploaded this sketch to OpenProcessing

2 Likes