void TriMesh::computeFaceGrad(const VectorXd& vertForm, std::vector<Vec3>& faceVector) const { faceVector.resize(numFaces()); for (unsigned face = 0; face < numFaces(); ++face) { std::vector<unsigned> fVert; getFaceVerts(face, fVert); assert(fVert.size() == 3); Vec3 pos[3]; double val[3]; for (unsigned i = 0; i < 3; ++i) { val[i] = vertForm(fVert[i]); pos[i] = getVertPos(fVert[i]); } Vec3 X = Vec3::Zero(); for (unsigned i = 0; i < 3; ++i) { unsigned j = (i + 1) % 3; unsigned k = (i + 2) % 3; X += val[i] * (pos[k] - pos[j]); } Vec3 n = (pos[1]-pos[0]).cross(pos[2]-pos[1]); double twice_area = n.norm(); n /= twice_area; faceVector[face] = n.cross(X) / twice_area; } }
void extractInternalFaces(const Dune::CpGrid& grid, Eigen::Array<int, Eigen::Dynamic, 1>& internal_faces, Eigen::Array<int, Eigen::Dynamic, 2, Eigen::RowMajor>& nbi) { // Extracts the internal faces of the grid. // These are stored in internal_faces. int nf=numFaces(grid); int num_internal=0; for(int f=0; f<nf; ++f) { if(grid.faceCell(f, 0)<0 || grid.faceCell(f, 1)<0) continue; ++num_internal; } // std::cout << num_internal << " internal faces." << std::endl; nbi.resize(num_internal, 2); internal_faces.resize(num_internal); int fi = 0; for (int f = 0; f < nf; ++f) { if(grid.faceCell(f, 0)>=0 && grid.faceCell(f, 1)>=0) { internal_faces[fi] = f; nbi(fi,0) = grid.faceCell(f, 0); nbi(fi,1) = grid.faceCell(f, 1); ++fi; } } }
void extractInternalFaces(const UnstructuredGrid& grid, Eigen::Array<int, Eigen::Dynamic, 1>& internal_faces, Eigen::Array<int, Eigen::Dynamic, 2, Eigen::RowMajor>& nbi) { typedef Eigen::Array<bool, Eigen::Dynamic, 1> OneColBool; typedef Eigen::Array<int, Eigen::Dynamic, 2, Eigen::RowMajor> TwoColInt; typedef Eigen::Array<bool, Eigen::Dynamic, 2, Eigen::RowMajor> TwoColBool; TwoColInt nb = faceCells(grid); // std::cout << "nb = \n" << nb << std::endl; // Extracts the internal faces of the grid. // These are stored in internal_faces. TwoColBool nbib = nb >= 0; OneColBool ifaces = nbib.rowwise().all(); const int num_internal = ifaces.cast<int>().sum(); // std::cout << num_internal << " internal faces." << std::endl; nbi.resize(num_internal, 2); internal_faces.resize(num_internal); int fi = 0; int nf = numFaces(grid); for (int f = 0; f < nf; ++f) { if (ifaces[f]) { internal_faces[fi] = f; nbi.row(fi) = nb.row(f); ++fi; } } }
double TriMesh::computeTotalArea() const { double sum = 0.0; for (unsigned face = 0; face < numFaces(); ++face) sum += computeFaceArea(face); return sum; }
void OBJGroup::addFace( const OBJFace& face ) { m_faces.push_back( face ); const std::string& lastMaterial = m_materialNames.back(); m_facesByMaterial[ lastMaterial ].push_back( numFaces() - 1 ); }
// for each face according to its vertices orientation void Mesh::compute_normals_per_facet() { for(int i = 0; i < numFaces(); ++i) { Face &face = m_face[i]; face.computeNormal(); } }
void Mesh::Vertex::computeNormal() { for(int i = 0; i < numFaces(); ++i) { Face_handle v = face(i); m_normal += v->normal(); } m_normal.unitize(); }
bool BspSceneFile::loadFaces(std::istream& bspStream, const Q3Bsp::DirEntry& facesEntry) { if (!bspStream.seekg(facesEntry.offset, std::ios::beg)) { return false; } std::size_t numFaces(facesEntry.length / sizeof(Q3Bsp::Face)); m_faces.reserve(numFaces); if (!bspStream.read(reinterpret_cast<char*>(&m_faces[0]), facesEntry.length)) { return false; } return true; }
void Mesh::buildEdges() { TSmallLargeEdgeI edgeMap; edgeMap.clear(); // map small index to map large index to the edge in the m_edge list for(int fi = 0; fi < numFaces(); ++fi) { //printf("%d- ", fi); Face &face = m_face[fi]; int v0i = face.vertexIndex(0); int v1i = face.vertexIndex(1); int v2i = face.vertexIndex(2); int e0i = addEdgeOnceUsing(v0i, v1i, edgeMap, &Mesh::addEdge); int e1i = addEdgeOnceUsing(v1i, v2i, edgeMap, &Mesh::addEdge); int e2i = addEdgeOnceUsing(v2i, v0i, edgeMap, &Mesh::addEdge); face.m_edges[0] = e0i; face.m_edges[1] = e1i; face.m_edges[2] = e2i; /* Vertex_handle v0 = find_vertex(v0i); v0->m_edges.append(e0i); v0->m_edges.append(e2i); Vertex_handle v1 = find_vertex(v1i); v1->m_edges.append(e0i); v1->m_edges.append(e1i); Vertex_handle v2 = find_vertex(v2i); v2->m_edges.append(e1i); v2->m_edges.append(e2i);*/ ///printf("%d %d %d\n", e0i, e1i, e2i); find_edge(e0i)->m_faces.append(fi); find_edge(e1i)->m_faces.append(fi);; find_edge(e2i)->m_faces.append(fi); // don't keep pointers since the vector might be reallocated // make sure the shortest one is in edges[0] /*if (e2->length() < e1->length()) qSwap(e2, e1); if (e1->length() < e0)->length()) qSwap(e1, e0); if (find_edge(e2)->length() < find_edge(e1)->length()) qSwap(e2, e1); don't need that */ } }
void TriMesh::computeVertArea(VectorXd& vertArea) const { vertArea = VectorXd::Zero(numVerts()); for (unsigned face = 0; face < numFaces(); ++face) { std::vector<unsigned> fVert; getFaceVerts(face, fVert); assert(fVert.size() == 3); double faceArea = computeFaceArea(face); for (unsigned i = 0; i < 3; ++i) vertArea(fVert[i]) += faceArea; } vertArea /= 3.0; }
//reads in an object from a .obj file BasicObject::BasicObject(const std::string &filename, const float _shininess){ shininess = _shininess; _numVerticies = numVertices(filename.c_str()); _numFaces = numFaces(filename.c_str()); _indexCount = _numFaces * 3; verticies = getVertices(filename.c_str(), _numVerticies); normals = getNormals(filename.c_str(), _numVerticies); faces = getFaces(filename.c_str(), _numFaces); texCoords = getTextureCoords(filename.c_str(), _numVerticies); }
void Mesh::commitRemove() { // first go over all the points and tell them where they go int count = 0; for(int i = 0; i < numVtx(); ++i) { Vertex_handle v = find_vertex(i); if (v->m_tran == -1) v->m_index = count++; else v->m_index = -1; // to be removed v->m_tran = -1; } // no go over the faces and transfer their point references count = 0; for(int i = 0; i < numFaces(); ++i) { Face_handle f = find_facet(i); bool remove = false; for(int ii = 0; ii < f->size(); ++ii) { int newvi = find_vertex(f->m_pi[ii])->m_index; f->m_pi[ii] = newvi; remove |= (newvi == -1); } if (!remove) f->m_index = count++; else f->m_index = -1; } // actually remove the vertices Vertex_iterator vit = vertices_begin(); while(vit != vertices_end()) { if (vit->m_index == -1) vit = m_vtx.erase(vit); else ++vit; } // remove faces Face_iterator fit = faces_begin(); while(fit != faces_end()) { if (fit->m_index == -1) fit = m_face.erase(fit); else ++fit; } }
void Mesh::buildVerticesInFaces() { for(int i = 0; i < numVtx(); ++i) { Vertex &v = m_vtx[i]; v.faceIndexs().clear(); } for(int fi = 0; fi < numFaces(); ++fi) { Face &face = m_face[fi]; for(int i = 0; i < face.size(); ++i) { m_vtx[face.vertexIndex(i)].faceIndexs().push_back(fi); } } }
float Mesh::compute_triangle_surfaces() { m_totalSurface = 0.0; for(int i = 0; i < numFaces(); ++i) { Face &face = m_face[i]; Vec3 v1(face.vertex(1)->point(), face.vertex(0)->point()); Vec3 v2(face.vertex(2)->point(), face.vertex(0)->point()); Vec3 cross = Vec3::crossProd(v1, v2); face.surface() = cross.length() / 2.0f; m_totalSurface += face.surface(); } return m_totalSurface; }
// only triangles Mesh::TIndexList Mesh::Vertex::neiVertices() const { TIndexList ret; for(int i = 0; i < numFaces(); ++i) { Face_const_handle f = face(i); for(int vi = 0; vi < f->size(); ++vi) { int cv = f->vertexIndex(vi); if (cv != index() && !ret.contains(cv)) ret.append(cv); } } return ret; }
void TriMesh::computeDivergence(const std::vector<Vec3>& faceVector, VectorXd& vertForm) const { vertForm = VectorXd::Zero(numVerts()); for (unsigned face = 0; face < numFaces(); ++face) { std::vector<unsigned> fVert; getFaceVerts(face, fVert); assert(fVert.size() == 3); Vec3 n = computeFaceNormal(face); for (unsigned i = 0; i < 3; ++i) { Vec3 p1 = getVertPos(fVert[(i+1)%3]); Vec3 p2 = getVertPos(fVert[(i+2)%3]); vertForm[fVert[i]] += 0.5*faceVector[face].dot(n.cross(p2-p1)); } } }
double TriMesh::computeMaxEdgeLength() const { double maxLen = 0.0; for (unsigned face = 0; face < numFaces(); ++face) { std::vector<unsigned> fVerts; getFaceVerts(face, fVerts); assert(fVerts.size() == 3); for (unsigned i = 0; i < 3; ++i) { unsigned vert0 = fVerts[(i+1)%3]; unsigned vert1 = fVerts[(i+2)%3]; double len = computeEdgeLength(vert0, vert1); maxLen = std::max(maxLen, len); } } return maxLen; }
void TriMesh::buildHeatKernel(SparseMatrix& A, double timestep) const { VectorXd diag; computeVertArea(diag); std::map< std::pair<unsigned,unsigned>, double > offdiag; for (unsigned face = 0; face < numFaces(); ++face) { std::vector<unsigned> fVert; getFaceVerts(face, fVert); assert(fVert.size() == 3); for (unsigned i = 0; i < 3; ++i) { unsigned vert0 = fVert[(i+1)%3]; unsigned vert1 = fVert[(i+2)%3]; if (vert0 > vert1) std::swap(vert0, vert1); std::pair<unsigned,unsigned> edge(vert0,vert1); double value = timestep * 0.5 * computeFaceCotan(face, i); diag(vert0) += value; diag(vert1) += value; if (offdiag.find(edge) == offdiag.end()) offdiag[edge] = -value; else offdiag[edge] -= value; } } std::vector<Triplet> triplet; for(unsigned i = 0; i < diag.size(); ++i) { triplet.push_back(Triplet(i,i,diag(i))); } for(std::map< std::pair<unsigned,unsigned>, double >::const_iterator it = offdiag.begin(); it != offdiag.end(); ++it) { triplet.push_back(Triplet(it->first.first,it->first.second,it->second)); triplet.push_back(Triplet(it->first.second,it->first.first,it->second)); } A.resize(numVerts(), numVerts()); A.setFromTriplets(triplet.begin(),triplet.end()); }
void Mesh::makeClosenessEdges() { int hasCount = 0; TSmallLargeEdgeI makec; for(int fi = 0; fi < numFaces(); ++fi) { Face_const_handle f = find_facet(fi); const TIndexList& clsf = f->closeFaces(); if (clsf.size() == 0) continue; ++hasCount; for(int cfi = 0; cfi < clsf.size(); ++cfi) { addEdgeOnceUsing(fi, clsf[cfi], makec, &Mesh::addCloseEdge); } } printf("Faces with close edges=%d\n", hasCount); }
void TriMesh::computeVertNormals(std::vector<Vec3>& vertNormal) const { vertNormal = std::vector<Vec3>(numVerts(), Vec3::Zero()); for (unsigned face = 0; face < numFaces(); ++face) { std::vector<unsigned> fVert; getFaceVerts(face, fVert); assert(fVert.size() == 3); double faceArea = computeFaceArea(face); Vec3 faceNormal = computeFaceNormal(face); for (unsigned i = 0; i < 3; ++i) vertNormal[fVert[i]] += faceArea * faceNormal; } for (unsigned vert = 0; vert < numVerts(); ++vert) { vertNormal[vert].normalize(); } }
Vec3 Mesh::centerOfMass() { // compute for every face for(int i = 0; i < numFaces(); ++i) { Face &f = m_face[i]; f.m_center.clear(); for(int i = 0; i < f.size(); ++i) f.m_center += f.vertex(i)->point(); f.m_center /= f.size(); } // now for all of the mess seperatly. Vec3 centerOfMass(0,0,0); for (Mesh::Vertex_iterator v = this->vertices_begin(); v != this->vertices_end(); v++) { centerOfMass = centerOfMass + (v->point()); // - CGAL::ORIGIN); } unsigned int size = this->size_of_vertices(); m_computedCenterOfMass = Vec3(centerOfMass.x/size, centerOfMass.y/size, centerOfMass.z/size); return m_computedCenterOfMass; }
void Mesh::saveSubMesh(const QString& filename, const TIndexList& facesList) const { QFile file(filename); file.open(QFile::WriteOnly | QFile::Truncate); file.setTextModeEnabled(true); QTextStream out(&file); out << "OFF\n"; int nVtx = numVtx(); int newIndexCounter = 0; // do we need only a subset of the vertices? QVector<int> newToOld; QHash<int, int> oldToNew; // old index -> new index. if (facesList.size() != numFaces()) { for(TIndexList::const_iterator pfi = facesList.constBegin(); pfi != facesList.constEnd(); ++pfi) { Face_const_handle f = find_facet(*pfi); for(int vfi = 0; vfi < f->size(); ++vfi) { int vi = f->vertexIndex(vfi); if (!oldToNew.contains(vi)) oldToNew.insert(vi, newIndexCounter++); } } newToOld.resize(newIndexCounter); // invert the map because we want a map from new to old for(QHash<int, int>::iterator hit = oldToNew.begin(); hit != oldToNew.end(); ++hit) { newToOld[hit.value()] = hit.key(); } nVtx = newIndexCounter; } // number of vertices, faces, 0 out << nVtx << " " << facesList.size() << " 0\n"; for(int i = 0; i < nVtx; ++i) { Vertex_const_handle v; if (newIndexCounter > 0) v = find_vertex(newToOld[i]); else v = find_vertex(i); const Vec3 &p = v->point(); out << p.x << " " << p.y << " " << p.z << "\n"; } for(TIndexList::const_iterator pfi = facesList.constBegin(); pfi != facesList.constEnd(); ++pfi) { Face_const_handle f = find_facet(*pfi); out << f->size(); for(int vfi = 0; vfi < f->size(); ++vfi) { int fii = f->vertexIndex(vfi); if (newIndexCounter > 0) fii = oldToNew[fii]; out << " " << fii; } out << "\n"; } }
SparseTableView face2Vertices(const UnstructuredGrid& grid) { return SparseTableView(grid.face_nodes, grid.face_nodepos, numFaces(grid)); }