147 lines
3.2 KiB
C#
Raw Normal View History

using UnityEngine;
using System.Collections.Generic;
using Delaunay.Utils;
namespace Delaunay
{
internal sealed class HalfedgePriorityQueue: Utils.IDisposable // also known as heap
{
private Halfedge[] _hash;
private int _count;
private int _minBucket;
private int _hashsize;
private float _ymin;
private float _deltay;
public HalfedgePriorityQueue (float ymin, float deltay, int sqrt_nsites)
{
_ymin = ymin;
_deltay = deltay;
_hashsize = 4 * sqrt_nsites;
Initialize ();
}
public void Dispose ()
{
// get rid of dummies
for (int i = 0; i < _hashsize; ++i) {
_hash [i].Dispose ();
_hash [i] = null;
}
_hash = null;
}
private void Initialize ()
{
int i;
_count = 0;
_minBucket = 0;
_hash = new Halfedge[_hashsize];
// dummy Halfedge at the top of each hash
for (i = 0; i < _hashsize; ++i) {
_hash [i] = Halfedge.CreateDummy ();
_hash [i].nextInPriorityQueue = null;
}
}
public void Insert (Halfedge halfEdge)
{
Halfedge previous, next;
int insertionBucket = Bucket (halfEdge);
if (insertionBucket < _minBucket) {
_minBucket = insertionBucket;
}
previous = _hash [insertionBucket];
while ((next = previous.nextInPriorityQueue) != null
&& (halfEdge.ystar > next.ystar || (halfEdge.ystar == next.ystar && halfEdge.vertex.x > next.vertex.x))) {
previous = next;
}
halfEdge.nextInPriorityQueue = previous.nextInPriorityQueue;
previous.nextInPriorityQueue = halfEdge;
++_count;
}
public void Remove (Halfedge halfEdge)
{
Halfedge previous;
int removalBucket = Bucket (halfEdge);
if (halfEdge.vertex != null) {
previous = _hash [removalBucket];
while (previous.nextInPriorityQueue != halfEdge) {
previous = previous.nextInPriorityQueue;
}
previous.nextInPriorityQueue = halfEdge.nextInPriorityQueue;
_count--;
halfEdge.vertex = null;
halfEdge.nextInPriorityQueue = null;
halfEdge.Dispose ();
}
}
private int Bucket (Halfedge halfEdge)
{
int theBucket = (int)((halfEdge.ystar - _ymin) / _deltay * _hashsize);
if (theBucket < 0)
theBucket = 0;
if (theBucket >= _hashsize)
theBucket = _hashsize - 1;
return theBucket;
}
private bool IsEmpty (int bucket)
{
return (_hash [bucket].nextInPriorityQueue == null);
}
/**
* move _minBucket until it contains an actual Halfedge (not just the dummy at the top);
*
*/
private void AdjustMinBucket ()
{
while (_minBucket < _hashsize - 1 && IsEmpty(_minBucket)) {
++_minBucket;
}
}
public bool Empty ()
{
return _count == 0;
}
/**
* @return coordinates of the Halfedge's vertex in V*, the transformed Voronoi diagram
*
*/
public Vector2 Min ()
{
AdjustMinBucket ();
Halfedge answer = _hash [_minBucket].nextInPriorityQueue;
return new Vector2 (answer.vertex.x, answer.ystar);
}
/**
* remove and return the min Halfedge
* @return
*
*/
public Halfedge ExtractMin ()
{
Halfedge answer;
// get the first real Halfedge in _minBucket
answer = _hash [_minBucket].nextInPriorityQueue;
_hash [_minBucket].nextInPriorityQueue = answer.nextInPriorityQueue;
_count--;
answer.nextInPriorityQueue = null;
return answer;
}
}
}