I'm trying to calculate the point marked in red (to create a line between the circle and the corner of the box)
It's a similar problem to this A JavaScript function that returns the x,y points of intersection between two circles?
However this is for 2 circles.
I know the position of both, circle radius etc, how do I calculate the nearest point to that corner on the circle?
const shapeTop = this.shape.getAttribute('position').clone()
//I want to apply the position here
const geo = this.button.children[0].getAttribute('geometry')
if(!geo)
return
const halfWidth = geo.width * 0.5
const halfHeight = geo.height * 0.5
const buttonEdge = {
x: buttonPos.x + (buttonPos.x > 0 ? - halfWidth : halfWidth),
y: buttonPos.y + (buttonPos.y > 0 ? - halfHeight : halfHeight),
z: buttonPos.z,
}
In three.js, you can calculate the desired point like so:
var vector = new THREE.Vector3(); // or Vector2
vector.copy( corner ).sub( center ).setLength( radius ).add( center );
three.js r.93
The core question is, how to find a point on the circle which has the shortest distance to a given rectangle.
After my thought, we can split the whole 2D-plane into two areas, one is where the rectangle can be moved to by translating with the direction of its' borders, the other is where the rectangle can't be moved in that way. The first area paints like a crossing road (the colored area), and the second area is the rest of the 2D-plane (the white area).
If the center of this circle is inside the first area, then the requested point is the intersecting point of ((the circle) and (the perpendicular line from (the center of circle) to (the nearest border of the rectangle))). Else if the center is inside the second area, then the requested point is the nearest corner of the rectangle.
Update: Another thought is to consider just these 6 points: 4 is the intersection of ((the circle) and (the line between circle center and the 4 corner of rectangle)), another 2 is the intersection of ((the circle) and (the perpendicular line from (the center of circle) to (the borders of rectangle))).
As #WestLangley's answer correctly points out, it is easy to find the nearest point of the circle, once the nearest point on the rectangle is known.
However, there are two different types of "nearest point" possibile on the rectangle: a corner or a side. The figure below illustrates both possibilities:
To determine which case you have, project the center of the circle onto each of the four lines (for example, as in this Q&A). If you do a normalized projection, a value <0 or >1 indicates that your nearest point for that segment is a corner. You are then left with the four corners and any projections that resulted in a value between 0 and 1 as candidates.
Once you have found which candidate is nearest the center of the circle, apply the accepted answer.
Related
I am implementing a function that can detect whether a circle and a polygon are overlapping or not.
I have all the points of the polygon and I know the center points and radius of the circle.
There I check two scenarios:
polygon vertices are inside the circle
circle center is inside the polygon
But there are other scenarios in which a circle and a polygon are overlapping, as shown in the attached image. Can anyone suggest validation for finding the intersection?
Here is a possible approach.
If one of the polygon vertices is inside the circle, there is overlap.
If the the circle center is inside the polygon, they overlap. Note that this test is not trivial for non-convex shape. For example consider a polygon similar to a thin spiral.
Otherwise, for every edge (a,b) of the polygon:
Find p, the projection of the circle center to the line (a,b).
If the distance of p to the circle center is larger than the radius, there is no overlap for this edge.
Otherwise, if p is between a and b (so p_x between a_x and b_x, and also p_y between a_y and b_y, to include the case of horizontal and vertical edges), then there is overlap for this edge, otherwise not.
I'm trying to find the angle it would take for me to rotate a polygon so that a specific side is completely horizontal and on the bottom.
For example, a shape like this:
Needs to be rotated so the side with the red square on it is on the bottom and completely horizontal, like this:
So far I've tried several approaches but all end up having strange edge cases where the angle is incorrect.
If you have coordinates of two vertices of this edge (x1,y1) and (x2,y2) in counterclockwise order, then rotation angle is
RotAngle = atan2 (y2-y1, x2-x1)
So let's say I have 2 objects. One with the sprite of a circle, other with the sprite of triangle.
My triangle object is set to the position of mouse in every step of the game, while circle is either standing in place or just moving in its own way, whatever.
What I want to do is to have the TRIANGLE move around the circle, but not on it's own, rather on the way your cursor is positioned.
So basically, calculate degree between circle's center and triangle's center. Whenever they are far from each other I just set triangle position to mouse position, BUT when you hover your mouse too close (past some X distance) you can't get any closer (the TRIANGLE is then positioned at maximum that X distance in the direction from circle center to mouse point)
I'll add a picture and hopefully you can get what I mean.
https://dl.dropboxusercontent.com/u/23334107/help2.png
Steps:
1. Calculate the distance between the cursor and the center of the circle. If it is more than the 'limit' then set the triangle's position to the cursor's position and skip to step 4.
2. Obtain the angle formed between the center of the circle and the cursor.
3. Calculate the new Cartesian coordinates (x, y) of the triangle based of off the polar coordinates we have now (angle and radius). The radius will be set to the limit of the circle before we calculate x and y, because we want the triangle to be prevented from entering this limit.
4. Rotate the image of the triangle to 1.5708-angle where angle was found in step 2. (1.5708, or pi/2, in radians is equivalent to 90°)
Details:
1. The distance between two points (x1, y1) and (x2, y2) is sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))
2. The angle (in radians) can be calculated with
double angle = Math.atan2(circleY-cursorY, cursorX-circleX);
The seemingly mistaken difference in order of circleY-cursorY and cursorX-circleX is an artefact of the coordinate system in most programming languages. (The y coordinate increases downwards instead of upwards, as it does in mathematics, while the x coordinate increases in concord with math - to the right.)
3. To convert polar coordinates to Cartesian coordinates use these conversions:
triangle.setX( cos(angle)*limit );
triangle.setY( sin(angle)*limit );
where limit is the distance you want the triangle to remain from the circle.
4. In order to get your triangle to 'face' the circle (as you illustrated), you have to rotate it using the libgdx Sprite function setRotation. It will rotate around the point set with setOrigin.
Now, you have to rotate by 1.5708-angle – this is because of further differences between angles in mathematics and angles in programming! The atan2 function returns the angle as measured mathematically, with 0° at three o'clock and increasing counterclockwise. The setRotation function (as far as I can tell) has 0° at twelve o'clock and increases clockwise. Also, we have to convert from radians to degrees. In short, this should work, but I haven't tested it:
triangle.setRotation(Math.toDegrees(1.4708-angle));
Hope this helps!
I need to check if some shapes are colliding in a 2D world.
To check collision between circle and rectangle I found this:
Collision Detection with Rotated Rectangles
But now I need to add another shape to this code (triangle), and the triangle can rotate too.
How can I do that?
This JSTS example (in javascript) shows how to intersect two polygons.
https://github.com/bjornharrtell/jsts/blob/master/examples/overlay.html
In order to modify the example to make one of them into a circle, use this snippet:
// this returns a JSTS polygon circle approximation with provided center and radius
function pointJSTS(center,radius){
var point = new jsts.geom.Point(center);
return point.buffer(radius);
}
// ....
// insert this into the example above at line 17
b = pointJSTS({x:10,y:20}, 40);
Further modification to the example to make the first polygon into a triangle is trivial.
let me begin by stating that's i'm dreadful at math.
i'm attempting to reposition and rotate a rectangle. however, i need to rotate the rectangle from a point that is not 0,0 but according to how far its coordinates has shifted. i'm sure that doesn't make much sense, so i've made some sketches to help explain what i need.
the image above shows 3 stages of the red rectangle moving from 0% to 100%. the red rectangle's X and Y coordinates (top left of the red rectangle) only moves a percentage of the blue rectangle's height.
the red rectangle can rotate. focusing only on the middle example ("Distance -50%") from above, where the red rectangle is repositioned at -50 of the blue rectangle's height, its new angle in the above image is now -45º. it has been rotated from its 0, 0 point.
now, my problem is that i want its rotational point to reflect its position.
the red and blue rectangles are the same size, but have opposite widths and heights. since the red rectangle's 0,0 coordinates are now -50% of the blue rectangle's height, and since they have opposite widths and heights, i want the rotational point to be 50% of the red rectangle's width (or 50% of the blue rectangle's height, which is the same thing).
rather than specifically telling the red rectangle to rotate at 50% of its width, in order to do what i want, i need to emulate doing so by using a formula that will position the red rectangle's X and Y coordinates so that its rotational point reflects its position.
Here's an illustrated solution to your problem:
I don't exactly understand what you need, but it seems that a procedure to rotate a rectangle around an arbitrary point may help.
Suppose we want to rotate a point (x,y) d radians around the origin (0,0). The formula for the location of the rotated point is:
x' = x*cos(d) - y*sin(d)
y' = x*sin(d) + y*cos(d)
Now we don't want to rotate around the origin, but around a given point (a,b). What we do is first move the origin to (a,b), then apply the rotation formula above, and then move the origin back to (0,0).
x' = (x-a)*cos(d) - (y-b)*sin(d) + a
y' = (x-a)*sin(d) + (y-b)*cos(d) + b
This is your formula for rotating a point (x,y) d radians around the point (a,b).
For your problem (a,b) would be the point halfway on the right side of the blue rectangle, and (x,y) would be every corner of the red rectangle. The formula gives (x',y') for the coordinates of the corners of rotated red rectangle.
It's quite simple really.
1. Let's settle on your point you want to rotate the rectangle about, i.e. the point of rotation (RP) which does not move when you swivel your rectangle around. Let's assume that the point is represented by the diamond in the figure below.
2. Translate the 4 points so that RP is at (0,0). Suppose the coordinates of that point is (RPx,RPy), therefore subtract all 4 corners of the rectangle by those coordinates.
3. Rotate the points with a rotation matrix (which rotates a point anticlockwise around the origin through some angle which is now the point of rotation thanks to the previous translation):
The following figure shows the rectangle rotated by 45° anticlockwise.
4. Translate the rectangle back (by adding RP to all 4 points):
I assume this is what you want :)
It seems like you could avoid a more complex rotation by more crafty positioning initially? For example, in the last example, position the red box at "-25% Blue Height" and "-25% Red Height" -- if I follow your referencing scheme -- then perform the rotation you want.
If you know the origin O and a point P on the side of rotated rectangle, you can calculate the vector between the two:
(source: equationsheet.com)
You can get the angle between the vector and the x-axis by taking the dot product with this vector:
(source: equationsheet.com)
Given this, you can transform any point on the rectangle by multiplying it by a rotation matrix:
(source: equationsheet.com)