<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_CONNECTION_QUEUE
#define TORRENT_CONNECTION_QUEUE

#include <list>
#include <boost/function/function1.hpp>
#include <boost/function/function0.hpp>
#include <boost/noncopyable.hpp>
#include "libtorrent/io_service.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/deadline_timer.hpp"

#ifdef TORRENT_CONNECTION_LOGGING
#include <fstream>
#endif

#include "libtorrent/thread.hpp"

namespace libtorrent
{

class TORRENT_EXTRA_EXPORT connection_queue : public boost::noncopyable
{
public:
	connection_queue(io_service& ios);

	// if there are no free slots, returns the negative
	// number of queued up connections
	int free_slots() const;

	void enqueue(boost::function<void(int)> const& on_connect
		, boost::function<void()> const& on_timeout
		, time_duration timeout, int priority = 0);
	void done(int ticket);
	void limit(int limit);
	int limit() const;
	void close();
	int size() const { return m_queue.size(); }
	int num_connecting() const { return m_num_connecting; }
#if defined TORRENT_ASIO_DEBUGGING
	float next_timeout() const { return total_milliseconds(m_timer.expires_at() - time_now_hires()) / 1000.f; }
	float max_timeout() const
	{
		ptime max_timeout = min_time();
		for (std::list<entry>::const_iterator i = m_queue.begin()
			, end(m_queue.end()); i != end; ++i)
		{
			if (!i->connecting) continue;
			if (i->expires > max_timeout) max_timeout = i->expires;
		}
		if (max_timeout == min_time()) return 0.f;
		return total_milliseconds(max_timeout - time_now_hires()) / 1000.f;
	}
#endif

#ifdef TORRENT_DEBUG
	void check_invariant() const;
#endif

private:

	typedef mutex mutex_t;

	void try_connect(mutex_t::scoped_lock& l);
	void on_timeout(error_code const& e);
	void on_try_connect();

	struct entry
	{
		entry(): connecting(false), ticket(0), expires(max_time()), priority(0) {}
		// called when the connection is initiated
		// this is when the timeout countdown starts
		// TODO: if we don't actually need the connection queue
		// to hold ownership of objects, replace these boost functions
		// with pointer to a pure virtual interface class
		boost::function<void(int)> on_connect;
		// called if done hasn't been called within the timeout
		// or if the connection queue aborts. This means there
		// are 3 different interleaves of these function calls:
		// 1. on_connect
		// 2. on_connect, on_timeout
		// 3. on_timeout
		boost::function<void()> on_timeout;
		bool connecting;
		int ticket;
		ptime expires;
		time_duration timeout;
		int priority;
	};

	// TODO: split this into a queue and connecting map. The key for the map
	// is the ticket. Most field in entry would only be necessary for the
	// connecting map.
	std::list<entry> m_queue;

	// the next ticket id a connection will be given
	int m_next_ticket;
	int m_num_connecting;
	int m_half_open_limit;
	bool m_abort;

	// the number of outstanding timers
	int m_num_timers;

	deadline_timer m_timer;

	mutable mutex_t m_mutex;

#ifdef TORRENT_DEBUG
	bool m_in_timeout_function;
#endif
#ifdef TORRENT_CONNECTION_LOGGING
	std::ofstream m_log;
#endif
};

}

#endif

<commit_msg>remove comments of things that have been done in upstream branches<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_CONNECTION_QUEUE
#define TORRENT_CONNECTION_QUEUE

#include <list>
#include <boost/function/function1.hpp>
#include <boost/function/function0.hpp>
#include <boost/noncopyable.hpp>
#include "libtorrent/io_service.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/deadline_timer.hpp"

#ifdef TORRENT_CONNECTION_LOGGING
#include <fstream>
#endif

#include "libtorrent/thread.hpp"

namespace libtorrent
{

class TORRENT_EXTRA_EXPORT connection_queue : public boost::noncopyable
{
public:
	connection_queue(io_service& ios);

	// if there are no free slots, returns the negative
	// number of queued up connections
	int free_slots() const;

	void enqueue(boost::function<void(int)> const& on_connect
		, boost::function<void()> const& on_timeout
		, time_duration timeout, int priority = 0);
	void done(int ticket);
	void limit(int limit);
	int limit() const;
	void close();
	int size() const { return m_queue.size(); }
	int num_connecting() const { return m_num_connecting; }
#if defined TORRENT_ASIO_DEBUGGING
	float next_timeout() const { return total_milliseconds(m_timer.expires_at() - time_now_hires()) / 1000.f; }
	float max_timeout() const
	{
		ptime max_timeout = min_time();
		for (std::list<entry>::const_iterator i = m_queue.begin()
			, end(m_queue.end()); i != end; ++i)
		{
			if (!i->connecting) continue;
			if (i->expires > max_timeout) max_timeout = i->expires;
		}
		if (max_timeout == min_time()) return 0.f;
		return total_milliseconds(max_timeout - time_now_hires()) / 1000.f;
	}
#endif

#ifdef TORRENT_DEBUG
	void check_invariant() const;
#endif

private:

	typedef mutex mutex_t;

	void try_connect(mutex_t::scoped_lock& l);
	void on_timeout(error_code const& e);
	void on_try_connect();

	struct entry
	{
		entry(): connecting(false), ticket(0), expires(max_time()), priority(0) {}
		// called when the connection is initiated
		// this is when the timeout countdown starts
		boost::function<void(int)> on_connect;
		// called if done hasn't been called within the timeout
		// or if the connection queue aborts. This means there
		// are 3 different interleaves of these function calls:
		// 1. on_connect
		// 2. on_connect, on_timeout
		// 3. on_timeout
		boost::function<void()> on_timeout;
		bool connecting;
		int ticket;
		ptime expires;
		time_duration timeout;
		int priority;
	};

	std::list<entry> m_queue;

	// the next ticket id a connection will be given
	int m_next_ticket;
	int m_num_connecting;
	int m_half_open_limit;
	bool m_abort;

	// the number of outstanding timers
	int m_num_timers;

	deadline_timer m_timer;

	mutable mutex_t m_mutex;

#ifdef TORRENT_DEBUG
	bool m_in_timeout_function;
#endif
#ifdef TORRENT_CONNECTION_LOGGING
	std::ofstream m_log;
#endif
};

}

#endif

<|endoftext|>


<commit_before>#include "graph.hpp"
#include <stack>
#include <queue>
#include <algorithm>

#define N 32

using namespace std;

shared_ptr<Vertex> Graph::getVertex(std::string name) const {
  auto it = this->vertices.begin();
  for (; it != this->vertices.end(); it++) {
    if ((*it)->getName() == name) break;
  }
  return (it != this->vertices.end()) ? *it : nullptr;

}

Graph::Graph(vector<tuple<string, int>> vertices,
	     vector<tuple<string, string, int>> edges,
	     bool directed=false) {

  this->directed = directed; 	// Is the graph directed?

  // Build the vertices
  for (auto it = vertices.begin(); it != vertices.end(); it++)
    this->vertices.push_back(make_shared<Vertex>(get<1>(*it), get<0>(*it)));

  for (auto it = edges.begin(); it != edges.end(); it++)
    this->edges.push_back(make_shared<Edge>(get<2>(*it),
				       Graph::getVertex(get<0>(*it)),
				       Graph::getVertex(get<1>(*it))));
  // Now make the adjacency list for the vertices
  for (auto it = this->vertices.begin(); it != this->vertices.end(); it++) {
    vector<shared_ptr<Edge>> ie;
    for (auto eit = this->edges.begin(); eit != this->edges.end(); eit++) {
      if ((*it)->getName() == (*eit)->second()->getName()
	  || (*it)->getName() == (*eit)->first()->getName())
	ie.push_back(*eit);
    }
    (*it)->setIEdges(ie);
  }
}

shared_ptr<Vertex> Edge::opposite(string v) {
  if (v == this->first()->getName())
    return this->second();
  else return this->first();
}

vector<shared_ptr<Vertex>> Vertex::neighbors() {
  vector<shared_ptr<Vertex>> ret;
  for (auto it = this->incidentEdges.begin(); it != this->incidentEdges.end(); it++) {
    ret.push_back((*it)->opposite(this->getName()));
  }
  return ret;
}

void print(shared_ptr<Vertex> v) {
  cout << " name: " << v->getName() << endl;
}

// DFS for the graph with a function.
template<typename F>
static void doDFS(Graph g, shared_ptr<Vertex> start, F fun) {
  stack<shared_ptr<Vertex>> s;
  s.push(start);

  do
    {
      // First get all the neighbors
      shared_ptr<Vertex> n = s.top();
      // Print the name of the node
      fun(n); // XXX: Look this is a lambda (functor in C++ parlance)
	      // from the argument.
      s.pop(); 			// Very bad stack interface of C++!
      n->setVisited(true);
      vector<shared_ptr<Vertex>> vns = n->neighbors();
      for (auto it = vns.begin(); it != vns.end(); it++) {
	if (!(*it)->getVisited()) {
	  s.push(*it);
	  (*it)->setVisited(true);
	}
      }
    } while (!s.empty());

  g.resetVisited();
}

// Topological sort in a directed graph
template<void (*fun)(shared_ptr<Vertex>)>
static void topological_sort(Graph g) {
  if (!g.getDirected()) return;

  // First make the degree for the vertex.
  queue<shared_ptr<Vertex>> start_vertices;
  vector<shared_ptr<Vertex>> mvertices = g.getVertices();
  for (auto it = mvertices.begin(); it != mvertices.end(); ++it) {
    vector<shared_ptr<Edge>> ves = (*it)->getIEdges();
    for (auto eit = ves.begin(); eit != ves.end(); ++eit) {
      // Increment your degree if you are the second in the incident-edge
      if ((*eit)->second()->getName() == (*it)->getName())
	(*it)->degree += 1;
    }
    if ((*it)->degree == 0) start_vertices.push(g.getVertex((*it)->getName()));
  }
  // Now we can start going through and doing the actual topological sort.
  do
    {
      // Process vertices
      shared_ptr<Vertex> el = start_vertices.front();
      start_vertices.pop(); 	// C++'s horrible API!
      fun(el); // XXX: Look this is a function pointer from the
	       // template argument.

      // Get all its neighbors and if their degree is 0, then push
      // them onto the queue.
      vector<shared_ptr<Vertex>> eln = el->neighbors();
      for (auto it = eln.begin(); it != eln.end(); ++it) {
	(*it)->degree -= 1;
	if ((*it)->degree == 0) start_vertices.push(*it);
      }
    } while (!start_vertices.empty());

}

vector<shared_ptr<Vertex>> mst (shared_ptr<Vertex> p, vector<shared_ptr<Vertex>> gvs) {
  vector<shared_ptr<Vertex>> ret;
  // XXX: Don't forget to remove the parent from the gvs
  auto it = gvs.begin();
  vector<decltype(it)> vits;
  for (; it != gvs.end(); ++it){
    if ((*it)->dist.second->getName() == p->getName()) {
      vits.push_back(it);
      ret.push_back(*it);
    }
  }

  // Now delete the indices from gvs.
  for (auto it = vits.begin(); it != vits.end(); ++it)
    gvs.erase(*it);

  return ret;
}

// XXX: shortest path and MST together
vector<shared_ptr<Vertex>> sp_mst(Graph g, shared_ptr<Vertex> start) {
  // We need to use a priority queue.

  // Initialize the start vertex distance to zero.
  start->dist.first = 0;
  start->dist.second = nullptr;

  // Declare a pq with a comparator.
  auto comp = [](const shared_ptr<Vertex> e1,
		 const shared_ptr<Vertex> e2){
    return e1->dist.first > e2->dist.first;
  };
  priority_queue<shared_ptr<Vertex>,
		 vector<shared_ptr<Vertex>>,
		 decltype(comp)> pq(comp);
  pq.push(start);

  do
    {
      // First get all the neighbors
      shared_ptr<Vertex> me = pq.top();
      vector<shared_ptr<Edge>> ie = me->getIEdges();
      pq.pop(); 		// remove the top from the pq.
      // Expand the distance for each neighbor.
      for(shared_ptr<Edge> x : ie) {
	shared_ptr<Vertex> men = x->opposite(me->getName());
	unsigned xw = x->getWeight();
	if (!men->getVisited() && men->dist.first > me->dist.first + xw) {
	  men->dist.first = me->dist.first+xw;
	  men->dist.second = me;
	  pq.push(men); 	// FIXME: can add same vertex again!
	}
      }
      me->setVisited(true);
    } while (!pq.empty());

  // Build the minimum spanning tree
  vector<shared_ptr<Vertex>> gvs = g.getVertices();
  vector<shared_ptr<Vertex>> q;
  q.push_back (start);

  // remove start from gvs.
  auto it = gvs.begin();
  for ( ; it != gvs.end(); ++it)
    if ((*it) == start) break;
  // remove it from gvs.
  gvs.erase(it);

  unsigned counter = 0;
  for (; counter < q.size(); ++counter) {
    auto nn = mst(q[counter], gvs);
    for (auto x: nn)
      q.push_back(x);
  }
  return q;

}

// XXX: Independent sets (dual of cliques).
vector<shared_ptr<Vertex>> independent_sets (Graph g){
  vector<shared_ptr<Vertex>> ret;
  vector<shared_ptr<Vertex>> gvs = g.getVertices();
  vector<shared_ptr<Edge>> ges = g.getEdges();

  return ret;
}

int main(void)
{
  // Test program.
  vector<tuple<string, int>> vertices = {make_tuple("a", 1), make_tuple("b", 2),
					 make_tuple("c", 3), make_tuple("d", 4)};
  vector<tuple<string, string, int>> edges = {make_tuple("a", "b", 5), make_tuple("a", "c", 1),
					      make_tuple("a", "d", 4), make_tuple("c", "d", 2),
					      make_tuple("d", "b", 3)};

  // This is the graph.
  Graph g(vertices, edges, false);
  vector<shared_ptr<Vertex>> mv = g.getVertices();

  // Print the graph using dfs and a std::copy_backward(std::begin(container), std::end(container), std::end(container));

  cout  << "DFS" << endl;
  // Here lambda is most likely also inlined.
  doDFS(g, g.getVertex("a"), [](shared_ptr<Vertex> x) -> void {cout << x->getName() << endl;});

  // make the graph directed.
  g.setDirected(true);

  // Do topological sort.
  cout  << "Topological sort" << endl;
  // Here print should be inlined -- passing print as a function pointer
  // at compile time as a template argument.
  topological_sort<print>(g);

  // Dijkstra's shortest path and minimum spanning tree together
  vector<shared_ptr<Vertex>> tree = sp_mst(g, g.getVertex("a"));
  cout << "Done mst" << "\n";

  // Print the tree
  for (auto x : tree)
    cout << x->getName() << " ";
  cout << "\n";

  // Independent sets
  independent_sets(g);

  return 0;
}
<commit_msg>Updated the independent set algo, still need to check it.<commit_after>#include "graph.hpp"
#include <stack>
#include <queue>
#include <algorithm>

#define N 32

using namespace std;

shared_ptr<Vertex> Graph::getVertex(std::string name) const {
  auto it = this->vertices.begin();
  for (; it != this->vertices.end(); it++) {
    if ((*it)->getName() == name) break;
  }
  return (it != this->vertices.end()) ? *it : nullptr;

}

Graph::Graph(vector<tuple<string, int>> vertices,
	     vector<tuple<string, string, int>> edges,
	     bool directed=false) {

  this->directed = directed; 	// Is the graph directed?

  // Build the vertices
  for (auto it = vertices.begin(); it != vertices.end(); it++)
    this->vertices.push_back(make_shared<Vertex>(get<1>(*it), get<0>(*it)));

  for (auto it = edges.begin(); it != edges.end(); it++)
    this->edges.push_back(make_shared<Edge>(get<2>(*it),
				       Graph::getVertex(get<0>(*it)),
				       Graph::getVertex(get<1>(*it))));
  // Now make the adjacency list for the vertices
  for (auto it = this->vertices.begin(); it != this->vertices.end(); it++) {
    vector<shared_ptr<Edge>> ie;
    for (auto eit = this->edges.begin(); eit != this->edges.end(); eit++) {
      if ((*it)->getName() == (*eit)->second()->getName()
	  || (*it)->getName() == (*eit)->first()->getName())
	ie.push_back(*eit);
    }
    (*it)->setIEdges(ie);
  }
}

shared_ptr<Vertex> Edge::opposite(string v) {
  if (v == this->first()->getName())
    return this->second();
  else return this->first();
}

vector<shared_ptr<Vertex>> Vertex::neighbors() {
  vector<shared_ptr<Vertex>> ret;
  for (auto it = this->incidentEdges.begin(); it != this->incidentEdges.end(); it++) {
    ret.push_back((*it)->opposite(this->getName()));
  }
  return ret;
}

void print(shared_ptr<Vertex> v) {
  cout << " name: " << v->getName() << endl;
}

// DFS for the graph with a function.
template<typename F>
static void doDFS(Graph g, shared_ptr<Vertex> start, F fun) {
  stack<shared_ptr<Vertex>> s;
  s.push(start);

  do
    {
      // First get all the neighbors
      shared_ptr<Vertex> n = s.top();
      // Print the name of the node
      fun(n); // XXX: Look this is a lambda (functor in C++ parlance)
	      // from the argument.
      s.pop(); 			// Very bad stack interface of C++!
      n->setVisited(true);
      vector<shared_ptr<Vertex>> vns = n->neighbors();
      for (auto it = vns.begin(); it != vns.end(); it++) {
	if (!(*it)->getVisited()) {
	  s.push(*it);
	  (*it)->setVisited(true);
	}
      }
    } while (!s.empty());

  g.resetVisited();
}

// Topological sort in a directed graph
template<void (*fun)(shared_ptr<Vertex>)>
static void topological_sort(Graph g) {
  if (!g.getDirected()) return;

  // First make the degree for the vertex.
  queue<shared_ptr<Vertex>> start_vertices;
  vector<shared_ptr<Vertex>> mvertices = g.getVertices();
  for (auto it = mvertices.begin(); it != mvertices.end(); ++it) {
    vector<shared_ptr<Edge>> ves = (*it)->getIEdges();
    for (auto eit = ves.begin(); eit != ves.end(); ++eit) {
      // Increment your degree if you are the second in the incident-edge
      if ((*eit)->second()->getName() == (*it)->getName())
	(*it)->degree += 1;
    }
    if ((*it)->degree == 0) start_vertices.push(g.getVertex((*it)->getName()));
  }
  // Now we can start going through and doing the actual topological sort.
  do
    {
      // Process vertices
      shared_ptr<Vertex> el = start_vertices.front();
      start_vertices.pop(); 	// C++'s horrible API!
      fun(el); // XXX: Look this is a function pointer from the
	       // template argument.

      // Get all its neighbors and if their degree is 0, then push
      // them onto the queue.
      vector<shared_ptr<Vertex>> eln = el->neighbors();
      for (auto it = eln.begin(); it != eln.end(); ++it) {
	(*it)->degree -= 1;
	if ((*it)->degree == 0) start_vertices.push(*it);
      }
    } while (!start_vertices.empty());

}

vector<shared_ptr<Vertex>> mst (shared_ptr<Vertex> p, vector<shared_ptr<Vertex>> gvs) {
  vector<shared_ptr<Vertex>> ret;
  // XXX: Don't forget to remove the parent from the gvs
  auto it = gvs.begin();
  vector<decltype(it)> vits;
  for (; it != gvs.end(); ++it){
    if ((*it)->dist.second->getName() == p->getName()) {
      vits.push_back(it);
      ret.push_back(*it);
    }
  }

  // Now delete the indices from gvs.
  for (auto it = vits.begin(); it != vits.end(); ++it)
    gvs.erase(*it);

  return ret;
}

// XXX: shortest path and MST together
vector<shared_ptr<Vertex>> sp_mst(Graph g, shared_ptr<Vertex> start) {
  // We need to use a priority queue.

  // Initialize the start vertex distance to zero.
  start->dist.first = 0;
  start->dist.second = nullptr;

  // Declare a pq with a comparator.
  auto comp = [](const shared_ptr<Vertex> e1,
		 const shared_ptr<Vertex> e2){
    return e1->dist.first > e2->dist.first;
  };
  priority_queue<shared_ptr<Vertex>,
		 vector<shared_ptr<Vertex>>,
		 decltype(comp)> pq(comp);
  pq.push(start);

  do
    {
      // First get all the neighbors
      shared_ptr<Vertex> me = pq.top();
      vector<shared_ptr<Edge>> ie = me->getIEdges();
      pq.pop(); 		// remove the top from the pq.
      // Expand the distance for each neighbor.
      for(shared_ptr<Edge> x : ie) {
	shared_ptr<Vertex> men = x->opposite(me->getName());
	unsigned xw = x->getWeight();
	if (!men->getVisited() && men->dist.first > me->dist.first + xw) {
	  men->dist.first = me->dist.first+xw;
	  men->dist.second = me;
	  pq.push(men); 	// FIXME: can add same vertex again!
	}
      }
      me->setVisited(true);
    } while (!pq.empty());

  // Build the minimum spanning tree
  vector<shared_ptr<Vertex>> gvs = g.getVertices();
  vector<shared_ptr<Vertex>> q;
  q.push_back (start);

  // remove start from gvs.
  auto it = gvs.begin();
  for ( ; it != gvs.end(); ++it)
    if ((*it) == start) break;
  // remove it from gvs.
  gvs.erase(it);

  unsigned counter = 0;
  for (; counter < q.size(); ++counter) {
    auto nn = mst(q[counter], gvs);
    for (auto x: nn)
      q.push_back(x);
  }
  return q;

}

// XXX: Independent sets (dual of cliques).
vector<shared_ptr<Vertex>> independent_sets (Graph g){
  vector<shared_ptr<Vertex>> ret {};
  vector<shared_ptr<Vertex>> gvs = g.getVertices();
  vector<shared_ptr<Edge>> ges = g.getEdges();
  vector<shared_ptr<Vertex>> gesv;
  for (auto it = ges.begin(); it != ges.end(); ++it) {
    gesv.push_back((*it)->first());
    gesv.push_back((*it)->second());
  }
  auto last = unique(gesv.begin(), gesv.end());
  gesv.erase(last, gesv.end()); // removed duplicates.

  vector<shared_ptr<Vertex>> intersect;
  // Now if intersecting gesv and gvs is null then we can just return.
  set_intersection(gvs.begin(), gvs.end(),
		   gesv.begin(), gesv.end(),
		   back_inserter(intersect));

  if(intersect.empty()) return ret;

  // Else we continue.
  // All the connected edges in the graph.
  unsigned pcount = 0;
  for (unsigned i = (2 << (gvs.size() - 1))-1; i >=1 ; --i) {
    bitset<N> bb(i);  		// FIXME: This is very annoying in C++
    vector<shared_ptr<Vertex>> fe;
    // Now just get the length of bits that we need.
    unsigned ccount = 0;
    for (int j = gvs.size()-1; j >= 0; --j)
      if (j == 1) {
	++ccount;
	fe.push_back(gvs[j]);
      }
    // Now check for intersection.
    set_intersection(fe.begin(), fe.end(),
		     gesv.begin(), gesv.end(),
		     back_inserter(intersect));

    // Now check if we should insert this in -- we have to go through
    // all, because we are using binary encoding of numbers!!
    if(intersect.size() == fe.size() && (ccount > pcount))
      ret = fe;
  }
  return ret;
}

int main(void)
{
  // Test program.
  vector<tuple<string, int>> vertices = {make_tuple("a", 1), make_tuple("b", 2),
					 make_tuple("c", 3), make_tuple("d", 4)};
  vector<tuple<string, string, int>> edges = {make_tuple("a", "b", 5), make_tuple("a", "c", 1),
					      make_tuple("a", "d", 4), make_tuple("c", "d", 2),
					      make_tuple("d", "b", 3)};

  // This is the graph.
  Graph g(vertices, edges, false);
  vector<shared_ptr<Vertex>> mv = g.getVertices();

  // Print the graph using dfs and a std::copy_backward(std::begin(container), std::end(container), std::end(container));

  cout  << "DFS" << endl;
  // Here lambda is most likely also inlined.
  doDFS(g, g.getVertex("a"), [](shared_ptr<Vertex> x) -> void {cout << x->getName() << endl;});

  // make the graph directed.
  g.setDirected(true);

  // Do topological sort.
  cout  << "Topological sort" << endl;
  // Here print should be inlined -- passing print as a function pointer
  // at compile time as a template argument.
  topological_sort<print>(g);

  // Dijkstra's shortest path and minimum spanning tree together
  vector<shared_ptr<Vertex>> tree = sp_mst(g, g.getVertex("a"));
  cout << "Done mst" << "\n";

  // Print the tree
  for (auto x : tree)
    cout << x->getName() << " ";
  cout << "\n";

  // Independent sets
  independent_sets(g);

  return 0;
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_FONT_ENGINE_FREETYPE_HPP
#define MAPNIK_FONT_ENGINE_FREETYPE_HPP

// mapnik
#include <mapnik/color.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/font_set.hpp>
#include <mapnik/char_info.hpp>
#include <mapnik/pixel_position.hpp>

// freetype2
extern "C"
{
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_STROKER_H
}

// boost
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/utility.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#ifdef MAPNIK_THREADSAFE
#include <boost/thread/mutex.hpp>
#endif

// stl
#include <string>
#include <vector>
#include <map>
#include <iostream>
#include <algorithm>

// uci
#include <unicode/unistr.h>

namespace mapnik
{
class font_face;
class text_path;
class string_info;

typedef boost::shared_ptr<font_face> face_ptr;

class MAPNIK_DECL font_glyph : private boost::noncopyable
{
public:
    font_glyph(face_ptr face, unsigned index)
        : face_(face), index_(index) {}

    face_ptr get_face() const
    {
        return face_;
    }

    unsigned get_index() const
    {
        return index_;
    }
private:
    face_ptr face_;
    unsigned index_;
};

typedef boost::shared_ptr<font_glyph> glyph_ptr;

class font_face : boost::noncopyable
{
public:
    font_face(FT_Face face)
        : face_(face) {}

    std::string  family_name() const
    {
        return std::string(face_->family_name);
    }

    std::string  style_name() const
    {
        return std::string(face_->style_name);
    }

    FT_GlyphSlot glyph() const
    {
        return face_->glyph;
    }

    FT_Face get_face() const
    {
        return face_;
    }

    unsigned get_char(unsigned c) const
    {
        return FT_Get_Char_Index(face_, c);
    }

    bool set_pixel_sizes(unsigned size)
    {
        if (! FT_Set_Pixel_Sizes( face_, 0, size ))
            return true;
        return false;
    }

    bool set_character_sizes(float size)
    {
        if ( !FT_Set_Char_Size(face_,0,(FT_F26Dot6)(size * (1<<6)),0,0))
            return true;
        return false;
    }

    ~font_face()
    {
#ifdef MAPNIK_DEBUG
        std::clog << "~font_face: Clean up face \"" << family_name()
                  << " " << style_name() << "\"" << std::endl;
#endif
        FT_Done_Face(face_);
    }

private:
    FT_Face face_;
};

class MAPNIK_DECL font_face_set : private boost::noncopyable
{
public:
    font_face_set(void)
        : faces_(),
        dimension_cache_() {}

    void add(face_ptr face)
    {
        faces_.push_back(face);
        dimension_cache_.clear(); //Make sure we don't use old cached data
    }

    unsigned size() const
    {
        return faces_.size();
    }

    glyph_ptr get_glyph(unsigned c) const
    {
        std::vector<face_ptr>::const_iterator face = faces_.begin();
        std::vector<face_ptr>::const_iterator end = faces_.end();
        for (; face != end; ++face)
        {
            FT_UInt g = (*face)->get_char(c);
            if (g) return boost::make_shared<font_glyph>(*face, g);
        }

        // Final fallback to empty square if nothing better in any font
        return boost::make_shared<font_glyph>(*faces_.begin(), 0);
    }

    char_info character_dimensions(const unsigned c);

    void get_string_info(string_info & info, UnicodeString const& ustr, char_properties *format);

    void set_pixel_sizes(unsigned size)
    {
        for (std::vector<face_ptr>::iterator face = faces_.begin(); face != faces_.end(); ++face)
        {
            (*face)->set_pixel_sizes(size);
        }
    }

    void set_character_sizes(float size)
    {
        for (std::vector<face_ptr>::iterator face = faces_.begin(); face != faces_.end(); ++face)
        {
            (*face)->set_character_sizes(size);
        }
    }
private:
    std::vector<face_ptr> faces_;
    std::map<unsigned, char_info> dimension_cache_;
};

// FT_Stroker wrapper
class stroker : boost::noncopyable
{
public:
    explicit stroker(FT_Stroker s)
        : s_(s) {}

    void init(double radius)
    {
        FT_Stroker_Set(s_, (FT_Fixed) (radius * (1<<6)),
                       FT_STROKER_LINECAP_ROUND,
                       FT_STROKER_LINEJOIN_ROUND,
                       0);
    }

    FT_Stroker const& get() const
    {
        return s_;
    }

    ~stroker()
    {
#ifdef MAPNIK_DEBUG
        std::clog << "~stroker: destroy stroker:" << s_ << std::endl;
#endif
        FT_Stroker_Done(s_);
    }
private:
    FT_Stroker s_;
};

typedef boost::shared_ptr<font_face_set> face_set_ptr;
typedef boost::shared_ptr<stroker> stroker_ptr;

class MAPNIK_DECL freetype_engine
{
public:
    static bool is_font_file(std::string const& file_name);
    static bool register_font(std::string const& file_name);
    static bool register_fonts(std::string const& dir, bool recurse = false);
    static std::vector<std::string> face_names();
    static std::map<std::string,std::pair<int,std::string> > const& get_mapping();
    face_ptr create_face(std::string const& family_name);
    stroker_ptr create_stroker();
    virtual ~freetype_engine();
    freetype_engine();
private:
    FT_Library library_;
#ifdef MAPNIK_THREADSAFE
    static boost::mutex mutex_;
#endif
    static std::map<std::string,std::pair<int,std::string> > name2file_;
};

template <typename T>
class MAPNIK_DECL face_manager : private boost::noncopyable
{
    typedef T font_engine_type;
    typedef std::map<std::string,face_ptr> face_ptr_cache_type;

public:
    face_manager(T & engine)
        : engine_(engine),
        stroker_(engine_.create_stroker())  {}

    face_ptr get_face(std::string const& name)
    {
        face_ptr_cache_type::iterator itr;
        itr = face_ptr_cache_.find(name);
        if (itr != face_ptr_cache_.end())
        {
            return itr->second;
        }
        else
        {
            face_ptr face = engine_.create_face(name);
            if (face)
            {
                face_ptr_cache_.insert(make_pair(name,face));
            }
            return face;
        }
    }

    face_set_ptr get_face_set(std::string const& name)
    {
        face_set_ptr face_set = boost::make_shared<font_face_set>();
        if (face_ptr face = get_face(name))
        {
            face_set->add(face);
        }
        return face_set;
    }

    face_set_ptr get_face_set(font_set const& fset)
    {
        std::vector<std::string> const& names = fset.get_face_names();
        face_set_ptr face_set = boost::make_shared<font_face_set>();
        for (std::vector<std::string>::const_iterator name = names.begin(); name != names.end(); ++name)
        {
            if (face_ptr face = get_face(*name))
            {
                face_set->add(face);
            } else {
#ifdef MAPNIK_DEBUG
                std::cerr << "Failed to find face '" << *name << "' in font set '" << fset.get_name() << "'\n";
#endif
            }
        }
        return face_set;
    }

    face_set_ptr get_face_set(std::string const& name, font_set const& fset)
    {
        if (fset.size() > 0)
        {
            return get_face_set(fset);
        }
        else
        {
            return get_face_set(name);
        }
    }

    stroker_ptr get_stroker()
    {
        return stroker_;
    }

private:
    face_ptr_cache_type face_ptr_cache_;
    font_engine_type & engine_;
    stroker_ptr stroker_;
};

template <typename T>
struct text_renderer : private boost::noncopyable
{
    struct glyph_t : boost::noncopyable
    {
        FT_Glyph image;
        char_properties *properties;
        glyph_t(FT_Glyph image_, char_properties *properties_) : image(image_), properties(properties_) {}
        ~glyph_t () { FT_Done_Glyph(image);}
    };

    typedef boost::ptr_vector<glyph_t> glyphs_t;
    typedef T pixmap_type;

    text_renderer (pixmap_type & pixmap, face_manager<freetype_engine> &font_manager_, stroker & s);
    box2d<double> prepare_glyphs(text_path *path);
    void render(pixel_position pos);
    void render_id(int feature_id, pixel_position pos, double min_radius=1.0);

private:
    void render_bitmap(FT_Bitmap *bitmap, unsigned rgba, int x, int y, double opacity)
    {
        int x_max=x+bitmap->width;
        int y_max=y+bitmap->rows;
        int i,p,j,q;

        for (i=x,p=0;i<x_max;++i,++p)
        {
            for (j=y,q=0;j<y_max;++j,++q)
            {
                int gray=bitmap->buffer[q*bitmap->width+p];
                if (gray)
                {
                    pixmap_.blendPixel2(i, j, rgba, gray, opacity);
                }
            }
        }
    }

    void render_bitmap_id(FT_Bitmap *bitmap,int feature_id,int x,int y)
    {
        int x_max=x+bitmap->width;
        int y_max=y+bitmap->rows;
        int i,p,j,q;

        for (i=x,p=0;i<x_max;++i,++p)
        {
            for (j=y,q=0;j<y_max;++j,++q)
            {
                int gray=bitmap->buffer[q*bitmap->width+p];
                if (gray)
                {
                    pixmap_.setPixel(i,j,feature_id);
                    //pixmap_.blendPixel2(i,j,rgba,gray,opacity_);
                }
            }
        }
    }

    pixmap_type & pixmap_;
    face_manager<freetype_engine> &font_manager_;
    stroker & stroker_;
    glyphs_t glyphs_;
};
typedef face_manager<freetype_engine> face_manager_freetype;
}

#endif // MAPNIK_FONT_ENGINE_FREETYPE_HPP
<commit_msg>even better, use BOOST_FOREACH<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_FONT_ENGINE_FREETYPE_HPP
#define MAPNIK_FONT_ENGINE_FREETYPE_HPP

// mapnik
#include <mapnik/color.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/font_set.hpp>
#include <mapnik/char_info.hpp>
#include <mapnik/pixel_position.hpp>

// freetype2
extern "C"
{
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_STROKER_H
}

// boost
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/utility.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/foreach.hpp>
#ifdef MAPNIK_THREADSAFE
#include <boost/thread/mutex.hpp>
#endif

// stl
#include <string>
#include <vector>
#include <map>
#include <iostream>
#include <algorithm>

// uci
#include <unicode/unistr.h>

namespace mapnik
{
class font_face;
class text_path;
class string_info;

typedef boost::shared_ptr<font_face> face_ptr;

class MAPNIK_DECL font_glyph : private boost::noncopyable
{
public:
    font_glyph(face_ptr face, unsigned index)
        : face_(face), index_(index) {}

    face_ptr get_face() const
    {
        return face_;
    }

    unsigned get_index() const
    {
        return index_;
    }
private:
    face_ptr face_;
    unsigned index_;
};

typedef boost::shared_ptr<font_glyph> glyph_ptr;

class font_face : boost::noncopyable
{
public:
    font_face(FT_Face face)
        : face_(face) {}

    std::string  family_name() const
    {
        return std::string(face_->family_name);
    }

    std::string  style_name() const
    {
        return std::string(face_->style_name);
    }

    FT_GlyphSlot glyph() const
    {
        return face_->glyph;
    }

    FT_Face get_face() const
    {
        return face_;
    }

    unsigned get_char(unsigned c) const
    {
        return FT_Get_Char_Index(face_, c);
    }

    bool set_pixel_sizes(unsigned size)
    {
        if (! FT_Set_Pixel_Sizes( face_, 0, size ))
            return true;
        return false;
    }

    bool set_character_sizes(float size)
    {
        if ( !FT_Set_Char_Size(face_,0,(FT_F26Dot6)(size * (1<<6)),0,0))
            return true;
        return false;
    }

    ~font_face()
    {
#ifdef MAPNIK_DEBUG
        std::clog << "~font_face: Clean up face \"" << family_name()
                  << " " << style_name() << "\"" << std::endl;
#endif
        FT_Done_Face(face_);
    }

private:
    FT_Face face_;
};

class MAPNIK_DECL font_face_set : private boost::noncopyable
{
public:
    font_face_set(void)
        : faces_(),
        dimension_cache_() {}

    void add(face_ptr face)
    {
        faces_.push_back(face);
        dimension_cache_.clear(); //Make sure we don't use old cached data
    }

    unsigned size() const
    {
        return faces_.size();
    }

    glyph_ptr get_glyph(unsigned c) const
    {
        BOOST_FOREACH ( face_ptr const& face, faces_)
        {
            FT_UInt g = face->get_char(c);
            if (g) return boost::make_shared<font_glyph>(face, g);
        }

        // Final fallback to empty square if nothing better in any font
        return boost::make_shared<font_glyph>(*faces_.begin(), 0);
    }

    char_info character_dimensions(const unsigned c);

    void get_string_info(string_info & info, UnicodeString const& ustr, char_properties *format);

    void set_pixel_sizes(unsigned size)
    {
        BOOST_FOREACH ( face_ptr const& face, faces_)
        {
            face->set_pixel_sizes(size);
        }
    }

    void set_character_sizes(float size)
    {
        BOOST_FOREACH ( face_ptr const& face, faces_)
        {
            face->set_character_sizes(size);
        }
    }
private:
    std::vector<face_ptr> faces_;
    std::map<unsigned, char_info> dimension_cache_;
};

// FT_Stroker wrapper
class stroker : boost::noncopyable
{
public:
    explicit stroker(FT_Stroker s)
        : s_(s) {}

    void init(double radius)
    {
        FT_Stroker_Set(s_, (FT_Fixed) (radius * (1<<6)),
                       FT_STROKER_LINECAP_ROUND,
                       FT_STROKER_LINEJOIN_ROUND,
                       0);
    }

    FT_Stroker const& get() const
    {
        return s_;
    }

    ~stroker()
    {
#ifdef MAPNIK_DEBUG
        std::clog << "~stroker: destroy stroker:" << s_ << std::endl;
#endif
        FT_Stroker_Done(s_);
    }
private:
    FT_Stroker s_;
};

typedef boost::shared_ptr<font_face_set> face_set_ptr;
typedef boost::shared_ptr<stroker> stroker_ptr;

class MAPNIK_DECL freetype_engine
{
public:
    static bool is_font_file(std::string const& file_name);
    static bool register_font(std::string const& file_name);
    static bool register_fonts(std::string const& dir, bool recurse = false);
    static std::vector<std::string> face_names();
    static std::map<std::string,std::pair<int,std::string> > const& get_mapping();
    face_ptr create_face(std::string const& family_name);
    stroker_ptr create_stroker();
    virtual ~freetype_engine();
    freetype_engine();
private:
    FT_Library library_;
#ifdef MAPNIK_THREADSAFE
    static boost::mutex mutex_;
#endif
    static std::map<std::string,std::pair<int,std::string> > name2file_;
};

template <typename T>
class MAPNIK_DECL face_manager : private boost::noncopyable
{
    typedef T font_engine_type;
    typedef std::map<std::string,face_ptr> face_ptr_cache_type;

public:
    face_manager(T & engine)
        : engine_(engine),
        stroker_(engine_.create_stroker())  {}

    face_ptr get_face(std::string const& name)
    {
        face_ptr_cache_type::iterator itr;
        itr = face_ptr_cache_.find(name);
        if (itr != face_ptr_cache_.end())
        {
            return itr->second;
        }
        else
        {
            face_ptr face = engine_.create_face(name);
            if (face)
            {
                face_ptr_cache_.insert(make_pair(name,face));
            }
            return face;
        }
    }

    face_set_ptr get_face_set(std::string const& name)
    {
        face_set_ptr face_set = boost::make_shared<font_face_set>();
        if (face_ptr face = get_face(name))
        {
            face_set->add(face);
        }
        return face_set;
    }

    face_set_ptr get_face_set(font_set const& fset)
    {
        std::vector<std::string> const& names = fset.get_face_names();
        face_set_ptr face_set = boost::make_shared<font_face_set>();
        for (std::vector<std::string>::const_iterator name = names.begin(); name != names.end(); ++name)
        {
            if (face_ptr face = get_face(*name))
            {
                face_set->add(face);
            } else {
#ifdef MAPNIK_DEBUG
                std::cerr << "Failed to find face '" << *name << "' in font set '" << fset.get_name() << "'\n";
#endif
            }
        }
        return face_set;
    }

    face_set_ptr get_face_set(std::string const& name, font_set const& fset)
    {
        if (fset.size() > 0)
        {
            return get_face_set(fset);
        }
        else
        {
            return get_face_set(name);
        }
    }

    stroker_ptr get_stroker()
    {
        return stroker_;
    }

private:
    face_ptr_cache_type face_ptr_cache_;
    font_engine_type & engine_;
    stroker_ptr stroker_;
};

template <typename T>
struct text_renderer : private boost::noncopyable
{
    struct glyph_t : boost::noncopyable
    {
        FT_Glyph image;
        char_properties *properties;
        glyph_t(FT_Glyph image_, char_properties *properties_) : image(image_), properties(properties_) {}
        ~glyph_t () { FT_Done_Glyph(image);}
    };

    typedef boost::ptr_vector<glyph_t> glyphs_t;
    typedef T pixmap_type;

    text_renderer (pixmap_type & pixmap, face_manager<freetype_engine> &font_manager_, stroker & s);
    box2d<double> prepare_glyphs(text_path *path);
    void render(pixel_position pos);
    void render_id(int feature_id, pixel_position pos, double min_radius=1.0);

private:
    void render_bitmap(FT_Bitmap *bitmap, unsigned rgba, int x, int y, double opacity)
    {
        int x_max=x+bitmap->width;
        int y_max=y+bitmap->rows;
        int i,p,j,q;

        for (i=x,p=0;i<x_max;++i,++p)
        {
            for (j=y,q=0;j<y_max;++j,++q)
            {
                int gray=bitmap->buffer[q*bitmap->width+p];
                if (gray)
                {
                    pixmap_.blendPixel2(i, j, rgba, gray, opacity);
                }
            }
        }
    }

    void render_bitmap_id(FT_Bitmap *bitmap,int feature_id,int x,int y)
    {
        int x_max=x+bitmap->width;
        int y_max=y+bitmap->rows;
        int i,p,j,q;

        for (i=x,p=0;i<x_max;++i,++p)
        {
            for (j=y,q=0;j<y_max;++j,++q)
            {
                int gray=bitmap->buffer[q*bitmap->width+p];
                if (gray)
                {
                    pixmap_.setPixel(i,j,feature_id);
                    //pixmap_.blendPixel2(i,j,rgba,gray,opacity_);
                }
            }
        }
    }

    pixmap_type & pixmap_;
    face_manager<freetype_engine> &font_manager_;
    stroker & stroker_;
    glyphs_t glyphs_;
};
typedef face_manager<freetype_engine> face_manager_freetype;
}

#endif // MAPNIK_FONT_ENGINE_FREETYPE_HPP
<|endoftext|>


<commit_before>#pragma once
#ifndef OPENGM_BRUTEFORCE_HXX
#define OPENGM_BRUTEFORCE_HXX

#include "inference.hxx"
#include "movemaker.hxx"
#include "opengm/inference/visitors/visitor.hxx"

namespace opengm {

template<class GM> class Movemaker;

/// Brute force inference algorithm
///
/// \ingroup inference
template<class GM, class ACC>
class Bruteforce : public Inference<GM, ACC>
{
public:
   typedef ACC AccumulationType;
   typedef GM GraphicalModelType;
   OPENGM_GM_TYPE_TYPEDEFS;
   typedef typename std::vector<LabelType>::const_iterator LabelIterator;
   typedef EmptyVisitor< Bruteforce<GM, ACC> > EmptyVisitorType;
   typedef VerboseVisitor< Bruteforce<GM, ACC> > VerboseVisitorType;
   typedef TimingVisitor< Bruteforce<GM, ACC> > TimingVisitorType;
   class Parameter {};

   Bruteforce(const GraphicalModelType&);
   Bruteforce(const GraphicalModelType&, const Parameter&);
   std::string name() const
      { return "Brute-Force"; }
   const GraphicalModelType& graphicalModel() const
      { return gm_; }
   InferenceTermination infer()
      {
         EmptyVisitorType visitor;
         return infer(visitor);
      }

   template<class VISITOR> InferenceTermination infer(VISITOR &);
   virtual ValueType value() const;
   InferenceTermination arg(std::vector<LabelType>&, const size_t = 1) const;
   void reset();

private:
    const GraphicalModelType& gm_;
    opengm::Movemaker<GraphicalModelType> movemaker_;
    std::vector<LabelType> states_;
    ValueType energy_;
};

template<class GM, class AKK>
Bruteforce<GM, AKK>::Bruteforce
(
    const GraphicalModelType& gm
)
:  gm_(gm),
   movemaker_(Movemaker<GM>(gm)),
   states_(std::vector<typename GM::LabelType>(gm.numberOfVariables() )),
   energy_(typename Bruteforce<GM, AKK>::ValueType())
{
   AKK::neutral(energy_);
}

template<class GM, class AKK>
void
Bruteforce<GM, AKK>::reset()
{
   movemaker_.reset();
   std::fill(states_.begin(), states_.end(), 0);
   AKK::neutral(energy_);
}

template<class GM, class AKK>
Bruteforce<GM, AKK>::Bruteforce
(
   const GraphicalModelType& gm,
   const typename Bruteforce<GM, AKK>::Parameter& param
)
:  gm_(gm),
   movemaker_(Movemaker<GM>(gm)),
   states_(std::vector<typename GM::LabelType>(gm.numberOfVariables())),
   energy_(typename Bruteforce<GM, AKK>::ValueType())
{}

template<class GM, class AKK>
template<class VISITOR>
InferenceTermination
Bruteforce<GM, AKK>::infer
(
   VISITOR & visitor
)
{
   std::vector<LabelType> states(gm_.numberOfVariables());
   std::vector<IndexType> vi(gm_.numberOfVariables());
   for(size_t j=0; j<gm_.numberOfVariables(); ++j) {
       vi[j] = j;
   }
   AccumulationType::neutral(energy_);
   for(;;) {
      ValueType energy = movemaker_.move(vi.begin(), vi.end(), states.begin());
      if(AccumulationType::bop(energy , energy_)) {
         visitor(*this, energy, energy);
         states_ = states;
      }
      AccumulationType::op(energy, energy_);
      bool overflow = true;
      for(size_t j=0; j<gm_.numberOfVariables(); ++j) {
         if( size_t(states[j]+1) < size_t(gm_.numberOfLabels(j))) {
            ++states[j];
            for(size_t k=0; k<j; ++k) {
               states[k] = 0;
            }
            overflow = false;
            break;
         }
      }
      if(overflow) {
         break;
      }
   }
   visitor.end(*this, energy_, energy_);
   return NORMAL;
}

/// \brief return the solution (value)
template<class GM, class ACC>
typename GM::ValueType
Bruteforce<GM, ACC>::value() const
{
   return energy_;
}

template<class GM, class AKK>
inline InferenceTermination
Bruteforce<GM, AKK>::arg
(
   std::vector<LabelType>& states,
   const size_t j
) const
{
   if(j == 1) {
      states = states_; // copy
      return NORMAL;
   }
   else {
      return UNKNOWN;
   }
}

} // namespace opengm

#endif // #ifndef OPENGM_BRUTEFORCE_HXX
<commit_msg>Revert "Fixed problem with non-idempotent semirings in bruteforce"<commit_after>#pragma once
#ifndef OPENGM_BRUTEFORCE_HXX
#define OPENGM_BRUTEFORCE_HXX

#include "inference.hxx"
#include "movemaker.hxx"
#include "opengm/inference/visitors/visitor.hxx"

namespace opengm {

template<class GM> class Movemaker;

/// Brute force inference algorithm
///
/// \ingroup inference
template<class GM, class ACC>
class Bruteforce : public Inference<GM, ACC>
{
public:
   typedef ACC AccumulationType;
   typedef GM GraphicalModelType;
   OPENGM_GM_TYPE_TYPEDEFS;
   typedef typename std::vector<LabelType>::const_iterator LabelIterator;
   typedef EmptyVisitor< Bruteforce<GM, ACC> > EmptyVisitorType;
   typedef VerboseVisitor< Bruteforce<GM, ACC> > VerboseVisitorType;
   typedef TimingVisitor< Bruteforce<GM, ACC> > TimingVisitorType;
   class Parameter {};

   Bruteforce(const GraphicalModelType&);
   Bruteforce(const GraphicalModelType&, const Parameter&);
   std::string name() const
      { return "Brute-Force"; }
   const GraphicalModelType& graphicalModel() const
      { return gm_; }
   InferenceTermination infer()
      {
         EmptyVisitorType visitor;
         return infer(visitor);
      }
   template<class VISITOR> InferenceTermination infer(VISITOR &);
   InferenceTermination arg(std::vector<LabelType>&, const size_t = 1) const;
   void reset();

private:
    const GraphicalModelType& gm_;
    opengm::Movemaker<GraphicalModelType> movemaker_;
    std::vector<LabelType> states_;
    ValueType energy_;
};

template<class GM, class AKK>
Bruteforce<GM, AKK>::Bruteforce
(
    const GraphicalModelType& gm
)
:  gm_(gm),
   movemaker_(Movemaker<GM>(gm)),
   states_(std::vector<typename GM::LabelType>(gm.numberOfVariables() )),
   energy_(typename Bruteforce<GM, AKK>::ValueType())
{
   AKK::neutral(energy_);
}

template<class GM, class AKK>
void
Bruteforce<GM, AKK>::reset()
{
   movemaker_.reset();
   std::fill(states_.begin(), states_.end(), 0);
   AKK::neutral(energy_);
}

template<class GM, class AKK>
Bruteforce<GM, AKK>::Bruteforce
(
   const GraphicalModelType& gm,
   const typename Bruteforce<GM, AKK>::Parameter& param
)
:  gm_(gm),
   movemaker_(Movemaker<GM>(gm)),
   states_(std::vector<typename GM::LabelType>(gm.numberOfVariables())),
   energy_(typename Bruteforce<GM, AKK>::ValueType())
{}

template<class GM, class AKK>
template<class VISITOR>
InferenceTermination
Bruteforce<GM, AKK>::infer
(
   VISITOR & visitor
)
{
   std::vector<LabelType> states(gm_.numberOfVariables());
   std::vector<IndexType> vi(gm_.numberOfVariables());
   for(size_t j=0; j<gm_.numberOfVariables(); ++j) {
       vi[j] = j;
   }
   energy_ = movemaker_.move(vi.begin(), vi.end(), states.begin());
   visitor.begin(*this, energy_, energy_);
   for(;;) {
      ValueType energy = movemaker_.move(vi.begin(), vi.end(), states.begin());
      if(AccumulationType::bop(energy , energy_)) {
         visitor(*this, energy, energy);
         energy_ = energy;
         states_ = states;
      }
      bool overflow = true;
      for(size_t j=0; j<gm_.numberOfVariables(); ++j) {
         if( size_t(states[j]+1) < size_t(gm_.numberOfLabels(j))) {
            ++states[j];
            for(size_t k=0; k<j; ++k) {
               states[k] = 0;
            }
            overflow = false;
            break;
         }
      }
      if(overflow) {
         break;
      }
   }
   visitor.end(*this, energy_, energy_);
   return NORMAL;
}

template<class GM, class AKK>
inline InferenceTermination
Bruteforce<GM, AKK>::arg
(
   std::vector<LabelType>& states,
   const size_t j
) const
{
   if(j == 1) {
      states = states_; // copy
      return NORMAL;
   }
   else {
      return UNKNOWN;
   }
}

} // namespace opengm

#endif // #ifndef OPENGM_BRUTEFORCE_HXX
<|endoftext|>


<commit_before>#ifndef __WSPP_UTIL_TEMPLATE_RENDERER_HPP__
#define __WSPP_UTIL_TEMPLATE_RENDERER_HPP__

#include <string>
#include <iostream>

#include <boost/variant.hpp>
#include <wspp/util/variant.hpp>

namespace wspp {

// abstract template loader
class TemplateLoader {
public:
    // override to return a template string from a key
    virtual std::string load(const std::string &src) =0 ;
    // this is used to implement recursive loading e.g. of partials or inheritance where keys may be relative to the parent
};

// loads templates from file system relative to root folders.

class FileSystemTemplateLoader: public TemplateLoader {

public:
    FileSystemTemplateLoader(const std::initializer_list<std::string> &root_folders, const std::string &suffix = ".mst") ;

    virtual std::string load(const std::string &src) override ;
private:
    std::vector<std::string> root_folders_ ;
    std::string suffix_ ;
};

// Mustache template engine implementation

class TemplateRenderer {
public:

    TemplateRenderer( const boost::shared_ptr<TemplateLoader> &loader, bool caching = false ): loader_(loader), caching_(caching) {}

    // Render a template file or template string using given context and list of partials.
    // If the resource is a file the string has to be prefixed by '@' which is relative to the root folder.
    // "partials" is a map of key value pairs i.e. mapping partial keys in the template to actual resources (template string or files)
    // For convenience if a partial key starts with @ then corresponding resource will be @key
    // A global cache is used to store compiled templates if caching is enabled.
    // A simple form of dynamic partials is implemented by allowing partial keys to contain substitution patterns e.g. {{> @forms/%field_type%_field.mst }}
    // The pattern params are looked up in the context stack and replaced with corresponding values before rendering the partials.
    // Also the substitution pattern {{.}} is used to render the current array element in an array section (in this case the data object should point to an array of literals)
    // Lambdas are not supported.

    std::string render(const std::string &key, const Variant &context) ;

private:

    boost::shared_ptr<TemplateLoader> loader_ ;
    bool caching_ ;
} ;

}

#endif
<commit_msg>mustache extensions<commit_after>#ifndef __WSPP_UTIL_TEMPLATE_RENDERER_HPP__
#define __WSPP_UTIL_TEMPLATE_RENDERER_HPP__

#include <string>
#include <iostream>

#include <boost/variant.hpp>
#include <wspp/util/variant.hpp>

namespace wspp {

// abstract template loader
class TemplateLoader {
public:
    // override to return a template string from a key
    virtual std::string load(const std::string &src) =0 ;
    // this is used to implement recursive loading e.g. of partials or inheritance where keys may be relative to the parent
};

// loads templates from file system relative to root folders.

class FileSystemTemplateLoader: public TemplateLoader {

public:
    FileSystemTemplateLoader(const std::initializer_list<std::string> &root_folders, const std::string &suffix = ".mst") ;

    virtual std::string load(const std::string &src) override ;
private:
    std::vector<std::string> root_folders_ ;
    std::string suffix_ ;
};

// Mustache template engine implementation

class TemplateRenderer {
public:

    TemplateRenderer( const boost::shared_ptr<TemplateLoader> &loader, bool caching = false ): loader_(loader), caching_(caching) {}

    // Render a template using given context and list of partials.
    // The loader is used to map the given key to a file or other resource.
    // A global cache is used to store compiled templates if caching is enabled.
    //
    // A simple form of dynamic partials is implemented by testing of the key is a variable in the current context. The corresponding value is then used as partial key.
    // Partials can take arguments in the form of "{{> <name> <arg1>="<val1>" <arg2>="<val2>" ... }}". The arguments are pushed in the context stack before evaluting the partial.
    // The implementation also supports an extension of mustache namely extensions and blocks similar to
    // https://github.com/mustache/spec/issues/38
    // Also the substitution pattern {{.}} is used to render the current array element in an array section (in this case the data object should point to an array of literals)
    // Lambdas are not supported.

    std::string render(const std::string &key, const Variant &context) ;

private:

    boost::shared_ptr<TemplateLoader> loader_ ;
    bool caching_ ;
} ;

}

#endif
<|endoftext|>


<commit_before>#include "tangram.h"

#include <memory>
#include <utility>
#include <cmath>
#include <set>

#include "platform.h"
#include "tile/tileManager.h"
#include "view/view.h"
#include "style/polygonStyle.h"
#include "style/polylineStyle.h"
#include "style/textStyle.h"
#include "style/debugTextStyle.h"
#include "style/debugStyle.h"
#include "style/spriteStyle.h"
#include "scene/sceneLoader.h"
#include "scene/scene.h"
#include "util/error.h"
#include "stl_util.hpp"

namespace Tangram {

    std::unique_ptr<TileManager> m_tileManager;
    std::shared_ptr<Scene> m_scene;
    std::shared_ptr<View> m_view;
    std::shared_ptr<LabelContainer> m_labelContainer;
    std::shared_ptr<FontContext> m_ftContext;
    std::shared_ptr<DebugStyle> m_debugStyle;

    static float g_time = 0.0;
    static unsigned long g_flags = 0;

    void initialize() {

        logMsg("initialize\n");

        // Create view
        if (!m_view) {
            m_view = std::make_shared<View>();
        }

        // Create a scene object
        if (!m_scene) {
            m_scene = std::make_shared<Scene>();

            std::shared_ptr<Material> mat(new Material());
            mat->setAmbientEnabled(true);
            //mat->setDiffuse("sem.jpg",MappingType::SPHEREMAP);
            mat->setSpecularEnabled(true);
            //mat->setNormal("normals.jpg",MappingType::UV);

            // Load style(s); hard-coded for now
            std::unique_ptr<Style> polyStyle(new PolygonStyle("Polygon"));
            polyStyle->setLighting(LightingType::fragment);
            polyStyle->addLayers({
                "buildings",
                "water",
                "earth",
                "landuse"
            });
            polyStyle->setMaterial(mat);
            m_scene->addStyle(std::move(polyStyle));

            std::unique_ptr<Style> linesStyle(new PolylineStyle("Polyline"));
            linesStyle->setLighting(LightingType::vertex);
            linesStyle->addLayers({"roads"});
            // linesStyle->setMaterial(mat);
            m_scene->addStyle(std::move(linesStyle));

            m_ftContext = std::make_shared<FontContext>();
            m_ftContext->addFont("FiraSans-Medium.ttf", "FiraSans");
            m_ftContext->addFont("FuturaStd-Condensed.ttf", "Futura");
            m_labelContainer = LabelContainer::GetInstance();
            m_labelContainer->setFontContext(m_ftContext);

            std::unique_ptr<Style> textStyle0(new TextStyle("FiraSans", "Textstyle0", 15.0f, 0xF7F0E1, true, true));
            textStyle0->addLayers({
                "roads",
                "places",
                "pois"
            });
            m_scene->addStyle(std::move(textStyle0));
            std::unique_ptr<Style> textStyle1(new TextStyle("Futura", "Textstyle1", 18.0f, 0x26241F, true, true));
            textStyle1->addLayers({
                "landuse",
            });
            m_scene->addStyle(std::move(textStyle1));

            std::unique_ptr<Style> debugTextStyle(new DebugTextStyle("FiraSans", "DebugTextStyle", 30.0f, 0xDC3522, true));
            m_scene->addStyle(std::move(debugTextStyle));

            std::unique_ptr<DebugStyle> debugStyle(new DebugStyle("Debug"));
            m_scene->addStyle(std::move(debugStyle));

            // Testing loading image
			// std::unique_ptr<Style> spriteStyle(new SpriteStyle("Sprite"));
            // m_scene->addStyle(std::move(spriteStyle));
        }

        // Create a tileManager
        if (!m_tileManager) {
            m_tileManager = TileManager::GetInstance();

            // Pass references to the view and scene into the tile manager
            m_tileManager->setView(m_view);
            m_tileManager->setScene(m_scene);
        }

        SceneLoader loader;
        loader.loadScene("config.yaml", *m_scene, *m_tileManager, *m_view);

        // Set up openGL state
        glDisable(GL_BLEND);
        glDisable(GL_STENCIL_TEST);
        glEnable(GL_DEPTH_TEST);
        glClearDepthf(1.0);
        glDepthRangef(0.0, 1.0);
        glDepthMask(GL_TRUE);
        glDepthFunc(GL_LEQUAL);
        glEnable(GL_CULL_FACE);
        glFrontFace(GL_CCW);
        glCullFace(GL_BACK);
        glClearColor(0.3f, 0.3f, 0.3f, 1.0f);

        while (Error::hadGlError("Tangram::initialize()")) {}

        logMsg("finish initialize\n");

    }

    void resize(int _newWidth, int _newHeight) {

        logMsg("resize: %d x %d\n", _newWidth, _newHeight);

        glViewport(0, 0, _newWidth, _newHeight);

        if (m_view) {
            m_view->setSize(_newWidth, _newHeight);
        }

        if (m_ftContext) {
            m_ftContext->setScreenSize(m_view->getWidth(), m_view->getHeight());
            m_labelContainer->setScreenSize(m_view->getWidth(), m_view->getHeight());
        }

        while (Error::hadGlError("Tangram::resize()")) {}

    }

    void update(float _dt) {

        g_time += _dt;

        if (m_view) {
            m_view->update();

            m_tileManager->updateTileSet();

            if(m_view->changedOnLastUpdate() || m_tileManager->hasTileSetChanged()) {
                m_labelContainer->setViewProjectionMatrix(m_view->getViewProjectionMatrix());

                for (const auto& mapIDandTile : m_tileManager->getVisibleTiles()) {
                    const std::shared_ptr<MapTile>& tile = mapIDandTile.second;
                    tile->update(_dt, *m_view);
                }

                // update labels for specific style
                for (const auto& style : m_scene->getStyles()) {
                    for (const auto& mapIDandTile : m_tileManager->getVisibleTiles()) {
                        const std::shared_ptr<MapTile>& tile = mapIDandTile.second;
                        tile->updateLabels(_dt, *style, *m_view, m_labelContainer);
                    }
                }

                // manage occlusions
                m_labelContainer->updateOcclusions();

                for (const auto& style : m_scene->getStyles()) {
                    for (const auto& mapIDandTile : m_tileManager->getVisibleTiles()) {
                        const std::shared_ptr<MapTile>& tile = mapIDandTile.second;
                        tile->pushLabelTransforms(*style, m_labelContainer);
                    }
                }
            }
        }

        if(m_scene) {
            // Update lights and styles
        }
    }

    void render() {

        // Set up openGL for new frame
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Loop over all styles
        for (const auto& style : m_scene->getStyles()) {
            style->setupFrame(m_view, m_scene);

            // Loop over all tiles in m_tileSet
            for (const auto& mapIDandTile : m_tileManager->getVisibleTiles()) {
                const std::shared_ptr<MapTile>& tile = mapIDandTile.second;
                if (tile->hasGeometry()) {
                    // Draw tile!
                    style->setupTile(tile);
                    tile->draw(*style, *m_view);
                }
            }

            style->teardown();
        }

        while (Error::hadGlError("Tangram::render()")) {}
    }

    void setPixelScale(float _pixelsPerPoint) {

        if (m_view) {
            m_view->setPixelScale(_pixelsPerPoint);
        }

        for (auto& style : m_scene->getStyles()) {
            style->setPixelScale(_pixelsPerPoint);
        }

    }

    void handleTapGesture(float _posX, float _posY) {

        float viewCenterX = 0.5f * m_view->getWidth();
        float viewCenterY = 0.5f * m_view->getHeight();

        m_view->screenToGroundPlane(viewCenterX, viewCenterY);
        m_view->screenToGroundPlane(_posX, _posY);

        m_view->translate((_posX - viewCenterX), (_posY - viewCenterY));

    }

    void handleDoubleTapGesture(float _posX, float _posY) {

        handlePinchGesture(_posX, _posY, 2.f);

    }

    void handlePanGesture(float _startX, float _startY, float _endX, float _endY) {

        m_view->screenToGroundPlane(_startX, _startY);
        m_view->screenToGroundPlane(_endX, _endY);

        m_view->translate(_startX - _endX, _startY - _endY);

    }

    void handlePinchGesture(float _posX, float _posY, float _scale) {

        float viewCenterX = 0.5f * m_view->getWidth();
        float viewCenterY = 0.5f * m_view->getHeight();

        m_view->screenToGroundPlane(viewCenterX, viewCenterY);
        m_view->screenToGroundPlane(_posX, _posY);

        m_view->translate((_posX - viewCenterX)*(1-1/_scale), (_posY - viewCenterY)*(1-1/_scale));

        m_view->zoom(log2f(_scale));
    }

    void handleRotateGesture(float _posX, float _posY, float _radians) {

        m_view->screenToGroundPlane(_posX, _posY);
        m_view->orbit(_posX, _posY, _radians);

    }

    void handleShoveGesture(float _distance) {

        m_view->pitch(_distance);

    }

    void setDebugFlag(DebugFlags _flag, bool _on) {

        if (_on) {
            g_flags |= (1 << _flag); // |ing with a bitfield that is 0 everywhere except index _flag; sets index _flag to 1
        } else {
            g_flags &= ~(1 << _flag); // &ing with a bitfield that is 1 everywhere except index _flag; sets index _flag to 0
        }

        m_view->setZoom(m_view->getZoom()); // Force the view to refresh

    }

    bool getDebugFlag(DebugFlags _flag) {

        return (g_flags & (1 << _flag)) != 0; // &ing with a bitfield that is 0 everywhere except index _flag will yield 0 iff index _flag is 0

    }

    void teardown() {
        // Release resources!
        logMsg("teardown\n");
        m_tileManager.reset();
        m_scene.reset();
        m_view.reset();
    }

    void onContextDestroyed() {

        logMsg("context destroyed\n");

        // The OpenGL context has been destroyed since the last time resources were created,
        // so we invalidate all data that depends on OpenGL object handles.

        // ShaderPrograms are invalidated and immediately rebuilt
        ShaderProgram::invalidateAllPrograms();

        // Buffer objects are invalidated and re-uploaded the next time they are used
        VboMesh::invalidateAllVBOs();

    }

}
<commit_msg>mergin master<commit_after>#include "tangram.h"

#include <memory>
#include <utility>
#include <cmath>
#include <set>

#include "platform.h"
#include "tile/tileManager.h"
#include "view/view.h"
#include "style/polygonStyle.h"
#include "style/polylineStyle.h"
#include "style/textStyle.h"
#include "style/debugTextStyle.h"
#include "style/debugStyle.h"
#include "style/spriteStyle.h"
#include "scene/sceneLoader.h"
#include "scene/scene.h"
#include "util/error.h"
#include "stl_util.hpp"

namespace Tangram {

    std::unique_ptr<TileManager> m_tileManager;
    std::shared_ptr<Scene> m_scene;
    std::shared_ptr<View> m_view;
    std::shared_ptr<LabelContainer> m_labelContainer;
    std::shared_ptr<FontContext> m_ftContext;
    std::shared_ptr<DebugStyle> m_debugStyle;

    static float g_time = 0.0;
    static unsigned long g_flags = 0;

    void initialize() {

        logMsg("initialize\n");

        // Create view
        if (!m_view) {
            m_view = std::make_shared<View>();
        }

        // Create a scene object
        if (!m_scene) {
            m_scene = std::make_shared<Scene>();

            std::shared_ptr<Material> mat(new Material());
            mat->setAmbientEnabled(true);
            // mat->setDiffuse("sem.jpg",MappingType::SPHEREMAP);
            mat->setSpecularEnabled(false);
            //mat->setNormal("normals.jpg",MappingType::UV);

            // Load style(s); hard-coded for now
            std::unique_ptr<Style> polyStyle(new PolygonStyle("Polygon"));
            polyStyle->setLighting(LightingType::fragment);
            polyStyle->addLayers({
                "buildings",
                "water",
                "earth",
                "landuse"
            });
            polyStyle->setMaterial(mat);
            m_scene->addStyle(std::move(polyStyle));

            std::unique_ptr<Style> linesStyle(new PolylineStyle("Polyline"));
            linesStyle->setLighting(LightingType::vertex);
            linesStyle->addLayers({"roads"});
            // linesStyle->setMaterial(mat);
            m_scene->addStyle(std::move(linesStyle));

            m_ftContext = std::make_shared<FontContext>();
            m_ftContext->addFont("FiraSans-Medium.ttf", "FiraSans");
            m_ftContext->addFont("FuturaStd-Condensed.ttf", "Futura");
            m_labelContainer = LabelContainer::GetInstance();
            m_labelContainer->setFontContext(m_ftContext);

            std::unique_ptr<Style> textStyle0(new TextStyle("FiraSans", "Textstyle0", 15.0f, 0xF7F0E1, true, true));
            textStyle0->addLayers({
                "roads",
                "places",
                "pois"
            });
            m_scene->addStyle(std::move(textStyle0));
            std::unique_ptr<Style> textStyle1(new TextStyle("Futura", "Textstyle1", 18.0f, 0x26241F, true, true));
            textStyle1->addLayers({
                "landuse",
            });
            m_scene->addStyle(std::move(textStyle1));

            std::unique_ptr<Style> debugTextStyle(new DebugTextStyle("FiraSans", "DebugTextStyle", 30.0f, 0xDC3522, true));
            m_scene->addStyle(std::move(debugTextStyle));

            std::unique_ptr<DebugStyle> debugStyle(new DebugStyle("Debug"));
            m_scene->addStyle(std::move(debugStyle));

            // Testing loading image
			// std::unique_ptr<Style> spriteStyle(new SpriteStyle("Sprite"));
            // m_scene->addStyle(std::move(spriteStyle));
        }

        // Create a tileManager
        if (!m_tileManager) {
            m_tileManager = TileManager::GetInstance();

            // Pass references to the view and scene into the tile manager
            m_tileManager->setView(m_view);
            m_tileManager->setScene(m_scene);
        }

        SceneLoader loader;
        loader.loadScene("config.yaml", *m_scene, *m_tileManager, *m_view);

        // Set up openGL state
        glDisable(GL_BLEND);
        glDisable(GL_STENCIL_TEST);
        glEnable(GL_DEPTH_TEST);
        glClearDepthf(1.0);
        glDepthRangef(0.0, 1.0);
        glDepthMask(GL_TRUE);
        glDepthFunc(GL_LEQUAL);
        glEnable(GL_CULL_FACE);
        glFrontFace(GL_CCW);
        glCullFace(GL_BACK);
        glClearColor(0.3f, 0.3f, 0.3f, 1.0f);

        while (Error::hadGlError("Tangram::initialize()")) {}

        logMsg("finish initialize\n");

    }

    void resize(int _newWidth, int _newHeight) {

        logMsg("resize: %d x %d\n", _newWidth, _newHeight);

        glViewport(0, 0, _newWidth, _newHeight);

        if (m_view) {
            m_view->setSize(_newWidth, _newHeight);
        }

        if (m_ftContext) {
            m_ftContext->setScreenSize(m_view->getWidth(), m_view->getHeight());
            m_labelContainer->setScreenSize(m_view->getWidth(), m_view->getHeight());
        }

        while (Error::hadGlError("Tangram::resize()")) {}

    }

    void update(float _dt) {

        g_time += _dt;

        if (m_view) {
            m_view->update();

            m_tileManager->updateTileSet();

            if(m_view->changedOnLastUpdate() || m_tileManager->hasTileSetChanged()) {
                m_labelContainer->setViewProjectionMatrix(m_view->getViewProjectionMatrix());

                for (const auto& mapIDandTile : m_tileManager->getVisibleTiles()) {
                    const std::shared_ptr<MapTile>& tile = mapIDandTile.second;
                    tile->update(_dt, *m_view);
                }

                // update labels for specific style
                for (const auto& style : m_scene->getStyles()) {
                    for (const auto& mapIDandTile : m_tileManager->getVisibleTiles()) {
                        const std::shared_ptr<MapTile>& tile = mapIDandTile.second;
                        tile->updateLabels(_dt, *style, *m_view, m_labelContainer);
                    }
                }

                // manage occlusions
                m_labelContainer->updateOcclusions();

                for (const auto& style : m_scene->getStyles()) {
                    for (const auto& mapIDandTile : m_tileManager->getVisibleTiles()) {
                        const std::shared_ptr<MapTile>& tile = mapIDandTile.second;
                        tile->pushLabelTransforms(*style, m_labelContainer);
                    }
                }
            }
        }

        if(m_scene) {
            // Update lights and styles
        }
    }

    void render() {

        // Set up openGL for new frame
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Loop over all styles
        for (const auto& style : m_scene->getStyles()) {
            style->setupFrame(m_view, m_scene);

            // Loop over all tiles in m_tileSet
            for (const auto& mapIDandTile : m_tileManager->getVisibleTiles()) {
                const std::shared_ptr<MapTile>& tile = mapIDandTile.second;
                if (tile->hasGeometry()) {
                    // Draw tile!
                    style->setupTile(tile);
                    tile->draw(*style, *m_view);
                }
            }

            style->teardown();
        }

        while (Error::hadGlError("Tangram::render()")) {}
    }

    void setPixelScale(float _pixelsPerPoint) {

        if (m_view) {
            m_view->setPixelScale(_pixelsPerPoint);
        }

        for (auto& style : m_scene->getStyles()) {
            style->setPixelScale(_pixelsPerPoint);
        }

    }

    void handleTapGesture(float _posX, float _posY) {

        float viewCenterX = 0.5f * m_view->getWidth();
        float viewCenterY = 0.5f * m_view->getHeight();

        m_view->screenToGroundPlane(viewCenterX, viewCenterY);
        m_view->screenToGroundPlane(_posX, _posY);

        m_view->translate((_posX - viewCenterX), (_posY - viewCenterY));

    }

    void handleDoubleTapGesture(float _posX, float _posY) {

        handlePinchGesture(_posX, _posY, 2.f);

    }

    void handlePanGesture(float _startX, float _startY, float _endX, float _endY) {

        m_view->screenToGroundPlane(_startX, _startY);
        m_view->screenToGroundPlane(_endX, _endY);

        m_view->translate(_startX - _endX, _startY - _endY);

    }

    void handlePinchGesture(float _posX, float _posY, float _scale) {

        float viewCenterX = 0.5f * m_view->getWidth();
        float viewCenterY = 0.5f * m_view->getHeight();

        m_view->screenToGroundPlane(viewCenterX, viewCenterY);
        m_view->screenToGroundPlane(_posX, _posY);

        m_view->translate((_posX - viewCenterX)*(1-1/_scale), (_posY - viewCenterY)*(1-1/_scale));

        m_view->zoom(log2f(_scale));
    }

    void handleRotateGesture(float _posX, float _posY, float _radians) {

        m_view->screenToGroundPlane(_posX, _posY);
        m_view->orbit(_posX, _posY, _radians);

    }

    void handleShoveGesture(float _distance) {

        m_view->pitch(_distance);

    }

    void setDebugFlag(DebugFlags _flag, bool _on) {

        if (_on) {
            g_flags |= (1 << _flag); // |ing with a bitfield that is 0 everywhere except index _flag; sets index _flag to 1
        } else {
            g_flags &= ~(1 << _flag); // &ing with a bitfield that is 1 everywhere except index _flag; sets index _flag to 0
        }

        m_view->setZoom(m_view->getZoom()); // Force the view to refresh

    }

    bool getDebugFlag(DebugFlags _flag) {

        return (g_flags & (1 << _flag)) != 0; // &ing with a bitfield that is 0 everywhere except index _flag will yield 0 iff index _flag is 0

    }

    void teardown() {
        // Release resources!
        logMsg("teardown\n");
        m_tileManager.reset();
        m_scene.reset();
        m_view.reset();
    }

    void onContextDestroyed() {

        logMsg("context destroyed\n");

        // The OpenGL context has been destroyed since the last time resources were created,
        // so we invalidate all data that depends on OpenGL object handles.

        // ShaderPrograms are invalidated and immediately rebuilt
        ShaderProgram::invalidateAllPrograms();

        // Buffer objects are invalidated and re-uploaded the next time they are used
        VboMesh::invalidateAllVBOs();

    }

}
<|endoftext|>


<commit_before>#define BOOST_TEST_MODULE Gpufit

#include "Gpufit/gpufit.h"

#include <boost/test/included/unit_test.hpp>

#include <array>

// TODO this doesn't fail anymore as expected, we do not really throw an error anymore and therefore cannot reliably check for an error

BOOST_AUTO_TEST_CASE( Error_Handling )
{
    std::size_t const n_fits{ 1 } ;
    std::size_t const n_points{ 2 } ;
    std::array< REAL, n_points > data{ { 0, 1 } } ;
    std::array< REAL, n_points > weights{ { 1, 1 } } ;
    std::array< REAL, 2 > initial_parameters{ { 0, 0 } } ;
    REAL tolerance{ 0.001f } ;
    int max_n_iterations{ 10 } ;
    std::array< int, 2 > parameters_to_fit{ { 0, 0 } } ;
    std::array< int, 2 > user_info{ { 0, 1 } } ;
    std::array< REAL, 2 > output_parameters ;
    int output_states ;
    REAL output_chi_square ;
    int output_n_iterations ;

    int const status
            = gpufit
            (
                n_fits,
                n_points,
                data.data(),
                weights.data(),
                LINEAR_1D,
                initial_parameters.data(),
                tolerance,
                max_n_iterations,
                parameters_to_fit.data(),
                LSE,
                n_points * sizeof( int ),
                reinterpret_cast< char * >( user_info.data() ),
                output_parameters.data(),
                & output_states,
                & output_chi_square,
                & output_n_iterations
            ) ;

    BOOST_CHECK( status == - 1 ) ;

    std::string const error = gpufit_get_last_error() ;

    BOOST_CHECK( error == "invalid configuration argument" ) ;
}
<commit_msg>error handling test fixed<commit_after>#define BOOST_TEST_MODULE Gpufit

#include "Gpufit/gpufit.h"

#include <boost/test/included/unit_test.hpp>

#include <array>

// TODO this doesn't fail anymore as expected, we do not really throw an error anymore and therefore cannot reliably check for an error

BOOST_AUTO_TEST_CASE( Error_Handling )
{
    std::size_t const n_fits{ 1 } ;
    std::size_t const n_points{ 2 } ;
    std::array< REAL, n_points > data{ { 0, 1 } } ;
    std::array< REAL, n_points > weights{ { 1, 1 } } ;
    REAL * initial_parameters = NULL;
    REAL tolerance{ 0.001f } ;
    int max_n_iterations{ 10 } ;
    std::array< int, 2 > parameters_to_fit{ { 0, 0 } } ;
    std::array< int, 2 > user_info{ { 0, 1 } } ;
    std::array< REAL, 2 > output_parameters ;
    int output_states ;
    REAL output_chi_square ;
    int output_n_iterations ;

    int const status
            = gpufit
            (
                n_fits,
                n_points,
                data.data(),
                weights.data(),
                LINEAR_1D,
                initial_parameters,
                tolerance,
                max_n_iterations,
                parameters_to_fit.data(),
                LSE,
                n_points * sizeof( int ),
                reinterpret_cast< char * >( user_info.data() ),
                output_parameters.data(),
                & output_states,
                & output_chi_square,
                & output_n_iterations
            ) ;

    BOOST_CHECK( status == - 1 ) ;

    std::string const error = gpufit_get_last_error() ;

    BOOST_CHECK( error == "invalid argument" ) ;
}
<|endoftext|>


<commit_before>#include <QStringList>
#include <QMessageBox>

#include "ionchannelconfig.h"
#include "ui_ionchannelconfig.h"

IonChannelConfig::IonChannelConfig(QTableView* view, GridProtocol* proto, QWidget *parent) :
	QWidget(parent),
	ui(new Ui::IonChannelConfig)
{
	ui->setupUi(this);
	this->view = view;
	this->model = (GridModel*)view->model();
	this->proto = proto;
	this->cellChanged();
	this->updateList();
//	ui->maxDist->setValue(0);
//	ui->maxVal->setValue(1000);
    ui->listWidget->addAction(ui->actionDelete);
    ui->listWidget->addAction(ui->actionShow_Cells);
	connect(this->model, &GridModel::cell_type_changed, this, &IonChannelConfig::cellChanged);
}

IonChannelConfig::~IonChannelConfig()
{
	delete ui;
}

void IonChannelConfig::updateList() {
	QStringList toAdd;
	string info;
	this->ui->listWidget->clear();
	for(auto& pvar : this->proto->new_pvars) {
		switch(pvar.second.dist) {
			case GridProtocol::Distribution::none:
				info = (pvar.first + "\tIncrementing\tInitial Value: "+to_string(pvar.second.val[0])+
						"\tIncrement Amount: "+to_string(pvar.second.val[1]));
				break;
			case GridProtocol::Distribution::normal:
				info = (pvar.first + "\tNormal Distribution\t Mean: "+to_string(pvar.second.val[0])+
						"\tStandard Deviation: "+to_string(pvar.second.val[1]));
				break;
			case GridProtocol::Distribution::lognormal:
				info = (pvar.first + "\tLognormal Distribution\t Mean: "+to_string(pvar.second.val[0])+
						"\tStandard Deviation: "+to_string(pvar.second.val[1]));
				break;
		}
		toAdd += info.c_str();
	}
	this->ui->listWidget->addItems(toAdd);
}

void IonChannelConfig::cellChanged() {
	QRegExp* allowed_vars = new QRegExp("Factor");
	QStringList toAdd;
	ui->ionChannelType->clear();
	for(auto& pvarName : this->proto->cell->getConstants()) {
		if(allowed_vars->indexIn(pvarName.c_str()) != -1) {
			toAdd += pvarName.c_str();
		}
	}
	toAdd.removeDuplicates();
	ui->ionChannelType->addItems(toAdd);
}

void IonChannelConfig::on_randomize_stateChanged(int state) {
	ui->normalDist->setVisible(state);
	ui->lognormalDist->setVisible(state);
	ui->mean->setVisible(state);
	ui->meanLabel->setVisible(state);
	ui->stdDev->setVisible(state);
	ui->stdDevLabel->setVisible(state);
	ui->startVal->setVisible(!state);
	ui->startValLabel->setVisible(!state);
	ui->incAmt->setVisible(!state);
	ui->incAmtLabel->setVisible(!state);
}

void IonChannelConfig::on_multiple_stateChanged(int state) {
	ui->maxDist->setValue(0);
	ui->maxVal->setValue(1000);
	ui->maxDist->setEnabled(state);
	ui->maxDistLabel->setEnabled(state);
	ui->maxVal->setEnabled(state);
	ui->maxValLabel->setEnabled(state);
}

void IonChannelConfig::on_normalDist_toggled(bool checked) {
	if(checked) {
	if(ui->mean->value() == 0) {
		ui->mean->setValue(1);
	}
	} else {
		if(ui->mean->value() == 1) {
			ui->mean->setValue(0);
		}
	}
}

void IonChannelConfig::on_addButton_clicked()
{
	string type = ui->ionChannelType->currentText().toStdString();
	GridProtocol::MIonChanParam toAdd;
	if(ui->randomize->checkState() == 0) {
		toAdd.dist = GridProtocol::Distribution::none;
		toAdd.val[0] = ui->startVal->value();
		toAdd.val[1] = ui->incAmt->value();
	} else {
		toAdd.val[0] = ui->mean->value();
		toAdd.val[1] = ui->stdDev->value();
		if(ui->normalDist->isChecked()) {
			toAdd.dist = GridProtocol::Distribution::normal;
		} else {
			toAdd.dist = GridProtocol::Distribution::lognormal;
		}
	}
	this->setIonChannels(ui->maxDist->value(), ui->maxVal->value(), toAdd);
	if(toAdd.cells.size() > 0) {
		this->proto->new_pvars[type] = toAdd;
	}
	this->updateList();
}
void IonChannelConfig::setIonChannels(int maxDist, double maxVal, GridProtocol::MIonChanParam& ionConf) {
	this->getInitial();
	int i = 0;
	double val = 0;
	while(current.size() > 0 && i <= maxDist) {
		for(const pair<int,int>& e: this->current) {
			switch(ionConf.dist) {
				case GridProtocol::Distribution::none:
					val = ionConf.val[0]+ionConf.val[1]*i;
					if(val > maxVal) {
						val = maxVal;
					}
					break;
				case GridProtocol::Distribution::normal:
					{
						normal_distribution<double> distribution(ionConf.val[0],ionConf.val[1]);
						val = distribution(proto->generator);
						break;
					}
				case GridProtocol::Distribution::lognormal:
					{
						lognormal_distribution<double> logdistribution(ionConf.val[0], ionConf.val[1]);
						val = logdistribution(proto->generator);
						break;
					}
			}
			ionConf.cells[make_pair(e.first,e.second)] = val;
			this->visited.insert(e);
		}
		++i;
		this->getNext();
	}
	this->current.clear();
	this->visited.clear();
}

void IonChannelConfig::getInitial() {
	auto selected = this->view->selectionModel()->selectedIndexes();
	for(auto toAdd : selected) {
		this->add({toAdd.column(),toAdd.row()},this->current);
	}
}

void IonChannelConfig::getNext() {
	set<pair<int,int>> next;
	for(const pair<int,int>& e: this->current) {
		this->add({e.first,e.second+1}, next);
		this->add({e.first,e.second-1}, next);
		this->add({e.first+1,e.second}, next);
		this->add({e.first-1,e.second}, next);
	}
	this->current = next;
}
//need to check for duplicates
void IonChannelConfig::add(pair<int,int> e, set<pair<int,int>>& next) {
	//check for out of bounds
	if(e.second<0||e.first<0||e.second>=this->model->rowCount()||e.first>=this->model->columnCount()) {
		return;
	}
	if(this->visited.count(e) == 0) {
		next.insert(e);
	}

}

void IonChannelConfig::on_actionDelete_triggered() {
    QList<QListWidgetItem *> items = ui->listWidget->selectedItems();
    for(auto item: items) {
        QString name = item->data(Qt::DisplayRole).toString().split("\t")[0];
        this->proto->new_pvars.erase(name.toStdString());
        int row = ui->listWidget->row(item);
        ui->listWidget->takeItem(row);
        delete item;
    }
}
void IonChannelConfig::on_actionShow_Cells_triggered() {
    QList<QListWidgetItem *> items = ui->listWidget->selectedItems();
    QString text = "(X <column>, Y <row>)\n";
    for(auto item: items) {
        QString name = item->data(Qt::DisplayRole).toString().split("\t")[0];
        text += name+"\n";
        GridProtocol::MIonChanParam param = this->proto->new_pvars[name.toStdString()];
        for(auto& cell: param.cells) {
            text += "(" + QString::number(cell.first.first) +","+
                    QString::number(cell.first.second) +") = "+QString::number(cell.second)+"\n";
        }
    }
    QMessageBox msgBox;
    msgBox.setText(text);
    msgBox.exec();
}
<commit_msg>apply to multiple check box in ionchannelconf now has an effect<commit_after>#include <QStringList>
#include <QMessageBox>

#include "ionchannelconfig.h"
#include "ui_ionchannelconfig.h"

IonChannelConfig::IonChannelConfig(QTableView* view, GridProtocol* proto, QWidget *parent) :
	QWidget(parent),
	ui(new Ui::IonChannelConfig)
{
	ui->setupUi(this);
	this->view = view;
	this->model = (GridModel*)view->model();
	this->proto = proto;
	this->cellChanged();
	this->updateList();
//	ui->maxDist->setValue(0);
//	ui->maxVal->setValue(1000);
    ui->listWidget->addAction(ui->actionDelete);
    ui->listWidget->addAction(ui->actionShow_Cells);
	connect(this->model, &GridModel::cell_type_changed, this, &IonChannelConfig::cellChanged);
}

IonChannelConfig::~IonChannelConfig()
{
	delete ui;
}

void IonChannelConfig::updateList() {
	QStringList toAdd;
	string info;
	this->ui->listWidget->clear();
	for(auto& pvar : this->proto->new_pvars) {
		switch(pvar.second.dist) {
			case GridProtocol::Distribution::none:
				info = (pvar.first + "\tIncrementing\tInitial Value: "+to_string(pvar.second.val[0])+
						"\tIncrement Amount: "+to_string(pvar.second.val[1]));
				break;
			case GridProtocol::Distribution::normal:
				info = (pvar.first + "\tNormal Distribution\t Mean: "+to_string(pvar.second.val[0])+
						"\tStandard Deviation: "+to_string(pvar.second.val[1]));
				break;
			case GridProtocol::Distribution::lognormal:
				info = (pvar.first + "\tLognormal Distribution\t Mean: "+to_string(pvar.second.val[0])+
						"\tStandard Deviation: "+to_string(pvar.second.val[1]));
				break;
		}
		toAdd += info.c_str();
	}
	this->ui->listWidget->addItems(toAdd);
}

void IonChannelConfig::cellChanged() {
	QRegExp* allowed_vars = new QRegExp("Factor");
	QStringList toAdd;
	ui->ionChannelType->clear();
	for(auto& pvarName : this->proto->cell->getConstants()) {
		if(allowed_vars->indexIn(pvarName.c_str()) != -1) {
			toAdd += pvarName.c_str();
		}
	}
	toAdd.removeDuplicates();
	ui->ionChannelType->addItems(toAdd);
}

void IonChannelConfig::on_randomize_stateChanged(int state) {
	ui->normalDist->setVisible(state);
	ui->lognormalDist->setVisible(state);
	ui->mean->setVisible(state);
	ui->meanLabel->setVisible(state);
	ui->stdDev->setVisible(state);
	ui->stdDevLabel->setVisible(state);
	ui->startVal->setVisible(!state);
	ui->startValLabel->setVisible(!state);
	ui->incAmt->setVisible(!state);
	ui->incAmtLabel->setVisible(!state);
}

void IonChannelConfig::on_multiple_stateChanged(int state) {
	ui->maxDist->setValue(0);
	ui->maxVal->setValue(1000);
	ui->maxDist->setEnabled(state);
	ui->maxDistLabel->setEnabled(state);
	ui->maxVal->setEnabled(state);
	ui->maxValLabel->setEnabled(state);
}

void IonChannelConfig::on_normalDist_toggled(bool checked) {
	if(checked) {
	if(ui->mean->value() == 0) {
		ui->mean->setValue(1);
	}
	} else {
		if(ui->mean->value() == 1) {
			ui->mean->setValue(0);
		}
	}
}

void IonChannelConfig::on_addButton_clicked()
{
	int maxDist = 0;
	double maxVal = 100;
	string type = ui->ionChannelType->currentText().toStdString();
	GridProtocol::MIonChanParam toAdd;
	if(ui->randomize->checkState() == 0) {
		toAdd.dist = GridProtocol::Distribution::none;
		toAdd.val[0] = ui->startVal->value();
		toAdd.val[1] = ui->incAmt->value();
	} else {
		toAdd.val[0] = ui->mean->value();
		toAdd.val[1] = ui->stdDev->value();
		if(ui->normalDist->isChecked()) {
			toAdd.dist = GridProtocol::Distribution::normal;
		} else {
			toAdd.dist = GridProtocol::Distribution::lognormal;
		}
	}
	if(ui->multiple->isChecked()) {
		maxDist = ui->maxDist->value();
		maxVal = ui->maxVal->value();
	}
	this->setIonChannels(maxDist, maxVal, toAdd);
	if(toAdd.cells.size() > 0) {
		this->proto->new_pvars[type] = toAdd;
	}
	this->updateList();
}
void IonChannelConfig::setIonChannels(int maxDist, double maxVal, GridProtocol::MIonChanParam& ionConf) {
	this->getInitial();
	int i = 0;
	double val = 0;
	while(current.size() > 0 && i <= maxDist) {
		for(const pair<int,int>& e: this->current) {
			switch(ionConf.dist) {
				case GridProtocol::Distribution::none:
					val = ionConf.val[0]+ionConf.val[1]*i;
					if(val > maxVal) {
						val = maxVal;
					}
					break;
				case GridProtocol::Distribution::normal:
					{
						normal_distribution<double> distribution(ionConf.val[0],ionConf.val[1]);
						val = distribution(proto->generator);
						break;
					}
				case GridProtocol::Distribution::lognormal:
					{
						lognormal_distribution<double> logdistribution(ionConf.val[0], ionConf.val[1]);
						val = logdistribution(proto->generator);
						break;
					}
			}
			ionConf.cells[make_pair(e.first,e.second)] = val;
			this->visited.insert(e);
		}
		++i;
		this->getNext();
	}
	this->current.clear();
	this->visited.clear();
}

void IonChannelConfig::getInitial() {
	auto selected = this->view->selectionModel()->selectedIndexes();
	for(auto toAdd : selected) {
		this->add({toAdd.column(),toAdd.row()},this->current);
	}
}

void IonChannelConfig::getNext() {
	set<pair<int,int>> next;
	for(const pair<int,int>& e: this->current) {
		this->add({e.first,e.second+1}, next);
		this->add({e.first,e.second-1}, next);
		this->add({e.first+1,e.second}, next);
		this->add({e.first-1,e.second}, next);
	}
	this->current = next;
}
//need to check for duplicates
void IonChannelConfig::add(pair<int,int> e, set<pair<int,int>>& next) {
	//check for out of bounds
	if(e.second<0||e.first<0||e.second>=this->model->rowCount()||e.first>=this->model->columnCount()) {
		return;
	}
	if(this->visited.count(e) == 0) {
		next.insert(e);
	}

}

void IonChannelConfig::on_actionDelete_triggered() {
    QList<QListWidgetItem *> items = ui->listWidget->selectedItems();
    for(auto item: items) {
        QString name = item->data(Qt::DisplayRole).toString().split("\t")[0];
        this->proto->new_pvars.erase(name.toStdString());
        int row = ui->listWidget->row(item);
        ui->listWidget->takeItem(row);
        delete item;
    }
}
void IonChannelConfig::on_actionShow_Cells_triggered() {
    QList<QListWidgetItem *> items = ui->listWidget->selectedItems();
    QString text = "(X <column>, Y <row>)\n";
    for(auto item: items) {
        QString name = item->data(Qt::DisplayRole).toString().split("\t")[0];
        text += name+"\n";
        GridProtocol::MIonChanParam param = this->proto->new_pvars[name.toStdString()];
        for(auto& cell: param.cells) {
            text += "(" + QString::number(cell.first.first) +","+
                    QString::number(cell.first.second) +") = "+QString::number(cell.second)+"\n";
        }
    }
    QMessageBox msgBox;
    msgBox.setText(text);
    msgBox.exec();
}
<|endoftext|>