0

This is probably a really simple thing, but I am stumped. This is part of a much larger thing, so the code is just a snippet. Each of the green circles arranged around the Particle is a Gate. When the mouse moves around the Particle the closest Gate should turn red to indicate that it is no longer free. The closest Gate is found by comparing the PVector heading of the Gate against PVector(mouseX,mouseY) using the cosine rule.

Particle p;

void setup()
{
  size(1000, 1000);
  p = new Particle(25);
  p.setLoc(width/2, height/2);
}

void draw()
{
  background(0);
  p.update();
  PVector mouse = new PVector(mouseX, mouseY);
  p.gm.getGate(mouse).notFree();
  p.display();

}

class Particle {

  GateManager gm;

  PVector loc;

  float size;
  float n_size;
  float r;//radius;
  float topspeed;

  boolean clicked;

  color MAIN = color(200, 200, 0);
  color HIGHLIGHT = color(255, 0, 0);
  color COLOUR = color(200, 200, 0);

  String name;

  Particle(int size_) { 

    loc = new PVector(0,0);
    this.n_size = size_;
    this.size = n_size*30000;
    r = sqrt(size/PI);
    topspeed = 2000/size;

    gm = new GateManager(this);

  }

  void setLoc(float x, float y) {
    loc.set(x, y);
  }

  void display()
  {
    gm.display();
  }

  Gate getGate(PVector pv)
  {
    PVector pv_ = PVector.sub(pv, loc);
    return gm.getGate(pv_);
  }

  void update() {
    gm.update();
  }
}///Particle




class Gate {

  float size = 5;
  PVector loc;
  PVector locP;
  float angle;
  boolean free;
  //Edge edge;
  PVector heading; ///which way is it pointing?
  GateManager parent;
  float x, y;

  color COLOUR;
  color FREE = color(0, 255, 0);
  color NOTFREE = color(255, 0, 0);


  Gate(GateManager gm, float angle_) {

    this.parent = gm;
    this.angle = angle_;
    this.x = parent.parent.r * .5 * cos(angle);
    this.y = parent.parent.r * .5 * sin(angle);
    locP = new PVector(x, y);
    loc = new PVector(x, y);
    free = true;
  }

  boolean isFree() {
    return free;
  }

  void notFree()
  {
    free = false;
    COLOUR = NOTFREE;
  }

  void free()
  {
    COLOUR = FREE;
    free = true;
  }

  void update()
  {
    free();
    heading = PVector.sub(loc, parent.parent.loc);
    heading.normalize();
    loc.set(parent.parent.loc.x +locP.x, parent.parent.loc.y+locP.y);
  }

  void display()
  {
    noStroke();
    fill(COLOUR);
    ellipse(loc.x, loc.y, size, size);
  }
}

class GateManager {

  ArrayList<Gate> gates;
  int capacity;
  Particle parent;
  float angle;

  GateManager(Particle p)
  {
    capacity = int(p.n_size*8);
    this.parent = p;
    gates = new ArrayList<Gate>();
    angle = TWO_PI/capacity;

    for (int i = 0; i<capacity; i++)
    {
      gates.add(new Gate(this, angle*i));
    }
  }

  Gate getGate(PVector pv)
  {

    float tolerance = -1;
    int i_val=-1;
    boolean found = false;

    for (int i = 0; i<capacity; i++)
    {
      if (gates.get(i).isFree()) {
        float temp = cosineSimilarity(pv, gates.get(i).heading);
        if ( (temp>tolerance))
        {
          tolerance = temp;
          i_val = i;
          found = true;
        }
      }
    }


    i_val = constrain(i_val, 0, capacity);

    text(i_val, 100, height-100);
    return gates.get(i_val);
  }

  void free()
  {
    for (Gate g : gates)
    {
      g.free();
    }
  }

  void update() {  
    for (Gate g : gates)
    {
      g.update();
    }
  }

  void display() {
    for (Gate g : gates)
    {
      g.display();
    }
  }
}//GateManager

float cosineSimilarity(PVector vA, PVector vB) {
  float dotProduct = 0.0;
  float normA = 0.0;
  float normB = 0.0;

  dotProduct += vA.x * vB.x;
  dotProduct += vA.y * vB.y;
  normA += Math.pow(vA.x, 2);
  normA += Math.pow(vA.y, 2);
  normB += Math.pow(vB.x, 2);
  normB += Math.pow(vB.y, 2);

  return dotProduct / (sqrt(normA) * sqrt(normB));
}

1 Answers1

0

You haven't told us what this code does, or how it differs from what you expected. So it's hard to debug, since we don't know what you think is wrong about it.

But you might be able to simplify your approach by just using the dist() function instead:

void setup() {
  size(500, 500);
  ellipseMode(RADIUS);
}

void draw() {
  background(0);

  float circleOneX = 100;
  float circleOneY = 200;
  float circleOneRadius = 50;

  float circleTwoX = 400;
  float circleTwoY = 300;
  float circleTwoRadius = 50;

  float distanceFromCircleOne = dist(mouseX, mouseY, circleOneX, circleOneY);
  float distanceFromCircleTwo = dist(mouseX, mouseY, circleTwoX, circleTwoY);

  if (distanceFromCircleOne < distanceFromCircleTwo) {
    //circle one is closer
    fill(255, 0, 0);
    ellipse(circleOneX, circleOneY, circleOneRadius, circleOneRadius);
    fill(0, 0, 255);
    ellipse(circleTwoX, circleTwoY, circleTwoRadius, circleTwoRadius);
  } else {
    //circle two is closer
    fill(0, 0, 255);
    ellipse(circleOneX, circleOneY, circleOneRadius, circleOneRadius);
    fill(255, 0, 0);
    ellipse(circleTwoX, circleTwoY, circleTwoRadius, circleTwoRadius);
  }
}

If you still can't get it working, please post an MCVE instead of your whole sketch, and try to be more specific about exactly what's not working. Try to narrow it down to as few lines as possible, and try to figure out exactly which line of code differs from what you expect it to do.

Community
  • 1
  • 1
Kevin Workman
  • 41,537
  • 9
  • 68
  • 107