+ }
+
+ if ( propagTypes.size() > 1 && aStatus == HYP_OK )
+ {
+ // detect concurrent Propagation hyps
+ _usedHypList.clear();
+ list< TopoDS_Shape > assignedTo;
+ if ( aMesh.GetHypotheses( aShape, propagFilter, _usedHypList, true, &assignedTo ) > 1 )
+ {
+ // find most simple shape and a hyp on it
+ int simpleShape = TopAbs_COMPOUND;
+ const SMESHDS_Hypothesis* localHyp = 0;
+ list< TopoDS_Shape >::iterator shape = assignedTo.begin();
+ list< const SMESHDS_Hypothesis *>::iterator hyp = _usedHypList.begin();
+ for ( ; shape != assignedTo.end(); ++shape )
+ if ( shape->ShapeType() > simpleShape )
+ {
+ simpleShape = shape->ShapeType();
+ localHyp = (*hyp);
+ }
+ // check if there a different hyp on simpleShape
+ shape = assignedTo.begin();
+ hyp = _usedHypList.begin();
+ for ( ; hyp != _usedHypList.end(); ++hyp, ++shape )
+ if ( shape->ShapeType() == simpleShape &&
+ !localHyp->IsSameName( **hyp ))
+ {
+ aStatus = HYP_INCOMPAT_HYPS;
+ return error( SMESH_Comment("Hypotheses of both \"")
+ << StdMeshers_Propagation::GetName() << "\" and \""
+ << StdMeshers_PropagOfDistribution::GetName()
+ << "\" types can't be applied to the same edge");
+ }
+ }
+ }
+
+ return ( aStatus == SMESH_Hypothesis::HYP_OK );
+}
+
+static bool computeParamByFunc(Adaptor3d_Curve& C3d,
+ double first, double last, double length,
+ bool theReverse, smIdType nbSeg, Function& func,
+ list<double>& theParams)
+{
+ // never do this way
+ //OSD::SetSignal( true );
+
+ if ( nbSeg <= 0 )
+ return false;
+
+ smIdType nbPnt = 1 + nbSeg;
+ vector<double> x( nbPnt, 0. );
+
+
+ const double eps = Min( 1E-4, 0.01 / double( nbSeg ));
+
+ if ( !buildDistribution( func, 0.0, 1.0, nbSeg, x, eps ))
+ return false;
+
+ // apply parameters in range [0,1] to the space of the curve
+ double prevU = first;
+ double sign = 1.;
+ if ( theReverse )
+ {
+ prevU = last;
+ sign = -1.;
+ }
+
+ for ( smIdType i = 1; i < nbSeg; i++ )
+ {
+ double curvLength = length * (x[i] - x[i-1]) * sign;
+ double tol = Min( Precision::Confusion(), curvLength / 100. );
+ GCPnts_AbscissaPoint Discret( tol, C3d, curvLength, prevU );
+ if ( !Discret.IsDone() )
+ return false;
+ double U = Discret.Parameter();
+ if ( U > first && U < last )
+ theParams.push_back( U );
+ else
+ return false;
+ prevU = U;
+ }
+ if ( theReverse )
+ theParams.reverse();
+
+ return true;
+}
+
+
+//================================================================================
+/*!
+ * \brief adjust internal node parameters so that the last segment length == an
+ * \param a1 - the first segment length
+ * \param an - the last segment length
+ * \param U1 - the first edge parameter
+ * \param Un - the last edge parameter
+ * \param length - the edge length
+ * \param C3d - the edge curve
+ * \param theParams - internal node parameters to adjust
+ * \param adjustNeighbors2an - to adjust length of segments next to the last one
+ * and not to remove parameters
+ */
+//================================================================================
+
+static void compensateError(double a1, double an,
+ double U1, double Un,
+ double length,
+ Adaptor3d_Curve& C3d,
+ list<double> & theParams,
+ bool adjustNeighbors2an = false)
+{
+ smIdType i, nPar = theParams.size();
+ if ( a1 + an <= length && nPar > 1 )
+ {
+ bool reverse = ( U1 > Un );
+ double tol = Min( Precision::Confusion(), 0.01 * an );
+ GCPnts_AbscissaPoint Discret( tol, C3d, reverse ? an : -an, Un );
+ if ( !Discret.IsDone() )
+ return;
+ double Utgt = Discret.Parameter(); // target value of the last parameter
+ list<double>::reverse_iterator itU = theParams.rbegin();
+ double Ul = *itU++; // real value of the last parameter
+ double dUn = Utgt - Ul; // parametric error of <an>
+ double dU = Abs( Ul - *itU ); // parametric length of the last but one segment
+ if ( Abs(dUn) <= 1e-3 * dU )
+ return;
+ if ( adjustNeighbors2an || Abs(dUn) < 0.5 * dU ) { // last segment is a bit shorter than it should
+ // move the last parameter to the edge beginning
+ }
+ else { // last segment is much shorter than it should -> remove the last param and
+ theParams.pop_back(); nPar--; // move the rest points toward the edge end
+ dUn = Utgt - theParams.back();
+ }
+
+ if ( !adjustNeighbors2an )
+ {
+ double q = dUn / ( Utgt - Un ); // (signed) factor of segment length change
+ for ( itU = theParams.rbegin(), i = 1; i < nPar; i++ ) {
+ double prevU = *itU;
+ (*itU) += dUn;
+ ++itU;
+ dUn = q * (*itU - prevU) * (prevU-U1)/(Un-U1);
+ }
+ }
+ else if ( nPar == 1 )
+ {
+ theParams.back() += dUn;
+ }
+ else
+ {
+ double q = dUn / double( nPar - 1 );
+ theParams.back() += dUn;
+ double sign = reverse ? -1 : 1;
+ double prevU = theParams.back();
+ itU = theParams.rbegin();
+ for ( ++itU, i = 2; i < nPar; ++itU, i++ ) {
+ double newU = *itU + dUn;
+ if ( newU*sign < prevU*sign ) {
+ prevU = *itU = newU;
+ dUn -= q;
+ }
+ else { // set U between prevU and next valid param
+ list<double>::reverse_iterator itU2 = itU;
+ ++itU2;
+ int nb = 2;
+ while ( (*itU2)*sign > prevU*sign ) {
+ ++itU2; ++nb;
+ }
+ dU = ( *itU2 - prevU ) / nb;
+ while ( itU != itU2 ) {
+ *itU += dU; ++itU;
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Class used to clean mesh on edges when 0D hyp modified.
+ * Common approach doesn't work when 0D algo is missing because the 0D hyp is
+ * considered as not participating in computation whereas it is used by 1D algo.
+ */
+//================================================================================
+
+// struct VertexEventListener : public SMESH_subMeshEventListener
+// {
+// VertexEventListener():SMESH_subMeshEventListener(0) // won't be deleted by submesh
+// {}
+// /*!
+// * \brief Clean mesh on edges
+// * \param event - algo_event or compute_event itself (of SMESH_subMesh)
+// * \param eventType - ALGO_EVENT or COMPUTE_EVENT (of SMESH_subMesh)
+// * \param subMesh - the submesh where the event occurs
+// */
+// void ProcessEvent(const int event, const int eventType, SMESH_subMesh* subMesh,
+// EventListenerData*, const SMESH_Hypothesis*)
+// {
+// if ( eventType == SMESH_subMesh::ALGO_EVENT) // all algo events
+// {
+// subMesh->ComputeStateEngine( SMESH_subMesh::MODIF_ALGO_STATE );
+// }
+// }
+// }; // struct VertexEventListener
+
+//=============================================================================
+/*!
+ * \brief Sets event listener to vertex submeshes
+ * \param subMesh - submesh where algo is set
+ *
+ * This method is called when a submesh gets HYP_OK algo_state.
+ * After being set, event listener is notified on each event of a submesh.
+ */
+//=============================================================================
+
+void StdMeshers_Regular_1D::SetEventListener(SMESH_subMesh* subMesh)
+{
+ StdMeshers_Propagation::SetPropagationMgr( subMesh );
+}
+
+//=============================================================================
+/*!
+ * \brief Do nothing
+ * \param subMesh - restored submesh
+ *
+ * This method is called only if a submesh has HYP_OK algo_state.
+ */
+//=============================================================================