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_Regular_1D.cxx
24 // Moved here from SMESH_Regular_1D.cxx
25 // Author : Paul RASCLE, EDF
29 #include "StdMeshers_Regular_1D.hxx"
30 #include "StdMeshers_Distribution.hxx"
32 #include "StdMeshers_LocalLength.hxx"
33 #include "StdMeshers_NumberOfSegments.hxx"
34 #include "StdMeshers_Arithmetic1D.hxx"
35 #include "StdMeshers_StartEndLength.hxx"
36 #include "StdMeshers_Deflection1D.hxx"
37 #include "StdMeshers_AutomaticLength.hxx"
38 #include "StdMeshers_SegmentLengthAroundVertex.hxx"
39 #include "StdMeshers_Propagation.hxx"
41 #include "SMESH_Gen.hxx"
42 #include "SMESH_Mesh.hxx"
43 #include "SMESH_HypoFilter.hxx"
44 #include "SMESH_subMesh.hxx"
45 #include "SMESH_subMeshEventListener.hxx"
46 #include "SMESH_Comment.hxx"
48 #include "SMDS_MeshElement.hxx"
49 #include "SMDS_MeshNode.hxx"
51 #include "Utils_SALOME_Exception.hxx"
52 #include "utilities.h"
54 #include <BRepAdaptor_Curve.hxx>
55 #include <BRep_Tool.hxx>
56 #include <GCPnts_AbscissaPoint.hxx>
57 #include <GCPnts_UniformAbscissa.hxx>
58 #include <GCPnts_UniformDeflection.hxx>
59 #include <Precision.hxx>
61 #include <TopExp_Explorer.hxx>
63 #include <TopoDS_Edge.hxx>
69 //=============================================================================
73 //=============================================================================
75 StdMeshers_Regular_1D::StdMeshers_Regular_1D(int hypId, int studyId,
76 SMESH_Gen * gen):SMESH_1D_Algo(hypId, studyId, gen)
78 MESSAGE("StdMeshers_Regular_1D::StdMeshers_Regular_1D");
80 _shapeType = (1 << TopAbs_EDGE);
82 _compatibleHypothesis.push_back("LocalLength");
83 _compatibleHypothesis.push_back("NumberOfSegments");
84 _compatibleHypothesis.push_back("StartEndLength");
85 _compatibleHypothesis.push_back("Deflection1D");
86 _compatibleHypothesis.push_back("Arithmetic1D");
87 _compatibleHypothesis.push_back("AutomaticLength");
89 _compatibleHypothesis.push_back("QuadraticMesh"); // auxiliary !!!
90 _compatibleHypothesis.push_back("Propagation"); // auxiliary !!!
93 //=============================================================================
97 //=============================================================================
99 StdMeshers_Regular_1D::~StdMeshers_Regular_1D()
103 //=============================================================================
107 //=============================================================================
109 bool StdMeshers_Regular_1D::CheckHypothesis
111 const TopoDS_Shape& aShape,
112 SMESH_Hypothesis::Hypothesis_Status& aStatus)
115 _quadraticMesh = false;
117 const bool ignoreAuxiliaryHyps = false;
118 const list <const SMESHDS_Hypothesis * > & hyps =
119 GetUsedHypothesis(aMesh, aShape, ignoreAuxiliaryHyps);
121 // find non-auxiliary hypothesis
122 const SMESHDS_Hypothesis *theHyp = 0;
123 list <const SMESHDS_Hypothesis * >::const_iterator h = hyps.begin();
124 for ( ; h != hyps.end(); ++h ) {
125 if ( static_cast<const SMESH_Hypothesis*>(*h)->IsAuxiliary() ) {
126 if ( strcmp( "QuadraticMesh", (*h)->GetName() ) == 0 )
127 _quadraticMesh = true;
131 theHyp = *h; // use only the first non-auxiliary hypothesis
137 aStatus = SMESH_Hypothesis::HYP_MISSING;
138 return false; // can't work without a hypothesis
141 string hypName = theHyp->GetName();
143 if (hypName == "LocalLength")
145 const StdMeshers_LocalLength * hyp =
146 dynamic_cast <const StdMeshers_LocalLength * >(theHyp);
148 //_value[ BEG_LENGTH_IND ] = _value[ END_LENGTH_IND ] = hyp->GetLength();
149 _value[ BEG_LENGTH_IND ] = hyp->GetLength();
150 _value[ END_LENGTH_IND ] = hyp->GetPrecision();
151 ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
152 _hypType = LOCAL_LENGTH;
153 aStatus = SMESH_Hypothesis::HYP_OK;
156 else if (hypName == "NumberOfSegments")
158 const StdMeshers_NumberOfSegments * hyp =
159 dynamic_cast <const StdMeshers_NumberOfSegments * >(theHyp);
161 _ivalue[ NB_SEGMENTS_IND ] = hyp->GetNumberOfSegments();
162 ASSERT( _ivalue[ NB_SEGMENTS_IND ] > 0 );
163 _ivalue[ DISTR_TYPE_IND ] = (int) hyp->GetDistrType();
164 switch (_ivalue[ DISTR_TYPE_IND ])
166 case StdMeshers_NumberOfSegments::DT_Scale:
167 _value[ SCALE_FACTOR_IND ] = hyp->GetScaleFactor();
169 case StdMeshers_NumberOfSegments::DT_TabFunc:
170 _vvalue[ TAB_FUNC_IND ] = hyp->GetTableFunction();
172 case StdMeshers_NumberOfSegments::DT_ExprFunc:
173 _svalue[ EXPR_FUNC_IND ] = hyp->GetExpressionFunction();
175 case StdMeshers_NumberOfSegments::DT_Regular:
181 if (_ivalue[ DISTR_TYPE_IND ] == StdMeshers_NumberOfSegments::DT_TabFunc ||
182 _ivalue[ DISTR_TYPE_IND ] == StdMeshers_NumberOfSegments::DT_ExprFunc)
183 _ivalue[ CONV_MODE_IND ] = hyp->ConversionMode();
184 _hypType = NB_SEGMENTS;
185 aStatus = SMESH_Hypothesis::HYP_OK;
188 else if (hypName == "Arithmetic1D")
190 const StdMeshers_Arithmetic1D * hyp =
191 dynamic_cast <const StdMeshers_Arithmetic1D * >(theHyp);
193 _value[ BEG_LENGTH_IND ] = hyp->GetLength( true );
194 _value[ END_LENGTH_IND ] = hyp->GetLength( false );
195 ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
196 _hypType = ARITHMETIC_1D;
197 aStatus = SMESH_Hypothesis::HYP_OK;
200 else if (hypName == "StartEndLength")
202 const StdMeshers_StartEndLength * hyp =
203 dynamic_cast <const StdMeshers_StartEndLength * >(theHyp);
205 _value[ BEG_LENGTH_IND ] = hyp->GetLength( true );
206 _value[ END_LENGTH_IND ] = hyp->GetLength( false );
207 ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
208 _hypType = BEG_END_LENGTH;
209 aStatus = SMESH_Hypothesis::HYP_OK;
212 else if (hypName == "Deflection1D")
214 const StdMeshers_Deflection1D * hyp =
215 dynamic_cast <const StdMeshers_Deflection1D * >(theHyp);
217 _value[ DEFLECTION_IND ] = hyp->GetDeflection();
218 ASSERT( _value[ DEFLECTION_IND ] > 0 );
219 _hypType = DEFLECTION;
220 aStatus = SMESH_Hypothesis::HYP_OK;
223 else if (hypName == "AutomaticLength")
225 StdMeshers_AutomaticLength * hyp = const_cast<StdMeshers_AutomaticLength *>
226 (dynamic_cast <const StdMeshers_AutomaticLength * >(theHyp));
228 //_value[ BEG_LENGTH_IND ] = _value[ END_LENGTH_IND ] = hyp->GetLength( &aMesh, aShape );
229 _value[ BEG_LENGTH_IND ] = hyp->GetLength( &aMesh, aShape );
230 _value[ END_LENGTH_IND ] = Precision::Confusion(); // ?? or set to zero?
231 ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
232 _hypType = LOCAL_LENGTH;
233 aStatus = SMESH_Hypothesis::HYP_OK;
236 aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
238 return ( _hypType != NONE );
241 static bool computeParamByFunc(Adaptor3d_Curve& C3d, double first, double last,
242 double length, bool theReverse,
243 int nbSeg, Function& func,
244 list<double>& theParams)
247 //OSD::SetSignal( true );
252 MESSAGE( "computeParamByFunc" );
254 int nbPnt = 1 + nbSeg;
255 vector<double> x(nbPnt, 0.);
257 if (!buildDistribution(func, 0.0, 1.0, nbSeg, x, 1E-4))
260 MESSAGE( "Points:\n" );
262 for ( int i=0; i<=nbSeg; i++ )
264 sprintf( buf, "%f\n", float(x[i] ) );
270 // apply parameters in range [0,1] to the space of the curve
271 double prevU = first;
278 for( int i = 1; i < nbSeg; i++ )
280 double curvLength = length * (x[i] - x[i-1]) * sign;
281 GCPnts_AbscissaPoint Discret( C3d, curvLength, prevU );
282 if ( !Discret.IsDone() )
284 double U = Discret.Parameter();
285 if ( U > first && U < last )
286 theParams.push_back( U );
295 //================================================================================
297 * \brief adjust internal node parameters so that the last segment length == an
298 * \param a1 - the first segment length
299 * \param an - the last segment length
300 * \param U1 - the first edge parameter
301 * \param Un - the last edge parameter
302 * \param length - the edge length
303 * \param C3d - the edge curve
304 * \param theParams - internal node parameters to adjust
305 * \param adjustNeighbors2an - to adjust length of segments next to the last one
306 * and not to remove parameters
308 //================================================================================
310 static void compensateError(double a1, double an,
311 double U1, double Un,
313 Adaptor3d_Curve& C3d,
314 list<double> & theParams,
315 bool adjustNeighbors2an = false)
317 int i, nPar = theParams.size();
318 if ( a1 + an < length && nPar > 1 )
320 bool reverse = ( U1 > Un );
321 GCPnts_AbscissaPoint Discret(C3d, reverse ? an : -an, Un);
322 if ( !Discret.IsDone() )
324 double Utgt = Discret.Parameter(); // target value of the last parameter
325 list<double>::reverse_iterator itU = theParams.rbegin();
326 double Ul = *itU++; // real value of the last parameter
327 double dUn = Utgt - Ul; // parametric error of <an>
328 if ( Abs(dUn) <= Precision::Confusion() )
330 double dU = Abs( Ul - *itU ); // parametric length of the last but one segment
331 if ( adjustNeighbors2an || Abs(dUn) < 0.5 * dU ) { // last segment is a bit shorter than it should
332 // move the last parameter to the edge beginning
334 else { // last segment is much shorter than it should -> remove the last param and
335 theParams.pop_back(); nPar--; // move the rest points toward the edge end
336 dUn = Utgt - theParams.back();
339 double q = dUn / ( nPar - 1 );
340 if ( !adjustNeighbors2an ) {
341 for ( itU = theParams.rbegin(), i = 1; i < nPar; itU++, i++ ) {
347 theParams.back() += dUn;
348 double sign = reverse ? -1 : 1;
349 double prevU = theParams.back();
350 itU = theParams.rbegin();
351 for ( ++itU, i = 2; i < nPar; ++itU, i++ ) {
352 double newU = *itU + dUn;
353 if ( newU*sign < prevU*sign ) {
357 else { // set U between prevU and next valid param
358 list<double>::reverse_iterator itU2 = itU;
361 while ( (*itU2)*sign > prevU*sign ) {
364 dU = ( *itU2 - prevU ) / nb;
365 while ( itU != itU2 ) {
375 //================================================================================
377 * \brief Class used to clean mesh on edges when 0D hyp modified.
378 * Common approach doesn't work when 0D algo is missing because the 0D hyp is
379 * considered as not participating in computation whereas it is used by 1D algo.
381 //================================================================================
383 // struct VertexEventListener : public SMESH_subMeshEventListener
385 // VertexEventListener():SMESH_subMeshEventListener(0) // won't be deleted by submesh
388 // * \brief Clean mesh on edges
389 // * \param event - algo_event or compute_event itself (of SMESH_subMesh)
390 // * \param eventType - ALGO_EVENT or COMPUTE_EVENT (of SMESH_subMesh)
391 // * \param subMesh - the submesh where the event occures
393 // void ProcessEvent(const int event, const int eventType, SMESH_subMesh* subMesh,
394 // EventListenerData*, const SMESH_Hypothesis*)
396 // if ( eventType == SMESH_subMesh::ALGO_EVENT) // all algo events
398 // subMesh->ComputeStateEngine( SMESH_subMesh::MODIF_ALGO_STATE );
401 // }; // struct VertexEventListener
403 //=============================================================================
405 * \brief Sets event listener to vertex submeshes
406 * \param subMesh - submesh where algo is set
408 * This method is called when a submesh gets HYP_OK algo_state.
409 * After being set, event listener is notified on each event of a submesh.
411 //=============================================================================
413 void StdMeshers_Regular_1D::SetEventListener(SMESH_subMesh* subMesh)
415 // static VertexEventListener listener;
416 // SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false,false);
417 // while (smIt->more()) {
418 // subMesh->SetEventListener( &listener, 0, smIt->next() );
420 StdMeshers_Propagation::SetPropagationMgr( subMesh );
423 //=============================================================================
426 * \param subMesh - restored submesh
428 * This method is called only if a submesh has HYP_OK algo_state.
430 //=============================================================================
432 void StdMeshers_Regular_1D::SubmeshRestored(SMESH_subMesh* subMesh)
436 //=============================================================================
438 * \brief Return StdMeshers_SegmentLengthAroundVertex assigned to vertex
440 //=============================================================================
442 const StdMeshers_SegmentLengthAroundVertex*
443 StdMeshers_Regular_1D::getVertexHyp(SMESH_Mesh & theMesh,
444 const TopoDS_Vertex & theV)
446 static SMESH_HypoFilter filter( SMESH_HypoFilter::HasName("SegmentAroundVertex_0D"));
447 if ( const SMESH_Hypothesis * h = theMesh.GetHypothesis( theV, filter, true ))
449 SMESH_Algo* algo = const_cast< SMESH_Algo* >( static_cast< const SMESH_Algo* > ( h ));
450 const list <const SMESHDS_Hypothesis *> & hypList = algo->GetUsedHypothesis( theMesh, theV, 0 );
451 if ( !hypList.empty() && string("SegmentLengthAroundVertex") == hypList.front()->GetName() )
452 return static_cast<const StdMeshers_SegmentLengthAroundVertex*>( hypList.front() );
457 //================================================================================
459 * \brief Tune parameters to fit "SegmentLengthAroundVertex" hypothesis
460 * \param theC3d - wire curve
461 * \param theLength - curve length
462 * \param theParameters - internal nodes parameters to modify
463 * \param theVf - 1st vertex
464 * \param theVl - 2nd vertex
466 //================================================================================
468 void StdMeshers_Regular_1D::redistributeNearVertices (SMESH_Mesh & theMesh,
469 Adaptor3d_Curve & theC3d,
471 std::list< double > & theParameters,
472 const TopoDS_Vertex & theVf,
473 const TopoDS_Vertex & theVl)
475 double f = theC3d.FirstParameter(), l = theC3d.LastParameter();
476 int nPar = theParameters.size();
477 for ( int isEnd1 = 0; isEnd1 < 2; ++isEnd1 )
479 const TopoDS_Vertex & V = isEnd1 ? theVf : theVl;
480 const StdMeshers_SegmentLengthAroundVertex* hyp = getVertexHyp (theMesh, V );
482 double vertexLength = hyp->GetLength();
483 if ( vertexLength > theLength / 2.0 )
485 if ( isEnd1 ) { // to have a segment of interest at end of theParameters
486 theParameters.reverse();
489 if ( _hypType == NB_SEGMENTS )
491 compensateError(0, vertexLength, f, l, theLength, theC3d, theParameters, true );
493 else if ( nPar <= 3 )
496 vertexLength = -vertexLength;
497 GCPnts_AbscissaPoint Discret(theC3d, vertexLength, l);
498 if ( Discret.IsDone() ) {
500 theParameters.push_back( Discret.Parameter());
502 double L = GCPnts_AbscissaPoint::Length( theC3d, theParameters.back(), l);
503 if ( vertexLength < L / 2.0 )
504 theParameters.push_back( Discret.Parameter());
506 compensateError(0, vertexLength, f, l, theLength, theC3d, theParameters, true );
512 // recompute params between the last segment and a middle one.
513 // find size of a middle segment
514 int nHalf = ( nPar-1 ) / 2;
515 list< double >::reverse_iterator itU = theParameters.rbegin();
516 std::advance( itU, nHalf );
518 double Lm = GCPnts_AbscissaPoint::Length( theC3d, Um, *itU);
519 double L = GCPnts_AbscissaPoint::Length( theC3d, *itU, l);
520 StdMeshers_Regular_1D algo( *this );
521 algo._hypType = BEG_END_LENGTH;
522 algo._value[ BEG_LENGTH_IND ] = Lm;
523 algo._value[ END_LENGTH_IND ] = vertexLength;
524 double from = *itU, to = l;
526 std::swap( from, to );
527 std::swap( algo._value[ BEG_LENGTH_IND ], algo._value[ END_LENGTH_IND ]);
530 if ( algo.computeInternalParameters( theMesh, theC3d, L, from, to, params, false ))
532 if ( isEnd1 ) params.reverse();
533 while ( 1 + nHalf-- )
534 theParameters.pop_back();
535 theParameters.splice( theParameters.end(), params );
539 compensateError(0, vertexLength, f, l, theLength, theC3d, theParameters, true );
543 theParameters.reverse();
548 //=============================================================================
552 //=============================================================================
553 bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh,
554 Adaptor3d_Curve& theC3d,
558 list<double> & theParams,
559 const bool theReverse,
560 bool theConsiderPropagation)
564 double f = theFirstU, l = theLastU;
572 if ( _hypType == LOCAL_LENGTH )
574 // Local Length hypothesis
575 double nbseg = ceil(theLength / _value[ BEG_LENGTH_IND ]); // integer sup
578 bool isFound = false;
579 if (theConsiderPropagation && !_mainEdge.IsNull()) // propagated from some other edge
581 // Advanced processing to assure equal number of segments in case of Propagation
582 SMESH_subMesh* sm = theMesh.GetSubMeshContaining(_mainEdge);
584 bool computed = sm->IsMeshComputed();
586 if (sm->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE) {
587 sm->ComputeStateEngine(SMESH_subMesh::COMPUTE);
588 computed = sm->IsMeshComputed();
592 SMESHDS_SubMesh* smds = sm->GetSubMeshDS();
593 int nb_segments = smds->NbElements();
594 if (nbseg - 1 <= nb_segments && nb_segments <= nbseg + 1) {
601 if (!isFound) // not found by meshed edge in the propagation chain, use precision
603 double aPrecision = _value[ END_LENGTH_IND ];
604 double nbseg_prec = ceil((theLength / _value[ BEG_LENGTH_IND ]) - aPrecision);
605 if (nbseg_prec == (nbseg - 1)) nbseg--;
609 nbseg = 1; // degenerated edge
610 eltSize = theLength / nbseg;
614 // Number Of Segments hypothesis
615 int NbSegm = _ivalue[ NB_SEGMENTS_IND ];
616 if ( NbSegm < 1 ) return false;
617 if ( NbSegm == 1 ) return true;
619 switch (_ivalue[ DISTR_TYPE_IND ])
621 case StdMeshers_NumberOfSegments::DT_Scale:
623 double scale = _value[ SCALE_FACTOR_IND ];
625 if (fabs(scale - 1.0) < Precision::Confusion()) {
626 // special case to avoid division by zero
627 for (int i = 1; i < NbSegm; i++) {
628 double param = f + (l - f) * i / NbSegm;
629 theParams.push_back( param );
632 // general case of scale distribution
636 double alpha = pow(scale, 1.0 / (NbSegm - 1));
637 double factor = (l - f) / (1.0 - pow(alpha, NbSegm));
639 for (int i = 1; i < NbSegm; i++) {
640 double param = f + factor * (1.0 - pow(alpha, i));
641 theParams.push_back( param );
647 case StdMeshers_NumberOfSegments::DT_TabFunc:
649 FunctionTable func(_vvalue[ TAB_FUNC_IND ], _ivalue[ CONV_MODE_IND ]);
650 return computeParamByFunc(theC3d, f, l, theLength, theReverse,
651 _ivalue[ NB_SEGMENTS_IND ], func,
655 case StdMeshers_NumberOfSegments::DT_ExprFunc:
657 FunctionExpr func(_svalue[ EXPR_FUNC_IND ].c_str(), _ivalue[ CONV_MODE_IND ]);
658 return computeParamByFunc(theC3d, f, l, theLength, theReverse,
659 _ivalue[ NB_SEGMENTS_IND ], func,
663 case StdMeshers_NumberOfSegments::DT_Regular:
664 eltSize = theLength / _ivalue[ NB_SEGMENTS_IND ];
670 GCPnts_UniformAbscissa Discret(theC3d, eltSize, f, l);
671 if ( !Discret.IsDone() )
672 return error( "GCPnts_UniformAbscissa failed");
674 int NbPoints = Discret.NbPoints();
675 for ( int i = 2; i < NbPoints; i++ )
677 double param = Discret.Parameter(i);
678 theParams.push_back( param );
680 compensateError( eltSize, eltSize, f, l, theLength, theC3d, theParams ); // for PAL9899
684 case BEG_END_LENGTH: {
686 // geometric progression: SUM(n) = ( a1 - an * q ) / ( 1 - q ) = theLength
688 double a1 = _value[ BEG_LENGTH_IND ];
689 double an = _value[ END_LENGTH_IND ];
690 double q = ( theLength - a1 ) / ( theLength - an );
692 double U1 = theReverse ? l : f;
693 double Un = theReverse ? f : l;
695 double eltSize = theReverse ? -a1 : a1;
697 // computes a point on a curve <theC3d> at the distance <eltSize>
698 // from the point of parameter <param>.
699 GCPnts_AbscissaPoint Discret( theC3d, eltSize, param );
700 if ( !Discret.IsDone() ) break;
701 param = Discret.Parameter();
702 if ( f < param && param < l )
703 theParams.push_back( param );
708 compensateError( a1, an, U1, Un, theLength, theC3d, theParams );
709 if (theReverse) theParams.reverse(); // NPAL18025
713 case ARITHMETIC_1D: {
715 // arithmetic progression: SUM(n) = ( an - a1 + q ) * ( a1 + an ) / ( 2 * q ) = theLength
717 double a1 = _value[ BEG_LENGTH_IND ];
718 double an = _value[ END_LENGTH_IND ];
720 double q = ( an - a1 ) / ( 2 *theLength/( a1 + an ) - 1 );
721 int n = int( 1 + ( an - a1 ) / q );
723 double U1 = theReverse ? l : f;
724 double Un = theReverse ? f : l;
731 while ( n-- > 0 && eltSize * ( Un - U1 ) > 0 ) {
732 // computes a point on a curve <theC3d> at the distance <eltSize>
733 // from the point of parameter <param>.
734 GCPnts_AbscissaPoint Discret( theC3d, eltSize, param );
735 if ( !Discret.IsDone() ) break;
736 param = Discret.Parameter();
737 if ( param > f && param < l )
738 theParams.push_back( param );
743 compensateError( a1, an, U1, Un, theLength, theC3d, theParams );
744 if (theReverse) theParams.reverse(); // NPAL18025
751 GCPnts_UniformDeflection Discret(theC3d, _value[ DEFLECTION_IND ], f, l, true);
752 if ( !Discret.IsDone() )
755 int NbPoints = Discret.NbPoints();
756 for ( int i = 2; i < NbPoints; i++ )
758 double param = Discret.Parameter(i);
759 theParams.push_back( param );
770 //=============================================================================
774 //=============================================================================
776 bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & theShape)
778 if ( _hypType == NONE )
781 SMESHDS_Mesh * meshDS = theMesh.GetMeshDS();
783 const TopoDS_Edge & EE = TopoDS::Edge(theShape);
784 TopoDS_Edge E = TopoDS::Edge(EE.Oriented(TopAbs_FORWARD));
785 int shapeID = meshDS->ShapeToIndex( E );
788 Handle(Geom_Curve) Curve = BRep_Tool::Curve(E, f, l);
790 TopoDS_Vertex VFirst, VLast;
791 TopExp::Vertices(E, VFirst, VLast); // Vfirst corresponds to f and Vlast to l
793 ASSERT(!VFirst.IsNull());
794 ASSERT(!VLast.IsNull());
795 const SMDS_MeshNode * idFirst = SMESH_Algo::VertexNode( VFirst, meshDS );
796 const SMDS_MeshNode * idLast = SMESH_Algo::VertexNode( VLast, meshDS );
797 if (!idFirst || !idLast)
798 return error( COMPERR_BAD_INPUT_MESH, "No node on vertex");
802 list< double > params;
803 bool reversed = false;
804 if ( !_mainEdge.IsNull() )
805 reversed = ( _mainEdge.Orientation() == TopAbs_REVERSED );
807 BRepAdaptor_Curve C3d( E );
808 double length = EdgeLength( E );
809 if ( ! computeInternalParameters( theMesh, C3d, length, f, l, params, reversed, true )) {
812 redistributeNearVertices( theMesh, C3d, length, params, VFirst, VLast );
814 // edge extrema (indexes : 1 & NbPoints) already in SMDS (TopoDS_Vertex)
815 // only internal nodes receive an edge position with param on curve
817 const SMDS_MeshNode * idPrev = idFirst;
831 for (list<double>::iterator itU = params.begin(); itU != params.end(); itU++) {
833 gp_Pnt P = Curve->Value(param);
835 //Add the Node in the DataStructure
836 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
837 meshDS->SetNodeOnEdge(node, shapeID, param);
840 // create medium node
841 double prm = ( parPrev + param )/2;
842 gp_Pnt PM = Curve->Value(prm);
843 SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z());
844 meshDS->SetNodeOnEdge(NM, shapeID, prm);
845 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node, NM);
846 meshDS->SetMeshElementOnShape(edge, shapeID);
849 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
850 meshDS->SetMeshElementOnShape(edge, shapeID);
857 double prm = ( parPrev + parLast )/2;
858 gp_Pnt PM = Curve->Value(prm);
859 SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z());
860 meshDS->SetNodeOnEdge(NM, shapeID, prm);
861 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast, NM);
862 meshDS->SetMeshElementOnShape(edge, shapeID);
865 SMDS_MeshEdge* edge = meshDS->AddEdge(idPrev, idLast);
866 meshDS->SetMeshElementOnShape(edge, shapeID);
871 //MESSAGE("************* Degenerated edge! *****************");
873 // Edge is a degenerated Edge : We put n = 5 points on the edge.
874 const int NbPoints = 5;
875 BRep_Tool::Range( E, f, l ); // PAL15185
876 double du = (l - f) / (NbPoints - 1);
878 gp_Pnt P = BRep_Tool::Pnt(VFirst);
880 const SMDS_MeshNode * idPrev = idFirst;
881 for (int i = 2; i < NbPoints; i++) {
882 double param = f + (i - 1) * du;
883 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
885 // create medium node
886 double prm = param - du/2.;
887 SMDS_MeshNode * NM = meshDS->AddNode(P.X(), P.Y(), P.Z());
888 meshDS->SetNodeOnEdge(NM, shapeID, prm);
889 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node, NM);
890 meshDS->SetMeshElementOnShape(edge, shapeID);
893 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
894 meshDS->SetMeshElementOnShape(edge, shapeID);
896 meshDS->SetNodeOnEdge(node, shapeID, param);
900 // create medium node
901 double prm = l - du/2.;
902 SMDS_MeshNode * NM = meshDS->AddNode(P.X(), P.Y(), P.Z());
903 meshDS->SetNodeOnEdge(NM, shapeID, prm);
904 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast, NM);
905 meshDS->SetMeshElementOnShape(edge, shapeID);
908 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast);
909 meshDS->SetMeshElementOnShape(edge, shapeID);
915 //=============================================================================
917 * See comments in SMESH_Algo.cxx
919 //=============================================================================
921 const list <const SMESHDS_Hypothesis *> &
922 StdMeshers_Regular_1D::GetUsedHypothesis(SMESH_Mesh & aMesh,
923 const TopoDS_Shape & aShape,
924 const bool ignoreAuxiliary)
926 _usedHypList.clear();
929 SMESH_HypoFilter auxiliaryFilter, compatibleFilter;
930 auxiliaryFilter.Init( SMESH_HypoFilter::IsAuxiliary() );
931 const bool ignoreAux = true;
932 InitCompatibleHypoFilter( compatibleFilter, ignoreAux );
934 // get non-auxiliary assigned to aShape
935 int nbHyp = aMesh.GetHypotheses( aShape, compatibleFilter, _usedHypList, false );
937 if (nbHyp == 0 && aShape.ShapeType() == TopAbs_EDGE)
939 // Check, if propagated from some other edge
940 _mainEdge = StdMeshers_Propagation::GetPropagationSource( aMesh, aShape );
941 if ( !_mainEdge.IsNull() )
943 // Propagation of 1D hypothesis from <aMainEdge> on this edge;
944 // get non-auxiliary assigned to _mainEdge
945 nbHyp = aMesh.GetHypotheses( _mainEdge, compatibleFilter, _usedHypList, true );
949 if (nbHyp == 0) // nothing propagated nor assigned to aShape
951 SMESH_Algo::GetUsedHypothesis( aMesh, aShape, ignoreAuxiliary );
952 nbHyp = _usedHypList.size();
956 // get auxiliary hyps from aShape
957 aMesh.GetHypotheses( aShape, auxiliaryFilter, _usedHypList, true );
959 if ( nbHyp > 1 && ignoreAuxiliary )
960 _usedHypList.clear(); //only one compatible non-auxiliary hypothesis allowed