Search Unity

  1. Unity 2019.1 is now released.
    Dismiss Notice

math problem

Discussion in 'Scripting' started by raoul, Jan 5, 2008.

  1. raoul

    raoul

    Joined:
    Jul 14, 2007
    Posts:
    4,220
    Hello, I need to find the coordinates of a point according the graph below:

    coordinates A, B and C are known. D is a point on the line between A and B and the angle between the lines AB and CD is 90 degrees. The question is what are the coordinates of point D? I can´t figure out how to do this, anyone good at this stuff? (all of this is in 2D btw!)
     

    Attached Files:

  2. helmishariff

    helmishariff

    Joined:
    Nov 29, 2007
    Posts:
    107
  3. bronxbomber92

    bronxbomber92

    Joined:
    Nov 11, 2006
    Posts:
    890
    Here's a function I use to find the closest point on a line to another point in 3D space. To use this in 2D, just set the z axis (or y axis if you're working on the XZ plane) to 0 for the points you feed in as arguments.

    Code (csharp):
    1. function ClosestPointOnLine(vA : Vector3, vB : Vector3, vPoint : Vector3)
    2. {
    3.     var vVector1 = vPoint - vA;
    4.     var vVector2 = (vB - vA).normalized;
    5.  
    6.     var d = Vector3.Distance(vA, vB);
    7.     var t = Vector3.Dot(vVector2, vVector1);
    8.  
    9.     if (t <= 0)
    10.         return vA;
    11.  
    12.     if (t >= d)
    13.         return vB;
    14.  
    15.     var vVector3 = vVector2 * t;
    16.  
    17.     var vClosestPoint = vA + vVector3;
    18.  
    19.     return vClosestPoint;
    20. }
    I also have a class for 2D Lines that can find the intersection point between two lines. If you'd like to see that, I can post that also.
     
  4. raoul

    raoul

    Joined:
    Jul 14, 2007
    Posts:
    4,220
    Many thanks guys!

    @helmishariff, I googled for solutions and found formulas but, just like the link you posted, the signs used in those formulas are slightly confusing for me :roll:

    @bronxbomber92, this seems to work (the error message I got in my previous solution is gone now) although I can´t test the final result yet due some other code I still have to implement. It would be very interesting to see the 2D solution if it is faster as this code is used in a critical stage in the game.
     
  5. bronxbomber92

    bronxbomber92

    Joined:
    Nov 11, 2006
    Posts:
    890
    I assume the Normal function for 2D vectors is the same as 3D vectors. I may be wrong though, so this may not work at all :p

    Code (csharp):
    1. function Normalized2D( vector : Vector2 ) : Vector2
    2. {
    3.     float mag = value.magnitude;
    4.     if( mag > .00001 )
    5.     {
    6.         return (value / mag);
    7.     }
    8.     return Vector2.zero;
    9. }
    10.  
    11. function ClosestPointOnLine(vA : Vector2, vB : Vector2, vPoint : Vector2)
    12. {
    13.    var vVector1 = vPoint - vA;
    14.     var vVector2 = Normalized2D(vB - vA);
    15.  
    16.     var d = Vector2.Distance(vA, vB);
    17.     var t = Vector2.Dot(vVector2, vVector1);
    18.  
    19.     if (t <= 0)
    20.       return vA;
    21.  
    22.     if (t >= d)
    23.       return vB;
    24.  
    25.     var vVector3 = vVector2 * t;
    26.  
    27.     var vClosestPoint = vA + vVector3;
    28.  
    29.    return vClosestPoint;
    30. }
     
  6. Vector

    Vector

    Joined:
    Jul 10, 2007
    Posts:
    11
    The closest point solution is accurate.

    There are a couple other approaches that may help you understand why it works: Since you know the angle BAC=a and ADC=90, then angle ACD=180-ADC-BAC=180-90-a, since the inner angles of a triangle equal 180 degrees when added, and you would extend that vector to intersect with the line. Here you can check to see if the angles of BAC or ABC are greater than 90, which would mean D would not lie on the line.

    The other way to do it, since you know that the DC line is perpendicular to the AB line, you could rotate the points so that AB lies upon the vertical Y axis, and then rotate C as well by that angle around A, and then translate the points so A would map to 0,0 - and then you use the Y coord of the resulting C as the distance along the AB line that D is lying on. You could then Linearly Interpolate it to find it's coordinates. Also if the Y coord of C is less than 0 or greater than B, D would be lying if it told you that it lies on the line.

    These are not more optimized approaches, but they should help you understand the solution of what you want to achieve. God bless,

    -Vector
     
  7. raoul

    raoul

    Joined:
    Jul 14, 2007
    Posts:
    4,220
    Thanks bronxbomber92, seems like you used the same approach but then used the similar vector2 function instead of vector3. Not sure what is going on behind the Vector2.Dot and Vector3.Dot functions but I will give it a try and see if the Vector2 version is faster.

    Victor, thank you for the explanation, I belief I found similar suggestions on the Internet as I remember reading about the interpolating part. I will bookmark this as a reference for later should all of this need more optimization.
     
  8. ZoomDomain

    ZoomDomain

    Joined:
    Aug 30, 2012
    Posts:
    150
     
    Last edited: Mar 21, 2013
  9. SinisterMephisto

    SinisterMephisto

    Joined:
    Feb 18, 2011
    Posts:
    176
    This code projects to a point outside the min max range of the line. Basically extends the line to infinity.
    I fixed it with a simple vector clamp post projection.

    Code (csharp):
    1. Vector3 Clamp(ref Vector3 min, ref Vector3 max, ref Vector3 data)
    2.     {
    3.         Vector3 result = Vector3.zero;
    4.         for(int i =0; i < 3; ++i)
    5.         {
    6.             result[i] = Mathf.Clamp(data[i],min[i],max[i]);
    7.         }
    8.         return result;
    9.     }
     
    Last edited: Jun 17, 2013