コード例 #1
0
        public static bool SweepIntersects(Vector2 a1, Vector2 a2, Vector2 b1, Vector2 b2, Vector2 l1, Vector2 l2, out Vector2 intersection, out float percent, float accuracy = 1)
        {
            intersection = Vector2.zero;
            percent      = 0;
            Vector2 lineDelta = l2 - l1;
            Vector2 point     = l2;

            b1 += -lineDelta;
            b2 += -lineDelta;
            Vector2[]  poly   = { a1, a2, b2, b1 };
            FlatBounds bounds = new FlatBounds(poly);

            if (!bounds.Contains(l1))
            {
                return(false);
            }

//            bounds.DrawDebug(Color.yellow);

            Vector2 pointRight = point + new Vector2(Mathf.Max(bounds.width, bounds.height), 0);
            //            Vector2 pointRight = point - lineDelta * bounds.width * bounds.height;
//            Debug.DrawLine(ToV3(point), ToV3(pointRight), Color.cyan);

            int numberOfPolyPoints = poly.Length;
            int numberOfCrossOvers = 0;

            for (int i = 0; i < numberOfPolyPoints; i++)
            {
                Vector2 p0 = poly[i];
                Vector2 p1 = poly[(i + 1) % numberOfPolyPoints];
//                Debug.DrawLine(ToV3(p0), ToV3(p1), Color.blue);
                if (FastLineIntersection(point, pointRight, p0, p1))
                {
                    numberOfCrossOvers++;
                }
            }

            if (numberOfCrossOvers % 2 == 0)
            {
                return(false);//point not within shape
            }
            bounds.DrawDebug(Color.green);

            Vector2 delta1     = b1 - a1;
            Vector2 delta2     = b2 - a2;
            float   maxDelta   = Mathf.Max(delta1.magnitude, delta2.magnitude);
            int     iterations = Mathf.CeilToInt(Mathf.Sqrt(maxDelta / accuracy));

            for (int i = 0; i < iterations; i++)
            {
                Vector2 c1 = Vector2.Lerp(a1, b1, 0.5f);
                Vector2 c2 = Vector2.Lerp(a2, b2, 0.5f);
                if (!Ccw(c1, c2, point))
                {
                    a1      = c1;
                    a2      = c2;
                    percent = Mathf.Lerp(percent, 1, 0.5f);
                }
                else
                {
                    b1      = c1;
                    b2      = c2;
                    percent = Mathf.Lerp(0, percent, 0.5f);
                }
            }

//            Vector2 x1 = Vector2.Lerp(a1, b1, 0.5f);
//            Vector2 x2 = Vector2.Lerp(a2, b2, 0.5f);
//            float dist1 = Vector2.Distance(x1, point);
//            float dist2 = Vector2.Distance(x2, point);
//            float xpercent = dist1 / (dist1 + dist2);
//            intersection = Vector2.Lerp(x1, x2, xpercent);
            intersection = Vector2.Lerp(l1, l2, percent);//translate the point to the real movement point
            Debug.DrawLine(ToV3(intersection), ToV3(intersection) + Vector3.up * 5, Color.red);
            return(true);
        }
コード例 #2
0
        public static bool SweepIntersects2(Vector2 a1, Vector2 a2, Vector2 b1, Vector2 b2, Vector2 l1, Vector2 l2, out Vector2 intersection, out float percent, float accuracy = 1, bool debug = false)
        {
            intersection = Vector2.zero;
            percent      = 0;
            Vector2[]  poly       = { a1, a2, b2, b1 };
            FlatBounds edgeBounds = new FlatBounds(poly);
            FlatBounds lineBounds = new FlatBounds(new [] { l1, l2 });

            if (!edgeBounds.Overlaps(lineBounds, true))
            {
                if (debug)
                {
                    edgeBounds.DrawDebug(Color.cyan);
                }
                if (debug)
                {
                    lineBounds.DrawDebug(Color.green);
                }
                if (debug)
                {
                    Debug.DrawLine(ToV3(l1), ToV3(l2), Color.cyan);
                }
                return(false);
            }

            int  numberOfPolyPoints  = poly.Length;
            bool lineIntersectsShape = false;

            for (int i = 0; i < numberOfPolyPoints; i++)
            {
                Vector2 p0 = poly[i];
                Vector2 p1 = poly[(i + 1) % numberOfPolyPoints];
                if (debug)
                {
                    Debug.DrawLine(ToV3(p0), ToV3(p1), Color.blue);
                }
                if (FastLineIntersection(p0, p1, l1, l2))
                {
                    lineIntersectsShape = true;
                    break;
                }
            }

            if (!lineIntersectsShape)//line never crosses shape
            {
                Vector2 right = new Vector2(Mathf.Max(edgeBounds.width, edgeBounds.height), 0);
                int     shapeIntersections = 0;
                for (int i = 0; i < numberOfPolyPoints; i++)
                {
                    Vector2 p0 = poly[i];
                    Vector2 p1 = poly[(i + 1) % numberOfPolyPoints];
                    if (debug)
                    {
                        Debug.DrawLine(ToV3(p0) + Vector3.up * 5, ToV3(p1) + Vector3.up * 5, Color.blue);
                    }
                    if (FastLineIntersection(l1, l1 + right, p0, p1))
                    {
                        if (debug)
                        {
                            Debug.DrawLine(ToV3(l1), ToV3(l1) + Vector3.up * 5, Color.magenta);
                        }
                        shapeIntersections++;
                    }
                    if (FastLineIntersection(l2, l2 + right, p0, p1))
                    {
                        if (debug)
                        {
                            Debug.DrawLine(ToV3(l1), ToV3(l1) + Vector3.up * 5, Color.magenta);
                        }
                        shapeIntersections++;
                        break;
                    }
                }

                if (shapeIntersections % 2 == 0)
                {
                    return(false);//line not within shape
                }
            }
            if (debug)
            {
                edgeBounds.DrawDebug(Color.green);
            }

            Vector2 delta1      = b1 - a1;
            Vector2 delta2      = b2 - a2;
            float   maxDelta    = Mathf.Max(delta1.magnitude, delta2.magnitude);
            int     iterations  = Mathf.CeilToInt(maxDelta / accuracy);
            bool    initalState = Ccw(a1, a2, l1);

            for (int i = 1; i < iterations; i++)
            {
                percent = i / (iterations - 1f);

                Vector2 e1 = Vector2.Lerp(a1, b1, percent);
                Vector2 e2 = Vector2.Lerp(a2, b2, percent);
                if (debug)
                {
                    Debug.DrawLine(ToV3(e1), ToV3(e2), new Color(1, 0, 1, 0.5f));
                }
                Vector2 p = Vector2.Lerp(l1, l2, percent);

                bool currentState = Ccw(e1, e2, p);

                if (currentState != initalState || i == iterations - 1)
                {
                    float dist1    = Vector2.Distance(e1, p);
                    float dist2    = Vector2.Distance(e2, p);
                    float xpercent = dist1 / (dist1 + dist2);
                    intersection = Vector2.Lerp(e1, e2, xpercent);
                    if (debug)
                    {
                        Debug.DrawLine(ToV3(e1), ToV3(e2), Color.red);
                    }
                    if (debug)
                    {
                        Debug.DrawLine(ToV3(intersection), ToV3(intersection) + Vector3.up * 10, Color.red);
                    }

                    break;
                }
            }
            return(true);
        }
コード例 #3
0
ファイル: QuickPolyCut.cs プロジェクト: ishui/unity3DScripts
        /// <summary>
        /// Return a shape with a defined shape cut out of it.
        /// Will test find the best closest non intersectional cut to make in the base shape
        /// Assumes the cut doesn't intersect the shape lines and is inside the base shape
        /// </summary>
        /// <param name="baseShape"></param>
        /// <param name="cut"></param>
        /// <returns></returns>
        public static Vector2[] Execute(Vector2[] baseShape, List <Vector2[]> cuts)
        {
            bool dbg = false;

            Vector2[] cut         = (Vector2[])cuts[0].Clone();//todo multiple cuts
            int       baseCount   = baseShape.Length;
            int       cutCount    = cut.Length;
            int       outputCount = baseCount + cutCount + 2;

            Vector2[]  output = new Vector2[outputCount];
            FlatBounds bounds = new FlatBounds(cut);

            if (dbg)
            {
                bounds.DrawDebug(Color.magenta);
            }
            Vector2 center       = bounds.center;
            float   nrest        = Mathf.Infinity;
            int     nearestIndex = 0;

            Array.Reverse(cut);//reverse winding to create cut
            for (int b = 0; b < baseCount; b++)
            {
                float sqrMag = (baseShape[b] - center).sqrMagnitude;
                if (sqrMag < nrest)
                {
                    Vector2 a1 = center;
                    Vector2 a2 = baseShape[b];

                    bool intersectsShape = false;
                    for (int x = 0; x < baseCount; x++)
                    {
                        if (b == x)
                        {
                            continue;
                        }
                        int x2 = (x + 1) % baseCount;
                        if (b == x2)
                        {
                            continue;
                        }
                        Vector2 b1 = baseShape[x];
                        Vector2 b2 = baseShape[x2];
                        if (dbg)
                        {
                            Debug.DrawLine(ToV3(b1), ToV3(b2), Color.yellow);
                        }
                        if (FastLineIntersection(a1, a2, b1, b2))
                        {
                            intersectsShape = true;
                            break;
                        }
                    }
                    if (!intersectsShape)
                    {
                        nearestIndex = b;
                        nrest        = sqrMag;
                    }
                    //intersection check
                }
            }

            //find nearest cut point to base point
            int     nearestCutIndex = 0;
            float   nearestCut      = Mathf.Infinity;
            Vector2 baseCut         = baseShape[nearestIndex];

            for (int i = 0; i < cutCount; i++)
            {
                float sqrMag = (cut[i] - baseCut).sqrMagnitude;
                if (sqrMag < nearestCut)
                {
                    nearestCutIndex = i;
                    nearestCut      = sqrMag;
                }
            }

            if (dbg)
            {
                Debug.Log(nearestIndex);
                Debug.DrawLine(ToV3(baseShape[nearestIndex]), ToV3(center), Color.red);
            }

            for (int o = 0; o < outputCount; o++)
            {
                if (o <= nearestIndex)
                {
                    output[o] = baseShape[o];
                    if (dbg && o > 0)
                    {
                        Debug.DrawLine(ToV3(output[o]), ToV3(output[o - 1]) + Vector3.up, Color.blue, 60);
                    }
                    if (dbg)
                    {
                        Debug.Log("0x " + baseCount + " " + cutCount + " " + output.Length + " " + o);
                    }
                }
                else if (o > nearestIndex && o <= nearestIndex + cutCount + 1)
                {
                    int cutIndex = (nearestCutIndex + o - nearestIndex - 1) % cutCount;
                    output[o] = cut[cutIndex];
                    if (dbg && o > 0)
                    {
                        Debug.DrawLine(ToV3(output[o]), ToV3(output[o - 1]) + Vector3.up, Color.blue, 60);
                    }
                    if (dbg)
                    {
                        Debug.Log("1x " + cutIndex + " " + baseCount + " " + cutCount + " " + output.Length + " " + o);
                    }
                }
                else
                {
                    int finalIndex = (o - cutCount - 2 + baseCount) % baseCount;
                    if (dbg)
                    {
                        Debug.Log("2x " + finalIndex + " " + baseCount + " " + cutCount + " " + output.Length + " " + o);
                    }
                    output[o] = baseShape[finalIndex];
                    if (dbg && o > 0)
                    {
                        Debug.DrawLine(ToV3(output[o]), ToV3(output[o - 1]) + Vector3.up, Color.blue, 60);
                    }
                }
            }

            return(output);
        }