Math details of mouse rollover circle
I don’t have a specific programming code problem. I wanted to share some code that I haven’t seen in tutorials. I’ve found two methods to do mouse rollover on a circle; there may be others. The sketch includes a demonstration of both methods.
Method A.
S1. Subtract center x from mouseX; square that
S2. Subtract center y from mousey; square that
S3. Add the two square values
S4. If the sum is <= square of radius, the mouse is over (in) the circle.
I copied this concept from: http://stackoverflow.com/questions/481144/how-do-you-test-if-a-point-is-inside-a-circle
Method B.
S1. Subtract mouseX from center x; square that
S2. Subtract mousey from center y; square that
S3. Add the two square values.
S4. Get the square root of that sum.
S5. If the square root < radius, the mouse is over (in) the circle.
Note: the “overCircle” block – not used - at end of my code is example of Method B, copied from:
http://processing.org/learning/topics/buttons.html
When the sketch starts, the mouse positions are 0,0 and is therefore not in the circle. As the user moves the mouse, the values in both methods are updated and displayed. Moving the mouse off the window resets it to 0,0.
The user can click on one of four X’s to show the values of each “corner” where either mouseX or mouseY is set to the radius. These corner settings are helpful in following the math in both methods. Note: Although the mouse settings are set to these values, I don’t know how to actually move the cursor.
Notice that only “A – ON CIRCLE” appears in the circle when a corner X is clicked. There seems to be a question of whether the points on the circumference are part of the circle or if they’re an outside wall of the circle. If one imagines the circumference as a “one-pixel-thick” container, the circumference points would not be inside the container. But in a 2d area, it seems that the circumference is part of the circle. I don’t want to open that discussion; you can modify it as desired. When the average person is moving the mouse, she doesn’t know if it’s exactly on the circumference, so either “<=” or “<” seem to work.
After moving the cursor around, I noticed a pattern. Both methods arrive at the same squared value in step 3. So it makes no difference in steps 1 and 2 which number is subtracted. A negative number squared is positive. So all coordinate differences give positive results in the fourth column.
The big difference is in steps 4 and 5. I don’t understand the logic (especially Method B) but they do work.
Anybody know how these calculations developed? Is it part of geometry?
- // Demonstrate a way to sense mouse over an ellipse
- int x;
- int y;
- int w;
- int h;
- int r;
- float aXdif;
- float aYdif;
- float bXdif;
- float bYdif;
-
- boolean A = false; // true if mouse over in A method
- boolean B = false; // true if mouse over in B method
-
- void setup() {
- size(500,400);
- smooth();
- x = 100;
- y = 100;
- w = 100;
- h = 100;
- r = w/2;
- }
-
- void draw() {
- background(255);
- fill(0);
- text("X", x, y - r - 5); // n
- text("X", x + r +5, y); // e
- text("X", x, y + r + 15); // s
- text("X", x - r - 15, y); // w
- text("Click on X to focus on that corner",5,12);
- // if mouse outside screen, reset both to 0
- if((mouseX == 0) || (mouseY == 0) || (mouseX == width-1) || (mouseY == height-1)) {
- mouseX = 0;
- mouseY = 0;
- }
-
- drawData(mouseX, mouseY);
- if(rolloverA(mouseX, mouseY)) {
- fill(0);
- text("A - ON CIRCLE", x-40, y -10);
- }
- if(rolloverB(mouseX, mouseY)) {
- fill(0);
- text("B - ON CIRCLE", x-40, y + 10);
- }
- fill(255,100);
- ellipse(x, y, w, h); // draw ellipse either way
- }
-
- boolean rolloverA(int mx, int my) {
- if((sq(aXdif)) + sq((aYdif)) <= sq(r)) {
- A = true;
- return true;
- } else {
- A = false;
- return false;
- }
- }
-
- boolean rolloverB(int mx, int my) {
- if(sqrt(sq(bXdif) + sq(bYdif)) < r) {
- B = true;
- return true;
- } else {
- B = false;
- return false;
- }
- }
-
- void drawData(int mx, int my) {
- int sly; // Method starting line
- int L = 12; // line size
- int tX;
- int tY;
- String tT;
- float mxyTotal;
- // mxMinusX = mx - x;
- // myMinusY = my - y;
-
- // draw line radius header
- tY = 32;
- tX = 430;
- tT = "r";
- drawText(tT, tX, tY);
-
- // draw line radius data
- tY = 44;
- tT = str(r);
- drawText(tT, tX, tY);
-
- //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- // method A
- aXdif = mx - x;
- aYdif = my - y;
- sly = 50; // method A starting line
-
- // draw method A line
- line(190, sly, 480, sly);
- tT = "Method A";
- tX = 190;
- tY = sly += L;
- drawText(tT, tX, tY);
- // draw line 1 headers =============================
- tX = 190;
- tY = sly += L*2;
- tT = "mx";
- drawText(tT, tX, tY);
-
- tX += 40;
- tT = "x";
- drawText(tT, tX, tY);
- tX += 40;
- tT = "(mx - x)";
- drawText(tT, tX, tY);
- tX += 60;
- tT = "sq(mx - x)";
- drawText(tT, tX, tY);
- // draw line 1 data
- tX = 190;
- tY = sly += L;
- tT = str(mx);
- drawText(tT, tX, tY);
-
- tX += 40;
- tT = str(x);
- drawText(tT, tX, tY);
- tX += 40;
- tT = str(aXdif);
- drawText(tT, tX, tY);
- tX += 60;
- tT = str(sq(aXdif));
- drawText(tT, tX, tY);
-
- // draw line 2 headers =============================
- tX = 190;
- tY = sly += L*2;
- tT = "my";
- drawText(tT, tX, tY);
-
- tX += 40;
- tT = "y";
- drawText(tT, tX, tY);
- tX += 40;
- tT = "(my - y)";
- drawText(tT, tX, tY);
- tX += 60;
- tT = "sq(my - y)";
- drawText(tT, tX, tY);
- // draw line 2 data
- tX = 190;
- tY = sly += L;
- tT = str(my);
- drawText(tT, tX, tY);
-
- tX += 40;
- tT = str(y);
- drawText(tT, tX, tY);
- tX += 40;
- tT = str(aYdif);
- drawText(tT, tX, tY);
- tX += 60;
- tT = str(sq(aYdif));
- drawText(tT, tX, tY);
-
- // draw line 3 headers =============================
- tX = 262;
- tY = sly += L*3;
- tT = "sq(mx - x) + sq(my - y)";
- drawText(tT, tX, tY);
-
- tX = 430;
- tT = "sq(r)";
- drawText(tT, tX, tY);
- // draw line 3 data
- tX = 330;
- tY = sly += L;
- tT = str(sq(aXdif) + sq(aYdif));
- drawText(tT, tX, tY);
-
- // draw =, > or <
- tX = 400;
- mxyTotal = sq(aXdif) + sq(aYdif);
- if(mxyTotal == sq(r)) {
- tT = "=";
- drawText(tT, tX, tY);
- }
- if(mxyTotal > sq(r)) {
- tT = ">";
- drawText(tT, tX, tY);
- }
- if(mxyTotal < sq(r)) {
- tT = "<";
- drawText(tT, tX, tY);
- }
-
- tX = 430;
- tT = str(sq(r));
- drawText(tT, tX, tY);
-
- //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- // method B
- bXdif = x - mx;
- bYdif = y - my;
- sly = 200; // method B starting line
-
- // draw method B line
- line(190, sly, 480, sly);
- tT = "Method B";
- tX = 190;
- tY = sly += L;
- drawText(tT, tX, tY);
- // draw line 1 headers =============================
- tX = 190;
- tY = sly += L*2;
- tT = "x";
- drawText(tT, tX, tY);
-
- tX += 40;
- tT = "mx";
- drawText(tT, tX, tY);
- tX += 40;
- tT = "(x - mx)";
- drawText(tT, tX, tY);
- tX += 60;
- tT = "sq(x - mx)";
- drawText(tT, tX, tY);
- // draw line 1 data
- tX = 190;
- tY = sly += L;
- tT = str(x);
- drawText(tT, tX, tY);
-
- tX += 40;
- tT = str(mx);
- drawText(tT, tX, tY);
- tX += 40;
- tT = str(bXdif);
- drawText(tT, tX, tY);
- tX += 60;
- tT = str(sq(bXdif));
- drawText(tT, tX, tY);
-
- // draw line 2 headers =============================
- tX = 190;
- tY = sly += L*2;
- tT = "y";
- drawText(tT, tX, tY);
-
- tX += 40;
- tT = "my";
- drawText(tT, tX, tY);
- tX += 40;
- tT = "(y - my)";
- drawText(tT, tX, tY);
- tX += 60;
- tT = "sq(y - my)";
- drawText(tT, tX, tY);
- // draw line 2 data
- tX = 190;
- tY = sly += L;
- tT = str(y);
- drawText(tT, tX, tY);
-
- tX += 40;
- tT = str(my);
- drawText(tT, tX, tY);
- tX += 40;
- tT = str(bYdif);
- drawText(tT, tX, tY);
- tX += 60;
- tT = str(sq(bYdif));
- drawText(tT, tX, tY);
-
- // draw line 3 headers =============================
- tX = 262;
- tY = sly += L*3;
- tT = "sq(x - mx) + sq(y - my)";
- drawText(tT, tX, tY);
-
-
- // tX = 430;
- // tT = "sq(r)";
- // drawText(tT, tX, tY);
- // draw line 3 data
- tX = 330;
- tY = sly += L;
- tT = str(sq(bXdif) + sq(bYdif));
- drawText(tT, tX, tY);
-
-
- // draw line 4 headers =============================
- tX = 242;
- tY = sly += L*3;
- tT = "sqrt(sq(x - mx) + sq(y - my))";
- drawText(tT, tX, tY);
- tX = 430;
- tT ="r";
- drawText(tT, tX, tY);
-
- // draw line 4 data =============================
- tX = 320;
- tY = sly += L;
- tT = str(sqrt(sq(x - mx) + sq(y - my)));
- drawText(tT, tX, tY);
-
- // draw =, > or <
- tX = 400;
- mxyTotal = sqrt(sq(bXdif) + sq(bYdif));
-
- if(mxyTotal == r) {
- tT = "=";
- drawText(tT, tX, tY);
- }
- if(mxyTotal < r) {
- tT = "<";
- drawText(tT, tX, tY);
- }
- if(mxyTotal > r) {
- tT = ">";
- drawText(tT, tX, tY);
- }
-
- tX = 430;
- tT = str(r);
- drawText(tT, tX, tY);
-
- }
-
- void drawText(String tTT, int tXX, int tYY) {
- text(tTT, tXX, tYY);
- }
-
- void mousePressed() {
- // n
- if(mouseY < y - r) {
- mouseX = x;
- mouseY = y - r;
- }
- // e
- if(mouseX > x + r) {
- mouseX = x + r;
- mouseY = y;
- }
- // s
- if(mouseY > y + r) {
- mouseX = x;
- mouseY = y + r;
- }
- // w
- if(mouseX < x - r) {
- mouseX = x - r;
- mouseY = y;
- }
- }
-
- // code snippet from processing.org/learning/topics/buttons
- boolean overCircle(int x, int y, int diameter)
- {
- float disX = x - mouseX;
- float disY = y - mouseY;
- if(sqrt(sq(disX) + sq(disY)) < diameter/2 ) {
- return true;
- }
- else {
- return false;
- }
- }