I am using CGAL to compute the 3D triangulation of a set of points:
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Delaunay_triangulation_3<K> CGALTriangulation;
typedef CGALTriangulation::Point Point;
// Construction from a list of points
std::list<Point> points;
points.push_front(Point(0, 0, 0));
points.push_front(Point(2, 0, 0));
points.push_front(Point(0, 2, 0));
points.push_front(Point(2, 2, 0));
points.push_front(Point(1, 1, 1));
// Perform triangulation
CGALTriangulation T(points.begin(), points.end());
Accessing triangles (facets)
I need to create a mesh out of this in Unity, so I am using CGAL because it has a lot of algorithms for taking care of this complex problem. The issue is that it is very difficult in the API to find a way to access the different triangles (and so their vertices) that compose the triangulation and I haven't yet found a way how to do so :(
Note Please note that accessing vertices alone is not enough for me:
for (CGALTriangulation::Finite_vertices_iterator it = T.finite_vertices_begin();
it != T.finite_vertices_end();
it++)
{
CGALTriangulation::Triangulation_data_structure::Vertex v = *it;
// Do something with the vertex
}
Because I do not get any info about which facet (triangle) each vertex belongs to. And the triangles is exactly what I need!
How can I access the triangles (facets) of the triangulation? How to get the vertices out of each facet?
I don't know precisely what you can to achieve. A 3D Delaunay triangulation is a decomposition of the convex hull of your points into tetrahedra. Any way, if you want to access the facets of a triangulation, you use the Finite_facets_iterator.
Something like:
for (CGALTriangulation::Finite_facets_iterator it = T.finite_facets_begin();
it != T.finite_facets_end();
it++)
{
std::pair<CGALTriangulation::Cell_handle, int> facet = *it;
CGALTriangulation::Vertex_handle v1 = facet.first->vertex( (facet.second+1)%4 );
CGALTriangulation::Vertex_handle v2 = facet.first->vertex( (facet.second+2)%4 );
CGALTriangulation::Vertex_handle v3 = facet.first->vertex( (facet.second+3)%4 );
}
If you are interested in a surface mesh, you might want to look a reconstruction algorithms such as Poisson surface reconstruction or Advancing Front Reconstruction.
I'm trying to create an application which displays a simple graph and since I'm using boost::graph for the underlying data structure, I'd like to use the layouting algorithms available in the library as well.
The answer presented here explains how to use a layout algorithm within the boost library to lay out vertices of graph:
How does the attractive force of Fruchterman Reingold work with Boost Graph Library
But sadly it does not explain how - after the layout has been calculated - the coordinates of the vertices can actually be accessed. Even though we get a vector of positions (or rather points), the float components are private, so that doesn't help. The boost::graph documentation also doesn't address this topic.
So how can simple (X,Y) coordinates of each vertex be retrieved after a layouting algorithm has been applied?
After reviewing the boost graph source code it turned out that this isn't so hard after all.
We can use a property map to iterate over the PositionsMap and the [] operator to access the coordinates:
template<typename Graph, typename Positions>
void print_positions(const Graph &g, const Positions &positions) {
auto index_map = boost::get(boost::vertex_index, graph);
using PropertyMap = boost::iterator_property_map<Positions::iterator, decltype(index_map)>;
PropertyMap position_map(positions.begin(), index_map);
BGL_FORALL_VERTICES(v, graph, Graph) {
Position pos = position_map[v];
cout << v << ": " << pos[0] << "|" << pos[1] << endl;
}
}
I'm having trouble getting boost's connected components algorithm working reliably. I want to use it to separate collections of 3D point data. I have a data set where there is are two obvious 'clusters' of 3D points separated by a large distance.
I create an undirected Boost graph object with bundled information which is a simple 'point' class, this contains an x, y and z property and a method to calculate distance of this point from another.
adjacency_list<vecS, vecS, undirectedS,Point> Graph;
I have a vector of point information (Point_dat) which I now transfer to vertices of the graph
for (size_t i = 0; i < Inter_dat.size(); i++)
{
// Create a new vertex for every element of the original data
add_vertex(Graph);
(Graph)[i] = Point_dat[i];
}
I now iterate through the vertices of the graph (in two loops) to calculate the distance from each vertex to each other vertex (I know there are more efficient ways of doing this but this is a first stab)
If the distance between two points is below a threshold, I add an edge between the two vertices.
typedef adjacency_list<vecS, vecS, undirectedS, Point>::vertex_iterator iterator;
std::pair<iterator, iterator> p = vertices(Graph);
for (iterator it = p.first; it != p.second; it++)
{
for (iterator it2 = it; it2 != p.second; it2++)
{
double thisdist = Graph[*it].Distance(Graph[*it2]);
if (thisdist < distance_thresh & thisdist > 0)
{
add_edge(*it,*it2, Graph);
}
}
}
I then calculate the connected components.
std::vector<int> comp(num_vertices(Graph));
int num = connected_components(Graph, &comp[0]);
The problem is, the data isn't being separated into the two clusters. The main cluster still contains some of the second. In fact if I re-run the analysis using the largest component (as selected by Boost) it finds a number of new components.
Why isn't it working? Do I need to add different parameters?
UPDATE: To give more context, I'm trying to implement a process I developed in Matlab in C++. To try and see the root of the problem I saved the edges of my graph
std::ofstream myfile("D:\\edges.txt");
auto q = edges(Graph);
for (auto it = q.first; it != q.second; ++it)
myfile << *it << std::endl;
myfile.close();
and imported the resulting data into Matlab. I then used Matlab's connected components process on this edge information and it gave me exactly the right answer. It seems that I'm setting the graph up correctly but Boosts connected components isn't giving me the right answer.
Let me first state that I just want direction, not necessarily actual code, unless a small snippet is the only way to get the point across.
I need to create a DIRECTED graph data structure using an adjacency list or matrix in C++, and add vertices/edges from standard input, which means dynamically.
I think I'd be able to create a graph fine if I was able to instantiate a set of Vertices first, then create edges and add them to the graph, but I don't understand how it is possible to add an edge which contains a vertex that hasn't been instantiated yet.
for example, the first line from standard input reads:
Miami -> New York/1100 -> Washington/1000 -> albuquerque/1700
How am I supposed to add an edge from Miami to New York if the New York vertex hasn't been added to the graph yet?
Thanks for the direction everyone!
how it is possible to add an edge which
contains a vertex that hasn't been instantiated yet.
Simple: instantiate it..
I do not see any issue with this. Assume V to be the vertex set seen so far. V is initially empty. As you read the input x->y, you get its end points (x and y). If any one of them is not instantiated (i.e., not in V), you instantiate it and add it to the vertex set.
Another way to look to it: imagine we are defining the graph by its edge set E. By definition any edge is a pair of vertices which in turn defines the vertex set of the graph.
How about you resize the adjacency list each time a new unique node comes in? You can maintain a set of unique node values and use its size to adjust the size of the adjacency list each time you have to add a node. Below is a some code that does the same.
class Graph
{
public:
// Add links in the graph
void addLink(int id1, int id2){
// Add to hashset
uniqueNodes.insert(id1);
uniqueNodes.insert(id2);
// Resize on the adjacency list based on how many nodes exists in the uniqueNodes set
adjList.resize(uniqueNodes.size());
// Make the connections assuming undirected graph
adjList[id1].push_back(id2);
adjList[id2].push_back(id1);
}
// Print the graph
void printGraph(){
for(int i = 0; i < adjList.size(); i++){
cout << i << ":";
for(auto it = adjList[i].begin(); it != adjList[i].end(); it++)
cout << *it << "->";
cout << "NULL\n";
}
}
private:
// Adjacency list for the graph
vector<list<int>> adjList;
// Hashset to help define the size of the adjacency list as nodes come in
set<int> uniqueNodes;
};
I am confused about how to actually create a Graph using the boost library, I have looked at the example code and there are no comments explaining what it does.
How do you make a graph, and add vertices and edges as you go?
Here's a simple example, using an adjacency list and executing a topological sort:
#include <iostream>
#include <deque>
#include <iterator>
#include "boost/graph/adjacency_list.hpp"
#include "boost/graph/topological_sort.hpp"
int main()
{
// Create a n adjacency list, add some vertices.
boost::adjacency_list<> g(num tasks);
boost::add_vertex(0, g);
boost::add_vertex(1, g);
boost::add_vertex(2, g);
boost::add_vertex(3, g);
boost::add_vertex(4, g);
boost::add_vertex(5, g);
boost::add_vertex(6, g);
// Add edges between vertices.
boost::add_edge(0, 3, g);
boost::add_edge(1, 3, g);
boost::add_edge(1, 4, g);
boost::add_edge(2, 1, g);
boost::add_edge(3, 5, g);
boost::add_edge(4, 6, g);
boost::add_edge(5, 6, g);
// Perform a topological sort.
std::deque<int> topo_order;
boost::topological_sort(g, std::front_inserter(topo_order));
// Print the results.
for(std::deque<int>::const_iterator i = topo_order.begin();
i != topo_order.end();
++i)
{
cout << tasks[v] << endl;
}
return 0;
}
I agree that the boost::graph documentation can be intimidating, but it's worth having a look.
I can't recall if the contents of the printed book is the same, I suspect it's a bit easier on the eyes. I actually learnt to use boost:graph from the book. The learning curve can feel pretty steep though. The book I refer to and reviews can be found here.
This is based off the example given on the boost::graph website, with comments added:
#include <iostream>
#include <utility>
#include <algorithm>
#include <vector>
#include "boost/graph/graph_traits.hpp"
#include "boost/graph/adjacency_list.hpp"
using namespace boost;
int main(int argc, char *argv[])
{
//create an -undirected- graph type, using vectors as the underlying containers
//and an adjacency_list as the basic representation
typedef adjacency_list<vecS, vecS, undirectedS> UndirectedGraph;
//Our set of edges, which basically are just converted into ints (0-4)
enum {A, B, C, D, E, N};
const char *name = "ABCDE";
//An edge is just a connection between two vertitices. Our verticies above
//are an enum, and are just used as integers, so our edges just become
//a std::pair<int, int>
typedef std::pair<int, int> Edge;
//Example uses an array, but we can easily use another container type
//to hold our edges.
std::vector<Edge> edgeVec;
edgeVec.push_back(Edge(A,B));
edgeVec.push_back(Edge(A,D));
edgeVec.push_back(Edge(C,A));
edgeVec.push_back(Edge(D,C));
edgeVec.push_back(Edge(C,E));
edgeVec.push_back(Edge(B,D));
edgeVec.push_back(Edge(D,E));
//Now we can initialize our graph using iterators from our above vector
UndirectedGraph g(edgeVec.begin(), edgeVec.end(), N);
std::cout << num_edges(g) << "\n";
//Ok, we want to see that all our edges are now contained in the graph
typedef graph_traits<UndirectedGraph>::edge_iterator edge_iterator;
//Tried to make this section more clear, instead of using tie, keeping all
//the original types so it's more clear what is going on
std::pair<edge_iterator, edge_iterator> ei = edges(g);
for(edge_iterator edge_iter = ei.first; edge_iter != ei.second; ++edge_iter) {
std::cout << "(" << source(*edge_iter, g) << ", " << target(*edge_iter, g) << ")\n";
}
std::cout << "\n";
//Want to add another edge between (A,E)?
add_edge(A, E, g);
//Print out the edge list again to see that it has been added
for(edge_iterator edge_iter = ei.first; edge_iter != ei.second; ++edge_iter) {
std::cout << "(" << source(*edge_iter, g) << ", " << target(*edge_iter, g) << ")\n";
}
//Finally lets add a new vertex - remember the verticies are just of type int
int F = add_vertex(g);
std::cout << F << "\n";
//Connect our new vertex with an edge to A...
add_edge(A, F, g);
//...and print out our edge set once more to see that it was added
for(edge_iterator edge_iter = ei.first; edge_iter != ei.second; ++edge_iter) {
std::cout << "(" << source(*edge_iter, g) << ", " << target(*edge_iter, g) << ")\n";
}
return 0;
}
I think you will find the following resources very helpful.
Graph Theory Primer
If you are unfamiliar with graph theory or need a refresher, then take a look at boost's Review of Elementary Graph Theory:
http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/graph_theory_review.html
This primer is helpful in understanding the terminology, how data structures represent graphs (adjacency matrix, adjacency list, etc…), and algorithms (breadth-first search, depth-first search, shortest-path, etc…).
Sample Code Described in Detail
For sample code for creating graphs that is described in detail, then take a look at the following section of Boris Schäling's online book - The Boost C++ Libraries:
http://theboostcpplibraries.com/boost.graph-vertices-and-edges
Boris explains how to work with vertices and edges using the adjacenty_list. The code is thoroughly explained so you can understand each example.
Understanding adjacency_list Template Parameters
It is important to understand the template parameters for the adjacency_list. For example, do you want a directed or undirected graph? Do you want your graph to contain multiple edges with the same end nodes (i.e. multigraphs)? Performance also comes into play. Boris' book explains some of these, but you will find additional information on using the adjacenty_list here:
http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/using_adjacency_list.html
Using Custom Objects for Vertices, Edges, or Graphs
If you want to use custom objects for the vertices, edges, or even the graph itself, then you will want to use bundled properties. The following links will be helpful for using bundled properties:
http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/bundles.html
And perhaps this one too for an example:
adding custom vertices to a boost graph
Detecting Circular Dependencies (Cycles)
There are multiple ways to detect circular dependencies including:
Depth-First Search:
One simple way is by performing a depth-first search and detecting if the search runs into an already discovered vertex in the current search tree. Here is an example of detecting cyclic dependencies using boost's depth-first search:
http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/file_dependency_example.html#sec:cycles
Topological Sort:
One can also detect cycles using a topological sort. boost provides a topological_sort algorithm:
http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/topological_sort.html
A topological sort works on a directed acyclic graph (DAG). If a cyclic graph is passed in, then an exception is thrown, thus indicating that the graph has a circular dependency. topological_sort includes a depth-first search, but also provides a linear ordering of the vertices. Here is an example:
http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/file_dependency_example.html#sec:cycles
Strongly Connected Components:
Additionally, finding strongly connected components can indicate whether or not a graph has cycles:
http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/GraphAlgor/strongComponent.htm
boost's strong_components function computes the strongly connected components of a directed graph using Tarjan's algorithm.
http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/strong_components.html
File Dependency Example
Another helpful link is one that was already provided - boost's File Dependency Example that shows how to setup a graph of source code files, order them based on their compilation order (topological sort), determine what files can be compiled simultaneously, and determine cyclic dependencies:
http://www.boost.org/doc/libs/1_58_0/libs/graph/doc/file_dependency_example.html
Boost's adjacency_list is a good way to go, this example creates a directed graph and outputs an image of the graph using AT&T's GraphViz:
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>
int main()
{
using namespace std;
using namespace boost;
/* define the graph type
listS: selects the STL list container to store
the OutEdge list
vecS: selects the STL vector container to store
the vertices
directedS: selects directed edges
*/
typedef adjacency_list< listS, vecS, directedS > digraph;
// instantiate a digraph object with 8 vertices
digraph g(8);
// add some edges
add_edge(0, 1, g);
add_edge(1, 5, g);
add_edge(5, 6, g);
add_edge(2, 3, g);
add_edge(2, 4, g);
add_edge(3, 5, g);
add_edge(4, 5, g);
add_edge(5, 7, g);
// represent graph in DOT format and send to cout
write_graphviz(cout, g);
return 0;
}
The output is a DOT file that you can quickly feed into the dot utility that comes with GraphViz.
Some short and to-the-point recipes in getting started with the Boost C++ libraries can be found here:
Using the Boost Graph Library
These code samples listed on here appear reasonably up to date and appear to compile and work fine. I am finding that some of the online documentation concerning the use of the Boost Graph Library seems to be out of date or produces compilation errors.
There are a number of working examples here including creating directed and undirected graphs, printing the weights of edges, finding minimal spanning trees using Kruskal's algorithm, and maximum flow problems.