示例#1
0
        private double dist(PointFortune s, PointFortune t)
        {
            double dx, dy;

            dx = s.X - t.X;
            dy = s.Y - t.Y;
            return(Convert.ToSingle(Math.Sqrt(dx * dx + dy * dy)));
        }
示例#2
0
        // create a new site where the HalfEdges el1 and el2 intersect - note that
        // the Point in the argument list is not used, don't know why it's there
        private PointFortune intersect(Halfedge el1, Halfedge el2)
        {
            EdgeF        e1, e2, e;
            Halfedge     el;
            double       d, xint, yint;
            bool         right_of_site;
            PointFortune v; // vertex

            e1 = el1.ELedge;
            e2 = el2.ELedge;

            if (e1 == null || e2 == null)
            {
                return(null);
            }

            // if the two edges bisect the same parent, return null
            if (e1.reg[1] == e2.reg[1])
            {
                return(null);
            }

            d = e1.a * e2.b - e1.b * e2.a;
            if (-1.0e-10 < d && d < 1.0e-10)
            {
                return(null);
            }

            xint = (e1.c * e2.b - e2.c * e1.b) / d;
            yint = (e2.c * e1.a - e1.c * e2.a) / d;

            if ((e1.reg[1].Y < e2.reg[1].Y) ||
                (e1.reg[1].Y == e2.reg[1].Y && e1.reg[1].X < e2.reg[1].X))
            {
                el = el1;
                e  = e1;
            }
            else
            {
                el = el2;
                e  = e2;
            }

            right_of_site = xint >= e.reg[1].X;
            if ((right_of_site && el.ELpm == LE) ||
                (!right_of_site && el.ELpm == RE))
            {
                return(null);
            }

            // create a new site at the point of intersection - this is a new vector
            // event waiting to happen
            v   = new PointFortune();
            v.X = xint;
            v.Y = yint;
            return(v);
        }
示例#3
0
 private void endpoint(EdgeF e, int lr, PointFortune s)
 {
     e.ep[lr] = s;
     if (e.ep[RE - lr] == null)
     {
         return;
     }
     clip_line(e);
 }
示例#4
0
        List <EdgeFortune> MakeVoronoiGraph(List <PointF> myListPoints, int width, int height)
        {
            List <PointFortune> listPointsFortune = new List <PointFortune>();

            for (int i = 0; i < myListPoints.Count; i++)
            {
                listPointsFortune.Add(new PointFortune(myListPoints[i].X, myListPoints[i].Y, i));
            }
            PointFortune max = new PointFortune(0, 0, 0);
            PointFortune min = new PointFortune(width, height, 0);

            return(voronoi.GenerateVoronoi(listPointsFortune));
        }
示例#5
0
        private PointFortune PQ_min()
        {
            PointFortune answer = new PointFortune();

            while (PQhash[PQmin].PQnext == null)
            {
                PQmin++;
            }

            answer.X = PQhash[PQmin].PQnext.vertex.X;
            answer.Y = PQhash[PQmin].PQnext.ystar;
            return(answer);
        }
示例#6
0
        private void pushGraphEdge(PointFortune leftPointFortune, PointFortune rightPointFortune, double x1, double y1, double x2, double y2)
        {
            EdgeFortune newEdge = new EdgeFortune();

            allEdges.Add(newEdge);
            newEdge.x1 = x1;
            newEdge.y1 = y1;
            newEdge.x2 = x2;
            newEdge.y2 = y2;

            newEdge.PointIndex1 = leftPointFortune.IndexInList;
            newEdge.PointIndex2 = rightPointFortune.IndexInList;
        }
示例#7
0
        // push the HalfEdge into the ordered linked list of pointCloud
        private void PQinsert(Halfedge he, PointFortune v, double offset)
        {
            Halfedge last, next;

            he.vertex = v;
            he.ystar  = (double)(v.Y + offset);
            last      = PQhash[PQbucket(he)];

            while
            (
                (next = last.PQnext) != null
                &&
                (he.ystar > next.ystar || (he.ystar == next.ystar && v.X > next.vertex.X))
            )
            {
                last = next;
            }

            he.PQnext   = last.PQnext;
            last.PQnext = he;
            PQcount++;
        }
示例#8
0
        private EdgeF bisect(PointFortune s1, PointFortune s2)
        {
            double dx, dy, adx, ady;
            EdgeF  newedge;

            newedge = new EdgeF();

            newedge.reg[0] = s1;
            newedge.reg[1] = s2;

            newedge.ep[0] = null;
            newedge.ep[1] = null;

            dx = s2.X - s1.X;
            dy = s2.Y - s1.Y;

            adx       = dx > 0 ? dx : -dx;
            ady       = dy > 0 ? dy : -dy;
            newedge.c = (double)(s1.X * dx + s1.Y * dy + (dx * dx + dy * dy) * 0.5);

            if (adx > ady)
            {
                newedge.a  = 1.0f;
                newedge.b  = dy / dx;
                newedge.c /= dx;
            }
            else
            {
                newedge.a  = dx / dy;
                newedge.b  = 1.0f;
                newedge.c /= dy;
            }

            newedge.edgenbr = nedges;
            nedges++;

            return(newedge);
        }
示例#9
0
        private void CalculateMinMax(ref PointFortune max, ref PointFortune min)
        {
            if (points.Count < 1)
            {
                return;
            }

            double xMax = points[0].X;
            double yMax = points[0].Y;
            double xMin = points[0].X;
            double yMin = points[0].Y;

            foreach (PointFortune ver in points)
            {
                if (ver.X > xMax)
                {
                    xMax = ver.X;
                }
                if (ver.Y > yMax)
                {
                    yMax = ver.Y;
                }

                if (ver.X < xMin)
                {
                    xMin = ver.X;
                }
                if (ver.Y < yMin)
                {
                    yMin = ver.Y;
                }
            }
            max.X = xMax;
            max.Y = yMax;

            min.X = xMin;
            min.Y = yMin;
        }
示例#10
0
        private void sortNode()
        {
            numberPointsStart = points.Count;
            xmin = points[0].X;
            ymin = points[0].Y;
            xmax = points[0].X;
            ymax = points[0].Y;

            for (int i = 0; i < numberPointsStart; i++)
            {
                PointFortune p = points[i];

                if (p.X < xmin)
                {
                    xmin = p.X;
                }
                else if (p.X > xmax)
                {
                    xmax = p.X;
                }

                if (p.Y < ymin)
                {
                    ymin = p.Y;
                }
                else if (p.Y > ymax)
                {
                    ymax = p.Y;
                }
            }

            points.Sort(new PointFortuneSorterYX());

            deltax = xmax - xmin;
            deltay = ymax - ymin;
        }
示例#11
0
        /// <summary>
        /// Generate a Voronoi List of Edges
        /// </summary>
        /// <param name="mypoints"></param>
        /// <param name="minX: The minimum X of the bounding box around the voronoi"></param>
        /// <param name="maxX: The maximum X of the bounding box around the voronoi"></param>
        /// <param name="minY: The minimum Y of the bounding box around the voronoi"></param>
        /// <param name="maxY: The maximum Y of the bounding box around the voronoi"></param>
        /// <returns></returns>
        public List <EdgeFortune> GenerateVoronoi(List <PointFortune> mypoints)
        {
            this.points = mypoints;

            PointFortune max = new PointFortune();
            PointFortune min = new PointFortune();

            CalculateMinMax(ref max, ref min);



            sort();

            //SwapValues(ref minX, ref maxX, ref minY, ref maxY);

            borderMinX = min.X;
            borderMinY = min.Y;
            borderMaxX = max.X;
            borderMaxY = max.Y;

            siteidx = 0;
            calculateVoronoi();
            return(allEdges);
        }
示例#12
0
        /*
         * implicit parameters: nsites, sqrt_nsites, xmin, xmax, ymin, ymax, deltax,
         * deltay (can all be estimates). Performance suffers if they are wrong;
         * better to make nsites, deltax, and deltay too big than too small. (?)
         */
        private bool calculateVoronoi()
        {
            PointFortune newsite, bot, top, temp, p;
            PointFortune v;
            PointFortune newintstar = null;
            int          pm;
            Halfedge     leftEdge, rightEdge, llHalfedge, rrHalfedge, bisector;
            EdgeF        e;

            PQinitialize();
            ELinitialize();

            bottomsite = nextone();
            newsite    = nextone();
            while (true)
            {
                if (!PQempty())
                {
                    newintstar = PQ_min();
                }
                // if the lowest site has a smaller y value than the lowest vector
                // intersection,
                // process the site otherwise process the vector intersection

                if (newsite != null && (PQempty() ||
                                        newsite.Y < newintstar.Y ||
                                        (newsite.Y == newintstar.Y &&
                                         newsite.X < newintstar.X)))
                {
                    /* new site is smallest -this is a site event */
                    // get the first HalfEdge to the LEFT of the new site
                    leftEdge = ELleftbnd((newsite));
                    // get the first HalfEdge to the RIGHT of the new site
                    rightEdge = ELright(leftEdge);
                    // if this halfedge has no edge,bot =bottom site (whatever that
                    // is)
                    bot = rightreg(leftEdge);
                    // create a new edge that bisects
                    e = bisect(bot, newsite);

                    // create a new HalfEdge, setting its ELpm field to 0
                    bisector = HEcreate(e, LE);
                    // insert this new bisector edge between the left and right
                    // vectors in a linked list
                    ELinsert(leftEdge, bisector);

                    // if the new bisector intersects with the left edge,
                    // remove the left edge's vertex, and put in the new one
                    if ((p = intersect(leftEdge, bisector)) != null)
                    {
                        PQdelete(leftEdge);
                        PQinsert(leftEdge, p, dist(p, newsite));
                    }
                    leftEdge = bisector;
                    // create a new HalfEdge, setting its ELpm field to 1
                    bisector = HEcreate(e, RE);
                    // insert the new HE to the right of the original bisector
                    // earlier in the IF stmt
                    ELinsert(leftEdge, bisector);

                    // if this new bisector intersects with the new HalfEdge
                    if ((p = intersect(bisector, rightEdge)) != null)
                    {
                        // push the HE into the ordered linked list of pointCloud
                        PQinsert(bisector, p, dist(p, newsite));
                    }
                    newsite = nextone();
                }
                else if (!PQempty())
                /* intersection is smallest - this is a vector event */
                {
                    // pop the HalfEdge with the lowest vector off the ordered list
                    // of vectors
                    leftEdge = PQextractmin();
                    // get the HalfEdge to the left of the above HE
                    llHalfedge = ELleft(leftEdge);
                    // get the HalfEdge to the right of the above HE
                    rightEdge = ELright(leftEdge);
                    // get the HalfEdge to the right of the HE to the right of the
                    // lowest HE
                    rrHalfedge = ELright(rightEdge);
                    // get the PointFortune to the left of the left HE which it bisects
                    bot = leftreg(leftEdge);
                    // get the PointFortune to the right of the right HE which it bisects
                    top = rightreg(rightEdge);

                    v = leftEdge.vertex; // get the vertex that caused this event
                    makevertex(v);       // set the vertex number - couldn't do this
                    // earlier since we didn't know when it would be processed
                    endpoint(leftEdge.ELedge, leftEdge.ELpm, v);
                    // set the endpoint of
                    // the left HalfEdge to be this vector
                    endpoint(rightEdge.ELedge, rightEdge.ELpm, v);
                    // set the endpoint of the right HalfEdge to
                    // be this vector
                    ELdelete(leftEdge); // mark the lowest HE for
                    // deletion - can't delete yet because there might be pointers
                    // to it in Hash Map
                    PQdelete(rightEdge);
                    // remove all vertex events to do with the right HE
                    ELdelete(rightEdge); // mark the right HE for
                    // deletion - can't delete yet because there might be pointers
                    // to it in Hash Map
                    pm = LE; // set the pm variable to zero

                    if (bot.Y > top.Y)
                    // if the site to the left of the event is higher than the
                    // PointFortune
                    { // to the right of it, then swap them and set the 'pm'
                        // variable to 1
                        temp = bot;
                        bot  = top;
                        top  = temp;
                        pm   = RE;
                    }
                    e = bisect(bot, top); // create an Edge (or line)
                    // that is between the two PointFortunes. This creates the formula of
                    // the line, and assigns a line number to it
                    bisector = HEcreate(e, pm); // create a HE from the Edge 'e',
                    // and make it point to that edge
                    // with its ELedge field
                    ELinsert(llHalfedge, bisector); // insert the new bisector to the
                    // right of the left HE
                    endpoint(e, RE - pm, v);        // set one endpoint to the new edge
                    // to be the vector point 'v'.
                    // If the site to the left of this bisector is higher than the
                    // right PointFortune, then this endpoint
                    // is put in position 0; otherwise in pos 1

                    // if left HE and the new bisector intersect, then delete
                    // the left HE, and reinsert it
                    if ((p = intersect(llHalfedge, bisector)) != null)
                    {
                        PQdelete(llHalfedge);
                        PQinsert(llHalfedge, p, dist(p, bot));
                    }

                    // if right HE and the new bisector intersect, then
                    // reinsert it
                    if ((p = intersect(bisector, rrHalfedge)) != null)
                    {
                        PQinsert(bisector, p, dist(p, bot));
                    }
                }
                else
                {
                    break;
                }
            }

            for (leftEdge = ELright(ELleftend); leftEdge != ELrightend; leftEdge = ELright(leftEdge))
            {
                e = leftEdge.ELedge;
                clip_line(e);
            }

            return(true);
        }
示例#13
0
        /* returns true if p is to right of halfedge e */
        private bool right_of(Halfedge el, PointFortune p)
        {
            EdgeF        e;
            PointFortune topsite;
            bool         right_of_site;
            bool         above, fast;
            double       dxp, dyp, dxs, t1, t2, t3, yl;

            e       = el.ELedge;
            topsite = e.reg[1];

            if (p.X > topsite.X)
            {
                right_of_site = true;
            }
            else
            {
                right_of_site = false;
            }

            if (right_of_site && el.ELpm == LE)
            {
                return(true);
            }
            if (!right_of_site && el.ELpm == RE)
            {
                return(false);
            }

            if (e.a == 1)
            {
                dxp  = p.X - topsite.X;
                dyp  = p.Y - topsite.Y;
                fast = false;

                if ((!right_of_site & (e.b < 0)) | (right_of_site & (e.b >= 0)))
                {
                    above = dyp >= e.b * dxp;
                    fast  = above;
                }
                else
                {
                    above = p.X + p.Y * e.b > e.c;
                    if (e.b < 0)
                    {
                        above = !above;
                    }
                    if (!above)
                    {
                        fast = true;
                    }
                }
                if (!fast)
                {
                    dxs   = topsite.X - (e.reg[0]).X;
                    above = e.b * (dxp * dxp - dyp * dyp)
                            < dxs * dyp * (1 + 2 * dxp / dxs + e.b * e.b);

                    if (e.b < 0)
                    {
                        above = !above;
                    }
                }
            }
            else // e.b == 1.0
            {
                yl    = e.c - e.a * p.X;
                t1    = p.Y - yl;
                t2    = p.X - topsite.X;
                t3    = yl - topsite.Y;
                above = t1 * t1 > t2 * t2 + t3 * t3;
            }
            return(el.ELpm == LE ? above : !above);
        }
示例#14
0
        private Halfedge ELleftbnd(PointFortune p)
        {
            int      bucket;
            Halfedge he;

            /* Use hash table to get close to desired halfedge */
            // use the hash function to find the place in the hash map that this
            // HalfEdge should be
            bucket = (int)((p.X - xmin) / deltax * ELhashsize);

            // make sure that the bucket position is within the range of the hash
            // array
            if (bucket < 0)
            {
                bucket = 0;
            }
            if (bucket >= ELhashsize)
            {
                bucket = ELhashsize - 1;
            }

            he = ELgethash(bucket);

            // if the HE isn't found, search backwards and forwards in the hash map
            // for the first non-null entry
            if (he == null)
            {
                for (int i = 1; i < ELhashsize; i++)
                {
                    if ((he = ELgethash(bucket - i)) != null)
                    {
                        break;
                    }
                    if ((he = ELgethash(bucket + i)) != null)
                    {
                        break;
                    }
                }
            }

            /* Now search linear list of halfedges for the correct one */
            if (he == ELleftend || (he != ELrightend && right_of(he, p)))
            {
                // keep going right on the list until either the end is reached, or
                // you find the 1st edge which the point isn't to the right of
                do
                {
                    he = he.ELright;
                }while (he != ELrightend && right_of(he, p));
                he = he.ELleft;
            }
            else
            // if the point is to the left of the HalfEdge, then search left for
            // the HE just to the left of the point
            {
                do
                {
                    he = he.ELleft;
                }while (he != ELleftend && !right_of(he, p));
            }

            /* Update hash table and reference counts */
            if (bucket > 0 && bucket < ELhashsize - 1)
            {
                ELhash[bucket] = he;
            }

            return(he);
        }
示例#15
0
 private void makevertex(PointFortune v)
 {
     v.IndexInList = numberPoints;
     numberPoints++;
 }