Exemple #1
0
        /*
         * divide and conquer delaunay
         */
        private void del_divide_and_conquer(DelaunaySegment del, int start, int end)
        {
            DelaunaySegment left = new DelaunaySegment();
            DelaunaySegment right = new DelaunaySegment();
            int             i, n;

            n = (end - start + 1);

            if (n > 3)
            {
                i            = (n / 2) + (n & 1);
                left.points  = del.points;
                right.points = del.points;
                del_divide_and_conquer(left, start, start + i - 1);
                del_divide_and_conquer(right, start + i, end);
                del_link(del, left, right);
            }
            else if (n == 3)
            {
                del_init_tri(del, start);
            }
            else if (n == 2)
            {
                del_init_seg(del, start);
            }
        }
Exemple #2
0
        /*
         * find the lower tangent between the two delaunay, going from left to right (returns the left half edge)
         */
        private Halfedge del_get_lower_tangent(DelaunaySegment left, DelaunaySegment right)
        {
            Point2d  pl;
            Point2d  pr;
            Halfedge right_d;
            Halfedge left_d;
            Halfedge new_ld, new_rd;
            int      sl, sr;

            left_d  = left.rightmost_he;
            right_d = right.leftmost_he;

            do
            {
                pl = left_d.prev.pair.vertex;
                pr = right_d.pair.vertex;

                if ((sl = classify_point_seg(left_d.vertex, right_d.vertex, pl)) == ON_RIGHT)
                {
                    left_d = left_d.prev.pair;
                }

                if ((sr = classify_point_seg(left_d.vertex, right_d.vertex, pr)) == ON_RIGHT)
                {
                    right_d = right_d.pair.next;
                }
            } while (sl == ON_RIGHT || sr == ON_RIGHT);

            /* create the 2 halfedges */
            new_ld = new Halfedge();
            new_rd = new Halfedge();

            /* setup new_gd and new_dd */
            new_ld.vertex    = left_d.vertex;
            new_ld.pair      = new_rd;
            new_ld.prev      = left_d.prev;
            left_d.prev.next = new_ld;
            new_ld.next      = left_d;
            left_d.prev      = new_ld;

            new_rd.vertex     = right_d.vertex;
            new_rd.pair       = new_ld;
            new_rd.prev       = right_d.prev;
            right_d.prev.next = new_rd;
            new_rd.next       = right_d;
            right_d.prev      = new_rd;

            return(new_ld);
        }
Exemple #3
0
        /*
         * link the 2 delaunay together
         */
        private void del_link(DelaunaySegment result, DelaunaySegment left, DelaunaySegment right)
        {
            Point2d  u;
            Point2d  v, ml, mr;
            Halfedge basis;

            Debug.Assert(left.points == right.points);

            /* save the most right point and the most left point */
            ml = left.leftmost_he.vertex;
            mr = right.rightmost_he.vertex;

            basis = del_get_lower_tangent(left, right);

            u = basis.next.pair.vertex;
            v = basis.pair.prev.pair.vertex;

            while (del_classify_point(basis, u) == ON_LEFT ||
                   del_classify_point(basis, v) == ON_LEFT)
            {
                basis = del_valid_link(basis);
                u     = basis.next.pair.vertex;
                v     = basis.pair.prev.pair.vertex;
            }

            right.rightmost_he = mr.he;
            left.leftmost_he   = ml.he;

            /* TODO: this part is not needed, and can be optimized */
            while (del_classify_point(right.rightmost_he, right.rightmost_he.prev.pair.vertex) == ON_RIGHT)
            {
                right.rightmost_he = right.rightmost_he.prev;
            }

            while (del_classify_point(left.leftmost_he, left.leftmost_he.prev.pair.vertex) == ON_RIGHT)
            {
                left.leftmost_he = left.leftmost_he.prev;
            }

            result.leftmost_he  = left.leftmost_he;
            result.rightmost_he = right.rightmost_he;
            result.points       = left.points;
            result.start_point  = left.start_point;
            result.end_point    = right.end_point;
        }
Exemple #4
0
        /*
         * build the faces for all the halfedge
         */
        private void del_build_faces(DelaunaySegment del)
        {
            int      i;
            Halfedge curr;

            del.num_faces = 0;
            del.faces     = null;

            /* build external face first */
            build_halfedge_face(del, del.rightmost_he.pair);

            for (i = del.start_point; i <= del.end_point; i++)
            {
                curr = del.points[i].he;

                do
                {
                    build_halfedge_face(del, curr);
                    curr = curr.next;
                } while (curr != del.points[i].he);
            }
        }
Exemple #5
0
        private void build_halfedge_face(DelaunaySegment del, Halfedge d)
        {
            Halfedge curr;

            /* test if the halfedge has already a pointing face */
            if (d.face != null)
            {
                return;
            }

            /* TODO: optimize this */
            /* copy the points */
            Face[] new_faces = new Face[del.num_faces + 1];
            Debug.Assert(null != new_faces && (del.num_faces == 0 || null != del.faces));
            for (int i = 0; i < del.num_faces; i++)
            {
                new_faces[i] = del.faces[i];
            }

            new_faces[del.num_faces] = new Face();
            del.faces = new_faces;

            Face f = del.faces[del.num_faces];

            curr        = d;
            f.he        = d;
            f.num_verts = 0;
            do
            {
                curr.face = f;
                (f.num_verts)++;
                curr = curr.pair.prev;
            } while (curr != d);

            (del.num_faces)++;
        }
Exemple #6
0
        /*
         * initialize delaunay segment
         */
        private int del_init_seg(DelaunaySegment del, int start)
        {
            Halfedge d0;
            Halfedge d1;
            Point2d  pt0;
            Point2d  pt1;

            /* init delaunay */
            del.start_point = start;
            del.end_point   = start + 1;

            /* setup pt0 and pt1 */
            pt0 = del.points[start];
            pt1 = del.points[start + 1];

            /* allocate the halfedges and setup them */
            d0 = new Halfedge();
            d1 = new Halfedge();

            d0.vertex = pt0;
            d1.vertex = pt1;

            d0.next = d0.prev = d0;
            d1.next = d1.prev = d1;

            d0.pair = d1;
            d1.pair = d0;

            pt0.he = d0;
            pt1.he = d1;

            del.rightmost_he = d1;
            del.leftmost_he  = d0;

            return(0);
        }
Exemple #7
0
        /*
         */
        private Delaunay2d delaunay2d_from(Del_Point2d[] points, int num_points)
        {
            Delaunay2d      res = null;
            DelaunaySegment del = new DelaunaySegment();
            int             i, j, fbuff_size = 0;

            int[] faces = null;

            /* allocate the points */
            del.points = new Point2d[num_points];
            Debug.Assert(null != del.points);

            /* copy the points */
            for (i = 0; i < num_points; i++)
            {
                del.points[i]     = new Point2d();
                del.points[i].idx = i;
                del.points[i].x   = points[i].x;
                del.points[i].y   = points[i].y;
            }

            Array.Sort(del.points);
            if (num_points >= 3)
            {
                del_divide_and_conquer(del, 0, num_points - 1);

                del_build_faces(del);

                fbuff_size = 0;
                for (i = 0; i < del.num_faces; i++)
                {
                    fbuff_size += del.faces[i].num_verts + 1;
                }

                faces = new int[fbuff_size];
                Debug.Assert(null != faces);

                j = 0;
                for (i = 0; i < del.num_faces; i++)
                {
                    Halfedge curr;

                    faces[j] = del.faces[i].num_verts;
                    j++;

                    curr = del.faces[i].he;
                    do
                    {
                        faces[j] = curr.vertex.idx;
                        j++;
                        curr = curr.pair.prev;
                    } while (curr != del.faces[i].he);
                }
                del.faces  = null;
                del.points = null;
            }

            res = new Delaunay2d();
            Debug.Assert(null != res);

            res.num_points = num_points;
            res.points     = new Del_Point2d[num_points];
            Debug.Assert(null != res.points);

            for (int loop = 0; loop < num_points; loop++)
            {
                res.points[loop] = (Del_Point2d)points[loop].Clone();
            }

            res.num_faces = del.num_faces;
            res.faces     = faces;

            return(res);
        }
Exemple #8
0
        /*
         * initialize delaunay triangle
         */
        private int del_init_tri(DelaunaySegment del, int start)
        {
            Halfedge d0;
            Halfedge d1;
            Halfedge d2, d3, d4, d5;
            Point2d  pt0;
            Point2d  pt1, pt2;

            /* initiate delaunay */
            del.start_point = start;
            del.end_point   = start + 2;

            /* setup the points */
            pt0 = del.points[start];
            pt1 = del.points[start + 1];
            pt2 = del.points[start + 2];

            /* allocate the 6 halfedges */
            d0 = new Halfedge();
            d1 = new Halfedge();
            d2 = new Halfedge();
            d3 = new Halfedge();
            d4 = new Halfedge();
            d5 = new Halfedge();

            if (classify_point_seg(pt0, pt2, pt1) == ON_LEFT)     /* first case */
            {
                /* set halfedges points */
                d0.vertex = pt0;
                d1.vertex = pt2;
                d2.vertex = pt1;

                d3.vertex = pt2;
                d4.vertex = pt1;
                d5.vertex = pt0;

                /* set points halfedges */
                pt0.he = d0;
                pt1.he = d2;
                pt2.he = d1;

                /* next and next -1 setup */
                d0.next = d5;
                d0.prev = d5;

                d1.next = d3;
                d1.prev = d3;

                d2.next = d4;
                d2.prev = d4;

                d3.next = d1;
                d3.prev = d1;

                d4.next = d2;
                d4.prev = d2;

                d5.next = d0;
                d5.prev = d0;

                /* set halfedges pair */
                d0.pair = d3;
                d3.pair = d0;

                d1.pair = d4;
                d4.pair = d1;

                d2.pair = d5;
                d5.pair = d2;

                del.rightmost_he = d1;
                del.leftmost_he  = d0;
            }
            else       /* 2nd case */
            {
                /* set halfedges points */
                d0.vertex = pt0;
                d1.vertex = pt1;
                d2.vertex = pt2;

                d3.vertex = pt1;
                d4.vertex = pt2;
                d5.vertex = pt0;

                /* set points halfedges */
                pt0.he = d0;
                pt1.he = d1;
                pt2.he = d2;

                /* next and next -1 setup */
                d0.next = d5;
                d0.prev = d5;

                d1.next = d3;
                d1.prev = d3;

                d2.next = d4;
                d2.prev = d4;

                d3.next = d1;
                d3.prev = d1;

                d4.next = d2;
                d4.prev = d2;

                d5.next = d0;
                d5.prev = d0;

                /* set halfedges pair */
                d0.pair = d3;
                d3.pair = d0;

                d1.pair = d4;
                d4.pair = d1;

                d2.pair = d5;
                d5.pair = d2;

                del.rightmost_he = d2;
                del.leftmost_he  = d0;
            }
            return(0);
        }
Exemple #9
0
        //void Triangulator::_recursiveTriangulatePolygon(const DelaunaySegment& cuttingSeg, std::vector<int> inputPoints, DelaunayTriangleBuffer& tbuffer, const PointList&  pointList) const
        void _recursiveTriangulatePolygon(DelaunaySegment cuttingSeg, std_vector <int> inputPoints, DelaunayTriangleBuffer tbuffer, PointList pointList)
        {
            if (inputPoints.size() == 0)
            {
                return;
            }
            if (inputPoints.size() == 1)
            {
                Triangle t2 = new Triangle(pointList);
                //t.setVertices(cuttingSeg.i1, cuttingSeg.i2, inputPoints.begin());
                t2.setVertices(cuttingSeg.i1, cuttingSeg.i2, inputPoints.front());
                t2.makeDirectIfNeeded();
                tbuffer.push_back(t2);
                return;
            }
            // Find a point which, when associated with seg.i1 and seg.i2, builds a Delaunay triangle
            //std::vector<int>::iterator currentPoint = inputPoints.begin();
            int  currentPoint_pos = inputPoints.begin();
            int  currentPoint     = inputPoints.front();
            bool found            = false;

            while (!found)
            {
                bool isDelaunay = true;
                //Circle c=new Circle(pointList[*currentPoint], pointList[cuttingSeg.i1], pointList[cuttingSeg.i2]);
                Circle c = new Circle(pointList[currentPoint], pointList[cuttingSeg.i1], pointList[cuttingSeg.i2]);
                //for (std::vector<int>::iterator it = inputPoints.begin(); it!=inputPoints.end(); ++it)
                int idx = -1;
                foreach (var it in inputPoints)
                {
                    idx++;
                    //if (c.isPointInside(pointList[*it]) && (*it != *currentPoint))
                    if (c.isPointInside(pointList[it]) && (it != currentPoint))
                    {
                        isDelaunay       = false;
                        currentPoint     = it;
                        currentPoint_pos = idx;
                        break;
                    }
                }
                if (isDelaunay)
                {
                    found = true;
                }
            }

            // Insert current triangle
            Triangle t = new Triangle(pointList);

            //t.setVertices(*currentPoint, cuttingSeg.i1, cuttingSeg.i2);
            t.setVertices(currentPoint, cuttingSeg.i1, cuttingSeg.i2);
            t.makeDirectIfNeeded();
            tbuffer.push_back(t);

            // Recurse
            //DelaunaySegment newCut1=new DelaunaySegment(cuttingSeg.i1, *currentPoint);
            //DelaunaySegment newCut2=new DelaunaySegment(cuttingSeg.i2, *currentPoint);
            DelaunaySegment newCut1 = new DelaunaySegment(cuttingSeg.i1, currentPoint);
            DelaunaySegment newCut2 = new DelaunaySegment(cuttingSeg.i2, currentPoint);
            //std_vector<int> set1=new std_vector<int>(inputPoints.begin(), currentPoint);
            //std_vector<int> set2=new std_vector<int>(currentPoint+1, inputPoints.end());
            std_vector <int> set1 = new std_vector <int>();

            set1.assign(inputPoints.ToArray(), inputPoints.begin(), currentPoint_pos);
            std_vector <int> set2 = new std_vector <int>();

            set2.assign(inputPoints.ToArray(), currentPoint_pos + 1, inputPoints.end());

            if (!set1.empty())
            {
                _recursiveTriangulatePolygon(newCut1, set1, tbuffer, pointList);
            }
            if (!set2.empty())
            {
                _recursiveTriangulatePolygon(newCut2, set2, tbuffer, pointList);
            }
        }
Exemple #10
0
        void _addConstraints(ref DelaunayTriangleBuffer tbuffer, PointList pl, std_vector <int> segmentListIndices)
        {
            std_vector <DelaunaySegment> segList = new std_vector <DelaunaySegment>();

            //Utils::log("a co");
            //for (DelaunayTriangleBuffer::iterator it = tbuffer.begin(); it!=tbuffer.end();it++)
            //	Utils::log(it->debugDescription());

            // First, list all the segments that are not already in one of the delaunay triangles
            //for (std::vector<int>::const_iterator it2 = segmentListIndices.begin(); it2 != segmentListIndices.end(); it2++)
            for (int i = 0; i < segmentListIndices.Count; i++)
            {
                //int i1 = *it2;
                int i1 = segmentListIndices[i];
                //it2++;
                i++;
                //int i2 = *it2;
                int i2 = segmentListIndices[i];

                bool isAlreadyIn = false;
                //for (DelaunayTriangleBuffer::iterator it = tbuffer.begin(); it!=tbuffer.end(); ++it)
                foreach (var it in tbuffer)
                {
                    if (it.containsSegment(i1, i2))
                    {
                        isAlreadyIn = true;
                        break;
                    }
                }
                // only do something for segments not already in DT
                if (!isAlreadyIn)
                {
                    segList.push_back(new DelaunaySegment(i1, i2));
                }
            }

            // Re-Triangulate according to the new segments
            //for (std::vector<DelaunaySegment>::iterator itSeg=segList.begin(); itSeg!=segList.end(); itSeg++)
            for (int ii = segList.Count - 1; ii >= 0; ii--)
            {
                DelaunaySegment itSeg = segList[ii];
                //Utils::log("itseg " + StringConverter::toString(itSeg->i1) + "," + StringConverter::toString(itSeg->i2) + " " + StringConverter::toString(pl[itSeg->i1]) + "," + StringConverter::toString(pl[itSeg->i2]));
                // Remove all triangles intersecting the segment and keep a list of outside edges
                std_set <DelaunaySegment> segments = new std_set <DelaunaySegment>();
                Segment2D seg1 = new Segment2D(pl[itSeg.i1], pl[itSeg.i2]);
                //for (DelaunayTriangleBuffer::iterator itTri = tbuffer.begin(); itTri!=tbuffer.end(); )
                for (int jj = tbuffer.Count - 1; jj >= 0; jj--)
                {
                    Triangle itTri = tbuffer.getElement(jj).Value;
                    bool     isTriangleIntersected = false;
                    bool     isDegenerate          = false;
                    int      degenIndex;
                    for (int i = 0; i < 3; i++)
                    {
                        //Early out if 2 points are in fact the same
                        if (itTri.i[i] == itSeg.i1 || itTri.i[i] == itSeg.i2 || itTri.i[(i + 1) % 3] == itSeg.i1 || itTri.i[(i + 1) % 3] == itSeg.i2)
                        {
                            if (itTri.isDegenerate())
                            {
                                if (itTri.i[i] == itSeg.i1 || itTri.i[(i + 1) % 3] == itSeg.i1)
                                {
                                    degenIndex = itSeg.i1;
                                }
                                else if (itTri.i[i] == itSeg.i2 || itTri.i[(i + 1) % 3] == itSeg.i2)
                                {
                                    degenIndex = itSeg.i2;
                                }
                                isTriangleIntersected = true;
                                isDegenerate          = true;
                            }
                            else
                            {
                                continue;
                            }
                        }
                        Segment2D seg2 = new Segment2D(itTri.p(i), itTri.p((i + 1) % 3));
                        if (seg1.intersects(seg2))
                        {
                            isTriangleIntersected = true;
                            break;
                        }
                    }
                    if (isTriangleIntersected)
                    {
                        //if (isDegenerate)
                        //Utils::log("degen " + itTri->debugDescription());
                        for (int k = 0; k < 3; k++)
                        {
                            DelaunaySegment d1 = new DelaunaySegment(itTri.i[k], itTri.i[(k + 1) % 3]);
                            if (segments.find(d1) != segments.end())
                            {
                                segments.erase(d1);
                            }
                            else if (segments.find(d1.inverse()) != segments.end())
                            {
                                segments.erase(d1.inverse());
                            }
                            else
                            {
                                segments.insert(d1);
                            }
                        }
                        //itTri=tbuffer.erase(itTri);
                        tbuffer.erase(jj);
                    }
                    //else
                    //	itTri++;
                }

                // Divide the list of points (coming from remaining segments) in 2 groups : "above" and "below"
                std_vector <int> pointsAbove = new std_vector <int>();
                std_vector <int> pointsBelow = new std_vector <int>();
                int  pt      = itSeg.i1;
                bool isAbove = true;
                while (segments.size() > 0)
                {
                    //find next point
                    //for (std::set<DelaunaySegment>::iterator it = segments.begin(); it!=segments.end(); ++it)
                    DelaunaySegment[] segments_all = segments.get_allocator();
                    for (int i = 0; i < segments_all.Length; ++i)
                    {
                        DelaunaySegment it = segments_all[i];//segments.find(i,true);
                        if (it.i1 == pt || it.i2 == pt)
                        {
                            //Utils::log("next " + StringConverter::toString(pt));

                            if (it.i1 == pt)
                            {
                                pt = it.i2;
                            }
                            else
                            {
                                pt = it.i1;
                            }
                            segments.erase(it);
                            if (pt == itSeg.i2)
                            {
                                isAbove = false;
                            }
                            else if (pt != itSeg.i1)
                            {
                                if (isAbove)
                                {
                                    pointsAbove.push_back(pt);
                                }
                                else
                                {
                                    pointsBelow.push_back(pt);
                                }
                            }
                            break;
                        }
                    }
                }

                // Recursively triangulate both polygons
                _recursiveTriangulatePolygon(itSeg, pointsAbove, tbuffer, pl);
                _recursiveTriangulatePolygon(itSeg.inverse(), pointsBelow, tbuffer, pl);
            }
            // Clean up segments outside of multishape
            if (mRemoveOutside)
            {
                if (mMultiShapeToTriangulate != null && mMultiShapeToTriangulate.isClosed())
                {
                    //for (DelaunayTriangleBuffer::iterator it = tbuffer.begin(); it!=tbuffer.end();)
                    for (int i = tbuffer.Count - 1; i >= 0; i--)
                    {
                        Triangle it            = tbuffer.getElement(i).Value;
                        bool     isTriangleOut = !mMultiShapeToTriangulate.isPointInside(it.getMidPoint());

                        if (isTriangleOut)
                        {
                            //it = tbuffer.erase(it);
                            tbuffer.erase(i);
                        }
                        //else
                        //	++it;
                    }
                }
                else if (mShapeToTriangulate != null && mShapeToTriangulate.isClosed())
                {
                    //for (DelaunayTriangleBuffer::iterator it = tbuffer.begin(); it!=tbuffer.end();)
                    for (int i = tbuffer.Count - 1; i >= 0; i--)
                    {
                        Triangle it            = tbuffer.getElement(i).Value;
                        bool     isTriangleOut = !mShapeToTriangulate.isPointInside(it.getMidPoint());

                        if (isTriangleOut)
                        {
                            //it = tbuffer.erase(it);
                            tbuffer.erase(i);
                        }
                        //else
                        //	++it;
                    }
                }
            }
        }
Exemple #11
0
        //
        //ORIGINAL LINE: void delaunay(List<Ogre::Vector2>& pointList, LinkedList<Triangle>& tbuffer) const
        void delaunay(PointList pointList, ref DelaunayTriangleBuffer tbuffer)
        {
            // Compute super triangle or insert manual super triangle
            if (mManualSuperTriangle != null)
            {
                float maxTriangleSize = 0.0f;
                //for (PointList::iterator it = pointList.begin(); it!=pointList.end(); ++it)
                foreach (Vector2 it in pointList)
                {
                    maxTriangleSize = max(maxTriangleSize, Math.Abs(it.x));
                    maxTriangleSize = max(maxTriangleSize, Math.Abs(it.y));
                }
                pointList.push_back(new Vector2(-3f * maxTriangleSize, -3f * maxTriangleSize));
                pointList.push_back(new Vector2(3f * maxTriangleSize, -3f * maxTriangleSize));
                pointList.push_back(new Vector2(0.0f, 3 * maxTriangleSize));

                int      maxTriangleIndex = pointList.size() - 3;
                Triangle superTriangle    = new Triangle(pointList);
                superTriangle.i[0] = maxTriangleIndex;
                superTriangle.i[1] = maxTriangleIndex + 1;
                superTriangle.i[2] = maxTriangleIndex + 2;
                tbuffer.push_back(superTriangle);
            }

            // Point insertion loop
            for (int i = 0; i < pointList.size() - 3; i++)
            {
                //Utils::log("insert point " + StringConverter::toString(i));
                //std::list<std::list<Triangle>::iterator> borderlineTriangles;
                std_list <Triangle> borderlineTriangles = new std_list <Triangle>();
                // Insert 1 point, find all triangles for which the point is in circumcircle
                Vector2 p = pointList[i];
                //std::set<DelaunaySegment> segments;
                std_set <DelaunaySegment> segments = new std_set <DelaunaySegment>();
                IEnumerator <Triangle>    et       = tbuffer.GetEnumerator();
                //for (DelaunayTriangleBuffer::iterator it = tbuffer.begin(); it!=tbuffer.end();)
                List <Triangle> need_erase = new List <Triangle>();
                while (et.MoveNext())
                {
                    Triangle            it       = et.Current;
                    Triangle.InsideType isInside = it.isPointInsideCircumcircle(p);
                    if (isInside == Triangle.InsideType.IT_INSIDE)
                    {
                        if (!it.isDegenerate())
                        {
                            //Utils::log("tri insie" + it->debugDescription());
                            for (int k = 0; k < 3; k++)
                            {
                                DelaunaySegment d1 = new DelaunaySegment(it.i[k], it.i[(k + 1) % 3]);
                                if (segments.find(d1) != segments.end())
                                {
                                    segments.erase(d1);
                                }
                                else if (segments.find(d1.inverse()) != segments.end())
                                {
                                    segments.erase(d1.inverse());
                                }
                                else
                                {
                                    segments.insert(d1);
                                }
                            }
                        }
                        //it=tbuffer.erase(it);
                        need_erase.Add(it);
                    }
                    else if (isInside == Triangle.InsideType.IT_BORDERLINEOUTSIDE)
                    {
                        //Utils::log("tri borer " + it->debugDescription());
                        borderlineTriangles.push_back(it);
                        //++it;
                    }
                    else
                    {
                        //++it;
                    }
                }
                //do delete
                foreach (var v in need_erase)
                {
                    tbuffer.Remove(v);
                }

                // Robustification of the standard algorithm : if one triangle's circumcircle was borderline against the new point,
                // test whether that triangle is intersected by new segments or not (normal situation : it should not)
                // If intersected, the triangle is considered having the new point in its circumc
                std_set <DelaunaySegment> copySegment = segments;
                IEnumerator <Triangle>    be          = borderlineTriangles.GetEnumerator();
                //for (std::list<std::list<Triangle>::iterator>::iterator itpTri = borderlineTriangles.begin(); itpTri!=borderlineTriangles.end(); itpTri++ )
                while (be.MoveNext())
                {
                    Triangle itpTri = be.Current;
                    //DelaunayTriangleBuffer::iterator itTri = *itpTri;
                    Triangle itTri      = itpTri;
                    bool     triRemoved = false;
                    //for (std::set<DelaunaySegment>::iterator it = copySegment.begin(); it!=copySegment.end() && !triRemoved; ++it)
                    IEnumerator <DelaunaySegment> cse = copySegment.GetEnumerator();
                    while (cse.MoveNext() && !triRemoved)
                    {
                        DelaunaySegment it = cse.Current;
                        bool            isTriangleIntersected = false;
                        for (int k = 0; k < 2; k++)
                        {
                            int i1 = (k == 0) ? it.i1 : it.i2;
                            int i2 = i;
                            for (int l = 0; l < 3; l++)
                            {
                                //Early out if 2 points are in fact the same
                                if (itTri.i[l] == i1 || itTri.i[l] == i2 || itTri.i[(l + 1) % 3] == i1 || itTri.i[(l + 1) % 3] == i2)
                                {
                                    continue;
                                }
                                Segment2D seg2 = new Segment2D(itTri.p(l), itTri.p((l + 1) % 3));
                                Segment2D seg1 = new Segment2D(pointList[i1], pointList[i2]);
                                if (seg1.intersects(seg2))
                                {
                                    isTriangleIntersected = true;
                                    break;
                                }
                            }
                        }
                        if (isTriangleIntersected)
                        {
                            if (!itTri.isDegenerate())
                            {
                                //Utils::log("tri inside" + itTri->debugDescription());
                                for (int m = 0; m < 3; m++)
                                {
                                    DelaunaySegment d1 = new DelaunaySegment(itTri.i[m], itTri.i[(m + 1) % 3]);
                                    if (segments.find(d1) != segments.end())
                                    {
                                        segments.erase(d1);
                                    }
                                    else if (segments.find(d1.inverse()) != segments.end())
                                    {
                                        segments.erase(d1.inverse());
                                    }
                                    else
                                    {
                                        segments.insert(d1);
                                    }
                                }
                            }
                            //tbuffer.erase(itTri);
                            need_erase.Clear();
                            need_erase.Add(itTri);
                            triRemoved = true;
                        }
                    }
                }
                //do delete
                foreach (var v in need_erase)
                {
                    tbuffer.Remove(v);
                }
                // Find all the non-interior edges
                IEnumerator <DelaunaySegment> seg_ie = segments.GetEnumerator();
                //for (std::set<DelaunaySegment>::iterator it = segments.begin(); it!=segments.end(); ++it)
                while (seg_ie.MoveNext())
                {
                    DelaunaySegment it = seg_ie.Current;
                    //Triangle dt(&pointList);
                    Triangle dt = new Triangle(pointList);
                    dt.setVertices(it.i1, it.i2, i);
                    dt.makeDirectIfNeeded();
                    //Utils::log("Add tri " + dt.debugDescription());
                    tbuffer.push_back(dt);
                }
            }

            // NB : Don't remove super triangle here, because all outer triangles are already removed in the addconstraints method.
            //      Uncomment that code if delaunay triangulation ever has to be unconstrained...

            /*TouchSuperTriangle touchSuperTriangle(maxTriangleIndex, maxTriangleIndex+1,maxTriangleIndex+2);
             * tbuffer.remove_if(touchSuperTriangle);
             * pointList.pop_back();
             * pointList.pop_back();
             * pointList.pop_back();*/
        }