/// <summary> /// Add a bad triangle to the end of a queue. /// </summary> /// <param name="enqtri"></param> /// <param name="minedge"></param> /// <param name="apex"></param> /// <param name="org"></param> /// <param name="dest"></param> public void Enqueue(ref Otri enqtri, float minedge, Vertex apex, Vertex org, Vertex dest) { // Allocate space for the bad triangle. BadTriangle newbad = new BadTriangle(); newbad.poortri = enqtri; newbad.key = minedge; newbad.apex = apex; newbad.org = org; newbad.dest = dest; Enqueue(newbad); }
/// <summary> /// Remove a triangle from the front of the queue. /// </summary> /// <returns></returns> public BadTriangle Dequeue() { // If no queues are nonempty, return NULL. if (firstnonemptyq < 0) { return(null); } count--; // Find the first triangle of the highest-priority queue. BadTriangle result = queuefront[firstnonemptyq]; // Remove the triangle from the queue. queuefront[firstnonemptyq] = result.next; // If this queue is now empty, note the new highest-priority // nonempty queue. if (result == queuetail[firstnonemptyq]) { firstnonemptyq = nextnonemptyq[firstnonemptyq]; } return(result); }
/// <summary> /// Inserts a vertex at the circumcenter of a triangle. Deletes /// the newly inserted vertex if it encroaches upon a segment. /// </summary> /// <param name="badtri"></param> private void SplitTriangle(BadTriangle badtri) { Otri badotri = default(Otri); Vertex borg, bdest, bapex; Point newloc; // Location of the new vertex double xi = 0, eta = 0; InsertVertexResult success; bool errorflag; badotri = badtri.poortri; borg = badotri.Org(); bdest = badotri.Dest(); bapex = badotri.Apex(); // Make sure that this triangle is still the same triangle it was // when it was tested and determined to be of bad quality. // Subsequent transformations may have made it a different triangle. if (!Otri.IsDead(badotri.tri) && (borg == badtri.org) && (bdest == badtri.dest) && (bapex == badtri.apex)) { errorflag = false; // Create a new vertex at the triangle's circumcenter. // Using the original (simpler) Steiner point location method // for mesh refinement. // TODO: NewLocation doesn't work for refinement. Why? Maybe // reset VertexType? if (behavior.fixedArea || behavior.VarArea) { newloc = predicates.FindCircumcenter(borg, bdest, bapex, ref xi, ref eta, behavior.offconstant); } else { newloc = newLocation.FindLocation(borg, bdest, bapex, ref xi, ref eta, true, badotri); } // Check whether the new vertex lies on a triangle vertex. if (((newloc.x == borg.x) && (newloc.y == borg.y)) || ((newloc.x == bdest.x) && (newloc.y == bdest.y)) || ((newloc.x == bapex.x) && (newloc.y == bapex.y))) { if (Log.Verbose) { logger.Warning("New vertex falls on existing vertex.", "Quality.SplitTriangle()"); errorflag = true; } } else { // The new vertex must be in the interior, and therefore is a // free vertex with a marker of zero. Vertex newvertex = new Vertex(newloc.x, newloc.y, 0 #if USE_ATTRIBS , mesh.nextras #endif ); newvertex.type = VertexType.FreeVertex; // Ensure that the handle 'badotri' does not represent the longest // edge of the triangle. This ensures that the circumcenter must // fall to the left of this edge, so point location will work. // (If the angle org-apex-dest exceeds 90 degrees, then the // circumcenter lies outside the org-dest edge, and eta is // negative. Roundoff error might prevent eta from being // negative when it should be, so I test eta against xi.) if (eta < xi) { badotri.Lprev(); } // Assign triangle for attributes interpolation. newvertex.tri.tri = newvertex_tri; // Insert the circumcenter, searching from the edge of the triangle, // and maintain the Delaunay property of the triangulation. Osub tmp = default(Osub); success = mesh.InsertVertex(newvertex, ref badotri, ref tmp, true, true); if (success == InsertVertexResult.Successful) { newvertex.hash = mesh.hash_vtx++; newvertex.id = newvertex.hash; #if USE_ATTRIBS if (mesh.nextras > 0) { Interpolation.InterpolateAttributes(newvertex, newvertex.tri.tri, mesh.nextras); } #endif mesh.vertices.Add(newvertex.hash, newvertex); if (mesh.steinerleft > 0) { mesh.steinerleft--; } } else if (success == InsertVertexResult.Encroaching) { // If the newly inserted vertex encroaches upon a subsegment, // delete the new vertex. mesh.UndoVertex(); } else if (success == InsertVertexResult.Violating) { // Failed to insert the new vertex, but some subsegment was // marked as being encroached. } else { // success == DUPLICATEVERTEX // Couldn't insert the new vertex because a vertex is already there. if (Log.Verbose) { logger.Warning("New vertex falls on existing vertex.", "Quality.SplitTriangle()"); errorflag = true; } } } if (errorflag) { logger.Error("The new vertex is at the circumcenter of triangle: This probably " + "means that I am trying to refine triangles to a smaller size than can be " + "accommodated by the finite precision of floating point arithmetic.", "Quality.SplitTriangle()"); throw new Exception("The new vertex is at the circumcenter of triangle."); } } }
/// <summary> /// Add a bad triangle data structure to the end of a queue. /// </summary> /// <param name="badtri">The bad triangle to enqueue.</param> public void Enqueue(BadTriangle badtri) { float length, multiplier; int exponent, expincrement; int queuenumber; int posexponent; int i; count++; // Determine the appropriate queue to put the bad triangle into. // Recall that the key is the square of its shortest edge length. if (badtri.key >= 1.0f) { length = badtri.key; posexponent = 1; } else { // 'badtri.key' is 2.0 to a negative exponent, so we'll record that // fact and use the reciprocal of 'badtri.key', which is > 1.0. length = 1.0f / badtri.key; posexponent = 0; } // 'length' is approximately 2.0 to what exponent? The following code // determines the answer in time logarithmic in the exponent. exponent = 0; while (length > 2.0f) { // Find an approximation by repeated squaring of two. expincrement = 1; multiplier = 0.5f; while (length * multiplier * multiplier > 1.0f) { expincrement *= 2; multiplier *= multiplier; } // Reduce the value of 'length', then iterate if necessary. exponent += expincrement; length *= multiplier; } // 'length' is approximately squareroot(2.0) to what exponent? exponent = 2 * exponent + (length > SQRT2 ? 1 : 0); // 'exponent' is now in the range 0...2047 for IEEE float precision. // Choose a queue in the range 0...4095. The shortest edges have the // highest priority (queue 4095). if (posexponent > 0) { queuenumber = 2047 - exponent; } else { queuenumber = 2048 + exponent; } // Are we inserting into an empty queue? if (queuefront[queuenumber] == null) { // Yes, we are inserting into an empty queue. // Will this become the highest-priority queue? if (queuenumber > firstnonemptyq) { // Yes, this is the highest-priority queue. nextnonemptyq[queuenumber] = firstnonemptyq; firstnonemptyq = queuenumber; } else { // No, this is not the highest-priority queue. // Find the queue with next higher priority. i = queuenumber + 1; while (queuefront[i] == null) { i++; } // Mark the newly nonempty queue as following a higher-priority queue. nextnonemptyq[queuenumber] = nextnonemptyq[i]; nextnonemptyq[i] = queuenumber; } // Put the bad triangle at the beginning of the (empty) queue. queuefront[queuenumber] = badtri; } else { // Add the bad triangle to the end of an already nonempty queue. queuetail[queuenumber].next = badtri; } // Maintain a pointer to the last triangle of the queue. queuetail[queuenumber] = badtri; // Newly enqueued bad triangle has no successor in the queue. badtri.next = null; }
/// <summary> /// Add a bad triangle data structure to the end of a queue. /// </summary> /// <param name="badtri">The bad triangle to enqueue.</param> public void Enqueue(BadTriangle badtri) { double length, multiplier; int exponent, expincrement; int queuenumber; int posexponent; int i; this.count++; // Determine the appropriate queue to put the bad triangle into. // Recall that the key is the square of its shortest edge length. if (badtri.key >= 1.0) { length = badtri.key; posexponent = 1; } else { // 'badtri.key' is 2.0 to a negative exponent, so we'll record that // fact and use the reciprocal of 'badtri.key', which is > 1.0. length = 1.0 / badtri.key; posexponent = 0; } // 'length' is approximately 2.0 to what exponent? The following code // determines the answer in time logarithmic in the exponent. exponent = 0; while (length > 2.0) { // Find an approximation by repeated squaring of two. expincrement = 1; multiplier = 0.5; while (length * multiplier * multiplier > 1.0) { expincrement *= 2; multiplier *= multiplier; } // Reduce the value of 'length', then iterate if necessary. exponent += expincrement; length *= multiplier; } // 'length' is approximately squareroot(2.0) to what exponent? exponent = 2 * exponent + (length > SQRT2 ? 1 : 0); // 'exponent' is now in the range 0...2047 for IEEE double precision. // Choose a queue in the range 0...4095. The shortest edges have the // highest priority (queue 4095). if (posexponent > 0) { queuenumber = 2047 - exponent; } else { queuenumber = 2048 + exponent; } // Are we inserting into an empty queue? if (queuefront[queuenumber] == null) { // Yes, we are inserting into an empty queue. // Will this become the highest-priority queue? if (queuenumber > firstnonemptyq) { // Yes, this is the highest-priority queue. nextnonemptyq[queuenumber] = firstnonemptyq; firstnonemptyq = queuenumber; } else { // No, this is not the highest-priority queue. // Find the queue with next higher priority. i = queuenumber + 1; while (queuefront[i] == null) { i++; } // Mark the newly nonempty queue as following a higher-priority queue. nextnonemptyq[queuenumber] = nextnonemptyq[i]; nextnonemptyq[i] = queuenumber; } // Put the bad triangle at the beginning of the (empty) queue. queuefront[queuenumber] = badtri; } else { // Add the bad triangle to the end of an already nonempty queue. queuetail[queuenumber].next = badtri; } // Maintain a pointer to the last triangle of the queue. queuetail[queuenumber] = badtri; // Newly enqueued bad triangle has no successor in the queue. badtri.next = null; }
/// <summary> /// Add a bad triangle to the end of a queue. /// </summary> /// <param name="enqtri"></param> /// <param name="minedge"></param> /// <param name="apex"></param> /// <param name="org"></param> /// <param name="dest"></param> public void Enqueue(ref Otri enqtri, double minedge, Vertex apex, Vertex org, Vertex dest) { // Allocate space for the bad triangle. BadTriangle newbad = new BadTriangle(); newbad.poortri = enqtri; newbad.key = minedge; newbad.apex = apex; newbad.org = org; newbad.dest = dest; Enqueue(newbad); }