#include "dual.h" #include #include dual::dual(PLYObject& ply) :_ply(ply) { /* Construct the dual graph from the _ply */ constructDualGraph(); } dual::~dual() { _vertices.clear(); _nodes.clear(); _edges.clear(); } void dual::constructDualGraph() { /* Use the connectivity information already built in _ply to create the dual graph */ fprintf(stderr,"Constructing Dual Graph\n"); /* Store the vertex information locally in a vector */ for(int i=0 ; i<_ply.nv ; i++) { avertex v; v.x = _ply.vertices[i][0]; v.y = _ply.vertices[i][1]; v.z = _ply.vertices[i][2]; v.nx = _ply.normals[i][0]; v.ny = _ply.normals[i][1]; v.nz = _ply.normals[i][2]; if (_ply.hascolor) { v.cr = _ply.colors[i][0]; v.cg = _ply.colors[i][1]; v.cb = _ply.colors[i][2]; } if (_ply.hastexture) { v.u = _ply.texcoords[i][0]; v.v = _ply.texcoords[i][1]; } _vertices.push_back(v); } /* Iterate over the nodes */ for(int i=0 ; i<_ply.nf ; i++) { dualnode n; n.v1 = _ply.faces[i][0]; n.v2 = _ply.faces[i][1]; n.v3 = _ply.faces[i][2]; n.e1 = _ply.nodes[i][0]; n.e2 = _ply.nodes[i][1]; n.e3 = _ply.nodes[i][2]; n.fnx = _ply.fnormals[i][0]; n.fny = _ply.fnormals[i][1]; n.fnz = _ply.fnormals[i][2]; _nodes.push_back(n); } for(int i=0 ; i<_ply.ne ; i++) { dualedge e; e.v1 = _ply.edges[i][0]; e.v2 = _ply.edges[i][1]; _edges.push_back(e); } hascolor = _ply.hascolor; hastexture = _ply.hastexture; #if 1 /* Delete duplicate info in _ply */ delete _ply.vertices; delete _ply.normals; delete _ply.colors; delete _ply.texcoords; delete _ply.faces; delete _ply.edges; delete _ply.nodes; delete _ply.fnormals; #endif } /* no of boundary edges in node */ int dual::boundaryEdges(int n) { int count = 0; if (-1==_nodes[n].e1) count++; if (-1==_nodes[n].e2) count++; if (-1==_nodes[n].e3) count++; return count; } /* number of boundary neighbors */ int dual::boundaryNeighbors(int n) { /* This guy mustn't be a boundary */ assert((-1 != _nodes[n].e1)&&(-1 != _nodes[n].e2)&&(-1 != _nodes[n].e3)); int count = 0; if (boundaryEdges(neighbor(n,_nodes[n].e1))!=0) count++; if (boundaryEdges(neighbor(n,_nodes[n].e2))!=0) count++; if (boundaryEdges(neighbor(n,_nodes[n].e3))!=0) count++; return count; } /* Find the edge to the only non-boundary neighbor for some guy */ int dual::nonBoundaryNeighborEdge(int n) { assert(2 == boundaryNeighbors(n)); if (boundaryEdges(neighbor(n,_nodes[n].e1))==0) return _nodes[n].e1; if (boundaryEdges(neighbor(n,_nodes[n].e2))==0) return _nodes[n].e2; if (boundaryEdges(neighbor(n,_nodes[n].e3))==0) return _nodes[n].e3; fprintf(stderr,"Error in finding non-boundary neighbor edge\n"); return -1; } /* Swap */ void dual::swap(int& n1, int& n2) { int temp = n1; n1 = n2; n2 = temp; } /* Assign edges to the vertex */ void dual::assignEdges(int n, int e1, int e2, int e3) { _nodes[n].e1 = e1; _nodes[n].e2 = e2; _nodes[n].e3 = e3; } /* Add a steiner vertex */ int dual::addSteinerVertex(int indexv1, int indexv2) { //fprintf(stderr,"Adding steiner vertex\n"); #if 1 avertex v; avertex v1 = _vertices[indexv1]; avertex v2 = _vertices[indexv2]; v.x = (v1.x + v2.x)/2; v.y = (v1.y + v2.y)/2; v.z = (v1.z + v2.z)/2; v.nx = (v1.nx + v2.nx)/2; v.ny = (v1.ny + v2.ny)/2; v.nz = (v1.nz + v2.nz)/2; v.cr = (v1.cr + v2.cr)/2; v.cg = (v1.cg + v2.cg)/2; v.cb = (v1.cb + v2.cb)/2; _vertices.push_back(v); return _vertices.size() - 1; #endif //return indexv1; } /* Find the neighbor of a node along a given adge */ int dual::neighbor(int n, int e) { if (e == -1) return -1; assert((_edges[e].v1 == n)||(_edges[e].v2 == n)); if (n == _edges[e].v1) return _edges[e].v2; if (n == _edges[e].v2) return _edges[e].v1; fprintf(stderr,"Error no neighbor found\n"); return -1; } /* Find the index of the common vertex in the 3 nodes(faces) */ int dual::commonVertex(int n1, int n2, int n3) { if (vertexInNode(_nodes[n1].v1, n2) && vertexInNode(_nodes[n1].v1, n3)) return _nodes[n1].v1; if (vertexInNode(_nodes[n1].v2, n2) && vertexInNode(_nodes[n1].v2, n3)) return _nodes[n1].v2; if (vertexInNode(_nodes[n1].v3, n2) && vertexInNode(_nodes[n1].v3, n3)) return _nodes[n1].v3; fprintf(stderr,"Error no common vertex\n"); return -1; } /* Returns a common edge index between 2 nodes */ int dual::commonEdge(int n1, int n2) { if (neighbor(n1, _nodes[n1].e1) == n2) return _nodes[n1].e1; if (neighbor(n1, _nodes[n1].e2) == n2) return _nodes[n1].e2; if (neighbor(n1, _nodes[n1].e3) == n2) return _nodes[n1].e3; fprintf(stderr,"Nodes not adjacent \n"); return -1; } /* Check if the vertex is present in the node */ bool dual::vertexInNode(int v, int n) { return ((_nodes[n].v1 == v)||(_nodes[n].v2 == v)||(_nodes[n].v3 == v)); } /* orient a new node according to some other node with which it shares 2 vertices */ void dual::orient(dualnode& node) { /* Find the normal and compare with the face normal */ Vector3f v1; v1[0] = _vertices[node.v1].x; v1[1] = _vertices[node.v1].y; v1[2] = _vertices[node.v1].z; Vector3f v2; v2[0] = _vertices[node.v2].x; v2[1] = _vertices[node.v2].y; v2[2] = _vertices[node.v2].z; Vector3f v3; v3[0] = _vertices[node.v3].x; v3[1] = _vertices[node.v3].y; v3[2] = _vertices[node.v3].z; Vector3f e1,e2; sub(e1,v2,v1); sub(e2,v3,v2); Vector3f n; vecProd(n,e1,e2); Vector3f fn; fn[0] = node.fnx; fn[1] = node.fny; fn[2] = node.fnz; if (dotProd(n,fn) < 0) { /* Invert any 2 guys */ int temp = node.v1; node.v1 = node.v2; node.v2 = temp; } } /* Replace a vertex in the dualnode */ void dual::replace(dualnode& n, int vold, int vnew) { if (n.v1 == vold) n.v1 = vnew; if (n.v2 == vold) n.v2 = vnew; if (n.v3 == vold) n.v3 = vnew; return; } /* Replace an old edge by a new edge in a node */ void dual::replace(int n, int edgeold, int edgenew) { if (_nodes[n].e1 == edgeold) { _nodes[n].e1 = edgenew; return; } if (_nodes[n].e2 == edgeold) { _nodes[n].e2 = edgenew; return; } if (_nodes[n].e3 == edgeold) { _nodes[n].e3 = edgenew; return; } fprintf(stderr,"Edge not found in node\n"); } /* Find a node in an edge different from the input */ int dual::otherNode(int e, int n) { if (_edges[e].v1 != n) return _nodes[e].v1; if (_nodes[e].v2 != n) return _nodes[e].v2; fprintf(stderr,"Node not in Edge\n"); return -1; } /* Find an edge from a node different from the input */ int dual::otherEdge(int n, int e) { if (_nodes[n].e1 != e) return _nodes[n].e1; if (_nodes[n].e2 != e) return _nodes[n].e2; fprintf(stderr,"Void Triangle 2\n"); return -1; } /* Find an edge from a node different from the input edges */ int dual::otherEdge(int n, int e1, int e2) { if ((_nodes[n].e1 != e1)&&(_nodes[n].e1 != e2)) return _nodes[n].e1; if ((_nodes[n].e2 != e1)&&(_nodes[n].e2 != e2)) return _nodes[n].e2; if ((_nodes[n].e3 != e1)&&(_nodes[n].e3 != e2)) return _nodes[n].e3; /* There are boundary edges => could be that both boundary edges */ if ((boundaryEdges(n) == 2)&&((e1==-1)||(e2==-1))) { return -1; } else { fprintf(stderr,"Void Triangle 3\n"); return -1; } } /* Find the missing vertex */ int dual::otherVertex(int n, int v1, int v2) { if ((_nodes[n].v1 != v1)&&(_nodes[n].v1 != v2)) return _nodes[n].v1; if ((_nodes[n].v2 != v1)&&(_nodes[n].v2 != v2)) return _nodes[n].v2; if ((_nodes[n].v3 != v1)&&(_nodes[n].v3 != v2)) return _nodes[n].v3; fprintf(stderr,"Missing Vertex not found \n"); return -1; }