- Home /
Get Intersection of a Line and a Circle?
Basically I am trying to make objects which are outside my minimap appear on the edge of the map's circle. (The map overlay is masked with a circle image). The object that I'm trying to manipulate (move to the edge of the circle) is only seen by the map camera, and represents an object in the scene... So I want to move that object to the edge of the circle.
I have figured out how to get a Vector3 that represents the normalized direction to the center of the map (where the main character is). What I can't figure out is how to get the position of the intersection between a raycast from the object and the edge of a circle centered on the main character. I'm guessing there's a way to do this without even using a ray or collider? That would be good since a collider that is almost as big as the room that contains my character would cause lots of other problems for me.
I don't know trigonometry or calculus or whatever is required to understand how to solve that problem. I wish I had taken more math classes!
Can anyone help me?
TLDR; How do I find the position where a line (direction) from an object intersects a radius surrounding my character?
Could you provide a bit more detail please. Is your $$anonymous$$imap implemented as a camera looking down on the map? I would highly recommend taking a look at how they set up the $$anonymous$$imap in the demo project "Bootcamp".
Sorry, yes. It's set up with a camera looking down on the scene, so the object that I want to move is a plane in the scene that's attached to the game object it represents.
I will look at the bootcamp project now. Thanks!
Answer by Alec Thilenius · Dec 20, 2012 at 04:21 AM
As for the math you want, its actually just Trig:
http://en.wikipedia.org/wiki/Unit_circle
The X component is Cos(theta) circle radius. The Y Component is Sin(theta) circle radius.
Theta is just your characters Y rotation, converted to radians (Angle * (180 / Pi))
So if I'm understanding where I think this is going... I know the direction to the object from the character already, so it's a matter of solving for X and Y since I also know the radius? I would then move the object to the x and y values relative to the character?
Correct :) Although I always forget that Unity uses Y as its 'up' coordinate. So it reality you will use X and Z, and lock the Y to your player's Y.
I tried to post another "answer" which is really just a question some formatted code that I have based on the above, but the mods haven't approved it for some reason. When I solve for x and y using the above formula, each always comes back as 0.
Sorry to do this, but I'm going to paste the code here... not sure if there's a way to code format in a comment?
============================== public GameObject character; public GameObject target; public float mapRadius = 3; Vector3 heading; float distance; Vector3 direction; float relX; float relZ; float theta;
void Start () {
}
void Update () {
heading = target.transform.position - character.transform.position;
distance = heading.magnitude;
if(distance > mapRadius) {
direction = heading / distance;
theta = direction.y;
relX = $$anonymous$$athf.Pow($$anonymous$$athf.Cos(theta) * mapRadius, 2);
relZ = $$anonymous$$athf.Pow($$anonymous$$athf.Sin(theta) * mapRadius, 2);
Debug.Log(relX + relZ);// always prints "0"
float newX = character.transform.position.x + relX;
float newZ = character.transform.position.x + relZ;
gameObject.transform.position = new Vector3(newX, 0, newZ);
}
}
==============================
Any ideas what might be wrong? the target variable is the object off in the distance that my plane represents in the map view. This script is attached to that plane.
Thanks!
Because you are accessing the linear Y component, not its rotation.
You need to use something like the "LookAt" function to look from your character to the target, and get the Y rotation from that.
Ok, that's helpful... Though I don't know if I can actually use LookAt because this script will be on more than one object in the scene. Also, I can't have my character always actually looking at these objects... I just need to know the rotation it would be if it was looking at it.
Answer by vladibo · Mar 09, 2017 at 02:50 AM
public static int BetweenLineAndCircle(
Vector2 circleCenter, float circleRadius,
Vector2 point1, Vector2 point2,
out Vector2 intersection1, out Vector2 intersection2)
{
float t;
var dx = point2.x - point1.x;
var dy = point2.y - point1.y;
var a = dx * dx + dy * dy;
var b = 2 * (dx * (point1.x - circleCenter.x) + dy * (point1.y - circleCenter.y));
var c = (point1.x - circleCenter.x) * (point1.x - circleCenter.x) + (point1.y - circleCenter.y) * (point1.y - circleCenter.y) - circleRadius * circleRadius;
var determinate = b * b - 4 * a * c;
if ((a <= 0.0000001) || (determinate < -0.0000001))
{
// No real solutions.
intersection1 = Vector2.zero;
intersection2 = Vector2.zero;
return 0;
}
if (determinate < 0.0000001 && determinate > -0.0000001)
{
// One solution.
t = -b / (2 * a);
intersection1 = new Vector2(point1.x + t * dx, point1.y + t * dy);
intersection2 = Vector2.zero;
return 1;
}
// Two solutions.
t = (float)((-b + Math.Sqrt(determinate)) / (2 * a));
intersection1 = new Vector2(point1.x + t * dx, point1.y + t * dy);
t = (float)((-b - Math.Sqrt(determinate)) / (2 * a));
intersection2 = new Vector2(point1.x + t * dx, point1.y + t * dy);
return 2;
}
Answer by ShaneTheVeryTall · Dec 21, 2012 at 12:57 AM
So here's what I have based on what we've talked about:
public GameObject character;
public GameObject target;
public float mapRadius = 3;
Vector3 heading;
float distance;
Vector3 direction;
float relX;
float relZ;
float theta;
void Start () {
}
void Update () {
heading = target.transform.position - character.transform.position;
distance = heading.magnitude;
if(distance > mapRadius) {
direction = heading / distance;
theta = direction.y;
relX = Mathf.Pow(Mathf.Cos(theta) * mapRadius, 2);
relZ = Mathf.Pow(Mathf.Sin(theta) * mapRadius, 2);
Debug.Log(relX + relZ);// always prints "0"
float newX = character.transform.position.x + relX;
float newZ = character.transform.position.x + relZ;
gameObject.transform.position = new Vector3(newX, 0, newZ);
}
}
The Debug.Log line always prints "0" but I thought it should print "1" or my mapRadius value?
Even though the relX and relZ are always 0, the object I intend to move (which has the above script attached to it) does in fact move... but it moves diagonally based on the character's x position. It does not constrain to a circle.
I'm confused. See anything that I'm doing wrong?
Thanks!
Answer by kolmich · Dec 27, 2012 at 03:17 PM
Hi there, The KGFMapSystem already solves this problem by showing an arrow or any other marker for objects outside the minimap area.
It is highly customizeable and comes with a lot of other features you may need. Check it out:
webdemo: http://www.kolmich.at/kolmich/demo/kgf/KGFMinimap/KGFMinimap.html
documentation: http://www.kolmich.at/documentation
assetstore: http://u3d.as/content/kolmich-creations/kgfmap-system/3bf
Your answer
Follow this Question
Related Questions
Creating Minimap Issues 0 Answers
Check if two vectors are intersected 0 Answers
Distance between 2 objects exteriors? 1 Answer
Vector3.Angle 2 Answers
CharacterController.Move precision 1 Answer