void Topo3PrimalRender<PFP>::setDartsIdColor(typename PFP::MAP& map) { m_vbo2->bind(); float* colorBuffer = reinterpret_cast<float*>(glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE)); unsigned int nb = 0; for (Dart d = map.begin(); d != map.end(); map.next(d)) { if (nb < m_nbDarts) { float r,g,b; dartToCol(d, r,g,b); float* local = colorBuffer+3*m_attIndex[d]; // get the right position in VBO *local++ = r; *local++ = g; *local++ = b; *local++ = r; *local++ = g; *local++ = b; nb++; } else { CGoGNerr << "Error buffer too small for color picking (change the selector parameter ?)" << CGoGNendl; break; } } glUnmapBuffer(GL_ARRAY_BUFFER); }
typename PFP::REAL vertexVoronoiArea(typename PFP::MAP& map, Dart d, const VertexAttribute<typename PFP::VEC3>& position) { typename PFP::REAL area(0) ; Traversor2VF<typename PFP::MAP> t(map, d) ; for(Dart it = t.begin(); it != t.end(); it = t.next()) { const typename PFP::VEC3& p1 = position[it] ; const typename PFP::VEC3& p2 = position[map.phi1(it)] ; const typename PFP::VEC3& p3 = position[map.phi_1(it)] ; if(!Geom::isTriangleObtuse(p1, p2, p3)) { typename PFP::REAL a = Geom::angle(p3 - p2, p1 - p2) ; typename PFP::REAL b = Geom::angle(p1 - p3, p2 - p3) ; area += ( (p2 - p1).norm2() / tan(b) + (p3 - p1).norm2() / tan(a) ) / 8 ; } else { typename PFP::REAL tArea = Geom::triangleArea(p1, p2, p3) ; if(Geom::angle(p2 - p1, p3 - p1) > M_PI / 2) area += tArea / 2 ; else area += tArea / 4 ; } } return area ; }
void mergeVertices(typename PFP::MAP& map, VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& positions, int precision) { // TODO optimiser en triant les sommets // map.template enableQuickTraversal<VERTEX>(); TraversorV<typename PFP::MAP> travV1(map) ; CellMarker<typename PFP::MAP, VERTEX> vM(map); for(Dart d1 = travV1.begin() ; d1 != travV1.end() ; d1 = travV1.next()) { vM.mark(d1); TraversorV<typename PFP::MAP> travV2(map) ; for(Dart d2 = travV2.begin() ; d2 != travV2.end() ; d2 = travV2.next()) { if(!vM.isMarked(d2)) { if(positions[d1].isNear(positions[d2], precision)) { if (map.sameVertex(d1,d2)) std::cout << "fusion: sameVertex" << std::endl ; if (!map.sameVertex(d1,d2)) mergeVertex<PFP>(map,positions,d1,d2,precision); } } } } // map.template disableQuickTraversal<VERTEX>(); }
typename PFP::REAL triangleArea(typename PFP::MAP& map, Dart d, const VertexAttribute<typename PFP::VEC3>& position) { typename PFP::VEC3 p1 = position[d] ; typename PFP::VEC3 p2 = position[map.phi1(d)] ; typename PFP::VEC3 p3 = position[map.phi_1(d)] ; return Geom::triangleArea(p1, p2, p3) ; }
typename PFP::REAL tetrahedronVolume(typename PFP::MAP& map, Vol v, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& position) { typedef typename PFP::VEC3 VEC3; VEC3 p1 = position[v.dart] ; VEC3 p2 = position[map.phi1(v)] ; VEC3 p3 = position[map.phi_1(v)] ; VEC3 p4 = position[map.phi_1(map.phi2(v))] ; return Geom::tetraVolume(p1, p2, p3, p4) ; }
void ColorPerFaceRender::updateVBO(Utils::VBO& vboPosition, Utils::VBO& vboColor, typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& positions, const AttributeHandler<typename PFP::VEC3,ORBIT, typename PFP::MAP>& colorPerXXX) { typedef typename PFP::VEC3 VEC3; typedef typename PFP::REAL REAL; typedef Geom::Vec3f VEC3F; std::vector<VEC3F> buffer; buffer.reserve(16384); std::vector<VEC3F> bufferColors; bufferColors.reserve(16384); TraversorCell<typename PFP::MAP, FACE> traFace(map); for (Dart d=traFace.begin(); d!=traFace.end(); d=traFace.next()) { Dart a = d; Dart b = map.phi1(a); Dart c = map.phi1(b); // loop to cut a polygon in triangle on the fly (works only with convex faces) do { buffer.push_back(positions[d]); bufferColors.push_back(colorPerXXX[d]); buffer.push_back(positions[b]); bufferColors.push_back(colorPerXXX[b]); buffer.push_back(positions[c]); bufferColors.push_back(colorPerXXX[c]); b = c; c = map.phi1(b); } while (c != d); } m_nbTris = GLuint(buffer.size()/3); vboPosition.setDataSize(3); vboPosition.allocate(uint32(buffer.size())); VEC3F* ptrPos = reinterpret_cast<VEC3F*>(vboPosition.lockPtr()); memcpy(ptrPos,&buffer[0],buffer.size()*sizeof(VEC3F)); vboPosition.releasePtr(); vboColor.setDataSize(3); vboColor.allocate(uint32(bufferColors.size())); VEC3F* ptrCol = reinterpret_cast<VEC3F*>(vboColor.lockPtr()); memcpy(ptrCol,&bufferColors[0],bufferColors.size()*sizeof(VEC3F)); vboColor.releasePtr(); }
bool intersectionLineConvexFace(typename PFP::MAP& map, Face f, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& position, const typename PFP::VEC3& P, const typename PFP::VEC3& Dir, typename PFP::VEC3& Inter) { typedef typename PFP::VEC3 VEC3 ; typedef typename PFP::REAL REAL; const REAL SMALL_NUM = std::numeric_limits<typename PFP::REAL>::min() * 5.0f; Dart d = f.dart; VEC3 p1 = position[d]; VEC3 n = faceNormal<PFP>(map, d, position); VEC3 w0 = P - p1; REAL a = -(n*w0); REAL b = n*Dir; if (fabs(b) < SMALL_NUM) return false; REAL r = a / b; Inter = P + r * Dir; // intersect point of ray and plane // is I inside the face? VEC3 p2 = position[map.phi1(d)]; VEC3 v = p2 - p1 ; VEC3 vInter = Inter - p1; REAL dirV = v * vInter; if(fabs(dirV) < SMALL_NUM) // on an edge return true; Dart it = map.phi1(d); while(it != d) { p1 = p2; p2 = position[map.phi1(it)]; v = p2 - p1; vInter = Inter - p1; REAL dirD = v * vInter; if(fabs(dirD) < SMALL_NUM) // on an edge return true; if((dirV > SMALL_NUM && dirD < SMALL_NUM) || (dirV < SMALL_NUM && dirD > SMALL_NUM)) //exterior of the face return false; it = map.phi1(it) ; } return true; }
typename PFP::REAL convexPolyhedronVolume(typename PFP::MAP& map, Vol v, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& position) { typedef typename PFP::MAP MAP; typedef typename PFP::VEC3 VEC3; if (Volume::Modelisation::Tetrahedralization::isTetrahedron<PFP>(map, v)) return tetrahedronVolume<PFP>(map, v, position) ; else { typename PFP::REAL vol = 0 ; VEC3 vCentroid = Algo::Surface::Geometry::volumeCentroid<PFP>(map, v, position) ; DartMarkerStore<MAP> mark(map) ; // Lock a marker std::vector<Face> visitedFaces ; visitedFaces.reserve(100) ; Face f(v.dart) ; visitedFaces.push_back(f) ; mark.markOrbit(f) ; for(unsigned int iface = 0; iface != visitedFaces.size(); ++iface) { f = visitedFaces[iface] ; if(map.isCycleTriangle(f)) { VEC3 p1 = position[f.dart] ; VEC3 p2 = position[map.phi1(f)] ; VEC3 p3 = position[map.phi_1(f)] ; vol += Geom::tetraVolume(p1, p2, p3, vCentroid) ; } else { VEC3 fCentroid = Algo::Surface::Geometry::faceCentroid<PFP>(map, f, position) ; Dart d = f.dart ; do { VEC3 p1 = position[d] ; VEC3 p2 = position[map.phi1(d)] ; vol += Geom::tetraVolume(p1, p2, fCentroid, vCentroid) ; d = map.phi1(d) ; } while(d != f.dart) ; } Dart d = f.dart; do // add all face neighbours to the table { Dart dd = map.phi2(d) ; if(!mark.isMarked(dd)) // not already marked { Face ff(dd); visitedFaces.push_back(ff) ; mark.markOrbit(ff) ; } d = map.phi1(d) ; } while(d != f.dart) ; } return vol ; } }
void drawerAddEdgeShrink(Utils::Drawer& dr, typename PFP::MAP& map, Dart d, const VertexAttribute<typename PFP::VEC3>& positions, const typename PFP::VEC3& C, float k) { const typename PFP::VEC3& P = positions[d]; Dart e = map.phi1(d); const typename PFP::VEC3& Q = positions[e]; dr.vertex(C*(1.0f-k) + k*P); dr.vertex(C*(1.0f-k) + k*Q); }
typename PFP::REAL convexFaceArea(typename PFP::MAP& map, Dart d, const VertexAttribute<typename PFP::VEC3>& position) { typedef typename PFP::VEC3 VEC3 ; if(map.faceDegree(d) == 3) return triangleArea<PFP>(map, d, position) ; else { float area = 0.0f ; VEC3 centroid = Algo::Geometry::faceCentroid<PFP>(map, d, position) ; Traversor2FE<typename PFP::MAP> t(map, d) ; for(Dart it = t.begin(); it != t.end(); it = t.next()) { VEC3 p1 = position[it] ; VEC3 p2 = position[map.phi1(it)] ; area += Geom::triangleArea(p1, p2, centroid) ; } return area ; } }
void mergeVertex(typename PFP::MAP& map, VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& positions, Dart d, Dart e, int precision) { assert(positions[d].isNear(positions[e], precision) && !map.sameVertex(d, e)) ; bool notempty = true ; do // While vertex of e contains more than one dart { Dart e1 = map.alpha1(e) ; // e1 stores next dart of vertex of e if (e1 == e) notempty = false ; // last dart of vertex of e else { map.removeEdgeFromVertex(e) ; // detach e from its vertex } // Searchs where e may be inserted in the vertex of d Dart d1 = d ; do { if (isBetween<PFP>(map, positions, e, d, map.alpha1(d))) break ; d = map.alpha1(d) ; } while (d != d1) ; // Inserted e in the correct place (after d) map.insertEdgeInVertex(d, e) ; // Go on with next darts d = e ; e = e1 ; } while (notempty) ; }
bool intersectionSphereEdge(typename PFP::MAP& map, const typename PFP::VEC3& center, typename PFP::REAL radius, Edge e, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& position, typename PFP::REAL& alpha) { typedef typename PFP::VEC3 VEC3 ; typedef typename PFP::REAL REAL ; const VEC3& p1 = position[e.dart]; const VEC3& p2 = position[map.phi1(e.dart)]; if(Geom::isPointInSphere(p1, center, radius) && !Geom::isPointInSphere(p2, center, radius)) { VEC3 p = p1 - center; VEC3 qminusp = p2 - center - p; REAL s = p * qminusp; REAL n2 = qminusp.norm2(); alpha = (- s + sqrt(s*s + n2 * (radius*radius - p.norm2()))) / n2; return true ; } return false ; }
typename V_ATT::DATA_TYPE localvolumeCentroidELW(typename PFP::MAP& map, Vol d, const V_ATT& attributs) { typedef typename V_ATT::DATA_TYPE EMB; EMB center(0.0); double count=0.0; for (Edge it : edgesIncidentToVolume3(map,d)) { EMB e1 = attributs[it.dart]; EMB e2 = attributs[map.phi1(it)]; double l = (e2-e1).norm(); center += (e1+e2)*l; count += 2.0*l ; } center /= double(count); return center ; }
bool areTrianglesInIntersection(typename PFP::MAP& map, Face t1, Face t2, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& position) { typedef typename PFP::VEC3 VEC3 ; typedef typename PFP::REAL REAL; Dart tri1 = t1.dart; Dart tri2 = t2.dart; //get vertices position VEC3 tris1[3]; VEC3 tris2[3]; for (unsigned int i = 0; i < 3; ++i) { tris1[i] = position[tri1]; tris2[i] = position[tri2]; tri1 = map.phi1(tri1); tri2 = map.phi1(tri2); } // gmtl::Vec3f nTri1,nTri2; // float offset1,offset2; // CGoGN::Algo::Geometry::trianglePlane<PFP>(map,tri1,nTri1,offset1); // CGoGN::Algo::Geometry::trianglePlane<PFP>(map,tri2,nTri2,offset2); // // Orientation3D oP[2][3]; // oP[0][0] = testOrientation3D(tris2[0],offset1,nTri1); // oP[0][1] = testOrientation3D(tris2[1],offset1,nTri1); // oP[0][2] = testOrientation3D(tris2[2],offset1,nTri1); // // if(oP[0][0]==oP[0][1] && oP[0][1]==oP[0][2]) { // if(oP[0][0]==ON) { //coplanar triangles // return isSegmentInTriangle2D(tris1[0],tris1[1],tris2[0],tris2[1],triS2[2],nTri2) // || isSegmentInTriangle2D(tris1[1],tris1[2],tris2[0],tris2[1],triS2[2],nTri2) // || isSegmentInTriangle2D(tris1[2],tris1[0],tris2[0],tris2[1],triS2[2],nTri2); // } // else // return false; // } // // oP[1][0] = testOrientation3D(tris1[0],offset2,nTri2); // oP[1][1] = testOrientation3D(tris1[1],offset2,nTri2); // oP[1][2] = testOrientation3D(tris1[2],offset2,nTri2); // // if(oP[1][0]==oP[1][1] && oP[1][1]==oP[1][2]) // return false; // // //search segment of tri 1 in plane of tri 2 // gmtl::Point3f inter1,inter2; // bool found = false; // for(unsigned int i=0;i<3 && !found;++i) { // //test if the first point is the one opposite to the two others // if(oP[0][i]!=oP[0][(1+i)%3] && oP[0][(1+i)%3]==oP[0][(2+i)%3]) { // found=true; // //search collision points with the two edges // float offset= gmtl::dot(tris2[0],nTri2); // gmtl::Planef pl(nTri2,offset); // // gmtl::Vec3f dir1(oP[0][(1+i)%3]); // dir1 -= oP[0][i]; // // gmtl::Vec3f dir2(oP[0][(2+i)%3]); // dir2 -= oP[0][i]; // // inter1 = gmtl::intersect(pl,gmtl::Ray(oP[0][i],dir1)); // inter2 = gmtl::intersect(pl,gmtl::Ray(oP[0][i],dir2)); // } // } // // return isSegmentInTriangle2D(inter1,inter2,tris2[0],tris2[1],triS2[2],nTri2); //compute face normal VEC3 normale1 = faceNormal<PFP>(map, t1, position); VEC3 bary1 = faceCentroid<PFP>(map, t1, position); int pos = 0; int neg = 0; //test position of points relative to first tri for (unsigned int i = 0; i < 3 ; ++i) { VEC3 nTest = bary1 - tris2[i]; REAL scal = nTest * normale1; if (scal < 0) ++neg; if (scal > 0) ++pos; } //if all pos or neg then no intersection if (neg == 3 || pos == 3) return false; //same for the second triangle VEC3 normale2 = faceNormal<PFP>(map, t2, position); VEC3 bary2 = faceCentroid<PFP>(map, t2, position); pos = 0; neg = 0; for (unsigned int i = 0; i < 3 ; ++i) { VEC3 nTest = bary2 - tris1[i]; REAL scal = nTest * normale2; if (scal<0) ++neg; if (scal>0) ++pos; } if (neg == 3 || pos == 3) return false; bool intersection = false; for (unsigned int i = 0; i < 3 && !intersection; ++i) { VEC3 inter; intersection = Geom::intersectionSegmentTriangle(tris1[i], tris1[(i + 1) % 3], tris2[0], tris2[1], tris2[2], inter) != Geom::NO_INTERSECTION; } if (intersection) return true; for (unsigned int i = 0; i < 3 && !intersection; ++i) { VEC3 inter; intersection = Geom::intersectionSegmentTriangle(tris2[i], tris2[(i + 1) % 3], tris1[0], tris1[1], tris1[2], inter) != Geom::NO_INTERSECTION; } return intersection; }
bool importOFFWithELERegions(typename PFP::MAP& map, const std::string& filenameOFF, const std::string& filenameELE, std::vector<std::string>& attrNames) { typedef typename PFP::VEC3 VEC3; VertexAttribute<VEC3> position = map.template addAttribute<VEC3, VERTEX>("position") ; attrNames.push_back(position.name()) ; AttributeContainer& container = map.template getAttributeContainer<VERTEX>() ; unsigned int m_nbVertices = 0, m_nbFaces = 0, m_nbEdges = 0, m_nbVolumes = 0; VertexAutoAttribute< NoMathIONameAttribute< std::vector<Dart> > > vecDartsPerVertex(map, "incidents"); // open files std::ifstream foff(filenameOFF.c_str(), std::ios::in); if (!foff.good()) { CGoGNerr << "Unable to open OFF file " << CGoGNendl; return false; } std::ifstream fele(filenameELE.c_str(), std::ios::in); if (!fele.good()) { CGoGNerr << "Unable to open ELE file " << CGoGNendl; return false; } std::string line; //OFF reading std::getline(foff, line); if(line.rfind("OFF") == std::string::npos) { CGoGNerr << "Problem reading off file: not an off file"<<CGoGNendl; CGoGNerr << line << CGoGNendl; return false; } //Reading number of vertex/faces/edges in OFF file unsigned int nbe; { do { std::getline(foff,line); }while(line.size() == 0); std::stringstream oss(line); oss >> m_nbVertices; oss >> m_nbFaces; oss >> m_nbEdges; oss >> nbe; } //Reading number of tetrahedra in ELE file unsigned int nbv; { do { std::getline(fele,line); }while(line.size() == 0); std::stringstream oss(line); oss >> m_nbVolumes; oss >> nbv ; oss >> nbv; } CGoGNout << "nb points = " << m_nbVertices << " / nb faces = " << m_nbFaces << " / nb edges = " << m_nbEdges << " / nb tet = " << m_nbVolumes << CGoGNendl; //Reading vertices std::vector<unsigned int> verticesID; verticesID.reserve(m_nbVertices); for(unsigned int i = 0 ; i < m_nbVertices ; ++i) { do { std::getline(foff,line); }while(line.size() == 0); std::stringstream oss(line); float x,y,z; oss >> x; oss >> y; oss >> z; //we can read colors informations if exists VEC3 pos(x,y,z); unsigned int id = container.insertLine(); position[id] = pos; verticesID.push_back(id); } std::vector<std::vector<Dart> > vecDartPtrEmb; vecDartPtrEmb.reserve(m_nbVertices); DartMarkerNoUnmark m(map) ; //Read and embed tetrahedra TODO for(unsigned i = 0; i < m_nbVolumes ; ++i) { do { std::getline(fele,line); } while(line.size() == 0); std::stringstream oss(line); oss >> nbe; Dart d = Algo::Modelisation::createTetrahedron<PFP>(map); Geom::Vec4ui pt; oss >> pt[0]; oss >> pt[1]; oss >> pt[2]; oss >> pt[3]; //regions ? oss >> nbe; // Embed three vertices for(unsigned int j = 0 ; j < 3 ; ++j) { FunctorSetEmb<typename PFP::MAP, VERTEX> fsetemb(map, verticesID[pt[2-j]]); map.template foreach_dart_of_orbit<PFP::MAP::VERTEX_OF_PARENT>(d, fsetemb); //store darts per vertices to optimize reconstruction Dart dd = d; do { m.mark(dd) ; vecDartsPerVertex[pt[2-j]].push_back(dd); dd = map.phi1(map.phi2(dd)); } while(dd != d); d = map.phi1(d); } //Embed the last vertex d = map.phi_1(map.phi2(d)); FunctorSetEmb<typename PFP::MAP, VERTEX> fsetemb(map, verticesID[pt[3]]); map.template foreach_dart_of_orbit<PFP::MAP::VERTEX_OF_PARENT>(d, fsetemb); //store darts per vertices to optimize reconstruction Dart dd = d; do { m.mark(dd) ; vecDartsPerVertex[pt[3]].push_back(dd); dd = map.phi1(map.phi2(dd)); } while(dd != d); } foff.close(); fele.close(); //Association des phi3 unsigned int nbBoundaryFaces = 0 ; for (Dart d = map.begin(); d != map.end(); map.next(d)) { if (m.isMarked(d)) { std::vector<Dart>& vec = vecDartsPerVertex[map.phi1(d)]; Dart good_dart = NIL; for(typename std::vector<Dart>::iterator it = vec.begin(); it != vec.end() && good_dart == NIL; ++it) { if(map.template getEmbedding<VERTEX>(map.phi1(*it)) == map.template getEmbedding<VERTEX>(d) && map.template getEmbedding<VERTEX>(map.phi_1(*it)) == map.template getEmbedding<VERTEX>(map.phi_1(d)) /*&& map.template getEmbedding<VERTEX>(*it) == map.template getEmbedding<VERTEX>(map.phi1(d)) */) { good_dart = *it ; } } if (good_dart != NIL) { map.sewVolumes(d, good_dart, false); m.template unmarkOrbit<FACE>(d); } else { m.template unmarkOrbit<PFP::MAP::FACE_OF_PARENT>(d); ++nbBoundaryFaces; } } } if (nbBoundaryFaces > 0) { std::cout << "closing" << std::endl ; map.closeMap(); CGoGNout << "Map closed (" << nbBoundaryFaces << " boundary faces)" << CGoGNendl; } return true; }
bool isBetween(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& positions, Dart d, Dart e, Dart f) { return CGoGN::Geom::isBetween(positions[map.phi1(d)]-positions[d], positions[map.phi1(e)]-positions[e], positions[map.phi1(f)]-positions[f]); }