1 // SMESH SMESH : implementaion of SMESH idl descriptions
3 // Copyright (C) 2003 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
24 // File : StdMeshers_Regular_1D.cxx
25 // Moved here from SMESH_Regular_1D.cxx
26 // Author : Paul RASCLE, EDF
30 #include "StdMeshers_Regular_1D.hxx"
31 #include "StdMeshers_Distribution.hxx"
33 #include "StdMeshers_LocalLength.hxx"
34 #include "StdMeshers_NumberOfSegments.hxx"
35 #include "StdMeshers_Arithmetic1D.hxx"
36 #include "StdMeshers_StartEndLength.hxx"
37 #include "StdMeshers_Deflection1D.hxx"
38 #include "StdMeshers_AutomaticLength.hxx"
39 #include "StdMeshers_SegmentLengthAroundVertex.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"
47 #include "SMDS_MeshElement.hxx"
48 #include "SMDS_MeshNode.hxx"
50 #include "Utils_SALOME_Exception.hxx"
51 #include "utilities.h"
53 #include <BRepAdaptor_Curve.hxx>
54 #include <BRep_Tool.hxx>
55 #include <TopoDS_Edge.hxx>
56 #include <TopExp_Explorer.hxx>
57 #include <GCPnts_AbscissaPoint.hxx>
58 #include <GCPnts_UniformAbscissa.hxx>
59 #include <GCPnts_UniformDeflection.hxx>
60 #include <Precision.hxx>
62 #include <Standard_ErrorHandler.hxx>
63 #include <Standard_Failure.hxx>
70 //=============================================================================
74 //=============================================================================
76 StdMeshers_Regular_1D::StdMeshers_Regular_1D(int hypId, int studyId,
77 SMESH_Gen * gen):SMESH_1D_Algo(hypId, studyId, gen)
79 MESSAGE("StdMeshers_Regular_1D::StdMeshers_Regular_1D");
81 _shapeType = (1 << TopAbs_EDGE);
83 _compatibleHypothesis.push_back("LocalLength");
84 _compatibleHypothesis.push_back("NumberOfSegments");
85 _compatibleHypothesis.push_back("StartEndLength");
86 _compatibleHypothesis.push_back("Deflection1D");
87 _compatibleHypothesis.push_back("Arithmetic1D");
88 _compatibleHypothesis.push_back("AutomaticLength");
90 _compatibleHypothesis.push_back("QuadraticMesh"); // 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 ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
150 _hypType = LOCAL_LENGTH;
151 aStatus = SMESH_Hypothesis::HYP_OK;
154 else if (hypName == "NumberOfSegments")
156 const StdMeshers_NumberOfSegments * hyp =
157 dynamic_cast <const StdMeshers_NumberOfSegments * >(theHyp);
159 _ivalue[ NB_SEGMENTS_IND ] = hyp->GetNumberOfSegments();
160 ASSERT( _ivalue[ NB_SEGMENTS_IND ] > 0 );
161 _ivalue[ DISTR_TYPE_IND ] = (int) hyp->GetDistrType();
162 switch (_ivalue[ DISTR_TYPE_IND ])
164 case StdMeshers_NumberOfSegments::DT_Scale:
165 _value[ SCALE_FACTOR_IND ] = hyp->GetScaleFactor();
167 case StdMeshers_NumberOfSegments::DT_TabFunc:
168 _vvalue[ TAB_FUNC_IND ] = hyp->GetTableFunction();
170 case StdMeshers_NumberOfSegments::DT_ExprFunc:
171 _svalue[ EXPR_FUNC_IND ] = hyp->GetExpressionFunction();
173 case StdMeshers_NumberOfSegments::DT_Regular:
179 if (_ivalue[ DISTR_TYPE_IND ] == StdMeshers_NumberOfSegments::DT_TabFunc ||
180 _ivalue[ DISTR_TYPE_IND ] == StdMeshers_NumberOfSegments::DT_ExprFunc)
181 _ivalue[ CONV_MODE_IND ] = hyp->ConversionMode();
182 _hypType = NB_SEGMENTS;
183 aStatus = SMESH_Hypothesis::HYP_OK;
186 else if (hypName == "Arithmetic1D")
188 const StdMeshers_Arithmetic1D * hyp =
189 dynamic_cast <const StdMeshers_Arithmetic1D * >(theHyp);
191 _value[ BEG_LENGTH_IND ] = hyp->GetLength( true );
192 _value[ END_LENGTH_IND ] = hyp->GetLength( false );
193 ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
194 _hypType = ARITHMETIC_1D;
195 aStatus = SMESH_Hypothesis::HYP_OK;
198 else if (hypName == "StartEndLength")
200 const StdMeshers_StartEndLength * hyp =
201 dynamic_cast <const StdMeshers_StartEndLength * >(theHyp);
203 _value[ BEG_LENGTH_IND ] = hyp->GetLength( true );
204 _value[ END_LENGTH_IND ] = hyp->GetLength( false );
205 ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
206 _hypType = BEG_END_LENGTH;
207 aStatus = SMESH_Hypothesis::HYP_OK;
210 else if (hypName == "Deflection1D")
212 const StdMeshers_Deflection1D * hyp =
213 dynamic_cast <const StdMeshers_Deflection1D * >(theHyp);
215 _value[ DEFLECTION_IND ] = hyp->GetDeflection();
216 ASSERT( _value[ DEFLECTION_IND ] > 0 );
217 _hypType = DEFLECTION;
218 aStatus = SMESH_Hypothesis::HYP_OK;
221 else if (hypName == "AutomaticLength")
223 StdMeshers_AutomaticLength * hyp = const_cast<StdMeshers_AutomaticLength *>
224 (dynamic_cast <const StdMeshers_AutomaticLength * >(theHyp));
226 _value[ BEG_LENGTH_IND ] = _value[ END_LENGTH_IND ] = hyp->GetLength( &aMesh, aShape );
227 ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
228 _hypType = LOCAL_LENGTH;
229 aStatus = SMESH_Hypothesis::HYP_OK;
232 aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
234 return ( _hypType != NONE );
237 static bool computeParamByFunc(Adaptor3d_Curve& C3d, double first, double last,
238 double length, bool theReverse,
239 int nbSeg, Function& func,
240 list<double>& theParams)
243 //OSD::SetSignal( true );
248 MESSAGE( "computeParamByFunc" );
250 int nbPnt = 1 + nbSeg;
251 vector<double> x(nbPnt, 0.);
253 if( !buildDistribution( func, 0.0, 1.0, nbSeg, x, 1E-4 ) )
256 MESSAGE( "Points:\n" );
258 for( int i=0; i<=nbSeg; i++ )
260 sprintf( buf, "%f\n", float(x[i] ) );
266 // apply parameters in range [0,1] to the space of the curve
267 double prevU = first;
274 for( int i = 1; i < nbSeg; i++ )
276 double curvLength = length * (x[i] - x[i-1]) * sign;
277 GCPnts_AbscissaPoint Discret( C3d, curvLength, prevU );
278 if ( !Discret.IsDone() )
280 double U = Discret.Parameter();
281 if ( U > first && U < last )
282 theParams.push_back( U );
291 //================================================================================
293 * \brief adjust internal node parameters so that the last segment length == an
294 * \param a1 - the first segment length
295 * \param an - the last segment length
296 * \param U1 - the first edge parameter
297 * \param Un - the last edge parameter
298 * \param length - the edge length
299 * \param C3d - the edge curve
300 * \param theParams - internal node parameters to adjust
301 * \param adjustNeighbors2an - to adjust length of segments next to the last one
302 * and not to remove parameters
304 //================================================================================
306 static void compensateError(double a1, double an,
307 double U1, double Un,
309 Adaptor3d_Curve& C3d,
310 list<double> & theParams,
311 bool adjustNeighbors2an = false)
313 int i, nPar = theParams.size();
314 if ( a1 + an < length && nPar > 1 )
316 bool reverse = ( U1 > Un );
317 GCPnts_AbscissaPoint Discret(C3d, reverse ? an : -an, Un);
318 if ( !Discret.IsDone() )
320 double Utgt = Discret.Parameter(); // target value of the last parameter
321 list<double>::reverse_iterator itU = theParams.rbegin();
322 double Ul = *itU++; // real value of the last parameter
323 double dUn = Utgt - Ul; // parametric error of <an>
324 if ( Abs(dUn) <= Precision::Confusion() )
326 double dU = Abs( Ul - *itU ); // parametric length of the last but one segment
327 if ( adjustNeighbors2an || Abs(dUn) < 0.5 * dU ) { // last segment is a bit shorter than it should
328 // move the last parameter to the edge beginning
330 else { // last segment is much shorter than it should -> remove the last param and
331 theParams.pop_back(); nPar--; // move the rest points toward the edge end
332 dUn = Utgt - theParams.back();
335 double q = dUn / ( nPar - 1 );
336 if ( !adjustNeighbors2an ) {
337 for ( itU = theParams.rbegin(), i = 1; i < nPar; itU++, i++ ) {
343 theParams.back() += dUn;
344 double sign = reverse ? -1 : 1;
345 double prevU = theParams.back();
346 itU = theParams.rbegin();
347 for ( ++itU, i = 2; i < nPar; ++itU, i++ ) {
348 double newU = *itU + dUn;
349 if ( newU*sign < prevU*sign ) {
353 else { // set U between prevU and next valid param
354 list<double>::reverse_iterator itU2 = itU;
357 while ( (*itU2)*sign > prevU*sign ) {
360 dU = ( *itU2 - prevU ) / nb;
361 while ( itU != itU2 ) {
371 //================================================================================
373 * \brief Class used to clean mesh on edges when 0D hyp modified.
374 * Common approach doesn't work when 0D algo is missing because the 0D hyp is
375 * considered as not participating in computation whereas it is used by 1D algo.
377 //================================================================================
379 struct VertexEventListener : public SMESH_subMeshEventListener
381 VertexEventListener():SMESH_subMeshEventListener(0) // won't be deleted by submesh
384 * \brief Clean mesh on edges
385 * \param event - algo_event or compute_event itself (of SMESH_subMesh)
386 * \param eventType - ALGO_EVENT or COMPUTE_EVENT (of SMESH_subMesh)
387 * \param subMesh - the submesh where the event occures
389 void ProcessEvent(const int event, const int eventType, SMESH_subMesh* subMesh,
390 EventListenerData*, SMESH_Hypothesis*)
392 if ( eventType == SMESH_subMesh::ALGO_EVENT) // all algo events
394 subMesh->ComputeStateEngine( SMESH_subMesh::MODIF_ALGO_STATE );
397 }; // struct VertexEventListener
399 //=============================================================================
401 * \brief Sets event listener to vertex submeshes
402 * \param subMesh - submesh where algo is set
404 * This method is called when a submesh gets HYP_OK algo_state.
405 * After being set, event listener is notified on each event of a submesh.
407 //=============================================================================
409 void StdMeshers_Regular_1D::SetEventListener(SMESH_subMesh* subMesh)
411 static VertexEventListener listener;
412 const map < int, SMESH_subMesh * >& vSMs = subMesh->DependsOn();
413 map < int, SMESH_subMesh * >::const_iterator itsub;
414 for (itsub = vSMs.begin(); itsub != vSMs.end(); itsub++)
416 subMesh->SetEventListener( &listener, 0, itsub->second );
420 //=============================================================================
423 * \param subMesh - restored submesh
425 * This method is called only if a submesh has HYP_OK algo_state.
427 //=============================================================================
429 void StdMeshers_Regular_1D::SubmeshRestored(SMESH_subMesh* subMesh)
433 //=============================================================================
435 * \brief Return StdMeshers_SegmentLengthAroundVertex assigned to vertex
437 //=============================================================================
439 const StdMeshers_SegmentLengthAroundVertex*
440 StdMeshers_Regular_1D::getVertexHyp(SMESH_Mesh & theMesh,
441 const TopoDS_Vertex & theV)
443 static SMESH_HypoFilter filter( SMESH_HypoFilter::HasName("SegmentLengthAroundVertex"));
444 const SMESH_Hypothesis * hyp = theMesh.GetHypothesis( theV, filter, true );
445 return static_cast<const StdMeshers_SegmentLengthAroundVertex*>( hyp );
448 //================================================================================
450 * \brief Tune parameters to fit "SegmentLengthAroundVertex" hypothesis
451 * \param theC3d - wire curve
452 * \param theLength - curve length
453 * \param theParameters - internal nodes parameters to modify
454 * \param theVf - 1st vertex
455 * \param theVl - 2nd vertex
457 //================================================================================
459 void StdMeshers_Regular_1D::redistributeNearVertices (SMESH_Mesh & theMesh,
460 Adaptor3d_Curve & theC3d,
462 std::list< double > & theParameters,
463 const TopoDS_Vertex & theVf,
464 const TopoDS_Vertex & theVl) const
466 double f = theC3d.FirstParameter(), l = theC3d.LastParameter();
467 int nPar = theParameters.size();
468 for ( int isEnd1 = 0; isEnd1 < 2; ++isEnd1 )
470 const TopoDS_Vertex & V = isEnd1 ? theVf : theVl;
471 const StdMeshers_SegmentLengthAroundVertex* hyp = getVertexHyp (theMesh, V );
473 double vertexLength = hyp->GetLength();
474 if ( vertexLength > theLength / 2.0 )
476 if ( isEnd1 ) { // to have a segment of interest at end of theParameters
477 theParameters.reverse();
480 if ( _hypType == NB_SEGMENTS )
482 compensateError(0, vertexLength, f, l, theLength, theC3d, theParameters, true );
484 else if ( nPar <= 3 )
487 vertexLength = -vertexLength;
488 GCPnts_AbscissaPoint Discret(theC3d, vertexLength, l);
489 if ( Discret.IsDone() ) {
491 theParameters.push_back( Discret.Parameter());
493 double L = GCPnts_AbscissaPoint::Length( theC3d, theParameters.back(), l);
494 if ( vertexLength < L / 2.0 )
495 theParameters.push_back( Discret.Parameter());
497 compensateError(0, vertexLength, f, l, theLength, theC3d, theParameters, true );
503 // recompute params between the last segment and a middle one.
504 // find size of a middle segment
505 int nHalf = ( nPar-1 ) / 2;
506 list< double >::reverse_iterator itU = theParameters.rbegin();
507 std::advance( itU, nHalf );
509 double Lm = GCPnts_AbscissaPoint::Length( theC3d, Um, *itU);
510 double L = GCPnts_AbscissaPoint::Length( theC3d, *itU, l);
511 StdMeshers_Regular_1D algo( *this );
512 algo._hypType = BEG_END_LENGTH;
513 algo._value[ BEG_LENGTH_IND ] = Lm;
514 algo._value[ END_LENGTH_IND ] = vertexLength;
515 double from = *itU, to = l;
517 std::swap( from, to );
518 std::swap( algo._value[ BEG_LENGTH_IND ], algo._value[ END_LENGTH_IND ]);
521 if ( algo.computeInternalParameters( theC3d, L, from, to, params, false ))
523 if ( isEnd1 ) params.reverse();
524 while ( 1 + nHalf-- )
525 theParameters.pop_back();
526 theParameters.splice( theParameters.end(), params );
530 compensateError(0, vertexLength, f, l, theLength, theC3d, theParameters, true );
534 theParameters.reverse();
539 //=============================================================================
543 //=============================================================================
544 bool StdMeshers_Regular_1D::computeInternalParameters(Adaptor3d_Curve& theC3d,
548 list<double> & theParams,
549 const bool theReverse) const
553 double f = theFirstU, l = theLastU;
561 if ( _hypType == LOCAL_LENGTH )
563 // Local Length hypothesis
564 double nbseg = ceil(theLength / _value[ BEG_LENGTH_IND ]); // integer sup
566 nbseg = 1; // degenerated edge
567 eltSize = theLength / nbseg;
571 // Number Of Segments hypothesis
572 int NbSegm = _ivalue[ NB_SEGMENTS_IND ];
573 if ( NbSegm < 1 ) return false;
574 if ( NbSegm == 1 ) return true;
576 switch (_ivalue[ DISTR_TYPE_IND ])
578 case StdMeshers_NumberOfSegments::DT_Scale:
580 double scale = _value[ SCALE_FACTOR_IND ];
582 if (fabs(scale - 1.0) < Precision::Confusion()) {
583 // special case to avoid division on zero
584 for (int i = 1; i < NbSegm; i++) {
585 double param = f + (l - f) * i / NbSegm;
586 theParams.push_back( param );
589 // general case of scale distribution
593 double alpha = pow(scale, 1.0 / (NbSegm - 1));
594 double factor = (l - f) / (1.0 - pow(alpha, NbSegm));
596 for (int i = 1; i < NbSegm; i++) {
597 double param = f + factor * (1.0 - pow(alpha, i));
598 theParams.push_back( param );
604 case StdMeshers_NumberOfSegments::DT_TabFunc:
606 FunctionTable func(_vvalue[ TAB_FUNC_IND ], _ivalue[ CONV_MODE_IND ]);
607 return computeParamByFunc(theC3d, f, l, theLength, theReverse,
608 _ivalue[ NB_SEGMENTS_IND ], func,
612 case StdMeshers_NumberOfSegments::DT_ExprFunc:
614 FunctionExpr func(_svalue[ EXPR_FUNC_IND ].c_str(), _ivalue[ CONV_MODE_IND ]);
615 return computeParamByFunc(theC3d, f, l, theLength, theReverse,
616 _ivalue[ NB_SEGMENTS_IND ], func,
620 case StdMeshers_NumberOfSegments::DT_Regular:
621 eltSize = theLength / _ivalue[ NB_SEGMENTS_IND ];
627 GCPnts_UniformAbscissa Discret(theC3d, eltSize, f, l);
628 if ( !Discret.IsDone() )
631 int NbPoints = Discret.NbPoints();
632 for ( int i = 2; i < NbPoints; i++ )
634 double param = Discret.Parameter(i);
635 theParams.push_back( param );
637 compensateError( eltSize, eltSize, f, l, theLength, theC3d, theParams ); // for PAL9899
641 case BEG_END_LENGTH: {
643 // geometric progression: SUM(n) = ( a1 - an * q ) / ( 1 - q ) = theLength
645 double a1 = _value[ BEG_LENGTH_IND ];
646 double an = _value[ END_LENGTH_IND ];
647 double q = ( theLength - a1 ) / ( theLength - an );
649 double U1 = theReverse ? l : f;
650 double Un = theReverse ? f : l;
652 double eltSize = theReverse ? -a1 : a1;
654 // computes a point on a curve <theC3d> at the distance <eltSize>
655 // from the point of parameter <param>.
656 GCPnts_AbscissaPoint Discret( theC3d, eltSize, param );
657 if ( !Discret.IsDone() ) break;
658 param = Discret.Parameter();
659 if ( param > f && param < l )
660 theParams.push_back( param );
665 compensateError( a1, an, U1, Un, theLength, theC3d, theParams );
669 case ARITHMETIC_1D: {
671 // arithmetic progression: SUM(n) = ( an - a1 + q ) * ( a1 + an ) / ( 2 * q ) = theLength
673 double a1 = _value[ BEG_LENGTH_IND ];
674 double an = _value[ END_LENGTH_IND ];
676 double q = ( an - a1 ) / ( 2 *theLength/( a1 + an ) - 1 );
677 int n = int( 1 + ( an - a1 ) / q );
679 double U1 = theReverse ? l : f;
680 double Un = theReverse ? f : l;
687 while ( n-- > 0 && eltSize * ( Un - U1 ) > 0 ) {
688 // computes a point on a curve <theC3d> at the distance <eltSize>
689 // from the point of parameter <param>.
690 GCPnts_AbscissaPoint Discret( theC3d, eltSize, param );
691 if ( !Discret.IsDone() ) break;
692 param = Discret.Parameter();
693 if ( param > f && param < l )
694 theParams.push_back( param );
699 compensateError( a1, an, U1, Un, theLength, theC3d, theParams );
706 GCPnts_UniformDeflection Discret(theC3d, _value[ DEFLECTION_IND ], f, l, true);
707 if ( !Discret.IsDone() )
710 int NbPoints = Discret.NbPoints();
711 for ( int i = 2; i < NbPoints; i++ )
713 double param = Discret.Parameter(i);
714 theParams.push_back( param );
726 //=============================================================================
730 //=============================================================================
732 bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape)
734 //MESSAGE("StdMeshers_Regular_1D::Compute");
736 if ( _hypType == NONE )
739 SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
741 const TopoDS_Edge & EE = TopoDS::Edge(aShape);
742 TopoDS_Edge E = TopoDS::Edge(EE.Oriented(TopAbs_FORWARD));
743 int shapeID = meshDS->ShapeToIndex( E );
746 Handle(Geom_Curve) Curve = BRep_Tool::Curve(E, f, l);
748 TopoDS_Vertex VFirst, VLast;
749 TopExp::Vertices(E, VFirst, VLast); // Vfirst corresponds to f and Vlast to l
751 ASSERT(!VFirst.IsNull());
752 const SMDS_MeshNode * idFirst = SMESH_Algo::VertexNode( VFirst, meshDS );
754 MESSAGE (" NO NODE BUILT ON VERTEX ");
758 ASSERT(!VLast.IsNull());
759 const SMDS_MeshNode * idLast = SMESH_Algo::VertexNode( VLast, meshDS );
761 MESSAGE (" NO NODE BUILT ON VERTEX ");
765 if (!Curve.IsNull()) {
766 list< double > params;
767 bool reversed = false;
768 if ( !_mainEdge.IsNull() )
769 reversed = aMesh.IsReversedInChain( EE, _mainEdge );
770 BRepAdaptor_Curve C3d( E );
771 double length = EdgeLength( E );
773 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
776 if ( ! computeInternalParameters( C3d, length, f, l, params, reversed )) {
779 redistributeNearVertices( aMesh, C3d, length, params, VFirst, VLast );
781 catch ( Standard_Failure ) {
785 // edge extrema (indexes : 1 & NbPoints) already in SMDS (TopoDS_Vertex)
786 // only internal nodes receive an edge position with param on curve
788 const SMDS_MeshNode * idPrev = idFirst;
792 for (list<double>::iterator itU = params.begin(); itU != params.end(); itU++) {
794 gp_Pnt P = Curve->Value(param);
796 //Add the Node in the DataStructure
797 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
798 meshDS->SetNodeOnEdge(node, shapeID, param);
801 // create medium node
802 double prm = ( parPrev + param )/2;
803 gp_Pnt PM = Curve->Value(prm);
804 SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z());
805 meshDS->SetNodeOnEdge(NM, shapeID, prm);
806 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node, NM);
807 meshDS->SetMeshElementOnShape(edge, shapeID);
810 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
811 meshDS->SetMeshElementOnShape(edge, shapeID);
818 double prm = ( parPrev + parLast )/2;
819 gp_Pnt PM = Curve->Value(prm);
820 SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z());
821 meshDS->SetNodeOnEdge(NM, shapeID, prm);
822 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast, NM);
823 meshDS->SetMeshElementOnShape(edge, shapeID);
826 SMDS_MeshEdge* edge = meshDS->AddEdge(idPrev, idLast);
827 meshDS->SetMeshElementOnShape(edge, shapeID);
831 // Edge is a degenerated Edge : We put n = 5 points on the edge.
832 const int NbPoints = 5;
833 double du = (l - f) / (NbPoints - 1);
834 //MESSAGE("************* Degenerated edge! *****************");
836 gp_Pnt P = BRep_Tool::Pnt(VFirst);
838 const SMDS_MeshNode * idPrev = idFirst;
839 for (int i = 2; i < NbPoints; i++) {
840 double param = f + (i - 1) * du;
841 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
843 // create medium node
844 double prm = param - du/2.;
845 SMDS_MeshNode * NM = meshDS->AddNode(P.X(), P.Y(), P.Z());
846 meshDS->SetNodeOnEdge(NM, shapeID, prm);
847 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node, NM);
848 meshDS->SetMeshElementOnShape(edge, shapeID);
851 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
852 meshDS->SetMeshElementOnShape(edge, shapeID);
854 meshDS->SetNodeOnEdge(node, shapeID, param);
858 // create medium node
859 double prm = l - du/2.;
860 SMDS_MeshNode * NM = meshDS->AddNode(P.X(), P.Y(), P.Z());
861 meshDS->SetNodeOnEdge(NM, shapeID, prm);
862 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast, NM);
863 meshDS->SetMeshElementOnShape(edge, shapeID);
866 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast);
867 meshDS->SetMeshElementOnShape(edge, shapeID);
873 //=============================================================================
875 * See comments in SMESH_Algo.cxx
877 //=============================================================================
879 const list <const SMESHDS_Hypothesis *> &
880 StdMeshers_Regular_1D::GetUsedHypothesis(SMESH_Mesh & aMesh,
881 const TopoDS_Shape & aShape,
882 const bool ignoreAuxiliary)
884 _usedHypList.clear();
887 SMESH_HypoFilter auxiliaryFilter, compatibleFilter;
888 auxiliaryFilter.Init( SMESH_HypoFilter::IsAuxiliary() );
889 const bool ignoreAux = true;
890 InitCompatibleHypoFilter( compatibleFilter, ignoreAux );
892 // get non-auxiliary assigned to aShape
893 int nbHyp = aMesh.GetHypotheses( aShape, compatibleFilter, _usedHypList, false );
897 // Check, if propagated from some other edge
898 if (aShape.ShapeType() == TopAbs_EDGE &&
899 aMesh.IsPropagatedHypothesis(aShape, _mainEdge))
901 // Propagation of 1D hypothesis from <aMainEdge> on this edge;
902 // get non-auxiliary assigned to _mainEdge
903 nbHyp = aMesh.GetHypotheses( _mainEdge, compatibleFilter, _usedHypList, true );
907 if (nbHyp == 0) // nothing propagated nor assigned to aShape
909 SMESH_Algo::GetUsedHypothesis( aMesh, aShape, ignoreAuxiliary );
910 nbHyp = _usedHypList.size();
914 // get auxiliary hyps from aShape
915 aMesh.GetHypotheses( aShape, auxiliaryFilter, _usedHypList, true );
917 if ( nbHyp > 1 && ignoreAuxiliary )
918 _usedHypList.clear(); //only one compatible non-auxiliary hypothesis allowed