Check direction of the mouse compared to a point in space

Hi, i wonder how to check and know the directions (left,right,up and down) of the mouse compared to a point in space.

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

void draw(){
  background(255);
  PVector dotPos = new PVector(150,150);
  fill(255,0,0);
  ellipse(dotPos.x, dotPos.y, 10, 10);
  
  PVector mousePos = new PVector(mouseX,mouseY);
  line(dotPos.x, dotPos.y,mousePos.x,mousePos.y);
  
  if(mousePos.y < dotPos.y){
    text("up",10,10);
  }
  if(mousePos.y > dotPos.y){
    text("down",10,10);
  }
  if(mousePos.x < dotPos.x){
    text("left",10,10);
  }
  if(mousePos.x > dotPos.x){
    text("right",10,10);
  }
  
}

I know its the wrong way to do it, but I have difficulties with the Switch Statements ( i think this is the good way to do it but i donā€™t know how)

thanks for your help and time.

just a rewrite with some code styling ideas

PVector dotPos = new PVector(150, 150);
PVector mousePos = new PVector(mouseX, mouseY);
String sDir1,sDir2;

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

void draw() {
  background(255);
  draw_mousepos();
}

void draw_mousepos() {
  noStroke();
  mousePos.set(mouseX, mouseY);
  fill(200, 0, 0);
  circle(dotPos.x, dotPos.y, 10);
  fill(0, 0, 200);
  circle(mousePos.x, mousePos.y, 10);
  stroke(0,200,0);
  line(dotPos.x, dotPos.y, mousePos.x, mousePos.y);

  if (mousePos.y < dotPos.y) sDir1 = "up";
  else                       sDir1 = "down";

  if (mousePos.x < dotPos.x) sDir2 = "left";
  else                       sDir2 = "right";
  text(sDir1+" "+sDir2, 10, 10);
}

1 Like

Thanks, I did not think about that, i will try it on my code

its solve one of my future problem (checking to have up left/right and down left/right), but i need to have a way to check when its up,down,left and right only too.

? not understand the question,
you do ( needed to ) have 2 separate variables
well you not need to use string variables at first, but the KNOWLEDGE is stored?
while your above code not stored anything AND even overwrite text at same positionā€¦

sorry if my question was not clear, what i looking for is a way to check when the mouse is up,down,left and right of the point. I know my first code is wrong and it overwrite text, it was to point my problem and my bad code

Remark

It would be very hard to move the mouse y for example exactly to the y position of the point

Instead you should check for example

  • if mouse X is smaller than your point X and
  • the distance of your mouse Y from the point Y is smaller than a threshold of letā€˜s say 30

.....dist(0,mouseY, 0, dotPos.y) < 30.....

then youā€™re LEFT

Chrisir

ok, i start to understand how to solve my problem. i need to have four ā€œareaā€ one for each directions and when the mouse is in one of these area my text say the correct direction (area).

Untitled
something like that

am i right ?

1 Like



PVector dotPos = new PVector(150, 150);
PVector mousePos = new PVector();
String sDir1;

void setup() {
  size(300, 300);
  background(255);
}

void draw() {
  background(255);
  draw_mousepos();
}

// -------------------------------------------------------------

void draw_mousepos() {

  mousePos.set(mouseX, mouseY);

  noStroke();
  fill(200, 0, 0);
  ellipse(dotPos.x, dotPos.y, 10, 10);
  fill(0, 0, 200);
  ellipse(mousePos.x, mousePos.y, 10, 10);

  stroke(0, 200, 0);
  line(dotPos.x, dotPos.y, 
    mousePos.x, mousePos.y);

  sDir1 = "";

  if (mousePos.y < dotPos.y-3      && near( mouseX, dotPos.x ) )  sDir1 = "up";
  else if (mousePos.y > dotPos.y+3 && near( mouseX, dotPos.x ) )  sDir1 = "down";
  else if (mousePos.x < dotPos.x-3 && near( mouseY, dotPos.y ) )  sDir1 = "left";
  else if (mousePos.x > dotPos.x+3 && near( mouseY, dotPos.y ) )  sDir1 = "right";

  fill(0);
  text(sDir1, 10, 10);
}

boolean near( float a, float b) {
  return
    dist(0, a, 0, b) < 30;
}
//
1 Like

ok so in theory i was right :slight_smile:
thanks i gonna test that

1 Like

ok so in theory i was right

No, the checked areas are not round but rectangles in my version:

Unbenannt

there are overlapping areas, here the order of the if-else-clauses decidesā€¦


PVector dotPos = new PVector(150, 150);
PVector mousePos = new PVector();
String sDir1;

void setup() {
  size(300, 300);
  background(255);
}

void draw() {
  background(255);
  draw_mousepos();
}

// -------------------------------------------------------------

void draw_mousepos() {

  mousePos.set(mouseX, mouseY);

  noStroke();
  fill(200, 0, 0);
  ellipse(dotPos.x, dotPos.y, 10, 10);
  fill(0, 0, 200);
  ellipse(mousePos.x, mousePos.y, 10, 10);

  stroke(0, 200, 0);
  // top 
  fill(255, 0, 0, 10); // red
  rect(dotPos.x-30, 0, 
    60, dotPos.y - 3);
  // bottom
  fill(0, 255, 0, 10); //green 
  rect(dotPos.x-30, dotPos.y + 3, 
    60, 300);

  // right
  fill(0, 0, 255, 10); // blue 
  rect(dotPos.x+3, dotPos.y - 30, 
    660, 60);
  // left 
  fill(255, 255, 0, 10); 
  rect(0, dotPos.y - 30, 
    dotPos.x-3, 60);

  stroke(0, 200, 0);
  line(dotPos.x, dotPos.y, 
    mousePos.x, mousePos.y);

  sDir1 = "";

  if (mousePos.y < dotPos.y-3      && near( mouseX, dotPos.x ) )  sDir1 = "up";
  else if (mousePos.y > dotPos.y+3 && near( mouseX, dotPos.x ) )  sDir1 = "down";
  else if (mousePos.x < dotPos.x-3 && near( mouseY, dotPos.y ) )  sDir1 = "left";
  else if (mousePos.x > dotPos.x+3 && near( mouseY, dotPos.y ) )  sDir1 = "right";

  fill(0);
  text(sDir1, 10, 10);
}



boolean near( float a, float b) {
  return
    dist(0, a, 0, b) < 30;
}
//

ok wow so my problem is harder that i imagined

itā€™s not hard at all.

What do you mean?

1 Like

well it create a lot of void between each rectangle, im sure i can modify it by making them wider.

thanks to you, now i can clearly display what im looking for.

this is what im looking for:
4 directions:
Untitled
8 directions:
Untitled2

iā€™m deeply sorry for wasting yours times by not express myself correctly.

1 Like

in this version we also check if the mouse is near (100) the reference point in the first place, before checking the areas


PVector dotPos = new PVector(150, 150);
PVector mousePos = new PVector();
String sDir1;

void setup() {
  size(300, 300);
  background(255);
}

void draw() {
  background(255);
  draw_mousepos();
}

// -------------------------------------------------------------

void draw_mousepos() {

  mousePos.set(mouseX, mouseY);

  noStroke();
  fill(200, 0, 0);
  ellipse(dotPos.x, dotPos.y, 10, 10);
  fill(0, 0, 200);
  ellipse(mousePos.x, mousePos.y, 10, 10);

  showFourRects(); 

  stroke(0, 200, 0);
  line(dotPos.x, dotPos.y, 
    mousePos.x, mousePos.y);

  sDir1 = "";

  if (mousePos.dist(dotPos) < 100) {
    if      (mousePos.y < dotPos.y-3 && near( mouseX, dotPos.x ) )  sDir1 = "up";
    else if (mousePos.y > dotPos.y+3 && near( mouseX, dotPos.x ) )  sDir1 = "down";
    else if (mousePos.x < dotPos.x-3 && near( mouseY, dotPos.y ) )  sDir1 = "left";
    else if (mousePos.x > dotPos.x+3 && near( mouseY, dotPos.y ) )  sDir1 = "right";
    else { //ignore
    }
  }//if

  fill(0);
  text(sDir1, 10, 10);
}

boolean near( float a, float b) {
  return
    dist(0, a, 0, b) < 30;
}

void showFourRects() {

  stroke(0, 200, 0);
  // top 
  fill(255, 0, 0, 10); // red
  rect(dotPos.x-30, dotPos.y - 100, 
    60, 100 - 3);

  // bottom
  fill(0, 255, 0, 10); //green 
  rect(dotPos.x-30, dotPos.y + 3, 
    60, 100-3 );

  // right
  fill(0, 0, 255, 10); // blue 
  rect(dotPos.x+3, dotPos.y - 30, 
    100-3, 60);

  // left 
  fill(255, 255, 0, 10); // other color 
  rect(dotPos.x-100, dotPos.y - 30, 
    100-3, 60);

  // show circle to symbolie:   if (mousePos.dist(dotPos) < 100) {
  stroke(0);
  noFill();
  ellipse( dotPos.x, dotPos.y, 200, 200);
}
//
2 Likes

totally new approach

uses the angle between mouse and center point

(angle 0 is on the right side, not on the top in processing)

(also remember, itā€™s in radians mostly, not degrees )




// https : // forum.processing.org/two/discussion/10474/find-angle-between-2-points

PVector centerPoint; // the fixed red point 

// make an int a String 
String[] textFromDir = {
  "Right", 
  "Right,down", 
  "down", 
  "down, left", 
  "left", 
  "left up", 
  "up", 
  "up right", 
}; 

void setup() {
  size(1200, 600);
  centerPoint = new PVector(width/2, height/2);
}

void draw() {  
  background(0);

  // draw arc 
  fill(255); 
  //arc( centerPoint.x, centerPoint.y, 
  //  430, 430, 
  //  radians(60), radians(90) );

  // draw a simple cross at centerPoint 
  crossAtPV(centerPoint); 

  // show centerPoint in red 
  ellipsePV(centerPoint); 

  // get angle 
  float angle = angleBetweenPV_PV(centerPoint, new PVector(mouseX, mouseY));

  angle=fixAngle(angle);

  // check Area !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  int dir=0;
  float angleInDegrees=degrees(angle);
  float scliceDegree = 360/8 ; 

  dir = 0;

  if       ( isBetween (angleInDegrees, 0*scliceDegree, 1*scliceDegree) )  dir = 0;
  else  if ( isBetween (angleInDegrees, 1*scliceDegree, 2*scliceDegree) )  dir = 1;
  else  if ( isBetween (angleInDegrees, 2*scliceDegree, 3*scliceDegree) )  dir = 2;

  else if  ( isBetween (angleInDegrees, 3*scliceDegree, 4*scliceDegree) )  dir = 3;
  else  if ( isBetween (angleInDegrees, 4*scliceDegree, 5*scliceDegree) )  dir = 4;
  else  if ( isBetween (angleInDegrees, 5*scliceDegree, 6*scliceDegree) )  dir = 5;

  else  if ( isBetween (angleInDegrees, 6*scliceDegree, 7*scliceDegree) )  dir = 6;
  else  if ( isBetween (angleInDegrees, 7*scliceDegree, 8*scliceDegree) )  dir = 7;


  // show the found angle
  fill(255, 0, 0); // red
  triangleMy(angle);
  fill(255); // white

  text(angle
    +"\n"
    +degrees(angle) + "\n" + dir + ": " + textFromDir[ dir ], 23, 23);
}

// --------------------------------------------------------------------

boolean isBetween(float inputValue, float down, float up) {
  return 
    inputValue>down- 360/16 &&
    inputValue<up- 360/16;
}
// --------------------------------------------------------------------

float angleBetweenPV_PV(PVector centerPV, PVector movingPV) {

  // calc angle : the core of the sketch 

  PVector d = new PVector();

  // calc angle

  // delta 
  d.x = movingPV.x - centerPV.x;
  d.y = movingPV.y - centerPV.y;
  // angle 
  float angle1 = atan2(d.y, d.x);

  return angle1;
} 

void triangleMy(float ang) {

  pushMatrix();

  translate(centerPoint.x, centerPoint.y);

  rotate(ang);

  // fill(255); // white shield 
  triangle(60, 0, 
    80, -30, 
    80, 30);

  popMatrix();
}

void ellipsePV(PVector pv) {
  fill(255, 0, 0); // red
  ellipse(pv.x, pv.y, 10, 10);
}

void crossAtPV(PVector pv) {
  stroke(255);
  line(pv.x, 0, pv.x, height);
  line(0, pv.y, width, pv.y);
}
// 
float fixAngle(float angle1) {
  // if > 2xPI 
  if (angle1>TWO_PI) 
    angle1-=TWO_PI; 
  if (angle1>TWO_PI) 
    angle1-=TWO_PI; 

  // if < 0 (negative angles like -40 should be expressed as positive angles like 320)
  if (angle1<0.0) {
    angle1 = TWO_PI + angle1;
  }
  if (angle1<0.0) 
    angle1 = TWO_PI + angle1;

  return angle1;
}
//
1 Like

amazing just amazing, i will try it on my code. Many thanks for your patience and answers.
i will check the link too.

2 Likes

new version

// https : // forum.processing.org/two/discussion/10474/find-angle-between-2-points
// https://discourse.processing.org/t/check-direction-of-the-mouse-compared-to-a-point-in-space/12883/16 

final int UNDEFINED = -1; 

PVector centerPoint; // the fixed red point 

// make an int dir a String dir 
String[] textFromDir = {
  "NONE", 
  "Right", 
  "Right, down", 
  "down", 
  "down, left", 
  "left", 
  "left, up", 
  "up", 
  "up, right", 
}; 

String text1=""; 
int dirFromMouse=0;

//---------------------------------------------------------------------------------------

void setup() {
  size(1200, 600);
  centerPoint = new PVector(width/2, height/2);
}

void draw() {  
  background(0);

  // draw a simple cross at centerPoint 
  crossAtPV(centerPoint); 

  // show centerPoint in red 
  ellipsePV(centerPoint); 

  //get mouse pvector
  PVector mousePV=new PVector(mouseX, mouseY);

  // get angle 
  float angle = angleBetweenPV_PV(centerPoint, mousePV);

  angle=fixAngle(angle);

  // check Area !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  float angleInDegrees=degrees(angle);
  float scliceDegree = 360/8 ; 

  dirFromMouse = UNDEFINED;

  // dist mouse center must be < 240 
  if (centerPoint.dist(mousePV)<200) {

    if       ( isBetween (angleInDegrees, 0*scliceDegree, 1*scliceDegree) )  dirFromMouse = 0;
    else  if ( isBetween (angleInDegrees, 1*scliceDegree, 2*scliceDegree) )  dirFromMouse = 1;
    else  if ( isBetween (angleInDegrees, 2*scliceDegree, 3*scliceDegree) )  dirFromMouse = 2;

    else if  ( isBetween (angleInDegrees, 3*scliceDegree, 4*scliceDegree) )  dirFromMouse = 3;
    else  if ( isBetween (angleInDegrees, 4*scliceDegree, 5*scliceDegree) )  dirFromMouse = 4;
    else  if ( isBetween (angleInDegrees, 5*scliceDegree, 6*scliceDegree) )  dirFromMouse = 5;

    else  if ( isBetween (angleInDegrees, 6*scliceDegree, 7*scliceDegree) )  dirFromMouse = 6;
    else  if ( isBetween (angleInDegrees, 7*scliceDegree, 8*scliceDegree) )  dirFromMouse = 7;
    else {
      // ignore
    }
  }//if 

  // show red lines 
  for (int i = 0; i < 9; i++) {
    stroke(255, 2, 2); // RED
    line(centerPoint.x, centerPoint.y, 
      cos(radians(i*scliceDegree- 360/16))*90 +centerPoint.x, sin(radians(i*scliceDegree- 360/16))*90 +centerPoint.y );
  }

  if (dirFromMouse>UNDEFINED) {
    // show yellow triangle (when mouse on)
    stroke(255, 2, 2); 
    int i2 = dirFromMouse+1; 
    fill(240, 255, 44); // YELLOW 
    stroke(255, 2, 2); // RED
    trianglePV ( centerPoint, 
      getPointOnCircle ( centerPoint, radians(dirFromMouse*scliceDegree- 360/16), 90 ), 
      getPointOnCircle ( centerPoint, radians(i2          *scliceDegree- 360/16), 90 ) );
  }

  // show the red triangle 
  fill(255, 0, 0); // red
  triangleMy(angle);
  fill(255); // white

  // upper left corner 
  text(angle
    +"\n"
    +degrees(angle) 
    + "\n" 
    + dirFromMouse 
    + ": " 
    + textFromDir[ dirFromMouse+1 ], 
    23, 23);

  // upper right corner: on mousePressed() 
  fill(255);
  text(text1, 
    width-210, 23);
}

// ------------------------------------------------------------------------------------------------

void mousePressed() {
  switch(dirFromMouse) {

  case UNDEFINED:
    text1="";
    break;

  default:
    text1 = "We got "
      +textFromDir[ dirFromMouse+1 ];
    break;
  }//switch
}//func 

// --------------------------------------------------------------------

boolean isBetween(float inputValue, float down, float up) {
  return 
    inputValue>down- 360/16 &&
    inputValue<up- 360/16;
}

// --------------------------------------------------------------------

float angleBetweenPV_PV(PVector centerPV, PVector movingPV) {

  // calc angle : the core of the sketch 

  PVector d = new PVector();

  // calc angle

  // delta 
  d.x = movingPV.x - centerPV.x;
  d.y = movingPV.y - centerPV.y;
  // angle 
  float angle1 = atan2(d.y, d.x);

  return angle1;
} 

void triangleMy(float ang) {
  pushMatrix();
  translate(centerPoint.x, centerPoint.y);
  rotate(ang);
  fill(255); // white  
  triangle(60, 0, 
    80, -30, 
    80, 30);
  popMatrix();
}

void ellipsePV(PVector pv) {
  fill(255, 0, 0); // red
  ellipse(pv.x, pv.y, 10, 10);
}

void trianglePV(PVector pv1, PVector pv2, PVector pv3) {
  triangle (pv1.x, pv1.y, 
    pv2.x, pv2.y, 
    pv3.x, pv3.y);
}

void crossAtPV(PVector pv) {
  stroke(255);
  line(pv.x, 0, pv.x, height);
  line(0, pv.y, width, pv.y);
}

PVector getPointOnCircle ( PVector center, float angle, float radius ) {
  // calcs a point on a circle from some data 
  return 
    new PVector(
    cos(angle)*radius +center.x, 
    sin(angle)*radius +center.y  );
}

float fixAngle(float angle1) {
  // repairs / beautify angle 

  // if > 2xPI 
  if (angle1>TWO_PI) 
    angle1-=TWO_PI; 
  if (angle1>TWO_PI) 
    angle1-=TWO_PI; 

  // if < 0 (negative angles like -40 should be expressed as positive angles like 320)
  if (angle1<0.0) {
    angle1 = TWO_PI + angle1;
  }
  if (angle1<0.0) 
    angle1 = TWO_PI + angle1;

  return angle1;
}
//
4 Likes

There is a way to get rid of those if-else statements for checking the directions to shrinkify the codes and makes life easier.

I came with this.


final int DIRS = 16;
//final int DIRS = 8;
//final int DIRS = 4;


// IF 16 DIRECTIONS ARE NEEDED
String[] dirName ={
  "W", 
  "WNW", 
  "NW", 
  "NNW", 
  "N", 
  "NNE", 
  "NE", 
  "ENE", 
  "E", 
  "ESE", 
  "SE", 
  "SSE", 
  "S", 
  "SSW", 
  "SW", 
  "WSW", 
  "W"
};

// IF 8 DIRECTIONS ARE NEEDED
String[] dirName2 ={
  "W", 
  "NW", 
  "N", 
  "NE", 
  "E", 
  "SE", 
  "S", 
  "SW", 
  "W"
};

// IF 4 DIRECTIONS ARE NEEDED
String[] dirName3 ={
  "W", 
  "N", 
  "E", 
  "S", 
  "W"
};

PVector origin;
void setup() {
  stroke(255);
  fullScreen();
  fill(255);
  origin = new PVector(width/2, height/2);
  textSize(30);
}

void draw() {
  background(51);
  fill(255);
  text(DIRS + " DIRECTIONS", 100, 60);
  int dirId = pointToward(mouseX, mouseY);
  text(dirName[dirId], 100, 100); // 16 directions
}

float r = 300; // FIELD RADIUS
int pointToward(float x, float y) {
  PVector point = new PVector(x, y);
  PVector dir = PVector.sub(point, origin);
  dir.normalize();
  float theta = dir.heading();
  // Get the nearest direction
  int angleMultiplier = round((DIRS) * theta/TWO_PI);
  theta = angleMultiplier * TWO_PI/(DIRS);

  // Get direction ID
  int dirId = angleMultiplier + (DIRS)/2;

  //drawing
  float triggerR = 3*r/DIRS; //TRIGGER RADIUS
  noFill();
  for (int i = -DIRS/2; i < DIRS/2; i++) {
    float cx = cos(i * TWO_PI/DIRS) * r + origin.x;
    float cy = sin(i * TWO_PI/DIRS) * r + origin.y;
    line(origin.x, origin.y, cx, cy);
    ellipse(cx, cy, triggerR*2, triggerR*2);
  }

  // check if it triggers the checking radius
  float tx = cos(theta) * r + origin.x;
  float ty = sin(theta) * r + origin.y;
  float d = dist(tx, ty, point.x, point.y);
  if (d < triggerR) {
    fill(255);
    ellipse(tx, ty, triggerR*2, triggerR*2);
    fill(0, 255, 100);
    text("TRIGGERED", 100, 150);
    //-----------------------------------DO SOMETHING HERE-----------------------------
    //text(dirName2[dirId], 100, 100); // 8 directions
    //text(dirName3[dirId], 100, 100); // 4 directions
  }
  return dirId;
}

3 Likes

Thanks for all the versions, i use the first 8 direction option, its perfect.

Thank you all