//
    public static void Clip(Vector2[] clip, Vector2[] shape, out List <List <Vector2> > result)
    {
        result = new List <List <Vector2> >();

        List <DeepPoint> deepShape = new List <DeepPoint>();
        List <DeepPoint> deepClip  = new List <DeepPoint>();

        foreach (Vector2 v in shape)
        {
            deepShape.Add(new DeepPoint(v, DeepPoint.PointType.Normal, DeepPoint.InOrOut(v, clip)));
        }

        foreach (Vector2 v in clip)
        {
            deepClip.Add(new DeepPoint(v, DeepPoint.PointType.Normal, DeepPoint.InOrOut(v, shape)));
        }

        for (int i = 0; i < deepShape.Count; i++)
        {
            DeepPoint p1 = deepShape[i];
            DeepPoint p2 = NextAfter(deepShape, i);

            //check for intersections
            for (int j = 0; j < deepClip.Count; j++)
            {
                DeepPoint c1 = deepClip[j];
                DeepPoint c2 = NextAfter(deepClip, j);

                List <Vector2> interOutput;
                if (LineIntersection(p1, p2, c1, c2, out interOutput))
                {
                    foreach (Vector2 inter in interOutput)
                    {
                        //This ensures that we have the same intersection added to both (avoid precision errors)
                        DeepPoint intersection = new DeepPoint(inter, DeepPoint.PointType.Intersection, DeepPoint.PointStatus.Undetermined);

                        if (inter == p1.p || inter == p2.p || inter == c1.p || inter == c2.p)
                        {
                            if (inter == p1.p && inter == c1.p)
                            {
                                p1.overlap = true;
                                c1.overlap = true;
                                p1.type    = DeepPoint.PointType.Intersection;
                                c1.type    = DeepPoint.PointType.Intersection;
                                continue;
                            }
                            else if (inter != p2.p && inter != c1.p && inter != c2.p)
                            {
                                if (inter == p1.p)
                                {
                                    p1.overlap = true;
                                    p1.type    = DeepPoint.PointType.Intersection;
                                }
                                else
                                {
                                    p1.intersections.Add(intersection);
                                }

                                c1.intersections.Add(intersection);
                            }
                        }
                        else
                        {
                            //TODO: if intersection is same as p1,p2,c1,c2 -> make a note of it?
                            p1.intersections.Add(intersection);
                            c1.intersections.Add(intersection);
                        }
                    }
                }
            }

            //sort intersections by distance to p1
            p1.SortIntersections();


            //loop through intersections between p1 and p2
            for (int j = 0; j < p1.intersections.Count; j++)
            {
                DeepPoint intersection = p1.intersections[j];

                //if there's a previous intersection
                if (j > 0)
                {
                    DeepPoint prev = p1.intersections[j - 1];
                    if (prev.status == DeepPoint.PointStatus.In)
                    {
                        intersection.status = DeepPoint.PointStatus.Out;                                          //set inter pStatus to Out
                    }
                    else
                    {
                        intersection.status = DeepPoint.PointStatus.In;  //set inter as In
                    }
                }
                else if (p1.status == DeepPoint.PointStatus.In)
                {
                    intersection.status = DeepPoint.PointStatus.Out;                                             //set inter as Out
                }
                else
                {
                    intersection.status = DeepPoint.PointStatus.In;  //set inter as In
                }
            }
        }

        //sort all intersections in clip
        for (int i = 0; i < deepClip.Count; i++)
        {
            deepClip[i].SortIntersections();
        }

        IntegrateIntersections(ref deepShape);
        IntegrateIntersections(ref deepClip);

        //Use these to jump from list to list
        Dictionary <Vector2, int> shapeIntersectionToClipIndex = new Dictionary <Vector2, int>();
        Dictionary <Vector2, int> clipIntersectionToShapeIndex = new Dictionary <Vector2, int>();

        BuildIntersectionMap(ref shapeIntersectionToClipIndex, deepShape, ref clipIntersectionToShapeIndex, deepClip);

        //start from entering points
        List <int> iEntering = new List <int>();

        //Get entering intersections
        for (int i = 0; i < deepShape.Count; i++)
        {
            DeepPoint point = deepShape[i];
            if (point.overlap || (point.type == DeepPoint.PointType.Intersection && point.status == DeepPoint.PointStatus.In))
            {
                iEntering.Add(i);
            }
        }

        List <List <DeepPoint> > output       = new List <List <DeepPoint> >();
        List <DeepPoint>         currentShape = new List <DeepPoint>();

        bool allEnteringAreOverlap = true;

        foreach (int i in iEntering)
        {
            if (!deepShape[i].overlap)
            {
                allEnteringAreOverlap = false;
                break;
            }
        }

        bool hasNonOverlapIntersections = false;

        foreach (DeepPoint p in deepShape)
        {
            if (!p.overlap && p.type == DeepPoint.PointType.Intersection)
            {
                hasNonOverlapIntersections = true;
                break;
            }
        }

        //handle special cases
        if ((iEntering.Count == 0 || allEnteringAreOverlap) && !hasNonOverlapIntersections)
        {
            bool allInside = true;
            foreach (DeepPoint p in deepShape)
            {
                if (p.status != DeepPoint.PointStatus.In && !p.overlap)
                {
                    allInside = false;
                    break;
                }
            }

            if (allInside)
            {
                foreach (DeepPoint p in deepShape)
                {
                    currentShape.Add(p);
                }
            }
            else
            {
                //check that deepClip are all inside
                allInside = true;
                foreach (DeepPoint p in deepClip)
                {
                    if (p.status != DeepPoint.PointStatus.In && !p.overlap)
                    {
                        allInside = false;
                        break;
                    }
                }

                if (allInside)
                {
                    foreach (DeepPoint p in deepClip)
                    {
                        currentShape.Add(p);
                    }
                }
                else
                {
                    return;
                }
            }

            output.Add(currentShape);
            return;
        }

        //TODO: add method to ignore entering points that were included in an output shape already

        //go through all of our entering points
        for (int mainCount = 0; mainCount < iEntering.Count; mainCount++)
        {
            int goToIndex = iEntering[mainCount];

            bool complete = false;

            while (!complete)
            {
                //loop through all shape points starting at goToIndex
                for (int iCount = goToIndex; iCount < deepShape.Count + goToIndex; iCount++)
                {
                    int       i  = iCount % deepShape.Count;
                    DeepPoint p1 = deepShape[i];
                    DeepPoint p2 = NextAfter(deepShape, i);

                    if (p1.overlap)
                    {
                        DeepPoint prev = PrevBefore(deepShape, i);
                        if (prev.overlap || prev.status == DeepPoint.PointStatus.Out)
                        {
                            p1.tempStatus = DeepPoint.PointStatus.In;
                        }
                        else
                        {
                            p1.tempStatus = DeepPoint.PointStatus.Out;
                        }
                    }
                    else
                    {
                        p1.tempStatus = p1.status;
                    }

                    if (p2.overlap)
                    {
                        if (p1.overlap || p1.status == DeepPoint.PointStatus.Out)
                        {
                            p2.tempStatus = DeepPoint.PointStatus.In;
                        }
                        else
                        {
                            p2.tempStatus = DeepPoint.PointStatus.Out;
                        }
                    }
                    else
                    {
                        p2.tempStatus = p2.status;
                    }

                    if (p1.type == DeepPoint.PointType.Normal)
                    {
                        if (p1.tempStatus == DeepPoint.PointStatus.In)
                        {
                            //break when we get back to start
                            if (currentShape.Count > 0 && currentShape[0].p == p1.p)
                            {
                                complete = true;
                                break;
                            }

                            currentShape.Add(p1);

                            //point2 must be heading outwards
                            if (p2.type == DeepPoint.PointType.Intersection)
                            {
                                //go to clipPoints loop and start from intersection
                                //goToIndex = shapeIntersectionToClipIndex[p2.p] + 1;
                                //break;
                            }
                        }
                        //we don't care about point2 here
                        //if point1 is an outside normal point,
                        //	then point2 must either be an outside normal point OR an intersection going inwards.
                        //		The former doesn't not need to be handled, the latter will be handled upon looping
                    }
                    else //p1 is an intersection
                    {
                        //break when we get back to start
                        if (currentShape.Count > 0 && currentShape[0].p == p1.p)
                        {
                            complete = true;
                            break;
                        }

                        //we must add point 1 since it's on the border
                        currentShape.Add(p1);

                        //exiting
                        if (p1.tempStatus == DeepPoint.PointStatus.Out)
                        {
                            //go to clipPoints loop and start from after intersection;
                            goToIndex = (shapeIntersectionToClipIndex[p1.p] + 1) % deepClip.Count;
                            break;
                        }
                    }
                } //end deepShape for

                //break while loop if complete
                if (complete)
                {
                    break;
                }

                //loop through all clip points starting at goToIndex
                //we should only get here from a go to from shapePoints
                for (int iCount = goToIndex; iCount < deepClip.Count + goToIndex; iCount++)
                {
                    int       i  = iCount % deepClip.Count;
                    DeepPoint p1 = deepClip[i];
                    DeepPoint p2 = NextAfter(deepClip, i);

                    if (p1.overlap)
                    {
                        DeepPoint prev = PrevBefore(deepClip, i);
                        if (prev.overlap || prev.status == DeepPoint.PointStatus.Out)
                        {
                            p1.tempStatus = DeepPoint.PointStatus.In;
                        }
                        else
                        {
                            p1.tempStatus = DeepPoint.PointStatus.Out;
                        }
                    }
                    else
                    {
                        p1.tempStatus = p1.status;
                    }

                    if (p2.overlap)
                    {
                        if (p1.overlap || p1.status == DeepPoint.PointStatus.Out)
                        {
                            p2.tempStatus = DeepPoint.PointStatus.In;
                        }
                        else
                        {
                            p2.tempStatus = DeepPoint.PointStatus.Out;
                        }
                    }
                    else
                    {
                        p2.tempStatus = p2.status;
                    }

                    if (p1.type == DeepPoint.PointType.Intersection)
                    {
                        //break when we get back to start
                        if (currentShape.Count > 0 && currentShape[0].p == p1.p)
                        {
                            complete = true;
                            break;
                        }

                        //we must add point 1 since it's on the border
                        currentShape.Add(p1);

                        //if it was going inwards
                        if (p1.tempStatus == DeepPoint.PointStatus.In)
                        {
                            //go to shapePoints loop and start from after point1
                            goToIndex = (clipIntersectionToShapeIndex[p1.p] + 1) % deepShape.Count;
                            break;
                        }
                    }
                    else //p1 is normal
                    {
                        if (p1.tempStatus == DeepPoint.PointStatus.In)
                        {
                            //break when we get back to start
                            if (currentShape.Count > 0 && currentShape[0].p == p1.p)
                            {
                                complete = true;
                                break;
                            }

                            //we must add point 1 since it's on the border
                            currentShape.Add(p1);
                        }
                    }
                } //end deepClip for
            }     //end while loop

            output.Add(currentShape);
            currentShape = new List <DeepPoint>();
        }//end main for loop

        //remove duplicate points
        for (int iOutput = 0; iOutput < output.Count; iOutput++)
        {
            List <DeepPoint> points = output[iOutput];
            for (int i = 0; i < points.Count; i++)
            {
                //remove duplicates
                if (points[i].p == NextAfter(points, i).p)
                {
                    //remove current
                    points.RemoveAt(i);
                    i--;
                }
            }

            if (points.Count < 3)
            {
                output.Remove(points);
                iOutput--;
            }
        }

        foreach (List <DeepPoint> o in output)
        {
            List <Vector2> vertices = new List <Vector2>();

            foreach (DeepPoint p in o)
            {
                vertices.Add(p.p);
            }

            result.Add(vertices);
        }
    } //end doClip