Exemplo n.º 1
0
///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);
  }
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
// 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;
}
Exemplo n.º 4
0
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());
}
Exemplo n.º 6
0
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());
}
Exemplo n.º 7
0
// 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;
}
Exemplo n.º 8
0
Arquivo: main.cpp Projeto: hutamaki/cg
    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);
}
Exemplo n.º 11
0
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;
    }
}
Exemplo n.º 12
0
// 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;
}
Exemplo n.º 13
0
// 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;
}
Exemplo n.º 14
0
//--------------------------------------------------------------------------------------------------
	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();
	}
Exemplo n.º 15
0
// 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;
    }
}
Exemplo n.º 17
0
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());
}
Exemplo n.º 19
0
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;
}
Exemplo n.º 20
0
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();
}