Point "over" object (inside to push ans pop matrix)

Hello,

I need to detect when a point is over an object (mouse, for example), but this object was previously moved, rotated and scaled inside to pushMatrix() and popMatrix()

Any idea or suggestion is welcome and appreciated. Thanks!!

You need to get a hold of the inverse of the matrix that you’re using to transform the object. If you multiply the test point by the inverse matrix, then you can do the test. It helps to make explicit the matrix that’s transforming your object.

You can try something like this:

Box box = new Box(100, 100, 300, 200);

void setup() {
  size(600, 600);
  box.transform.rotate(0.25 * PI);
  box.transform.translate(100, 200);
  box.transform.scale(1.5, 0.75);
}

void draw() {
  box.draw();
  println(boxContainsMouse());
}

boolean boxContainsMouse() {
  box.transform.invert(); // get the inverse of the matrix
  
  // transform the point by the inverse matrix:
  float mx = box.transform.multX(mouseX, mouseY); 
  float my = box.transform.multY(mouseX, mouseY);
  
  box.transform.invert(); // get the inverse of the inverse (the matrix we started with)

  return box.contains(mx, my);
}

class Box {
  float x1, y1, x2, y2;
  PMatrix2D transform; // make explicit the matrix that's transforming the box
  
  Box(float x1, float y1, float x2, float y2) {
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
    this.transform = new PMatrix2D();
  }
  
  void draw() {
    pushMatrix();
    applyMatrix(transform); // transform the box
    rectMode(CORNERS);
    rect(x1, y1, x2, y2);
    popMatrix();
  }
  
  boolean contains(float x, float y) {
    return x1 <= x && x < x2 && y1 <= y && y <= y2;
  }
}
1 Like

Apparently, there’s also a getMatrix() function which you can use to get Processing’s current matrix. In that case, you could alternatively do something like this. The concept is the same but we use Processing’s getMatrix() instead of a matrix stored in the object:

Box box = new Box(100, 100, 300, 200);

void setup() {
  size(600, 600);
  
}

void draw() {
  pushMatrix();
  rotate(0.25 * PI);
  translate(100, 200);
  scale(1.5, 0.75);
  box.draw();
  println(boxContainsMouse());
  popMatrix();
}

boolean boxContainsMouse() {
  PMatrix2D currMatrix = (PMatrix2D) getMatrix(); // get current matrix
  
  currMatrix.invert(); // get inverse of current matrix
  
  // transform point by the inverse of the matrix:
  float mx = currMatrix.multX(mouseX, mouseY);
  float my = currMatrix.multY(mouseX, mouseY);
  
  currMatrix.invert(); // restore previous state of matrix

  return box.contains(mx, my);
}

class Box {
  float x1, y1, x2, y2;

  Box(float x1, float y1, float x2, float y2) {
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
  }
  
  void draw() {
    rectMode(CORNERS);
    rect(x1, y1, x2, y2);
  }
  
  boolean contains(float x, float y) {
    return x1 <= x && x < x2 && y1 <= y && y <= y2;
  }
}
1 Like

wow…excellent … your help was very valuable…thank you very much!!!

I made my own version modifying your code (without using a class to create the object):

boolean overRect;
float px=200, py=90;
float largo=333, ancho=66;
void setup() {
  size(640, 480);  
}

void draw() {
background(0);
pushMatrix();
px=200+frameCount*0.5;
py=90+frameCount*0.2;
rectMode(CENTER);
rotate(radians(45));
translate(px,py);
scale(0.9);

PMatrix2D currMatrix = (PMatrix2D) getMatrix(); 
currMatrix.invert();
float targetX = currMatrix.multX(mouseX, mouseY)+px;
float targetY = currMatrix.multY(mouseX, mouseY)+py;  
currMatrix.invert();

  if(overRect(targetX,targetY,largo,ancho,px,py)){
  fill(0,0,255); 
  }
  else
  {
  fill(0,255,0);  
  }
  rect(0,0,largo,ancho);
  

popMatrix();

}

boolean overRect(float x, float y, float width, float height, float xx, float yy)  {
  if (x >= xx-width*0.5  && x <=  xx+width*0.5  && 
      y >=yy-height*0.5  && y <= yy+height*0.5) {
    return true;
  } else {
    return false;
  }
}

thank you again :slight_smile: