00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "StdMeshers_Projection_1D.hxx"
00030
00031 #include "StdMeshers_ProjectionSource1D.hxx"
00032 #include "StdMeshers_ProjectionUtils.hxx"
00033
00034 #include "SMDS_MeshNode.hxx"
00035 #include "SMDS_MeshElement.hxx"
00036 #include "SMESHDS_Mesh.hxx"
00037 #include "SMESHDS_SubMesh.hxx"
00038 #include "SMESH_Mesh.hxx"
00039 #include "SMESH_MesherHelper.hxx"
00040 #include "SMESH_subMesh.hxx"
00041 #include "SMESH_subMeshEventListener.hxx"
00042 #include "SMESH_Gen.hxx"
00043 #include "SMESH_Comment.hxx"
00044
00045 #include <BRepAdaptor_Curve.hxx>
00046 #include <BRep_Tool.hxx>
00047 #include <GCPnts_AbscissaPoint.hxx>
00048 #include <TopExp.hxx>
00049 #include <TopoDS.hxx>
00050 #include <gp_Pnt.hxx>
00051 #include <TopTools_ListIteratorOfListOfShape.hxx>
00052
00053 #include "utilities.h"
00054
00055
00056 using namespace std;
00057
00058 #define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; }
00059
00060 typedef StdMeshers_ProjectionUtils TAssocTool;
00061
00062
00063
00064
00065
00066
00067 StdMeshers_Projection_1D::StdMeshers_Projection_1D(int hypId, int studyId, SMESH_Gen* gen)
00068 :SMESH_1D_Algo(hypId, studyId, gen)
00069 {
00070 _name = "Projection_1D";
00071 _shapeType = (1 << TopAbs_EDGE);
00072
00073 _compatibleHypothesis.push_back("ProjectionSource1D");
00074 _sourceHypo = 0;
00075 }
00076
00077
00081
00082
00083 StdMeshers_Projection_1D::~StdMeshers_Projection_1D()
00084 {}
00085
00086
00087
00088
00089
00090
00091 bool StdMeshers_Projection_1D::CheckHypothesis(SMESH_Mesh& aMesh,
00092 const TopoDS_Shape& aShape,
00093 SMESH_Hypothesis::Hypothesis_Status& aStatus)
00094 {
00095 _sourceHypo = 0;
00096 list <const SMESHDS_Hypothesis * >::const_iterator itl;
00097
00098 const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
00099 if ( hyps.size() == 0 )
00100 {
00101 aStatus = HYP_MISSING;
00102 return false;
00103 }
00104
00105 if ( hyps.size() > 1 )
00106 {
00107 aStatus = HYP_ALREADY_EXIST;
00108 return false;
00109 }
00110
00111 const SMESHDS_Hypothesis *theHyp = hyps.front();
00112
00113 string hypName = theHyp->GetName();
00114
00115 aStatus = HYP_OK;
00116
00117 if (hypName == "ProjectionSource1D")
00118 {
00119 _sourceHypo = static_cast<const StdMeshers_ProjectionSource1D *>(theHyp);
00120
00121
00122
00123 SMESH_Mesh* srcMesh = _sourceHypo->GetSourceMesh();
00124 SMESH_Mesh* tgtMesh = & aMesh;
00125 if ( !srcMesh )
00126 srcMesh = tgtMesh;
00127
00128
00129 if ( _sourceHypo->HasVertexAssociation() )
00130 {
00131
00132 if ( !SMESH_MesherHelper::IsSubShape( _sourceHypo->GetSourceVertex(), srcMesh ) ||
00133 !SMESH_MesherHelper::IsSubShape( _sourceHypo->GetTargetVertex(), tgtMesh ) ||
00134 !SMESH_MesherHelper::IsSubShape( _sourceHypo->GetSourceVertex(),
00135 _sourceHypo->GetSourceEdge() ))
00136 {
00137 aStatus = HYP_BAD_PARAMETER;
00138 SCRUTE((SMESH_MesherHelper::IsSubShape( _sourceHypo->GetSourceVertex(), srcMesh )));
00139 SCRUTE((SMESH_MesherHelper::IsSubShape( _sourceHypo->GetTargetVertex(), tgtMesh )));
00140 SCRUTE((SMESH_MesherHelper::IsSubShape( _sourceHypo->GetSourceVertex(),
00141 _sourceHypo->GetSourceEdge() )));
00142 }
00143
00144 else
00145 {
00146 bool isSub = SMESH_MesherHelper::IsSubShape( _sourceHypo->GetTargetVertex(), aShape );
00147 if ( !_sourceHypo->IsCompoundSource() ) {
00148 if ( !isSub ) {
00149 aStatus = HYP_BAD_PARAMETER;
00150 SCRUTE((SMESH_MesherHelper::IsSubShape( _sourceHypo->GetTargetVertex(), aShape)));
00151 }
00152 }
00153 else if ( isSub ) {
00154
00155
00156 TopoDS_Shape sharingEdge;
00157 TopTools_ListIteratorOfListOfShape ancestIt
00158 ( aMesh.GetAncestors( _sourceHypo->GetSourceVertex() ));
00159 for ( ; ancestIt.More(); ancestIt.Next() )
00160 {
00161 const TopoDS_Shape& ancestor = ancestIt.Value();
00162 if ( ancestor.ShapeType() == TopAbs_EDGE &&
00163 SMESH_MesherHelper::IsSubShape( ancestor, _sourceHypo->GetSourceEdge() ))
00164 {
00165 if ( sharingEdge.IsNull() || ancestor.IsSame( sharingEdge ))
00166 sharingEdge = ancestor;
00167 else {
00168
00169 aStatus = HYP_BAD_PARAMETER;
00170 MESSAGE("Source vertex is shared by several edges of a group");
00171 break;
00172 }
00173 }
00174 }
00175 }
00176 }
00177 }
00178
00179 if ( !SMESH_MesherHelper::IsSubShape( _sourceHypo->GetSourceEdge(), srcMesh ) ||
00180 ( srcMesh == tgtMesh && aShape == _sourceHypo->GetSourceEdge() ))
00181 {
00182 aStatus = HYP_BAD_PARAMETER;
00183 SCRUTE((SMESH_MesherHelper::IsSubShape( _sourceHypo->GetSourceEdge(), srcMesh )));
00184 SCRUTE((srcMesh == tgtMesh));
00185 SCRUTE(( aShape == _sourceHypo->GetSourceEdge() ));
00186 }
00187 }
00188 else
00189 {
00190 aStatus = HYP_INCOMPATIBLE;
00191 }
00192 return ( aStatus == HYP_OK );
00193 }
00194
00195
00196
00197
00198
00199
00200 bool StdMeshers_Projection_1D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape)
00201 {
00202 if ( !_sourceHypo )
00203 return false;
00204
00205 SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh();
00206 SMESH_Mesh * tgtMesh = & theMesh;
00207 if ( !srcMesh )
00208 srcMesh = tgtMesh;
00209
00210 SMESHDS_Mesh * meshDS = theMesh.GetMeshDS();
00211
00212
00213
00214
00215
00216 TopoDS_Edge srcEdge, tgtEdge = TopoDS::Edge( theShape.Oriented(TopAbs_FORWARD));
00217 TopoDS_Shape srcShape = _sourceHypo->GetSourceEdge().Oriented(TopAbs_FORWARD);
00218
00219 TAssocTool::TShapeShapeMap shape2ShapeMap;
00220 TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap, tgtEdge );
00221 if ( !TAssocTool::FindSubShapeAssociation( tgtEdge, tgtMesh, srcShape, srcMesh,
00222 shape2ShapeMap) ||
00223 !shape2ShapeMap.IsBound( tgtEdge ))
00224 return error("Vertices association failed" );
00225
00226 srcEdge = TopoDS::Edge( shape2ShapeMap( tgtEdge ).Oriented(TopAbs_FORWARD));
00227
00228
00229
00230 TopoDS_Vertex tgtV[2], srcV[2];
00231 TopExp::Vertices( tgtEdge, tgtV[0], tgtV[1] );
00232 TopExp::Vertices( srcEdge, srcV[0], srcV[1] );
00233
00234
00235
00236
00237
00238 SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( srcEdge );
00239
00240
00241 if ( tgtMesh == srcMesh ) {
00242 if ( !TAssocTool::MakeComputed( srcSubMesh ))
00243 return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
00244 }
00245 else {
00246 if ( !srcSubMesh->IsMeshComputed() )
00247 return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
00248 }
00249
00250
00251
00252
00253 double srcLength = EdgeLength( srcEdge );
00254 double tgtLength = EdgeLength( tgtEdge );
00255
00256 vector< double > params;
00257 if ( !SMESH_Algo::GetNodeParamOnEdge( srcMesh->GetMeshDS(), srcEdge, params ))
00258 return error(COMPERR_BAD_INPUT_MESH,"Bad node parameters on the source edge");
00259
00260 int i, nbNodes = params.size();
00261
00262 vector< double > lengths( nbNodes - 1 );
00263 if ( srcLength > 0 )
00264 {
00265 BRepAdaptor_Curve curveAdaptor( srcEdge );
00266 for ( i = 1; i < nbNodes; ++i )
00267 lengths[ i-1 ] = GCPnts_AbscissaPoint::Length( curveAdaptor, params[i-1], params[i]);
00268 }
00269 else
00270 {
00271 for ( i = 1; i < nbNodes; ++i )
00272 lengths[ i-1 ] = params[i] - params[i-1];
00273 srcLength = params.back() - params[0];
00274 }
00275
00276 bool reverse = ( srcV[0].IsSame( shape2ShapeMap( tgtV[1] )));
00277 if ( tgtV[0].IsSame( tgtV[1] ))
00278 reverse = ( shape2ShapeMap( tgtEdge ).Orientation() == TopAbs_REVERSED );
00279 if ( reverse )
00280 std::reverse( lengths.begin(), lengths.end() );
00281
00282
00283
00284
00285
00286
00287 vector< const SMDS_MeshNode* > nodes ( nbNodes );
00288
00289
00290 nodes.front() = VertexNode( tgtV[0], meshDS );
00291 nodes.back() = VertexNode( tgtV[1], meshDS );
00292 if ( !nodes.front() || !nodes.back() )
00293 return error(COMPERR_BAD_INPUT_MESH,"No node on vertex");
00294
00295
00296
00297
00298 vector< double > tgtParams( nbNodes );
00299
00300 BRep_Tool::Range( tgtEdge, tgtParams.front(), tgtParams.back() );
00301 if ( tgtLength <= 0 )
00302 tgtLength = tgtParams.back() - tgtParams.front();
00303 double dl = tgtLength / srcLength;
00304
00305 if ( tgtLength > 0 )
00306 {
00307 BRepAdaptor_Curve curveAdaptor( tgtEdge );
00308
00309
00310 for ( i = 1; i < nbNodes - 1; ++i )
00311 {
00312
00313
00314 GCPnts_AbscissaPoint Discret( curveAdaptor, dl * lengths[ i-1 ], tgtParams[ i-1 ] );
00315 if ( !Discret.IsDone() )
00316 return error("GCPnts_AbscissaPoint failed");
00317 tgtParams[ i ] = Discret.Parameter();
00318 }
00319
00320 for ( i = 1; i < nbNodes - 1; ++i )
00321 {
00322 gp_Pnt P = curveAdaptor.Value( tgtParams[ i ]);
00323 SMDS_MeshNode* node = meshDS->AddNode(P.X(), P.Y(), P.Z());
00324 meshDS->SetNodeOnEdge( node, tgtEdge, tgtParams[ i ]);
00325 nodes[ i ] = node;
00326 }
00327 }
00328 else
00329 {
00330
00331 gp_Pnt P = BRep_Tool::Pnt( tgtV[0] );
00332
00333 for ( i = 1; i < nbNodes - 1; ++i )
00334 {
00335 SMDS_MeshNode* node = meshDS->AddNode(P.X(), P.Y(), P.Z());
00336 tgtParams[ i ] = tgtParams[ i-1 ] + dl * lengths[ i-1 ];
00337 meshDS->SetNodeOnEdge( node, tgtEdge, tgtParams[ i ]);
00338 nodes[ i ] = node;
00339 }
00340 }
00341
00342
00343
00344
00345 bool quadratic = false;
00346 SMDS_ElemIteratorPtr elemIt = srcSubMesh->GetSubMeshDS()->GetElements();
00347 if ( elemIt->more() )
00348 quadratic = elemIt->next()->IsQuadratic();
00349 else {
00350 SMDS_NodeIteratorPtr nodeIt = srcSubMesh->GetSubMeshDS()->GetNodes();
00351 while ( nodeIt->more() && !quadratic )
00352 quadratic = SMESH_MesherHelper::IsMedium( nodeIt->next() );
00353 }
00354
00355 if ( quadratic && ( nbNodes < 3 || ( nbNodes % 2 != 1 )))
00356 return error(COMPERR_BAD_INPUT_MESH,
00357 SMESH_Comment("Wrong number of nodes to make quadratic mesh: ")<<nbNodes);
00358
00359
00360
00361
00362 SMDS_MeshElement* edge = 0;
00363 int di = quadratic ? 2 : 1;
00364 for ( i = di; i < nbNodes; i += di)
00365 {
00366 if ( quadratic )
00367 edge = meshDS->AddEdge( nodes[i-2], nodes[i], nodes[i-1] );
00368 else
00369 edge = meshDS->AddEdge( nodes[i-1], nodes[i] );
00370 meshDS->SetMeshElementOnShape(edge, tgtEdge );
00371 }
00372
00373 return true;
00374 }
00375
00376
00377
00378
00379
00380
00381
00382 bool StdMeshers_Projection_1D::Evaluate(SMESH_Mesh& theMesh,
00383 const TopoDS_Shape& theShape,
00384 MapShapeNbElems& aResMap)
00385 {
00386 if ( !_sourceHypo )
00387 return false;
00388
00389 SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh();
00390 SMESH_Mesh * tgtMesh = & theMesh;
00391 if ( !srcMesh )
00392 srcMesh = tgtMesh;
00393
00394
00395
00396
00397
00398
00399
00400 TopoDS_Edge srcEdge, tgtEdge = TopoDS::Edge( theShape.Oriented(TopAbs_FORWARD));
00401 TopoDS_Shape srcShape = _sourceHypo->GetSourceEdge().Oriented(TopAbs_FORWARD);
00402
00403 TAssocTool::TShapeShapeMap shape2ShapeMap;
00404 TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap, tgtEdge );
00405 if ( !TAssocTool::FindSubShapeAssociation( tgtEdge, tgtMesh, srcShape, srcMesh,
00406 shape2ShapeMap) ||
00407 !shape2ShapeMap.IsBound( tgtEdge ))
00408 return error("Vertices association failed" );
00409
00410 srcEdge = TopoDS::Edge( shape2ShapeMap( tgtEdge ).Oriented(TopAbs_FORWARD));
00411
00412
00413
00414 TopoDS_Vertex tgtV[2], srcV[2];
00415 TopExp::Vertices( tgtEdge, tgtV[0], tgtV[1] );
00416 TopExp::Vertices( srcEdge, srcV[0], srcV[1] );
00417
00418
00419
00420
00421
00422 SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( srcEdge );
00423
00424
00425 if ( tgtMesh == srcMesh ) {
00426 if ( !TAssocTool::MakeComputed( srcSubMesh ))
00427 return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
00428 }
00429 else {
00430 if ( !srcSubMesh->IsMeshComputed() )
00431 return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
00432 }
00433
00434
00435
00436
00437
00438
00439
00440 vector< double > params;
00441 if ( !SMESH_Algo::GetNodeParamOnEdge( srcMesh->GetMeshDS(), srcEdge, params ))
00442 return error(COMPERR_BAD_INPUT_MESH,"Bad node parameters on the source edge");
00443
00444 int nbNodes = params.size();
00445
00446 std::vector<int> aVec(SMDSEntity_Last);
00447 for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i] = 0;
00448
00449 aVec[SMDSEntity_Node] = nbNodes;
00450
00451 bool quadratic = false;
00452 SMDS_ElemIteratorPtr elemIt = srcSubMesh->GetSubMeshDS()->GetElements();
00453 if ( elemIt->more() )
00454 quadratic = elemIt->next()->IsQuadratic();
00455 if(quadratic)
00456 aVec[SMDSEntity_Quad_Edge] = (nbNodes-1)/2;
00457 else
00458 aVec[SMDSEntity_Edge] = nbNodes - 1;
00459
00460 SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
00461 aResMap.insert(std::make_pair(sm,aVec));
00462
00463 return true;
00464 }
00465
00466
00467
00477
00478
00479 void StdMeshers_Projection_1D::SetEventListener(SMESH_subMesh* subMesh)
00480 {
00481 TAssocTool::SetEventListener( subMesh,
00482 _sourceHypo->GetSourceEdge(),
00483 _sourceHypo->GetSourceMesh() );
00484 }