+ Unexpect aCatch(SalomeException);
+ return _myMeshDS->NbSubMesh();
+}
+
+//=======================================================================
+//function : IsNotConformAllowed
+//purpose : check if a hypothesis alowing notconform mesh is present
+//=======================================================================
+
+bool SMESH_Mesh::IsNotConformAllowed() const
+{
+ if(MYDEBUG) MESSAGE("SMESH_Mesh::IsNotConformAllowed");
+
+ SMESH_HypoFilter filter( SMESH_HypoFilter::HasName( "NotConformAllowed" ));
+ return GetHypothesis( _myMeshDS->ShapeToMesh(), filter, false );
+}
+
+//=======================================================================
+//function : IsMainShape
+//purpose :
+//=======================================================================
+
+bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const
+{
+ return theShape.IsSame(_myMeshDS->ShapeToMesh() );
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+SMESH_Group* SMESH_Mesh::AddGroup (const SMDSAbs_ElementType theType,
+ const char* theName,
+ int& theId,
+ const TopoDS_Shape& theShape)
+{
+ if (_mapGroup.find(_groupId) != _mapGroup.end())
+ return NULL;
+ theId = _groupId;
+ SMESH_Group* aGroup = new SMESH_Group (theId, this, theType, theName, theShape);
+ GetMeshDS()->AddGroup( aGroup->GetGroupDS() );
+ _mapGroup[_groupId++] = aGroup;
+ return aGroup;
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+SMESH_Group* SMESH_Mesh::GetGroup (const int theGroupID)
+{
+ if (_mapGroup.find(theGroupID) == _mapGroup.end())
+ return NULL;
+ return _mapGroup[theGroupID];
+}
+
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+list<int> SMESH_Mesh::GetGroupIds()
+{
+ list<int> anIds;
+ for ( map<int, SMESH_Group*>::const_iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
+ anIds.push_back( it->first );
+
+ return anIds;
+}
+
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+void SMESH_Mesh::RemoveGroup (const int theGroupID)
+{
+ if (_mapGroup.find(theGroupID) == _mapGroup.end())
+ return;
+ GetMeshDS()->RemoveGroup( _mapGroup[theGroupID]->GetGroupDS() );
+ delete _mapGroup[theGroupID];
+ _mapGroup.erase (theGroupID);
+}
+
+//=============================================================================
+/*!
+ * IsLocal1DHypothesis
+ * Returns a local 1D hypothesis used for theEdge
+ */
+//=============================================================================
+const SMESH_Hypothesis* SMESH_Mesh::IsLocal1DHypothesis (const TopoDS_Shape& theEdge)
+{
+ SMESH_HypoFilter hypo ( SMESH_HypoFilter::HasDim( 1 ));
+ hypo.AndNot( hypo.IsAlgo() ).AndNot( hypo.IsAssignedTo( GetMeshDS()->ShapeToMesh() ));
+
+ return GetHypothesis( theEdge, hypo, true );
+}
+
+//=============================================================================
+/*!
+ * IsPropagationHypothesis
+ */
+//=============================================================================
+bool SMESH_Mesh::IsPropagationHypothesis (const TopoDS_Shape& theEdge)
+{
+ return _mapPropagationChains.Contains(theEdge);
+}
+
+//=============================================================================
+/*!
+ * IsPropagatedHypothesis
+ */
+//=============================================================================
+bool SMESH_Mesh::IsPropagatedHypothesis (const TopoDS_Shape& theEdge,
+ TopoDS_Shape& theMainEdge)
+{
+ int nbChains = _mapPropagationChains.Extent();
+ for (int i = 1; i <= nbChains; i++) {
+ //const TopTools_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromIndex(i);
+ const SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromIndex(i);
+ if (aChain.Contains(theEdge)) {
+ theMainEdge = _mapPropagationChains.FindKey(i);
+ return true;
+ }
+ }
+
+ return false;
+}
+//=============================================================================
+/*!
+ * IsReversedInChain
+ */
+//=============================================================================
+
+bool SMESH_Mesh::IsReversedInChain (const TopoDS_Shape& theEdge,
+ const TopoDS_Shape& theMainEdge)
+{
+ if ( !theMainEdge.IsNull() && !theEdge.IsNull() &&
+ _mapPropagationChains.Contains( theMainEdge ))
+ {
+ const SMESH_IndexedMapOfShape& aChain =
+ _mapPropagationChains.FindFromKey( theMainEdge );
+ int index = aChain.FindIndex( theEdge );
+ if ( index )
+ return aChain(index).Orientation() == TopAbs_REVERSED;
+ }
+ return false;
+}
+
+//=============================================================================
+/*!
+ * CleanMeshOnPropagationChain
+ */
+//=============================================================================
+void SMESH_Mesh::CleanMeshOnPropagationChain (const TopoDS_Shape& theMainEdge)
+{
+ const SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromKey(theMainEdge);
+ int i, nbEdges = aChain.Extent();
+ for (i = 1; i <= nbEdges; i++) {
+ TopoDS_Shape anEdge = aChain.FindKey(i);
+ SMESH_subMesh *subMesh = GetSubMesh(anEdge);
+ SMESHDS_SubMesh *subMeshDS = subMesh->GetSubMeshDS();
+ if (subMeshDS && subMeshDS->NbElements() > 0) {
+ subMesh->ComputeStateEngine(SMESH_subMesh::CLEAN);
+ }
+ }
+}
+
+//=============================================================================
+/*!
+ * RebuildPropagationChains
+ * Rebuild all existing propagation chains.
+ * Have to be used, if 1D hypothesis have been assigned/removed to/from any edge
+ */
+//=============================================================================
+bool SMESH_Mesh::RebuildPropagationChains()
+{
+ bool ret = true;
+
+ // Clean all chains, because they can be not up-to-date
+ int i, nbChains = _mapPropagationChains.Extent();
+ for (i = 1; i <= nbChains; i++) {
+ TopoDS_Shape aMainEdge = _mapPropagationChains.FindKey(i);
+ CleanMeshOnPropagationChain(aMainEdge);
+ _mapPropagationChains.ChangeFromIndex(i).Clear();
+ }
+
+ // Build all chains
+ for (i = 1; i <= nbChains; i++) {
+ TopoDS_Shape aMainEdge = _mapPropagationChains.FindKey(i);
+ if (!BuildPropagationChain(aMainEdge))
+ ret = false;
+ CleanMeshOnPropagationChain(aMainEdge);
+ }
+
+ return ret;
+}
+
+//=============================================================================
+/*!
+ * RemovePropagationChain
+ * Have to be used, if Propagation hypothesis is removed from <theMainEdge>
+ */
+//=============================================================================
+bool SMESH_Mesh::RemovePropagationChain (const TopoDS_Shape& theMainEdge)
+{
+ if (!_mapPropagationChains.Contains(theMainEdge))
+ return false;
+
+ // Clean mesh elements and nodes, built on the chain
+ CleanMeshOnPropagationChain(theMainEdge);
+
+ // Clean the chain
+ _mapPropagationChains.ChangeFromKey(theMainEdge).Clear();
+
+ // Remove the chain from the map
+ int i = _mapPropagationChains.FindIndex(theMainEdge);
+ if ( i == _mapPropagationChains.Extent() )
+ _mapPropagationChains.RemoveLast();
+ else {
+ TopoDS_Vertex anEmptyShape;
+ BRep_Builder BB;
+ BB.MakeVertex(anEmptyShape, gp_Pnt(0,0,0), 0.1);
+ SMESH_IndexedMapOfShape anEmptyMap;
+ _mapPropagationChains.Substitute(i, anEmptyShape, anEmptyMap);
+ }
+
+ return true;
+}
+
+//=============================================================================
+/*!
+ * BuildPropagationChain
+ */
+//=============================================================================
+bool SMESH_Mesh::BuildPropagationChain (const TopoDS_Shape& theMainEdge)
+{
+ if (theMainEdge.ShapeType() != TopAbs_EDGE) return true;
+
+ // Add new chain, if there is no
+ if (!_mapPropagationChains.Contains(theMainEdge)) {
+ SMESH_IndexedMapOfShape aNewChain;
+ _mapPropagationChains.Add(theMainEdge, aNewChain);
+ }
+
+ // Check presence of 1D hypothesis to be propagated
+ const SMESH_Hypothesis* aMainHyp = IsLocal1DHypothesis(theMainEdge);
+ if (!aMainHyp) {
+ MESSAGE("Warning: There is no 1D hypothesis to propagate. Please, assign.");
+ return true;
+ }
+
+ // Edges, on which the 1D hypothesis will be propagated from <theMainEdge>
+ SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.ChangeFromKey(theMainEdge);
+ if (aChain.Extent() > 0) {
+ CleanMeshOnPropagationChain(theMainEdge);
+ aChain.Clear();
+ }
+
+ // At first put <theMainEdge> in the chain
+ aChain.Add(theMainEdge);
+
+ // List of edges, added to chain on the previous cycle pass
+ TopTools_ListOfShape listPrevEdges;
+ listPrevEdges.Append(theMainEdge.Oriented( TopAbs_FORWARD ));
+
+// 5____4____3____4____5____6
+// | | | | | |
+// | | | | | |
+// 4____3____2____3____4____5
+// | | | | | | Number in the each knot of
+// | | | | | | grid indicates cycle pass,
+// 3____2____1____2____3____4 on which corresponding edge
+// | | | | | | (perpendicular to the plane
+// | | | | | | of view) will be found.
+// 2____1____0____1____2____3
+// | | | | | |
+// | | | | | |
+// 3____2____1____2____3____4
+
+ // Collect all edges pass by pass
+ while (listPrevEdges.Extent() > 0) {
+ // List of edges, added to chain on this cycle pass
+ TopTools_ListOfShape listCurEdges;
+
+ // Find the next portion of edges
+ TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
+ for (; itE.More(); itE.Next()) {
+ TopoDS_Shape anE = itE.Value();
+
+ // Iterate on faces, having edge <anE>
+ TopTools_ListIteratorOfListOfShape itA (GetAncestors(anE));
+ for (; itA.More(); itA.Next()) {
+ TopoDS_Shape aW = itA.Value();
+
+ // There are objects of different type among the ancestors of edge
+ if (aW.ShapeType() == TopAbs_WIRE) {
+ TopoDS_Shape anOppE;
+
+ BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
+ Standard_Integer nb = 1, found = 0;
+ TopTools_Array1OfShape anEdges (1,4);
+ for (; aWE.More(); aWE.Next(), nb++) {
+ if (nb > 4) {
+ found = 0;
+ break;
+ }
+ anEdges(nb) = aWE.Current();
+ if (!_mapAncestors.Contains(anEdges(nb))) {
+ MESSAGE("WIRE EXPLORER HAVE GIVEN AN INVALID EDGE !!!");
+ break;
+ }
+ if (anEdges(nb).IsSame(anE)) found = nb;
+ }
+
+ if (nb == 5 && found > 0) {
+ // Quadrangle face found, get an opposite edge
+ Standard_Integer opp = found + 2;
+ if (opp > 4) opp -= 4;
+ anOppE = anEdges(opp);
+
+ // add anOppE to aChain if ...
+ if (!aChain.Contains(anOppE)) { // ... anOppE is not in aChain
+ if (!IsLocal1DHypothesis(anOppE)) { // ... no other 1d hyp on anOppE
+ TopoDS_Shape aMainEdgeForOppEdge; // ... no other hyp is propagated to anOppE
+ if (!IsPropagatedHypothesis(anOppE, aMainEdgeForOppEdge))
+ {
+ // Add found edge to the chain oriented so that to
+ // have it co-directed with a forward MainEdge
+ TopAbs_Orientation ori = anE.Orientation();
+ if ( anEdges(opp).Orientation() == anEdges(found).Orientation() )
+ ori = TopAbs::Reverse( ori );
+ anOppE.Orientation( ori );
+ aChain.Add(anOppE);
+ listCurEdges.Append(anOppE);
+ }
+ else {
+ // Collision!
+ MESSAGE("Error: Collision between propagated hypotheses");
+ CleanMeshOnPropagationChain(theMainEdge);
+ aChain.Clear();
+ return ( aMainHyp == IsLocal1DHypothesis(aMainEdgeForOppEdge) );
+ }
+ }
+ }
+ } // if (nb == 5 && found > 0)
+ } // if (aF.ShapeType() == TopAbs_WIRE)
+ } // for (; itF.More(); itF.Next())
+ } // for (; itE.More(); itE.Next())
+
+ listPrevEdges = listCurEdges;
+ } // while (listPrevEdges.Extent() > 0)
+
+ CleanMeshOnPropagationChain(theMainEdge);
+ return true;
+}
+
+//=======================================================================
+//function : GetAncestors
+//purpose : return list of ancestors of theSubShape in the order
+// that lower dimention shapes come first.
+//=======================================================================
+
+const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS) const
+{
+ if ( _mapAncestors.Contains( theS ) )
+ return _mapAncestors.FindFromKey( theS );
+
+ static TopTools_ListOfShape emptyList;
+ return emptyList;
+}
+
+//=======================================================================
+//function : Dump
+//purpose : dumps contents of mesh to stream [ debug purposes ]
+//=======================================================================
+ostream& SMESH_Mesh::Dump(ostream& save)
+{
+ int clause = 0;
+ save << "========================== Dump contents of mesh ==========================" << endl << endl;
+ save << ++clause << ") Total number of nodes: \t" << NbNodes() << endl;
+ save << ++clause << ") Total number of edges: \t" << NbEdges() << endl;
+ save << ++clause << ") Total number of faces: \t" << NbFaces() << endl;
+ save << ++clause << ") Total number of polygons:\t" << NbPolygons() << endl;
+ save << ++clause << ") Total number of volumes:\t" << NbVolumes() << endl;
+ save << ++clause << ") Total number of polyhedrons:\t" << NbPolyhedrons() << endl << endl;
+ for ( int isQuadratic = 0; isQuadratic < 2; ++isQuadratic )
+ {
+ string orderStr = isQuadratic ? "quadratic" : "linear";
+ ElementOrder order = isQuadratic ? ORDER_QUADRATIC : ORDER_LINEAR;
+
+ save << ++clause << ") Total number of " << orderStr << " edges:\t" << NbEdges(order) << endl;
+ save << ++clause << ") Total number of " << orderStr << " faces:\t" << NbFaces(order) << endl;
+ if ( NbFaces(order) > 0 ) {
+ int nb3 = NbTriangles(order);
+ int nb4 = NbQuadrangles(order);
+ save << clause << ".1) Number of " << orderStr << " triangles: \t" << nb3 << endl;
+ save << clause << ".2) Number of " << orderStr << " quadrangles:\t" << nb4 << endl;
+ if ( nb3 + nb4 != NbFaces(order) ) {
+ map<int,int> myFaceMap;
+ SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
+ while( itFaces->more( ) ) {
+ int nbNodes = itFaces->next()->NbNodes();
+ if ( myFaceMap.find( nbNodes ) == myFaceMap.end() )
+ myFaceMap[ nbNodes ] = 0;
+ myFaceMap[ nbNodes ] = myFaceMap[ nbNodes ] + 1;
+ }
+ save << clause << ".3) Faces in detail: " << endl;
+ map <int,int>::iterator itF;
+ for (itF = myFaceMap.begin(); itF != myFaceMap.end(); itF++)
+ save << "--> nb nodes: " << itF->first << " - nb elemens:\t" << itF->second << endl;
+ }
+ }
+ save << ++clause << ") Total number of " << orderStr << " volumes:\t" << NbVolumes(order) << endl;
+ if ( NbVolumes(order) > 0 ) {
+ int nb8 = NbHexas(order);
+ int nb4 = NbTetras(order);
+ int nb5 = NbPyramids(order);
+ int nb6 = NbPrisms(order);
+ save << clause << ".1) Number of " << orderStr << " hexahedrons:\t" << nb8 << endl;
+ save << clause << ".2) Number of " << orderStr << " tetrahedrons:\t" << nb4 << endl;
+ save << clause << ".3) Number of " << orderStr << " prisms: \t" << nb6 << endl;
+ save << clause << ".4) Number of " << orderStr << " pyramids:\t" << nb5 << endl;
+ if ( nb8 + nb4 + nb5 + nb6 != NbVolumes(order) ) {
+ map<int,int> myVolumesMap;
+ SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
+ while( itVolumes->more( ) ) {
+ int nbNodes = itVolumes->next()->NbNodes();
+ if ( myVolumesMap.find( nbNodes ) == myVolumesMap.end() )
+ myVolumesMap[ nbNodes ] = 0;
+ myVolumesMap[ nbNodes ] = myVolumesMap[ nbNodes ] + 1;
+ }
+ save << clause << ".5) Volumes in detail: " << endl;
+ map <int,int>::iterator itV;
+ for (itV = myVolumesMap.begin(); itV != myVolumesMap.end(); itV++)
+ save << "--> nb nodes: " << itV->first << " - nb elemens:\t" << itV->second << endl;
+ }
+ }
+ save << endl;
+ }
+ save << "===========================================================================" << endl;
+ return save;
+}
+
+//=======================================================================
+//function : GetElementType
+//purpose : Returns type of mesh element with certain id
+//=======================================================================
+SMDSAbs_ElementType SMESH_Mesh::GetElementType( const int id, const bool iselem )
+{
+ return _myMeshDS->GetElementType( id, iselem );