Rect Overlap error

Thanks for the assistance @Hyperion65, you’re amazing.

I got it working exactly for my purposes by modifying that example from Jeffrey Thompson.
It might not be pretty or well built, but it does what it needs to.

Thanks again for your assistance and patience.

My Solution:

//Jeffrey Thmpson
//http://jeffreythompson.org/collision-detection/matrix-transformations.php
ArrayList<Square> squares;
int w = 100;
int tmrStart;

void setup() {
  size(400, 400);

  init();
}

void init() {
  // squares defined as PVector 
  // arrays around the origin
  PVector[] sq = {
    new PVector(-50, -50), 
    new PVector(50, -50), 
    new PVector(50, 50), 
    new PVector(-50, 50)
  };
  squares = new ArrayList<Square>();
  boolean r = false;
  tmrStart = millis();
  for (int i = 0; i < 5; i++) {
    if (random(2) > 1) r = false;
    else r = true;

    squares.add(new Square(int(random(25, width-25)), int(random(25, height-25)), r, i, sq));

    if (i > 0) {
      //check for collision
      for (int j = 0; j < squares.size(); j++) {
        if (i != j) {
          boolean hit = polyPoly(squares.get(j).getSqScreen(), squares.get(i).getSqScreen());
          if (hit) squares.get(i).newPos();
        }
      }
    }
  }
}

void recheck() {

  for (int i = 0; i < squares.size(); i++) {
    if (millis() - tmrStart > 1000) break; 
    if (i > 0) {
      //check for collision
      for (int j = 0; j < squares.size(); j++) {
        if (i != j) {
          boolean hit = polyPoly(squares.get(j).getSqScreen(), squares.get(i).getSqScreen());
          if (hit) squares.get(i).newPos();
        }
      }
    }
  }
}

void mouseReleased() {
  init();
}

void draw() {
  background(255);

  for (Square s : squares) {
    s.draw();
  }
}

// a function that returns the actual screen coordinates
// after matrix transformations (like translate and rotate)
// we could do this up above but easier to make it a function
// that can take any number of polygon points
PVector[] pointsToScreenCoords(PVector[] points) {
  PVector[] screenPoints = new PVector[points.length];   // create output array
  for (int i=0; i<points.length; i++) {                  // go through all the points
    float x = screenX(points[i].x, points[i].y);         // get the screen x coordinate
    float y = screenY(points[i].x, points[i].y);
    screenPoints[i] = new PVector(x, y);
  }
  return screenPoints;
}

// POLYGON/POLYGON
boolean polyPoly(PVector[] p1, PVector[] p2) {

  // go through each of the vertices, plus the next vertex in the list
  int next = 0;
  for (int current=0; current<p1.length; current++) {

    // get next vertex in list
    // if we’ve hit the end, wrap around to 0
    next = current+1;
    if (next == p1.length) next = 0;

    // get the PVectors at our current position
    // this makes our if statement a little cleaner
    PVector vc = p1[current];    // c for “current”
    PVector vn = p1[next];       // n for “next”

    // now we can use these two points (a line) to compare to the
    // other polygon’s vertices using polyLine()
    boolean collision = polyLine(p2, vc.x, vc.y, vn.x, vn.y);
    if (collision) return true;

    // optional: check if the 2nd polygon is INSIDE the first
    collision = polyPoint(p1, p2[0].x, p2[0].y);
    if (collision) return true;
  }

  return false;
}


// POLYGON/LINE
boolean polyLine(PVector[] vertices, float x1, float y1, float x2, float y2) {

  // go through each of the vertices, plus the next vertex in the list
  int next = 0;
  for (int current=0; current<vertices.length; current++) {

    // get next vertex in list
    // if we’ve hit the end, wrap around to 0
    next = current+1;
    if (next == vertices.length) next = 0;

    // get the PVectors at our current position
    // extract X/Y coordinates from each
    float x3 = vertices[current].x;
    float y3 = vertices[current].y;
    float x4 = vertices[next].x;
    float y4 = vertices[next].y;

    // do a Line/Line comparison
    // if true, return ‘true’ immediately and stop testing (faster)
    boolean hit = lineLine(x1, y1, x2, y2, x3, y3, x4, y4);
    if (hit) {
      return true;
    }
  }

  // never got a hit
  return false;
}


// LINE/LINE
boolean lineLine(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) {

  // calculate the direction of the lines
  float uA = ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
  float uB = ((x2-x1)*(y1-y3) - (y2-y1)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));

  // if uA and uB are between 0-1, lines are colliding
  if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) {
    return true;
  }
  return false;
}


// POLYGON/POINT
// used only to check if the second polygon is INSIDE the first
boolean polyPoint(PVector[] vertices, float px, float py) {
  boolean collision = false;

  // go through each of the vertices, plus the next vertex in the list
  int next = 0;
  for (int current=0; current<vertices.length; current++) {

    // get next vertex in list
    // if we’ve hit the end, wrap around to 0
    next = current+1;
    if (next == vertices.length) next = 0;

    // get the PVectors at our current position
    // this makes our if statement a little cleaner
    PVector vc = vertices[current];    // c for “current”
    PVector vn = vertices[next];       // n for “next”

    // compare position, flip ‘collision’ variable back and forth
    if ( ((vc.y > py && vn.y < py) || (vc.y < py && vn.y > py)) &&
      (px < (vn.x-vc.x) * (py-vc.y) / (vn.y-vc.y) + vc.x) ) {
      collision = !collision;
    }
  }
  return collision;
}

class Square {
  PVector[] arr;
  PVector pos;
  boolean rot;
  color c = color(0, 150);
  int id;

  Square(int x, int y, boolean rot, int id, PVector[] arr) {
    pos = new PVector(x, y);
    this.rot = rot;
    this.arr = arr;
    this.id = id;
  }

  void draw() {
    // move the origin to the position of the first square
    pushMatrix();
    translate(pos.x, pos.y);   
    if (rot) rotate(radians(45));

    // and draw the square!
    fill(c);
    noStroke();
    beginShape();
    for (PVector pt : arr) {
      vertex(pt.x, pt.y);
    }
    endShape(CLOSE);
    fill(0);
    text(id, 0, 0);
    popMatrix();
  }

  PVector[] getSqScreen() {
    pushMatrix();
    translate(pos.x, pos.y);
    if (rot) rotate(radians(45));
    PVector[] square1Screen = pointsToScreenCoords(arr);
    popMatrix();
    return square1Screen;
  }

  void setFill(color c) {
    this.c = c;
  }

  void newPos() {
    pos.x = int(random(50, width-50));
    pos.y = int(random(50, height-50));
    recheck();
  }
}

2 Likes