I am computing the 2D delaunay triangulation of a few thousand points. Each point has more data associated with it beyond x and y coordinates. Therefore, I was wondering if it is possible to retrieve the index of each point so that I can access my own point struct in another vector.
Currently, as I access vertices from a Face_handle, it returns a point (i.e. x,y coordinates) How can I return each vertex by its ID (index) instead of its x,y coordinates? Thank you.
#include <vector>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_2.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Delaunay_triangulation_2<Kernel> Delaunay;
typedef Kernel::Point_2 Point;
void example() {
std::vector<Point> points;
points.push_back(Point(1,1)); //index 0
points.push_back(Point(1,2)); //index 1
points.push_back(Point(1,3)); //index 2
points.push_back(Point(2,1)); //index 3
points.push_back(Point(2,2)); //index 4
points.push_back(Point(2,3)); //index 5
Delaunay triangulation;
triangulation.insert(points.begin(),points.end());
for(Delaunay::Finite_faces_iterator fit = triangulation.finite_faces_begin();
fit != triangulation.finite_faces_end(); ++fit) {
Delaunay::Face_handle face = fit;
std::cout << "Triangle:\t" << triangulation.triangle(face) << std::endl;
std::cout << "Vertex 0:\t" << triangulation.triangle(face)[0] << std::endl;
}
}
Output (x,y coordinates):
Triangle: 1 3 1 2 2 2
Vertex 0: 1 3
Triangle: 1 2 1 1 2 1
Vertex 0: 1 2
Triangle: 1 3 2 2 2 3
Vertex 0: 1 3
Triangle: 1 2 2 1 2 2
Vertex 0: 1 2
Desired Output (indices):
Triangle: 2 1 4
Vertex 0: 2
Triangle: 1 0 3
Vertex 0: 1
Triangle: 2 4 5
Vertex 0: 2
Triangle: 1 3 4
Vertex 0: 1
You can attach any information to vertices in a triangulation. For example to add indices (unsigned int) you could do the following:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <vector>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Triangulation_vertex_base_with_info_2<unsigned int, Kernel> Vb;
typedef CGAL::Triangulation_data_structure_2<Vb> Tds;
typedef CGAL::Delaunay_triangulation_2<Kernel, Tds> Delaunay;
typedef Kernel::Point_2 Point;
int main() {
std::vector< std::pair<Point,unsigned> > points;
points.push_back( std::make_pair( Point(1,1), 0 ) );
points.push_back( std::make_pair( Point(1,2), 1 ) );
points.push_back( std::make_pair( Point(1,3), 2 ) );
points.push_back( std::make_pair( Point(2,1), 3 ) );
points.push_back( std::make_pair( Point(2,2), 4 ) );
points.push_back( std::make_pair( Point(2,3), 5 ) );
Delaunay triangulation;
triangulation.insert(points.begin(),points.end());
for(Delaunay::Finite_faces_iterator fit = triangulation.finite_faces_begin();
fit != triangulation.finite_faces_end(); ++fit) {
Delaunay::Face_handle face = fit;
std::cout << "Triangle:\t" << triangulation.triangle(face) << std::endl;
std::cout << "Vertex 0:\t" << triangulation.triangle(face)[0] << std::endl;
std::cout << "Vertex 0:\t" << face->vertex(0)->info() << std::endl;
}
}
Related
Suppose, I have a file with 3 column. first 2 column is index of matrix and 3rd column is value of that position in a matrix.
0 0 1
0 1 0
0 2 2
1 0 0
1 1 0
1 2 3
2 0 0
2 1 0
2 2 4
Now i want to search in this file everytime by this loop
for(int a=0; a<8;a=a+2){
for(int b=0; b<8;b=b+2){
for(int c=a; c<2;c++){
for(int d=a; d<2;d++){
//check here c and d is exist in file. if exist then return the 3 column value of that index position and if not then return 0
}
}
}
}
I can not search the value in the whole file every time because it hold the position before the file read in past.please help me I stack on a huge problem in my academia.
Possible solution with std::map for your problem:
First we write every value with the index as key and the value as the mapped value in the map and then we can search for any index:
#include <iostream>
#include <map>
#include <sstream>
#include <string>
int main()
{
std::stringstream stream(
"\
0 0 1\n\
0 1 0\n\
0 2 2\n\
1 0 0\n\
1 1 0\n\
1 2 3\n\
2 0 0\n\
2 1 0\n\
2 2 4\n\
");
std::map<std::pair<int,int>,int> map;
int x, y, value;
while(stream >> x >> y >> value)
{
map.insert({{x, y}, value});
}
int c = 0, d = 2;
auto pos = map.find({c, d});
if(pos != map.end())
{
std::cout << "Value of searched index: " << pos->second << std::endl;
}
return 0;
}
I am solving a graph problem where I have to take input from a file. Below is my input.txt file.
12
1 2
2 3
2 4
2 5
3 6
4 5
4 7
5 2
5 6
5 7
6 3
6 8
7 8
7 10
8 7
9 7
10 9
10 11
11 12
12 10
In the above input.txt file first input is no of vertices and the others till the end of the file are directed edge of Graph. The first one is the source and the second one is the destination. All the input will be read from the input.txt file.
#include <bits/stdc++.h>
#include <fstream>
using namespace std;
class Graph {
private:
int V;
list<int> *l;
public:
Graph(int V) {
this->V = V;
l = new list<int>[V];
}
void addEdge(int source, int destination) {
// As it is a directed graph edge will be source to destination only
l[source].push_back(destination);
}
void printAdjList() {
for(int i = 1; i <= V; i++) {
cout << "Vertex " << i << "-> " ;
for(int previous: l[i]) {
cout << previous << " " ;
}
cout << endl;
}
}
};
int main() {
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
ifstream inputFile;
inputFile.open("input.txt");
int noOfVertex, s, d, noOfEdge=20;
inputFile >> noOfVertex ;
// cout << noOfVertex << endl;
Graph g(noOfEdge);
// while(cin.eof()) {
// // cout << s << " " << d << endl;
// cin >> s >> d;
// g.addEdge(s, d);
// }
if(inputFile) {
while(inputFile >> s >> d) {
// cout << s << " " << d << endl;
g.addEdge(s, d);
}
inputFile.close();
}
else {
cout << "Error opening input file" << endl;
}
g.printAdjList();
return 0;
}
I am getting this result after running the code
Vertex 1-> 2
Vertex 2-> 3 4 5
Vertex 3-> 6
Vertex 4-> 5 7
Vertex 5-> 2 6 7
Vertex 6-> 3 8
Vertex 7-> 8 10
Vertex 8-> 7
Vertex 9-> 7
Vertex 10-> 9 11
Vertex 11-> 12
Vertex 12-> 10
Vertex 13->
Vertex 14->
Vertex 15->
Vertex 16->
Vertex 17->
Vertex 18->
Vertex 19->
I can not take the number of edge for this problem. The number of vetices and given directed edges will be taken one by one line from the file and it will show an adjacency list like that
Vertex 1-> 2
Vertex 2-> 3 4 5
Vertex 3-> 6
Vertex 4-> 5 7
Vertex 5-> 2 6 7
Vertex 6-> 3 8
Vertex 7-> 8 10
Vertex 8-> 7
Vertex 9-> 7
Vertex 10-> 9 11
Vertex 11-> 12
Vertex 12-> 10
How can I take input from the file so that I can get the above output? I have applied many methods but nothing is working.
Your code is wrong for 2 reasons:
you use a hardcoded number of edges when should use the number of vertex
you use an array with an index starting at 0 when the number of the vertex is read from file and does not start at 0
If you want to be safe, you should use a map (or unordered map) int -> list:
...
class Graph {
private:
int V;
unordered_map<int, list<int> > l; // change here
public:
Graph(int V) {
this->V = V;
l.reserve(V); // here
}
...
int noOfVertex, s, d, noOfEdge = 20;
inputFile >> noOfVertex;
// cout << noOfVertex << endl;
Graph g(noOfVertex); // and here
...
That is enough to get as expected:
Vertex 1-> 2
Vertex 2-> 3 4 5
Vertex 3-> 6
Vertex 4-> 5 7
Vertex 5-> 2 6 7
Vertex 6-> 3 8
Vertex 7-> 8 10
Vertex 8-> 7
Vertex 9-> 7
Vertex 10-> 9 11
Vertex 11-> 12
Vertex 12-> 10
I suggest you make your addEdge method more flexible and easier to use. As one problem, if the source input is larger than the size of list your program will crash. The logic should be:
if there is no source vertex, add it
if there is no destination vertex, add it
add link from source to destination.
Here is a more detailed description of the suggested procedure.
/// find vertex "n", returning vertex index, or -1 if missing
int find( int n )
{
loop over graph
if vertex is "n
return index
return -1
}
/// find vertex "n", or add it if not present
int findoradd( int n )
{
int i = find( n );
if( i >= 0 )
return i
return addvertex( n )
}
/// add link between vertices
void addLink( int u, int v )
{
addEdge(
findoradd( u ),
findoradd( v ) );
}
Hi I am pretty new to the Boost libraries. I want to build a graph from a square two dimensional map that will be used for a star algorithm (the map is an array with 1s and 0s for both wall and normal terrain).
The graph should be undirected and change with the size of the map. Each node has 8 edges (except for sides of the map).
I've gone through a few examples but I don't understand the procedure for building graphs of this size since most examples look like this (look bellow) in the boost graph library documentation.
Any help or ideas will be really appreciated
#include <iostream> // for std::cout
#include <utility> // for std::pair
#include <algorithm> // for std::for_each
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
using namespace boost;
int main(int,char*[])
{
// create a typedef for the Graph type
typedef adjacency_list<vecS, vecS, bidirectionalS> Graph;
// Make convenient labels for the vertices
enum { A, B, C, D, E, N };
const int num_vertices = N;
const char* name = "ABCDE";
// writing out the edges in the graph
typedef std::pair<int, int> Edge;
Edge edge_array[] =
{ Edge(A,B), Edge(A,D), Edge(C,A), Edge(D,C),
Edge(C,E), Edge(B,D), Edge(D,E) };
const int num_edges = sizeof(edge_array)/sizeof(edge_array[0]);
// declare a graph object
Graph g(num_vertices);
// add the edges to the graph object
for (int i = 0; i < num_edges; ++i){
add_edge(edge_array[i].first, edge_array[i].second, g);
}
return 0;
}
On second reading of the question it seems like your question is simply how to add nodes and edges.
Here's a start that queries for the number of rows/columns and creates the square "grid". I use a nodes matrix on the side to have easy lookup from (x,y) in the grid to the vertex descriptor in the graph.
Live On Coliru
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_utility.hpp>
#include <iostream>
using namespace boost;
struct Point {
int x, y;
friend std::ostream& operator<<(std::ostream& os, Point p) {
return os << "[" << p.x << "," << p.y << "]";
}
};
int main() {
using std::vector;
using Graph = adjacency_list<setS, vecS, undirectedS, Point>;
using vertex_descriptor = Graph::vertex_descriptor;
Graph lattuce;
int num_rows;
if (!(std::cin >> num_rows && num_rows > 0))
return 255;
vector<vector<vertex_descriptor> > nodes(num_rows, vector<vertex_descriptor>(num_rows));
for (auto i = 0; i < num_rows; ++i)
for (auto j = 0; j < num_rows; ++j)
nodes[i][j] = add_vertex(Point{i,j}, lattuce);
auto is_valid = [num_rows](Point p) { return (p.x >= 0 && p.x < num_rows) &&
(p.y >= 0 && p.y < num_rows); };
for (auto vd : make_iterator_range(vertices(lattuce))) {
auto p = lattuce[vd];
for (Point neighbour : {
Point { p.x - 1, p.y - 1 }, Point { p.x - 1, p.y + 0 }, Point { p.x - 1, p.y + 1 },
Point { p.x + 0, p.y - 1 }, Point { p.x + 0, p.y + 1 },
Point { p.x + 1, p.y - 1 }, Point { p.x + 1, p.y + 0 }, Point { p.x + 1, p.y + 1 },
})
{
if (is_valid(neighbour))
add_edge(nodes[neighbour.x][neighbour.y], vd, lattuce);
};
}
print_graph(lattuce, get(vertex_bundle, lattuce));
}
Prints, e.g. for input 3:
[0,0] <--> [0,1] [1,0] [1,1]
[0,1] <--> [0,0] [0,2] [1,0] [1,1] [1,2]
[0,2] <--> [0,1] [1,1] [1,2]
[1,0] <--> [0,0] [0,1] [1,1] [2,0] [2,1]
[1,1] <--> [0,0] [0,1] [0,2] [1,0] [1,2] [2,0] [2,1] [2,2]
[1,2] <--> [0,1] [0,2] [1,1] [2,1] [2,2]
[2,0] <--> [1,0] [1,1] [2,1]
[2,1] <--> [1,0] [1,1] [1,2] [2,0] [2,2]
[2,2] <--> [1,1] [1,2] [2,1]
I am trying to determine whether a point within a shape.
I found a algorithm that does the job
https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html
I tested the algorithm out with a square shape.
total corners of a square = 4
but however it returns me a wrong result.(see my output results below) after my codes
Shape.h
#ifndef __Shape__Shape__
#define __Shape__Shape__
class Shape {
private:
int xArray[4];
int yArray[4];
int x;
int y;
public:
bool inPoly(int x,int y);
void pointInShape();
};
#endif
Shape.cpp
#include "Shape.h"
#include <iostream>
bool Shape::inPoly(int x,int y) {
xArray[0] = 1;
xArray[1] = 1;
xArray[2] = 3;
xArray[3] = 3;
yArray[0] = 1;
yArray[1] = 3;
yArray[2] = 3;
yArray[3] = 1;
int i, j, nvert = 4, c = 0;
for (i = 0, j = nvert - 1; i < nvert; j = i++) {
if ( ((yArray[i]>y) != (yArray[j]>y)) &&
(x < (xArray[j]-xArray[i]) * (y-yArray[i]) / (yArray[j]-yArray[i]) + xArray[i]) )
c = !c;
}
return c;
}
void Shape::pointInShape() {
std::cout << "results" << std::endl;
std::cout << inPoly(1,1) << std::endl;
std::cout << inPoly(1,2) << std::endl;
std::cout << inPoly(1,3) << std::endl;
std::cout << inPoly(2,1) << std::endl;
std::cout << inPoly(2,2) << std::endl;
std::cout << inPoly(2,3) << std::endl;
std::cout << inPoly(3,1) << std::endl;
std::cout << inPoly(3,2) << std::endl;
std::cout << inPoly(3,3) << std::endl;
}
main.cpp
#include "Shape.h"
#include <iostream>
int main() {
Shape shape;
shape.pointInShape();
}
it returns me this output
results
1 <-- (means that 1,1 is is within polygon)
1 <-- (means that 1,2 is is within polygon)
0 <-- (means that 1,3 is is not within polygon)
1 <-- (means that 2,1 is is within polygon)
1 <-- (means that 2,2 is is within polygon)
0 <-- (means that 2,3 is is not within polygon)
0 <-- (means that 3,1 is is not within polygon)
0 <-- (means that 3,2 is is not within polygon)
0 <-- (means that 3,3 is is not within polygon)
by right the correct output should only return 2,2 as true
correct output
results
0 <-- (means that 1,1 is not within polygon)
0 <-- (means that 1,2 is not within polygon)
0 <-- (means that 1,3 is not within polygon)
0 <-- (means that 2,1 is not within polygon)
1 <-- (2,2 is is within polygon)
0 <-- (means that 2,3 is is not within polygon)
0 <-- (means that 3,1 is is not within polygon)
0 <-- (means that 3,2 is is not within polygon)
0 <-- (means that 3,3 is is not within polygon)
Any advice/suggestions?
the PNPOLY code as written is really meant for floats not ints. If you defined your arrays and vertices as floats it would give you the expected results.
1.0f and 2.0f are not adjacent in float math, but 1 and 2 are in int math.
what should tip you off is the function prototype
int pnpoly(int nvert, float *vertx, float *verty, float testx, float testy)
furthermore the line:
(testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
is going to truncate your ints to the nearest int after those divides.
If you really want to use ints you would have to define your shapes with a more room, say 100x100 instead of 2x2.
According to your link and this one: http://www.faqs.org/faqs/graphics/algorithms-faq/ (see section 2.03) the algorithm you've used will only work for points in the inside/outside of the polygon. Points on the border may return a 1 or a 0
If you want to know when a point is exactly on the boundary, you need another program. This is only one of many functions that PNPOLY lacks; it also doesn't predict tomorrow's weather. You are free to extend PNPOLY's source code.
Can you please post example code to levelize a directed graph using BGL?
Definition of levelization: Vertex has a property "int level". During BFS traversal of the graph, when a vertex is being "examined", look at its predecessor vertices' levels, take max of these, increment, and assign this to the "level" of this vertex.
If you mean the BFS depth then this is already built in to boost BFS and can be gotten easily.
Just use a vector to store the depths and a depth BFS visitor like this example I made:
#include <iostream>
#include <vector>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/breadth_first_search.hpp>
using namespace std;
using namespace boost;
typedef adjacency_list < vecS, vecS, directedS,
property< vertex_index_t, size_t> ,
property< edge_index_t, size_t > > Graph;
typedef graph_traits<Graph>::vertex_descriptor Vertex;
typedef graph_traits<Graph>::edge_descriptor Edge;
int main(int argc, char* argv[]){
Graph G;
vector<Vertex> verts;
for(size_t i = 0; i < 9; ++i){
Vertex v = add_vertex(G);
verts.push_back(v);
}
/*
0 0
/ \
1 1 4
/ \
2 2 5
/ \
3 3 6
\
4 7
\
5 8
*/
add_edge(verts.at(0),verts.at(1),G);
add_edge(verts.at(1),verts.at(2),G);
add_edge(verts.at(2),verts.at(3),G);
add_edge(verts.at(0),verts.at(4),G);
add_edge(verts.at(4),verts.at(5),G);
add_edge(verts.at(5),verts.at(6),G);
add_edge(verts.at(6),verts.at(7),G);
add_edge(verts.at(7),verts.at(8),G);
cout << "vertices " << num_vertices(G) << endl;
cout << "edges " << num_edges(G) << endl;
//store depths
vector<size_t> d(num_vertices(G));
//get an index map, from Graph definition property< vertex_index_t, size_t>
typedef boost::property_map< Graph, boost::vertex_index_t>::type VertexIndexMap;
VertexIndexMap v_index = get(boost::vertex_index, G);
// Create the external property map, this map wraps the storage vector d
boost::iterator_property_map< std::vector< size_t >::iterator, VertexIndexMap >
d_map(d.begin(), v_index);
//Start at 0
boost::breadth_first_search(G, verts.at(0),
boost::visitor(boost::make_bfs_visitor(
boost::record_distances(d_map, boost::on_tree_edge())
)));
cout << "Starting at 0" << endl;
for(size_t i = 0; i < 9; ++i){
//depth (level) of BFS
cout << "vertex " << i << "\t" << d.at(i) << endl;
}
vector<size_t> d2(num_vertices(G));
cout << "Starting at 4" << endl;
// Create the external property map, this map wraps the storage vector d
boost::iterator_property_map< std::vector< size_t >::iterator, VertexIndexMap >
d2_map(d2.begin(), v_index);
//start at 4
boost::breadth_first_search(G, verts.at(4),
boost::visitor(boost::make_bfs_visitor(
boost::record_distances(d2_map, boost::on_tree_edge())
)));
for(size_t i = 0; i < 9; ++i){
//depth (level) of BFS
cout << "vertex " << i << "\t" << d2.at(i) << endl;
}
}
Output should look like this:
vertices 9
edges 8
Starting at 0
vertex 0 0
vertex 1 1
vertex 2 2
vertex 3 3
vertex 4 1
vertex 5 2
vertex 6 3
vertex 7 4
vertex 8 5
Starting at 4
vertex 0 0
vertex 1 0
vertex 2 0
vertex 3 0
vertex 4 0
vertex 5 1
vertex 6 2
vertex 7 3
vertex 8 4
When you start at 4 the other vertices are not reachable (directed) so the vector contains default values (0 in this case). This should work for undirected too.