123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- // -----------------------------------------------------------------------
- // <copyright file="BadTriQueue.cs">
- // Original Triangle code by Jonathan Richard Shewchuk, http://www.cs.cmu.edu/~quake/triangle.html
- // Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
- // </copyright>
- // -----------------------------------------------------------------------
- namespace UnityEngine.U2D.Animation.TriangleNet
- .Meshing.Data
- {
- using Animation.TriangleNet.Geometry;
- using Animation.TriangleNet.Topology;
- /// <summary>
- /// A (priority) queue for bad triangles.
- /// </summary>
- /// <remarks>
- // The queue is actually a set of 4096 queues. I use multiple queues to
- // give priority to smaller angles. I originally implemented a heap, but
- // the queues are faster by a larger margin than I'd suspected.
- /// </remarks>
- class BadTriQueue
- {
- const double SQRT2 = 1.4142135623730950488016887242096980785696718753769480732;
- public int Count { get { return this.count; } }
- // Variables that maintain the bad triangle queues. The queues are
- // ordered from 4095 (highest priority) to 0 (lowest priority).
- BadTriangle[] queuefront;
- BadTriangle[] queuetail;
- int[] nextnonemptyq;
- int firstnonemptyq;
- int count;
- public BadTriQueue()
- {
- queuefront = new BadTriangle[4096];
- queuetail = new BadTriangle[4096];
- nextnonemptyq = new int[4096];
- firstnonemptyq = -1;
- count = 0;
- }
- /// <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);
- }
- /// <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;
- }
- this.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;
- }
- }
- }
|