I have a line colliding with a sphere:
The grey spheres are the endpoints of the line.
The white sphere is colliding with the line.
The blue sphere is the point of collision.
What I want to do is essentially move the blue sphere (the point of collision) to the edge of the white sphere by moving the grey spheres (the line endpoints).
But, I want the grey spheres moved based on how close the colliding white sphere is.
e.g. in the image above, the white sphere is colliding roughly 80% to the right on the line. So the grey sphere on the left should have to perform 80% of the movement, with the left sphere doing 20%, resulting in the diagonal movement (shown below)
While a more central collision would result in equal movement from both:
Any advice on the maths required here?
What I have available in my equation is:
The collision position
The endpoint positions of the line
The position and radius of the white sphere
I'd like to use this information to move the two endpoint positions.
So.. not as hard as I thought it would be:
Vector3 d = (Vector3)lastCollisionPoint - sc;
float dlen = d.magnitude;
var movement = (sc + d * (r / dlen)) - (Vector3)lastCollisionPoint;
t2.transform.position += Vector3.Lerp(Vector3.zero, movement, lerp);
t1.transform.position += Vector3.Lerp(Vector3.zero, movement, 1f - lerp);
sc = sphere centre
lastCollisonPoint = the blue sphere collision point
t1 & t2 = the two points of the line
Related
My challenge is to rotate a rectangle inside another rectangle.
Problem description:
The inner rectangle, let’s call it B, is not allowed to cross the outer rectangle, let’s call it A. But if A is rotated further, so that it might come to a legal position again, it should be rotated to it. So the wanted behavior is to stop rotation before it would cross the border and continue the rotation as soon as B would have a legal position again. B is rotated with a mouse and it might be that not every single degree is calculated extra. So the mouse event might point to 20 degrees and in the next iteration to 40 degrees.
My approach is to solve the problem by calculating and working with rotations. I got the alpha rotation pointing to the mouse. Beta is the rotation from alpha to the right top corner of B.
I calculated the bounding sphere (orange) and its collision points with A (Top Left, Top Right, Right Top, Right Bottom (Left and Bot are not mentioned to not complicate the problem).
Made Calculations:
With this approach I managed to calculate when I have to stop, but only for the top side and the right side separately.
For example: Clockwise Rotation -> Top cropping
If (B.leftTopCornerRotation < TopLeft || B.leftTopCornerRotation > TopRight) {
Alpha = TopLeft - Beta;
} else if (B.leftBotCornerRotation < TopLeft || B. leftBotCornerRotation > TopRight) {
Alpha = Topleft + Beta + PI; // + PI rotates the value by 180 degree
} else if (B.rightBotCornerRotation < TopLeft || B. rightBotCornerRotation > TopRight) {
Alpha = TopLeft - Beta + PI;
} else if (B.rightTopCornerRotation < TopLeft || B. rightTopCornerRotation > TopRight) {
Alpha = TopLeft + Beta;
}
My first problem is, that if B is out of bounds on more than one line (e.g. top and right) there come situations in which I correct the rotation, so that there is no overstep for the right side, than correct that there is no overstep on the top side. But with the second correction I cause a overstep on the right side. This will lead to an infinite loop.
My second problem is, that this approach seams really complicated.
My question would be, if there is some better / working approach to calculate a valid rotation for B clockwise and counterclockwise, so that it does not overstep the borders. Best case would be when it would look like it just stops at the corner.
For every B corner find angle intervals when it is lies outside of every A edge (infinite edge for simplicity).
Then make union of these 16 intervals (most of them should be empty if B is not large) and exclude resulting interval set from the full circle range.
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.
We have Square Grid with a Cell width and height of 1.0
The grid can be of any size, let's say 25x25 for this example.
Now there's a rectangle (or a line with a thickness), that has an arbitrary start and end point, e.g. start point (2.2, 1.0) end point (20.4, 5.5), thickness 1.5. The start and end point are in the center of a rectangle line, hence the thickness expands equally on both sides of the line.
How can one calculate all cell coordinates that this rectangle intersects with?
To enumerate all intersected cells for thin line case, there is method of Amanatides and Woo A Fast Voxel Traversal Algorithm for Ray Tracing.
Here is practical implementation.
For thick line you may choose two parallel edges of rectangle and walk through them synchronously by some coordinate (X or Y), at every step getting the whole scanline.
For your case (arbitrary coordinates, probably not exact):
bottom left corner is in (2,0) cell, top left in (2,1) cell
(2,0)-(2,1) vertical scanline contains two cells
walk with bottom ray to (3,0), wait until top ray reaches X=3
walk with top ray to (2,2), add this cell to the last scanline
walk with top ray to (3,2)
(3,0)-(3,2) vertical scanline contains three cells
and so on
Hey I have a problem and I do not get this calculated on Unity 3D
I want to manipulate vertices. Thats ok but I want to move on X Axis where my mouse is. That doesn't work properly.
So what I do is just throw a ray from origin to a direction. So the ray could be infinitiv long.
With this I want to move the vertice of the mesh to the point where the mouse is. I limited it the range with ray_z = vertice_z (pseudo) but if you look the black line which is the ray you notice it getting longer or shorter when I move or rotate the camera. So the vertice is not on the same position like the mouse.
So I don't get calculated. How can I calculate the position from Z (black line) crosses X (red line).
Example:
cam(1,0,0) // cam & the start position of the ray
x_axis(10,0,10) // red line cutting black
ray_position(15,0,15) // the end of the ray (where the mouse could be if you look from cam to mouse)
Btw: The viewport is not top down. I painted wrong.
If you didn't understand I may try again ^^.
You're looking for Plane.Raycast, I think.
Let's say your plane has a <0, 0, -1> normal (the x-y plane) and passes through the origin:
Plane p = new Plane(Vector3.back, Vector3.zero);
Then you can find the point where a camera/mouse ray intersects with that plane:
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
float distanceAlongRay;
p.Raycast(ray, out distanceAlongRay);
Vector3 mouseOnPlane = ray.GetPoint(distanceAlongRay);
mouseOnPlane is the point on the x-y plane where the mouse ray hit. If you're only interested in the x, then use mouseOnPlane.x.
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)