public static void main(IEnumerable <Point> points) { Output.LineCollection.Clear(); sorted = triangulate = plot = debug = false; Func <Site> next; if (sorted) { //** } else { ReadSites(points); next = () => NextOne(); siteidx = 0; VoronoiGeometry.geominit(); if (plot) { Output.plotinit(); } VoronoiAlgorithm.voronoi(() => { Site nextSite = next(); return(nextSite); }); } }
internal static Edge bisect(Site s1, Site s2) { if (s1 == null) { throw new ArgumentNullException("s1"); } if (s2 == null) { throw new ArgumentNullException("s2"); } double dx, dy; double adx, ady; // absolute dx and dy - |.| Edge newedge = new Edge(); //** getfree newedge.reg[0] = s1; newedge.reg[1] = s2; VoronoiGeometry.Ref(s1); VoronoiGeometry.Ref(s2); newedge.EndPoints[0] = null; newedge.EndPoints[1] = null; dx = s2.Coord.X - s1.Coord.X; dy = s2.Coord.Y - s1.Coord.Y; adx = Math.Abs(dx); ady = Math.Abs(dy); newedge.c = s1.Coord.X * dx + s1.Coord.Y * dy + 0.5 * (dx * dx + dy * dy); if (adx > ady) { newedge.a = 1; newedge.b = dy / dx; newedge.c /= dx; } else { newedge.b = 1; newedge.a = dx / dy; newedge.c /= dy; } newedge.edgeNumber = nedges; Output.out_bisector(newedge); nedges++; return(newedge); }
internal static void endpoint(Edge e, int lr, Site s) { e.EndPoints[lr] = s; VoronoiGeometry.Ref(s); if (e.EndPoints[EndPoint.Right - lr] == null) { return; } Output.OutputEndPoint(e); VoronoiGeometry.deref(e.reg[EndPoint.Left]); VoronoiGeometry.deref(e.reg[EndPoint.Right]); //** makefree((Freenode)e, (Freelist)efl); }
public static void PQdelete(HalfEdge he) { HalfEdge last; if (he.Vertex != null) { last = PQhash[PQbucket(he)]; while (last.PQnext != he) { last = last.PQnext; } last.PQnext = he.PQnext; PQcount--; VoronoiGeometry.deref(he.Vertex); he.Vertex = null; } }
public static void PQinsert(HalfEdge he, Site v, double offset) { he.Vertex = v; VoronoiGeometry.Ref(v); he.ystar = v.Coord.Y + offset; HalfEdge last = PQhash[PQbucket(he)]; HalfEdge next; while ((next = last.PQnext) != null && (he.ystar > next.ystar || he.ystar == next.ystar && v.Coord.X > next.Vertex.Coord.X)) { last = next; } he.PQnext = last.PQnext; last.PQnext = he; PQcount++; }
public static void voronoi(Func <Site> nextsite) { Heap.PQinitialize(); EdgeList.Bottomsite = nextsite(); Output.OutputSite(EdgeList.Bottomsite); EdgeList.ELinitialize(); Site newsite = nextsite(); HalfEdge lbnd, rbnd, llbnd, rrbnd, bisector; Site bottom, top, temp, p, v; Point newintstar = new Point(); int pm; Edge e; while (true) { if (!Heap.PQempty()) { newintstar = Heap.PQ_min(); } if (newsite != null && (Heap.PQempty() || newsite.Coord.Y < newintstar.Y || (newsite.Coord.Y == newintstar.Y && newsite.Coord.X < newintstar.X))) { // new site is smallest Output.OutputSite(newsite); lbnd = EdgeList.ELleftbnd(newsite.Coord); rbnd = EdgeList.ELright(lbnd); bottom = EdgeList.rightreg(lbnd); e = VoronoiGeometry.bisect(bottom, newsite); bisector = EdgeList.HEcreate(e, EndPoint.Left); EdgeList.ELinsert(lbnd, bisector); p = VoronoiGeometry.intersect(lbnd, bisector); if (p != null) { Heap.PQdelete(lbnd); Heap.PQinsert(lbnd, p, VoronoiGeometry.dist(p, newsite)); } lbnd = bisector; bisector = EdgeList.HEcreate(e, EndPoint.Right); EdgeList.ELinsert(lbnd, bisector); p = VoronoiGeometry.intersect(bisector, rbnd); if (p != null) { Heap.PQinsert(bisector, p, VoronoiGeometry.dist(p, newsite)); } newsite = nextsite(); } else if (!Heap.PQempty()) /* intersection is smallest */ { lbnd = Heap.PQextractmin(); llbnd = EdgeList.ELleft(lbnd); rbnd = EdgeList.ELright(lbnd); rrbnd = EdgeList.ELright(rbnd); bottom = EdgeList.leftreg(lbnd); top = EdgeList.rightreg(rbnd); Output.out_triple(bottom, top, EdgeList.rightreg(lbnd)); v = lbnd.Vertex; VoronoiGeometry.makevertex(v); VoronoiGeometry.endpoint(lbnd.Edge, lbnd.ELpm, v); VoronoiGeometry.endpoint(rbnd.Edge, rbnd.ELpm, v); EdgeList.ELdelete(lbnd); Heap.PQdelete(rbnd); EdgeList.ELdelete(rbnd); pm = EndPoint.Left; if (bottom.Coord.Y > top.Coord.Y) { temp = bottom; bottom = top; top = temp; pm = EndPoint.Right; } e = VoronoiGeometry.bisect(bottom, top); bisector = EdgeList.HEcreate(e, pm); EdgeList.ELinsert(llbnd, bisector); VoronoiGeometry.endpoint(e, EndPoint.Right - pm, v); VoronoiGeometry.deref(v); p = VoronoiGeometry.intersect(llbnd, bisector); if (p != null) { Heap.PQdelete(llbnd); Heap.PQinsert(llbnd, p, VoronoiGeometry.dist(p, bottom)); } p = VoronoiGeometry.intersect(bisector, rrbnd); if (p != null) { Heap.PQinsert(bisector, p, VoronoiGeometry.dist(p, bottom)); } } else { break; } } for (lbnd = EdgeList.ELright(EdgeList.ELleftend); lbnd != EdgeList.ELrightend; lbnd = EdgeList.ELright(lbnd)) { e = lbnd.Edge; Output.OutputEndPoint(e); } } // end of while
public static HalfEdge ELleftbnd(Point p) { int bucket = (int)((p.X - VoronoiMain.xmin) / VoronoiGeometry.deltax * ELhashsize); if (bucket < 0) { bucket = 0; } if (bucket >= ELhashsize) { bucket = ELhashsize - 1; } HalfEdge he = ELgethash(bucket); if (he == null) { int i = 1; while (true) { he = ELgethash(bucket - i); if (he != null) { break; } he = ELgethash(bucket + i); if (he != null) { break; } i++; } totalsearch += i; } ntry++; // Now search linear list of halfedges for the correct one if (he == ELleftend || (he != ELrightend && VoronoiGeometry.right_of(he, p))) { do { he = he.Right; } while (he != ELrightend && VoronoiGeometry.right_of(he, p)); he = he.Left; } else { do { he = he.Left; } while (he != ELleftend && !VoronoiGeometry.right_of(he, p)); } // Update hash table and reference count if (bucket > 0 && bucket < (ELhashsize - 1)) { if (ELhash[bucket] != null) { ELhash[bucket].RefCount--; } ELhash[bucket] = he; ELhash[bucket].RefCount++; } return(he); }