3

I am trying to make a little algorithm that colors a point a certain color based on what side of a line the point is on. This is what i have at the moment. The code doesnt give any errors, but the colors also arent correct for the dots.. Could someone point out to me what i am doing wrong?

See the code:

PVector[] points; 

void setup() {
  size(500, 500);
  points = new PVector[10];
  for (int i = 0; i < points.length; i++) {
    points[i] = new PVector(random(0, width), random(0, height));
  }

  ExtremesLine(points);
}

void ExtremesLine(PVector[] pts) {
  float maxx = 0, minx = width+1;
  PVector min = new PVector(), max = new PVector();
  ArrayList<PVector> groupA = new ArrayList<PVector>(), groupB = new ArrayList<PVector>();
  for (int i = 0; i < pts.length; i++) {
    if (pts[i].x > maxx) { 
      maxx = pts[i].x;
      max = pts[i];
    } 
    if (pts[i].x < minx) {
      minx = pts[i].x;
      min = pts[i];
    }
  }
  PVector divisionLine  = new PVector();
  PVector.sub(max, min, divisionLine);
  PVector normal  = new PVector(-divisionLine.y, divisionLine.x).normalize();
  for (int i = 0; i < pts.length; i++) {
    float s = PVector.dot(normal, pts[i].copy().normalize());
    if ( s < 0) groupA.add(pts[i]);
    else if ( s > 0) groupB.add(pts[i]);
  }

  fill(0);
  line(min.x, min.y, max.x, max.y);
  for (int i = 0; i < groupA.size(); i++) {
    fill(255, 0, 0);
    ellipse(groupA.get(i).x, groupA.get(i).y, 10, 10);
  }
  for (int i = 0; i < groupB.size(); i++) {
    fill(0, 0, 255);
    ellipse(groupB.get(i).x, groupB.get(i).y, 10, 10);
  }
}

As you can see from the images below sometimes it works but 90% of the time it doesnt. First image is the correct result, second image is the incorrect result
enter image description here enter image description here

If there is anything unclear pls let me know so i can clarify!

FutureCake
  • 2,614
  • 3
  • 27
  • 70

1 Answers1

3

You need to dot with vectors from min:

replace

float s = PVector.dot(normal, pts[i].copy().normalize());

by

float s = PVector.dot(normal, pts[i].copy().sub(min).normalize());

and it will work as expected:

enter image description here

Tangentially, since min and max are Processing built-ins, are you sure that you want to use them as variable names?

Community
  • 1
  • 1
John Coleman
  • 51,337
  • 7
  • 54
  • 119
  • didnt know about min and max being processing built-ins, thanks will change that :) could you maybe elaborate why i need to subtract `min` from the `pts[i]`? – FutureCake May 18 '19 at 17:56
  • There is this duality with vectors. On the one hand, they represent points, on the other hand they represent arrows (direction and magnitude). If you think of `pt[i]` as a *vector* -- implicitly it is the vector which goes from `(0,0)` to `pt[i]` -- the arrow from the upper left hand corner to the point. In effect, your original code has implicitly based on the angle between *that* vector and `normal` but what you really want would be based on the angle between `normal` and a vector which comes from `directionLine` – John Coleman May 18 '19 at 18:04