private void OnCollisionEnter2D(Collision2D collision) { ContactPoint2D contact = collision.contacts[0]; // Debug.Break(); Triangulator trianSc = collision.gameObject.transform.GetComponent <Triangulator>(); if (trianSc == null) { return; } IndexableCyclicalLinkedList <Vertex> lst = trianSc.GetVertLst(); int prevIdx; int pointIdx = GetClosestPointIdx(lst, contact.point); LinkedListNode <Vertex> prev, nxt, ctr, closest; ctr = GetClosestPointVert(lst, contact.point); closest = ctr; // prev = ctr.Previous; if (ctr.Next != null) { nxt = ctr.Next; } else { nxt = lst.First; } prevIdx = pointIdx - 1; //co gdy circledmg zakrewa wszystkie punkty?.... // //to teraz maja idx bierzesz dwie intersekcje a potem dla tych intersekcji sprawdzasz dystans do segmentow //dzieki temu bedzieszi wiedzil jaki odcienek dzielic. if (prevIdx < 0) { prevIdx += pointsTab.Length; } Vector2 [] intersection; //form first line seg intersection = null; List <Vertex> VertToRemoveLst; VertToRemoveLst = new List <Vertex>(); int someIdx = lst.Count; LinkedListNode <Vertex> prevT, nxtT, ctrT; ctrT = ctr; int a = 0; List <LineSegmentWithAngle> lineSegsOuter; List <LineSegmentInnerWithIntersect> intersectionLineSeg; List <IntersectionWithVert> intersctionVertLst; intersctionVertLst = new List <IntersectionWithVert>(); lineSegsOuter = new List <LineSegmentWithAngle>(); intersectionLineSeg = new List <LineSegmentInnerWithIntersect>(); // return; bool areWeOnBeginning = true; while (1 == 1)//going counter clock wise by vertexes { string temp = "we check now ctr:" + ctr.Value.Index.ToString() + "on " + ctr.Value.Position.ToString() + " and " + nxt.Value.Index.ToString() + "on " + nxt.Value.Position.ToString(); string temp1 = "czy odleglosc od contact point :" + contact.point.ToString() + " do " + ctr.Value.Position.ToString() + " = " + Distance(contact.point, ctr.Value.Position).ToString(); float ctr_next_radius = (float)Distance(ctr.Value.Position, nxt.Value.Position) + dmgRadius; string temp2 = "jest wieksza od dystansy z ctr do nxt plus dmgRadius" + ctr_next_radius.ToString(); if (ctr == closest && areWeOnBeginning) { areWeOnBeginning = false; } if (Distance(contact.point, ctr.Value.Position) > Distance(ctr.Value.Position, nxt.Value.Position) + dmgRadius)//if to far to calc { } else { intersection = Intersection(contact.point.x, contact.point.y, dmgRadius, ctr.Value.Position, nxt.Value.Position); if (Distance(ctr.Value.Position, contact.point) < dmgRadius) { VertToRemoveLst.Add(ctr.Value); } if (intersection != null) { if (intersection.Length == 1) { // lst.AddBefore(nxt, new LinkedListNode<Vertex>(new Vertex(intersection[0], someIdx++))); if (Distance(nxt.Value.Position, contact.point) < dmgRadius) { //odcinek wchodzacy w dmgRadius push. intersectionLineSeg.Add(new LineSegmentInnerWithIntersect(ctr.Value, nxt.Value, ctr, nxt, intersection[0], true)); //zapamietac intersekcje wychodzącę. //pod koniec alg lecisz od wychodzacej dopuki nie masz intersekcji. //powinno dzialac dobrze x171113 Vector2[] circleIntersection; circleIntersection = new Vector2[2]; Vector2 tempRotatedVec = intersection[0]; bool weHaveSecondCircleIntersect = false; // float tempAngle = AngleBetweenVectorsDe(nxt.Value.Position, ctr.Value.Position); // while(!weHaveSecondCircleIntersect)// check is have lenght already? // { // circleIntersection[0] = intersection[0]; // RotateVecPFromI(contact.point, 20, tempRotatedVec); //kuzwa nie da rady tak trzeba wyliczyc wszystkie intersekcje i zapameitywac gdzie byly z jakimi odcinkami i potem na podstawie //tych info dodawac te vertexy. //patrzysz jeszcze czy to jest intersekcja wejsciowa czy wyjsciowa. //mozna dwie listy bo potem tylko szukasz intersekcji wyjsciowych. //to lecisz to tych intesekcjach z odcinkami wedle clockwise i bierzesz pierwsza ktora jest pod wzgledem wielkosci konta. //czyli wyjsciowa intersekcja odcninkowa z najmniejszym katem clockwise co do obecnej wejsciowej. // } //addbefore nxt until in } else { lineSegsOuter.Add(new LineSegmentWithAngle(ctr.Value, nxt.Value)); // intersectionLineSeg.Add(new LineSegmentInnerWithIntersect(ctr.Value, nxt.Value,intersection[0], false)); } // if (Distance(ctr.Value.Position, contact.point) < dmgRadius) // { // VertToRemoveLst.Add(ctr.Value); // kiedy remove bo jak mamy kilka vertow np 3 w kole to jak? // rozkmin ten usuwa tylko dwoch. // } // VertToRemoveLst.Add(ctr.Value); // break; } else { if (FirstIsCloserThenSecond(intersection[0], intersection[1], nxt.Value.Position)) { // lst.AddBefore(nxt, new LinkedListNode<Vertex>(new Vertex(intersection[0], someIdx++))); intersectionLineSeg.Add(new LineSegmentInnerWithIntersect(ctr.Value, nxt.Value, ctr, nxt, intersection[1], true)); lineSegsOuter.Add(new LineSegmentWithAngle(ctr.Value, nxt.Value)); // previus ctr to nxt // lst.AddBefore(nxt.Previous, new LinkedListNode<Vertex>(new Vertex(intersection[1], someIdx++))); // areWeHaveTwoIntesect = true; // break; } else { // lst.AddBefore(nxt, new LinkedListNode<Vertex>(new Vertex(intersection[1], someIdx++))); // lst.AddBefore(nxt.Previous, new LinkedListNode<Vertex>(new Vertex(intersection[0], someIdx++))); intersectionLineSeg.Add(new LineSegmentInnerWithIntersect(ctr.Value, nxt.Value, ctr, nxt, intersection[0], true)); lineSegsOuter.Add(new LineSegmentWithAngle(ctr.Value, nxt.Value)); // areWeHaveTwoIntesect = true; // break; } } } else { // i tak trzbea leciec po wszystkich bo jak beda plaskie polygony to bedzie uj // a jak lecisz po wszystkich to wtedy nie mozesz breakowac jak juz masz intersekcje z dmgRadius. } } ctr = nxt; if (nxt.Next == null) { nxt = lst.First; } else { nxt = nxt.Next; } if (ctr == closest && !areWeOnBeginning) { break; } //ctr = closest; } /* * while(1==1 && !areWeHaveTwoIntesect) * { * intersection = Intersection(contact.point.x, contact.point.y, dmgRadius, ctr.Value.Position, prev.Value.Position); * * if (intersection != null) * { * if (intersection.Length == 1) * { * lst.AddAfter(prev, new LinkedListNode<Vertex>(new Vertex(intersection[0], someIdx++))); * VertToRemoveLst.Add(ctr.Value); * break; * } * else * { * if (FirstIsCloserThenSecond(intersection[0], intersection[1], nxt.Value.Position)) * { * lst.AddAfter(prev, new LinkedListNode<Vertex>(new Vertex(intersection[0], someIdx++))); * lst.AddAfter(prev.Next, new LinkedListNode<Vertex>(new Vertex(intersection[1], someIdx++))); * areWeHaveTwoIntesect = true; * break; * } * else * { * lst.AddAfter(prev, new LinkedListNode<Vertex>(new Vertex(intersection[1], someIdx++))); * lst.AddAfter(prev.Next, new LinkedListNode<Vertex>(new Vertex(intersection[0], someIdx++))); * areWeHaveTwoIntesect = true; * break; * } * } * * } * else * { * ctr = prev; * prev = prev.Previous; * VertToRemoveLst.Add(ctr.Value); * } * } * */ //we must do this i one direction // gizmosLineSegs = new List <LineSegment>(); while (intersectionLineSeg.Count > 0) { LineSegmentInnerWithIntersect trg = intersectionLineSeg[0]; float angleOftrg = Angle(trg.A.Position - trg.B.Position); float angleOfOuter = Angle(lineSegsOuter[0].A.Position - lineSegsOuter[0].B.Position); LinkedListNode <Vertex> tmp; bool weHaveIntersect = false; Vector2 intersecVector = trg.intersection; Vector2 ctrV; ctrV = intersecVector; float basicAngle = Angle(trg.intersection - contact.point); foreach (LineSegmentWithAngle i in lineSegsOuter) { i.angle -= basicAngle; if (i.angle < 0) { i.angle += Mathf.PI * 2; } } //float tempAngle = AngleBetweenVectorsDe(nxt.Value.Position, ctr.Value.Position); // objListOrder.Sort((x, y) => x.OrderDate.CompareTo(y.OrderDate)); lineSegsOuter.OrderByDescending(x => x.angle); float crossingX, crossingY; // lineSegsOuter.Sort() tmp = lst.AddAfter(trg.aLink, new Vertex(trg.intersection, someIdx++)); ctrV = RotateVecPFromI(contact.point, -2, ctrV); while (!weHaveIntersect)// check is have lenght already? { Vector2 nxtV; LineSegmentWithAngle nearestLineSeg = lineSegsOuter[0]; nxtV = RotateVecPFromI(contact.point, -30, ctrV); // czy obraca w dobra strone? if (Get_line_intersection(ctrV.x, ctrV.y, nxtV.x, nxtV.y, nearestLineSeg.A.Position.x, nearestLineSeg.A.Position.y, nearestLineSeg.B.Position.x, nearestLineSeg.B.Position.y, out crossingX, out crossingY) == 0) { ctrV = nxtV; nxtV = RotateVecPFromI(contact.point, -30, ctrV); tmp = lst.AddAfter(tmp, new Vertex(ctrV, someIdx++)); } else { tmp = lst.AddAfter(tmp, new Vertex(new Vector2(crossingX, crossingY), someIdx++)); weHaveIntersect = true; intersectionLineSeg.RemoveAt(0); } gizmosLineSegs.Add(new LineSegment(new Vertex(ctrV, /*idx*/ 1000), new Vertex(nxtV, /*idx*/ 1000))); // lst.ad //kuzwa nie da rady tak trzeba wyliczyc wszystkie intersekcje i zapameitywac gdzie byly z jakimi odcinkami i potem na podstawie //tych info dodawac te vertexy. //patrzysz jeszcze czy to jest intersekcja wejsciowa czy wyjsciowa. //mozna dwie listy bo potem tylko szukasz intersekcji wyjsciowych. //to lecisz to tych intesekcjach z odcinkami wedle clockwise i bierzesz pierwsza ktora jest pod wzgledem wielkosci konta. //czyli wyjsciowa intersekcja odcninkowa z najmniejszym katem clockwise co do obecnej wejsciowej. } } for (int i = 0; i < VertToRemoveLst.Count; i++) { lst.Remove(VertToRemoveLst[i]); } /* * intersection = Intersection(contact.point.x, contact.point.y, dmgRadius, ctr.Value.Position, nxt.Value.Position); * * for(int i=0;i<intersection.Length;i++) * { * circleIntesections.Add(intersection[i]); * } * * * intersection = Intersection(contact.point.x, contact.point.y, dmgRadius, ctr.Value.Position, nxt.Value.Position); * * for (int i = 0; i < intersection.Length; i++) * { * circleIntesections.Add(intersection[i]); * } * */ //lecisz po next od near i dozycasz do wyrzucenia. // //lst. for (int i = 0; i < lst.Count; i++) { Debug.Log(lst[i].Value); } trianSc.ApplyNewPointsFromLst(lst); trianSc.InitNeighboursWithCollision(collision.contacts[0].point, dmgRadius); ExplosionWaker explWk = this.GetComponent <ExplosionWaker>(); if (explWk != null) { explWk.WakeExplo(collision.contacts[0].point, dmgRadius); } Destroy(gameObject); }
/// <summary> /// Cuts a hole into a shape. /// </summary> /// <param name="shapeVerts">An array of vertices for the primary shape.</param> /// <param name="holeVerts">An array of vertices for the hole to be cut. It is assumed that these vertices lie completely within the shape verts.</param> /// <returns>The new array of vertices that can be passed to Triangulate to properly triangulate the shape with the hole.</returns> public static TSVector2[] CutHoleInShape(TSVector2[] shapeVerts, TSVector2[] holeVerts) { Log("\nCutting hole into shape..."); //make sure the shape vertices are wound counter clockwise and the hole vertices clockwise shapeVerts = EnsureWindingOrder(shapeVerts, WindingOrder.CounterClockwise); holeVerts = EnsureWindingOrder(holeVerts, WindingOrder.Clockwise); //clear all of the lists polygonVertices.Clear(); earVertices.Clear(); convexVertices.Clear(); reflexVertices.Clear(); //generate the cyclical list of vertices in the polygon for (int i = 0; i < shapeVerts.Length; i++) { polygonVertices.AddLast(new Vertex(shapeVerts[i], (short)i)); } CyclicalList <Vertex> holePolygon = new CyclicalList <Vertex>(); for (int i = 0; i < holeVerts.Length; i++) { holePolygon.Add(new Vertex(holeVerts[i], (short)(i + polygonVertices.Count))); } #if DEBUG StringBuilder vString = new StringBuilder(); foreach (Vertex v in polygonVertices) { vString.Append(string.Format("{0}, ", v)); } Log("Shape Vertices: {0}", vString); vString = new StringBuilder(); foreach (Vertex v in holePolygon) { vString.Append(string.Format("{0}, ", v)); } Log("Hole Vertices: {0}", vString); #endif FindConvexAndReflexVertices(); FindEarVertices(); //find the hole vertex with the largest X value Vertex rightMostHoleVertex = holePolygon[0]; foreach (Vertex v in holePolygon) { if (v.Position.x > rightMostHoleVertex.Position.x) { rightMostHoleVertex = v; } } //construct a list of all line segments where at least one vertex //is to the right of the rightmost hole vertex with one vertex //above the hole vertex and one below List <LineSegment> segmentsToTest = new List <LineSegment>(); for (int i = 0; i < polygonVertices.Count; i++) { Vertex a = polygonVertices[i].Value; Vertex b = polygonVertices[i + 1].Value; if ((a.Position.x > rightMostHoleVertex.Position.x || b.Position.x > rightMostHoleVertex.Position.x) && ((a.Position.y >= rightMostHoleVertex.Position.y && b.Position.y <= rightMostHoleVertex.Position.y) || (a.Position.y <= rightMostHoleVertex.Position.y && b.Position.y >= rightMostHoleVertex.Position.y))) { segmentsToTest.Add(new LineSegment(a, b)); } } //now we try to find the closest intersection point heading to the right from //our hole vertex. FP? closestPoint = null; LineSegment closestSegment = new LineSegment(); foreach (LineSegment segment in segmentsToTest) { FP?intersection = segment.IntersectsWithRay(rightMostHoleVertex.Position, TSVector2.right); if (intersection != null) { if (closestPoint == null || closestPoint.Value > intersection.Value) { closestPoint = intersection; closestSegment = segment; } } } //if closestPoint is null, there were no collisions (likely from improper input data), //but we'll just return without doing anything else if (closestPoint == null) { return(shapeVerts); } //otherwise we can find our mutually visible vertex to split the polygon TSVector2 I = rightMostHoleVertex.Position + TSVector2.right * closestPoint.Value; Vertex P = (closestSegment.A.Position.x > closestSegment.B.Position.x) ? closestSegment.A : closestSegment.B; //construct triangle MIP Triangle mip = new Triangle(rightMostHoleVertex, new Vertex(I, 1), P); //see if any of the reflex vertices lie inside of the MIP triangle List <Vertex> interiorReflexVertices = new List <Vertex>(); foreach (Vertex v in reflexVertices) { if (mip.ContainsPoint(v)) { interiorReflexVertices.Add(v); } } //if there are any interior reflex vertices, find the one that, when connected //to our rightMostHoleVertex, forms the line closest to Vector2.UnitX if (interiorReflexVertices.Count > 0) { FP closestDot = -1f; foreach (Vertex v in interiorReflexVertices) { //compute the dot product of the vector against the UnitX TSVector2 d = TSVector2.Normalize(v.Position - rightMostHoleVertex.Position); FP dot = TSVector2.Dot(TSVector2.right, d); //if this line is the closest we've found if (dot > closestDot) { //save the value and save the vertex as P closestDot = dot; P = v; } } } //now we just form our output array by injecting the hole vertices into place //we know we have to inject the hole into the main array after point P going from //rightMostHoleVertex around and then back to P. int mIndex = holePolygon.IndexOf(rightMostHoleVertex); int injectPoint = polygonVertices.IndexOf(P); Log("Inserting hole at injection point {0} starting at hole vertex {1}.", P, rightMostHoleVertex); for (int i = mIndex; i <= mIndex + holePolygon.Count; i++) { Log("Inserting vertex {0} after vertex {1}.", holePolygon[i], polygonVertices[injectPoint].Value); polygonVertices.AddAfter(polygonVertices[injectPoint++], holePolygon[i]); } polygonVertices.AddAfter(polygonVertices[injectPoint], P); #if DEBUG vString = new StringBuilder(); foreach (Vertex v in polygonVertices) { vString.Append(string.Format("{0}, ", v)); } Log("New Shape Vertices: {0}\n", vString); #endif //finally we write out the new polygon vertices and return them out TSVector2[] newShapeVerts = new TSVector2[polygonVertices.Count]; for (int i = 0; i < polygonVertices.Count; i++) { newShapeVerts[i] = polygonVertices[i].Value.Position; } return(newShapeVerts); }
/// <summary> /// Cuts a hole into a shape. /// </summary> /// <param name="shapeVerts">An array of vertices for the primary shape.</param> /// <param name="holeVerts">An array of vertices for the hole to be cut. It is assumed that these vertices lie completely within the shape verts.</param> /// <returns>The new array of vertices that can be passed to Triangulate to properly triangulate the shape with the hole.</returns> public static Vector2[] CutHoleInShape(Vector2[] shapeVerts, Vector2[] holeVerts) { //make sure the shape vertices are wound counter clockwise and the hole vertices clockwise shapeVerts = EnsureWindingOrder(shapeVerts, WindingOrder.CounterClockwise); holeVerts = EnsureWindingOrder(holeVerts, WindingOrder.Clockwise); //clear all of the lists polygonVertices.Clear(); earVertices.Clear(); convexVertices.Clear(); reflexVertices.Clear(); //generate the cyclical list of vertices in the polygon for (int i = 0; i < shapeVerts.Length; i++) { polygonVertices.AddLast(new Vertex(shapeVerts[i], i)); } CyclicalList <Vertex> holePolygon = new CyclicalList <Vertex>(); for (int i = 0; i < holeVerts.Length; i++) { holePolygon.Add(new Vertex(holeVerts[i], i + polygonVertices.Count)); } FindConvexAndReflexVertices(); FindEarVertices(); //find the hole vertex with the largest X value Vertex rightMostHoleVertex = holePolygon[0]; foreach (Vertex v in holePolygon) { if (v.Position.x > rightMostHoleVertex.Position.x) { rightMostHoleVertex = v; } } Debug.Log("rightMost to cut out is " + rightMostHoleVertex); Debug.Log("rightMost to cut out isdskdl;skdl;ksal;dkl;sakd;lksa;ldk;sakd;lsakdl;ksa;ldfdgdfgfdsgfdgfdgdgfd\n \n\n\n "); //construct a list of all line segments where at least one vertex //is to the right of the rightmost hole vertex with one vertex //above the hole vertex and one below List <LineSegment> segmentsToTest = new List <LineSegment>(); for (int i = 0; i < polygonVertices.Count; i++) { Vertex a = polygonVertices[i].Value; Vertex b = polygonVertices[i + 1].Value; if ((a.Position.x > rightMostHoleVertex.Position.x || b.Position.x > rightMostHoleVertex.Position.x) && ((a.Position.y >= rightMostHoleVertex.Position.y && b.Position.y <= rightMostHoleVertex.Position.y) || (a.Position.y <= rightMostHoleVertex.Position.y && b.Position.y >= rightMostHoleVertex.Position.y))) { segmentsToTest.Add(new LineSegment(a, b)); } } //now we try to find the closest intersection point heading to the right from //our hole vertex. float? closestPoint = null; LineSegment closestSegment = new LineSegment(); foreach (LineSegment segment in segmentsToTest) { float?intersection = segment.IntersectsWithRay(rightMostHoleVertex.Position, new Vector2(1f, 0f)); if (intersection != null) { if (closestPoint == null || closestPoint.Value > intersection.Value) { closestPoint = intersection; closestSegment = segment; } } } //if closestPoint is null, there were no collisions (likely from improper input data), //but we'll just return without doing anything else if (closestPoint == null) { return(shapeVerts); } //otherwise we can find our mutually visible vertex to split the polygon Vector2 I = rightMostHoleVertex.Position + new Vector2(1f, 0f) * closestPoint.Value; Vertex P = (closestSegment.A.Position.x > closestSegment.B.Position.x) ? closestSegment.A : closestSegment.B; //construct triangle MIP Triangle mip = new Triangle(rightMostHoleVertex, new Vertex(I, 1), P); //see if any of the reflex vertices lie inside of the MIP triangle List <Vertex> interiorReflexVertices = new List <Vertex>(); foreach (Vertex v in reflexVertices) { if (mip.ContainsPoint(v)) { interiorReflexVertices.Add(v); } } //if there are any interior reflex vertices, find the one that, when connected //to our rightMostHoleVertex, forms the line closest to Vector2.UnitX if (interiorReflexVertices.Count > 0) { float closestDot = -1f; foreach (Vertex v in interiorReflexVertices) { //compute the dot product of the vector against the UnitX Vector2 d = v.Position - rightMostHoleVertex.Position; d.Normalize(); float dot = Vector2.Dot(new Vector2(1f, 0), d); //if this line is the closest we've found if (dot > closestDot) { //save the value and save the vertex as P closestDot = dot; P = v; } } } //now we just form our output array by injecting the hole vertices into place //we know we have to inject the hole into the main array after point P going from //rightMostHoleVertex around and then back to P. int mIndex = holePolygon.IndexOf(rightMostHoleVertex); int injectPoint = polygonVertices.IndexOf(P); for (int i = mIndex; i <= mIndex + holePolygon.Count; i++) { polygonVertices.AddAfter(polygonVertices[injectPoint++], holePolygon[i]); } polygonVertices.AddAfter(polygonVertices[injectPoint], P); //finally we write out the new polygon vertices and return them out Vector2[] newShapeVerts = new Vector2[polygonVertices.Count]; for (int i = 0; i < polygonVertices.Count; i++) { newShapeVerts[i] = polygonVertices[i].Value.Position; } return(newShapeVerts); }