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));
}