37 template <
class T,
class container>
41 if(lists.empty())
return;
42 container
const &first_list = lists[0];
44 for(
auto item = first_list.begin(); item != first_list.end(); item++) {
47 for(
auto list_iter = lists.begin(); list_iter != lists.end(); list_iter++) {
48 if(*(list_iter) != first_list) {
50 if(std::find((*list_iter).begin(), (*list_iter).end(), (*item)) ==
60 if(found || allsame) { res.push_back(*item); }
66 for(
auto pair = matching.begin(); pair != matching.end(); pair++) {
67 if((*pair).left() == entity)
return ((*pair).right());
74 std::vector<Pair<GVertex *, GVertex *> > *
78 std::vector<Pair<GVertex *, GVertex *> > *coresp_v =
79 new std::vector<Pair<GVertex *, GVertex *> >;
80 int num_matched_vertices = 0;
83 std::vector<GVertex *> vertices;
92 double best_score = DBL_MAX;
100 std::max(fabs(v1->
x() - v2->
x()),
101 std::max(fabs(v1->
y() - v2->
y()), fabs(v1->
z() - v2->
z())));
102 if(score < tol && score < best_score) {
108 if(choice && best_score != DBL_MAX) {
111 num_matched_vertices++;
115 if(num_matched_vertices != num_total_vertices) ok =
false;
116 Msg::Info(
"Matched %i nodes out of %i", num_matched_vertices,
123 std::vector<Pair<GEdge *, GEdge *> > *
128 int num_matched_edges = 0;
132 std::vector<Pair<GEdge *, GEdge *> > *coresp_e =
133 new std::vector<Pair<GEdge *, GEdge *> >;
135 std::vector<GEdge *> closed_curves;
143 std::vector<GEdge *> common_edges;
144 std::vector<std::vector<GEdge *> > lists;
148 closed_curves.push_back(e1);
157 common_edges.push_back(e2);
164 if(findMatching<GVertex *>(*coresp_v, v1) != 0) {
166 lists.push_back((findMatching<GVertex *>(*coresp_v, v1))->
edges());
168 if(findMatching<GVertex *>(*coresp_v, v2) != 0) {
170 lists.push_back((findMatching<GVertex *>(*coresp_v, v2))->
edges());
172 if(ok1 && ok2) getIntersection<GEdge *>(common_edges, lists);
175 GEdge *choice =
nullptr;
176 if(common_edges.size() == 0)
continue;
177 if(common_edges.size() == 1) { choice = common_edges[0]; }
185 double best_score = DBL_MAX;
187 for(
auto candidate = common_edges.begin();
188 candidate != common_edges.end(); candidate++) {
192 if(score < best_score) {
194 choice = (*candidate);
209 Msg::Info(
"Matched %i curves out of %i", num_matched_edges, num_total_edges);
210 if(num_matched_edges != num_total_edges) ok =
false;
216 std::vector<Pair<GFace *, GFace *> > *
221 int num_matched_faces = 0;
224 std::vector<Pair<GFace *, GFace *> > *coresp_f =
225 new std::vector<Pair<GFace *, GFace *> >;
230 std::vector<std::vector<GFace *> > lists;
232 std::vector<GEdge *> boundary_edges = f1->
edges();
234 for(
auto boundary_edge = boundary_edges.begin();
235 boundary_edge != boundary_edges.end(); boundary_edge++) {
238 if(!(*boundary_edge)->isSeam(f1)) {
239 GEdge *ge = findMatching<GEdge *>(*coresp_e, *boundary_edge);
241 Msg::Error(
"Could not find curve %i in surface %i during matching",
242 (*boundary_edge)->tag(), f1->
tag());
244 lists.push_back(ge->
faces());
247 std::vector<GFace *> common_faces;
248 getIntersection<GFace *>(common_faces, lists);
249 GFace *choice =
nullptr;
251 if(common_faces.size() == 0) {
256 if(common_faces.size() == 1) { choice = common_faces[0]; }
261 double best_score = DBL_MAX;
263 for(
auto candidate = common_faces.begin();
264 candidate != common_faces.end(); candidate++) {
270 if(score < best_score) {
272 choice = (*candidate);
287 Msg::Info(
"Matched %i surfaces out of %i", num_matched_faces,
295 std::vector<Pair<GRegion *, GRegion *> > *
301 int num_matched_regions = 0;
302 int num_total_regions = 0;
304 std::vector<Pair<GRegion *, GRegion *> > *coresp_r =
305 new std::vector<Pair<GRegion *, GRegion *> >;
307 std::vector<GEntity *> m1_entities;
309 std::vector<GEntity *> m2_entities;
312 if(m1_entities.empty() || m2_entities.empty()) {
313 Msg::Info(
"No volumes could be matched since one of the models does "
318 for(
auto entity1 = m1_entities.begin(); entity1 != m1_entities.end();
324 std::vector<GFace *> boundary_faces = ((
GFace *)(*entity1))->
faces();
325 std::vector<GFace *> coresp_bound_faces;
326 std::vector<GRegion *> common_regions;
328 for(
auto boundary_face = boundary_faces.begin();
329 boundary_face != boundary_faces.end(); boundary_face++) {
330 coresp_bound_faces.push_back(
331 findMatching<GFace *>(*coresp_f, *boundary_face));
333 for(
auto entity2 = m2_entities.begin(); entity2 != m2_entities.end();
335 if((*entity2)->dim() != 3)
continue;
336 std::vector<std::vector<GFace *> > lists;
337 lists.push_back(coresp_bound_faces);
339 std::vector<GFace *> common_faces;
340 getIntersection<GFace *>(common_faces, lists);
341 if(common_faces.size() == coresp_bound_faces.size()) {
342 common_regions.push_back((
GRegion *)*entity2);
346 if(common_regions.size() == 1) {
349 common_regions[0]->setTag(((
GRegion *)*entity1)->tag());
350 (*entity1)->physicals = common_regions[0]->physicals;
351 num_matched_regions++;
353 else if(common_regions.size() > 1) {
359 std::vector<GEdge *> boundaries = ((
GRegion *)*entity1)->edges();
365 double best_score = DBL_MAX;
367 for(
auto candidate = common_regions.begin();
368 candidate != common_regions.end(); candidate++) {
375 if(score < best_score) {
377 choice = (*candidate);
384 (*entity1)->physicals = choice->
physicals;
386 num_matched_regions++;
390 Msg::Info(
"Volumes matched: %i / %i", num_matched_regions,
392 if(num_matched_regions != num_total_regions) ok =
false;
413 double bestScore = TOL;
416 GVertex *v2 = (*it)->getBeginVertex();
417 double score = sqrt((v1->
x() - v2->
x()) * (v1->
x() - v2->
x()) +
418 (v1->
y() - v2->
y()) * (v1->
y() - v2->
y()) +
419 (v1->
z() - v2->
z()) * (v1->
z() - v2->
z()));
420 if(score < bestScore) {
426 GVertex *v2 = (*it)->getEndVertex();
427 double score = sqrt((v1->
x() - v2->
x()) * (v1->
x() - v2->
x()) +
428 (v1->
y() - v2->
y()) * (v1->
y() - v2->
y()) +
429 (v1->
z() - v2->
z()) * (v1->
z() - v2->
z()));
430 if(score < bestScore) {
442 double bestScore = TOL;
448 double score = sqrt((v1->
x() - gp.
x()) * (v1->
x() - gp.
x()) +
449 (v1->
y() - gp.
y()) * (v1->
y() - gp.
y()) +
450 (v1->
z() - gp.
z()) * (v1->
z() - gp.
z()));
451 if(score < bestScore) {
463 double bestScore = TOL;
467 double guess[2] = {0, 0};
469 double score = sqrt((v1->
x() - gp.
x()) * (v1->
x() - gp.
x()) +
470 (v1->
y() - gp.
y()) * (v1->
y() - gp.
y()) +
471 (v1->
z() - gp.
z()) * (v1->
z() - gp.
z()));
472 if(score < bestScore) {
484 std::vector<GEntity *> entities;
486 for(std::size_t i = 0; i < entities.size(); i++) {
487 for(std::size_t j = 0; j < entities[i]->mesh_vertices.size(); j++) {
488 MVertex *v = entities[i]->mesh_vertices[j];
512 gp.
x(), gp.
y(), gp.
z(), gg, gp.
u(), gp.
v(), v->
getNum()));
516 Msg::Error(
"Node %d classified on entity of dimension %d and tag %d "
522 for(std::size_t i = 0; i < (*it)->lines.size(); i++) {
546 (*it)->lines[i]->getVertex(0)->getNum());
549 (*it)->lines[i]->getVertex(1)->getNum());
554 for(std::size_t i = 0; i < (*it)->triangles.size(); i++) {
568 for(std::size_t i = 0; i < (*it)->quadrangles.size(); i++) {
580 ->quadrangles.push_back(
new MQuadrangle(v1, v2, v3, v4));
583 ->quadrangles.push_back(
new MQuadrangle(v1, v2, v3, v4));
586 ->quadrangles.push_back(
new MQuadrangle(v1, v2, v3, v4));
589 ->quadrangles.push_back(
new MQuadrangle(v1, v2, v3, v4));
592 geom->
writeMSH(
"hopla.msh", 2.2,
false,
false,
true);
596 template <
class GEType>
598 std::map<MVertex *, MVertex *> &mesh_to_geom)
600 typename std::multimap<GEType *, GEType *> eMap;
601 auto eIter = eCor.begin();
602 for(; eIter != eCor.end(); ++eIter) {
603 eMap.insert(std::make_pair(eIter->second(), eIter->first()));
606 auto srcIter = eMap.begin();
608 for(; srcIter != eMap.end(); ++srcIter) {
609 GEType *oldTgt = srcIter->first;
610 GEType *oldSrc =
dynamic_cast<GEType *
>(oldTgt->getMeshMaster());
612 if(oldSrc !=
nullptr && oldSrc != oldTgt) {
613 GEType *newTgt = srcIter->second;
614 auto tgtIter = eMap.find(oldSrc);
615 if(tgtIter == eMap.end()) {
616 Msg::Error(
"Could not find matched entity for %d, which has a matched "
617 "periodic counterpart %d", oldSrc->tag(), oldTgt->tag());
620 GEType *newSrc = tgtIter->second;
621 newTgt->setMeshMaster(newSrc, oldTgt->affineTransform);
623 std::map<MVertex *, MVertex *> &oldV2v = oldTgt->correspondingVertices;
624 std::map<MVertex *, MVertex *> &newV2v = newTgt->correspondingVertices;
626 auto vIter = oldV2v.begin();
627 for(; vIter != oldV2v.end(); ++vIter) {
628 MVertex *oldTgtV = vIter->first;
629 MVertex *oldSrcV = vIter->second;
631 auto newTvIter = mesh_to_geom.find(oldTgtV);
632 auto newSvIter = mesh_to_geom.find(oldSrcV);
634 if(newTvIter == mesh_to_geom.end()) {
635 Msg::Error(
"Could not find copy of target node %d in entity %d "
636 "of dim %d", oldTgtV->
getIndex(), oldTgt->tag(),
641 if(newSvIter == mesh_to_geom.end()) {
642 Msg::Error(
"Could not find copy of source node %d in entity %d "
643 "of dim %d", oldSrcV->
getIndex(), oldSrc->tag(),
647 newV2v[newTvIter->second] = newSvIter->second;
653 template <
class GEType>
656 typename std::multimap<GEType *, GEType *> eMap;
657 auto eIter = eCor.begin();
658 for(; eIter != eCor.end(); ++eIter) {
659 eMap.insert(std::make_pair(eIter->second(), eIter->first()));
662 auto srcIter = eMap.begin();
666 for(; srcIter != eMap.end(); ++srcIter) {
667 GEType *newTgt = srcIter->second;
668 newTgt->updateCorrespondingVertices();
669 newTgt->alignElementsWithMaster();
670 if(dim == -1) dim = newTgt->dim();
674 for(srcIter = eMap.begin(); srcIter != eMap.end(); ++srcIter) {
675 GEType *newTgt = srcIter->second;
676 newTgt->copyMasterCoordinates();
677 newTgt->alignElementsWithMaster();
685 std::map<MVertex *, MVertex *> &_mesh_to_geom)
689 for(std::size_t i = 0; i < 1; i++) {
693 _mesh_to_geom[v_from] = v_to;
698 std::map<MVertex *, MVertex *> &_mesh_to_geom)
702 for(std::size_t i = 0; i < from->
mesh_vertices.size(); i++) {
706 _mesh_to_geom[v_from] = v_to;
711 std::map<MVertex *, MVertex *> &_mesh_to_geom)
715 Msg::Warning(
"Curve %d in the mesh do not match any curve in the model",
720 Msg::Warning(
"Curve %d in the geometry do not match any curve in the mesh",
725 for(std::size_t i = 0; i < from->
mesh_vertices.size(); i++) {
732 _mesh_to_geom[v_from] = v_to;
737 std::map<MVertex *, MVertex *> &_mesh_to_geom)
739 for(std::size_t i = 0; i < from->
mesh_vertices.size(); i++) {
744 double DDD = (v_from->
x() - gp.
x()) * (v_from->
x() - gp.
x()) +
745 (v_from->
y() - gp.
y()) * (v_from->
y() - gp.
y()) +
746 (v_from->
z() - gp.
z()) * (v_from->
z() - gp.
z());
748 if(sqrt(DDD) > 1.e-1)
749 Msg::Error(
"Impossible to match node: original (%g,%g,%g), new (%g,%g,%g)",
750 v_from->
x(), v_from->
y(), v_from->
z(), gp.
x(), gp.
y(), gp.
z());
752 else if(sqrt(DDD) > 1.e-3)
753 Msg::Warning(
"One mesh node (%g,%g,%g) of surface %d is difficult to match: "
754 "closest point (%g,%g,%g)", v_from->
x(), v_from->
y(), v_from->
z(),
755 to->
tag(), gp.
x(), gp.
y(), gp.
z());
760 _mesh_to_geom[v_from] = v_to;
764 template <
class ELEMENT>
766 std::vector<ELEMENT *> &from,
767 std::map<MVertex *, MVertex *> &_mesh_to_geom)
771 for(std::size_t i = 0; i < from.size(); i++) {
772 ELEMENT *e = from[i];
773 std::vector<MVertex *> nodes;
774 for(std::size_t j = 0; j < e->getNumVertices(); j++) {
775 auto vIter = _mesh_to_geom.find(e->getVertex(j));
776 if(vIter == _mesh_to_geom.end()) {
777 Msg::Error(
"Could not find match for node %i during element copy",
778 e->getVertex(j)->getNum());
781 nodes.push_back(vIter->second);
783 if(nodes.size() == e->getNumVertices())
784 to.push_back((ELEMENT *)(toto.
create(e->getTypeForMSH(), nodes)));
789 std::map<MVertex *, MVertex *> &_mesh_to_geom,
796 for(std::size_t i = 0; i < coresp_v->size(); ++i)
797 copy_vertices((*coresp_v)[i].first(), (*coresp_v)[i].second(),
799 for(std::size_t i = 0; i < coresp_e->size(); ++i)
800 copy_vertices((*coresp_e)[i].first(), (*coresp_e)[i].second(),
802 for(std::size_t i = 0; i < coresp_f->size(); ++i)
803 copy_vertices((*coresp_f)[i].first(), (*coresp_f)[i].second(),
805 for(std::size_t i = 0; i < coresp_r->size(); ++i)
806 copy_vertices((*coresp_r)[i].first(), (*coresp_r)[i].second(),
810 std::map<MVertex *, MVertex *> &_mesh_to_geom,
818 for(std::size_t i = 0; i < coresp_v->size(); ++i) {
819 GVertex *dest = (*coresp_v)[i].first();
820 GVertex *orig = (*coresp_v)[i].second();
821 copy_elements<MPoint>(dest->
points, orig->
points, _mesh_to_geom);
824 for(std::size_t i = 0; i < coresp_e->size(); ++i) {
825 GEdge *dest = (*coresp_e)[i].first();
826 GEdge *orig = (*coresp_e)[i].second();
827 copy_elements<MLine>(dest->
lines, orig->
lines, _mesh_to_geom);
830 for(std::size_t i = 0; i < coresp_f->size(); ++i) {
831 GFace *dest = (*coresp_f)[i].first();
832 GFace *orig = (*coresp_f)[i].second();
838 for(std::size_t i = 0; i < coresp_r->size(); ++i) {
839 GRegion *dest = (*coresp_r)[i].first();
840 GRegion *orig = (*coresp_r)[i].second();
844 copy_elements<MPrism>(dest->
prisms, orig->
prisms, _mesh_to_geom);
860 std::vector<Pair<GVertex *, GVertex *> > *coresp_v(
nullptr);
861 std::vector<Pair<GEdge *, GEdge *> > *coresp_e(
nullptr);
862 std::vector<Pair<GFace *, GFace *> > *coresp_f(
nullptr);
863 std::vector<Pair<GRegion *, GRegion *> > *coresp_r(
nullptr);
867 coresp_e =
matchEdges(geom, mesh, coresp_v, ok);
869 coresp_f =
matchFaces(geom, mesh, coresp_e, ok);
870 if(ok) { coresp_r =
matchRegions(geom, mesh, coresp_f, ok); }
872 Msg::Error(
"Could only match %i surfaces out of %i: stopping match",
876 Msg::Error(
"Could only match %i curves out of %i: stopping match",
880 Msg::Error(
"Could only match %i points out of %i: check mesh/CAD or "
881 "increase Geom.MatchMeshTolerance (currently %g)",
885 std::map<MVertex *, MVertex *> _mesh_to_geom;
888 Msg::Info(
"Copying mesh nodes and elements to CAD model entities...");
889 copy_vertices(geom, mesh, _mesh_to_geom, coresp_v, coresp_e, coresp_f,
891 copy_elements(geom, mesh, _mesh_to_geom, coresp_v, coresp_e, coresp_f,
893 Msg::Info(
"Applying periodicity to CAD model entities...");
902 if(coresp_v)
delete coresp_v;
903 if(coresp_e)
delete coresp_e;
904 if(coresp_f)
delete coresp_f;
905 if(coresp_r)
delete coresp_r;
908 Msg::StatusBar(
true,
"Successfully matched mesh to CAD (Wall %gs, CPU %gs)",