1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // SMESH SMESH : implementaion of SMESH idl descriptions
23 // File : StdMeshers_RadialQuadrangle_1D2D.cxx
25 // Created : Fri Oct 20 11:37:07 2006
26 // Author : Edward AGAPOV (eap)
28 #include "StdMeshers_RadialQuadrangle_1D2D.hxx"
30 //#include "StdMeshers_ProjectionUtils.hxx"
31 #include "StdMeshers_NumberOfLayers.hxx"
32 #include "StdMeshers_LayerDistribution.hxx"
33 //#include "StdMeshers_Prism_3D.hxx"
34 #include "StdMeshers_Regular_1D.hxx"
36 #include "SMDS_MeshNode.hxx"
37 #include "SMESHDS_SubMesh.hxx"
38 #include "SMESH_Gen.hxx"
39 #include "SMESH_Mesh.hxx"
40 #include "SMESH_MesherHelper.hxx"
41 #include "SMESH_subMesh.hxx"
42 #include "SMESH_subMeshEventListener.hxx"
44 #include "utilities.h"
46 #include <BRepAdaptor_Curve.hxx>
47 #include <BRepBuilderAPI_MakeEdge.hxx>
48 //#include <BRepTools.hxx>
49 #include <BRep_Tool.hxx>
50 #include <TopExp_Explorer.hxx>
52 //#include <TopoDS_Shell.hxx>
53 //#include <TopoDS_Solid.hxx>
54 //#include <TopTools_MapOfShape.hxx>
56 //#include <gp_Pnt.hxx>
59 #include <Geom_TrimmedCurve.hxx>
60 #include <Geom_Circle.hxx>
61 #include <Geom_Line.hxx>
62 #include <TColgp_SequenceOfPnt.hxx>
63 #include <TColgp_SequenceOfPnt2d.hxx>
64 #include <GeomAPI_ProjectPointOnSurf.hxx>
69 #define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; }
70 #define gpXYZ(n) gp_XYZ(n->X(),n->Y(),n->Z())
72 //typedef StdMeshers_ProjectionUtils TAssocTool;
75 //=======================================================================
76 //function : StdMeshers_RadialQuadrangle_1D2D
78 //=======================================================================
80 StdMeshers_RadialQuadrangle_1D2D::StdMeshers_RadialQuadrangle_1D2D(int hypId,
83 :SMESH_2D_Algo(hypId, studyId, gen)
85 _name = "RadialQuadrangle_1D2D";
86 _shapeType = (1 << TopAbs_FACE); // 1 bit per shape type
88 _compatibleHypothesis.push_back("LayerDistribution2D");
89 _compatibleHypothesis.push_back("NumberOfLayers2D");
91 myDistributionHypo = 0;
92 _requireDescretBoundary = false;
96 //================================================================================
100 //================================================================================
102 StdMeshers_RadialQuadrangle_1D2D::~StdMeshers_RadialQuadrangle_1D2D()
106 //=======================================================================
107 //function : CheckHypothesis
109 //=======================================================================
111 bool StdMeshers_RadialQuadrangle_1D2D::CheckHypothesis
113 const TopoDS_Shape& aShape,
114 SMESH_Hypothesis::Hypothesis_Status& aStatus)
118 myDistributionHypo = 0;
120 list <const SMESHDS_Hypothesis * >::const_iterator itl;
122 const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
123 if ( hyps.size() == 0 ) {
124 aStatus = SMESH_Hypothesis::HYP_MISSING;
125 return false; // can't work with no hypothesis
128 if ( hyps.size() > 1 ) {
129 aStatus = SMESH_Hypothesis::HYP_ALREADY_EXIST;
133 const SMESHDS_Hypothesis *theHyp = hyps.front();
135 string hypName = theHyp->GetName();
137 if (hypName == "NumberOfLayers2D") {
138 myNbLayerHypo = static_cast<const StdMeshers_NumberOfLayers *>(theHyp);
139 aStatus = SMESH_Hypothesis::HYP_OK;
142 if (hypName == "LayerDistribution2D") {
143 myDistributionHypo = static_cast<const StdMeshers_LayerDistribution *>(theHyp);
144 aStatus = SMESH_Hypothesis::HYP_OK;
147 aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
152 //=======================================================================
155 //=======================================================================
157 bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh& aMesh,
158 const TopoDS_Shape& aShape)
161 SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
163 myHelper = new SMESH_MesherHelper( aMesh );
164 myHelper->IsQuadraticSubMesh( aShape );
166 myLayerPositions.clear();
168 TopoDS_Edge E1,E2,E3;
169 Handle(Geom_Curve) C1,C2,C3;
170 double f1,l1,f2,l2,f3,l3;
172 for ( exp.Init( aShape, TopAbs_EDGE ); exp.More(); exp.Next() ) {
174 TopoDS_Edge E = TopoDS::Edge( exp.Current() );
177 C1 = BRep_Tool::Curve(E,f1,l1);
181 C2 = BRep_Tool::Curve(E,f2,l2);
185 C3 = BRep_Tool::Curve(E,f3,l3);
190 return error(COMPERR_BAD_SHAPE);
193 // points for rotation
194 TColgp_SequenceOfPnt Points;
195 // angles for rotation
196 TColStd_SequenceOfReal Angles;
197 // Nodes1 and Nodes2 - nodes along radiuses
198 // CNodes - nodes on circle edge
199 std::vector< const SMDS_MeshNode* > Nodes1, Nodes2, CNodes;
201 // parameters edge nodes on face
202 TColgp_SequenceOfPnt2d Pnts2d1, Pnts2d2;
205 int faceID = meshDS->ShapeToIndex(aShape);
206 TopoDS_Face F = TopoDS::Face(aShape);
207 Handle(Geom_Surface) S = BRep_Tool::Surface(F);
209 //cout<<"RadialQuadrangle_1D2D::Compute nbe = "<<nbe<<endl;
210 TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
212 // C1 must be a circle
213 Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(C1);
215 return error(COMPERR_BAD_SHAPE);
218 bool ok = _gen->Compute( aMesh, CircEdge, false, MeshDim_1D );
219 if( !ok ) return false;
220 std::map< double, const SMDS_MeshNode* > theNodes;
221 GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes);
224 std::map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin();
225 const SMDS_MeshNode* NF = (*itn).second;
226 CNodes.push_back( (*itn).second );
227 double fang = (*itn).first;
229 for(; itn != theNodes.end(); itn++ ) {
230 CNodes.push_back( (*itn).second );
231 double ang = (*itn).first - fang;
232 if( ang>PI ) ang = ang - 2*PI;
233 if( ang<-PI ) ang = ang + 2*PI;
234 Angles.Append( ang );
236 P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() );
237 P0 = aCirc->Location();
239 myLayerPositions.clear();
240 computeLayerPositions(P0,P1);
242 exp.Init( CircEdge, TopAbs_VERTEX );
243 TopoDS_Vertex V1 = TopoDS::Vertex( exp.Current() );
244 gp_Pnt2d p2dV = BRep_Tool::Parameters( V1, TopoDS::Face(aShape) );
246 NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z());
247 GeomAPI_ProjectPointOnSurf PPS(P0,S);
249 PPS.Parameters(1,U0,V0);
250 meshDS->SetNodeOnFace(NC, faceID, U0, V0);
251 PC = gp_Pnt2d(U0,V0);
254 gp_Vec2d aVec2d(PC,p2dV);
255 Nodes1.resize( myLayerPositions.size()+1 );
256 Nodes2.resize( myLayerPositions.size()+1 );
258 for(; i<myLayerPositions.size(); i++) {
259 gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
260 P0.Y() + aVec.Y()*myLayerPositions[i],
261 P0.Z() + aVec.Z()*myLayerPositions[i] );
263 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
266 double U = PC.X() + aVec2d.X()*myLayerPositions[i];
267 double V = PC.Y() + aVec2d.Y()*myLayerPositions[i];
268 meshDS->SetNodeOnFace( node, faceID, U, V );
269 Pnts2d1.Append(gp_Pnt2d(U,V));
270 Pnts2d2.Append(gp_Pnt2d(U,V));
272 Nodes1[Nodes1.size()-1] = NF;
273 Nodes2[Nodes1.size()-1] = NF;
276 // one curve must be a half of circle and other curve must be
278 Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(C1);
279 while( !tc.IsNull() ) {
280 C1 = tc->BasisCurve();
281 tc = Handle(Geom_TrimmedCurve)::DownCast(C1);
283 tc = Handle(Geom_TrimmedCurve)::DownCast(C2);
284 while( !tc.IsNull() ) {
285 C2 = tc->BasisCurve();
286 tc = Handle(Geom_TrimmedCurve)::DownCast(C2);
289 Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(C1);
290 Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast(C2);
295 if( aCirc.IsNull() ) {
296 aCirc = Handle(Geom_Circle)::DownCast(C2);
301 aLine = Handle(Geom_Line)::DownCast(C3);
303 if( aCirc.IsNull() ) {
305 return error(COMPERR_BAD_SHAPE);
307 if( fabs(fabs(lp-fp)-PI) > Precision::Confusion() ) {
308 // not half of circle
309 return error(COMPERR_BAD_SHAPE);
311 if( aLine.IsNull() ) {
312 // other curve not line
313 return error(COMPERR_BAD_SHAPE);
315 SMESH_subMesh* sm1 = aMesh.GetSubMesh(LinEdge1);
317 SMESHDS_SubMesh* sdssm1 = sm1->GetSubMeshDS();
319 if( sm1->GetSubMeshDS()->NbNodes()>0 ) {
320 SMESH_subMesh* sm = aMesh.GetSubMesh(F);
321 SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
322 smError.reset(new SMESH_ComputeError(COMPERR_ALGO_FAILED,
323 "Invalid set of hypothesises",this));
329 bool ok = _gen->Compute( aMesh, CircEdge, false, MeshDim_1D );
330 if( !ok ) return false;
331 std::map< double, const SMDS_MeshNode* > theNodes;
332 GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes);
335 std::map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin();
336 const SMDS_MeshNode* NF = (*itn).second;
337 CNodes.push_back( (*itn).second );
338 double fang = (*itn).first;
340 const SMDS_MeshNode* NL;
342 for(; itn != theNodes.end(); itn++ ) {
344 if( nbn == theNodes.size() )
346 CNodes.push_back( (*itn).second );
347 double ang = (*itn).first - fang;
348 if( ang>PI ) ang = ang - 2*PI;
349 if( ang<-PI ) ang = ang + 2*PI;
350 Angles.Append( ang );
352 P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() );
353 gp_Pnt P2( NL->X(), NL->Y(), NL->Z() );
354 P0 = aCirc->Location();
356 myLayerPositions.clear();
357 computeLayerPositions(P0,P1);
360 int edgeID = meshDS->ShapeToIndex(LinEdge1);
362 Handle(Geom_Curve) Crv = BRep_Tool::Curve(LinEdge1,fp,lp);
366 if( P1.Distance(Ptmp) > Precision::Confusion() )
368 // get UV points for edge
370 BRep_Tool::UVPoints( LinEdge1, TopoDS::Face(aShape), PF, PL );
371 PC = gp_Pnt2d( (PF.X()+PL.X())/2, (PF.Y()+PL.Y())/2 );
373 if(ori) V2d = gp_Vec2d(PC,PF);
374 else V2d = gp_Vec2d(PC,PL);
376 double cp = (fp+lp)/2;
377 double dp2 = (lp-fp)/2;
378 NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z());
379 meshDS->SetNodeOnEdge(NC, edgeID, cp);
380 Nodes1.resize( myLayerPositions.size()+1 );
381 Nodes2.resize( myLayerPositions.size()+1 );
383 for(; i<myLayerPositions.size(); i++) {
384 gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
385 P0.Y() + aVec.Y()*myLayerPositions[i],
386 P0.Z() + aVec.Z()*myLayerPositions[i] );
388 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
392 param = fp + dp2*(1-myLayerPositions[i]);
394 param = cp + dp2*myLayerPositions[i];
395 meshDS->SetNodeOnEdge(node, edgeID, param);
396 P = gp_Pnt( P0.X() - aVec.X()*myLayerPositions[i],
397 P0.Y() - aVec.Y()*myLayerPositions[i],
398 P0.Z() - aVec.Z()*myLayerPositions[i] );
399 node = meshDS->AddNode(P.X(), P.Y(), P.Z());
402 param = fp + dp2*(1-myLayerPositions[i]);
404 param = cp + dp2*myLayerPositions[i];
405 meshDS->SetNodeOnEdge(node, edgeID, param);
406 // parameters on face
407 gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i],
408 PC.Y() + V2d.Y()*myLayerPositions[i] );
410 P2d = gp_Pnt2d( PC.X() - V2d.X()*myLayerPositions[i],
411 PC.Y() - V2d.Y()*myLayerPositions[i] );
414 Nodes1[ myLayerPositions.size() ] = NF;
415 Nodes2[ myLayerPositions.size() ] = NL;
416 // create 1D elements on edge
417 std::vector< const SMDS_MeshNode* > tmpNodes;
418 tmpNodes.resize(2*Nodes1.size()+1);
419 for(i=0; i<Nodes2.size(); i++)
420 tmpNodes[Nodes2.size()-i-1] = Nodes2[i];
421 tmpNodes[Nodes2.size()] = NC;
422 for(i=0; i<Nodes1.size(); i++)
423 tmpNodes[Nodes2.size()+1+i] = Nodes1[i];
424 for(i=1; i<tmpNodes.size(); i++) {
425 SMDS_MeshEdge* ME = myHelper->AddEdge( tmpNodes[i-1], tmpNodes[i] );
426 if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
430 // one curve must be a part of circle and other curves must be
432 Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(C1);
433 while( !tc.IsNull() ) {
434 C1 = tc->BasisCurve();
435 tc = Handle(Geom_TrimmedCurve)::DownCast(C1);
437 tc = Handle(Geom_TrimmedCurve)::DownCast(C2);
438 while( !tc.IsNull() ) {
439 C2 = tc->BasisCurve();
440 tc = Handle(Geom_TrimmedCurve)::DownCast(C2);
442 tc = Handle(Geom_TrimmedCurve)::DownCast(C3);
443 while( !tc.IsNull() ) {
444 C3 = tc->BasisCurve();
445 tc = Handle(Geom_TrimmedCurve)::DownCast(C3);
448 Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(C1);
449 Handle(Geom_Line) aLine1 = Handle(Geom_Line)::DownCast(C2);
450 Handle(Geom_Line) aLine2 = Handle(Geom_Line)::DownCast(C3);
456 if( aCirc.IsNull() ) {
457 aCirc = Handle(Geom_Circle)::DownCast(C2);
463 aLine1 = Handle(Geom_Line)::DownCast(C3);
464 aLine2 = Handle(Geom_Line)::DownCast(C1);
465 if( aCirc.IsNull() ) {
466 aCirc = Handle(Geom_Circle)::DownCast(C3);
472 aLine1 = Handle(Geom_Line)::DownCast(C1);
473 aLine2 = Handle(Geom_Line)::DownCast(C2);
476 if( aCirc.IsNull() ) {
478 return error(COMPERR_BAD_SHAPE);
480 if( aLine1.IsNull() || aLine2.IsNull() ) {
481 // other curve not line
482 return error(COMPERR_BAD_SHAPE);
484 SMESH_subMesh* sm1 = aMesh.GetSubMesh(LinEdge1);
485 SMESH_subMesh* sm2 = aMesh.GetSubMesh(LinEdge2);
487 SMESHDS_SubMesh* sdssm1 = sm1->GetSubMeshDS();
488 SMESHDS_SubMesh* sdssm2 = sm2->GetSubMeshDS();
489 if( sdssm1 && sdssm2 ) {
490 if( sm1->GetSubMeshDS()->NbNodes()>0 || sm2->GetSubMeshDS()->NbNodes()>0 ) {
491 SMESH_subMesh* sm = aMesh.GetSubMesh(F);
492 SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
493 smError.reset(new SMESH_ComputeError(COMPERR_ALGO_FAILED,
494 "Invalid set of hypothesises",this));
500 bool ok = _gen->Compute( aMesh, CircEdge, false, MeshDim_1D );
501 if( !ok ) return false;
502 std::map< double, const SMDS_MeshNode* > theNodes;
503 GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes);
506 std::map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin();
507 const SMDS_MeshNode* NF = (*itn).second;
508 CNodes.push_back( (*itn).second );
509 double fang = (*itn).first;
511 const SMDS_MeshNode* NL;
513 for(; itn != theNodes.end(); itn++ ) {
515 if( nbn == theNodes.size() )
517 CNodes.push_back( (*itn).second );
518 double ang = (*itn).first - fang;
519 if( ang>PI ) ang = ang - 2*PI;
520 if( ang<-PI ) ang = ang + 2*PI;
521 Angles.Append( ang );
523 P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() );
524 gp_Pnt P2( NL->X(), NL->Y(), NL->Z() );
525 P0 = aCirc->Location();
527 myLayerPositions.clear();
528 computeLayerPositions(P0,P1);
530 exp.Init( LinEdge1, TopAbs_VERTEX );
531 TopoDS_Vertex V1 = TopoDS::Vertex( exp.Current() );
533 TopoDS_Vertex V2 = TopoDS::Vertex( exp.Current() );
534 gp_Pnt PE1 = BRep_Tool::Pnt(V1);
535 gp_Pnt PE2 = BRep_Tool::Pnt(V2);
536 if( ( P1.Distance(PE1) > Precision::Confusion() ) &&
537 ( P1.Distance(PE2) > Precision::Confusion() ) ) {
538 TopoDS_Edge E = LinEdge1;
543 if( ( P1.Distance(PE1) > Precision::Confusion() ) &&
544 ( P2.Distance(PE1) > Precision::Confusion() ) ) {
548 int vertID = meshDS->ShapeToIndex(VC);
550 int edgeID = meshDS->ShapeToIndex(LinEdge1);
553 Handle(Geom_Curve) Crv = BRep_Tool::Curve(LinEdge1,fp,lp);
557 if( P1.Distance(Ptmp) > Precision::Confusion() )
559 // get UV points for edge
561 BRep_Tool::UVPoints( LinEdge1, TopoDS::Face(aShape), PF, PL );
564 V2d = gp_Vec2d(PF,PL);
568 V2d = gp_Vec2d(PL,PF);
571 NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z());
572 meshDS->SetNodeOnVertex(NC, vertID);
574 Nodes1.resize( myLayerPositions.size()+1 );
576 for(; i<myLayerPositions.size(); i++) {
577 gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
578 P0.Y() + aVec.Y()*myLayerPositions[i],
579 P0.Z() + aVec.Z()*myLayerPositions[i] );
581 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
585 param = fp + dp*(1-myLayerPositions[i]);
587 param = fp + dp*myLayerPositions[i];
588 meshDS->SetNodeOnEdge(node, edgeID, param);
589 // parameters on face
590 gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i],
591 PC.Y() + V2d.Y()*myLayerPositions[i] );
594 Nodes1[ myLayerPositions.size() ] = NF;
595 // create 1D elements on edge
596 SMDS_MeshEdge* ME = myHelper->AddEdge( NC, Nodes1[0] );
597 if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
598 for(i=1; i<Nodes1.size(); i++) {
599 SMDS_MeshEdge* ME = myHelper->AddEdge( Nodes1[i-1], Nodes1[i] );
600 if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
603 edgeID = meshDS->ShapeToIndex(LinEdge1);
604 aVec = gp_Vec(P0,P2);
606 Crv = BRep_Tool::Curve(LinEdge2,fp,lp);
609 if( P2.Distance(Ptmp) > Precision::Confusion() )
611 // get UV points for edge
612 BRep_Tool::UVPoints( LinEdge2, TopoDS::Face(aShape), PF, PL );
614 V2d = gp_Vec2d(PF,PL);
618 V2d = gp_Vec2d(PL,PF);
622 Nodes2.resize( myLayerPositions.size()+1 );
623 for(i=0; i<myLayerPositions.size(); i++) {
624 gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
625 P0.Y() + aVec.Y()*myLayerPositions[i],
626 P0.Z() + aVec.Z()*myLayerPositions[i] );
627 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
631 param = fp + dp*(1-myLayerPositions[i]);
633 param = fp + dp*myLayerPositions[i];
634 meshDS->SetNodeOnEdge(node, edgeID, param);
635 // parameters on face
636 gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i],
637 PC.Y() + V2d.Y()*myLayerPositions[i] );
640 Nodes2[ myLayerPositions.size() ] = NL;
641 // create 1D elements on edge
642 ME = myHelper->AddEdge( NC, Nodes2[0] );
643 if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
644 for(i=1; i<Nodes2.size(); i++) {
645 SMDS_MeshEdge* ME = myHelper->AddEdge( Nodes2[i-1], Nodes2[i] );
646 if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
650 // create nodes and mesh elements on face
651 // find axis of rotation
652 gp_Pnt P2 = gp_Pnt( CNodes[1]->X(), CNodes[1]->Y(), CNodes[1]->Z() );
655 gp_Vec Axis = Vec1.Crossed(Vec2);
658 //cout<<"Angles.Length() = "<<Angles.Length()<<" Points.Length() = "<<Points.Length()<<endl;
659 //cout<<"Nodes1.size() = "<<Nodes1.size()<<" Pnts2d1.Length() = "<<Pnts2d1.Length()<<endl;
660 for(; i<Angles.Length(); i++) {
661 std::vector< const SMDS_MeshNode* > tmpNodes;
662 tmpNodes.reserve(Nodes1.size());
664 gp_Ax1 theAxis(P0,gp_Dir(Axis));
665 aTrsf.SetRotation( theAxis, Angles.Value(i) );
667 aTrsf2d.SetRotation( PC, Angles.Value(i) );
670 for(; j<=Points.Length(); j++) {
672 Points.Value(j).Coord( cx, cy, cz );
673 aTrsf.Transforms( cx, cy, cz );
674 SMDS_MeshNode* node = myHelper->AddNode( cx, cy, cz );
675 // find parameters on face
676 Pnts2d1.Value(j).Coord( cx, cy );
677 aTrsf2d.Transforms( cx, cy );
679 meshDS->SetNodeOnFace( node, faceID, cx, cy );
680 tmpNodes[j-1] = node;
683 tmpNodes[Points.Length()] = CNodes[i];
685 for(j=0; j<Nodes1.size()-1; j++) {
686 SMDS_MeshFace* MF = myHelper->AddFace( tmpNodes[j], Nodes1[j],
687 Nodes1[j+1], tmpNodes[j+1] );
688 if(MF) meshDS->SetMeshElementOnShape(MF, faceID);
691 SMDS_MeshFace* MF = myHelper->AddFace( NC, Nodes1[0], tmpNodes[0] );
692 if(MF) meshDS->SetMeshElementOnShape(MF, faceID);
693 for(j=0; j<Nodes1.size(); j++) {
694 Nodes1[j] = tmpNodes[j];
699 for(i=0; i<Nodes1.size()-1; i++) {
700 SMDS_MeshFace* MF = myHelper->AddFace( Nodes2[i], Nodes1[i],
701 Nodes1[i+1], Nodes2[i+1] );
702 if(MF) meshDS->SetMeshElementOnShape(MF, faceID);
705 SMDS_MeshFace* MF = myHelper->AddFace( NC, Nodes1[0], Nodes2[0] );
706 if(MF) meshDS->SetMeshElementOnShape(MF, faceID);
709 // to delete helper at exit from Compute()
710 std::auto_ptr<SMESH_MesherHelper> helperDeleter( myHelper );
716 //================================================================================
717 //================================================================================
719 * \brief Class computing layers distribution using data of
720 * StdMeshers_LayerDistribution hypothesis
722 //================================================================================
723 //================================================================================
725 class TNodeDistributor: public StdMeshers_Regular_1D
727 list <const SMESHDS_Hypothesis *> myUsedHyps;
729 // -----------------------------------------------------------------------------
730 static TNodeDistributor* GetDistributor(SMESH_Mesh& aMesh)
732 const int myID = -1000;
733 map < int, SMESH_1D_Algo * > & algoMap = aMesh.GetGen()->_map1D_Algo;
734 map < int, SMESH_1D_Algo * >::iterator id_algo = algoMap.find( myID );
735 if ( id_algo == algoMap.end() )
736 return new TNodeDistributor( myID, 0, aMesh.GetGen() );
737 return static_cast< TNodeDistributor* >( id_algo->second );
739 // -----------------------------------------------------------------------------
740 bool Compute( vector< double > & positions,
744 const StdMeshers_LayerDistribution* hyp)
746 double len = pIn.Distance( pOut );
747 if ( len <= DBL_MIN ) return error("Too close points of inner and outer shells");
749 if ( !hyp || !hyp->GetLayerDistribution() )
750 return error( "Invalid LayerDistribution hypothesis");
752 myUsedHyps.push_back( hyp->GetLayerDistribution() );
754 TopoDS_Edge edge = BRepBuilderAPI_MakeEdge( pIn, pOut );
755 SMESH_Hypothesis::Hypothesis_Status aStatus;
756 if ( !StdMeshers_Regular_1D::CheckHypothesis( aMesh, edge, aStatus ))
757 return error( "StdMeshers_Regular_1D::CheckHypothesis() failed "
758 "with LayerDistribution hypothesis");
760 BRepAdaptor_Curve C3D(edge);
761 double f = C3D.FirstParameter(), l = C3D.LastParameter();
762 list< double > params;
763 if ( !StdMeshers_Regular_1D::computeInternalParameters( aMesh, C3D, len, f, l, params, false ))
764 return error("StdMeshers_Regular_1D failed to compute layers distribution");
767 positions.reserve( params.size() );
768 for (list<double>::iterator itU = params.begin(); itU != params.end(); itU++)
769 positions.push_back( *itU / len );
773 // -----------------------------------------------------------------------------
774 TNodeDistributor( int hypId, int studyId, SMESH_Gen* gen)
775 : StdMeshers_Regular_1D( hypId, studyId, gen)
778 // -----------------------------------------------------------------------------
779 virtual const list <const SMESHDS_Hypothesis *> &
780 GetUsedHypothesis(SMESH_Mesh &, const TopoDS_Shape &, const bool)
784 // -----------------------------------------------------------------------------
787 //================================================================================
789 * \brief Compute positions of nodes between the internal and the external surfaces
790 * \retval bool - is a success
792 //================================================================================
794 bool StdMeshers_RadialQuadrangle_1D2D::computeLayerPositions(const gp_Pnt& pIn,
799 int nbSegments = myNbLayerHypo->GetNumberOfLayers();
800 myLayerPositions.resize( nbSegments - 1 );
801 for ( int z = 1; z < nbSegments; ++z )
802 myLayerPositions[ z - 1 ] = double( z )/ double( nbSegments );
805 if ( myDistributionHypo ) {
806 SMESH_Mesh * mesh = myHelper->GetMesh();
807 if ( !TNodeDistributor::GetDistributor(*mesh)->Compute( myLayerPositions, pIn, pOut,
808 *mesh, myDistributionHypo ))
810 error( TNodeDistributor::GetDistributor(*mesh)->GetComputeError() );
814 RETURN_BAD_RESULT("Bad hypothesis");
818 //=======================================================================
819 //function : Evaluate
821 //=======================================================================
823 bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh& aMesh,
824 const TopoDS_Shape& aShape,
825 MapShapeNbElems& aResMap)
827 if( aShape.ShapeType() != TopAbs_FACE ) {
830 SMESH_subMesh * smf = aMesh.GetSubMesh(aShape);
831 MapShapeNbElemsItr anIt = aResMap.find(smf);
832 if( anIt != aResMap.end() ) {
836 myLayerPositions.clear();
839 computeLayerPositions(P0,P1);
841 TopoDS_Edge E1,E2,E3;
842 Handle(Geom_Curve) C1,C2,C3;
843 double f1,l1,f2,l2,f3,l3;
846 for ( exp.Init( aShape, TopAbs_EDGE ); exp.More(); exp.Next() ) {
848 TopoDS_Edge E = TopoDS::Edge( exp.Current() );
851 C1 = BRep_Tool::Curve(E,f1,l1);
855 C2 = BRep_Tool::Curve(E,f2,l2);
859 C3 = BRep_Tool::Curve(E,f3,l3);
863 TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
864 int nb0d=0, nb2d_tria=0, nb2d_quad=0;
865 bool isQuadratic = false;
867 // C1 must be a circle
868 Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(C1);
869 if( !aCirc.IsNull() ) {
870 bool ok = _gen->Evaluate( aMesh, CircEdge, aResMap );
872 SMESH_subMesh * sm = aMesh.GetSubMesh(CircEdge);
873 MapShapeNbElemsItr anIt = aResMap.find(sm);
874 std::vector<int> aVec = (*anIt).second;
875 isQuadratic = aVec[SMDSEntity_Quad_Edge]>aVec[SMDSEntity_Edge];
878 nb0d = (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
879 // radial medium nodes
880 nb0d += (aVec[SMDSEntity_Node]+1) * (myLayerPositions.size()+1);
881 // other medium nodes
882 nb0d += (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
885 nb0d = (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
887 nb2d_tria = aVec[SMDSEntity_Node] + 1;
893 // one curve must be a half of circle and other curve must be
895 Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(C1);
896 while( !tc.IsNull() ) {
897 C1 = tc->BasisCurve();
898 tc = Handle(Geom_TrimmedCurve)::DownCast(C1);
900 tc = Handle(Geom_TrimmedCurve)::DownCast(C2);
901 while( !tc.IsNull() ) {
902 C2 = tc->BasisCurve();
903 tc = Handle(Geom_TrimmedCurve)::DownCast(C2);
905 Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(C1);
906 Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast(C2);
911 if( aCirc.IsNull() ) {
912 aCirc = Handle(Geom_Circle)::DownCast(C2);
917 aLine = Handle(Geom_Line)::DownCast(C3);
919 bool ok = !aCirc.IsNull() && !aLine.IsNull();
920 if( fabs(fabs(lp-fp)-PI) > Precision::Confusion() ) {
921 // not half of circle
924 SMESH_subMesh* sm1 = aMesh.GetSubMesh(LinEdge1);
925 MapShapeNbElemsItr anIt = aResMap.find(sm1);
926 if( anIt!=aResMap.end() ) {
930 ok = _gen->Evaluate( aMesh, CircEdge, aResMap );
933 SMESH_subMesh * sm = aMesh.GetSubMesh(CircEdge);
934 MapShapeNbElemsItr anIt = aResMap.find(sm);
935 std::vector<int> aVec = (*anIt).second;
936 isQuadratic = aVec[SMDSEntity_Quad_Edge]>aVec[SMDSEntity_Edge];
939 nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
940 // radial medium nodes
941 nb0d += aVec[SMDSEntity_Node] * (myLayerPositions.size()+1);
942 // other medium nodes
943 nb0d += (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
946 nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
948 nb2d_tria = aVec[SMDSEntity_Node] + 1;
949 nb2d_quad = nb2d_tria * myLayerPositions.size();
950 // add evaluation for edges
951 std::vector<int> aResVec(SMDSEntity_Last);
952 for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
954 aResVec[SMDSEntity_Node] = 4*myLayerPositions.size() + 3;
955 aResVec[SMDSEntity_Quad_Edge] = 2*myLayerPositions.size() + 2;
958 aResVec[SMDSEntity_Node] = 2*myLayerPositions.size() + 1;
959 aResVec[SMDSEntity_Edge] = 2*myLayerPositions.size() + 2;
961 sm = aMesh.GetSubMesh(LinEdge1);
962 aResMap.insert(std::make_pair(sm,aResVec));
966 // one curve must be a part of circle and other curves must be
968 Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(C1);
969 while( !tc.IsNull() ) {
970 C1 = tc->BasisCurve();
971 tc = Handle(Geom_TrimmedCurve)::DownCast(C1);
973 tc = Handle(Geom_TrimmedCurve)::DownCast(C2);
974 while( !tc.IsNull() ) {
975 C2 = tc->BasisCurve();
976 tc = Handle(Geom_TrimmedCurve)::DownCast(C2);
978 tc = Handle(Geom_TrimmedCurve)::DownCast(C3);
979 while( !tc.IsNull() ) {
980 C3 = tc->BasisCurve();
981 tc = Handle(Geom_TrimmedCurve)::DownCast(C3);
983 Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(C1);
984 Handle(Geom_Line) aLine1 = Handle(Geom_Line)::DownCast(C2);
985 Handle(Geom_Line) aLine2 = Handle(Geom_Line)::DownCast(C3);
991 if( aCirc.IsNull() ) {
992 aCirc = Handle(Geom_Circle)::DownCast(C2);
998 aLine1 = Handle(Geom_Line)::DownCast(C3);
999 aLine2 = Handle(Geom_Line)::DownCast(C1);
1000 if( aCirc.IsNull() ) {
1001 aCirc = Handle(Geom_Circle)::DownCast(C3);
1007 aLine1 = Handle(Geom_Line)::DownCast(C1);
1008 aLine2 = Handle(Geom_Line)::DownCast(C2);
1011 bool ok = !aCirc.IsNull() && !aLine1.IsNull() && !aLine1.IsNull();
1012 SMESH_subMesh* sm = aMesh.GetSubMesh(LinEdge1);
1013 MapShapeNbElemsItr anIt = aResMap.find(sm);
1014 if( anIt!=aResMap.end() ) {
1017 sm = aMesh.GetSubMesh(LinEdge2);
1018 anIt = aResMap.find(sm);
1019 if( anIt!=aResMap.end() ) {
1023 ok = _gen->Evaluate( aMesh, CircEdge, aResMap );
1026 SMESH_subMesh * sm = aMesh.GetSubMesh(CircEdge);
1027 MapShapeNbElemsItr anIt = aResMap.find(sm);
1028 std::vector<int> aVec = (*anIt).second;
1029 isQuadratic = aVec[SMDSEntity_Quad_Edge]>aVec[SMDSEntity_Edge];
1032 nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
1033 // radial medium nodes
1034 nb0d += aVec[SMDSEntity_Node] * (myLayerPositions.size()+1);
1035 // other medium nodes
1036 nb0d += (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
1039 nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
1041 nb2d_tria = aVec[SMDSEntity_Node] + 1;
1042 nb2d_quad = nb2d_tria * myLayerPositions.size();
1043 // add evaluation for edges
1044 std::vector<int> aResVec(SMDSEntity_Last);
1045 for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
1047 aResVec[SMDSEntity_Node] = 2*myLayerPositions.size() + 1;
1048 aResVec[SMDSEntity_Quad_Edge] = myLayerPositions.size() + 1;
1051 aResVec[SMDSEntity_Node] = myLayerPositions.size();
1052 aResVec[SMDSEntity_Edge] = myLayerPositions.size() + 1;
1054 sm = aMesh.GetSubMesh(LinEdge1);
1055 aResMap.insert(std::make_pair(sm,aResVec));
1056 sm = aMesh.GetSubMesh(LinEdge2);
1057 aResMap.insert(std::make_pair(sm,aResVec));
1061 std::vector<int> aResVec(SMDSEntity_Last);
1062 for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0;
1063 SMESH_subMesh * sm = aMesh.GetSubMesh(aShape);
1065 //cout<<"nb0d = "<<nb0d<<" nb2d_tria = "<<nb2d_tria<<" nb2d_quad = "<<nb2d_quad<<endl;
1069 aResVec[SMDSEntity_Quad_Triangle] = nb2d_tria;
1070 aResVec[SMDSEntity_Quad_Quadrangle] = nb2d_quad;
1073 aResVec[SMDSEntity_Triangle] = nb2d_tria;
1074 aResVec[SMDSEntity_Quadrangle] = nb2d_quad;
1076 aResMap.insert(std::make_pair(sm,aResVec));
1081 aResMap.insert(std::make_pair(sm,aResVec));
1082 SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
1083 smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,
1084 "Submesh can not be evaluated",this));