/* returns true if p is to right of halfedge e */ private bool right_of(Halfedge el, DoubleVector2 p) { Edge e; Site 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.Coord.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.0 ) { dxp = p.X - topsite.Coord.X; dyp = p.Y - topsite.Coord.Y; fast = false; if ( (!right_of_site & (e.b < 0.0)) | (right_of_site & (e.b >= 0.0)) ) { above = dyp >= e.b * dxp; fast = above; } else { above = p.X + p.Y * e.b > e.c; if ( e.b < 0.0 ) above = !above; if ( !above ) fast = true; } if ( !fast ) { dxs = topsite.Coord.X - ( e.reg[0] ).Coord.X; above = e.b * (dxp * dxp - dyp * dyp) < dxs * dyp * (1.0 + 2.0 * 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.Coord.X; t3 = yl - topsite.Coord.Y; above = t1 * t1 > t2 * t2 + t3 * t3; } return ( el.ELpm == LE ? above : !above ); }
public int Compare ( Site p1, Site p2 ) { DoubleVector2 s1 = p1.Coord; DoubleVector2 s2 = p2.Coord; if ( s1.Y < s2.Y ) return -1; if ( s1.Y > s2.Y ) return 1; if ( s1.X < s2.X ) return -1; if ( s1.X > s2.X ) return 1; return 0; }
private DoubleVector2 PQ_min () { DoubleVector2 answer = new DoubleVector2 (); while ( PQhash[PQmin].PQnext == null ) { PQmin++; } answer.X = PQhash[PQmin].PQnext.vertex.Coord.X; answer.Y = PQhash[PQmin].PQnext.ystar; return answer; }
public int Compare(Site p1, Site p2) { DoubleVector2 s1 = p1.Coord; DoubleVector2 s2 = p2.Coord; if (s1.Y < s2.Y) { return(-1); } if (s1.Y > s2.Y) { return(1); } if (s1.X < s2.X) { return(-1); } if (s1.X > s2.X) { return(1); } return(0); }
public Site() { Coord = new DoubleVector2(); }
/* * 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 voronoi_bd() { Site newsite, bot, top, temp, p; Site v; DoubleVector2 newintstar = null; int pm; Halfedge lbnd, rbnd, llbnd, rrbnd, bisector; Edge 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.Coord.Y < newintstar.Y || (newsite.Coord.Y == newintstar.Y && newsite.Coord.X < newintstar.X))) { /* new site is smallest -this is a site event */ // get the first HalfEdge to the LEFT of the new site lbnd = ELleftbnd((newsite.Coord)); // get the first HalfEdge to the RIGHT of the new site rbnd = ELright(lbnd); // if this halfedge has no edge,bot =bottom site (whatever that // is) bot = rightreg(lbnd); // 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(lbnd, 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(lbnd, bisector)) != null) { PQdelete(lbnd); PQinsert(lbnd, p, dist(p, newsite)); } lbnd = 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(lbnd, bisector); // if this new bisector intersects with the new HalfEdge if ((p = intersect(bisector, rbnd)) != null) { // push the HE into the ordered linked list of vertices 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 lbnd = PQextractmin(); // get the HalfEdge to the left of the above HE llbnd = ELleft(lbnd); // get the HalfEdge to the right of the above HE rbnd = ELright(lbnd); // get the HalfEdge to the right of the HE to the right of the // lowest HE rrbnd = ELright(rbnd); // get the Site to the left of the left HE which it bisects bot = leftreg(lbnd); // get the Site to the right of the right HE which it bisects top = rightreg(rbnd); v = lbnd.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(lbnd.ELedge, lbnd.ELpm, v); // set the endpoint of // the left HalfEdge to be this vector endpoint(rbnd.ELedge, rbnd.ELpm, v); // set the endpoint of the right HalfEdge to // be this vector ELdelete(lbnd); // mark the lowest HE for // deletion - can't delete yet because there might be pointers // to it in Hash Map PQdelete(rbnd); // remove all vertex events to do with the right HE ELdelete(rbnd); // 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.Coord.Y > top.Coord.Y) // if the site to the left of the event is higher than the // Site { // 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 Sites. 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(llbnd, 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 Site, 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(llbnd, bisector)) != null) { PQdelete(llbnd); PQinsert(llbnd, p, dist(p, bot)); } // if right HE and the new bisector intersect, then // reinsert it if ((p = intersect(bisector, rrbnd)) != null) { PQinsert(bisector, p, dist(p, bot)); } } else { break; } } for (lbnd = ELright(ELleftend); lbnd != ELrightend; lbnd = ELright(lbnd)) { e = lbnd.ELedge; clip_line(e); } return true; }
private Halfedge ELleftbnd( DoubleVector2 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; }