Search Unity

All intersection point in single collider

Discussion in 'Physics' started by BrainSTRM, Jan 31, 2017.

  1. BrainSTRM

    BrainSTRM

    Joined:
    Oct 25, 2016
    Posts:
    2
    I want to get all intersection point in single collider. I used Collider.Raycast, but this method only give one point (entry point).

    I used reversed raycasting to find exit point. But, this method's have problem in some mesh collider.

    intersection.jpg
    In photo, i successfully get red points (entry and exit points). But, i need all intersection point.
    I think Collider.RaycastAll method is good for this problem. But Unity hasn't RaycastAll method for single collider.
     
  2. BrainSTRM

    BrainSTRM

    Joined:
    Oct 25, 2016
    Posts:
    2
    RaycastAll only give one point only per single collider. In here, I used reversed raycasting for finding exit point.

    intersection2p.png
     
  3. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,478
    Yes, Raycast is designed to do just that, not give entry/exit points of a ray.

    You have the polygon outline vertex so you simply need to iterate the edges of the polygon, checking if each edge intersects the ray or line-segment. If it does then calculate the intersection point and add it to a list of points.
     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,478
    Okay, so I had a little time on my hands this evening and I like little challenges like this. ;)

    Here's an example project that does what you want. Note that I've not tried to make it super efficient; for instance it grabs the points from the polygon each frame which produces memory garbage. You can obviously grab this once only if it's not changing or only grab it when it changes.

    Anyway, here's it working.
     
    junhossi likes this.
  5. hshahbodaghkhan

    hshahbodaghkhan

    Joined:
    Aug 24, 2018
    Posts:
    11
    I need the same thing.
    But your link does not work.
    would you please upload it again?
     
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,478
    The hosting site was closed down. Here's the single script that you can use as an example:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [ExecuteInEditMode]
    6. public class ClippingScript : MonoBehaviour
    7. {
    8.     public Vector2 LineStart;
    9.     public Vector2 LineEnd;
    10.     public float crossScale = 0.05f;
    11.  
    12.     Vector2[] polygonPoints;
    13.     PolygonCollider2D polygon;
    14.     List<Vector2> clipPoints = new List<Vector2> ();
    15.  
    16.  
    17.     // Use this for initialization
    18.     void Start ()
    19.     {
    20.         // Start the body rotating.
    21.         GetComponent<Rigidbody2D> ().angularVelocity = 45.0f;
    22.  
    23.         polygon = GetComponent<PolygonCollider2D> ();
    24.     }
    25.  
    26.     // Update is called once per frame
    27.     void Update ()
    28.     {
    29.         // Fetch the polygon points in world-space (not the most efficient way of doing things)!
    30.         polygonPoints = polygon.points;
    31.         for (var i = 0; i < polygonPoints.Length; ++i)
    32.             polygonPoints[i] = transform.TransformPoint (polygonPoints[i]);
    33.  
    34.         // Perform clipping against the polygon.
    35.         clipPoints.Clear ();
    36.         var pointCount = polygonPoints.Length;
    37.         for (int i = 0, j = pointCount - 1; i < pointCount; j = i++)
    38.         {
    39.             var edgeStart = polygonPoints[i];
    40.             var edgeEnd = polygonPoints[j];
    41.  
    42.             Vector2 clipPoint;
    43.             if (LineSegmentIntersection (LineStart, LineEnd, edgeStart, edgeEnd, out clipPoint))
    44.                 clipPoints.Add (clipPoint);
    45.         }
    46.  
    47.         // Draw the clipping line.
    48.         Debug.DrawLine (LineStart, LineEnd, Color.red);
    49.  
    50.         // Draw the clip points.
    51.         foreach (var v in clipPoints)
    52.         {
    53.             var clipPoint = (Vector3)v;
    54.             Debug.DrawLine (clipPoint + (Vector3.left * crossScale), clipPoint + (Vector3.right * crossScale), Color.white);
    55.             Debug.DrawLine (clipPoint + (Vector3.up * crossScale), clipPoint + (Vector3.down * crossScale), Color.white);
    56.         }
    57.     }
    58.  
    59.     bool LineSegmentIntersection (Vector2 a, Vector2 b, Vector2 c, Vector2 d, out Vector2 point)
    60.     {
    61.         // Sign of areas correspond to which side of ab points c and d are.
    62.         float area1 = SignedTriangleArea (a, b, d);
    63.         float area2 = SignedTriangleArea (a, b, c);
    64.  
    65.         // If c and d are on different sides of ab, areas have different signs.
    66.         if (area1 * area2 < 0.0f)
    67.         {
    68.             // Compute signs for a and b with respect to segment cd.
    69.             float area3 = SignedTriangleArea (c, d, a);
    70.             float area4 = area3 + area2 - area1;
    71.  
    72.             // Points a and b on different sides of cd if areas have different signs.
    73.             if (area3 * area4 < 0.0f)
    74.             {
    75.                 float time = area3 / (area3 - area4);
    76.                 point = a + time * (b - a);
    77.                 return true;
    78.             }
    79.         }
    80.  
    81.         // Segments are not intersecting or collinear.
    82.         point = Vector2.zero;
    83.         return false;
    84.     }
    85.  
    86.     float SignedTriangleArea (Vector2 a, Vector2 b, Vector2 c)
    87.     {
    88.         return (a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x);
    89.     }
    90.  
    91. }
    92.  
     
    DmytroSerebrennikov likes this.
  7. hshahbodaghkhan

    hshahbodaghkhan

    Joined:
    Aug 24, 2018
    Posts:
    11
    Thank you very much.
    your example is very helpful.
    if I want to use the method with Circle collider which part should be changed?
     
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,478
    The above is for convex polygons only, not for any type of collider. You'd need to write a ray/circle intersection script for any circle.

    You can fnid these kinds of intersection tests though on Google, there's plenty of them. For line/circle there's this one, amongst many.
     
  9. hshahbodaghkhan

    hshahbodaghkhan

    Joined:
    Aug 24, 2018
    Posts:
    11
    Thank you so muchfor your hard work.
    I use it a lot.
    I also have a trouble using ray 2d.
    I designed a ray reflection.
    but it work incorrectly at some angle of the ray source
    here is my Q on stackoverflow:
    https://stackoverflow.com/questions/64400118/why-the-ray-reflection-system-not-work-correctly
     
  10. unityl2ga

    unityl2ga

    Joined:
    Feb 3, 2022
    Posts:
    10
    Thanks a lot for this amazing script. Works like a charm in :)
    However It was only giving me points of the first element of the polygon collider. I modified it a little like this now it covers entire sprite with polygon islands

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class ClippingScript : MonoBehaviour
    7. {
    8.     public Vector2 LineStart;
    9.     public Vector2 LineEnd;
    10.     public float crossScale = 0.05f;
    11.  
    12.     Vector2[] polygonPoints;
    13.     PolygonCollider2D polygon;
    14.     List<Vector2> clipPoints = new List<Vector2>();
    15.  
    16.  
    17.     // Use this for initialization
    18.     void Start()
    19.     {
    20.         polygon = GetComponent<PolygonCollider2D>();
    21.     }
    22.  
    23.     // Update is called once per frame
    24.     void Update()
    25.     {
    26.         // Fetch the polygon points in world-space (not the most efficient way of doing things)!
    27.         List<Vector2> vecs = new List<Vector2>();
    28.         for (int x = 0; x < polygon.pathCount; x++)
    29.         {
    30.             Vector2[] pax = polygon.GetPath(x);
    31.             for (int y = 0; y < pax.Length; y++)
    32.             {
    33.                 vecs.Add(pax[y]);
    34.             }
    35.         }
    36.         polygonPoints = vecs.ToArray();
    37.         vecs.Clear();
    38.         vecs.TrimExcess();
    39.         vecs = null;
    40.        
    41.         for (var i = 0; i < polygonPoints.Length; ++i)
    42.             polygonPoints[i] = transform.TransformPoint(polygonPoints[i]);
    43.  
    44.         // Perform clipping against the polygon.
    45.         clipPoints.Clear();
    46.         var pointCount = polygonPoints.Length;
    47.         for (int i = 0, j = pointCount - 1; i < pointCount; j = i++)
    48.         {
    49.             var edgeStart = polygonPoints[i];
    50.             var edgeEnd = polygonPoints[j];
    51.  
    52.             Vector2 clipPoint;
    53.             if (LineSegmentIntersection(LineStart, LineEnd, edgeStart, edgeEnd, out clipPoint))
    54.                 clipPoints.Add(clipPoint);
    55.         }
    56.  
    57.         // Draw the clipping line.
    58.         Debug.DrawLine(LineStart, LineEnd, Color.red);
    59.  
    60.         // Draw the clip points.
    61.         foreach (var v in clipPoints)
    62.         {
    63.             var clipPoint = (Vector3)v;
    64.             Debug.DrawLine(clipPoint + (Vector3.left * crossScale), clipPoint + (Vector3.right * crossScale), Color.white);
    65.             Debug.DrawLine(clipPoint + (Vector3.up * crossScale), clipPoint + (Vector3.down * crossScale), Color.white);
    66.         }
    67.     }
    68.  
    69.     bool LineSegmentIntersection(Vector2 a, Vector2 b, Vector2 c, Vector2 d, out Vector2 point)
    70.     {
    71.         // Sign of areas correspond to which side of ab points c and d are.
    72.         float area1 = SignedTriangleArea(a, b, d);
    73.         float area2 = SignedTriangleArea(a, b, c);
    74.  
    75.         // If c and d are on different sides of ab, areas have different signs.
    76.         if (area1 * area2 < 0.0f)
    77.         {
    78.             // Compute signs for a and b with respect to segment cd.
    79.             float area3 = SignedTriangleArea(c, d, a);
    80.             float area4 = area3 + area2 - area1;
    81.  
    82.             // Points a and b on different sides of cd if areas have different signs.
    83.             if (area3 * area4 < 0.0f)
    84.             {
    85.                 float time = area3 / (area3 - area4);
    86.                 point = a + time * (b - a);
    87.                 return true;
    88.             }
    89.         }
    90.  
    91.         // Segments are not intersecting or collinear.
    92.         point = Vector2.zero;
    93.         return false;
    94.     }
    95.  
    96.     float SignedTriangleArea(Vector2 a, Vector2 b, Vector2 c)
    97.     {
    98.         return (a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x);
    99.     }
    100.  
    101. }
     
    MelvMay likes this.
  11. DmytroSerebrennikov

    DmytroSerebrennikov

    Joined:
    May 28, 2022
    Posts:
    16
    Code (CSharp):
    1. // Fetch the polygon points in world-space (not the most efficient way of doing things)!
    2.         polygonPoints = polygon.points;
    3.         for (var i = 0; i < polygonPoints.Length; ++i)
    4.             polygonPoints[i] = transform.TransformPoint (polygonPoints[i]);
    I've been stuck at this for 3 days already, how can I find the intersection without finding global coordinates or find them in a more optimized way? My FPS drops very much because of this function, I checked it with a stopwatch. please help
     
  12. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,478
    Please create your own thread for your own questions.