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); }
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; } } }