TripleDouble PointsMapperArchive::getMappedPoint(PointCGAL p) { std::map<PointCGAL, TripleDouble>::iterator foundPair = mapPointsDoubleValues.find(p); if (foundPair == mapPointsDoubleValues.end()) { double x = CGAL::to_double(p.x()); double y = CGAL::to_double(p.y()); double z = CGAL::to_double(p.z()); TripleDouble tripleDouble; tripleDouble.d1 = x; tripleDouble.d2 = y; tripleDouble.d3 = z; mapPointsDoubleValues.insert(std::pair<PointCGAL, TripleDouble>(p, tripleDouble)); return tripleDouble; } else { return foundPair->second; } }
//Find the barycenter for each mesh and translate each mesh into the barycenter, returning mesh and barycenter std::list<TranslatedMeshData> centerMeshesInBarycenter(std::list<MeshData> &listMeshData) { std::list< std::pair<MeshData,PointCGAL> > result; std::list<MeshData>::iterator meshDataInter; for(meshDataInter = listMeshData.begin(); meshDataInter != listMeshData.end(); ++meshDataInter) { MeshData meshData = *meshDataInter; PointCGAL barycenter = getMeshBarycenter(meshData); MeshData meshDataTranslated = translateMesh(meshData, PointCGAL(-barycenter.x(), -barycenter.y(), -barycenter.z())); result.push_back(TranslatedMeshData(meshDataTranslated, barycenter)); } return result; }
MeshData translateMesh(MeshData &meshData, PointCGAL point) { std::list<Triangle> *meshTriangles = &(meshData.first); //std::list<TriangleInfo> cutInfo = meshData.second; std::list<Triangle> meshTrianglesTranslated; CGAL::Aff_transformation_3<Kernel> translate(CGAL::TRANSLATION, Vector(point.x(), point.y(), point.z())); std::list<Triangle>::iterator triangleIter; for(triangleIter = meshTriangles->begin(); triangleIter != meshTriangles->end(); ++triangleIter) { //Method 1 //Triangle t = *triangleIter; //Triangle tTranslated(translate(t.vertex(0)), translate(t.vertex(1)), translate(t.vertex(2)) ); //meshTrianglesTranslated.push_back(tTranslated); //Method 2 meshTrianglesTranslated.push_back(triangleIter->transform(translate)); } //return MeshData(meshTrianglesTranslated, cutInfo); return MeshData(meshTrianglesTranslated, meshData.second); }
//TODO: use CGAL::Cartesian_converter<K1,K2> converter; //K1::Point_3 p_k1(1,2,3); //K2::Point_3 p_k2 = converter( p_k1 ); KDPoint converPointExactToInexact(PointCGAL point) { return KDPoint(CGAL::to_double(point.x()), CGAL::to_double(point.y()), CGAL::to_double(point.z())); }
/* * Given a site with known fluidness, examine the links to not-yet-visited * neighbouring sites. If the neighbours have unknown fluidness, set that. * * Since we wish to examine each link only once, this will set link properties * from neighbour => site as well as site => neighbour * */ void PolyDataGenerator::ClassifySite(Site& site) { if (!site.IsFluidKnown){ throw GenerationErrorMessage("The start site is not known cannot continue"); } for (LaterNeighbourIterator neighIt = site.begin(); neighIt != site.end(); ++neighIt) { Site& neigh = *neighIt; unsigned int iNeigh = neighIt.GetNeighbourIndex(); int nHits = Intersect(site,neigh); // Four cases: fluid-fluid, solid-solid, fluid-solid and solid-fluid. // Will handle the last two together. if (site.IsFluid == neigh.IsFluid) { if (site.IsFluid) { // Fluid-fluid, must set CUT_NONE for both site.Links[iNeigh].Type = geometry::CUT_NONE; neigh.Links[Neighbours::inverses[iNeigh]].Type = geometry::CUT_NONE; } else { // solid-solid, nothing to do. } } else { // They differ, figure out which is fluid and which is solid. Site* fluid; Site* solid; // Index of the solid site from the fluid site. int iSolid; // Index of the point in this->hitPoints we're considering as the // hit of interest (i.e. the one closest to the fluid site). int iHit; Vector hitPoint; PointCGAL hitPointCGAL; SegmentCGAL hitsegmentCGAL; int hitCellId; double distancetol = 0.01; std::vector<int> CloseIoletIDS; if (nHits == -1){//unclassified intersection need to be carefull. if (site.IsFluid) { fluid = &site; solid = &neigh; iSolid = iNeigh; int n=0; iHit = n; // here we iterate over all intersections until we // find a wall or the rest are futher away than the tol. for (std::vector<Object_Primitive_and_distance>::iterator distit = IntersectionCGAL.begin(); distit != IntersectionCGAL.end(); ++distit){ if (distit->second > IntersectionCGAL[0].second+distancetol){ iHit = n; break; } int tempioletId = distit->first.second->id() - 2; //shifting back from unsigned if (tempioletId < 0){ break;//hit a wall no need to continue. }//what if we hit both an inlet and outlet. Can that ever happen? ++n; } } else { fluid = &neigh; solid = &site; iSolid = Neighbours::inverses[iNeigh]; int n = IntersectionCGAL.size()-1; iHit = n; for (std::vector<Object_Primitive_and_distance>::reverse_iterator distit = IntersectionCGAL.rbegin(); distit != IntersectionCGAL.rend(); ++distit){ if (distit->second < IntersectionCGAL.back().second - distancetol){ iHit = n; break;//ignoring the following intersections, they are to far away. } int tempioletId = distit->first.second->id() - 2; //shifting back from unsigned if (tempioletId < 0){ break;//hit a wall no need to continue. }//what if we hit both an inlet and outlet. Can that ever happen? --n; } } } else{//normal intersection just take the closest point. if (site.IsFluid) { fluid = &site; solid = &neigh; iSolid = iNeigh; iHit = 0; } else { fluid = &neigh; solid = &site; iSolid = Neighbours::inverses[iNeigh]; iHit = nHits - 1; } } Object_Primitive_and_distance hitpoint_triangle_dist = IntersectionCGAL[iHit]; if (CGAL::assign(hitPointCGAL, hitpoint_triangle_dist.first.first)){ //we do an explicite cast to double here. //The cast to double is only needed if we use an exact_construction kernel. //Otherwise this is already a double but keeping this in makes it //posible to change the kernel for testing. hitPoint = Vector(CGAL::to_double(hitPointCGAL.x()),CGAL::to_double(hitPointCGAL.y()), CGAL::to_double(hitPointCGAL.z())); } else if (CGAL::assign(hitsegmentCGAL, hitpoint_triangle_dist.first.first)){ hitPointCGAL = CGAL::midpoint(hitsegmentCGAL.vertex(0),hitsegmentCGAL.vertex(1)); hitPoint = Vector(CGAL::to_double(hitPointCGAL.x()),CGAL::to_double(hitPointCGAL.y()), CGAL::to_double(hitPointCGAL.z())); } else{ throw GenerationErrorMessage("This type of intersection should not happen"); } LinkData& link = fluid->Links[iSolid]; // This is set in any solid case float distanceInVoxels = (hitPoint - fluid->Position).GetMagnitude(); // The distance is in voxels but must be output as a fraction of // the lattice vector. Scale it. link.Distance = distanceInVoxels / Neighbours::norms[iSolid]; int ioletId = hitpoint_triangle_dist.first.second->id() - 2; //shifting back from unsigned. if (ioletId < 0) { // -1 => we hit a wall link.Type = geometry::CUT_WALL; } else { // We hit an inlet or outlet Iolet* iolet = this->Iolets[ioletId]; if (iolet->IsInlet) { link.Type = geometry::CUT_INLET; } else { link.Type = geometry::CUT_OUTLET; } // Set the Id link.IoletId = iolet->Id; } // If this link intersected the wall, store the normal of the cell we hit and the distance to it. if (link.Type == geometry::CUT_WALL) { VectorCGAL CGALNorm = CGAL::cross_product(hitpoint_triangle_dist.first.second->halfedge()->next()->vertex()->point() - hitpoint_triangle_dist.first.second->halfedge()->vertex()->point(), hitpoint_triangle_dist.first.second->halfedge()->next()->next()->vertex()->point() - hitpoint_triangle_dist.first.second->halfedge()->next()->vertex()->point()); CGALNorm = CGALNorm/CGAL::sqrt(CGALNorm.squared_length()); link.WallNormalAtWallCut = Vector(CGALNorm.x(), CGALNorm.y(),CGALNorm.z()); link.DistanceInVoxels = distanceInVoxels; } } } // If there's enough information available, an approximation of the wall normal will be computed for this fluid site. this->ComputeAveragedNormal(site); }
void operator()( HDS& hds) { CGAL::Polyhedron_incremental_builder_3<HDS> B(hds, false); //B.begin_surface( 3*trianglesList->size(), trianglesList->size(), 0, CGAL::Polyhedron_incremental_builder_3<HDS>::RELATIVE_INDEXING); //ABSOLUTE_INDEXING B.begin_surface( 3*trianglesList->size(), trianglesList->size()); //ABSOLUTE_INDEXING // Init data structures and add points to B int pointIndex = 0; int triangleIndex = 0; int edgeIndex = 0; std::list<Triangle>::iterator triangleIter; for(triangleIter = trianglesList->begin(); triangleIter != trianglesList->end(); ++triangleIter) { Triangle t = *triangleIter; if (t.is_degenerate()) { continue; } TriangleVisitedInfoMS tvi; tvi.triangle = &(*triangleIter); //Use the pointer, it should not change into the container, since there aren't new added elements tvi.visited = false; // loop for vertexes for (int i = 0; i < 3; ++i) { PointCGAL v = t.vertex(i); MapPointId::iterator foundPair = mapPointId.find(v); if (foundPair == mapPointId.end()) { // PointCGAL not found Polyhedron::Vertex_handle vh = B.add_vertex( PointKK(CGAL::to_double(v.x()), CGAL::to_double(v.y()), CGAL::to_double(v.z())) ); mapPointId.insert(PairPointId(v, pointIndex)); vertexPoints.push_back(v); tvi.vertexIndexes.push_back(pointIndex); pointIndex++; } else { tvi.vertexIndexes.push_back(foundPair->second); } } // loop for edges for (int i = 0; i < 3; ++i) { int firstEdgeIndex = i; int secondEdgeIndex = (i<2) ? (i+1) : 0; IntUnorderedPair iup; iup.first = tvi.vertexIndexes.at(firstEdgeIndex); iup.second = tvi.vertexIndexes.at(secondEdgeIndex); MapUnorderedPairId::iterator foundPair = mapEdgeId.find(iup); if (foundPair == mapEdgeId.end()) { // Edge not found EdgeVisitedInfo evi; evi.edgeVertexes = iup; evi.visited = false; evi.triangleVisitedInfoIndexes.push_back(triangleIndex); mapEdgeId.insert(PairIntUnorderedPairId(iup, edgeIndex)); edgesVisited.push_back(evi); tvi.edgeVisitedInfoIndexes.push_back(edgeIndex); edgeIndex++; } else { EdgeVisitedInfo *evi = &(edgesVisited.at(foundPair->second)); evi->triangleVisitedInfoIndexes.push_back(triangleIndex); tvi.edgeVisitedInfoIndexes.push_back(foundPair->second); } } trianglesVisited.push_back(tvi); triangleIndex++; } // build the surface adding the triangles std::queue<EdgeVisitedInfo*> fifoEdgesToVisit; for (unsigned int edgeIdx = 0; edgeIdx < edgesVisited.size(); edgeIdx++) { EdgeVisitedInfo *evip = &edgesVisited.at(edgeIdx); if (!(evip->visited)) { //std::cout << "START"; fifoEdgesToVisit.push(evip); while(!fifoEdgesToVisit.empty()) { EdgeVisitedInfo *evitv = fifoEdgesToVisit.front(); fifoEdgesToVisit.pop(); //if (!(evitv->visited)) { //std::cout << "*"; evitv->visited = true; for (unsigned int triangleVecIdx = 0; triangleVecIdx < evitv->triangleVisitedInfoIndexes.size(); triangleVecIdx++) { TriangleVisitedInfoMS *tvitv = &trianglesVisited.at(evitv->triangleVisitedInfoIndexes.at(triangleVecIdx)); if (!(tvitv->visited)) { // check if the triangle edges have more than 2 connected triangles // and add the connected non visited edges to fifoEdgesToVisit bool oneEdgeHasMoreThanTwoTriangles = false; for (unsigned int edgeVecIdx = 0; edgeVecIdx < tvitv->edgeVisitedInfoIndexes.size(); edgeVecIdx++) { EdgeVisitedInfo *eviTvitv = &edgesVisited.at(tvitv->edgeVisitedInfoIndexes.at(edgeVecIdx)); if (!(eviTvitv->visited)) { fifoEdgesToVisit.push(eviTvitv); } if (eviTvitv->triangleVisitedInfoIndexes.size() > 2) { oneEdgeHasMoreThanTwoTriangles = true; } } if (oneEdgeHasMoreThanTwoTriangles) { //std::cout << "2"; // Add new points and the triangle with these new vertexes std::vector<unsigned int> newVertexIndexes; for (int vIdx = 0; vIdx < tvitv->vertexIndexes.size(); vIdx++) { PointCGAL vt = vertexPoints.at(tvitv->vertexIndexes.at(vIdx)); B.add_vertex( PointKK(CGAL::to_double(vt.x()), CGAL::to_double(vt.y()), CGAL::to_double(vt.z())) ); vertexPoints.push_back(vt); newVertexIndexes.push_back(pointIndex); pointIndex++; } if (B.test_facet(newVertexIndexes.begin(), newVertexIndexes.end())) { B.add_facet(newVertexIndexes.begin(), newVertexIndexes.end()); } else { std::cout << "Build_triangle_mesh_coherent_surface: WARNING: can't add a triangle in polyhedron (1)!!!\n"; } } else { //add triangle tvitv to Polyhedron surface bool testFacetVerseA = B.test_facet(tvitv->vertexIndexes.begin(), tvitv->vertexIndexes.end()); if (testFacetVerseA) { //std::cout << "A"; B.add_facet(tvitv->vertexIndexes.begin(), tvitv->vertexIndexes.end()); } else { bool testFacetVerseB = B.test_facet(tvitv->vertexIndexes.rbegin(), tvitv->vertexIndexes.rend()); if (testFacetVerseB) { //std::cout << "B"; B.add_facet(tvitv->vertexIndexes.rbegin(), tvitv->vertexIndexes.rend()); } else { //std::cout << "C"; // Same block of 2 // Add new points and the triangle with these new vertexes std::vector<unsigned int> newVertexIndexes; for (int vIdx = 0; vIdx < tvitv->vertexIndexes.size(); vIdx++) { PointCGAL vt = vertexPoints.at(tvitv->vertexIndexes.at(vIdx)); B.add_vertex( PointKK(CGAL::to_double(vt.x()), CGAL::to_double(vt.y()), CGAL::to_double(vt.z())) ); vertexPoints.push_back(vt); newVertexIndexes.push_back(pointIndex); pointIndex++; } if (B.test_facet(newVertexIndexes.begin(), newVertexIndexes.end())) { B.add_facet(newVertexIndexes.begin(), newVertexIndexes.end()); } else { std::cout << "Build_triangle_mesh_coherent_surface: WARNING: can't add a triangle in polyhedron (2)!!!\n"; } } } } tvitv->visited = true; } } } } } } if ( B.check_unconnected_vertices() ) { //std::cout << "Remove_unconnected_vertices" << std::endl; B.remove_unconnected_vertices(); } B.end_surface(); }