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_Regular_1D.hxx"
00030 #include "StdMeshers_Distribution.hxx"
00031
00032 #include "StdMeshers_Arithmetic1D.hxx"
00033 #include "StdMeshers_AutomaticLength.hxx"
00034 #include "StdMeshers_Deflection1D.hxx"
00035 #include "StdMeshers_LocalLength.hxx"
00036 #include "StdMeshers_MaxLength.hxx"
00037 #include "StdMeshers_NumberOfSegments.hxx"
00038 #include "StdMeshers_Propagation.hxx"
00039 #include "StdMeshers_SegmentLengthAroundVertex.hxx"
00040 #include "StdMeshers_StartEndLength.hxx"
00041
00042 #include "SMESH_Gen.hxx"
00043 #include "SMESH_Mesh.hxx"
00044 #include "SMESH_HypoFilter.hxx"
00045 #include "SMESH_subMesh.hxx"
00046 #include "SMESH_subMeshEventListener.hxx"
00047 #include "SMESH_Comment.hxx"
00048
00049 #include "SMDS_MeshElement.hxx"
00050 #include "SMDS_MeshNode.hxx"
00051
00052 #include "Utils_SALOME_Exception.hxx"
00053 #include "utilities.h"
00054
00055 #include <BRepAdaptor_Curve.hxx>
00056 #include <BRep_Tool.hxx>
00057 #include <GCPnts_AbscissaPoint.hxx>
00058 #include <GCPnts_UniformAbscissa.hxx>
00059 #include <GCPnts_UniformDeflection.hxx>
00060 #include <Precision.hxx>
00061 #include <TopExp.hxx>
00062 #include <TopExp_Explorer.hxx>
00063 #include <TopoDS.hxx>
00064 #include <TopoDS_Edge.hxx>
00065
00066 #include <string>
00067 #include <limits>
00068
00069 using namespace std;
00070
00071
00075
00076
00077 StdMeshers_Regular_1D::StdMeshers_Regular_1D(int hypId, int studyId,
00078 SMESH_Gen * gen):SMESH_1D_Algo(hypId, studyId, gen)
00079 {
00080 MESSAGE("StdMeshers_Regular_1D::StdMeshers_Regular_1D");
00081 _name = "Regular_1D";
00082 _shapeType = (1 << TopAbs_EDGE);
00083 _fpHyp = 0;
00084
00085 _compatibleHypothesis.push_back("LocalLength");
00086 _compatibleHypothesis.push_back("MaxLength");
00087 _compatibleHypothesis.push_back("NumberOfSegments");
00088 _compatibleHypothesis.push_back("StartEndLength");
00089 _compatibleHypothesis.push_back("Deflection1D");
00090 _compatibleHypothesis.push_back("Arithmetic1D");
00091 _compatibleHypothesis.push_back("FixedPoints1D");
00092 _compatibleHypothesis.push_back("AutomaticLength");
00093
00094 _compatibleHypothesis.push_back("QuadraticMesh");
00095 _compatibleHypothesis.push_back("Propagation");
00096 }
00097
00098
00102
00103
00104 StdMeshers_Regular_1D::~StdMeshers_Regular_1D()
00105 {
00106 }
00107
00108
00112
00113
00114 bool StdMeshers_Regular_1D::CheckHypothesis
00115 (SMESH_Mesh& aMesh,
00116 const TopoDS_Shape& aShape,
00117 SMESH_Hypothesis::Hypothesis_Status& aStatus)
00118 {
00119 _hypType = NONE;
00120 _quadraticMesh = false;
00121
00122 const list <const SMESHDS_Hypothesis * > & hyps =
00123 GetUsedHypothesis(aMesh, aShape, false);
00124
00125
00126 const SMESHDS_Hypothesis *theHyp = 0;
00127 list <const SMESHDS_Hypothesis * >::const_iterator h = hyps.begin();
00128 for ( ; h != hyps.end(); ++h ) {
00129 if ( static_cast<const SMESH_Hypothesis*>(*h)->IsAuxiliary() ) {
00130 if ( strcmp( "QuadraticMesh", (*h)->GetName() ) == 0 )
00131 _quadraticMesh = true;
00132 }
00133 else {
00134 if ( !theHyp )
00135 theHyp = *h;
00136 }
00137 }
00138
00139 if ( !theHyp )
00140 {
00141 aStatus = SMESH_Hypothesis::HYP_MISSING;
00142 return false;
00143 }
00144
00145 string hypName = theHyp->GetName();
00146
00147 if (hypName == "LocalLength")
00148 {
00149 const StdMeshers_LocalLength * hyp =
00150 dynamic_cast <const StdMeshers_LocalLength * >(theHyp);
00151 ASSERT(hyp);
00152 _value[ BEG_LENGTH_IND ] = hyp->GetLength();
00153 _value[ PRECISION_IND ] = hyp->GetPrecision();
00154 ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
00155 _hypType = LOCAL_LENGTH;
00156 aStatus = SMESH_Hypothesis::HYP_OK;
00157 }
00158
00159 else if (hypName == "MaxLength")
00160 {
00161 const StdMeshers_MaxLength * hyp =
00162 dynamic_cast <const StdMeshers_MaxLength * >(theHyp);
00163 ASSERT(hyp);
00164 _value[ BEG_LENGTH_IND ] = hyp->GetLength();
00165 if ( hyp->GetUsePreestimatedLength() ) {
00166 if ( int nbSeg = aMesh.GetGen()->GetBoundaryBoxSegmentation() )
00167 _value[ BEG_LENGTH_IND ] = aMesh.GetShapeDiagonalSize() / nbSeg;
00168 }
00169 ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
00170 _hypType = MAX_LENGTH;
00171 aStatus = SMESH_Hypothesis::HYP_OK;
00172 }
00173
00174 else if (hypName == "NumberOfSegments")
00175 {
00176 const StdMeshers_NumberOfSegments * hyp =
00177 dynamic_cast <const StdMeshers_NumberOfSegments * >(theHyp);
00178 ASSERT(hyp);
00179 _ivalue[ NB_SEGMENTS_IND ] = hyp->GetNumberOfSegments();
00180 ASSERT( _ivalue[ NB_SEGMENTS_IND ] > 0 );
00181 _ivalue[ DISTR_TYPE_IND ] = (int) hyp->GetDistrType();
00182 switch (_ivalue[ DISTR_TYPE_IND ])
00183 {
00184 case StdMeshers_NumberOfSegments::DT_Scale:
00185 _value[ SCALE_FACTOR_IND ] = hyp->GetScaleFactor();
00186 _revEdgesIDs = hyp->GetReversedEdges();
00187 break;
00188 case StdMeshers_NumberOfSegments::DT_TabFunc:
00189 _vvalue[ TAB_FUNC_IND ] = hyp->GetTableFunction();
00190 _revEdgesIDs = hyp->GetReversedEdges();
00191 break;
00192 case StdMeshers_NumberOfSegments::DT_ExprFunc:
00193 _svalue[ EXPR_FUNC_IND ] = hyp->GetExpressionFunction();
00194 _revEdgesIDs = hyp->GetReversedEdges();
00195 break;
00196 case StdMeshers_NumberOfSegments::DT_Regular:
00197 break;
00198 default:
00199 ASSERT(0);
00200 break;
00201 }
00202 if (_ivalue[ DISTR_TYPE_IND ] == StdMeshers_NumberOfSegments::DT_TabFunc ||
00203 _ivalue[ DISTR_TYPE_IND ] == StdMeshers_NumberOfSegments::DT_ExprFunc)
00204 _ivalue[ CONV_MODE_IND ] = hyp->ConversionMode();
00205 _hypType = NB_SEGMENTS;
00206 aStatus = SMESH_Hypothesis::HYP_OK;
00207 }
00208
00209 else if (hypName == "Arithmetic1D")
00210 {
00211 const StdMeshers_Arithmetic1D * hyp =
00212 dynamic_cast <const StdMeshers_Arithmetic1D * >(theHyp);
00213 ASSERT(hyp);
00214 _value[ BEG_LENGTH_IND ] = hyp->GetLength( true );
00215 _value[ END_LENGTH_IND ] = hyp->GetLength( false );
00216 ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
00217 _hypType = ARITHMETIC_1D;
00218
00219 _revEdgesIDs = hyp->GetReversedEdges();
00220
00221 aStatus = SMESH_Hypothesis::HYP_OK;
00222 }
00223
00224 else if (hypName == "FixedPoints1D") {
00225 _fpHyp = dynamic_cast <const StdMeshers_FixedPoints1D*>(theHyp);
00226 ASSERT(_fpHyp);
00227 _hypType = FIXED_POINTS_1D;
00228
00229 _revEdgesIDs = _fpHyp->GetReversedEdges();
00230
00231 aStatus = SMESH_Hypothesis::HYP_OK;
00232 }
00233
00234 else if (hypName == "StartEndLength")
00235 {
00236 const StdMeshers_StartEndLength * hyp =
00237 dynamic_cast <const StdMeshers_StartEndLength * >(theHyp);
00238 ASSERT(hyp);
00239 _value[ BEG_LENGTH_IND ] = hyp->GetLength( true );
00240 _value[ END_LENGTH_IND ] = hyp->GetLength( false );
00241 ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
00242 _hypType = BEG_END_LENGTH;
00243
00244 _revEdgesIDs = hyp->GetReversedEdges();
00245
00246 aStatus = SMESH_Hypothesis::HYP_OK;
00247 }
00248
00249 else if (hypName == "Deflection1D")
00250 {
00251 const StdMeshers_Deflection1D * hyp =
00252 dynamic_cast <const StdMeshers_Deflection1D * >(theHyp);
00253 ASSERT(hyp);
00254 _value[ DEFLECTION_IND ] = hyp->GetDeflection();
00255 ASSERT( _value[ DEFLECTION_IND ] > 0 );
00256 _hypType = DEFLECTION;
00257 aStatus = SMESH_Hypothesis::HYP_OK;
00258 }
00259
00260 else if (hypName == "AutomaticLength")
00261 {
00262 StdMeshers_AutomaticLength * hyp = const_cast<StdMeshers_AutomaticLength *>
00263 (dynamic_cast <const StdMeshers_AutomaticLength * >(theHyp));
00264 ASSERT(hyp);
00265 _value[ BEG_LENGTH_IND ] = _value[ END_LENGTH_IND ] = hyp->GetLength( &aMesh, aShape );
00266
00267
00268 ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
00269 _hypType = MAX_LENGTH;
00270 aStatus = SMESH_Hypothesis::HYP_OK;
00271 }
00272 else
00273 aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
00274
00275 return ( _hypType != NONE );
00276 }
00277
00278 static bool computeParamByFunc(Adaptor3d_Curve& C3d, double first, double last,
00279 double length, bool theReverse,
00280 int nbSeg, Function& func,
00281 list<double>& theParams)
00282 {
00283
00284
00285
00286 if (nbSeg <= 0)
00287 return false;
00288
00289 MESSAGE( "computeParamByFunc" );
00290
00291 int nbPnt = 1 + nbSeg;
00292 vector<double> x(nbPnt, 0.);
00293
00294 if (!buildDistribution(func, 0.0, 1.0, nbSeg, x, 1E-4))
00295 return false;
00296
00297 MESSAGE( "Points:\n" );
00298 char buf[1024];
00299 for ( int i=0; i<=nbSeg; i++ )
00300 {
00301 sprintf( buf, "%f\n", float(x[i] ) );
00302 MESSAGE( buf );
00303 }
00304
00305
00306
00307
00308 double prevU = first;
00309 double sign = 1.;
00310 if (theReverse)
00311 {
00312 prevU = last;
00313 sign = -1.;
00314 }
00315 for( int i = 1; i < nbSeg; i++ )
00316 {
00317 double curvLength = length * (x[i] - x[i-1]) * sign;
00318 GCPnts_AbscissaPoint Discret( C3d, curvLength, prevU );
00319 if ( !Discret.IsDone() )
00320 return false;
00321 double U = Discret.Parameter();
00322 if ( U > first && U < last )
00323 theParams.push_back( U );
00324 else
00325 return false;
00326 prevU = U;
00327 }
00328 if ( theReverse )
00329 theParams.reverse();
00330 return true;
00331 }
00332
00333
00334
00347
00348
00349 static void compensateError(double a1, double an,
00350 double U1, double Un,
00351 double length,
00352 Adaptor3d_Curve& C3d,
00353 list<double> & theParams,
00354 bool adjustNeighbors2an = false)
00355 {
00356 int i, nPar = theParams.size();
00357 if ( a1 + an < length && nPar > 1 )
00358 {
00359 bool reverse = ( U1 > Un );
00360 GCPnts_AbscissaPoint Discret(C3d, reverse ? an : -an, Un);
00361 if ( !Discret.IsDone() )
00362 return;
00363 double Utgt = Discret.Parameter();
00364 list<double>::reverse_iterator itU = theParams.rbegin();
00365 double Ul = *itU++;
00366 double dUn = Utgt - Ul;
00367 if ( Abs(dUn) <= Precision::Confusion() )
00368 return;
00369 double dU = Abs( Ul - *itU );
00370 if ( adjustNeighbors2an || Abs(dUn) < 0.5 * dU ) {
00371
00372 }
00373 else {
00374 theParams.pop_back(); nPar--;
00375 dUn = Utgt - theParams.back();
00376 }
00377
00378 double q = dUn / ( nPar - 1 );
00379 if ( !adjustNeighbors2an )
00380 {
00381 q = dUn / ( Utgt - Un );
00382 for ( itU = theParams.rbegin(), i = 1; i < nPar; i++ ) {
00383 double prevU = *itU;
00384 (*itU) += dUn;
00385 ++itU;
00386 dUn = q * (*itU - prevU) * (prevU-U1)/(Un-U1);
00387 }
00388 }
00389 else {
00390 theParams.back() += dUn;
00391 double sign = reverse ? -1 : 1;
00392 double prevU = theParams.back();
00393 itU = theParams.rbegin();
00394 for ( ++itU, i = 2; i < nPar; ++itU, i++ ) {
00395 double newU = *itU + dUn;
00396 if ( newU*sign < prevU*sign ) {
00397 prevU = *itU = newU;
00398 dUn -= q;
00399 }
00400 else {
00401 list<double>::reverse_iterator itU2 = itU;
00402 ++itU2;
00403 int nb = 2;
00404 while ( (*itU2)*sign > prevU*sign ) {
00405 ++itU2; ++nb;
00406 }
00407 dU = ( *itU2 - prevU ) / nb;
00408 while ( itU != itU2 ) {
00409 *itU += dU; ++itU;
00410 }
00411 break;
00412 }
00413 }
00414 }
00415 }
00416 }
00417
00418
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00454
00455
00456 void StdMeshers_Regular_1D::SetEventListener(SMESH_subMesh* subMesh)
00457 {
00458 StdMeshers_Propagation::SetPropagationMgr( subMesh );
00459 }
00460
00461
00468
00469
00470 void StdMeshers_Regular_1D::SubmeshRestored(SMESH_subMesh* subMesh)
00471 {
00472 }
00473
00474
00478
00479
00480 const StdMeshers_SegmentLengthAroundVertex*
00481 StdMeshers_Regular_1D::getVertexHyp(SMESH_Mesh & theMesh,
00482 const TopoDS_Vertex & theV)
00483 {
00484 static SMESH_HypoFilter filter( SMESH_HypoFilter::HasName("SegmentAroundVertex_0D"));
00485 if ( const SMESH_Hypothesis * h = theMesh.GetHypothesis( theV, filter, true ))
00486 {
00487 SMESH_Algo* algo = const_cast< SMESH_Algo* >( static_cast< const SMESH_Algo* > ( h ));
00488 const list <const SMESHDS_Hypothesis *> & hypList = algo->GetUsedHypothesis( theMesh, theV, 0 );
00489 if ( !hypList.empty() && string("SegmentLengthAroundVertex") == hypList.front()->GetName() )
00490 return static_cast<const StdMeshers_SegmentLengthAroundVertex*>( hypList.front() );
00491 }
00492 return 0;
00493 }
00494
00495
00504
00505
00506 void StdMeshers_Regular_1D::redistributeNearVertices (SMESH_Mesh & theMesh,
00507 Adaptor3d_Curve & theC3d,
00508 double theLength,
00509 std::list< double > & theParameters,
00510 const TopoDS_Vertex & theVf,
00511 const TopoDS_Vertex & theVl)
00512 {
00513 double f = theC3d.FirstParameter(), l = theC3d.LastParameter();
00514 int nPar = theParameters.size();
00515 for ( int isEnd1 = 0; isEnd1 < 2; ++isEnd1 )
00516 {
00517 const TopoDS_Vertex & V = isEnd1 ? theVf : theVl;
00518 const StdMeshers_SegmentLengthAroundVertex* hyp = getVertexHyp (theMesh, V );
00519 if ( hyp ) {
00520 double vertexLength = hyp->GetLength();
00521 if ( vertexLength > theLength / 2.0 )
00522 continue;
00523 if ( isEnd1 ) {
00524 theParameters.reverse();
00525 std::swap( f, l );
00526 }
00527 if ( _hypType == NB_SEGMENTS )
00528 {
00529 compensateError(0, vertexLength, f, l, theLength, theC3d, theParameters, true );
00530 }
00531 else if ( nPar <= 3 )
00532 {
00533 if ( !isEnd1 )
00534 vertexLength = -vertexLength;
00535 GCPnts_AbscissaPoint Discret(theC3d, vertexLength, l);
00536 if ( Discret.IsDone() ) {
00537 if ( nPar == 0 )
00538 theParameters.push_back( Discret.Parameter());
00539 else {
00540 double L = GCPnts_AbscissaPoint::Length( theC3d, theParameters.back(), l);
00541 if ( vertexLength < L / 2.0 )
00542 theParameters.push_back( Discret.Parameter());
00543 else
00544 compensateError(0, vertexLength, f, l, theLength, theC3d, theParameters, true );
00545 }
00546 }
00547 }
00548 else
00549 {
00550
00551
00552 int nHalf = ( nPar-1 ) / 2;
00553 list< double >::reverse_iterator itU = theParameters.rbegin();
00554 std::advance( itU, nHalf );
00555 double Um = *itU++;
00556 double Lm = GCPnts_AbscissaPoint::Length( theC3d, Um, *itU);
00557 double L = GCPnts_AbscissaPoint::Length( theC3d, *itU, l);
00558 StdMeshers_Regular_1D algo( *this );
00559 algo._hypType = BEG_END_LENGTH;
00560 algo._value[ BEG_LENGTH_IND ] = Lm;
00561 algo._value[ END_LENGTH_IND ] = vertexLength;
00562 double from = *itU, to = l;
00563 if ( isEnd1 ) {
00564 std::swap( from, to );
00565 std::swap( algo._value[ BEG_LENGTH_IND ], algo._value[ END_LENGTH_IND ]);
00566 }
00567 list<double> params;
00568 if ( algo.computeInternalParameters( theMesh, theC3d, L, from, to, params, false ))
00569 {
00570 if ( isEnd1 ) params.reverse();
00571 while ( 1 + nHalf-- )
00572 theParameters.pop_back();
00573 theParameters.splice( theParameters.end(), params );
00574 }
00575 else
00576 {
00577 compensateError(0, vertexLength, f, l, theLength, theC3d, theParameters, true );
00578 }
00579 }
00580 if ( isEnd1 )
00581 theParameters.reverse();
00582 }
00583 }
00584 }
00585
00586
00590
00591 bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh,
00592 Adaptor3d_Curve& theC3d,
00593 double theLength,
00594 double theFirstU,
00595 double theLastU,
00596 list<double> & theParams,
00597 const bool theReverse,
00598 bool theConsiderPropagation)
00599 {
00600 theParams.clear();
00601
00602 double f = theFirstU, l = theLastU;
00603
00604 switch( _hypType )
00605 {
00606 case LOCAL_LENGTH:
00607 case MAX_LENGTH:
00608 case NB_SEGMENTS: {
00609
00610 double eltSize = 1;
00611 if ( _hypType == MAX_LENGTH )
00612 {
00613 double nbseg = ceil(theLength / _value[ BEG_LENGTH_IND ]);
00614 if (nbseg <= 0)
00615 nbseg = 1;
00616 eltSize = theLength / nbseg;
00617 }
00618 else if ( _hypType == LOCAL_LENGTH )
00619 {
00620
00621 double nbseg = ceil(theLength / _value[ BEG_LENGTH_IND ]);
00622
00623
00624 bool isFound = false;
00625 if (theConsiderPropagation && !_mainEdge.IsNull())
00626 {
00627
00628 SMESH_subMesh* sm = theMesh.GetSubMeshContaining(_mainEdge);
00629 if (sm) {
00630 bool computed = sm->IsMeshComputed();
00631 if (!computed) {
00632 if (sm->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE) {
00633 _gen->Compute( theMesh, _mainEdge, true);
00634 computed = sm->IsMeshComputed();
00635 }
00636 }
00637 if (computed) {
00638 SMESHDS_SubMesh* smds = sm->GetSubMeshDS();
00639 int nb_segments = smds->NbElements();
00640 if (nbseg - 1 <= nb_segments && nb_segments <= nbseg + 1) {
00641 isFound = true;
00642 nbseg = nb_segments;
00643 }
00644 }
00645 }
00646 }
00647 if (!isFound)
00648 {
00649 double aPrecision = _value[ PRECISION_IND ];
00650 double nbseg_prec = ceil((theLength / _value[ BEG_LENGTH_IND ]) - aPrecision);
00651 if (nbseg_prec == (nbseg - 1)) nbseg--;
00652 }
00653
00654 if (nbseg <= 0)
00655 nbseg = 1;
00656 eltSize = theLength / nbseg;
00657 }
00658 else
00659 {
00660
00661 int NbSegm = _ivalue[ NB_SEGMENTS_IND ];
00662 if ( NbSegm < 1 ) return false;
00663 if ( NbSegm == 1 ) return true;
00664
00665 switch (_ivalue[ DISTR_TYPE_IND ])
00666 {
00667 case StdMeshers_NumberOfSegments::DT_Scale:
00668 {
00669 double scale = _value[ SCALE_FACTOR_IND ];
00670
00671 if (fabs(scale - 1.0) < Precision::Confusion()) {
00672
00673 for (int i = 1; i < NbSegm; i++) {
00674 double param = f + (l - f) * i / NbSegm;
00675 theParams.push_back( param );
00676 }
00677 } else {
00678
00679 if ( theReverse )
00680 scale = 1.0 / scale;
00681
00682 double alpha = pow(scale, 1.0 / (NbSegm - 1));
00683 double factor = (l - f) / (1.0 - pow(alpha, NbSegm));
00684
00685 for (int i = 1; i < NbSegm; i++) {
00686 double param = f + factor * (1.0 - pow(alpha, i));
00687 theParams.push_back( param );
00688 }
00689 }
00690 return true;
00691 }
00692 break;
00693 case StdMeshers_NumberOfSegments::DT_TabFunc:
00694 {
00695 FunctionTable func(_vvalue[ TAB_FUNC_IND ], _ivalue[ CONV_MODE_IND ]);
00696 return computeParamByFunc(theC3d, f, l, theLength, theReverse,
00697 _ivalue[ NB_SEGMENTS_IND ], func,
00698 theParams);
00699 }
00700 break;
00701 case StdMeshers_NumberOfSegments::DT_ExprFunc:
00702 {
00703 FunctionExpr func(_svalue[ EXPR_FUNC_IND ].c_str(), _ivalue[ CONV_MODE_IND ]);
00704 return computeParamByFunc(theC3d, f, l, theLength, theReverse,
00705 _ivalue[ NB_SEGMENTS_IND ], func,
00706 theParams);
00707 }
00708 break;
00709 case StdMeshers_NumberOfSegments::DT_Regular:
00710 eltSize = theLength / _ivalue[ NB_SEGMENTS_IND ];
00711 break;
00712 default:
00713 return false;
00714 }
00715 }
00716 GCPnts_UniformAbscissa Discret(theC3d, eltSize, f, l);
00717 if ( !Discret.IsDone() )
00718 return error( "GCPnts_UniformAbscissa failed");
00719
00720 int NbPoints = Discret.NbPoints();
00721 for ( int i = 2; i < NbPoints; i++ )
00722 {
00723 double param = Discret.Parameter(i);
00724 theParams.push_back( param );
00725 }
00726 compensateError( eltSize, eltSize, f, l, theLength, theC3d, theParams );
00727 return true;
00728 }
00729
00730 case BEG_END_LENGTH: {
00731
00732
00733
00734 double a1 = _value[ BEG_LENGTH_IND ];
00735 double an = _value[ END_LENGTH_IND ];
00736 double q = ( theLength - a1 ) / ( theLength - an );
00737 if ( q < theLength/1e6 || 1.01*theLength < a1 + an)
00738 return error ( SMESH_Comment("Invalid segment lengths (")<<a1<<" and "<<an<<") "<<
00739 "for an edge of length "<<theLength);
00740
00741 double U1 = theReverse ? l : f;
00742 double Un = theReverse ? f : l;
00743 double param = U1;
00744 double eltSize = theReverse ? -a1 : a1;
00745 while ( 1 ) {
00746
00747
00748 GCPnts_AbscissaPoint Discret( theC3d, eltSize, param );
00749 if ( !Discret.IsDone() ) break;
00750 param = Discret.Parameter();
00751 if ( f < param && param < l )
00752 theParams.push_back( param );
00753 else
00754 break;
00755 eltSize *= q;
00756 }
00757 compensateError( a1, an, U1, Un, theLength, theC3d, theParams );
00758 if (theReverse) theParams.reverse();
00759 return true;
00760 }
00761
00762 case ARITHMETIC_1D: {
00763
00764
00765
00766 double a1 = _value[ BEG_LENGTH_IND ];
00767 double an = _value[ END_LENGTH_IND ];
00768 if ( 1.01*theLength < a1 + an)
00769 return error ( SMESH_Comment("Invalid segment lengths (")<<a1<<" and "<<an<<") "<<
00770 "for an edge of length "<<theLength);
00771
00772 double q = ( an - a1 ) / ( 2 *theLength/( a1 + an ) - 1 );
00773 int n = int(fabs(q) > numeric_limits<double>::min() ? ( 1+( an-a1 )/q ) : ( 1+theLength/a1 ));
00774
00775 double U1 = theReverse ? l : f;
00776 double Un = theReverse ? f : l;
00777 double param = U1;
00778 double eltSize = a1;
00779 if ( theReverse ) {
00780 eltSize = -eltSize;
00781 q = -q;
00782 }
00783 while ( n-- > 0 && eltSize * ( Un - U1 ) > 0 ) {
00784
00785
00786 GCPnts_AbscissaPoint Discret( theC3d, eltSize, param );
00787 if ( !Discret.IsDone() ) break;
00788 param = Discret.Parameter();
00789 if ( param > f && param < l )
00790 theParams.push_back( param );
00791 else
00792 break;
00793 eltSize += q;
00794 }
00795 compensateError( a1, an, U1, Un, theLength, theC3d, theParams );
00796 if (theReverse) theParams.reverse();
00797
00798 return true;
00799 }
00800
00801 case FIXED_POINTS_1D: {
00802 const std::vector<double>& aPnts = _fpHyp->GetPoints();
00803 const std::vector<int>& nbsegs = _fpHyp->GetNbSegments();
00804 int i = 0;
00805 TColStd_SequenceOfReal Params;
00806 for(; i<aPnts.size(); i++) {
00807 if( aPnts[i]<0.0001 || aPnts[i]>0.9999 ) continue;
00808 int j=1;
00809 bool IsExist = false;
00810 for(; j<=Params.Length(); j++) {
00811 if( fabs(aPnts[i]-Params.Value(j)) < 1e-4 ) {
00812 IsExist = true;
00813 break;
00814 }
00815 if( aPnts[i]<Params.Value(j) ) break;
00816 }
00817 if(!IsExist) Params.InsertBefore(j,aPnts[i]);
00818 }
00819 double par2, par1, lp;
00820 par1 = f;
00821 lp = l;
00822 double sign = 1.0;
00823 if(theReverse) {
00824 par1 = l;
00825 lp = f;
00826 sign = -1.0;
00827 }
00828 double eltSize, segmentSize = 0.;
00829 double currAbscissa = 0;
00830 for(i=0; i<Params.Length(); i++) {
00831 int nbseg = ( i > nbsegs.size()-1 ) ? nbsegs[0] : nbsegs[i];
00832 segmentSize = Params.Value(i+1)*theLength - currAbscissa;
00833 currAbscissa += segmentSize;
00834 GCPnts_AbscissaPoint APnt(theC3d, sign*segmentSize, par1);
00835 if( !APnt.IsDone() )
00836 return error( "GCPnts_AbscissaPoint failed");
00837 par2 = APnt.Parameter();
00838 eltSize = segmentSize/nbseg;
00839 GCPnts_UniformAbscissa Discret(theC3d, eltSize, par1, par2);
00840 if(theReverse)
00841 Discret.Initialize(theC3d, eltSize, par2, par1);
00842 else
00843 Discret.Initialize(theC3d, eltSize, par1, par2);
00844 if ( !Discret.IsDone() )
00845 return error( "GCPnts_UniformAbscissa failed");
00846 int NbPoints = Discret.NbPoints();
00847 list<double> tmpParams;
00848 for(int i=2; i<NbPoints; i++) {
00849 double param = Discret.Parameter(i);
00850 tmpParams.push_back( param );
00851 }
00852 if (theReverse) {
00853 compensateError( eltSize, eltSize, par2, par1, segmentSize, theC3d, tmpParams );
00854 tmpParams.reverse();
00855 }
00856 else {
00857 compensateError( eltSize, eltSize, par1, par2, segmentSize, theC3d, tmpParams );
00858 }
00859 list<double>::iterator itP = tmpParams.begin();
00860 for(; itP != tmpParams.end(); itP++) {
00861 theParams.push_back( *(itP) );
00862 }
00863 theParams.push_back( par2 );
00864
00865 par1 = par2;
00866 }
00867
00868 int nbseg = ( nbsegs.size() > Params.Length() ) ? nbsegs[Params.Length()] : nbsegs[0];
00869 segmentSize = theLength - currAbscissa;
00870 eltSize = segmentSize/nbseg;
00871 GCPnts_UniformAbscissa Discret;
00872 if(theReverse)
00873 Discret.Initialize(theC3d, eltSize, par1, lp);
00874 else
00875 Discret.Initialize(theC3d, eltSize, lp, par1);
00876 if ( !Discret.IsDone() )
00877 return error( "GCPnts_UniformAbscissa failed");
00878 int NbPoints = Discret.NbPoints();
00879 list<double> tmpParams;
00880 for(int i=2; i<NbPoints; i++) {
00881 double param = Discret.Parameter(i);
00882 tmpParams.push_back( param );
00883 }
00884 if (theReverse) {
00885 compensateError( eltSize, eltSize, lp, par1, segmentSize, theC3d, tmpParams );
00886 tmpParams.reverse();
00887 }
00888 else {
00889 compensateError( eltSize, eltSize, par1, lp, segmentSize, theC3d, tmpParams );
00890 }
00891 list<double>::iterator itP = tmpParams.begin();
00892 for(; itP != tmpParams.end(); itP++) {
00893 theParams.push_back( *(itP) );
00894 }
00895
00896 if (theReverse) {
00897 theParams.reverse();
00898 }
00899 return true;
00900 }
00901
00902 case DEFLECTION: {
00903
00904 GCPnts_UniformDeflection Discret(theC3d, _value[ DEFLECTION_IND ], f, l, true);
00905 if ( !Discret.IsDone() )
00906 return false;
00907
00908 int NbPoints = Discret.NbPoints();
00909 for ( int i = 2; i < NbPoints; i++ )
00910 {
00911 double param = Discret.Parameter(i);
00912 theParams.push_back( param );
00913 }
00914 return true;
00915 }
00916
00917 default:;
00918 }
00919
00920 return false;
00921 }
00922
00923
00927
00928
00929 bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & theShape)
00930 {
00931 if ( _hypType == NONE )
00932 return false;
00933
00934 SMESHDS_Mesh * meshDS = theMesh.GetMeshDS();
00935
00936 const TopoDS_Edge & EE = TopoDS::Edge(theShape);
00937 TopoDS_Edge E = TopoDS::Edge(EE.Oriented(TopAbs_FORWARD));
00938 int shapeID = meshDS->ShapeToIndex( E );
00939
00940 double f, l;
00941 Handle(Geom_Curve) Curve = BRep_Tool::Curve(E, f, l);
00942
00943 TopoDS_Vertex VFirst, VLast;
00944 TopExp::Vertices(E, VFirst, VLast);
00945
00946 ASSERT(!VFirst.IsNull());
00947 ASSERT(!VLast.IsNull());
00948 const SMDS_MeshNode * idFirst = SMESH_Algo::VertexNode( VFirst, meshDS );
00949 const SMDS_MeshNode * idLast = SMESH_Algo::VertexNode( VLast, meshDS );
00950 if (!idFirst || !idLast)
00951 return error( COMPERR_BAD_INPUT_MESH, "No node on vertex");
00952
00953
00954
00955
00956
00957 if (SMESHDS_SubMesh * subMeshDS = meshDS->MeshElements(theShape))
00958 {
00959 SMDS_ElemIteratorPtr ite = subMeshDS->GetElements();
00960 while (ite->more())
00961 meshDS->RemoveFreeElement(ite->next(), subMeshDS);
00962 SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes();
00963 while (itn->more()) {
00964 const SMDS_MeshNode * node = itn->next();
00965 if ( node->NbInverseElements() == 0 )
00966 meshDS->RemoveFreeNode(node, subMeshDS);
00967 else
00968 meshDS->RemoveNode(node);
00969 }
00970 }
00971
00972 if (!Curve.IsNull())
00973 {
00974 list< double > params;
00975 bool reversed = false;
00976 if ( theMesh.GetShapeToMesh().ShapeType() >= TopAbs_WIRE ) {
00977
00978 reversed = ( EE.Orientation() == TopAbs_REVERSED );
00979 }
00980 if ( !_mainEdge.IsNull() ) {
00981
00982 reversed = ( _mainEdge.Orientation() == TopAbs_REVERSED );
00983 int mainID = meshDS->ShapeToIndex(_mainEdge);
00984 if ( std::find( _revEdgesIDs.begin(), _revEdgesIDs.end(), mainID) != _revEdgesIDs.end())
00985 reversed = !reversed;
00986 }
00987
00988 if ( std::find( _revEdgesIDs.begin(), _revEdgesIDs.end(), shapeID) != _revEdgesIDs.end())
00989 reversed = !reversed;
00990
00991 BRepAdaptor_Curve C3d( E );
00992 double length = EdgeLength( E );
00993 if ( ! computeInternalParameters( theMesh, C3d, length, f, l, params, reversed, true )) {
00994 return false;
00995 }
00996 redistributeNearVertices( theMesh, C3d, length, params, VFirst, VLast );
00997
00998
00999
01000
01001 const SMDS_MeshNode * idPrev = idFirst;
01002 double parPrev = f;
01003 double parLast = l;
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014 for (list<double>::iterator itU = params.begin(); itU != params.end(); itU++) {
01015 double param = *itU;
01016 gp_Pnt P = Curve->Value(param);
01017
01018
01019 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
01020 meshDS->SetNodeOnEdge(node, shapeID, param);
01021
01022 if(_quadraticMesh) {
01023
01024 double prm = ( parPrev + param )/2;
01025 gp_Pnt PM = Curve->Value(prm);
01026 SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z());
01027 meshDS->SetNodeOnEdge(NM, shapeID, prm);
01028 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node, NM);
01029 meshDS->SetMeshElementOnShape(edge, shapeID);
01030 }
01031 else {
01032 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
01033 meshDS->SetMeshElementOnShape(edge, shapeID);
01034 }
01035
01036 idPrev = node;
01037 parPrev = param;
01038 }
01039 if(_quadraticMesh) {
01040 double prm = ( parPrev + parLast )/2;
01041 gp_Pnt PM = Curve->Value(prm);
01042 SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z());
01043 meshDS->SetNodeOnEdge(NM, shapeID, prm);
01044 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast, NM);
01045 meshDS->SetMeshElementOnShape(edge, shapeID);
01046 }
01047 else {
01048 SMDS_MeshEdge* edge = meshDS->AddEdge(idPrev, idLast);
01049 meshDS->SetMeshElementOnShape(edge, shapeID);
01050 }
01051 }
01052 else
01053 {
01054
01055
01056
01057 const int NbPoints = 5;
01058 BRep_Tool::Range( E, f, l );
01059 double du = (l - f) / (NbPoints - 1);
01060
01061 gp_Pnt P = BRep_Tool::Pnt(VFirst);
01062
01063 const SMDS_MeshNode * idPrev = idFirst;
01064 for (int i = 2; i < NbPoints; i++) {
01065 double param = f + (i - 1) * du;
01066 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
01067 if(_quadraticMesh) {
01068
01069 double prm = param - du/2.;
01070 SMDS_MeshNode * NM = meshDS->AddNode(P.X(), P.Y(), P.Z());
01071 meshDS->SetNodeOnEdge(NM, shapeID, prm);
01072 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node, NM);
01073 meshDS->SetMeshElementOnShape(edge, shapeID);
01074 }
01075 else {
01076 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
01077 meshDS->SetMeshElementOnShape(edge, shapeID);
01078 }
01079 meshDS->SetNodeOnEdge(node, shapeID, param);
01080 idPrev = node;
01081 }
01082 if(_quadraticMesh) {
01083
01084 double prm = l - du/2.;
01085 SMDS_MeshNode * NM = meshDS->AddNode(P.X(), P.Y(), P.Z());
01086 meshDS->SetNodeOnEdge(NM, shapeID, prm);
01087 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast, NM);
01088 meshDS->SetMeshElementOnShape(edge, shapeID);
01089 }
01090 else {
01091 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast);
01092 meshDS->SetMeshElementOnShape(edge, shapeID);
01093 }
01094 }
01095 return true;
01096 }
01097
01098
01099
01103
01104
01105 bool StdMeshers_Regular_1D::Evaluate(SMESH_Mesh & theMesh,
01106 const TopoDS_Shape & theShape,
01107 MapShapeNbElems& aResMap)
01108 {
01109 if ( _hypType == NONE )
01110 return false;
01111
01112
01113
01114 const TopoDS_Edge & EE = TopoDS::Edge(theShape);
01115 TopoDS_Edge E = TopoDS::Edge(EE.Oriented(TopAbs_FORWARD));
01116
01117
01118 double f, l;
01119 Handle(Geom_Curve) Curve = BRep_Tool::Curve(E, f, l);
01120
01121 TopoDS_Vertex VFirst, VLast;
01122 TopExp::Vertices(E, VFirst, VLast);
01123
01124 ASSERT(!VFirst.IsNull());
01125 ASSERT(!VLast.IsNull());
01126
01127 std::vector<int> aVec(SMDSEntity_Last,0);
01128
01129 if (!Curve.IsNull()) {
01130 list< double > params;
01131
01132 BRepAdaptor_Curve C3d( E );
01133 double length = EdgeLength( E );
01134 if ( ! computeInternalParameters( theMesh, C3d, length, f, l, params, false, true )) {
01135 SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
01136 aResMap.insert(std::make_pair(sm,aVec));
01137 SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
01138 smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this));
01139 return false;
01140 }
01141 redistributeNearVertices( theMesh, C3d, length, params, VFirst, VLast );
01142
01143 if(_quadraticMesh) {
01144 aVec[SMDSEntity_Node] = 2*params.size() + 1;
01145 aVec[SMDSEntity_Quad_Edge] = params.size() + 1;
01146 }
01147 else {
01148 aVec[SMDSEntity_Node] = params.size();
01149 aVec[SMDSEntity_Edge] = params.size() + 1;
01150 }
01151
01152 }
01153 else {
01154
01155
01156 if(_quadraticMesh) {
01157 aVec[SMDSEntity_Node] = 11;
01158 aVec[SMDSEntity_Quad_Edge] = 6;
01159 }
01160 else {
01161 aVec[SMDSEntity_Node] = 5;
01162 aVec[SMDSEntity_Edge] = 6;
01163 }
01164 }
01165
01166 SMESH_subMesh * sm = theMesh.GetSubMesh(theShape);
01167 aResMap.insert(std::make_pair(sm,aVec));
01168
01169 return true;
01170 }
01171
01172
01173
01177
01178
01179 const list <const SMESHDS_Hypothesis *> &
01180 StdMeshers_Regular_1D::GetUsedHypothesis(SMESH_Mesh & aMesh,
01181 const TopoDS_Shape & aShape,
01182 const bool ignoreAuxiliary)
01183 {
01184 _usedHypList.clear();
01185 _mainEdge.Nullify();
01186
01187 SMESH_HypoFilter auxiliaryFilter, compatibleFilter;
01188 auxiliaryFilter.Init( SMESH_HypoFilter::IsAuxiliary() );
01189 InitCompatibleHypoFilter( compatibleFilter, true );
01190
01191
01192 int nbHyp = aMesh.GetHypotheses( aShape, compatibleFilter, _usedHypList, false );
01193
01194 if (nbHyp == 0 && aShape.ShapeType() == TopAbs_EDGE)
01195 {
01196
01197 _mainEdge = StdMeshers_Propagation::GetPropagationSource( aMesh, aShape );
01198 if ( !_mainEdge.IsNull() )
01199 {
01200
01201
01202 nbHyp = aMesh.GetHypotheses( _mainEdge, compatibleFilter, _usedHypList, true );
01203 }
01204 }
01205
01206 if (nbHyp == 0)
01207 {
01208 SMESH_Algo::GetUsedHypothesis( aMesh, aShape, ignoreAuxiliary );
01209 nbHyp = _usedHypList.size();
01210 }
01211 else
01212 {
01213
01214 aMesh.GetHypotheses( aShape, auxiliaryFilter, _usedHypList, true );
01215 }
01216 if ( nbHyp > 1 && ignoreAuxiliary )
01217 _usedHypList.clear();
01218
01219 return _usedHypList;
01220 }