123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- // -----------------------------------------------------------------------
- // <copyright file="TrianglePool.cs" company="">
- // Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
- // </copyright>
- // -----------------------------------------------------------------------
- namespace UnityEngine.U2D.Animation.TriangleNet
- {
- using System;
- using System.Collections.Generic;
- using Animation.TriangleNet.Geometry;
- using Animation.TriangleNet.Topology;
- internal class TrianglePool : ICollection<Triangle>
- {
- // Determines the size of each block in the pool.
- private const int BLOCKSIZE = 1024;
- // The total number of currently allocated triangles.
- int size;
- // The number of triangles currently used.
- int count;
- // The pool.
- Triangle[][] pool;
- // A stack of free triangles.
- Stack<Triangle> stack;
- public TrianglePool()
- {
- size = 0;
- // On startup, the pool should be able to hold 2^16 triangles.
- int n = Math.Max(1, 65536 / BLOCKSIZE);
- pool = new Triangle[n][];
- pool[0] = new Triangle[BLOCKSIZE];
- stack = new Stack<Triangle>(BLOCKSIZE);
- }
- /// <summary>
- /// Gets a triangle from the pool.
- /// </summary>
- /// <returns></returns>
- public Triangle Get()
- {
- Triangle triangle;
- if (stack.Count > 0)
- {
- triangle = stack.Pop();
- triangle.hash = -triangle.hash - 1;
- Cleanup(triangle);
- }
- else if (count < size)
- {
- triangle = pool[count / BLOCKSIZE][count % BLOCKSIZE];
- triangle.id = triangle.hash;
- Cleanup(triangle);
- count++;
- }
- else
- {
- triangle = new Triangle();
- triangle.hash = size;
- triangle.id = triangle.hash;
- int block = size / BLOCKSIZE;
- if (pool[block] == null)
- {
- pool[block] = new Triangle[BLOCKSIZE];
- // Check if the pool has to be resized.
- if (block + 1 == pool.Length)
- {
- Array.Resize(ref pool, 2 * pool.Length);
- }
- }
- // Add triangle to pool.
- pool[block][size % BLOCKSIZE] = triangle;
- count = ++size;
- }
- return triangle;
- }
- public void Release(Triangle triangle)
- {
- stack.Push(triangle);
- // Mark the triangle as free (used by enumerator).
- triangle.hash = -triangle.hash - 1;
- }
- /// <summary>
- /// Restart the triangle pool.
- /// </summary>
- public TrianglePool Restart()
- {
- foreach (var triangle in stack)
- {
- // Reset hash to original value.
- triangle.hash = -triangle.hash - 1;
- }
- stack.Clear();
- count = 0;
- return this;
- }
- /// <summary>
- /// Samples a number of triangles from the pool.
- /// </summary>
- /// <param name="k">The number of triangles to sample.</param>
- /// <param name="random"></param>
- /// <returns></returns>
- internal IEnumerable<Triangle> Sample(int k, Random random)
- {
- int i, count = this.Count;
- if (k > count)
- {
- // TODO: handle Sample special case.
- k = count;
- }
- Triangle t;
- // TODO: improve sampling code (to ensure no duplicates).
- while (k > 0)
- {
- i = random.Next(0, count);
- t = pool[i / BLOCKSIZE][i % BLOCKSIZE];
- if (t.hash >= 0)
- {
- k--;
- yield return t;
- }
- }
- }
- private void Cleanup(Triangle triangle)
- {
- triangle.label = 0;
- triangle.area = 0.0;
- triangle.infected = false;
- for (int i = 0; i < 3; i++)
- {
- triangle.vertices[i] = null;
- triangle.subsegs[i] = default(Osub);
- triangle.neighbors[i] = default(Otri);
- }
- }
- public void Add(Triangle item)
- {
- throw new NotImplementedException();
- }
- public void Clear()
- {
- stack.Clear();
- int blocks = (size / BLOCKSIZE) + 1;
- for (int i = 0; i < blocks; i++)
- {
- var block = pool[i];
- // Number of triangles in current block:
- int length = (size - i * BLOCKSIZE) % BLOCKSIZE;
- for (int j = 0; j < length; j++)
- {
- block[j] = null;
- }
- }
- size = count = 0;
- }
- public bool Contains(Triangle item)
- {
- int i = item.hash;
- if (i < 0 || i > size)
- {
- return false;
- }
- return pool[i / BLOCKSIZE][i % BLOCKSIZE].hash >= 0;
- }
- public void CopyTo(Triangle[] array, int index)
- {
- var enumerator = GetEnumerator();
- while (enumerator.MoveNext())
- {
- array[index] = enumerator.Current;
- index++;
- }
- }
- public int Count
- {
- get { return count - stack.Count; }
- }
- public bool IsReadOnly
- {
- get { return true; }
- }
- public bool Remove(Triangle item)
- {
- throw new NotImplementedException();
- }
- public IEnumerator<Triangle> GetEnumerator()
- {
- return new Enumerator(this);
- }
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
- class Enumerator : IEnumerator<Triangle>
- {
- // TODO: enumerator should be able to tell if collection changed.
- int count;
- Triangle[][] pool;
- Triangle current;
- int index, offset;
- internal Enumerator(TrianglePool pool)
- {
- this.count = pool.Count;
- this.pool = pool.pool;
- index = 0;
- offset = 0;
- }
- public Triangle Current
- {
- get { return current; }
- }
- public void Dispose()
- {
- }
- object System.Collections.IEnumerator.Current
- {
- get { return current; }
- }
- public bool MoveNext()
- {
- while (index < count)
- {
- current = pool[offset / BLOCKSIZE][offset % BLOCKSIZE];
- offset++;
- if (current.hash >= 0)
- {
- index++;
- return true;
- }
- }
- return false;
- }
- public void Reset()
- {
- index = offset = 0;
- }
- }
- }
- }
|