Exemple #1
0
    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);
    }
Exemple #2
0
        /// <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);
        }
Exemple #3
0
    /// <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);
    }