示例#1
0
 private Polygon2 ClipHoleContour(Polygon2 polygon)
 {
     PolygonOperations.TryConvexClip(polygon, ClipperExtentsHoleClipPolygon, out var result);
     if (result != null)
     {
         for (var i = 0; i < result.Points.Count; i++)
         {
             var t = true;
             ClipperBase.RangeTest(result.Points[i], ref t);
         }
     }
     return(result);
 }
示例#2
0
 public static bool SlopesEqual(IntPoint pt1, IntPoint pt2, IntPoint pt3, IntPoint pt4, bool UseFullRange)
 {
     return(ClipperBase.SlopesEqual(pt1, pt2, pt3, pt4, UseFullRange));
 }
        internal static bool AddPath(this Clipper clipper, List <Vector2d> pg, PolyType polyType, float scale,
                                     bool closed)
        {
            if (!closed)
            {
                throw new ClipperException("AddPath: Open paths have been disabled.");
            }

            int highI = pg.Count() - 1;

            if (closed)
            {
                while (highI > 0 && (pg[highI] == pg[0]))
                {
                    --highI;
                }
            }
            while (highI > 0 && (pg[highI] == pg[highI - 1]))
            {
                --highI;
            }
            if ((closed && highI < 2) || (!closed && highI < 1))
            {
                return(false);
            }

            //create a new edge array ...
            List <TEdge> edges = new List <TEdge>(highI + 1);

            for (int i = 0; i <= highI; i++)
            {
                edges.Add(ClipperPool.AllocEdge());
            }

            bool IsFlat = true;

            //1. Basic (first) edge initialization ...
            var pg0     = new IntPoint(pg[0].X * scale, pg[0].Y * scale);
            var pgHighI = new IntPoint(pg[highI].X * scale, pg[highI].Y * scale);

            edges[1].Curr = new IntPoint(pg[1].X * scale, pg[1].Y * scale);
            clipper.RangeTest(pg0, ref clipper.m_UseFullRange);
            clipper.RangeTest(pgHighI, ref clipper.m_UseFullRange);
            clipper.InitEdge(edges[0], edges[1], edges[highI], pg0);
            clipper.InitEdge(edges[highI], edges[0], edges[highI - 1], pgHighI);
            for (int i = highI - 1; i >= 1; --i)
            {
                var pgI = new IntPoint(pg[i].X * scale, pg[i].Y * scale);
                clipper.RangeTest(pgI, ref clipper.m_UseFullRange);
                clipper.InitEdge(edges[i], edges[i + 1], edges[i - 1], pgI);
            }
            TEdge eStart = edges[0];

            //2. Remove duplicate vertices, and (when closed) collinear edges ...
            TEdge E = eStart, eLoopStop = eStart;

            for (;;)
            {
                //nb: allows matching start and end points when not Closed ...
                if (E.Curr == E.Next.Curr && (closed || E.Next != eStart))
                {
                    if (E == E.Next)
                    {
                        break;
                    }
                    if (E == eStart)
                    {
                        eStart = E.Next;
                    }
                    E         = clipper.RemoveEdge(E);
                    eLoopStop = E;
                    continue;
                }
                if (E.Prev == E.Next)
                {
                    break; //only two vertices
                }
                if (closed &&
                    ClipperBase.SlopesEqual(E.Prev.Curr, E.Curr, E.Next.Curr, clipper.m_UseFullRange) &&
                    (!clipper.PreserveCollinear ||
                     !clipper.Pt2IsBetweenPt1AndPt3(E.Prev.Curr, E.Curr, E.Next.Curr)))
                {
                    //Collinear edges are allowed for open paths but in closed paths
                    //the default is to merge adjacent collinear edges into a single edge.
                    //However, if the PreserveCollinear property is enabled, only overlapping
                    //collinear edges (ie spikes) will be removed from closed paths.
                    if (E == eStart)
                    {
                        eStart = E.Next;
                    }
                    E         = clipper.RemoveEdge(E);
                    E         = E.Prev;
                    eLoopStop = E;
                    continue;
                }
                E = E.Next;
                if ((E == eLoopStop) || (!closed && E.Next == eStart))
                {
                    break;
                }
            }

            if ((!closed && (E == E.Next)) || (closed && (E.Prev == E.Next)))
            {
                return(false);
            }

            //3. Do second stage of edge initialization ...
            E = eStart;
            do
            {
                clipper.InitEdge2(E, polyType);
                E = E.Next;
                if (IsFlat && E.Curr.Y != eStart.Curr.Y)
                {
                    IsFlat = false;
                }
            } while (E != eStart);

            //4. Finally, add edge bounds to LocalMinima list ...

            //Totally flat paths must be handled differently when adding them
            //to LocalMinima list to avoid endless loops etc ...
            if (IsFlat)
            {
                if (closed)
                {
                    return(false);
                }
            }

            clipper.m_edges.Add(edges);
            bool  leftBoundIsForward;
            TEdge EMin = null;

            //workaround to avoid an endless loop in the while loop below when
            //open paths have matching start and end points ...
            if (E.Prev.Bot == E.Prev.Top)
            {
                E = E.Next;
            }

            for (;;)
            {
                E = clipper.FindNextLocMin(E);
                if (E == EMin)
                {
                    break;
                }
                if (EMin == null)
                {
                    EMin = E;
                }

                //E and E.Prev now share a local minima (left aligned if horizontal).
                //Compare their slopes to find which starts which bound ...
                LocalMinima locMin = new LocalMinima();
                locMin.Next = null;
                locMin.Y    = E.Bot.Y;
                if (E.Dx < E.Prev.Dx)
                {
                    locMin.LeftBound   = E.Prev;
                    locMin.RightBound  = E;
                    leftBoundIsForward = false; //Q.nextInLML = Q.prev
                }
                else
                {
                    locMin.LeftBound   = E;
                    locMin.RightBound  = E.Prev;
                    leftBoundIsForward = true; //Q.nextInLML = Q.next
                }
                locMin.LeftBound.Side  = EdgeSide.esLeft;
                locMin.RightBound.Side = EdgeSide.esRight;

                if (locMin.LeftBound.Next == locMin.RightBound)
                {
                    locMin.LeftBound.WindDelta = -1;
                }
                else
                {
                    locMin.LeftBound.WindDelta = 1;
                }
                locMin.RightBound.WindDelta = -locMin.LeftBound.WindDelta;

                E = clipper.ProcessBound(locMin.LeftBound, leftBoundIsForward);
                if (E.OutIdx == ClipperBase.Skip)
                {
                    E = clipper.ProcessBound(E, leftBoundIsForward);
                }

                TEdge E2 = clipper.ProcessBound(locMin.RightBound, !leftBoundIsForward);
                if (E2.OutIdx == ClipperBase.Skip)
                {
                    E2 = clipper.ProcessBound(E2, !leftBoundIsForward);
                }

                if (locMin.LeftBound.OutIdx == ClipperBase.Skip)
                {
                    locMin.LeftBound = null;
                }
                else if (locMin.RightBound.OutIdx == ClipperBase.Skip)
                {
                    locMin.RightBound = null;
                }
                clipper.InsertLocalMinima(locMin);
                if (!leftBoundIsForward)
                {
                    E = E2;
                }
            }
            return(true);
        }
    // Update is called once per frame
    void Update()
    {
        particleCollisionJob.maxParticleCollisionEffectDistance = maxParticleCollisionEffectDistance;
        particleCollisionJob.deltaTime        = Time.deltaTime;
        particleTriggerCollisionJob.deltaTime = Time.deltaTime;
        int currentTime = System.DateTime.Now.Millisecond;

        ParticleSystem.Particle[] myParticles = new ParticleSystem.Particle[ps.main.maxParticles];
        int maxParticles = ps.GetParticles(myParticles);

        Clipper c = new Clipper();
        float   sizeMultiplier   = 1;
        int     realMaxParticles = 0;
        // for( int i = 0; i < maxParticles; i++ )
        // {
        //     var psSOL = ps.sizeOverLifetime;
        //     if( psSOL.enabled )
        //     {
        //         sizeMultiplier = psSOL.size.Evaluate( 1 - (myParticles[i].remainingLifetime / myParticles[i].startLifetime) );
        //     }
        //     if( sizeMultiplier >= sizeOverLifetimeCutoff )
        //     {
        //         realMaxParticles++;
        //     }
        // }
        Paths subj       = new Paths();
        int   addedPaths = 0;

        for (int i = 0; i < maxParticles; i++)
        {
            var psSOL = ps.sizeOverLifetime;
            if (psSOL.enabled)
            {
                sizeMultiplier = psSOL.size.Evaluate(1 - (myParticles[i].remainingLifetime / myParticles[i].startLifetime));
            }
            if (sizeMultiplier >= sizeOverLifetimeCutoff)
            {
                subj.Add(new Path(4));
                subj[addedPaths].Add(new IntPoint((int)((myParticles[i].position.x - sizeMultiplier * particleWidth / 2f) * clipperPrecision), (int)((myParticles[i].position.y - sizeMultiplier * particleWidth / 2f) * clipperPrecision)));
                subj[addedPaths].Add(new IntPoint((int)((myParticles[i].position.x + sizeMultiplier * particleWidth / 2f) * clipperPrecision), (int)((myParticles[i].position.y - sizeMultiplier * particleWidth / 2f) * clipperPrecision)));
                subj[addedPaths].Add(new IntPoint((int)((myParticles[i].position.x + sizeMultiplier * particleWidth / 2f) * clipperPrecision), (int)((myParticles[i].position.y + sizeMultiplier * particleWidth / 2f) * clipperPrecision)));
                subj[addedPaths].Add(new IntPoint((int)((myParticles[i].position.x - sizeMultiplier * particleWidth / 2f) * clipperPrecision), (int)((myParticles[i].position.y + sizeMultiplier * particleWidth / 2f) * clipperPrecision)));
                addedPaths++;
            }
        }

        IntRect boundingRect = ClipperBase.GetBounds(subj);
        Paths   clipperPath  = new Paths(1);

        clipperPath.Add(new Path(4));
        clipperPath[0].Add(new IntPoint(boundingRect.left, boundingRect.bottom));
        clipperPath[0].Add(new IntPoint(boundingRect.right, boundingRect.bottom));
        clipperPath[0].Add(new IntPoint(boundingRect.right, boundingRect.top));
        clipperPath[0].Add(new IntPoint(boundingRect.left, boundingRect.top));

        c.AddPaths(subj, PolyType.ptSubject, true);
        c.AddPaths(clipperPath, PolyType.ptClip, true);

        timeToCreatePaths = (System.DateTime.Now.Millisecond - currentTime) / 1000f;
        currentTime       = System.DateTime.Now.Millisecond;

        c.Execute(ClipType.ctIntersection, solution,
                  PolyFillType.pftNonZero, PolyFillType.pftNonZero);

        timeToExecutePaths = (System.DateTime.Now.Millisecond - currentTime) / 1000f;
        currentTime        = System.DateTime.Now.Millisecond;

        myCollider.pathCount = solution.Count;
        // List<Vector2> colliderPaths = new List<Vector2>();
        for (int i = 0; i < solution.Count; i++)
        {
            Vector2[] colliderPaths = new Vector2[solution[i].Count];
            for (int j = 0; j < solution[i].Count; j++)
            {
                Vector2 tempPoints = new Vector2((float)solution[i][j].X / clipperPrecision - transform.position.x, (float)solution[i][j].Y / clipperPrecision - transform.position.y);
                colliderPaths[j] = Quaternion.Inverse(transform.rotation) * ((Vector3)(tempPoints));
                if (drawBounds)
                {
                    Debug.DrawLine(
                        new Vector2((float)solution[i][j].X / clipperPrecision, (float)solution[i][j].Y / clipperPrecision),
                        new Vector2((float)solution[i][(j + 1) % solution[i].Count].X / clipperPrecision, (float)solution[i][(j + 1) % solution[i].Count].Y / clipperPrecision),
                        Color.magenta
                        );
                }
            }
            if (i < 100)
            {
                myCollider.SetPath(i, colliderPaths);
            }
        }
        timeToDrawPaths = (System.DateTime.Now.Millisecond - currentTime) / 1000f;
        currentTime     = System.DateTime.Now.Millisecond;

        if (myCollider.isTrigger)
        {
            if (!particleTriggerColliders.ContainsKey(myCollider.gameObject.GetInstanceID()))
            {
                particleTriggerColliders.Add(myCollider.gameObject.GetInstanceID(), new TriggerColliderData(myCollider, solution, myCollider.bounds));
            }
            else
            {
                particleTriggerColliders[myCollider.gameObject.GetInstanceID()].path   = solution;
                particleTriggerColliders[myCollider.gameObject.GetInstanceID()].bounds = myCollider.bounds;
            }
        }
    }