Example #1
0
        /// <summary>
        /// Updates the grid index to reflect changes to the triangulation. Note that added
        /// triangles outside the indexed region will force to recompute the whole index
        /// with the enlarged region
        /// </summary>
        /// <param name="updatedTriangles">Changed triangles of the triangulation. This may be added triangles,
        ///  removed triangles or both. All that matter is that they cover the
        ///  changed area.
        /// </param>
        public void updateIndex(IEnumerator <Triangle_dt> updatedTriangles)
        {
            // Gather the bounding box of the updated area
            BoundingBox updatedRegion = new BoundingBox();

            while (((updatedTriangles.Current != null)))
            {
                updatedRegion = updatedRegion.UnionWith(updatedTriangles.Current.BoundingBox);
                updatedTriangles.MoveNext();
            }
            if ((updatedRegion.isNull))
            {
                return;
            }
            // No update...
            // Bad news - the updated region lies outside the indexed region.
            // The whole index must be recalculated
            if ((!indexRegion.contains(updatedRegion)))
            {
                init(indexDelaunay, Convert.ToInt32(indexRegion.Width / x_size), Convert.ToInt32(indexRegion.Height / y_size), indexRegion.UnionWith(updatedRegion));
            }
            else
            {
                // Find the cell region to be updated
                Point_dt minInvalidCell = getCellOf(updatedRegion.MinPoint);
                Point_dt maxInvalidCell = getCellOf(updatedRegion.MaxPoint);
                // And update it with fresh triangles
                Triangle_dt adjacentValidTriangle = findValidTriangle(minInvalidCell);
                updateCellValues((int)minInvalidCell.x, (int)minInvalidCell.y, (int)maxInvalidCell.x, (int)maxInvalidCell.y, adjacentValidTriangle);
            }
        }
 /// <summary>
 /// assumes v is NOT an halfplane! returns the next triangle for find.
 /// </summary>
 private static Triangle_dt findnext1(Point_dt p, Triangle_dt v)
 {
     if ((p.pointLineTest(v.a, v.b) == Point_dt.RIGHT & (!(v.abnext.isHalfplane))))
     {
         return(v.abnext);
     }
     if ((p.pointLineTest(v.b, v.c) == Point_dt.RIGHT & (!(v.bcnext.isHalfplane))))
     {
         return(v.bcnext);
     }
     if ((p.pointLineTest(v.c, v.a) == Point_dt.RIGHT & (!(v.canext.isHalfplane))))
     {
         return(v.canext);
     }
     if ((p.pointLineTest(v.a, v.b) == Point_dt.RIGHT))
     {
         return(v.abnext);
     }
     if ((p.pointLineTest(v.b, v.c) == Point_dt.RIGHT))
     {
         return(v.bcnext);
     }
     if ((p.pointLineTest(v.c, v.a) == Point_dt.RIGHT))
     {
         return(v.canext);
     }
     return(null);
 }
        private Triangle_dt extendOutside(Triangle_dt t, Point_dt p)
        {
            if ((p.pointLineTest(t.a, t.b) == Point_dt.ONSEGMENT))
            {
                Triangle_dt dg = new Triangle_dt(t.a, t.b, p);
                Triangle_dt hp = new Triangle_dt(p, t.b);
                t.b       = p;
                dg.abnext = t.abnext;
                dg.abnext.switchneighbors(t, dg);
                dg.bcnext        = hp;
                hp.abnext        = dg;
                dg.canext        = t;
                t.abnext         = dg;
                hp.bcnext        = t.bcnext;
                hp.bcnext.canext = hp;
                hp.canext        = t;
                t.bcnext         = hp;
                return(dg);
            }
            Triangle_dt ccT = extendcounterclock(t, p);
            Triangle_dt cT  = extendclock(t, p);

            ccT.bcnext        = cT;
            cT.canext         = ccT;
            startTriangleHull = cT;
            return(cT.abnext);
        }
        private void startTriangulation(Point_dt p1, Point_dt p2)
        {
            Point_dt ps = default(Point_dt);
            Point_dt pb = default(Point_dt);

            if ((p1.isLess(p2)))
            {
                ps = p1;
                pb = p2;
            }
            else
            {
                ps = p2;
                pb = p1;
            }
            firstT = new Triangle_dt(pb, ps);
            lastT  = firstT;
            Triangle_dt t = new Triangle_dt(ps, pb);

            firstT.abnext     = t;
            t.abnext          = firstT;
            firstT.bcnext     = t;
            t.canext          = firstT;
            firstT.canext     = t;
            t.bcnext          = firstT;
            firstP            = firstT.b;
            lastP             = lastT.a;
            startTriangleHull = firstT;
        }
Example #5
0
        /// <summary>
        /// Returns the neighbors that shares the given corner and is not the previous triangle.
        /// </summary>
        /// <param name="p">The given corner.</param>
        /// <param name="prevTriangle">The previous triangle.</param>
        /// <returns>The neighbors that shares the given corner and is not the previous triangle.</returns>
        public object nextNeighbor(Point_dt p, Triangle_dt prevTriangle)
        {
            Triangle_dt neighbor = null;

            if (_a.Equals(p))
            {
                neighbor = _canext;
            }
            else if (_b.Equals(p))
            {
                neighbor = _abnext;
            }
            else if (_c.Equals(p))
            {
                neighbor = _bcnext;
            }
            if (neighbor.Equals(prevTriangle) | neighbor.isHalfplane)
            {
                if (_a.Equals(p))
                {
                    neighbor = _abnext;
                }
                else if (_b.Equals(p))
                {
                    neighbor = _bcnext;
                }
                else if (_c.Equals(p))
                {
                    neighbor = _canext;
                }
            }
            return(neighbor);
        }
        private Triangle_dt extendInside(Triangle_dt t, Point_dt p)
        {
            Triangle_dt h1 = default(Triangle_dt);
            Triangle_dt h2 = default(Triangle_dt);

            h1 = treatDegeneracyInside(t, p);
            if ((h1 != null))
            {
                return(h1);
            }
            h1  = new Triangle_dt(t.c, t.a, p);
            h2  = new Triangle_dt(t.b, t.c, p);
            t.c = p;
            t.circumcircle();
            h1.abnext = t.canext;
            h1.bcnext = t;
            h1.canext = h2;
            h2.abnext = t.bcnext;
            h2.bcnext = h1;
            h2.canext = t;
            h1.abnext.switchneighbors(t, h1);
            h2.abnext.switchneighbors(t, h2);
            t.bcnext = h2;
            t.canext = h1;
            return(t);
        }
        public void insertPoint(Point_dt p)
        {
            if (_vertices.Contains(p))
            {
                return;
            }
            _modCount += 1;
            updateBoundingBox(p);
            _vertices.Add(p);
            Triangle_dt t = insertPointSimple(p);

            if (t == null)
            {
                return;
            }
            Triangle_dt tt = t;

            currT = t;
            // recall the last point for fast (last) update iterator
            do
            {
                Flip(tt, _modCount);
                tt = tt.canext;
            } while (tt.Equals(t) & !tt.isHalfplane);
            if ((gridIndex != null))
            {
                gridIndex.updateIndex(getLastUpdatedTriangles());
            }
        }
        private static Triangle_dt Find(Triangle_dt curr, Point_dt p)
        {
            if (p == null)
            {
                return(null);
            }
            Triangle_dt next_t = default(Triangle_dt);

            if ((curr.isHalfplane))
            {
                next_t = findnext2(p, curr);
                if ((next_t == null | next_t.isHalfplane))
                {
                    return(curr);
                }
                curr = next_t;
            }
            while (true)
            {
                next_t = findnext1(p, curr);
                if ((next_t == null))
                {
                    return(curr);
                }
                if ((next_t.isHalfplane))
                {
                    return(next_t);
                }
                curr = next_t;
            }
            return(null);
            // Never supposed to get here
        }
        /// <summary>
        /// finds the triangle the query point falls in, note if out-side of this
        /// triangulation a half plane triangle will be returned (see contains). the
        /// search starts from the the start triangle
        /// </summary>
        /// <param name="p">Query point</param>
        /// <param name="start">The triangle the search starts at.</param>
        /// <returns>The triangle that point <paramref name="p"/> is in.</returns>
        public Triangle_dt Find(Point_dt p, Triangle_dt start)
        {
            if (start == null)
            {
                start = startTriangle;
            }
            Triangle_dt T = Find(start, p);

            return(T);
        }
 private void allTriangles(Triangle_dt curr, List <Triangle_dt> front, int mc)
 {
     if (((curr != null)) && curr.mc == mc && (!(front.Contains(curr))))
     {
         front.Add(curr);
         allTriangles(curr.abnext, front, mc);
         allTriangles(curr.bcnext, front, mc);
         allTriangles(curr.canext, front, mc);
     }
 }
        public IEnumerator <Triangle_dt> getLastUpdatedTriangles()
        {
            List <Triangle_dt> tmp = new List <Triangle_dt>();

            if (this.TrianglesSize() > 1)
            {
                Triangle_dt t = currT;
                allTriangles(t, tmp, this._modCount);
            }
            return(tmp.GetEnumerator());
        }
Example #12
0
        public void init(Delaunay_Triangulation delaunay, int xCellCount, int yCellCount, BoundingBox region)
        {
            indexDelaunay = delaunay;
            indexRegion   = region;
            x_size        = region.Width / yCellCount;
            y_size        = region.Height / xCellCount;
            // The grid will hold a trinagle for each cell, so a point (x,y) will lie
            // in the cell representing the grid partition of region to a
            //  xCellCount on yCellCount grid
            grid = new Triangle_dt[xCellCount + 1, yCellCount + 1];
            Triangle_dt colStartTriangle = indexDelaunay.Find(middleOfCell(0, 0));

            updateCellValues(0, 0, xCellCount - 1, yCellCount - 1, colStartTriangle);
        }
 private Triangle_dt treatDegeneracyInside(Triangle_dt t, Point_dt p)
 {
     if ((t.abnext.isHalfplane & p.pointLineTest(t.b, t.a) == Point_dt.ONSEGMENT))
     {
         return(extendOutside(t.abnext, p));
     }
     if ((t.bcnext.isHalfplane & p.pointLineTest(t.c, t.b) == Point_dt.ONSEGMENT))
     {
         return(extendOutside(t.bcnext, p));
     }
     if ((t.canext.isHalfplane & p.pointLineTest(t.a, t.c) == Point_dt.ONSEGMENT))
     {
         return(extendOutside(t.canext, p));
     }
     return(null);
 }
 /// <summary>
 /// assumes v is an halfplane! - returns another (none halfplane) triangle
 /// </summary>
 private static Triangle_dt findnext2(Point_dt p, Triangle_dt v)
 {
     if ((((v.abnext != null)) & (!(v.abnext.isHalfplane))))
     {
         return(v.abnext);
     }
     if ((((v.bcnext != null)) & (!(v.bcnext.isHalfplane))))
     {
         return(v.bcnext);
     }
     if ((((v.canext != null)) & (!(v.canext.isHalfplane))))
     {
         return(v.canext);
     }
     return(null);
 }
Example #15
0
 /// <summary>
 /// Go over each grid cell and locate a triangle in it to be the cell's
 /// starting search triangle. Since we only pass between adjacent cells
 /// we can search from the last triangle found and not from the start.
 /// Add triangles for each column cells
 /// </summary>
 /// <param name="startXCell"></param>
 /// <param name="startYCell"></param>
 /// <param name="lastXCell"></param>
 /// <param name="lastYCell"></param>
 /// <param name="startTriangle"></param>
 /// <remarks></remarks>
 private void updateCellValues(int startXCell, int startYCell, int lastXCell, int lastYCell, Triangle_dt startTriangle)
 {
     for (int i = startXCell; i <= lastXCell; i++)
     {
         // Find a triangle at the begining of the current column
         startTriangle       = indexDelaunay.Find(middleOfCell(i, startYCell), startTriangle);
         grid[i, startYCell] = startTriangle;
         Triangle_dt prevRowTriangle = startTriangle;
         // Add triangles for the next row cells
         for (int j = startYCell + 1; j <= lastYCell; j++)
         {
             grid[i, j]      = indexDelaunay.Find(middleOfCell(i, j), prevRowTriangle);
             prevRowTriangle = grid[i, j];
         }
     }
 }
        /// <summary>
        /// finds the triangle the query point falls in, note if out-side of this
        /// triangulation a half plane triangle will be returned (see contains), the
        /// search has expected time of O(n^0.5), and it starts form a fixed triangle
        /// (me.startTriangle).
        /// </summary>
        /// <param name="p">Query point</param>
        /// <returns>The triangle that point <paramref name="p"/> is in.</returns>
        public Triangle_dt Find(Point_dt p)
        {
            // If triangulation has a spatial index try to use it as the starting
            //triangle
            Triangle_dt searchTriangle = startTriangle;

            if ((gridIndex != null))
            {
                Triangle_dt indexTriangle = gridIndex.findCellTriangleOf(p);
                if ((indexTriangle != null))
                {
                    searchTriangle = indexTriangle;
                }
            }
            // Search for the point's triangle starting from searchTriangle
            return(Find(searchTriangle, p));
        }
        private void Flip(Triangle_dt t, int mc)
        {
            Triangle_dt u = t.abnext;
            Triangle_dt v = default(Triangle_dt);

            t.mc = mc;
            if ((u.isHalfplane | (!(u.circumcircle_contains(t.c)))))
            {
                return;
            }
            if ((t.a.Equals(u.a)))
            {
                v        = new Triangle_dt(u.b, t.b, t.c);
                v.abnext = u.bcnext;
                t.abnext = u.abnext;
            }
            else if ((t.a.Equals(u.b)))
            {
                v        = new Triangle_dt(u.c, t.b, t.c);
                v.abnext = u.canext;
                t.abnext = u.bcnext;
            }
            else if ((t.a.Equals(u.c)))
            {
                v        = new Triangle_dt(u.a, t.b, t.c);
                v.abnext = u.abnext;
                t.abnext = u.canext;
            }
            else
            {
                throw new Exception("Error in flip.");
            }
            v.mc     = mc;
            v.bcnext = t.bcnext;
            v.abnext.switchneighbors(u, v);
            v.bcnext.switchneighbors(t, v);
            t.bcnext = v;
            v.canext = t;
            t.b      = v.a;
            t.abnext.switchneighbors(u, t);
            t.circumcircle();
            currT = v;
            Flip(t, mc);
            Flip(v, mc);
        }
        private Triangle_dt extendclock(Triangle_dt t, Point_dt p)
        {
            t.isHalfplane = false;
            t.c           = p;
            t.circumcircle();
            Triangle_dt tbc = t.bcnext;

            if ((p.pointLineTest(tbc.a, tbc.b) >= Point_dt.RIGHT))
            {
                Triangle_dt nT = new Triangle_dt(p, t.b);
                nT.abnext  = t;
                t.bcnext   = nT;
                nT.bcnext  = tbc;
                tbc.canext = nT;
                return(nT);
            }
            return(extendclock(tbc, p));
        }
        private Triangle_dt extendcounterclock(Triangle_dt t, Point_dt p)
        {
            t.isHalfplane = false;
            t.c           = p;
            t.circumcircle();
            Triangle_dt tca = t.canext;

            if ((p.pointLineTest(tca.a, tca.b) >= Point_dt.RIGHT))
            {
                Triangle_dt nT = new Triangle_dt(t.a, p);
                nT.abnext  = t;
                t.canext   = nT;
                nT.canext  = tca;
                tca.bcnext = nT;
                return(nT);
            }
            return(extendcounterclock(tca, p));
        }
Example #20
0
 public void switchneighbors(Triangle_dt old_t, Triangle_dt new_t)
 {
     if (_abnext.Equals(old_t))
     {
         _abnext = new_t;
     }
     else if (_bcnext.Equals(old_t))
     {
         _bcnext = new_t;
     }
     else if (_canext.Equals(old_t))
     {
         _canext = new_t;
     }
     else
     {
         Console.WriteLine("Error, switchneighbors can't find Old.");
     }
 }
 private void initTriangles()
 {
     if (_modCount == _modCount2)
     {
         return;
     }
     if (this.Size() > 2)
     {
         _modCount2 = _modCount;
         List <Triangle_dt> front = new List <Triangle_dt>();
         _triangles = new List <Triangle_dt>();
         front.Add(this.startTriangle);
         while ((front.Count > 0))
         {
             Triangle_dt t = front[0];
             front.RemoveAt(0);
             if ((t.mark == false))
             {
                 t.mark = true;
                 _triangles.Add(t);
                 if (((t.abnext != null)) && (!t.abnext.mark))
                 {
                     front.Add(t.abnext);
                 }
                 if (((t.bcnext != null)) && (!t.bcnext.mark))
                 {
                     front.Add(t.bcnext);
                 }
                 if (((t.canext != null)) && (!t.canext.mark))
                 {
                     front.Add(t.bcnext);
                 }
             }
         }
         foreach (Triangle_dt aTriangle in _triangles)
         {
             aTriangle.mark = false;
         }
     }
 }
        /// <summary>
        /// Return point with x/y and updated Z value (z value is as given by the triangulation)
        /// </summary>
        /// <param name="p">Query point (x/y=</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public Point_dt z(Point_dt p)
        {
            Triangle_dt t = Find(p);

            return(t.z(p));
        }
        /// <summary>
        /// Search for x/y point within current triangulation
        /// </summary>
        /// <param name="x">Query point x coordinate</param>
        /// <param name="y">Query point y coordinate</param>
        /// <returns>Return true if x/y is within current triangulation (in its 2D convex hull).</returns>
        public bool contains(double x, double y)
        {
            Triangle_dt tt = Find(new Point_dt(x, y));

            return(!tt.isHalfplane);
        }
        /// <summary>
        /// Search for p within current triangulation
        /// </summary>
        /// <param name="p">Query point</param>
        /// <returns>Return true if p is within current triangulation (in its 2D convex hull).</returns>
        public bool contains(Point_dt p)
        {
            Triangle_dt tt = Find(p);

            return(!tt.isHalfplane);
        }
        private Triangle_dt insertPointSimple(Point_dt p)
        {
            nPoints += 1;
            if ((!allColinear))
            {
                Triangle_dt t = Find(startTriangle, p);
                if (t.isHalfplane)
                {
                    startTriangle = extendOutside(t, p);
                }
                else
                {
                    startTriangle = extendInside(t, p);
                }
                return(startTriangle);
            }
            if (nPoints == 1)
            {
                firstP = p;
                return(null);
            }
            if (nPoints == 2)
            {
                startTriangulation(firstP, p);
                return(null);
            }
            switch (p.pointLineTest(firstP, lastP))
            {
            case Point_dt.LEFT:
                startTriangle = extendOutside(firstT.abnext, p);
                allColinear   = false;
                break;                         // TODO: might not be correct. Was : Exit Select

                break;

            case Point_dt.RIGHT:
                startTriangle = extendOutside(firstT, p);
                allColinear   = false;
                break;                         // TODO: might not be correct. Was : Exit Select

                break;

            case Point_dt.ONSEGMENT:
                insertCollinear(p, Point_dt.ONSEGMENT);
                break;                         // TODO: might not be correct. Was : Exit Select

                break;

            case Point_dt.INFRONTOFA:
                insertCollinear(p, Point_dt.INFRONTOFA);
                break;                         // TODO: might not be correct. Was : Exit Select

                break;

            case Point_dt.BEHINDB:
                insertCollinear(p, Point_dt.BEHINDB);
                break;                         // TODO: might not be correct. Was : Exit Select

                break;
            }
            return(null);
        }
        private void insertCollinear(Point_dt p, int res)
        {
            Triangle_dt t  = default(Triangle_dt);
            Triangle_dt tp = default(Triangle_dt);
            Triangle_dt u  = default(Triangle_dt);

            switch (res)
            {
            case Point_dt.INFRONTOFA:
                t                    = new Triangle_dt(firstP, p);
                tp                   = new Triangle_dt(p, firstP);
                t.abnext             = tp;
                tp.abnext            = t;
                t.bcnext             = tp;
                tp.canext            = t;
                t.canext             = firstT;
                firstT.bcnext        = t;
                tp.bcnext            = firstT.abnext;
                firstT.abnext.canext = tp;
                firstT               = t;
                firstP               = p;
                break;                         // TODO: might not be correct. Was : Exit Select

                break;

            case Point_dt.BEHINDB:
                t                   = new Triangle_dt(p, lastP);
                tp                  = new Triangle_dt(lastP, p);
                t.abnext            = tp;
                tp.abnext           = t;
                t.bcnext            = lastT;
                lastT.canext        = t;
                t.canext            = tp;
                tp.bcnext           = t;
                tp.canext           = lastT.abnext;
                lastT.abnext.bcnext = tp;
                lastT               = t;
                lastP               = p;
                break;                         // TODO: might not be correct. Was : Exit Select

                break;

            case Point_dt.ONSEGMENT:
                u = firstT;
                while (p.isGreater(u.a))
                {
                    u = u.canext;
                }
                t                      = new Triangle_dt(p, u.b);
                tp                     = new Triangle_dt(u.b, p);
                u.b                    = p;
                u.abnext.a             = p;
                t.abnext               = tp;
                tp.abnext              = t;
                t.bcnext               = u.bcnext;
                u.bcnext.canext        = t;
                t.canext               = u;
                u.bcnext               = t;
                tp.canext              = u.abnext.canext;
                u.abnext.canext.bcnext = tp;
                tp.bcnext              = u.abnext;
                u.abnext.canext        = tp;
                if ((firstT.Equals(u)))
                {
                    firstT = t;
                }
                break;                         // TODO: might not be correct. Was : Exit Select

                break;
            }
        }