///Assign random number to modify the priority of neighbors counter ///@param queue is a priority queue stores the number of neighbors for each empty cell of current game ///@param counter is a vector stores pair of index value of empty cells and count of neighbors ///@return NONE void Strategy::assignRandomNeighbors(PriorityQueue<int, int>& queue, vector<pair<int, int> >& counter, int currentempty) { long long seed = hexgame::chrono::system_clock::now().time_since_epoch().count(); //TODO refactor to have consistent codes for C++11 and < C++11 #if __cplusplus > 199711L default_random_engine generator(seed); #else boost::mt19937 generator(static_cast<unsigned>(seed)); srand(static_cast<unsigned>(seed)); #endif //ensure assign unique number vector<int> numbers(currentempty); for (int i = 0; i < currentempty; i++) numbers[i] = (i + 1); #if __cplusplus > 199711L shuffle(numbers.begin(), numbers.end(), generator); #else std::random_shuffle(numbers.begin(), numbers.end()); #endif hexgame::uniform_real_distribution<float> probability(0.0, 1.0); for (int i = 0; i < currentempty; i++) { float prob = probability(generator); //if randomness = 1, then doing shuffle int weight = static_cast<int>((counter[i].second) * (1.0 - randomness)); if (prob <= randomness) queue.insert(counter[i].first, -(weight + numbers[i])); else queue.insert(counter[i].first, -weight); } }
void insert_edge_to_heap(int v, EdgeNode *p){ edgepair *ep = new edgepair; ep->x = v; ep->y = p->y; ep->weight = p->weight; min_heap.insert(ep); }
// Return a list<Edge> containing the list of edges in the minimum spanning tree found by Kruskal's Algorithm list<Edge> KruskalMST::tree() { list<Edge> mst; PriorityQueue<Edge> p; Node selected; Edge selectedEdge; // Add each node of the graph to its own set list<Node> allNodes = graph.vertices(); for(list<Node>::iterator i=allNodes.begin(); i != allNodes.end(); ++i) makeSet(*i); // Insert all edges from the graph into priority queue for(list<Node>::iterator i=allNodes.begin(); i != allNodes.end(); ++i) { list<Node> iEdges = graph.neighbors((*i).getNodeNumber()); for(list<Node>::iterator j=iEdges.begin(); j != iEdges.end(); ++j) { Edge e((*i).getNodeNumber(),(*j).getNodeNumber(),(*j).getEdgeWeight()); p.insert(e); } } while(p.size() != 0) { selectedEdge = p.top(); // Remove the lower edge from the priority queue if (findSet(selectedEdge.getSrc()) != findSet(selectedEdge.getDst())) { mst.push_back(selectedEdge); // If src and dst are in different sets, then add this edge to mst combineSet(selectedEdge.getSrc(),selectedEdge.getDst()); // Combine both sets into one } } return mst; }
int* getOptimalPath(Vertex Graph[], int size, int start, int goal) { PriorityQueue<float> PQ; LinkedList<edge>* Edges; int current, next, i; float NewCost; float *CostSoFar = new float[size]; for (i = 1; i < size; i++) CostSoFar[i] = FLT_MAX; CostSoFar[0] = 0.0; int* parent = new int[size]; //PQ.insert(start, getEuclideanDistance(Coordinates[start], Coordinates[goal])); PQ.insert(start, 0); while (!PQ.isEmpty()) { //PQ.Print(); current = PQ.remove(); if (current == goal) { delete [] CostSoFar; return parent; } else { Edges = &Graph[current].getEdges(); for (Edges->begin(); !Edges->end(); Edges->next()) { next = Edges->getCurrent().to; NewCost = CostSoFar[current] + Edges->getCurrent().cost /*+ getEuclideanDistance(Coordinates[next], Coordinates[goal])*/; if (NewCost < CostSoFar[next]) { CostSoFar[next] = NewCost; parent[next] = current; PQ.insert(next, NewCost); } } } } delete [] CostSoFar; return NULL; }
TEST(Solution, TwoSamePrioString) { PriorityQueue pq = PriorityQueue(); std::string x = "xxx"; std::string w = "www"; std::string y = "yyy"; pq.insert(20, x); pq.insert(20, w); pq.insert(10, y); std::string call1 = pq.next(); EXPECT_TRUE(call1 == w || call1 == x); std::string call2 = pq.next(); EXPECT_TRUE(call2 == w || call2 == x); // How to handle when there are no elements? EXPECT_TRUE(NULL == pq.next()); EXPECT_EQ(y, pq.next()); }
TEST(QueueTest, PrioritySortTest) { // Check that inserting several nodes sorts them // in order of f (g+h) PriorityQueue queue; Node n1(0,1,4,5,false), n2(1,2,4,3,false), n3(2,1,3,6,false), n4(1,0,4,7,false); queue.insert(&n1); queue.insert(&n2); queue.insert(&n3); queue.insert(&n4); // Order should be n2,n3,n1,n4 ASSERT_EQ(&n2, queue.removeFront()); ASSERT_EQ(&n3, queue.removeFront()); ASSERT_EQ(&n1, queue.removeFront()); ASSERT_EQ(&n4, queue.removeFront()); }
// Return a list<Edge> containing the list of edges in the minimum spanning tree found by Prim's Algorithm list<Edge> PrimMST::tree() { list<Edge> mst; PriorityQueue<Edge> p; Node selected; Edge selectedEdge; // Create selectedNodes empty set // Create candidateNodes set containing all nodes list<Node> selectedNodes; list<Node> candidateNodes = graph.vertices(); while (!candidateNodes.empty()) { // Add first node from candidateNodes set to selectedNodes set and remove it from candidateNodes selected = candidateNodes.front(); selectedNodes.push_back(selected); candidateNodes.remove(selected); // Insert all edges from first node into priority queue list<Node> sEdges = graph.neighbors(selected.getNodeNumber()); for(list<Node>::iterator j=sEdges.begin(); j != sEdges.end(); ++j) { Edge e(selected.getNodeNumber(),(*j).getNodeNumber(),(*j).getEdgeWeight()); p.insert(e); } while(p.size() != 0) { selectedEdge = p.top(); // Remove the lower edge from the priority queue if ((isSrcInSet(selectedEdge,selectedNodes)) && (isDstInSet(selectedEdge,candidateNodes))) { mst.push_back(selectedEdge); // Add selected node to selectedNodes set and remove it from candidateNodes set selected = getNodeInSet(selectedEdge.getDst(),candidateNodes); selectedNodes.push_back(selected); candidateNodes.remove(selected); // Insert all edges from dst node into priority queue sEdges = graph.neighbors(selected.getNodeNumber()); for(list<Node>::iterator j=sEdges.begin(); j != sEdges.end(); ++j) { Edge e(selected.getNodeNumber(),(*j).getNodeNumber(),(*j).getEdgeWeight()); p.insert(e); } } } } return mst; }
Node<Plot>* search(std::map<Plot*, std::vector<Plot*> >& path, Plot& start, Plot& goal) { Node<Plot>* node_goal = new Node<Plot>(goal); Node<Plot>* node_start = new Node<Plot>(start); PriorityQueue queue; std::unordered_map<Plot*, int> closeList; queue.insert(node_start); int iter = 0; while (!queue.empty()) { iter++; Node<Plot> *current(*(queue.begin())); queue.erase(queue.begin()); std::vector<Plot*>& neighbours(path[current->node]); for (Plot *p : neighbours) { Node<Plot>* next = new Node<Plot>(*p); next->g = current->g + manhattan_distance(current->node, p); next->h = manhattan_distance(p, &goal); next->f = next->g + next->h; next->x = current->x + 1; // nb turns next->parent = current; if (p == node_goal->node) { std::cout << "nbIter: " << iter << std::endl; return next; } if (isWorthTrying(next, queue, closeList)) { queue.insert(next); } } closeList[current->node] = current->f; delete current; } return nullptr; }
int main() { string op; int idx = 0; PriorityQueue <int> h; while (cin >> op) { if (op == "push") { int v; cin >> v; h.insert(idx, v); } else if (op == "extract-min") {
TEST(Solution, TwoStrings) { PriorityQueue pq = PriorityQueue(); std::string x = "xxx"; std::string w = "www"; pq.insert(10, w); pq.insert(20, x); EXPECT_EQ(x, pq.next()); EXPECT_EQ(w, pq.next()); // How to handle when there are no elements? EXPECT_TRUE(NULL == pq.next); }
void testPriorityQueue() { cout << "PriorityQueue => "; PriorityQueue* q = new PriorityQueue(); CharString* cc = new CharString("test@#$%^*()_+1234567890",24); q->insert(0,cc); CharString* qq = (CharString*)q->removeMin(); if(qq == cc) { cout << "Pass" << endl; } else { cout << "Fail" << "(" << qq->get() << ")" << endl; } }
// Return a list<char> containing the list of nodes in the shortest path between 'u' and 'w' list<char> ShortestPath::path(char u, char w) { // Initialize candidates list with all nodes list<char> candidates = graph.vertices(), desiredPath; list<NodeInfo> minPaths; PriorityQueue p; NodeInfo lastSelected, n; // Calculate shortest path from 'u' to 'w' (Dijkstra's Algorithm) candidates.remove(u); // Remove 'u' from candidates list lastSelected.nodeName = u; // Set 'u' as lastSelected lastSelected.minDist = 0; lastSelected.through = u; minPaths.push_back(lastSelected); // Add 'u' to minPath list while ((!candidates.empty()) && (lastSelected.nodeName !=w)) { // For each node in candidate list calculate the cost to reach that candidate through lastSelected for(list<char>::iterator i=candidates.begin(); i != candidates.end(); ++i) { n.nodeName=*i; n.minDist=lastSelected.minDist+graph.get_edge_value(lastSelected.nodeName,*i); n.through=lastSelected.nodeName; if (!p.contains(n)) // Add candidate to priority queue if doesn't exist p.insert(n); else if (p.isBetter(n)) // Update candidate minDist in priority queue if a better path was found p.chgPriority(n); } lastSelected = p.top(); // Select the candidate with minDist from priority queue p.minPriority(); // Remove it from the priority queue minPaths.push_back(lastSelected); // Add the candidate with min distance to minPath list candidates.remove(lastSelected.nodeName); // Remove it from candidates list } // Go backward from 'w' to 'u' adding nodes in that path to desiredPath list lastSelected=minPaths.back(); desiredPath.push_front(lastSelected.nodeName); while(lastSelected.nodeName!=u) { for(list<NodeInfo>::iterator i=minPaths.begin(); i != minPaths.end(); ++i) if ((*i).nodeName==lastSelected.through) { lastSelected=(*i); desiredPath.push_front(lastSelected.nodeName); } } return desiredPath; }
// Run a simulation finding the Prim's and Kruskal's MST in a given graph void MonteCarlo::run(Graph g) { static int turn=0; cout << endl << "=== RUNNING SIMULATION No. " << ++turn << " ===" << endl; // Print out graph information double d = static_cast<double>(g.E())/((static_cast<double>(g.V())*static_cast<double>(g.V())-1)/2)*100; // Calculate real density reached cout << "Vertices: " << g.V() << endl; cout << "Edges: " << g.E() << " (density: " << d << "%)" << endl; cout << "Nodes: " << g.vertices() << endl; cout << "Graph: " << g << endl; cout << "Graph (.dot format): " << endl; cout << "graph Homework3 {" << endl; // Insert all edges from the graph into priority queue list<Node> allNodes = g.vertices(); PriorityQueue<Edge> p; for(list<Node>::iterator i=allNodes.begin(); i != allNodes.end(); ++i) { list<Node> iEdges = g.neighbors((*i).getNodeNumber()); for(list<Node>::iterator j=iEdges.begin(); j != iEdges.end(); ++j) { Edge e((*i).getNodeNumber(),(*j).getNodeNumber(),(*j).getEdgeWeight()); p.insert(e); } } cout << p; cout << "}" << endl; PrimMST prim(g); cout << "Prim MST (.dot format): " << endl; cout << "graph PrimMST {" << endl; cout << prim.tree(); cout << "}" << endl; cout << "Prim MST cost: " << prim.cost() << endl; cout << endl; KruskalMST kruskal(g); cout << "Kruskal MST (.dot format): " << endl; cout << "graph KruskalMST {" << endl; cout << kruskal.tree(); cout << "}" << endl; cout << "Kruskal MST cost: " << kruskal.cost() << endl; }
//-------------------------------------------------------------------------------------------------- void testMinHeap() { PriorityQueue *minHeap = new MinHeap(); minHeap->insert(22); minHeap->insert(8); minHeap->insert(50); minHeap->insert(3); minHeap->insert(2); minHeap->insert(30); minHeap->insert(100); minHeap->display(); cout << "Minimum value is - " << (dynamic_cast<MinHeap *>(minHeap))->getMin() << endl; cout << "Now I am deleting max value" << endl; (dynamic_cast<MinHeap *>(minHeap))->deleteMin(); minHeap->display(); }
// DESC: Dijkstra's algorithm to find shortest distance from source to destination on a graph. // INPUT: Graph to expand on, Vertex to represent as the source. // OUTPUT: Linked list of the path LinkedListT* DijkstraDistances(Graph* graph, Vertex* source) { // form a cloud to every point. // Store this cloud in the PQueue. LinkedListT* verticies = graph->verticies(); PriorityQueue* pq = new PriorityQueue(); // loop through verticies for(int i=0; i<verticies->size(); i++) { Vertex* vv = (Vertex*)verticies->get(i); if(vv == source) { vv->distance = 0; // set vertex to zero if it is the source vertex. } else { vv->distance = 999999999; // set verticies to infinity to represent an unreachable location. } // insert into queue. pq->insert(vv->distance,vv); } // empty out the set while(!pq->empty()) { // remove the minimum distance from the set. (usually source vertex on start) Vertex* v = (Vertex*)pq->removeMin(); LinkedListT* vt = v->incidentEdges; // loop through incident Edges for(int i=0; i<vt->size(); i++) { Edge* e = (Edge*)vt->get(i); Vertex* v2 = e->opposite(v); int r = v->distance + e->data; // if the total range is less than v2's distance, then set it. if(r < v2->distance) { v2->distance = r; pq->replaceKey(pq->top(),(void*)v2,r); } } } }
inline void singleDefUse(FlowGraph* fg, X86Instruction* ins, BasicBlock* bb, Loop* loop, std::pebil_map_type<uint64_t, X86Instruction*>& ipebil_map_type, std::pebil_map_type<uint64_t, BasicBlock*>& bpebil_map_type, std::pebil_map_type<uint64_t, LinkedList<X86Instruction::ReachingDefinition*>*>& alliuses, std::pebil_map_type<uint64_t, LinkedList<X86Instruction::ReachingDefinition*>*>& allidefs, int k, uint64_t loopLeader, uint32_t fcnt){ // Get defintions for this instruction: ins LinkedList<X86Instruction::ReachingDefinition*>* idefs = ins->getDefs(); LinkedList<X86Instruction::ReachingDefinition*>* allDefs = idefs; // Skip instruction if it doesn't define anything if (idefs == NULL) { return; } if (idefs->empty()) { delete idefs; return; } set<LinkedList<X86Instruction::ReachingDefinition*>*> allDefLists; allDefLists.insert(idefs); PriorityQueue<struct path*, uint32_t> paths = PriorityQueue<struct path*, uint32_t>(); bool blockTouched[fg->getFunction()->getNumberOfBasicBlocks()]; bzero(&blockTouched, sizeof(bool) * fg->getFunction()->getNumberOfBasicBlocks()); // Initialize worklist with the path from this instruction // Only take paths inside the loop. Since the definitions are in a loop, uses in the loop will be most relevant. if (k == bb->getNumberOfInstructions() - 1){ ASSERT(ins->controlFallsThrough()); if (bb->getNumberOfTargets() > 0){ ASSERT(bb->getNumberOfTargets() == 1); if (flowsInDefUseScope(bb->getTargetBlock(0), loop)){ // Path flows to the first instruction of the next block paths.insert(new path(bb->getTargetBlock(0)->getLeader(), idefs), 1); } } } else { // path flows to the next instruction in this block paths.insert(new path(bb->getInstruction(k+1), idefs), 1); } // while there are paths in worklist while (!paths.isEmpty()) { // take the shortest path in list uint32_t currDist; struct path* p = paths.deleteMin(&currDist); X86Instruction* cand = p->ins; idefs = p->defs; delete p; LinkedList<X86Instruction::ReachingDefinition*>* i2uses, *i2defs, *newdefs; i2uses = alliuses[cand->getBaseAddress()]; // Check if any of idefs is used if(i2uses != NULL && anyDefsAreUsed(idefs, i2uses)){ // Check if use is shortest uint32_t duDist; duDist = trueDefUseDist(currDist, fcnt); if (!ins->getDefUseDist() || ins->getDefUseDist() > duDist) { ins->setDefUseDist(duDist); } // If dist has increased beyond size of function, we must be looping? if (currDist > fcnt) { ins->setDefXIter(); break; } // Stop searching along this path continue; } // Check if any defines are overwritten i2defs = allidefs[cand->getBaseAddress()]; newdefs = removeInvalidated(idefs, i2defs); // If all definitions killed, stop searching along this path if (newdefs == NULL) continue; allDefLists.insert(newdefs); // end of block that is a branch if (cand->usesControlTarget() && !cand->isCall()){ BasicBlock* tgtBlock = bpebil_map_type[cand->getTargetAddress()]; if (tgtBlock && !blockTouched[tgtBlock->getIndex()] && flowsInDefUseScope(tgtBlock, loop)){ blockTouched[tgtBlock->getIndex()] = true; if (tgtBlock->getBaseAddress() == loopLeader){ paths.insert(new path(tgtBlock->getLeader(), newdefs), loopXDefUseDist(currDist + 1, fcnt)); } else { paths.insert(new path(tgtBlock->getLeader(), newdefs), currDist + 1); } } } // non-branching control if (cand->controlFallsThrough()){ BasicBlock* tgtBlock = bpebil_map_type[cand->getBaseAddress() + cand->getSizeInBytes()]; if (tgtBlock && flowsInDefUseScope(tgtBlock, loop)){ X86Instruction* ftTarget = ipebil_map_type[cand->getBaseAddress() + cand->getSizeInBytes()]; if (ftTarget){ if (ftTarget->isLeader()){ if (!blockTouched[tgtBlock->getIndex()]){ blockTouched[tgtBlock->getIndex()] = true; if (ftTarget->getBaseAddress() == loopLeader){ paths.insert(new path(ftTarget, newdefs), loopXDefUseDist(currDist + 1, fcnt)); } else { paths.insert(new path(ftTarget, newdefs), currDist + 1); } } } else { paths.insert(new path(ftTarget, newdefs), currDist + 1); } } } } } if (!paths.isEmpty()){ ins->setDefUseDist(0); } while (!paths.isEmpty()){ delete paths.deleteMin(NULL); } while (!allDefs->empty()){ delete allDefs->shift(); } for(set<LinkedList<X86Instruction::ReachingDefinition*>*>::iterator it = allDefLists.begin(); it != allDefLists.end(); ++it){ delete *it; } }
int main(int argc, char *argv[]) { cout << "Usage: " << argv[0] << " [FILENAME].[off|obj|ply] [1-7] [sl]" << endl; cout << "where 1-7 is the cost function to use" << endl; cout << " s = save images at all decimation steps" << endl; cout << " l = disable lighting" << endl; cout << endl; cout << "Keybindings:" << endl; cout << " [space] toggle animation." << endl; cout << " 'r' reset." << endl; cout << " '1' edge collapse." << endl; cout << " '2' vertex split." << endl; cout << " 's' save screenshot." << endl; cout << " 'c' switch color mode." << endl; cout << " 'f' cycle cost function." << endl; cout << endl; // Load a closed manifold mesh string filename; if (argc >= 2) { filename = argv[1]; } else { return 0; } if (argc >= 3) { int idx = stoi(argv[2]) - 1; cost_function_n = idx; if (idx >= 0 && idx < cost_functions.size()) shortest_edge_and_midpoint = *(cost_functions.begin() + idx); } if (!igl::read_triangle_mesh(filename, OV, OF)) { cout << "could not read mesh from \"" << filename << "\"" << endl; return 1; } // compute normals igl::per_face_normals(OV, OF, normals); // Prepare array-based edge data structures and priority queue // EMAP is a map from faces to edges. // Index into it like EMAP(face + i*F.rows()) where i is an edge index // between 0 and 2 corresponding to the three edges of a triangle. VectorXi EMAP; // E is a map from edges to vertices. Given some edge index e, // E(e, 0) and E(e, 1) are the two vertices that the edge is composed of. MatrixXi E; // EF is a map from edges to faces. For some edge index e, // EF(e, 0) and E(e, 1) are the two faces that contain the edge e. MatrixXi EF; // EI is a map from edges to face corners. For some edge index e, // EI(e, 0) is the index i such that EMAP(EF(e, 0) + i*F.rows()) == e and // EI(e, 1) is the index i such that EMAP(EF(e, 1) + i*F.rows()) == e. MatrixXi EI; typedef std::set<std::pair<double, int>> PriorityQueue; // Q stores the list of possible edge collapses and their costs PriorityQueue Q; std::vector<PriorityQueue::iterator> Qit; // If an edge were collapsed, we'd collapse it to these points: MatrixXd C; // Keep some info on edge collapses for reversal and debug reasons int num_collapsed; std::vector<MeshModification> mods; std::vector<int> iters; int total_decimations = 0; const auto &reset_view = [&]() { viewer.data.clear(); viewer.data.set_mesh(V, F); switch (color_mode) { case DISTANCE_VISUALIZATION: generate_distance_field(); case COST_VISUALIZATION: viewer.data.set_colors(colors); break; case SOLID: viewer.data.set_colors(RowVector3d(1.0, 1.0, 1.0)); break; } viewer.data.set_face_based(false); }; // Function to reset original mesh and data structures const auto &reset = [&]() { total_decimations = 0; mods.clear(); iters.clear(); F = OF; V = OV; igl::edge_flaps(F, E, EMAP, EF, EI); Qit.resize(E.rows()); C.resize(E.rows(), V.cols()); colors.resize(V.rows(), 3); colors.setZero(); VectorXd costs(V.rows()); costs.setZero(); for (int e = 0; e < E.rows(); e++) { double cost = e; RowVectorXd p(1, 3); shortest_edge_and_midpoint(e, V, F, E, EMAP, EF, EI, cost, p); C.row(e) = p; Qit[e] = Q.insert(std::pair<double, int>(cost, e)).first; costs(E(e, 0)) += cost; costs(E(e, 1)) += cost; } igl::jet(costs, true, colors); num_collapsed = 0; reset_view(); }; const auto &collapse_edges = [&](igl::viewer::Viewer &viewer) -> bool { // If animating then collapse 10% of edges if (viewer.core.is_animating && !Q.empty()) { bool something_collapsed = false; // collapse edge const int num_iters = 50; // Store the state from before the collapse so that it can be // reversed later. MatrixXd prev_V = V; MatrixXi prev_F = F; MatrixXi prev_E = E; num_collapsed = 0; int total_failures = 0; // If a certain number of failures have // occurred, we exit an infinte fail loop. for (int j = 0; j < num_iters; j++) { int e, e1, e2, f1, f2; std::vector<int> faceInd, vertInd; if (Q.empty()) break; if (!collapse_edge(shortest_edge_and_midpoint, V, F, E, EMAP, EF, EI, Q, Qit, C, e, e1, e2, f1, f2, faceInd)) { total_failures++; j--; if (total_failures > 1000) { break; } continue; } else { total_decimations++; num_collapsed++; } MatrixXi faces(faceInd.size() + 2, 3); faceInd.push_back(f1); faceInd.push_back(f2); for (int i = 0; i < faceInd.size(); i++) { faces.row(i) = prev_F.row(faceInd[i]); // cout << "ffF" << faces.row(i) << endl; } MatrixXd verts(2, 3); vertInd.push_back(prev_E(e, 0)); vertInd.push_back(prev_E(e, 1)); for (int i = 0; i < vertInd.size(); i++) { verts.row(i) = prev_V.row(vertInd[i]); } mods.push_back( MeshModification(vertInd, verts, faceInd, faces)); something_collapsed = true; } if (something_collapsed) { iters.push_back(num_collapsed); reset_view(); } } cout << "Collapsed an Edge\n" << "Decimations: " << total_decimations << "\n"; return false; }; // function to reverse edge collapse const auto &uncollapse_edges = [&](igl::viewer::Viewer &viewer) -> bool { if (viewer.core.is_animating && !mods.empty() && !iters.empty()) { int max_iter = iters.back(); iters.pop_back(); for (int i = 0; i < max_iter; i++) { MeshModification mod = mods.back(); mods.pop_back(); total_decimations--; for (int i = 0; i < mod.vertInd.size(); i++) { V.row(mod.vertInd[i]) = mod.verts.row(i); } for (int i = 0; i < mod.faceInd.size(); i++) { F.row(mod.faceInd[i]) = mod.faces.row(i); } } reset_view(); cout << "Uncollapsed an Edge\n" << "Decimations: " << total_decimations << "\n"; } }; const auto &save_images = [&]() -> bool { reset(); viewer.draw(); save_screenshot(viewer, "images/before.png"); char fn[100]; char command[512]; ofstream distfile("surface_distances", ofstream::trunc); for (int i = 0; i <= 50; i++) { collapse_edges(viewer); distfile << generate_distance_field() << endl; viewer.draw(); sprintf(fn, "images/after%03d.png", i); save_screenshot(viewer, fn); sprintf(command, "composite images/before.png " "images/after%03d.png -compose difference " "images/diff%03d.png ", i, i); system(command); sprintf(command, "composite images/after%03d.png " "images/after%03d.png -compose difference " "images/delta%03d.png ", i, i - 1, i); system(command); cout << "Step " << i << " / 100" << endl; } distfile.close(); exit(EXIT_SUCCESS); }; const auto &key_down = [&](igl::viewer::Viewer &viewer, unsigned char key, int mod) -> bool { switch (key) { case ' ': viewer.core.is_animating ^= 1; break; case 'R': case 'r': reset(); break; case '1': collapse_edges(viewer); break; case '2': uncollapse_edges(viewer); break; case '3': save_images(); break; case 'S': case 's': save_screenshot(viewer, "images/screen.png"); cout << "saved screen to images/screen.png" << endl; break; case 'C': case 'c': ((int &)color_mode)++; ((int &)color_mode) %= MAX_COLOR_MODE; reset_view(); break; case 'F': case 'f': cost_function_n++; cost_function_n %= cost_functions.size(); shortest_edge_and_midpoint = *(cost_functions.begin() + cost_function_n); reset(); break; case 'g': case 'G': cout << generate_distance_field() << endl; break; default: return false; } return true; }; const auto &s_option = [&](igl::viewer::Viewer &viewer) -> bool { if (argc >= 4) { for (char c : string(argv[3])) { switch (c) { case 's': save_images(); break; case 'l': viewer.core.shininess = 1.0; viewer.core.lighting_factor = 0.0; break; } } } }; reset(); viewer.core.is_animating = true; viewer.callback_key_pressed = key_down; viewer.callback_init = s_option; viewer.core.show_lines = false; viewer.core.camera_zoom = 2.0; return viewer.launch(); }
TEST(Solution, OneString) { PriorityQueue pq = PriorityQueue(); std::string x = "xxx"; pq.insert(20, x); EXPECT_EQ(x, pq.next()); }
IGL_INLINE bool igl::decimate( const Eigen::MatrixXd & OV, const Eigen::MatrixXi & OF, const std::function<void( const int, const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, double &, Eigen::RowVectorXd &)> & cost_and_placement, const std::function<bool( const Eigen::MatrixXd &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const Eigen::VectorXi &, const Eigen::MatrixXi &, const Eigen::MatrixXi &, const std::set<std::pair<double,int> > &, const std::vector<std::set<std::pair<double,int> >::iterator > &, const Eigen::MatrixXd &, const int, const int, const int, const int, const int)> & stopping_condition, const std::function<bool( const Eigen::MatrixXd & ,/*V*/ const Eigen::MatrixXi & ,/*F*/ const Eigen::MatrixXi & ,/*E*/ const Eigen::VectorXi & ,/*EMAP*/ const Eigen::MatrixXi & ,/*EF*/ const Eigen::MatrixXi & ,/*EI*/ const std::set<std::pair<double,int> > & ,/*Q*/ const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/ const Eigen::MatrixXd & ,/*C*/ const int /*e*/ )> & pre_collapse, const std::function<void( const Eigen::MatrixXd & , /*V*/ const Eigen::MatrixXi & , /*F*/ const Eigen::MatrixXi & , /*E*/ const Eigen::VectorXi & ,/*EMAP*/ const Eigen::MatrixXi & , /*EF*/ const Eigen::MatrixXi & , /*EI*/ const std::set<std::pair<double,int> > & , /*Q*/ const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/ const Eigen::MatrixXd & , /*C*/ const int , /*e*/ const int , /*e1*/ const int , /*e2*/ const int , /*f1*/ const int , /*f2*/ const bool /*collapsed*/ )> & post_collapse, const Eigen::MatrixXi & OE, const Eigen::VectorXi & OEMAP, const Eigen::MatrixXi & OEF, const Eigen::MatrixXi & OEI, Eigen::MatrixXd & U, Eigen::MatrixXi & G, Eigen::VectorXi & J, Eigen::VectorXi & I ) { // Decimate 1 using namespace Eigen; using namespace std; // Working copies Eigen::MatrixXd V = OV; Eigen::MatrixXi F = OF; Eigen::MatrixXi E = OE; Eigen::VectorXi EMAP = OEMAP; Eigen::MatrixXi EF = OEF; Eigen::MatrixXi EI = OEI; typedef std::set<std::pair<double,int> > PriorityQueue; PriorityQueue Q; std::vector<PriorityQueue::iterator > Qit; Qit.resize(E.rows()); // If an edge were collapsed, we'd collapse it to these points: MatrixXd C(E.rows(),V.cols()); for(int e = 0;e<E.rows();e++) { double cost = e; RowVectorXd p(1,3); cost_and_placement(e,V,F,E,EMAP,EF,EI,cost,p); C.row(e) = p; Qit[e] = Q.insert(std::pair<double,int>(cost,e)).first; } int prev_e = -1; bool clean_finish = false; while(true) { if(Q.empty()) { break; } if(Q.begin()->first == std::numeric_limits<double>::infinity()) { // min cost edge is infinite cost break; } int e,e1,e2,f1,f2; if(collapse_edge( cost_and_placement, pre_collapse, post_collapse, V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2)) { if(stopping_condition(V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2)) { clean_finish = true; break; } }else { if(prev_e == e) { assert(false && "Edge collapse no progress... bad stopping condition?"); break; } // Edge was not collapsed... must have been invalid. collapse_edge should // have updated its cost to inf... continue } prev_e = e; } // remove all IGL_COLLAPSE_EDGE_NULL faces MatrixXi F2(F.rows(),3); J.resize(F.rows()); int m = 0; for(int f = 0;f<F.rows();f++) { if( F(f,0) != IGL_COLLAPSE_EDGE_NULL || F(f,1) != IGL_COLLAPSE_EDGE_NULL || F(f,2) != IGL_COLLAPSE_EDGE_NULL) { F2.row(m) = F.row(f); J(m) = f; m++; } } F2.conservativeResize(m,F2.cols()); J.conservativeResize(m); VectorXi _1; remove_unreferenced(V,F2,U,G,_1,I); return clean_finish; }
int main(int argc, char * argv[]) { using namespace std; using namespace Eigen; using namespace igl; cout<<"Usage: ./703_Decimation_bin [filename.(off|obj|ply)]"<<endl; cout<<" [space] toggle animation."<<endl; cout<<" 'r' reset."<<endl; // Load a closed manifold mesh string filename(TUTORIAL_SHARED_PATH "/fertility.off"); if(argc>=2) { filename = argv[1]; } MatrixXd V,OV; MatrixXi F,OF; read_triangle_mesh(filename,OV,OF); igl::viewer::Viewer viewer; // Prepare array-based edge data structures and priority queue VectorXi EMAP; MatrixXi E,EF,EI; typedef std::set<std::pair<double,int> > PriorityQueue; PriorityQueue Q; std::vector<PriorityQueue::iterator > Qit; // If an edge were collapsed, we'd collapse it to these points: MatrixXd C; int num_collapsed; // Function to reset original mesh and data structures const auto & reset = [&]() { F = OF; V = OV; edge_flaps(F,E,EMAP,EF,EI); Qit.resize(E.rows()); C.resize(E.rows(),V.cols()); VectorXd costs(E.rows()); Q.clear(); for(int e = 0;e<E.rows();e++) { double cost = e; RowVectorXd p(1,3); shortest_edge_and_midpoint(e,V,F,E,EMAP,EF,EI,cost,p); C.row(e) = p; Qit[e] = Q.insert(std::pair<double,int>(cost,e)).first; } num_collapsed = 0; viewer.data.clear(); viewer.data.set_mesh(V,F); viewer.data.set_face_based(true); }; const auto &pre_draw = [&](igl::viewer::Viewer & viewer)->bool { // If animating then collapse 10% of edges if(viewer.core.is_animating && !Q.empty()) { bool something_collapsed = false; // collapse edge const int max_iter = std::ceil(0.01*Q.size()); for(int j = 0;j<max_iter;j++) { if(!collapse_edge( shortest_edge_and_midpoint, V,F,E,EMAP,EF,EI,Q,Qit,C)) { break; } something_collapsed = true; num_collapsed++; } if(something_collapsed) { viewer.data.clear(); viewer.data.set_mesh(V,F); viewer.data.set_face_based(true); } } return false; }; const auto &key_down = [&](igl::viewer::Viewer &viewer,unsigned char key,int mod)->bool { switch(key) { case ' ': viewer.core.is_animating ^= 1; break; case 'R': case 'r': reset(); break; default: return false; } return true; }; reset(); viewer.core.is_animating = true; viewer.callback_key_down = key_down; viewer.callback_pre_draw = pre_draw; return viewer.launch(); }