/// Optimize in a greedy fashion. public void PriorityQueueOptimization(HMesh m, EnergyFun efun) { //HalfEdgeAttributeVector<HalfEdgeCounter> counter(m.allocated_halfedges(), HalfEdgeCounter{0, false}); // VertexAttributeVector<int> flipCounter(m.allocated_vertices(), 0); Dictionary <int, HalfEdgeCounter> counter = new Dictionary <int, HalfEdgeCounter>(); Dictionary <int, int> flipCounter = new Dictionary <int, int>(); Priority_Queue.SimplePriorityQueue <PQElement> Q = new SimplePriorityQueue <PQElement>(); //priority_queue<PQElement> Q; //cout << "Building priority queue"<< endl; int time = 1; foreach (var h in m.GetHalfedgesRaw()) { if (!counter.ContainsKey(h.id)) { counter.Add(h.id, new HalfEdgeCounter()); } AddToQueue(counter, Q, h, efun, flipCounter, time); } //cout << "Emptying priority queue of size: " << Q.size() << " "; while (Q.Count > 0) { PQElement elem = Q.Dequeue(); //Walker w = m.walker(elem.h); if (counter[elem.h.id].isRemovedFromQueue) // if item already has been processed continue { continue; } counter[elem.h.id].isRemovedFromQueue = true; if (counter[elem.h.id].touched != elem.time) { if (efun.DeltaEnergy(elem.h) >= 0) { continue; } } if (!PrecondFlipEdge(elem.h)) { continue; } flipCounter[elem.h.vert.id]++; elem.h.Flip(); AddOneRingToQueue(counter, Q, elem.h.vert, efun, flipCounter, time); AddOneRingToQueue(counter, Q, elem.h.next.vert, efun, flipCounter, time); AddOneRingToQueue(counter, Q, elem.h.opp.vert, efun, flipCounter, time); AddOneRingToQueue(counter, Q, elem.h.opp.next.vert, efun, flipCounter, time); } }
private void AddToQueue(Dictionary <int, HalfEdgeCounter> counter, SimplePriorityQueue <PQElement> Q, Halfedge h, EnergyFun efun, Dictionary <int, int> flipCounter, int time) { if (h.IsBoundary()) { return; } // only consider one of the halfedges if (h.id < h.opp.id) { h = h.opp; } // if half edge already tested for queue in the current frame then skip HalfEdgeCounter c = null; if (!counter.TryGetValue(h.id, out c)) { c = new HalfEdgeCounter(); counter[h.id] = c; } if (c.touched == time) { return; } c.isRemovedFromQueue = false; if (!PrecondFlipEdge(h)) { return; } double energy = efun.DeltaEnergy(h); c.touched = time; const int avgValence = 6; int count = 0; if (!flipCounter.TryGetValue(h.vert.id, out count)) { flipCounter[h.vert.id] = 0; } if ((energy < 0) && (count < avgValence)) { Q.Enqueue(new PQElement(energy, h, time), (float)energy); } }