diff --git a/Common/CommandLine.cpp b/Common/CommandLine.cpp index fa1caf10fd3a77ac707224ed937946990828c257..45d42dcc57f03d9a220ef60f57320bfa9e3fad2a 100644 --- a/Common/CommandLine.cpp +++ b/Common/CommandLine.cpp @@ -54,7 +54,7 @@ void PrintUsage(const char *name) Msg::Direct("Geometry options:"); Msg::Direct(" -0 Output unrolled geometry, then exit"); Msg::Direct(" -tol float Set geometrical tolerance"); - Msg::Direct(" -match int Match geometries and meshes if int != 0"); + Msg::Direct(" -match Match geometries and meshes"); Msg::Direct("Mesh options:"); Msg::Direct(" -1, -2, -3 Perform 1D, 2D or 3D mesh generation, then exit"); Msg::Direct(" -refine Perform uniform mesh refinement, then exit"); @@ -291,10 +291,7 @@ void GetOptions(int argc, char *argv[]) } else if(!strcmp(argv[i] + 1, "match")) { i++; - if(argv[1]) - CTX::instance()->geom.matchGeomAndMesh = atoi(argv[i++]); - else - Msg::Fatal("Missing number"); + CTX::instance()->geom.matchGeomAndMesh = 1; } else if(!strcmp(argv[i] + 1, "scale")) { i++; diff --git a/Common/OpenFile.cpp b/Common/OpenFile.cpp index 5b6ba9dec75b96f5111f736011b2fd6b222176f5..937f3ca86e2d86667f728841b97c4320c0186130 100644 --- a/Common/OpenFile.cpp +++ b/Common/OpenFile.cpp @@ -335,10 +335,11 @@ int MergeFile(std::string fileName, bool warnIfMissing) // MATCHER if(CTX::instance()->geom.matchGeomAndMesh && !GModel::current()->empty() ) { + GModel* current_mod = GModel::current(); GModel* tmp_model = new GModel(); tmp_model->readMSH(fileName); - //tmp_model->scaleMesh(1000); - int match_status = GeomMeshMatcher::instance()->match(GModel::current(), tmp_model); + int match_status = GeomMeshMatcher::instance()->match(current_mod, tmp_model); + if (match_status) fileName = "out.msh"; delete tmp_model; diff --git a/Geo/GeomMeshMatcher.cpp b/Geo/GeomMeshMatcher.cpp index 4afead0bbe50bbcf9ae8e271d521e36186e2676d..1ffbce151d2658d02230144a9568f0e784636bf5 100644 --- a/Geo/GeomMeshMatcher.cpp +++ b/Geo/GeomMeshMatcher.cpp @@ -16,6 +16,9 @@ #include "discreteVertex.h" #include "GmshMessage.h" #include "SOrientedBoundingBox.h" +#include "MElement.h" +#include "MVertex.h" +#include "MLine.h" GeomMeshMatcher *GeomMeshMatcher::_gmm_instance = 0; @@ -78,7 +81,7 @@ template <class T> T findMatching(std::vector<Pair<T,T> >& matching, T& entity) // Private std::vector<Pair<GVertex*,GVertex*> >* -GeomMeshMatcher::matchVertices(GModel* m1, GModel *m2) +GeomMeshMatcher::matchVertices(GModel* m1, GModel *m2, bool& ok) { // Vector that will be returned. std::vector<Pair<GVertex*,GVertex*> >* coresp_v = new std::vector<Pair<GVertex*, @@ -125,14 +128,14 @@ GeomMeshMatcher::matchVertices(GModel* m1, GModel *m2) fabs(v1->z() - v2->z()) < tol ) { Msg::Info("Vertices %i (in m1) and %i (in m2) match.", - counter1, - counter2); + (*entity1)->tag(), + (*entity2)->tag()); + // ToDo : Relax this assumption... // We assume that two mesh vertices can't match with the same // geometrical one. coresp_v->push_back(Pair<GVertex*,GVertex*>((GVertex*) *entity1, (GVertex*) *entity2)); - // TODO : Double-check this part... ((GVertex*) *entity2)->setTag(((GVertex*) *entity1)->tag()); num_matched_vertices++; break; @@ -142,13 +145,15 @@ GeomMeshMatcher::matchVertices(GModel* m1, GModel *m2) } counter1++; } + printf("Vertices matched : %i / %i", num_matched_vertices, num_total_vertices); Msg::Info("Vertices matched : %i / %i", num_matched_vertices, num_total_vertices); + if(num_matched_vertices != num_total_vertices) ok = false; return (coresp_v); } std::vector<Pair<GEdge*,GEdge*> >* GeomMeshMatcher::matchEdges(GModel* m1, GModel* m2, - std::vector<Pair<GVertex*,GVertex*> >* coresp_v) + std::vector<Pair<GVertex*,GVertex*> >* coresp_v, bool& ok) { int num_matched_edges = 0; @@ -168,8 +173,7 @@ GeomMeshMatcher::matchEdges(GModel* m1, GModel* m2, entity1++) { if ((*entity1)->dim() != 1) continue; - num_total_edges++; - + num_total_edges++; GVertex* v1 = ((GEdge*)(*entity1))->getBeginVertex(); @@ -181,13 +185,11 @@ GeomMeshMatcher::matchEdges(GModel* m1, GModel* m2, lists.push_back((findMatching<GVertex*>(*coresp_v,v2))->edges()); getIntersection<GEdge*>(common_edges, lists); + GEdge* choice = 0; + if (common_edges.size() == 1) { - coresp_e->push_back( Pair<GEdge*,GEdge*> ((GEdge*) *entity1, common_edges[0])); - Msg::Info("Edges %i (in m1) and %i (in m2) match.", - ((GEdge*)*entity1)->tag(), - common_edges[0]->tag()); - common_edges[0]->setTag(((GEdge*) *entity1)->tag()); - num_matched_edges++; + Msg::Info("There's only one edge !"); + choice = common_edges[0]; } else { // More than one edge between the two points ? No worries, let // us use those bounding boxes ! @@ -196,53 +198,60 @@ GeomMeshMatcher::matchEdges(GModel* m1, GModel* m2, // Then, compute the minimal bounding box SOrientedBoundingBox geo_obb = ((GEdge*)(*entity1))->getOBB(); - GEdge* choice = 0; double best_score = DBL_MAX; // Next, let's iterate over the mesh entities. for (std::vector<GEdge*>::iterator candidate = common_edges.begin(); candidate != common_edges.end(); candidate++) { - SOrientedBoundingBox mesh_obb = (*candidate)->getOBB(); - Msg::Info("Comparing score : %f", - SOrientedBoundingBox::compare(geo_obb,mesh_obb)); - - //if (geo_obb->intersects(mesh_obb)) { - - //double cen_dist1 = geo_obb->getCenter()[0]-mesh_obb->getCenter()[0]; - //double cen_dist2 = geo_obb->getCenter()[1]-mesh_obb->getCenter()[1]; - //double cen_dist3 = geo_obb->getCenter()[2]-mesh_obb->getCenter()[2]; - //double score1 = sqrt( cen_dist1*cen_dist1 - // + cen_dist2*cen_dist2 - // + cen_dist3*cen_dist3); - - // double score2 = fabs(geo_obb->getSize()[0]-mesh_obb->getSize()[0]); - //double score3 = fabs(geo_obb->getSize()[1]-mesh_obb->getSize()[1]); - //double score4 = fabs(geo_obb->getSize()[2]-mesh_obb->getSize()[2]); - double score = SOrientedBoundingBox::compare(geo_obb,mesh_obb); - if (score < best_score) { - best_score = score; - choice = (*candidate); - } - //} + SOrientedBoundingBox mesh_obb = (*candidate)->getOBB(); + Msg::Info("Comparing score : %f", + SOrientedBoundingBox::compare(geo_obb,mesh_obb)); + + + double score = SOrientedBoundingBox::compare(geo_obb,mesh_obb); + if (score < best_score) { + best_score = score; + choice = (*candidate); } - Msg::Info("Edges %i (in m1) and %i (in m2) match.", - ((GEdge*)*entity1)->tag(), - choice->tag()); - coresp_e->push_back(Pair<GEdge*,GEdge*>((GEdge*) *entity1 , - choice)); - choice->setTag(((GEdge*) *entity1)->tag()); - num_matched_edges++; + //} + } } + Msg::Info("Edges %i (in m1) and %i (in m2) match.", + ((GEdge*)*entity1)->tag(), + choice->tag()); + coresp_e->push_back(Pair<GEdge*,GEdge*>((GEdge*) *entity1 , + choice)); + choice->setTag(((GEdge*) *entity1)->tag()); + num_matched_edges++; - } + for (std::vector<MLine*>::iterator mline = choice->lines.begin(); mline != choice->lines.end(); mline++) { + if (((GEdge*)*entity1)->parFromPoint(((MLine*) *mline)->getVertex(0)->point()) > ((GEdge*)*entity1)->parFromPoint( ((MLine*) *mline)->getVertex(1)->point()) ) + ((MLine*) *mline)->revert(); + } + + + for (int i = 0; i < choice->getNumMeshElements(); i++) { + for (int j = 0; j < choice->getMeshElement(i)->getNumVertices(); j++) { + MVertex* v = choice->getMeshElement(i)->getVertex(j); + double param = ((GEdge*) *entity1)->parFromPoint(v->point()); + Msg::Info("Param %f",param); + Msg::Info("Par bounds %f %f",((GEdge*) *entity1)->parBounds(0).low(),((GEdge*) *entity1)->parBounds(0).high()); + if (v->onWhat()->dim() == 1) + reparamMeshVertexOnEdge(v,(GEdge*)*entity1,param); + } + } + } Msg::Info("Edges matched : %i / %i", num_matched_edges, num_total_edges); + if(num_matched_edges != num_total_edges) ok = false; return (coresp_e); - + } +//----------------------------------------------------------------------------- + std::vector<Pair<GFace*,GFace*> >* GeomMeshMatcher:: matchFaces(GModel* m1, GModel* m2, - std::vector<Pair<GEdge*,GEdge*> >* coresp_e) + std::vector<Pair<GEdge*,GEdge*> >* coresp_e, bool& ok) { int num_matched_faces = 0; int num_total_faces = 0; @@ -261,7 +270,7 @@ GeomMeshMatcher:: matchFaces(GModel* m1, GModel* m2, if ((*entity1)->dim() != 2) continue; num_total_faces++; - std::vector<std::list<GFace*> > lists; + std::vector<std::list<GFace*> > lists; std::list<GEdge*> boundary_edges = ((GEdge*)(*entity1))->edges(); for (std::list<GEdge*>::iterator boundary_edge = boundary_edges.begin(); boundary_edge != boundary_edges.end(); boundary_edge++) { @@ -270,57 +279,66 @@ GeomMeshMatcher:: matchFaces(GModel* m1, GModel* m2, std::vector<GFace*> common_faces; getIntersection<GFace*>(common_faces, lists); //cout << "We found " << common_faces.size() << " common faces." << endl; + GFace* choice = 0; if (common_faces.size() == 1) { - coresp_f->push_back( Pair<GFace*,GFace*> ((GFace*) *entity1, common_faces[0])); - common_faces[0]->setTag(((GFace*) *entity1)->tag()); - num_matched_faces++; + // SOrientedBoundingBox mesh_obb = (common_faces[0])->getOBB(); + choice = common_faces[0]; + //coresp_f->push_back( Pair<GFace*,GFace*> ((GFace*) *entity1, common_faces[0])); + //common_faces[0]->setTag(((GFace*) *entity1)->tag()); + //num_matched_faces++; } else if (common_faces.size() > 1) { // Then, compute the minimal bounding box SOrientedBoundingBox geo_obb = ((GFace*)(*entity1))->getOBB(); - GFace* choice = 0; + //GFace* choice = 0; double best_score = DBL_MAX; // Next, let's iterate over the mesh entities. for (std::vector<GFace*>::iterator candidate = common_faces.begin(); candidate != common_faces.end(); candidate++) { SOrientedBoundingBox mesh_obb = (*candidate)->getOBB(); Msg::Info("Comparing score : %f", SOrientedBoundingBox::compare(geo_obb,mesh_obb)); - - double cen_dist1 = geo_obb.getCenter()[0]-mesh_obb.getCenter()[0]; - double cen_dist2 = geo_obb.getCenter()[1]-mesh_obb.getCenter()[1]; - double cen_dist3 = geo_obb.getCenter()[2]-mesh_obb.getCenter()[2]; - double score1 = sqrt( cen_dist1*cen_dist1 - + cen_dist2*cen_dist2 - + cen_dist3*cen_dist3); - - double score2 = fabs(geo_obb.getSize()[0]-mesh_obb.getSize()[0]); - double score3 = fabs(geo_obb.getSize()[1]-mesh_obb.getSize()[1]); - double score4 = fabs(geo_obb.getSize()[2]-mesh_obb.getSize()[2]); + double score = SOrientedBoundingBox::compare(geo_obb,mesh_obb); - if (std::max(std::max(score1,score2),std::max(score3,score4)) < best_score) { - best_score = std::max(std::max(score1,score2),std::max(score3,score4)); + if (score < best_score) { + best_score = score; choice = (*candidate); } } //cout << "And the winner is ... " << choice << endl; - coresp_f->push_back(Pair<GFace*,GFace*>((GFace*) *entity1 , + } + + coresp_f->push_back(Pair<GFace*,GFace*>((GFace*) *entity1 , choice)); - choice->setTag(((GFace*) *entity1)->tag()); - num_matched_faces++; + choice->setTag(((GFace*) *entity1)->tag()); + num_matched_faces++; + + for (int i = 0; i < choice->getNumMeshElements(); i++) { + MVertex* v1 = choice->getMeshElement(i)->getVertex(0); + MVertex* v2 = choice->getMeshElement(i)->getVertex(1); + SPoint2 param1 = ((GFace*) *entity1)->parFromPoint(v1->point()); + SPoint2 param2 = ((GFace*) *entity1)->parFromPoint(v2->point()); + reparamMeshEdgeOnFace(v1,v2,(GFace*) *entity1,param1,param2); + if (v1->onWhat()->dim() == 2) + reparamMeshVertexOnFace(v1,(GFace*)*entity1,param1); + if (v2->onWhat()->dim() == 2) + reparamMeshVertexOnFace(v2,(GFace*)*entity1,param2); } } Msg::Info("Faces matched : %i / %i", num_matched_faces, num_total_faces); + if(num_matched_faces != num_total_faces) ok = false; + return coresp_f; } std::vector<Pair<GRegion*,GRegion*> >* GeomMeshMatcher::matchRegions(GModel* m1, GModel* m2, - std::vector<Pair<GFace*,GFace*> >* coresp_f) + std::vector<Pair<GFace*,GFace*> >* coresp_f, bool& ok) + { int num_matched_regions = 0; int num_total_regions = 0; @@ -389,25 +407,13 @@ GeomMeshMatcher::matchRegions(GModel* m1, GModel* m2, SOrientedBoundingBox mesh_obb = (*candidate)->getOBB(); Msg::Info("Comparing score : %f", SOrientedBoundingBox::compare(geo_obb,mesh_obb)); + double score = SOrientedBoundingBox::compare(geo_obb,mesh_obb); - if (geo_obb.intersects(mesh_obb)) { - double cen_dist1 = geo_obb.getCenter()[0]-mesh_obb.getCenter()[0]; - double cen_dist2 = geo_obb.getCenter()[1]-mesh_obb.getCenter()[1]; - double cen_dist3 = geo_obb.getCenter()[2]-mesh_obb.getCenter()[2]; - double score1 = sqrt( cen_dist1*cen_dist1 - + cen_dist2*cen_dist2 - + cen_dist3*cen_dist3); - - double score2 = fabs(geo_obb.getSize()[0]-mesh_obb.getSize()[0]); - double score3 = fabs(geo_obb.getSize()[1]-mesh_obb.getSize()[1]); - double score4 = fabs(geo_obb.getSize()[2]-mesh_obb.getSize()[2]); - - if (std::max(std::max(score1,score2),std::max(score3,score4)) < best_score) { - best_score = std::max(std::max(score1,score2),std::max(score3,score4)); + if (score < best_score) { + best_score = score; choice = (*candidate); } - } } coresp_r->push_back(Pair<GRegion*,GRegion*>((GRegion*) *entity1 , choice)); @@ -417,6 +423,7 @@ GeomMeshMatcher::matchRegions(GModel* m1, GModel* m2, } Msg::Info("Regions matched : %i / %i", num_matched_regions, num_total_regions); + if(num_matched_regions != num_total_regions) ok = false; return coresp_r; } @@ -439,20 +446,36 @@ void GeomMeshMatcher::destroy() int GeomMeshMatcher:: match(GModel *geom, GModel *mesh) { mesh->createTopologyFromMesh(); + bool ok = true; // This will match VERTICES - std::vector<Pair<GVertex*, GVertex*> > *coresp_v = matchVertices(geom, mesh); - - // This will match EDGES - std::vector<Pair<GEdge*, GEdge*> > *coresp_e = matchEdges(geom, mesh, coresp_v); - - // This will match SURFACES - std::vector<Pair<GFace*, GFace*> > *coresp_f = matchFaces(geom, mesh, coresp_e); - - // This will match REGIONS - //std::vector<Pair<GRegion*, GRegion*> >* coresp_r = - matchRegions(geom, mesh, coresp_f); - - mesh->writeMSH("out.msh", 2.0, false, true); - - return 1; + std::vector<Pair<GVertex*, GVertex*> > *coresp_v = matchVertices(geom, mesh,ok); + if (ok) { + // This will match EDGES + std::vector<Pair<GEdge*, GEdge*> > *coresp_e = matchEdges(geom, mesh, coresp_v,ok); + if (ok) { + // This will match SURFACES + std::vector<Pair<GFace*, GFace*> > *coresp_f = matchFaces(geom, mesh, coresp_e,ok); + if (ok) { + // This will match REGIONS + std::vector<Pair<GRegion*, GRegion*> >* coresp_r = matchRegions(geom, mesh, coresp_f,ok); + if (ok) { + mesh->writeMSH("out.msh",2.0,false,true,true); + return 1; + } else { + Msg::Error("Could not match every region !"); + return 0; + } + } else { + Msg::Error("Could not match every surface !"); + return 0; + } + } else { + Msg::Error("Could not match every edge !"); + return 0; + } + } else { + Msg::Error("Could not match every vertex !"); + return 0; + } + return 0; } diff --git a/Geo/GeomMeshMatcher.h b/Geo/GeomMeshMatcher.h index fd1eb917f77439f72d36ee37a15303688793fa8d..d7db73c2cafe669a10c4415890477c6cf9f519a2 100644 --- a/Geo/GeomMeshMatcher.h +++ b/Geo/GeomMeshMatcher.h @@ -20,13 +20,13 @@ class GeomMeshMatcher { private: - std::vector<Pair<GVertex*, GVertex*> > *matchVertices(GModel *m1, GModel *m2); + std::vector<Pair<GVertex*, GVertex*> > *matchVertices(GModel *m1, GModel *m2, bool& ok); std::vector<Pair<GEdge*, GEdge*> > *matchEdges - (GModel* m1, GModel* m2, std::vector<Pair<GVertex*, GVertex*> > *coresp_v); + (GModel* m1, GModel* m2, std::vector<Pair<GVertex*, GVertex*> > *coresp_v, bool& ok); std::vector<Pair<GFace*, GFace*> > *matchFaces - (GModel* m1, GModel* m2, std::vector<Pair<GEdge*,GEdge*> > *coresp_e); + (GModel* m1, GModel* m2, std::vector<Pair<GEdge*,GEdge*> > *coresp_e, bool& ok); std::vector<Pair<GRegion*, GRegion*> > *matchRegions - (GModel *m1, GModel *m2, std::vector<Pair<GFace*,GFace*> > *coresp_f); + (GModel *m1, GModel *m2, std::vector<Pair<GFace*,GFace*> > *coresp_f, bool& ok); static GeomMeshMatcher *_gmm_instance; GeomMeshMatcher() {} ~GeomMeshMatcher() {} diff --git a/Geo/SOrientedBoundingBox.cpp b/Geo/SOrientedBoundingBox.cpp index 773240a51c70d48d64d8557dec25718550fafb1c..cd1431d7828ba0d95eaa68e10173d5975806707a 100644 --- a/Geo/SOrientedBoundingBox.cpp +++ b/Geo/SOrientedBoundingBox.cpp @@ -156,9 +156,9 @@ SVector3 SOrientedBoundingBox::getAxis(int axis) { SVector3 ret; switch (axis) { - case 0: ret=axisX; - case 1: ret=axisY; - case 2: ret=axisZ; + case 0: ret=axisX; break; + case 1: ret=axisY; break; + case 2: ret=axisZ; break; } return ret; } @@ -531,13 +531,14 @@ SOrientedBoundingBox* SOrientedBoundingBox::buildOBB(std::vector<SPoint3> vertic center = aux1*center_pca + aux2*least_rectangle.center->at(0) + aux3*least_rectangle.center->at(1); //center[1] = -center[1]; - /* Msg::Info("Box center : %f %f %f",center[0],center[1],center[2]); Msg::Info("Box size : %f %f %f",size[0],size[1],size[2]); Msg::Info("Box axis 1 : %f %f %f",Axis1[0],Axis1[1],Axis1[2]); Msg::Info("Box axis 2 : %f %f %f",Axis2[0],Axis2[1],Axis2[2]); - Msg::Info("Box axis 1 : %f %f %f",Axis3[0],Axis3[1],Axis3[2]); + Msg::Info("Box axis 3 : %f %f %f",Axis3[0],Axis3[1],Axis3[2]); + + Msg::Info("Volume : %f", size[0]*size[1]*size[2]); */ return (new SOrientedBoundingBox(center, size[0], size[1], size[2], Axis1, Axis2, Axis3));