#include <TopoDS_Wire.hxx>
#ifdef _DEBUG_
+//#define _MYDEBUG_
#include "SMESH_File.hxx"
#include "SMESH_Comment.hxx"
#endif
struct InPoint
{
- int _a, _b;
- double _param;
+ int _a, _b; // coordinates
+ double _param; // param on EDGE
InPoint(int x, int y, double param) : _a(x), _b(y), _param(param) {}
InPoint() : _a(0), _b(0), _param(0) {}
size_t index( const vector< InPoint >& inPoints ) const { return this - &inPoints[0]; }
bool operator==( const InPoint& other ) const { return _a == other._a && _b == other._b; }
+ bool operator==( const TVDVertex* v ) const { return ( Abs( _a - v->x() ) < 1. &&
+ Abs( _b - v->y() ) < 1. ); }
};
// -------------------------------------------------------------------------------------
// check if a TVDEdge begins at my end or ends at my start
inline bool InSegment::isConnected( const TVDEdge* edge )
{
- return ((Abs( edge->vertex0()->x() - _p1->_a ) < 1.&&
- Abs( edge->vertex0()->y() - _p1->_b ) < 1. ) ||
- (Abs( edge->vertex1()->x() - _p0->_a ) < 1.&&
- Abs( edge->vertex1()->y() - _p0->_b ) < 1. ));
+ return (( edge->vertex0() && edge->vertex1() )
+ &&
+ ((Abs( edge->vertex0()->x() - _p1->_a ) < 1.&&
+ Abs( edge->vertex0()->y() - _p1->_b ) < 1. ) ||
+ (Abs( edge->vertex1()->x() - _p0->_a ) < 1.&&
+ Abs( edge->vertex1()->y() - _p0->_b ) < 1. )));
}
// check if a MA TVDEdge is outside of a domain
// }
// -------------------------------------------------------------------------------------
-#ifdef _DEBUG_
+#ifdef _MYDEBUG_
// writes segments into a txt file readable by voronoi_visualizer
void inSegmentsToFile( vector< InSegment>& inSegments)
{
return;
const char* fileName = "/misc/dn25/salome/eap/salome/misc/Code/C++/MAdebug.txt";
SMESH_File file(fileName, false );
+ file.remove();
file.openForWriting();
SMESH_Comment text;
text << "0\n"; // nb points
if ( !edge->vertex1() )
cout << ") -> ( INF, INF";
else
- cout << ") -> (" << edge->vertex1()->x() << ", " << edge->vertex1()->y();
+ cout << ") -> ( " << edge->vertex1()->x() << ", " << edge->vertex1()->y();
cout << ")\t cell=" << edge->cell()
<< " iBnd=" << edge->color()
<< " twin=" << edge->twin()
namespace
{
const int theNoBrachID = 0; // std::numeric_limits<int>::max();
+ double theScale[2]; // scale used in bndSegsToMesh()
// -------------------------------------------------------------------------------------
/*!
if ( _edge ) // pass branch to an opposite BndSeg
{
size_t oppSegIndex = SMESH_MAT2d::Branch::getBndSegment( _edge->twin() );
- if ( oppSegIndex < bndSegs.size() /*&& bndSegs[ oppSegIndex ]._branchID == theNoBrachID*/ )
+ if ( oppSegIndex < bndSegs.size() && bndSegs[ oppSegIndex ]._branchID == theNoBrachID )
bndSegs[ oppSegIndex ]._branchID = -branchID;
}
}
//================================================================================
/*!
- * \brief Computes length of of TVDEdge
+ * \brief debug: to visually check found MA edges
+ */
+ //================================================================================
+
+ void bndSegsToMesh( const vector< BndSeg >& bndSegs )
+ {
+#ifdef _MYDEBUG_
+ if ( !getenv("bndSegsToMesh")) return;
+ map< const TVDVertex *, int > v2Node;
+ map< const TVDVertex *, int >::iterator v2n;
+ set< const TVDEdge* > addedEdges;
+
+ const char* fileName = "/misc/dn25/salome/eap/salome/misc/Code/C++/MAedges.py";
+ SMESH_File file(fileName, false );
+ file.remove();
+ file.openForWriting();
+ SMESH_Comment text;
+ text << "import salome, SMESH\n";
+ text << "salome.salome_init()\n";
+ text << "from salome.smesh import smeshBuilder\n";
+ text << "smesh = smeshBuilder.New(salome.myStudy)\n";
+ text << "m=smesh.Mesh()\n";
+ for ( size_t i = 0; i < bndSegs.size(); ++i )
+ {
+ if ( !bndSegs[i]._edge )
+ text << "# " << i << " NULL edge";
+ else if ( !bndSegs[i]._edge->vertex0() ||
+ !bndSegs[i]._edge->vertex1() )
+ text << "# " << i << " INFINITE edge";
+ else if ( addedEdges.insert( bndSegs[i]._edge ).second &&
+ addedEdges.insert( bndSegs[i]._edge->twin() ).second )
+ {
+ v2n = v2Node.insert( make_pair( bndSegs[i]._edge->vertex0(), v2Node.size() + 1 )).first;
+ int n0 = v2n->second;
+ if ( n0 == v2Node.size() )
+ text << "n" << n0 << " = m.AddNode( "
+ << bndSegs[i]._edge->vertex0()->x() / theScale[0] << ", "
+ << bndSegs[i]._edge->vertex0()->y() / theScale[1] << ", 0 )\n";
+
+ v2n = v2Node.insert( make_pair( bndSegs[i]._edge->vertex1(), v2Node.size() + 1 )).first;
+ int n1 = v2n->second;
+ if ( n1 == v2Node.size() )
+ text << "n" << n1 << " = m.AddNode( "
+ << bndSegs[i]._edge->vertex1()->x() / theScale[0] << ", "
+ << bndSegs[i]._edge->vertex1()->y() / theScale[1] << ", 0 )\n";
+
+ text << "e" << i << " = m.AddEdge([ n" << n0 << ", n" << n1 << " ])\n";
+ }
+ }
+ text << "\n";
+ file.write( text.c_str(), text.size() );
+ cout << "Write " << fileName << endl;
+#endif
+ }
+
+ //================================================================================
+ /*!
+ * \brief Computes length of a TVDEdge
*/
//================================================================================
gp_Pnt p, pPrev;
if ( !c3d.IsNull() )
pPrev = c3d->Value( f );
- for ( int i = 2; i <= discret.NbPoints(); i++ ) // skip the 1st point
- {
- double u = discret.Parameter(i);
- if ( !c3d.IsNull() )
+ if ( discret.NbPoints() > 2 )
+ for ( int i = 2; i <= discret.NbPoints(); i++ ) // skip the 1st point
{
- p = c3d->Value( u );
- int nbDiv = int( p.Distance( pPrev ) / minSegLen / theDiscrCoef );
- double dU = ( u - points.back()._u ) / nbDiv;
- for ( int iD = 1; iD < nbDiv; ++iD )
+ double u = discret.Parameter(i);
+ if ( !c3d.IsNull() )
{
- double uD = points.back()._u + dU;
- points.push_back( UVU( c2d->Value( uD ), uD ));
+ p = c3d->Value( u );
+ int nbDiv = int( p.Distance( pPrev ) / minSegLen / theDiscrCoef );
+ double dU = ( u - points.back()._u ) / nbDiv;
+ for ( int iD = 1; iD < nbDiv; ++iD )
+ {
+ double uD = points.back()._u + dU;
+ points.push_back( UVU( c2d->Value( uD ), uD ));
+ }
+ pPrev = p;
}
- pPrev = p;
+ points.push_back( UVU( c2d->Value( u ), u ));
+ uvBox.Add( points.back()._uv );
}
- points.push_back( UVU( c2d->Value( u ), u ));
- uvBox.Add( points.back()._uv );
- }
// if ( !c3d.IsNull() )
// {
// vector<double> params;
}
}
}
+ // debug
+ theScale[0] = scale[0];
+ theScale[1] = scale[1];
+
return true;
}
+ //================================================================================
+ /*!
+ * \brief Update a branch joined to another one
+ */
+ //================================================================================
+
+ void updateJoinedBranch( vector< const TVDEdge* > & branchEdges,
+ const size_t newID,
+ vector< BndSeg > & bndSegs,
+ const bool reverse)
+ {
+ if ( reverse )
+ {
+ for ( size_t i = 0; i < branchEdges.size(); ++i )
+ {
+ size_t seg1 = SMESH_MAT2d::Branch::getBndSegment( branchEdges[i] );
+ size_t seg2 = SMESH_MAT2d::Branch::getBndSegment( branchEdges[i]->twin() );
+ bndSegs[ seg1 ]._branchID /= bndSegs[ seg1 ].branchID();
+ bndSegs[ seg2 ]._branchID /= bndSegs[ seg2 ].branchID();
+ bndSegs[ seg1 ]._branchID *= -newID;
+ bndSegs[ seg2 ]._branchID *= -newID;
+ branchEdges[i] = branchEdges[i]->twin();
+ }
+ std::reverse( branchEdges.begin(), branchEdges.end() );
+ }
+ else
+ {
+ for ( size_t i = 0; i < branchEdges.size(); ++i )
+ {
+ size_t seg1 = SMESH_MAT2d::Branch::getBndSegment( branchEdges[i] );
+ size_t seg2 = SMESH_MAT2d::Branch::getBndSegment( branchEdges[i]->twin() );
+ bndSegs[ seg1 ]._branchID /= bndSegs[ seg1 ].branchID();
+ bndSegs[ seg2 ]._branchID /= bndSegs[ seg2 ].branchID();
+ bndSegs[ seg1 ]._branchID *= newID;
+ bndSegs[ seg2 ]._branchID *= newID;
+ }
+ }
+ }
+
//================================================================================
/*!
* \brief Create MA branches and FACE boundary data
//================================================================================
void makeMA( const TVD& vd,
+ const bool ignoreCorners,
vector< InPoint >& inPoints,
vector< InSegment > & inSegments,
vector< SMESH_MAT2d::Branch >& branch,
continue;
inPntChecked[ pInd ] = true;
- const TVDEdge* edge = // a TVDEdge passing through an end of inSeg
- is2nd ? maEdges.front()->prev() : maEdges.back()->next();
- while ( true )
+ const TVDEdge* maE = is2nd ? maEdges.front() : maEdges.back();
+ if ( inPnt == ( is2nd ? maE->vertex0() : maE->vertex1() ))
+ continue;
+ const TVDEdge* edge = // a secondary TVDEdge connecting inPnt and maE
+ is2nd ? maE->prev() : maE->next();
+ while ( inSeg.isConnected( edge ))
{
if ( edge->is_primary() ) break; // this should not happen
const TVDEdge* edge2 = edge->twin(); // we are in a neighbor cell, add MA edges to inPnt
inPoints[0]._edges.clear();
}
- // Divide InSegment's into BndSeg's
+ // Divide InSegment's into BndSeg's (so that each BndSeg corresponds to one MA edge)
vector< BndSeg > bndSegs;
bndSegs.reserve( inSegments.size() * 3 );
inPntChecked[ ip0 ] = false;
// segments of InSegment's
- size_t nbMaEdges = inSeg._edges.size();
+ const size_t nbMaEdges = inSeg._edges.size();
switch ( nbMaEdges ) {
case 0: // "around" circle center
bndSegs.push_back( BndSeg( &inSeg, 0, inSeg._p1->_param )); break;
case 1:
bndSegs.push_back( BndSeg( &inSeg, inSeg._edges.back(), inSeg._p1->_param )); break;
default:
- vector< double > len;
- len.push_back(0);
- for ( e = inSeg._edges.rbegin(); e != inSeg._edges.rend(); ++e )
- len.push_back( len.back() + length( *e ));
-
+ gp_XY inSegDir( inSeg._p1->_a - inSeg._p0->_a,
+ inSeg._p1->_b - inSeg._p0->_b );
+ const double inSegLen2 = inSegDir.SquareModulus();
e = inSeg._edges.rbegin();
- for ( size_t l = 1; l < len.size(); ++e, ++l )
+ for ( size_t iE = 1; iE < nbMaEdges; ++e, ++iE )
{
- double dl = len[l] / len.back();
- double u = dl * inSeg._p1->_param + ( 1. - dl ) * inSeg._p0->_param;
+ gp_XY toMA( (*e)->vertex0()->x() - inSeg._p0->_a,
+ (*e)->vertex0()->y() - inSeg._p0->_b );
+ double r = toMA * inSegDir / inSegLen2;
+ double u = r * inSeg._p1->_param + ( 1. - r ) * inSeg._p0->_param;
bndSegs.push_back( BndSeg( &inSeg, *e, u ));
}
+ bndSegs.push_back( BndSeg( &inSeg, *e, inSeg._p1->_param ));
}
// segments around 2nd concave point
size_t ip1 = inSeg._p1->index( inPoints );
for ( size_t i = 0; i < bndSegs.size(); ++i )
bndSegs[i].setIndexToEdge( i );
+ bndSegsToMesh( bndSegs ); // debug: visually check found MA edges
+
// Find TVDEdge's of Branches and associate them with bndSegs
size_t i1st = 0;
while ( i1st < bndSegs.size() && !bndSegs[i1st].hasOppositeEdge( noEdgeID ))
++i1st;
- bndSegs[i1st].setBranch( branchID, bndSegs ); // set to i-th and the opposite bndSeg
+ bndSegs[i1st].setBranch( branchID, bndSegs ); // set to the i-th and to the opposite bndSeg
branchEdges[ branchID ].push_back( bndSegs[i1st]._edge );
for ( size_t i = i1st+1; i < bndSegs.size(); ++i )
endType.insert( make_pair( bndSegs[i]._edge->vertex1(),
SMESH_MAT2d::BE_BRANCH_POINT ));
}
- bndSegs[i].setBranch( branchID, bndSegs ); // set to i-th and the opposite bndSeg
+ bndSegs[i].setBranch( branchID, bndSegs ); // set to i-th and to the opposite bndSeg
if ( bndSegs[i].hasOppositeEdge( noEdgeID ))
branchEdges[ bndSegs[i].branchID() ].push_back( bndSegs[i]._edge );
}
br2.clear();
}
+ // remove branches ending at BE_ON_VERTEX
+
+ vector<bool> isBranchRemoved( branchEdges.size(), false );
+
+ if ( ignoreCorners && branchEdges.size() > 2 && !branchEdges[2].empty() )
+ {
+ // find branches to remove
+ map< const TVDVertex*, SMESH_MAT2d::BranchEndType >::iterator v2et;
+ for ( size_t iB = 1; iB < branchEdges.size(); ++iB )
+ {
+ if ( branchEdges[iB].empty() )
+ continue;
+ const TVDVertex* v0 = branchEdges[iB][0]->vertex1();
+ const TVDVertex* v1 = branchEdges[iB].back()->vertex0();
+ v2et = endType.find( v0 );
+ if ( v2et != endType.end() && v2et->second == SMESH_MAT2d::BE_ON_VERTEX )
+ isBranchRemoved[ iB ] = true;
+ v2et = endType.find( v1 );
+ if ( v2et != endType.end() && v2et->second == SMESH_MAT2d::BE_ON_VERTEX )
+ isBranchRemoved[ iB ] = true;
+ }
+ // try to join not removed branches into one
+ for ( size_t iB = 1; iB < branchEdges.size(); ++iB )
+ {
+ if ( branchEdges[iB].empty() || isBranchRemoved[iB] )
+ continue;
+ const TVDVertex* v0 = branchEdges[iB][0]->vertex1();
+ const TVDVertex* v1 = branchEdges[iB].back()->vertex0();
+ v2et = endType.find( v0 );
+ if ( v2et == endType.end() || v2et->second != SMESH_MAT2d::BE_BRANCH_POINT )
+ v0 = 0;
+ v2et = endType.find( v1 );
+ if ( v2et == endType.end() || v2et->second != SMESH_MAT2d::BE_BRANCH_POINT )
+ v1 = 0;
+ if ( !v0 && !v1 )
+ continue;
+
+ size_t iBrToJoin = 0;
+ for ( size_t iB2 = 1; iB2 < branchEdges.size(); ++iB2 )
+ {
+ if ( branchEdges[iB2].empty() || isBranchRemoved[iB2] || iB == iB2 )
+ continue;
+ const TVDVertex* v02 = branchEdges[iB2][0]->vertex1();
+ const TVDVertex* v12 = branchEdges[iB2].back()->vertex0();
+ if ( v0 == v02 || v0 == v12 || v1 == v02 || v1 == v12 )
+ {
+ if ( iBrToJoin > 0 )
+ {
+ iBrToJoin = 0;
+ break; // more than 2 not removed branches meat at a TVDVertex
+ }
+ iBrToJoin = iB2;
+ }
+ }
+ if ( iBrToJoin > 0 )
+ {
+ vector<const TVDEdge*>& branch = branchEdges[ iBrToJoin ];
+ const TVDVertex* v02 = branch[0]->vertex1();
+ const TVDVertex* v12 = branch.back()->vertex0();
+ updateJoinedBranch( branch, iB, bndSegs, /*reverse=*/(v0 == v02 || v1 == v12 ));
+ if ( v0 == v02 || v0 == v12 )
+ branchEdges[iB].insert( branchEdges[iB].begin(), branch.begin(), branch.end() );
+ else
+ branchEdges[iB].insert( branchEdges[iB].end(), branch.begin(), branch.end() );
+ branch.clear();
+ }
+ } // loop on branchEdges
+ } // if ( ignoreCorners )
+
// associate branchIDs and the input branch vector (arg)
- vector< const SMESH_MAT2d::Branch* > branchByID( branchEdges.size() );
+ vector< SMESH_MAT2d::Branch* > branchByID( branchEdges.size(), 0 );
int nbBranches = 0;
for ( size_t i = 0; i < branchEdges.size(); ++i )
{
nbBranches += ( !branchEdges[i].empty() );
}
branch.resize( nbBranches );
- for ( size_t iBr = 0, brID = 0; brID < branchEdges.size(); ++brID )
+ size_t iBr = 0;
+ for ( size_t brID = 1; brID < branchEdges.size(); ++brID ) // 1st - not removed
+ {
+ if ( !branchEdges[ brID ].empty() && !isBranchRemoved[ brID ])
+ branchByID[ brID ] = & branch[ iBr++ ];
+ }
+ for ( size_t brID = 1; brID < branchEdges.size(); ++brID ) // then - removed
{
- if ( !branchEdges[ brID ].empty() )
+ if ( !branchEdges[ brID ].empty() && isBranchRemoved[ brID ])
branchByID[ brID ] = & branch[ iBr++ ];
}
{
edgeInd += dInd;
- if ( edgeInd < 0 ||
- edgeInd >= (int) branchEdges[ brID ].size() ||
- branchEdges[ brID ][ edgeInd ] != bndSegs[ i ]._edge )
+ if (( edgeInd < 0 ||
+ edgeInd >= (int) branchEdges[ brID ].size() ) ||
+ ( branchEdges[ brID ][ edgeInd ] != bndSegs[ i ]._edge &&
+ branchEdges[ brID ][ edgeInd ]->twin() != bndSegs[ i ]._edge ))
{
- if ( bndSegs[ i ]._branchID < 0 &&
- branchEdges[ brID ].back() == bndSegs[ i ]._edge )
+ if ( bndSegs[ i ]._branchID < 0 )
{
- edgeInd = branchEdges[ brID ].size() - 1;
dInd = -1;
+ for ( edgeInd = branchEdges[ brID ].size() - 1; edgeInd > 0; --edgeInd )
+ if ( branchEdges[ brID ][ edgeInd ]->twin() == bndSegs[ i ]._edge )
+ break;
}
- else if ( bndSegs[ i ]._branchID > 0 &&
- branchEdges[ brID ].front() == bndSegs[ i ]._edge )
+ else // bndSegs[ i ]._branchID > 0
{
- edgeInd = 0;
dInd = +1;
- }
- else
- {
for ( edgeInd = 0; edgeInd < branchEdges[ brID ].size(); ++edgeInd )
if ( branchEdges[ brID ][ edgeInd ] == bndSegs[ i ]._edge )
break;
- dInd = bndSegs[ i ]._branchID > 0 ? +1 : -1;
}
}
}
{
// no MA edge, bndSeg corresponds to an end point of a branch
if ( bndPoints._maEdges.empty() )
- {
- // should not get here according to algo design
edgeInd = 0;
- }
else
- {
edgeInd = branchEdges[ brID ].size();
- dInd = bndSegs[ i ]._branchID > 0 ? +1 : -1;
- }
+ dInd = bndSegs[ i ]._branchID > 0 ? +1 : -1;
}
bndPoints._maEdges.push_back( make_pair( br, ( 1 + edgeInd ) * dInd ));
iSeg = iSegEnd;
- } // loop on all bndSegs
+ } // loop on all bndSegs to construct Boundary
+ // Initialize branches
+ // find a not removed branch
+ size_t iBrNorRemoved = 0;
+ for ( size_t brID = 1; brID < branchEdges.size(); ++brID )
+ if ( !branchEdges[brID].empty() && !isBranchRemoved[brID] )
+ {
+ iBrNorRemoved = brID;
+ break;
+ }
// fill the branches with MA edges
- for ( size_t iBr = 0, brID = 0; brID < branchEdges.size(); ++brID )
+ for ( size_t brID = 1; brID < branchEdges.size(); ++brID )
if ( !branchEdges[brID].empty() )
{
- branch[ iBr ].init( branchEdges[brID], & boundary, endType );
- iBr++;
+ branchByID[ brID ]->init( branchEdges[brID], & boundary, endType );
+ }
+ // mark removed branches
+ for ( size_t brID = 1; brID < branchEdges.size(); ++brID )
+ if ( isBranchRemoved[brID] && iBrNorRemoved > 0 )
+ {
+ SMESH_MAT2d::Branch* branch = branchByID[ brID ];
+ SMESH_MAT2d::Branch* mainBranch = branchByID[ iBrNorRemoved ];
+ bool is1stBrPnt = ( branch->getEnd(0)->_type == SMESH_MAT2d::BE_BRANCH_POINT );
+ const TVDVertex* branchVextex =
+ is1stBrPnt ? branch->getEnd(0)->_vertex : branch->getEnd(1)->_vertex;
+ SMESH_MAT2d::BranchPoint bp = mainBranch->getPoint( branchVextex );
+ branch->setRemoved( bp );
}
// set branches to branch ends
for ( size_t i = 0; i < branch.size(); ++i )
- branch[i].setBranchesToEnds( branch );
+ if ( !branch[i].isRemoved() )
+ branch[i].setBranchesToEnds( branch );
// fill branchPnt arg
map< const TVDVertex*, const SMESH_MAT2d::BranchEnd* > v2end;
if ( !makeInputData( face, edges, minSegLen, inPoints, inSegments, _scale ))
return;
- //inSegmentsToFile( inSegments );
+ inSegmentsToFile( inSegments );
// build voronoi diagram
construct_voronoi( inSegments.begin(), inSegments.end(), &_vd );
// make MA data
- makeMA( _vd, inPoints, inSegments, _branch, _branchPnt, _boundary );
+ makeMA( _vd, ignoreCorners, inPoints, inSegments, _branch, _branchPnt, _boundary );
+
+ // count valid branches
+ _nbBranches = _branch.size();
+ for ( size_t i = 0; i < _branch.size(); ++i )
+ if ( _branch[i].isRemoved() )
+ --_nbBranches;
+}
+
+//================================================================================
+/*!
+ * \brief Returns the i-th branch
+ */
+//================================================================================
+
+const SMESH_MAT2d::Branch* SMESH_MAT2d::MedialAxis::getBranch(size_t i) const
+{
+ return i < _nbBranches ? &_branch[i] : 0;
}
//================================================================================
*/
//================================================================================
-void SMESH_MAT2d::MedialAxis::getPoints( const Branch& branch,
+void SMESH_MAT2d::MedialAxis::getPoints( const Branch* branch,
std::vector< gp_XY >& points) const
{
- branch.getPoints( points, _scale );
+ branch->getPoints( points, _scale );
}
//================================================================================
/*!
* \brief Returns a BranchPoint corresponding to a given point on a geom EDGE
- * \param [in] iGeomEdge - index of geom EDGE within a vector passed at construction
+ * \param [in] iEdge - index of geom EDGE within a vector passed at MA construction
* \param [in] u - parameter of the point on EDGE curve
* \param [out] p - the found BranchPoint
* \return bool - is OK
return false;
const BndPoints& points = _pointsPerEdge[ iEdge ];
- const bool edgeReverse = ( points._params[0] > points._params.back() );
+ const bool edgeReverse = ( points._params[0] > points._params.back() );
if ( u < ( edgeReverse ? points._params.back() : points._params[0] ))
u = edgeReverse ? points._params.back() : points._params[0];
while ( points._params[i ] > u ) --i;
while ( points._params[i+1] < u ) ++i;
}
+
double edgeParam = ( u - points._params[i] ) / ( points._params[i+1] - points._params[i] );
+ if ( !points._maEdges[ i ].second ) // no branch at the EDGE end, look for a closest branch
+ {
+ if ( i < points._maEdges.size() / 2 ) // near 1st point
+ {
+ while ( i < points._maEdges.size()-1 && !points._maEdges[ i ].second )
+ ++i;
+ edgeParam = edgeReverse;
+ }
+ else // near last point
+ {
+ while ( i > 0 && !points._maEdges[ i ].second )
+ --i;
+ edgeParam = !edgeReverse;
+ }
+ }
const std::pair< const Branch*, int >& maE = points._maEdges[ i ];
bool maReverse = ( maE.second < 0 );
- p._branch = maE.first;
- p._iEdge = maE.second - 1; // countered from 1 to store sign
- p._edgeParam = maReverse ? ( 1. - edgeParam ) : edgeParam;
+ p._branch = maE.first;
+ p._iEdge = ( maReverse ? -maE.second : maE.second ) - 1; // countered from 1 to store sign
+ p._edgeParam = ( maE.first && maReverse ) ? ( 1. - edgeParam ) : edgeParam;
return true;
}
*/
//================================================================================
-bool SMESH_MAT2d::Boundary::IsConcaveSegment( std::size_t iEdge, std::size_t iSeg ) const
+bool SMESH_MAT2d::Boundary::isConcaveSegment( std::size_t iEdge, std::size_t iSeg ) const
{
if ( iEdge >= _pointsPerEdge.size() || _pointsPerEdge[iEdge]._params.empty() )
return false;
const BndPoints& points = _pointsPerEdge[ iEdge ];
- if ( points._params.size() >= iSeg+1 )
+ if ( points._params.size() <= iSeg+1 )
+ return false;
+
+ return Abs( points._params[ iSeg ] - points._params[ iSeg+1 ]) < 1e-20;
+}
+
+//================================================================================
+/*!
+ * \brief Moves (changes _param) a given BoundaryPoint to a closest EDGE end
+ */
+//================================================================================
+
+bool SMESH_MAT2d::Boundary::moveToClosestEdgeEnd( BoundaryPoint& bp ) const
+{
+ if ( bp._edgeIndex >= _pointsPerEdge.size() )
return false;
- return Abs( points._params[ iEdge ] - points._params[ iEdge+1 ]) < 1e-20;
+ const BndPoints& points = _pointsPerEdge[ bp._edgeIndex ];
+ if ( bp._param - points._params[0] < points._params.back() - bp._param )
+ bp._param = points._params[0];
+ else
+ bp._param = points._params.back();
+
+ return true;
}
//================================================================================
//================================================================================
/*!
- * \brief fill BranchEnd::_branches of its ends
+ * \brief fills BranchEnd::_branches of its ends
*/
//================================================================================
}
}
+//================================================================================
+/*!
+ * \brief returns a BranchPoint corresponding to a TVDVertex
+ */
+//================================================================================
+
+SMESH_MAT2d::BranchPoint SMESH_MAT2d::Branch::getPoint( const TVDVertex* vertex ) const
+{
+ BranchPoint p;
+ p._branch = this;
+ p._iEdge = 0;
+
+ if ( vertex == _maEdges[0]->vertex1() )
+ {
+ p._edgeParam = 0;
+ }
+ else
+ {
+ for ( ; p._iEdge < _maEdges.size(); ++p._iEdge )
+ if ( vertex == _maEdges[ p._iEdge ]->vertex0() )
+ {
+ p._edgeParam = _params[ p._iEdge ];
+ break;
+ }
+ }
+ return p;
+}
+
+//================================================================================
+/*!
+ * \brief Sets a proxy point for a removed branch
+ * \param [in] proxyPoint - a point of another branch to which all points of this
+ * branch are mapped
+ */
+//================================================================================
+
+void SMESH_MAT2d::Branch::setRemoved( const BranchPoint& proxyPoint )
+{
+ _proxyPoint = proxyPoint;
+}
+
//================================================================================
/*!
* \brief Returns points on two EDGEs, equidistant from a given point of this Branch
{
if ( param < _params[0] || param > _params.back() )
return false;
-
+
// look for an index of a MA edge by param
double ip = param * _params.size();
size_t i = size_t( Min( int( _maEdges.size()-1), int( ip )));
BoundaryPoint& bp1,
BoundaryPoint& bp2 ) const
{
+ if ( isRemoved() )
+ return _proxyPoint._branch->getBoundaryPoints( _proxyPoint, bp1, bp2 );
+
if ( iMAEdge > _maEdges.size() )
return false;
+ if ( iMAEdge == _maEdges.size() )
+ iMAEdge = _maEdges.size() - 1;
size_t iGeom1 = getGeomEdge( _maEdges[ iMAEdge ] );
size_t iGeom2 = getGeomEdge( _maEdges[ iMAEdge ]->twin() );
bool SMESH_MAT2d::Branch::getParameter(const BranchPoint & p, double & u ) const
{
+ if ( this != p._branch && p._branch )
+ return p._branch->getParameter( p, u );
+
+ if ( isRemoved() )
+ return _proxyPoint._branch->getParameter( _proxyPoint, u );
+
if ( p._iEdge > _params.size()-1 )
return false;
+ if ( p._iEdge == _params.size()-1 )
+ return u = 1.;
u = ( _params[ p._iEdge ] * ( 1 - p._edgeParam ) +
_params[ p._iEdge+1 ] * p._edgeParam );
size_t iSeg1 = getBndSegment( maEdges[ i-1 ] );
size_t iSeg2 = getBndSegment( maEdges[ i ] );
- bool isConcaPrev = _boundary->IsConcaveSegment( edgeIDs1.back(), iSeg1 );
- bool isConcaNext = _boundary->IsConcaveSegment( ie1, iSeg2 );
+ bool isConcaPrev = _boundary->isConcaveSegment( edgeIDs1.back(), iSeg1 );
+ bool isConcaNext = _boundary->isConcaveSegment( ie1, iSeg2 );
if ( !isConcaNext && !isConcaPrev )
return false;
while ( iNext < maEdges.size() )
{
iSeg2 = getBndSegment( maEdges[ iNext ] );
- if ( _boundary->IsConcaveSegment( ie1, iSeg2 ))
+ if ( _boundary->isConcaveSegment( ie1, iSeg2 ))
++iNext;
else
break;
}
if ( vertexFound )
{
- i = --iNext;
+ iPrev = i = --iNext; // not to add a BP in the moddle
isConcaveV = true;
}
}
while ( iPrev-1 >= 0 )
{
iSeg1 = getBndSegment( maEdges[ iPrev-1 ] );
- if ( _boundary->IsConcaveSegment( edgeIDs1.back(), iSeg1 ))
+ if ( _boundary->isConcaveSegment( edgeIDs1.back(), iSeg1 ))
--iPrev;
else
break;
if ( iPrev < i-1 || iNext > i )
{
// no VERTEX on the opposite EDGE, put the Branch Point in the middle
- double par1 = _params[ iPrev ], par2 = _params[ iNext ];
+ double par1 = _params[ iPrev+1 ], par2 = _params[ iNext ];
double midPar = 0.5 * ( par1 + par2 );
divisionPnt._iEdge = iPrev;
while ( _params[ divisionPnt._iEdge + 1 ] < midPar )