# How to snap mouse to a shape/coordinate?

**URL:** <https://discourse.processing.org/t/how-to-snap-mouse-to-a-shape-coordinate/13414>\
**Category:** Coding Questions\
**Created:** [August 16, 2019, 2:23pm UTC](https://discourse.processing.org/t/how-to-snap-mouse-to-a-shape-coordinate/13414 "2019-08-16T14:23:05Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![NadeW](https://avatars.discourse-cdn.com/v4/letter/n/ac8455/32.png) [@NadeW](https://discourse.processing.org/u/NadeW)\
**Post date:** [August 16, 2019, 2:23pm UTC](https://discourse.processing.org/t/how-to-snap-mouse-to-a-shape-coordinate/13414/1 "2019-08-16T14:23:05Z")

</div>

Hello my idea is to snap the mouse cursor to intersections on a grid when the user approaches them (this will center the mouse pointer to that cross on the grid). I did some digging but I haven’t found anything that can ‘force’ the cursor onto a point/shape. Is there a function or library I can use to do this?

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [August 16, 2019, 2:26pm UTC](https://discourse.processing.org/t/how-to-snap-mouse-to-a-shape-coordinate/13414/2 "2019-08-16T14:26:19Z")

</div>

library robot mouse - search here in the forum

Chrisir

---

<div class="post-metadata">

**Author:** ![micycle](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micycle/32/201_2.png) [@micycle](https://discourse.processing.org/u/micycle)\
**Post date:** [August 16, 2019, 2:30pm UTC](https://discourse.processing.org/t/how-to-snap-mouse-to-a-shape-coordinate/13414/3 "2019-08-16T14:30:49Z")

</div>

How will they move the mouse off the grid point once it’s snapped on?

---

<div class="post-metadata">

**Author:** ![NadeW](https://avatars.discourse-cdn.com/v4/letter/n/ac8455/32.png) [@NadeW](https://discourse.processing.org/u/NadeW)\
**Post date:** [August 16, 2019, 3:25pm UTC](https://discourse.processing.org/t/how-to-snap-mouse-to-a-shape-coordinate/13414/4 "2019-08-16T15:25:46Z")

</div>

The easiest way is to press a key as a ‘release button’, but I will try to mimic those programs where if you move the mouse slow enough, it doesn’t snap in the first place, and you can also drag the mouse away from the snap if you ‘yank’ your mouse away fast enough

---

<div class="post-metadata">

**Author:** ![NadeW](https://avatars.discourse-cdn.com/v4/letter/n/ac8455/32.png) [@NadeW](https://discourse.processing.org/u/NadeW)\
**Post date:** [August 16, 2019, 3:26pm UTC](https://discourse.processing.org/t/how-to-snap-mouse-to-a-shape-coordinate/13414/5 "2019-08-16T15:26:08Z")

</div>

Thank you Chrisir, I will check it out!

---

<div class="post-metadata">

**Author:** ![kll](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kll/32/964_2.png) [@kll](https://discourse.processing.org/u/kll)\
**Post date:** [August 16, 2019, 9:38pm UTC](https://discourse.processing.org/t/how-to-snap-mouse-to-a-shape-coordinate/13414/6 "2019-08-16T21:38:34Z")

</div>

in this i use a grid of RECT  
and the STROKE to show MOUSE OVER  
the mouse cursor is ON ( HAND ) but can be disabled by key [m] or change start default.

if no mouse cursor is visible, the stroke show over what RECT the mouse is,  
can be called “mouse SNAP to RECT”

make the console window bigger to see all that options / possible operations

```auto
// https://discourse.processing.org/t/scalable-grid-with-rectangles/7256
// https://discourse.processing.org/t/better-grid-performance/7314
// https://discourse.processing.org/t/gryd-system-graphic-design/10457
// https://discourse.processing.org/t/change-rectangles-seperately-in-for-loop/10908/2
// https://discourse.processing.org/t/creating-a-grid-of-toggle-buttons/12162
// use backup memory array for resize/reinit grid but remember selected rects

// use mouse over on button stroke and disable cursor with [m]
// https://discourse.processing.org/t/how-to-snap-mouse-to-a-shape-coordinate/13414

int x = 100, y = x, w = 150, h = w, off= 15, grid = 3, many = grid*grid;
float rang = 0, strokew=5.0;
boolean auto = false;//false;//true;
boolean shownum = false; // key [n]
boolean showFPS = true;
boolean togfill = false;
boolean showmouse = true;

// color setup:
color bg = color(200, 200, 0);
color stk = color(0, 0, 200);
color stkover = color(0, 200, 0);
color fillsel = color(0, 200, 200);
color fillnsel= color(200, 0, 200);

Myrect[] myrects = new Myrect[many];
Mybackup[] myselects = new Mybackup[many]; // temporary memory

void setup() {
  size(800, 520);
  noSmooth();
  set_grid(true); // init
  String help = "";
  help += "use: mouse LEFT to select, mouse RIGHT to deselect\n";
  help += "key UP DOWN RIGHT LEFT for position\n";
  help += "key [+] [-] for grid size\n";
  help += "key [n] toggle shownumber\n";
  help += "key [f] toggle fill\n";
  help += "key [c] clear selected\n";
  help += "key [m] toggle cursor\n";
  help += " ____MouseWheel Plus Plus____ \n";
  help += "use key [x] [y] [w] [h] [o] for position and size\n";
  help += "use key [r] rotate / key [s] stroke width\n";
  help += "and turn mouse wheel";
  println(help);
  if ( showmouse ) cursor(HAND); else noCursor();
}

void draw() {
  background(bg);
  fill(0);
  if (showFPS ) text(nf(frameRate, 1, 1), 10, 10);
  for (int i = 0; i < many; i++) myrects[i].drawit(); // draw each rect ( and check on mouse over + click )
}

class Mybackup {
  boolean selected=false;
}

class Myrect {
  int x, y, id;//, w, h, off, rang; from global
  boolean selected=false;
  Myrect (int x, int y, int id) {
    this.x = x; 
    this.y = y;
    this.id = id;
  }

  void drawit() {
    if ( strokew > 0.2 ) { 
      strokeWeight(strokew);
      stroke( stk );
      if ( over() ) stroke( stkover );
    } else noStroke();
    if ( selected ) fill(fillsel);
    else fill(fillnsel);
    if ( togfill ) noFill();
    push();
    translate(x, y);
    rotate(rang);
    rect(-(w-off)/2, -(h-off)/2, (w-off), (h-off));
    fill(0); // black text
    if (shownum) text(id, -w/8, +h/8);
    pop();
    sel();
  }

  boolean over() {
    return( x-(w-off)/2 < mouseX && mouseX < x+(w-off)/2 && y-(h-off)/2 < mouseY && mouseY < y+(h-off)/2 );
  }

  void sel() {
    if ( over() ) {
      if ( selected && mousePressed && mouseButton == RIGHT) selected=false;
      if ( !selected && mousePressed && mouseButton == LEFT) selected=true;
    }
  }
}

void set_wh() {
  // use x,y,grid as master and auto adjust rectangles (w,h) to window:
  println(" width= "+width+", height= "+height+", grid= "+grid);
  w = ( width - 2 * x ) / grid-off;   
  println(" w= "+w+", x= "+x+", ( grid * w + 2 * x )= "+(grid*w+2*x));
  h = ( height - 2 * y ) / grid-off;
  println(" h= "+h+", y= "+y+", ( grid * h + 2 * y )= "+(grid*h+2*y));
}

void set_grid(boolean init) {
  if ( auto ) set_wh();
  if ( init ) for (int i = 0; i < many; i++) myselects[i]=new Mybackup(); // init backup memory
  else for (int i = 0; i < many; i++) myselects[i].selected = myrects[i].selected; // backup
  for (int i = 0; i < many; i++) myrects[i]=new Myrect(x+(i%grid)*w, y+(floor(i/grid))*h, i); // resize
  if ( !init ) for (int i = 0; i < many; i++) myrects[i].selected = myselects[i].selected; // restore
}

void clear_selected() {
  for (int i = 0; i < many; i++) myrects[i].selected = false; 
  println("clear selected after key [c]");
}

void keyPressed() {
  if ( keyCode == UP ) y--;
  else if ( keyCode == DOWN ) y++;
  else if ( keyCode == LEFT ) x--;
  else if ( keyCode == RIGHT ) x++;
  else if ( key == '+' ) { 
    w++; 
    h++;
  } else if ( key == '-' ) { 
    w--; 
    h--;
  }
  //h=w; // quadrat only
  auto = false; // confirm
  set_grid(false); // resize
  if ( key == 'n' ) shownum = !shownum;
  if ( key == 'f' ) togfill = !togfill;
  if ( key == 'c' ) clear_selected();
  if ( key == 'm' ) showmouse = ! showmouse;
  if ( showmouse ) cursor(HAND); else noCursor();

}

void mouseWheel(MouseEvent event) {
  float e = event.getCount(); //println(e);
  if ( keyPressed && key == 'x' ) { 
    x += e ;
    println(" key x: x "+x);
  }
  if ( keyPressed && key == 'y' ) { 
    y += e;
    println(" key y: y "+y);
  }
  if ( keyPressed && key == 'w' ) { 
    w += e;
    w=constrain(w, 0, width);
    println(" key w: w "+w);
  }
  if ( keyPressed && key == 'h' ) { 
    h += e;
    h=constrain(h, 0, height);
    println(" key h: h "+h);
  }
  if ( keyPressed && key == 'o' ) { 
    off += e;
    off=constrain(off, 0, w);
    println(" key o: off "+off);
  }
  if ( keyPressed && key == 'r' ) { 
    rang += e*0.03;
    println(" key r: rang "+int(degrees(rang)));
  }
  if ( keyPressed && key == 's' ) { 
    strokew += e*0.1;
    strokew = constrain(strokew, 0, w/2);
    println(" key s: strokew "+nf(strokew, 1, 1));
  }
}

```

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [August 16, 2019, 10:17pm UTC](https://discourse.processing.org/t/how-to-snap-mouse-to-a-shape-coordinate/13414/7 "2019-08-16T22:17:08Z")

</div>

example without robot class lib

```auto

int x = 100, y = x, w = 150, h = w, off= 15, grid = 3, many = grid*grid;

Myrect[] myrects = new Myrect[many];

boolean auto = false;//false;//true;

void setup() {
  size(800, 520);
  // noSmooth();
  set_grid(true); // init
  // noCursor();
}

void draw() {
  background(0);
  fill(0);

  for (int i = 0; i < many; i++)
    myrects[i].drawit(); // draw each rect ( and check on mouse over + click )

  // artificial mouse 
  float x=mouseX; 
  float y=mouseY; 

  // search snap points 
  for (int i = 0; i < many; i++) {
    if (dist(myrects[i].x, myrects[i].y, mouseX, mouseY) < 39) {
      // SNAP 
      x=myrects[i].x;
      y=myrects[i].y;
      break;
    }
  }

  // show artificial mouse 
  fill(255);
  // noStroke(); 
  ellipse(x, y, 
    10, 10);
  noFill();
  stroke(0); 
  ellipse(x, y, 
    17, 17);

  // Text 
  fill(255);
  text("snapping to center of rects", 16, 16);
}

void set_grid(boolean init) {
  if ( auto )
    set_wh();
  //if ( init ) for (int i = 0; i < many; i++) myselects[i]=new Myb//ackup(); // init backup memory
  // else for (int i = 0; i < many; i++) myselects[i].selected = myrects[i].selected; // backup

  for (int i = 0; i < many; i++)  
    myrects[i]=new Myrect(x+(i%grid)*w, y+(floor(i/grid))*h, i); // resize
  //if ( !init ) for (int i = 0; i < many; i++) myrects[i].selected = myselects[i].selected; // restore
}

void set_wh() {
  // use x,y,grid as master and auto adjust rectangles (w,h) to window:
  println(" width= "+width+", height= "+height+", grid= "+grid);
  w = ( width - 2 * x ) / grid-off;   
  println(" w= "+w+", x= "+x+", ( grid * w + 2 * x )= "+(grid*w+2*x));
  h = ( height - 2 * y ) / grid-off;
  println(" h= "+h+", y= "+y+", ( grid * h + 2 * y )= "+(grid*h+2*y));
}

// ==========================================================================

class Myrect {
  int x, y, id;//, w, h, off, rang; from global
  boolean selected=false;

  Myrect (int x, int y, int id) {
    this.x = x; 
    this.y = y;
    this.id = id;
  }

  void drawit() {
    pushMatrix();
    translate(x, y);
    fill(244, 33, 0);
    rect(-(w-off)/2, -(h-off)/2, (w-off), (h-off));
    fill(0); // black text
    popMatrix();
  }

  boolean over() {
    return( x-(w-off)/2 < mouseX && mouseX < x+(w-off)/2 && y-(h-off)/2 < mouseY && mouseY < y+(h-off)/2 );
  }
}

```

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [August 17, 2019, 7:54am UTC](https://discourse.processing.org/t/how-to-snap-mouse-to-a-shape-coordinate/13414/8 "2019-08-17T07:54:34Z")

</div>

What exactly do you mean by snap?

That the cursor jumps to a certain point when near it (see my example) OR the selection of cells (see kll example)?

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [August 18, 2019, 2:48pm UTC](https://discourse.processing.org/t/how-to-snap-mouse-to-a-shape-coordinate/13414/9 "2019-08-18T14:48:45Z")

</div>

The simplest way to snap in 2D is `%`. Define your grid step, then subtract the modulo of that from your current location to snap, no modulo for free motion.

```auto
int gstep = 10;

void draw(){
  background(128);
  if (keyPressed){
    ellipse(mouseX, mouseY, 10, 10);
  } else {
    ellipse(mouseX - mouseX%gstep, mouseY - mouseY%gstep, 10, 10); // snap
  }
  lines();
}

void lines(){
  for(int x=0; x<=width; x+=gstep) line(x,0,x,width);
  for(int y=0; y<=height; y+=gstep) line(0,y,height,y);
}

```

This assumes your origin in 0,0, your step size is an integer, and your grid is whole-screen, but setting to an arbitrary range on the screen isn’t much more complicated. Good for basic sketches.

At a certain point, if you are, e.g. programming the game “Battleship” with two grids floating in screen, you might want to transition to an Object oriented example with a grid class.

* * *

The snap-down behavior, above, means that your mouse won’t be snapping to the closest point – it will be snapping to the closest point up-and-left. That may not be what you want. You can snap to closest in a simple way by adding a 0.49 step to your input. Try enabling and disabling the “change snap-down” line below to see the difference.

```auto
int gstep = 25;

void draw(){
  background(128);
  if (keyPressed){
    ellipse(mouseX, mouseY, 10, 10);
  } else {
    ellipse(snap(mouseX, gstep), snap(mouseY, gstep), 10, 10); // snap
  }
  lines();
}

float snap(float input, float step){
  input += (step*0.49); // change snap-down to snap-closest
  float snapped = input - (input % step);
  return snapped;
}

void lines(){
  for(int x=0; x<=width; x+=gstep) line(x,0,x,width);
  for(int y=0; y<=height; y+=gstep) line(0,y,height,y);
}

```
