How to convert position on a rectangle into position inside the circle

141 Views Asked by At

I want to create a simple demo of moving an eye (black circle) inside a bigger circle with a black stroke when moving a mouse. I have cursor positions mouseX and mouseY on a canvas and I need to map the value of mouse position into a circle so the eye is moving inside the circle.

This should be trivial but I have no idea how to solve this problem.

This is a coding problem but I think that I will get the best results from this Q&A. If not I will ask on stack overflow.

This is the code that shows the problem.

https://editor.p5js.org/jcubic/sketches/E2hVGceN9

If you use map function in P5JS library (that is linear map from one range to a different range) I get the black circle to move in a square with a side equal to the diameter of the circle. So the black circle is outside.

I'm not sure what should I use to calculate the position of the black circle so it's always inside the bigger circle.

enter image description here

4

There are 4 best solutions below

2
On

I think, from my understanding of your question, that you are trying to clip coordinates in the plane, to be inside or on the boundary of the big circle.

For that, suppose the given mouse position is $x_1 = mouseX , y_1 = mouseY $ and the equation of the circle in the plane is given by

$ (x - h)^2 + (y - k)^2 = R^2 $

Then what you want to check first is whether the point $(x_1, y_1)$ is inside this circle by checking if

$ (x_1 - h)^2 + (y_1 - k)^2 \le R^2 $

If it is, then leave the coordiantes $(x_1, y_1)$ as they are.

If not, then calculate the vector from the center to the point $(x_1, y_1)$ and scale it such that it lies on the boundary, this is achieved explicitly as follows

Let $v = \dfrac{( x_1 - h , y_1 - k )}{\sqrt{ (x_1 - h)^2 + (y_1 - k)^2 } } $

Then the new coordinates are

$ (x_2, y_2) = (h, k) + R v $

This new point is the point where you want to place your black dot, and it will be on the boundary of the big circle.

So you have effectively clipped all positions in the plane to be inside the circle or on its perimeter.

0
On

By your use of the map function on both $x$ and $y$, the centre of the black circle (with diameter $20$) will be limited to a rectangle.

If the centre of the outer circle (with diameter $100$) is at the origin, your code limits the centre of the black circle to $|x|\le 40$ and $|y|\le 40$: (your code, my comment)

    let x = map(posX, 0, width, 50 + 10, 150 - 10); 
    let y = map(posY, 0, height, 50 + 10, 150 - 10);
    // i.e. ..., 100 - 40, 100 + 40);

One extreme case, at the top or bottom of the outer circle, the possible $x$ can only be $0$ relative to the outer centre. Then one change is to limit the $x$-position of the black circle to exactly that, and keep the $y$ formula unchanged:

    let x = map(posX, 0, width, 100, 100);  // or simply let x = 100;

A less-extreme case is to allow the black circle to move in a rectangle inside the outer circle. Note how the centre of the black circle can be at most $40$ away from the centre of the outer circle. If we let $maxY$ be the maximum $y$-distance, then the maximum $x$ distance would be $\sqrt{40^2-maxY^2}$:

    let maxY = 24;  // for example, must be between 0 and 40
    let maxX = sqrt(40 * 40 - maxY * maxY);
    let x = map(posX, 0, width, 100 - maxX, 100 + maxX);
    let y = map(posY, 0, height, 100 - maxY, 100 + maxY);

Setting $maxY=40$ would be the extreme case above.

0
On

I may not be understanding the problem correctly. If not, please advise:

It seems as if you are facing two mathematical challenges:

  • You are given a circle with center at the Cartesian coordinate $(0,0)$, of radius $(r)$. You are also given a square, whose diagonal is exactly of length $(2r)$. You want to know how to mathematically correspond the points inside the circle with the points inside the square.

  • Same as previous bullet point, except that the length of the square's diagonal may be less than or greater than $(2r)$.

The remainder of this posting is based on the above assumptions. If I am interpreting your question incorrectly, then leave a comment after this answer, and I will edit the answer accordingly.


I will start with the first bullet point and then conclude with the second bullet point.

The easiest approach is to require that the Cartesian coordinates of the exact center of the square be $(0,0)$. Then, (for example), the $(x,y)$ coordinates of the upper right and lower left corners of the square are
$\displaystyle \left( ~\frac{r}{\sqrt{2}}, ~\frac{r}{\sqrt{2}}, ~\right)~$ and $\displaystyle \left( ~-\frac{r}{\sqrt{2}}, ~-\frac{r}{\sqrt{2}}, ~\right),~$ respectively.

As indicated at the start of my answer, it is also assumed that the exact center of the circle also has (in effect) Cartesian coordinates $(0,0)$. So, the $(x,y)$ coordinate of $(0,0)$ corresponds to the exact center of the circle.

Now, you need a way of associating each point in the square, other than $(0,0)$, with some point in the circle. Any such point $(x,y) \neq (0,0),$ that is inside the square will automatically translate into the following point inside the circle:
$(s,\theta),~$ where $~(s)~$ is a positive number,
and $(\theta)$ is some angle such that $0^\circ \leq \theta < 360^\circ.$

The computation is:

  • $\displaystyle (s) = \sqrt{x^2 + y^2}.$

  • $(\theta)$ is the unique angle in the half-open interval $[0^\circ, 360^\circ)$ such that
    $\displaystyle \cos(\theta) = \frac{x}{s}, ~\sin(\theta) = \frac{y}{s}.$

Once $(x,y)$ has been translated into $(s,\theta)$, you then map the $(s,\theta)$ coordinates into a point on or inside the circle, as follows:

  • You want the point inside the circle to be such that it is exactly $(s)$ units away from the exact center of the circle.

  • Further, you want the point inside the circle to be such that if you draw the line segment from this point to the exact center of the circle, and also draw the horizontal line segment from the center of the circle to the right hand side boundary of the circle, then the angle formed will be equal to $(\theta)$.

To conclude the first bullet point, you also need an algorithm that performs the inverse translation. That is, if you are given a point $(s,\theta)$, where $~0 < s \leq r,~$ and $~0^\circ \leq \theta < 360^\circ,~$ you need to be able to compute the corresponding point in the square.

This is done as follows:

  • The $(x)$ coordinate is $~s \times \cos(\theta).$

  • The $(y)$ coordinate is $~s \times \sin(\theta).$

One final point, for the first bullet point:
the above approach is based on the idea that the square has been inscribed inside the circle, so that the $(4)$ corners of the square are each touching a point on the circle's boundary.

This implies that there will be points inside the circle that fall outside the boundary of the square. This implies that if you were to take any random point $(s,\theta)$ inside the circle, and apply the inverse algorithm described above, the corresponding $(x,y)$ coordinate could fall outside the square.

For simplicity, I will refer to points on or inside the circle, that are outside the corresponding square as invalid points.

While it is important to consider the issue of invalid points, the 2nd bullet point (discussed below) permits the square to be of any size. So, if you wish to translate a point inside the circle that is invalid with respect to a specific square, then you will need to first enlarge the corresponding square so that it will include the corresponding invalid point.


The second bullet point, at the start of my answer, discussed the situation where (in effect), the diagonal of the square was $(2R)$, where $R \neq r$, with $(r)$ equaling the radius of the circle.

All of the analysis of the previous section applies, with only minor modifications:

The point $(0,0)$ inside the square continues to be associated with the point $(0,0)$ [i.e. the exact center] of the circle.

For a point inside the square of coordinates $(x,y) \neq (0,0)$, when you compute $~\displaystyle S = \sqrt{x^2 + y^2},$ and then compute $\theta$ in accordance with the previous analysis, you then need to compute

$$s = S \times \frac{r}{R}. \tag1 $$

That is, you are simply applying a scaling factor to the distance of the point $(x,y)$ to the center of the square. Then, having converted $(S,\theta)$ to $(s,\theta)$, you proceed as per the analysis in the previous section.

For the inverse algorithm, you simply apply the scaling factor, in reverse.

That is, having identified the specific $(s,\theta)$ coordinate inside the circle, you then compute

$$S = s \times \frac{R}{r}. \tag2 $$

Then, after $(s,\theta)$ has been converted into $(S,\theta)$ you follow the approach documented in the previous section to convert this into the coordinates $(x,y)$.

4
On

Call $p$ the position of the cursor and $c$ the center of the large circle. First, we move the origin to be the center of the circle by considering the vector $v=p-c$ so that $v$ is pointing from the center of circle in the direction of $p$. Now we normalize $v$ to $u= \frac{v}{\vert v \vert}$ which is the unit vector in the direction of $v$. Say the radius of the large circle is $R$ and the radius of the black dot is $r$ This means the boundary point on the big circle will be $Ru$ and from there we can see shortening the vector by $r$ will give us the center point of the black dot, which is to say $(R-r)u$. Finally, we need to move the origin back by adding $c$ to get the final coordinates since we subtracted it off initially which gives us $(R-r)u+c$. This is just the naïve geometric method translated into vectors.