return nbRemoved;
}
+ //================================================================================
+ /*!
+ * Consider continuous straight EDGES as one side - mark them to unite
+ */
+ //================================================================================
+
+ int countNbSides( const Prism_3D::TPrismTopo & thePrism,
+ vector<int> & nbUnitePerEdge )
+ {
+ int nbEdges = thePrism.myNbEdgesInWires.front(); // nb outer edges
+ int nbSides = nbEdges;
+
+ list< TopoDS_Edge >::const_iterator edgeIt = thePrism.myBottomEdges.begin();
+ std::advance( edgeIt, nbEdges-1 );
+ TopoDS_Edge prevE = *edgeIt;
+ bool isPrevStraight = SMESH_Algo::isStraight( prevE );
+ int iPrev = nbEdges - 1;
+
+ int iUnite = -1; // the first of united EDGEs
+
+ edgeIt = thePrism.myBottomEdges.begin();
+ for ( int iE = 0; iE < nbEdges; ++iE, ++edgeIt )
+ {
+ const TopoDS_Edge& curE = *edgeIt;
+ const bool isCurStraight = SMESH_Algo::isStraight( curE );
+ if ( isPrevStraight && isCurStraight && SMESH_Algo::IsContinuous( prevE, curE ))
+ {
+ if ( iUnite < 0 )
+ iUnite = iPrev;
+ nbUnitePerEdge[ iUnite ]++;
+ nbUnitePerEdge[ iE ] = -1;
+ --nbSides;
+ }
+ else
+ {
+ iUnite = -1;
+ }
+ prevE = curE;
+ isPrevStraight = isCurStraight;
+ iPrev = iE;
+ }
+
+ return nbSides;
+ }
+
+ void pointsToPython(const std::vector<gp_XYZ>& p)
+ {
+#ifdef _DEBUG_
+ for ( int i = SMESH_Block::ID_V000; i < p.size(); ++i )
+ {
+ cout << "mesh.AddNode( " << p[i].X() << ", "<< p[i].Y() << ", "<< p[i].Z() << ") # " << i <<" " ;
+ SMESH_Block::DumpShapeID( i, cout ) << endl;
+ }
+#endif
+ }
} // namespace
//=======================================================================
list< TopoDS_Edge >::iterator edge = thePrism.myBottomEdges.begin();
std::list< int >::iterator nbE = thePrism.myNbEdgesInWires.begin();
int iE = 0;
+ double f,l;
while ( edge != thePrism.myBottomEdges.end() )
{
++iE;
- if ( BRep_Tool::Degenerated( *edge ))
+ if ( BRep_Tool::Curve( *edge, f,l ).IsNull() )
{
edge = thePrism.myBottomEdges.erase( edge );
--iE;
if ( !SMESH_Block::ShellPoint( params, myShapeXYZ, coords ))
return toSM( error("Can't compute coordinates by normalized parameters"));
+ // if ( !meshDS->MeshElements( volumeID ) ||
+ // meshDS->MeshElements( volumeID )->NbNodes() == 0 )
+ // pointsToPython(myShapeXYZ);
SHOWYXZ("TOPFacePoint ",myShapeXYZ[ ID_TOP_FACE]);
SHOWYXZ("BOT Node "<< tBotNode.myNode->GetID(),gpXYZ(tBotNode.myNode));
SHOWYXZ("ShellPoint ",coords);
myParam2ColumnMaps.resize( thePrism.myBottomEdges.size() ); // total nb edges
size_t iE, nbEdges = thePrism.myNbEdgesInWires.front(); // nb outer edges
- vector< double > edgeLength( nbEdges );
+ vector< double > edgeLength( nbEdges );
multimap< double, int > len2edgeMap;
+ // for each EDGE: either split into several parts, or join with several next EDGEs
+ vector<int> nbSplitPerEdge( nbEdges, 0 );
+ vector<int> nbUnitePerEdge( nbEdges, 0 ); // -1 means "joined to a previous"
+
+ // consider continuous straight EDGEs as one side
+ const int nbSides = countNbSides( thePrism, nbUnitePerEdge );
+
list< TopoDS_Edge >::const_iterator edgeIt = thePrism.myBottomEdges.begin();
for ( iE = 0; iE < nbEdges; ++iE, ++edgeIt )
{
edgeLength[ iE ] = SMESH_Algo::EdgeLength( *edgeIt );
- if ( nbEdges < NB_WALL_FACES ) // fill map used to split faces
- {
- SMESHDS_SubMesh* smDS = meshDS->MeshElements( *edgeIt);
- if ( !smDS )
- return error(COMPERR_BAD_INPUT_MESH, TCom("Null submesh on the edge #")
- << MeshDS()->ShapeToIndex( *edgeIt ));
- len2edgeMap.insert( make_pair( edgeLength[ iE ], iE ));
- }
+ if ( nbSides < NB_WALL_FACES ) // fill map used to split faces
+ len2edgeMap.insert( make_pair( edgeLength[ iE ], iE )); // sort edges by length
}
// Load columns of internal edges (forming holes)
// and fill map ShapeIndex to TParam2ColumnMap for them
// Create 4 wall faces of a block
// -------------------------------
- if ( nbEdges <= NB_WALL_FACES ) // ************* Split faces if necessary
+ if ( nbSides <= NB_WALL_FACES ) // ************* Split faces if necessary
{
- map< int, int > iE2nbSplit;
- if ( nbEdges != NB_WALL_FACES ) // define how to split
+ if ( nbSides != NB_WALL_FACES ) // define how to split
{
if ( len2edgeMap.size() != nbEdges )
RETURN_BAD_RESULT("Uniqueness of edge lengths not assured");
double midLen = ( len2edgeMap.size() == 1 ) ? 0 : midLen_i->first;
switch ( nbEdges ) {
case 1: // 0-th edge is split into 4 parts
- iE2nbSplit.insert( make_pair( 0, 4 )); break;
+ nbSplitPerEdge[ 0 ] = 4;
+ break;
case 2: // either the longest edge is split into 3 parts, or both edges into halves
if ( maxLen / 3 > midLen / 2 ) {
- iE2nbSplit.insert( make_pair( maxLen_i->second, 3 ));
+ nbSplitPerEdge[ maxLen_i->second ] = 3;
}
else {
- iE2nbSplit.insert( make_pair( maxLen_i->second, 2 ));
- iE2nbSplit.insert( make_pair( midLen_i->second, 2 ));
+ nbSplitPerEdge[ maxLen_i->second ] = 2;
+ nbSplitPerEdge[ midLen_i->second ] = 2;
}
break;
case 3:
- // split longest into halves
- iE2nbSplit.insert( make_pair( maxLen_i->second, 2 ));
+ if ( nbSides == 2 )
+ // split longest into 3 parts
+ nbSplitPerEdge[ maxLen_i->second ] = 3;
+ else
+ // split longest into halves
+ nbSplitPerEdge[ maxLen_i->second ] = 2;
}
}
- // Create TSideFace's
- int iSide = 0;
- list< TopoDS_Edge >::const_iterator botE = thePrism.myBottomEdges.begin();
- for ( iE = 0; iE < nbEdges; ++iE, ++botE )
+ }
+ else // **************************** Unite faces
+ {
+ int nbExraFaces = nbSides - 3; // nb of faces to fuse
+ for ( iE = 0; iE < nbEdges; ++iE )
{
- TFaceQuadStructPtr quad = thePrism.myWallQuads[ iE ].front();
- // split?
- map< int, int >::iterator i_nb = iE2nbSplit.find( iE );
- if ( i_nb != iE2nbSplit.end() ) {
- // split!
- int nbSplit = i_nb->second;
- vector< double > params;
- splitParams( nbSplit, &myParam2ColumnMaps[ iE ], params );
- const bool isForward =
- StdMeshers_PrismAsBlock::IsForwardEdge( myHelper->GetMeshDS(),
- myParam2ColumnMaps[iE],
- *botE, SMESH_Block::ID_Fx0z );
- for ( int i = 0; i < nbSplit; ++i ) {
- double f = ( isForward ? params[ i ] : params[ nbSplit - i-1 ]);
- double l = ( isForward ? params[ i+1 ] : params[ nbSplit - i ]);
- TSideFace* comp = new TSideFace( *mesh, wallFaceIds[ iSide ],
- thePrism.myWallQuads[ iE ], *botE,
- &myParam2ColumnMaps[ iE ], f, l );
- mySide->SetComponent( iSide++, comp );
- }
+ if ( nbUnitePerEdge[ iE ] < 0 )
+ continue;
+ // look for already united faces
+ for ( int i = iE; i < iE + nbExraFaces; ++i )
+ {
+ if ( nbUnitePerEdge[ i ] > 0 ) // a side including nbUnitePerEdge[i]+1 edge
+ nbExraFaces += nbUnitePerEdge[ i ];
+ nbUnitePerEdge[ i ] = -1;
}
- else {
+ nbUnitePerEdge[ iE ] = nbExraFaces;
+ break;
+ }
+ }
+
+ // Create TSideFace's
+ int iSide = 0;
+ list< TopoDS_Edge >::const_iterator botE = thePrism.myBottomEdges.begin();
+ for ( iE = 0; iE < nbEdges; ++iE, ++botE )
+ {
+ TFaceQuadStructPtr quad = thePrism.myWallQuads[ iE ].front();
+ const int nbSplit = nbSplitPerEdge[ iE ];
+ const int nbExraFaces = nbUnitePerEdge[ iE ] + 1;
+ if ( nbSplit > 0 ) // split
+ {
+ vector< double > params;
+ splitParams( nbSplit, &myParam2ColumnMaps[ iE ], params );
+ const bool isForward =
+ StdMeshers_PrismAsBlock::IsForwardEdge( myHelper->GetMeshDS(),
+ myParam2ColumnMaps[iE],
+ *botE, SMESH_Block::ID_Fx0z );
+ for ( int i = 0; i < nbSplit; ++i ) {
+ double f = ( isForward ? params[ i ] : params[ nbSplit - i-1 ]);
+ double l = ( isForward ? params[ i+1 ] : params[ nbSplit - i ]);
TSideFace* comp = new TSideFace( *mesh, wallFaceIds[ iSide ],
thePrism.myWallQuads[ iE ], *botE,
- &myParam2ColumnMaps[ iE ]);
+ &myParam2ColumnMaps[ iE ], f, l );
mySide->SetComponent( iSide++, comp );
}
}
- }
- else { // **************************** Unite faces
-
- // unite first faces
- int nbExraFaces = nbEdges - 3;
- int iSide = 0, iE;
- double u0 = 0, sumLen = 0;
- for ( iE = 0; iE < nbExraFaces; ++iE )
- sumLen += edgeLength[ iE ];
-
- vector< TSideFace* > components( nbExraFaces );
- vector< pair< double, double> > params( nbExraFaces );
- list< TopoDS_Edge >::const_iterator botE = thePrism.myBottomEdges.begin();
- for ( iE = 0; iE < nbExraFaces; ++iE, ++botE )
+ else if ( nbExraFaces > 1 ) // unite
{
- components[ iE ] = new TSideFace( *mesh, wallFaceIds[ iSide ],
- thePrism.myWallQuads[ iE ], *botE,
- &myParam2ColumnMaps[ iE ]);
- double u1 = u0 + edgeLength[ iE ] / sumLen;
- params[ iE ] = make_pair( u0 , u1 );
- u0 = u1;
+ double u0 = 0, sumLen = 0;
+ for ( int i = iE; i < iE + nbExraFaces; ++i )
+ sumLen += edgeLength[ i ];
+
+ vector< TSideFace* > components( nbExraFaces );
+ vector< pair< double, double> > params( nbExraFaces );
+ bool endReached = false;
+ for ( int i = 0; i < nbExraFaces; ++i, ++botE, ++iE )
+ {
+ if ( iE == nbEdges )
+ {
+ endReached = true;
+ botE = thePrism.myBottomEdges.begin();
+ iE = 0;
+ }
+ components[ i ] = new TSideFace( *mesh, wallFaceIds[ iSide ],
+ thePrism.myWallQuads[ iE ], *botE,
+ &myParam2ColumnMaps[ iE ]);
+ double u1 = u0 + edgeLength[ iE ] / sumLen;
+ params[ i ] = make_pair( u0 , u1 );
+ u0 = u1;
+ }
+ TSideFace* comp = new TSideFace( *mesh, components, params );
+ mySide->SetComponent( iSide++, comp );
+ if ( endReached )
+ break;
+ --iE; // for increment in an external loop on iE
+ --botE;
}
- mySide->SetComponent( iSide++, new TSideFace( *mesh, components, params ));
-
- // fill the rest faces
- for ( ; iE < nbEdges; ++iE, ++botE )
+ else if ( nbExraFaces < 0 ) // skip already united face
+ {
+ }
+ else // use as is
{
TSideFace* comp = new TSideFace( *mesh, wallFaceIds[ iSide ],
thePrism.myWallQuads[ iE ], *botE,
}
}
-// gp_XYZ testPar(0.25, 0.25, 0), testCoord;
-// if ( !FacePoint( ID_BOT_FACE, testPar, testCoord ))
-// RETURN_BAD_RESULT("TEST FacePoint() FAILED");
-// SHOWYXZ("IN TEST PARAM" , testPar);
-// SHOWYXZ("OUT TEST CORD" , testCoord);
-// if ( !ComputeParameters( testCoord, testPar , ID_BOT_FACE))
-// RETURN_BAD_RESULT("TEST ComputeParameters() FAILED");
-// SHOWYXZ("OUT TEST PARAM" , testPar);
-
+ // double _u[]={ 0.1, 0.1, 0.9, 0.9 };
+ // double _v[]={ 0.1, 0.9, 0.1, 0.9, };
+ // for ( int i = 0; i < 4; ++i )
+ // {
+ // //gp_XYZ testPar(0.25, 0.25, 0), testCoord;
+ // gp_XYZ testPar(_u[i], _v[i], 0), testCoord;
+ // if ( !FacePoint( ID_BOT_FACE, testPar, testCoord ))
+ // RETURN_BAD_RESULT("TEST FacePoint() FAILED");
+ // SHOWYXZ("IN TEST PARAM" , testPar);
+ // SHOWYXZ("OUT TEST CORD" , testCoord);
+ // if ( !ComputeParameters( testCoord, testPar , ID_BOT_FACE))
+ // RETURN_BAD_RESULT("TEST ComputeParameters() FAILED");
+ // SHOWYXZ("OUT TEST PARAM" , testPar);
+ // }
return true;
}
myIsForward = StdMeshers_PrismAsBlock::IsForwardEdge( myHelper.GetMeshDS(),
*myParamToColumnMap,
myBaseEdge, myID );
+ myHelper.SetSubShape( quadList.front()->face );
+
if ( quadList.size() > 1 ) // side is vertically composite
{
// fill myShapeID2Surf map to enable finding a right surface by any sub-shape ID
myIsForward( true ),
myComponents( components ),
myHelper( mesh )
-{}
+{
+ if ( myID == ID_Fx1z || myID == ID_F0yz )
+ {
+ // reverse components
+ std::reverse( myComponents.begin(), myComponents.end() );
+ std::reverse( myParams.begin(), myParams.end() );
+ for ( size_t i = 0; i < myParams.size(); ++i )
+ {
+ const double f = myParams[i].first;
+ const double l = myParams[i].second;
+ myParams[i] = make_pair( 1. - l, 1. - f );
+ }
+ }
+}
//================================================================================
/*!
* \brief Copy constructor
throw SALOME_Exception("StdMeshers_PrismAsBlock::TSideFace::Value() !mySurface");
}
}
-
+ ((TSideFace*) this)->myHelper.SetSubShape( mySurface->Face() );
+
gp_XY uv1 = myHelper.GetNodeUV( mySurface->Face(), nn[0], nn[2]);
gp_XY uv2 = myHelper.GetNodeUV( mySurface->Face(), nn[1], nn[3]);
gp_XY uv12 = uv1 * ( 1 - vR ) + uv2 * vR;