// SMESH SMESH : implementaion of SMESH idl descriptions // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : StdMeshers_MEFISTO_2D.cxx // Moved here from SMESH_MEFISTO_2D.cxx // Author : Paul RASCLE, EDF // Module : SMESH // $Header$ using namespace std; #include "StdMeshers_MEFISTO_2D.hxx" #include "SMESH_Gen.hxx" #include "SMESH_Mesh.hxx" #include "StdMeshers_MaxElementArea.hxx" #include "StdMeshers_LengthFromEdges.hxx" #include "Rn.h" #include "aptrte.h" #include "SMDS_MeshElement.hxx" #include "SMDS_MeshNode.hxx" #include "SMDS_EdgePosition.hxx" #include "SMDS_FacePosition.hxx" #include "utilities.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //============================================================================= /*! * */ //============================================================================= StdMeshers_MEFISTO_2D::StdMeshers_MEFISTO_2D(int hypId, int studyId, SMESH_Gen * gen):SMESH_2D_Algo(hypId, studyId, gen) { MESSAGE("StdMeshers_MEFISTO_2D::StdMeshers_MEFISTO_2D"); _name = "MEFISTO_2D"; // _shapeType = TopAbs_FACE; _shapeType = (1 << TopAbs_FACE); _compatibleHypothesis.push_back("MaxElementArea"); _compatibleHypothesis.push_back("LengthFromEdges"); _edgeLength = 0; _maxElementArea = 0; _hypMaxElementArea = NULL; _hypLengthFromEdges = NULL; } //============================================================================= /*! * */ //============================================================================= StdMeshers_MEFISTO_2D::~StdMeshers_MEFISTO_2D() { MESSAGE("StdMeshers_MEFISTO_2D::~StdMeshers_MEFISTO_2D"); } //============================================================================= /*! * */ //============================================================================= bool StdMeshers_MEFISTO_2D::CheckHypothesis (SMESH_Mesh& aMesh, const TopoDS_Shape& aShape, SMESH_Hypothesis::Hypothesis_Status& aStatus) { //MESSAGE("StdMeshers_MEFISTO_2D::CheckHypothesis"); _hypMaxElementArea = NULL; _hypLengthFromEdges = NULL; list ::const_iterator itl; const SMESHDS_Hypothesis *theHyp; const list &hyps = GetUsedHypothesis(aMesh, aShape); int nbHyp = hyps.size(); if (!nbHyp) { aStatus = SMESH_Hypothesis::HYP_MISSING; return false; // can't work with no hypothesis } itl = hyps.begin(); theHyp = (*itl); // use only the first hypothesis string hypName = theHyp->GetName(); int hypId = theHyp->GetID(); //SCRUTE(hypName); bool isOk = false; if (hypName == "MaxElementArea") { _hypMaxElementArea = static_cast(theHyp); ASSERT(_hypMaxElementArea); _maxElementArea = _hypMaxElementArea->GetMaxArea(); _edgeLength = 0; isOk = true; aStatus = SMESH_Hypothesis::HYP_OK; } else if (hypName == "LengthFromEdges") { _hypLengthFromEdges = static_cast(theHyp); ASSERT(_hypLengthFromEdges); _edgeLength = 0; _maxElementArea = 0; isOk = true; aStatus = SMESH_Hypothesis::HYP_OK; } else aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE; if (isOk) { isOk = false; if (_maxElementArea > 0) { _edgeLength = 2 * sqrt(_maxElementArea); // triangles : minorant isOk = true; } else isOk = (_hypLengthFromEdges != NULL); // **** check mode if (!isOk) aStatus = SMESH_Hypothesis::HYP_BAD_PARAMETER; } //SCRUTE(_edgeLength); //SCRUTE(_maxElementArea); return isOk; } //============================================================================= /*! * */ //============================================================================= bool StdMeshers_MEFISTO_2D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape) { MESSAGE("StdMeshers_MEFISTO_2D::Compute"); if (_hypLengthFromEdges) _edgeLength = ComputeEdgeElementLength(aMesh, aShape); bool isOk = false; const SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); SMESH_subMesh *theSubMesh = aMesh.GetSubMesh(aShape); const TopoDS_Face & FF = TopoDS::Face(aShape); bool faceIsForward = (FF.Orientation() == TopAbs_FORWARD); TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD)); Z nblf; //nombre de lignes fermees (enveloppe en tete) Z *nudslf = NULL; //numero du dernier sommet de chaque ligne fermee R2 *uvslf = NULL; Z nbpti = 0; //nombre points internes futurs sommets de la triangulation R2 *uvpti = NULL; Z nbst; R2 *uvst = NULL; Z nbt; Z *nust = NULL; Z ierr = 0; Z nutysu = 1; // 1: il existe un fonction areteideale_() // Z nutysu=0; // 0: on utilise aretmx R aretmx = _edgeLength; // longueur max aretes future triangulation //SCRUTE(aretmx); nblf = NumberOfWires(F); //SCRUTE(nblf); nudslf = new Z[1 + nblf]; nudslf[0] = 0; int iw = 1; int nbpnt = 0; const TopoDS_Wire OW1 = BRepTools::OuterWire(F); nbpnt += NumberOfPoints(aMesh, OW1); nudslf[iw++] = nbpnt; //SCRUTE(nbpnt); for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next()) { const TopoDS_Wire & W = TopoDS::Wire(exp.Current()); if (!OW1.IsSame(W)) { nbpnt += NumberOfPoints(aMesh, W); nudslf[iw++] = nbpnt; //SCRUTE(nbpnt); } } uvslf = new R2[nudslf[nblf]]; //SCRUTE(nudslf[nblf]); int m = 0; map mefistoToDS; // correspondence mefisto index--> points IDNodes TopoDS_Wire OW = BRepTools::OuterWire(F); LoadPoints(aMesh, F, OW, uvslf, m, mefistoToDS); //SCRUTE(m); for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next()) { const TopoDS_Wire & W = TopoDS::Wire(exp.Current()); if (!OW.IsSame(W)) { LoadPoints(aMesh, F, W, uvslf, m, mefistoToDS); //SCRUTE(m); } } // SCRUTE(nudslf[nblf]); // for (int i=0; i<=nblf; i++) // { // MESSAGE(" -+- " <&mefistoToDS) { MESSAGE("StdMeshers_MEFISTO_2D::LoadPoints"); SMDS_Mesh * meshDS = aMesh.GetMeshDS(); double scalex; double scaley; TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD)); ComputeScaleOnFace(aMesh, F, scalex, scaley); TopoDS_Wire W = TopoDS::Wire(WW.Oriented(TopAbs_FORWARD)); BRepTools_WireExplorer wexp(W, F); for (wexp.Init(W, F); wexp.More(); wexp.Next()) { const TopoDS_Edge & E = wexp.Current(); // --- IDNodes of first and last Vertex TopoDS_Vertex VFirst, VLast; TopExp::Vertices(E, VFirst, VLast); // corresponds to f and l ASSERT(!VFirst.IsNull()); SMDS_NodeIteratorPtr lid= aMesh.GetSubMesh(VFirst)->GetSubMeshDS()->GetNodes(); const SMDS_MeshNode* idFirst = lid->next(); ASSERT(!VLast.IsNull()); lid=aMesh.GetSubMesh(VLast)->GetSubMeshDS()->GetNodes(); const SMDS_MeshNode* idLast = lid->next(); // --- edge internal IDNodes (relies on good order storage, not checked) int nbPoints = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes(); //SCRUTE(nbPoints); double f, l; Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l); SMDS_NodeIteratorPtr ite= aMesh.GetSubMesh(E)->GetSubMeshDS()->GetNodes(); bool isForward = (E.Orientation() == TopAbs_FORWARD); map params; while(ite->more()) { const SMDS_MeshNode * node = ite->next(); const SMDS_EdgePosition* epos = static_cast(node->GetPosition().get()); double param = epos->GetUParameter(); params[param] = node; } // --- load 2D values into MEFISTO structure, // add IDNodes in mefistoToDS map if (E.Orientation() == TopAbs_FORWARD) { gp_Pnt2d p = C2d->Value(f); // first point = Vertex Forward uvslf[m].x = scalex * p.X(); uvslf[m].y = scaley * p.Y(); mefistoToDS[m + 1] = idFirst; //MESSAGE(" "<::iterator itp = params.begin(); for (int i = 1; i <= nbPoints; i++) // nbPoints internal { double param = (*itp).first; gp_Pnt2d p = C2d->Value(param); uvslf[m].x = scalex * p.X(); uvslf[m].y = scaley * p.Y(); mefistoToDS[m + 1] = (*itp).second; // MESSAGE(" "<Value(l); // last point = Vertex Reversed uvslf[m].x = scalex * p.X(); uvslf[m].y = scaley * p.Y(); mefistoToDS[m + 1] = idLast; // MESSAGE(" "<::reverse_iterator itp = params.rbegin(); for (int i = nbPoints; i >= 1; i--) { double param = (*itp).first; gp_Pnt2d p = C2d->Value(param); uvslf[m].x = scalex * p.X(); uvslf[m].y = scaley * p.Y(); mefistoToDS[m + 1] = (*itp).second; // MESSAGE(" "<Value(param); if (p.X() < xmin) xmin = p.X(); if (p.X() > xmax) xmax = p.X(); if (p.Y() < ymin) ymin = p.Y(); if (p.Y() > ymax) ymax = p.Y(); // MESSAGE(" "<< f<<" "<Value(xmin, ymoy); gp_Pnt PY0 = S->Value(xmoy, ymin); for (int i = 1; i <= nbp; i++) { double x = xmin + (double (i) / double (nbp))*(xmax - xmin); gp_Pnt PX = S->Value(x, ymoy); double y = ymin + (double (i) / double (nbp))*(ymax - ymin); gp_Pnt PY = S->Value(xmoy, y); length_x += PX.Distance(PX0); length_y += PY.Distance(PY0); PX0.SetCoord(PX.X(), PX.Y(), PX.Z()); PY0.SetCoord(PY.X(), PY.Y(), PY.Z()); } // SCRUTE(length_x); // SCRUTE(length_y); scalex = length_x / (xmax - xmin); scaley = length_y / (ymax - ymin); // SCRUTE(scalex); // SCRUTE(scaley); ASSERT(scalex); ASSERT(scaley); } //============================================================================= /*! * */ //============================================================================= void StdMeshers_MEFISTO_2D::StoreResult(SMESH_Mesh & aMesh, Z nbst, R2 * uvst, Z nbt, Z * nust, const TopoDS_Face & F, bool faceIsForward, map&mefistoToDS) { double scalex; double scaley; ComputeScaleOnFace(aMesh, F, scalex, scaley); SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); Z n, m; Handle(Geom_Surface) S = BRep_Tool::Surface(F); for (n = 0; n < nbst; n++) { double u = uvst[n][0] / scalex; double v = uvst[n][1] / scaley; gp_Pnt P = S->Value(u, v); if (mefistoToDS.find(n + 1) == mefistoToDS.end()) { SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z()); meshDS->SetNodeOnFace(node, F); //MESSAGE(nodeId<<" "<(node->GetPosition().get()); fpos->SetUParameter(u); fpos->SetVParameter(v); } } m = 0; int mt = 0; //SCRUTE(faceIsForward); for (n = 1; n <= nbt; n++) { int inode1 = nust[m++]; int inode2 = nust[m++]; int inode3 = nust[m++]; const SMDS_MeshNode *n1, *n2, *n3; n1 = mefistoToDS[inode1]; n2 = mefistoToDS[inode2]; n3 = mefistoToDS[inode3]; //MESSAGE("-- "<AddFace(n1, n2, n3); else elt = meshDS->AddFace(n1, n3, n2); meshDS->SetMeshElementOnShape(elt, F); m++; } } //============================================================================= /*! * */ //============================================================================= double StdMeshers_MEFISTO_2D::ComputeEdgeElementLength(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape) { MESSAGE("StdMeshers_MEFISTO_2D::ComputeEdgeElementLength"); // **** a mettre dans SMESH_2D_Algo ? const TopoDS_Face & FF = TopoDS::Face(aShape); bool faceIsForward = (FF.Orientation() == TopAbs_FORWARD); TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD)); double meanElementLength = 100; double wireLength = 0; int wireElementsNumber = 0; for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next()) { const TopoDS_Wire & W = TopoDS::Wire(exp.Current()); for (TopExp_Explorer expe(W, TopAbs_EDGE); expe.More(); expe.Next()) { const TopoDS_Edge & E = TopoDS::Edge(expe.Current()); int nb = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes(); double length = EdgeLength(E); wireLength += length; wireElementsNumber += nb; } } if (wireElementsNumber) meanElementLength = wireLength / wireElementsNumber; //SCRUTE(meanElementLength); return meanElementLength; } //============================================================================= /*! * */ //============================================================================= ostream & StdMeshers_MEFISTO_2D::SaveTo(ostream & save) { return save; } //============================================================================= /*! * */ //============================================================================= istream & StdMeshers_MEFISTO_2D::LoadFrom(istream & load) { return load; } //============================================================================= /*! * */ //============================================================================= ostream & operator <<(ostream & save, StdMeshers_MEFISTO_2D & hyp) { return hyp.SaveTo( save ); } //============================================================================= /*! * */ //============================================================================= istream & operator >>(istream & load, StdMeshers_MEFISTO_2D & hyp) { return hyp.LoadFrom( load ); }