OpenMesh find edge connecting two vertices - openmesh

Is there a readily available function in OpenMesh that returns the edge handle connecting two vertices? For half edges there is the find_halfedge(vertex1, vertex2) function, but I could not find a corresponding find_edge(vertex1, vertex2) function. Currently I'm using my own, but I was wondering if there is any better way than this. Essentially I'm iterating over the surrounding edges of the two vertices and check where their halfedges point to:
MyMesh::EdgeHandle find_edge(MyMesh & mesh, MyMesh::VertexHandle & v1, MyMesh::VertexHandle & v2 ){
for (MyMesh::VertexEdgeIter edge = mesh.ve_iter(v1); edge.is_valid(); ++edge){
if( (mesh.from_vertex_handle((*edge).h0())==v1) && (mesh.to_vertex_handle((*edge).h0())==v2)){
return *edge;
}
if( (mesh.from_vertex_handle((*edge).h0())==v2) && (mesh.to_vertex_handle((*edge).h0())==v1)){
return *edge;
}
}
std::cout<<"No common edge between v1 and v2"<<std::endl;
MyMesh::EdgeHandle edge_null;
return edge_null;
}

There is no built-in find_edge method, but you can readily construct one from find_halfedge, as halfedges know which edge they belong to:
MyMesh::EdgeHandle find_edge(const MyMesh& m, MyMesh::VertexHandle v1, MyMesh::VertexHandle v2)
{
MyMesh::HalfedgeHandle heh = m.find_halfedge(v1, v2);
if (heh.is_valid()) {
return m.edge_handle(heh);
}
else {
return MyMesh::InvalidEdgeHandle;
}
}

Related

How to increase efficiency of Prim's algorithm used in finding minimum spanning tree from adjacency matrix of an undirected graph?

I have implemented an undirected graph using adjacency matrix. Now I want to find the edges in the minimum spanning tree that can be obtained by using Prim's Algorithm (along with priority queue). I did that using classic method, but it is highly inefficient (giving correct results). On larger data sets (of vertices and the vertices that they are connected to.).
This is the implementation of Prim's algorithm using priority queue as i used in my code. (This is the code from site geeksforgeeks, the code i wrote is an inspiration from this.)
void Graph::primMST()
{
// Create a priority queue to store vertices that
// are being primMST. This is weird syntax in C++.
// Refer below link for details of this syntax
// http://geeksquiz.com/implement-min-heap-using-stl/
priority_queue< iPair, vector <iPair> , greater<iPair> > pq;
int src = 0; // Taking vertex 0 as source
// Create a vector for keys and initialize all
// keys as infinite (INF)
vector<int> key(V, INF);
// To store parent array which in turn store MST
vector<int> parent(V, -1);
// To keep track of vertices included in MST
vector<bool> inMST(V, false);
// Insert source itself in priority queue and initialize
// its key as 0.
pq.push(make_pair(0, src));
key[src] = 0;
/* Looping till priority queue becomes empty */
while (!pq.empty())
{
// The first vertex in pair is the minimum key
// vertex, extract it from priority queue.
// vertex label is stored in second of pair (it
// has to be done this way to keep the vertices
// sorted key (key must be first item
// in pair)
int u = pq.top().second;
pq.pop();
//Different key values for same vertex may exist in the priority queue.
//The one with the least key value is always processed first.
//Therefore, ignore the rest.
if(inMST[u] == true){
continue;
}
inMST[u] = true; // Include vertex in MST
// 'i' is used to get all adjacent vertices of a vertex
list< pair<int, int> >::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
{
// Get vertex label and weight of current adjacent
// of u.
int v = (*i).first;
int weight = (*i).second;
// If v is not in MST and weight of (u,v) is smaller
// than current key of v
if (inMST[v] == false && key[v] > weight)
{
// Updating key of v
key[v] = weight;
pq.push(make_pair(key[v], v));
parent[v] = u;
}
}
}
// Print edges of MST using parent array
for (int i = 1; i < V; ++i)
printf("%d - %d\n", parent[i], i);
}
Thanks in advance.

How to detect and save cyclic connectivity in edge vertices (hole detection)?

thanks for taking the time to read my question.
I am working on detecting holes in a triangular mesh and fill them with new triangles. I have done some of the parts that are, to get a list of edge vertices, etc. Following are the vertices/edges that make holes, please have a look at the image.
(9, 62) => vertex # 9 and 62 makes an edge (left hole)
(66, 9) => vertex # 66 and 9 makes an edge (left hole)
(70, 66) => vertex # 70 and 66 makes an edge (left hole)
(62, 70) => vertex # 62 and 70 makes an edge (left hole)
(147, 63) => vertex # 147 and 63 makes an edge (right hole)
(55, 148)
(63, 149)
(149, 55)
(148, 147)
The first thing that I need to do is to check which vertices make a cycle (means a hole is detected), and then save in a separate set of cyclic vertices.
The issue is to write such an algorithm that checks whether the given graph(vertices/edges) contains how many cycles? and then save into separate sets.
Please write me some simple and optimized algorithm to solve this problem.
Thank you.
mesh
Let assume your STL mesh got n triangles you need to convert it into indexed format. So extract all triangle points and convert to two separate tables. one holding all the points and second holding 3 indexes of points per each triangle. Let assume you got m points and n triangles.
You should have the point table (index) sorted and using binary search to speed this up from O(n.m) to O(m.log(n)).
_edge structure
create structure that holds all the edges of your mesh. Something like:
struct _edge
{
int p0,p1; // used vertexes index
int cnt; // count of edge usage
};
where p0<p1.
create _edge edge[] table O(n)
It should be a list holding all the edges (3n) so loop through all the triangles and add 3 edges per each. The count set to cnt=1 This is O(n).
Now sort the list by p0,p1 which is O(n.log(n)). After that just join all the edges with the same p0,p1 by summing their cnt and deleting one of them. If coded right then this is O(n).
detect hole
In regular STL each edge must have cnt=2. If cnt=1 then triangle is missing and you found your hole. if cnt>2 you got geometric error in your mesh.
So delete all edges with cnt>=2 from your edge[] table which is O(n).
detect loops
let assume we got k edges left in our edge[] table. Now for each 2 edges that are sharing a point create triangle. Something like:
for (i=0;i<k;i++)
for (j=i+1;j<k;j++)
{
if ((edge[i].p0==edge[j].p0)||(edge[i].p1==edge[j].p0)) add_triangle(edge[i].p0,edge[i].p1,edge[j].p1);
if ((edge[i].p0==edge[j].p1)||(edge[i].p1==edge[j].p1)) add_triangle(edge[i].p0,edge[i].p1,edge[j].p0);
}
If you use binary search for the inner loop then this will be O(k.log(k)). Also you should avoid to add duplicate triangles and correct the winding of them so first add the triangles to separate table (or remember starting index) and then remove duplicates (or you can do it directly in add_triangle).
Also to handle bigger holes do not forget to add new edges to your edge[] table. You can either update the edges after current edges are processed and repeat #4 or incorporate the changes on the run.
[Edit1] C++ example
recently I was doing some coding for STL for this QA:
Generating outside supporters into mesh for 3D printing
So as I got all the infrastructure already coded I chose to give this a shot and here the result:
struct STL3D_edge
{
int p0,p1,cnt,dir;
STL3D_edge() {}
STL3D_edge(STL3D_edge& a) { *this=a; }
~STL3D_edge() {}
STL3D_edge* operator = (const STL3D_edge *a) { *this=*a; return this; }
//STL3D_edge* operator = (const STL3D_edge &a) { ...copy... return this; }
int operator == (const STL3D_edge &a) { return ((p0==a.p0)&&(p1==a.p1)); }
int operator != (const STL3D_edge &a) { return ((p0!=a.p0)||(p1!=a.p1)); }
void ld(int a,int b) { cnt=1; if (a<=b) { dir=0; p0=a; p1=b; } else { dir=1; p0=b; p1=a; }}
};
List<STL3D_edge> edge;
List<float> pnt;
void edge_draw()
{
int i; STL3D_edge *e;
glBegin(GL_LINES);
for (e=edge.dat,i=0;i<edge.num;i++,e++)
{
glVertex3fv(pnt.dat+e->p0);
glVertex3fv(pnt.dat+e->p1);
}
glEnd();
}
void STL3D::holes()
{
// https://stackoverflow.com/a/45541861/2521214
int i,j,i0,i1,i2,j0,j1,j2;
float q[3];
_fac *f,ff;
STL3D_edge *e,ee,*e0,*e1,*e2;
ff.attr=31<<5; // patched triangles color/id
// create some holes for testing
if (fac.num<100) return;
for (i=0;i<10;i++) fac.del(Random(fac.num));
// compute edge table
edge.allocate(fac.num*3); edge.num=0;
for (f=fac.dat,i=0;i<fac.num;i++,f++)
{
// add/find points to/in pnt[]
for (i0=-1,j=0;j<pnt.num;j+=3){ vectorf_sub(q,pnt.dat+j,f->p[0]); if (vectorf_len2(q)<1e-6) { i0=j; break; }} if (i0<0) { i0=pnt.num; for (j=0;j<3;j++) pnt.add(f->p[0][j]); }
for (i1=-1,j=0;j<pnt.num;j+=3){ vectorf_sub(q,pnt.dat+j,f->p[1]); if (vectorf_len2(q)<1e-6) { i1=j; break; }} if (i1<0) { i1=pnt.num; for (j=0;j<3;j++) pnt.add(f->p[1][j]); }
for (i2=-1,j=0;j<pnt.num;j+=3){ vectorf_sub(q,pnt.dat+j,f->p[2]); if (vectorf_len2(q)<1e-6) { i2=j; break; }} if (i2<0) { i2=pnt.num; for (j=0;j<3;j++) pnt.add(f->p[2][j]); }
// add edges
ee.ld(i0,i1); for (e=edge.dat,j=0;j<edge.num;j++,e++) if (*e==ee) { e->cnt++; j=-1; break; } if (j>=0) edge.add(ee);
ee.ld(i1,i2); for (e=edge.dat,j=0;j<edge.num;j++,e++) if (*e==ee) { e->cnt++; j=-1; break; } if (j>=0) edge.add(ee);
ee.ld(i2,i0); for (e=edge.dat,j=0;j<edge.num;j++,e++) if (*e==ee) { e->cnt++; j=-1; break; } if (j>=0) edge.add(ee);
}
// delete even times used edges (to speed up the loops finding)
for (i0=i1=0,e0=e1=edge.dat;i0<edge.num;i0++,e0++)
if (int(e0->cnt&1)==1) { *e1=*e0; i1++; e1++; } edge.num=i1;
// find 2 edges with one comon point (j1)
for (e0=edge.dat,i0=0;i0<edge.num;i0++,e0++) if (int(e0->cnt&1)==1)
for (e1=e0+1,i1=i0+1;i1<edge.num;i1++,e1++) if (int(e1->cnt&1)==1)
{
// decide which points to use
j0=-1; j1=-1; j2=-1;
if (e0->p0==e1->p0) { j0=e0->p1; j1=e0->p0; j2=e1->p1; }
if (e0->p0==e1->p1) { j0=e0->p1; j1=e0->p0; j2=e1->p0; }
if (e0->p1==e1->p0) { j0=e0->p0; j1=e0->p1; j2=e1->p1; }
if (e0->p1==e1->p1) { j0=e0->p0; j1=e0->p1; j2=e1->p0; }
if (j2<0) continue;
// add missin triangle
if (e0->dir)
{
vectorf_copy(ff.p[0],pnt.dat+j1);
vectorf_copy(ff.p[1],pnt.dat+j0);
vectorf_copy(ff.p[2],pnt.dat+j2);
}
else{
vectorf_copy(ff.p[0],pnt.dat+j0);
vectorf_copy(ff.p[1],pnt.dat+j1);
vectorf_copy(ff.p[2],pnt.dat+j2);
}
ff.compute();
fac.add(ff);
// update edges
e0->cnt++;
e1->cnt++;
ee.ld(j0,j2); for (e=edge.dat,j=0;j<edge.num;j++,e++) if (*e==ee) { e->cnt++; j=-1; break; } if (j>=0) edge.add(ee);
break;
}
}
The full C++ code and description for the STL3D class is in the link above. I used some sphere STL mesh I found in my archive and color the hole patching triangles in green to recognize them. Here the result:
The black lines are wireframe and red ones are just debug draw of the edge[],pnt[] arrays for debug ...
As you can see it works even for holes bigger than just single triangle :) ...

Detected Cycle in directed graph if the vertex is found in recursive stack-why?

I have read an article from here about how to detect cycle in a directed graph. The basic concept of this algorithm is if a node is found in recursive stack then there is a cycle, but i don't understand why. what is the logic here?
#include<iostream>
#include <list>
#include <limits.h>
using namespace std;
class Graph
{
int V; // No. of vertices
list<int> *adj; // Pointer to an array containing adjacency lists
bool isCyclicUtil(int v, bool visited[], bool *rs);
public:
Graph(int V); // Constructor
void addEdge(int v, int w); // to add an edge to graph
bool isCyclic(); // returns true if there is a cycle in this graph
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list.
}
bool Graph::isCyclicUtil(int v, bool visited[], bool *recStack)
{
if(visited[v] == false)
{
// Mark the current node as visited and part of recursion stack
visited[v] = true;
recStack[v] = true;
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for(i = adj[v].begin(); i != adj[v].end(); ++i)
{
if ( !visited[*i] && isCyclicUtil(*i, visited, recStack) )
return true;
else if (recStack[*i])
return true;
}
}
recStack[v] = false; // remove the vertex from recursion stack
return false;
}
bool Graph::isCyclic()
{
// Mark all the vertices as not visited and not part of recursion
// stack
bool *visited = new bool[V];
bool *recStack = new bool[V];
for(int i = 0; i < V; i++)
{
visited[i] = false;
recStack[i] = false;
}
for(int i = 0; i < V; i++)
if (isCyclicUtil(i, visited, recStack))
return true;
return false;
}
int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
if(g.isCyclic())
cout << "Graph contains cycle";
else
cout << "Graph doesn't contain cycle";
return 0;
}
From a brief look, the code snippet is an implementation of depth-first search, which is a basic search technique for directed graphs; the same approach works for breadth-first search. Note that apparently this implementation works only if there is only one connected component, otherwise the test must be performed for each connected component until a cycle is found.
That being said, the technique works by choosing one node at will and starting a recursive search there. Basically, if the search discovers a node that is in the stack, there must be a cycle, since it has been previously reached.
In the current implementation, recStack is not actually the stack, it just indicates whether a specific node is currently in the stack, no sequence information is stored. The actual cycle is contained implicitly in the call stack. The cycle is the sequence of nodes for which the calls of isCyclicUtil has not yet returned. If the actual cycle has to be extracted, the implementation must be changed.
So essentailly, what this is saying, is if a node leads to itself, there is a cycle. This makes sense if you think about it!
Say we start at node1.
{node1 -> node2}
{node2 -> node3}
{node3 -> node4
node3 -> node1}
{node4 -> end}
{node1 -> node2}
{node2 -> node3}.....
This is a small graph that contains a cycle. As you can see, we traverse the graph, going from each node to the next. In some cases we reach and end, but even if we reach the end, our code wants to go back to the other branch off of node3 so that it can check it's next node. This node then leads back to node1.
This will happen forever if we let it, because the path starting at node1 leads back to itself. We are recursively putting each node we visit on the stack, and if we reach an end, we remove all of the nodes from the stack AFTER the branch. In our case, we would be removing node4 from the stack every time we hit the end, but the rest of the nodes would stay on the stack because of the branch off of node3.
Hope this helps!

Can I use just a simple Set for cycle detection in directed graph?

I have seen quite a lot of algorithms to do cycle detection, such as Tarjan's strongly connected components algorithm answered in Best algorithm for detecting cycles in a directed graph.
I never thought detecting a cycle would be that complicated and I always believed a simple Set can help solve the problem.
So in addition to the usual marker array for recording visited vertices, we can use an additional Set to record all vertices along a path from the source.
The key thing is to remember to remove a vertex from the set after all its next neighbours are done.
A trivial code is like this:
public boolean hasCycle(List<Integer>[] vs) {
boolean[] marker = new boolean[v.length];
Set<Integer> tracker = new HashSet<Integer>();
for(int v = 0;v < vs.length;v++)
if (explore(v, vs, marker, tracker)) return true;
return false;
}
private boolean explore(int v, List<Integer>[] vs, boolean[] marker, Set<Integer> tracker) {
if (tracker.contains(v)) return true;
else if (!marker[v]) {
marker[v] = true;
tracker.add(v); // add current vertex to tracker
for (int u:vs[v]) if (explore(v, vs, marker, tracker)) return true;
tracker.remove(v); // remove the vertex from tracker, as it is fully done.
}
else return false;
}
Is there any problem about this algorithm?
With help from sasha's answer, actually even the set is not necessary and just an array is enough.
public boolean hasCycle(List<Integer>[] vs) {
boolean[] marker = new boolean[v.length];
boolean[] onPath = new boolean[v.length];
for(int v = 0;v < vs.length;v++)
if (explore(v, vs, marker, onPath)) return true;
return false;
}
private boolean explore(int v, List<Integer>[] vs, boolean[] marker, boolean[] onPath) {
if (onPath[v]) return true;
else if (!marker[v]) {
marker[v] = true;
onPath[v] = true; // add current vertex to the path
for (int u:vs[v]) if (explore(v, vs, marker, onPath)) return true;
onPath[v] = false; // remove the vertex from the path, as it is fully done.
}
else return false;
}
I am not an expert in java but talking about C++ passing set etc in recursion is not time efficient. Also set takes O(log(n)) in inserting/deleting an element. Your logic looks correct to me. But you can do it more efficiently and easily by keeping two arrays parent[] and visited[]. Basically do a bfs and following is the pseudo code ( visited is initialized to all zeros ) .
/* There are n nodes from 0 to n-1 */
visited[0]=1
parent[0]=0
flag=0
queue.push(0)
while the queue is not empty
top = queue.front()
queue.pop()
for all neighbors x of top
if not visited[top]
visited[x]=1
parent[x]=top
queue.push(x)
else if visited[x] is 1 and parent[top] is not x
flag = 1
if flag is 1 cycle is there otherwise not
As it may not be necessary that starting from 0 all nodes are visited . So repeat until all nodes are visited. Complexity is O(E+V) slightly better than the complexity of your method O(E+VlogV). But it is simple to write and not recursive.

Writing a program to check if a graph is bipartite

I need to write a program that check if a graph is bipartite.
I have read through wikipedia articles about graph coloring and bipartite graph. These two article suggest methods to test bipartiteness like BFS search, but I cannot write a program implementing these methods.
Why can't you? Your question makes it hard for someone to even write the program for you since you don't even mention a specific language...
The idea is to start by placing a random node into a FIFO queue (also here). Color it blue. Then repeat this while there are nodes still left in the queue: dequeue an element. Color its neighbors with a different color than the extracted element and insert (enqueue) each neighbour into the FIFO queue. For example, if you dequeue (extract) an element (node) colored red, color its neighbours blue. If you extract a blue node, color its neighbours red. If there are no coloring conflicts, the graph is bipartite. If you end up coloring a node with two different colors, than it's not bipartite.
Like #Moron said, what I described will only work for connected graphs. However, you can apply the same algorithm on each connected component to make it work for any graph.
http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/GraphAlgor/breadthSearch.htm
Please read this web page, using breadth first search to check when you find a node has been visited, check the current cycle is odd or even.
A graph is bipartite if and only if it does not contain an odd cycle.
The detailed implementation is as follows (C++ version):
struct NODE
{
int color;
vector<int> neigh_list;
};
bool checkAllNodesVisited(NODE *graph, int numNodes, int & index);
bool checkBigraph(NODE * graph, int numNodes)
{
int start = 0;
do
{
queue<int> Myqueue;
Myqueue.push(start);
graph[start].color = 0;
while(!Myqueue.empty())
{
int gid = Myqueue.front();
for(int i=0; i<graph[gid].neigh_list.size(); i++)
{
int neighid = graph[gid].neigh_list[i];
if(graph[neighid].color == -1)
{
graph[neighid].color = (graph[gid].color+1)%2; // assign to another group
Myqueue.push(neighid);
}
else
{
if(graph[neighid].color == graph[gid].color) // touble pair in the same group
return false;
}
}
Myqueue.pop();
}
} while (!checkAllNodesVisited(graph, numNodes, start)); // make sure all nodes visited
// to be able to handle several separated graphs, IMPORTANT!!!
return true;
}
bool checkAllNodesVisited(NODE *graph, int numNodes, int & index)
{
for (int i=0; i<numNodes; i++)
{
if (graph[i].color == -1)
{
index = i;
return false;
}
}
return true;
}

Resources