PyObject* FemMeshPy::addQuad(PyObject *args)
{
    int n1,n2,n3,n4;
    if (!PyArg_ParseTuple(args, "iiii",&n1,&n2,&n3,&n4))
        return 0;

    try {
        SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
        SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
        const SMDS_MeshNode* node1 = meshDS->FindNode(n1);
        const SMDS_MeshNode* node2 = meshDS->FindNode(n2);
        const SMDS_MeshNode* node3 = meshDS->FindNode(n3);
        const SMDS_MeshNode* node4 = meshDS->FindNode(n4);
        if (!node1 || !node2 || !node3 || !node4)
            throw std::runtime_error("Failed to get node of the given indices");
        SMDS_MeshFace* face = meshDS->AddFace(node1, node2, node3, node4);
        if (!face)
            throw std::runtime_error("Failed to add quad");
        return Py::new_reference_to(Py::Long(face->GetID()));
    }
    catch (const std::exception& e) {
        PyErr_SetString(Base::BaseExceptionFreeCADError, e.what());
        return 0;
    }
}
TNodeColumn* StdMeshers_RadialPrism_3D::makeNodeColumn( TNode2ColumnMap&     n2ColMap,
                                                        const SMDS_MeshNode* outNode,
                                                        const SMDS_MeshNode* inNode)
{
  SMESHDS_Mesh * meshDS = myHelper->GetMeshDS();
  int shapeID = myHelper->GetSubShapeID();

  if ( myLayerPositions.empty() ) {
    gp_Pnt pIn = gpXYZ( inNode ), pOut = gpXYZ( outNode );
    computeLayerPositions( pIn, pOut );
  }
  int nbSegments = myLayerPositions.size() + 1;

  TNode2ColumnMap::iterator n_col =
    n2ColMap.insert( make_pair( outNode, TNodeColumn() )).first;
  TNodeColumn & column = n_col->second;
  column.resize( nbSegments + 1 );
  column.front() = outNode;
  column.back() =  inNode;

  gp_XYZ p1 = gpXYZ( outNode );
  gp_XYZ p2 = gpXYZ( inNode );
  for ( int z = 1; z < nbSegments; ++z )
  {
    double r = myLayerPositions[ z - 1 ];
    gp_XYZ p = ( 1 - r ) * p1 + r * p2;
    SMDS_MeshNode* n = meshDS->AddNode( p.X(), p.Y(), p.Z() );
    meshDS->SetNodeInVolume( n, shapeID );
    column[ z ] = n;
  }

  return & column;
}
PyObject* FemMeshPy::addVolume(PyObject *args)
{
    int n1,n2,n3,n4;
    if (!PyArg_ParseTuple(args, "iiii",&n1,&n2,&n3,&n4))
        return 0;

    try {
        SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
        SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
        const SMDS_MeshNode* node1 = meshDS->FindNode(n1);
        const SMDS_MeshNode* node2 = meshDS->FindNode(n2);
        const SMDS_MeshNode* node3 = meshDS->FindNode(n3);
        const SMDS_MeshNode* node4 = meshDS->FindNode(n4);
        if (!node1 || !node2 || !node3 || !node4)
            throw std::runtime_error("Failed to get node of the given indices");
        SMDS_MeshVolume* vol = meshDS->AddVolume(node1, node2, node3, node4);
        if (!vol)
            throw std::runtime_error("Failed to add volume");
        return Py::new_reference_to(Py::Int(vol->GetID()));
    }
    catch (const std::exception& e) {
        PyErr_SetString(PyExc_Exception, e.what());
        return 0;
    }
}
Esempio n. 4
0
bool SMESH_MesherHelper::IsQuadraticSubMesh(const TopoDS_Shape& aSh)
{
  SMESHDS_Mesh* meshDS = GetMeshDS();
  // we can create quadratic elements only if all elements
  // created on subshapes of given shape are quadratic
  // also we have to fill myNLinkNodeMap
  myCreateQuadratic = true;
  mySeamShapeIds.clear();
  myDegenShapeIds.clear();
  TopAbs_ShapeEnum subType( aSh.ShapeType()==TopAbs_FACE ? TopAbs_EDGE : TopAbs_FACE );
  SMDSAbs_ElementType elemType( subType==TopAbs_FACE ? SMDSAbs_Face : SMDSAbs_Edge );

  int nbOldLinks = myNLinkNodeMap.size();

  TopExp_Explorer exp( aSh, subType );
  for (; exp.More() && myCreateQuadratic; exp.Next()) {
    if ( SMESHDS_SubMesh * subMesh = meshDS->MeshElements( exp.Current() )) {
      if ( SMDS_ElemIteratorPtr it = subMesh->GetElements() ) {
        while(it->more()) {
          const SMDS_MeshElement* e = it->next();
          if ( e->GetType() != elemType || !e->IsQuadratic() ) {
            myCreateQuadratic = false;
            break;
          }
          else {
            // fill NLinkNodeMap
            switch ( e->NbNodes() ) {
            case 3:
              AddNLinkNode(e->GetNode(0),e->GetNode(1),e->GetNode(2)); break;
            case 6:
              AddNLinkNode(e->GetNode(0),e->GetNode(1),e->GetNode(3));
              AddNLinkNode(e->GetNode(1),e->GetNode(2),e->GetNode(4));
              AddNLinkNode(e->GetNode(2),e->GetNode(0),e->GetNode(5)); break;
            case 8:
              AddNLinkNode(e->GetNode(0),e->GetNode(1),e->GetNode(4));
              AddNLinkNode(e->GetNode(1),e->GetNode(2),e->GetNode(5));
              AddNLinkNode(e->GetNode(2),e->GetNode(3),e->GetNode(6));
              AddNLinkNode(e->GetNode(3),e->GetNode(0),e->GetNode(7));
              break;
            default:
              myCreateQuadratic = false;
              break;
            }
          }
        }
      }
    }
  }

  if ( nbOldLinks == myNLinkNodeMap.size() )
    myCreateQuadratic = false;

  if(!myCreateQuadratic) {
    myNLinkNodeMap.clear();
  }
  SetSubShape( aSh );

  return myCreateQuadratic;
}
App::DocumentObjectExecReturn *FemMeshShapeNetgenObject::execute(void)
{
#ifdef FCWithNetgen

    Fem::FemMesh newMesh;

    Part::Feature *feat = Shape.getValue<Part::Feature*>();
    TopoDS_Shape shape = feat->Shape.getValue();

    NETGENPlugin_Mesher myNetGenMesher(newMesh.getSMesh(),shape,true);
    NETGENPlugin_Hypothesis* tet= new NETGENPlugin_Hypothesis(0,1,newMesh.getGenerator());
    tet->SetMaxSize(MaxSize.getValue());
    tet->SetSecondOrder(SecondOrder.getValue());
    tet->SetOptimize(Optimize.getValue());
    int iFineness = Fineness.getValue();
    tet->SetFineness((NETGENPlugin_Hypothesis::Fineness)iFineness);
    if(iFineness == 5){
        tet->SetGrowthRate(GrowthRate.getValue());
        tet->SetNbSegPerEdge(NbSegsPerEdge.getValue());
        tet->SetNbSegPerRadius(NbSegsPerRadius.getValue());
    }
    myNetGenMesher.SetParameters( tet);
    newMesh.getSMesh()->ShapeToMesh(shape);

    myNetGenMesher.Compute();

    // throw Base::RuntimeError("Compute Done\n");

    SMESHDS_Mesh* data = const_cast<SMESH_Mesh*>(newMesh.getSMesh())->GetMeshDS();
    const SMDS_MeshInfo& info = data->GetMeshInfo();
    int numFaces = data->NbFaces();
    int numNode = info.NbNodes();
  //int numTria = info.NbTriangles();
  //int numQuad = info.NbQuadrangles();
  //int numPoly = info.NbPolygons();
    int numVolu = info.NbVolumes();
  //int numTetr = info.NbTetras();
  //int numHexa = info.NbHexas();
  //int numPyrd = info.NbPyramids();
  //int numPris = info.NbPrisms();
  //int numHedr = info.NbPolyhedrons();

    Base::Console().Log("NetgenMesh: %i Nodes, %i Volumes, %i Faces\n",numNode,numVolu,numFaces);

      FemMesh.setValue(newMesh);
    return App::DocumentObject::StdReturn;
#else
    return new App::DocumentObjectExecReturn("The FEM module is built without NETGEN support. Meshing will not work!!!", this);
#endif
}
Esempio n. 6
0
double SMESH_MesherHelper::GetNodeU(const TopoDS_Edge&   E,
                                    const SMDS_MeshNode* n)
{
  double param = 0;
  const SMDS_PositionPtr Pos = n->GetPosition();
  if(Pos->GetTypeOfPosition()==SMDS_TOP_EDGE) {
    const SMDS_EdgePosition* epos =
      static_cast<const SMDS_EdgePosition*>(n->GetPosition().get());
    param =  epos->GetUParameter();
  }
  else if(Pos->GetTypeOfPosition()==SMDS_TOP_VERTEX) {
    SMESHDS_Mesh * meshDS = GetMeshDS();
    int vertexID = n->GetPosition()->GetShapeId();
    const TopoDS_Vertex& V = TopoDS::Vertex(meshDS->IndexToShape(vertexID));
    param =  BRep_Tool::Parameter( V, E );
  }
  return param;
}
PyObject* FemMeshPy::addNode(PyObject *args)
{
    double x,y,z;
    if (!PyArg_ParseTuple(args, "ddd",&x,&y,&z))
        return 0;

    try {
        SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
        SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
        SMDS_MeshNode* node = meshDS->AddNode(x,y,z);
        if (!node)
            throw std::runtime_error("Failed to add node");
        return Py::new_reference_to(Py::Int(node->GetID()));
    }
    catch (const std::exception& e) {
        PyErr_SetString(PyExc_Exception, e.what());
        return 0;
    }
}
PyObject* FemMeshPy::addNode(PyObject *args)
{
    double x,y,z;
    int i = -1;
    if (PyArg_ParseTuple(args, "ddd",&x,&y,&z)){
        try {
            SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
            SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
            SMDS_MeshNode* node = meshDS->AddNode(x,y,z);
            if (!node)
                throw std::runtime_error("Failed to add node");
            return Py::new_reference_to(Py::Int(node->GetID()));
        }
        catch (const std::exception& e) {
            PyErr_SetString(Base::BaseExceptionFreeCADError, e.what());
            return 0;
        }
    }
    PyErr_Clear();

    if (PyArg_ParseTuple(args, "dddi",&x,&y,&z,&i)){
        try {
            SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
            SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
            SMDS_MeshNode* node = meshDS->AddNodeWithID(x,y,z,i);
            if (!node)
                throw std::runtime_error("Failed to add node");
            return Py::new_reference_to(Py::Int(node->GetID()));
        }
        catch (const std::exception& e) {
            PyErr_SetString(Base::BaseExceptionFreeCADError, e.what());
            return 0;
        }
    }
    PyErr_SetString(PyExc_TypeError, "addNode() accepts:\n"
        "-- addNode(x,y,z)\n"
        "-- addNode(x,y,z,ElemId)\n");
    return 0;

}
Esempio n. 9
0
SMDS_MeshVolume* SMESH_MesherHelper::AddVolume(const SMDS_MeshNode* n1,
                                               const SMDS_MeshNode* n2,
                                               const SMDS_MeshNode* n3,
                                               const SMDS_MeshNode* n4,
                                               const int id, 
					       const bool force3d)
{
  SMESHDS_Mesh * meshDS = GetMeshDS();
  SMDS_MeshVolume* elem = 0;
  if(!myCreateQuadratic) {
    if(id)
      elem = meshDS->AddVolumeWithID(n1, n2, n3, n4, id);
    else
      elem = meshDS->AddVolume(n1, n2, n3, n4);
  }
  else {
    const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
    const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
    const SMDS_MeshNode* n31 = GetMediumNode(n3,n1,force3d);

    const SMDS_MeshNode* n14 = GetMediumNode(n1,n4,force3d);
    const SMDS_MeshNode* n24 = GetMediumNode(n2,n4,force3d);
    const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,force3d);

    if(id)
      elem = meshDS->AddVolumeWithID(n1, n2, n3, n4, n12, n23, n31, n14, n24, n34, id);
    else
      elem = meshDS->AddVolume(n1, n2, n3, n4, n12, n23, n31, n14, n24, n34);
  }
  if ( mySetElemOnShape && myShapeID > 0 )
    meshDS->SetMeshElementOnShape( elem, myShapeID );

  return elem;
}
Esempio n. 10
0
SMDS_MeshEdge* SMESH_MesherHelper::AddEdge(const SMDS_MeshNode* n1,
                                                const SMDS_MeshNode* n2,
                                                const int id,
                                                const bool force3d)
{
  SMESHDS_Mesh * meshDS = GetMeshDS();
  
  SMDS_MeshEdge* edge = 0;
  if (myCreateQuadratic) {
    const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
    if(id)
      edge = meshDS->AddEdgeWithID(n1, n2, n12, id);
    else
      edge = meshDS->AddEdge(n1, n2, n12);
  }
  else {
    if(id)
      edge = meshDS->AddEdgeWithID(n1, n2, id);
    else
      edge = meshDS->AddEdge(n1, n2);
  }

  if ( mySetElemOnShape && myShapeID > 0 )
    meshDS->SetMeshElementOnShape( edge, myShapeID );

  return edge;
}
PyObject* FemMeshPy::addEdge(PyObject *args)
{
    int n1,n2;
    if (!PyArg_ParseTuple(args, "ii",&n1,&n2))
        return 0;

    try {
        SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
        SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
        const SMDS_MeshNode* node1 = meshDS->FindNode(n1);
        const SMDS_MeshNode* node2 = meshDS->FindNode(n2);
        if (!node1 || !node2)
            throw std::runtime_error("Failed to get node of the given indices");
        SMDS_MeshEdge* edge = meshDS->AddEdge(node1, node2);
        if (!edge)
            throw std::runtime_error("Failed to add edge");
        return Py::new_reference_to(Py::Int(edge->GetID()));
    }
    catch (const std::exception& e) {
        PyErr_SetString(PyExc_Exception, e.what());
        return 0;
    }
}
Esempio n. 12
0
SMDS_MeshVolume* SMESH_MesherHelper::AddVolume(const SMDS_MeshNode* n1,
                                               const SMDS_MeshNode* n2,
                                               const SMDS_MeshNode* n3,
                                               const SMDS_MeshNode* n4,
                                               const SMDS_MeshNode* n5,
                                               const SMDS_MeshNode* n6,
                                               const SMDS_MeshNode* n7,
                                               const SMDS_MeshNode* n8,
                                               const int id,
					       const bool force3d)
{
  SMESHDS_Mesh * meshDS = GetMeshDS();
  SMDS_MeshVolume* elem = 0;
  if(!myCreateQuadratic) {
    if(id)
      elem = meshDS->AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, id);
    else
      elem = meshDS->AddVolume(n1, n2, n3, n4, n5, n6, n7, n8);
  }
  else {
    const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
    const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
    const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,force3d);
    const SMDS_MeshNode* n41 = GetMediumNode(n4,n1,force3d);

    const SMDS_MeshNode* n56 = GetMediumNode(n5,n6,force3d);
    const SMDS_MeshNode* n67 = GetMediumNode(n6,n7,force3d);
    const SMDS_MeshNode* n78 = GetMediumNode(n7,n8,force3d);
    const SMDS_MeshNode* n85 = GetMediumNode(n8,n5,force3d);

    const SMDS_MeshNode* n15 = GetMediumNode(n1,n5,force3d);
    const SMDS_MeshNode* n26 = GetMediumNode(n2,n6,force3d);
    const SMDS_MeshNode* n37 = GetMediumNode(n3,n7,force3d);
    const SMDS_MeshNode* n48 = GetMediumNode(n4,n8,force3d);

    if(id)
      elem = meshDS->AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8,
                                     n12, n23, n34, n41, n56, n67,
                                     n78, n85, n15, n26, n37, n48, id);
    else
      elem = meshDS->AddVolume(n1, n2, n3, n4, n5, n6, n7, n8,
                               n12, n23, n34, n41, n56, n67,
                               n78, n85, n15, n26, n37, n48);
  }
  if ( mySetElemOnShape && myShapeID > 0 )
    meshDS->SetMeshElementOnShape( elem, myShapeID );

  return elem;
}
Esempio n. 13
0
SMDS_MeshNode* SMESH_MesherHelper::AddNode(double x, double y, double z, int ID)
{
  SMESHDS_Mesh * meshDS = GetMeshDS();
  SMDS_MeshNode* node = 0;
  if ( ID )
    node = meshDS->AddNodeWithID( x, y, z, ID );
  else
    node = meshDS->AddNode( x, y, z );
  if ( mySetElemOnShape && myShapeID > 0 ) {
    switch ( myShape.ShapeType() ) {
    case TopAbs_SOLID:  meshDS->SetNodeInVolume( node, myShapeID); break;
    case TopAbs_SHELL:  meshDS->SetNodeInVolume( node, myShapeID); break;
    case TopAbs_FACE:   meshDS->SetNodeOnFace(   node, myShapeID); break;
    case TopAbs_EDGE:   meshDS->SetNodeOnEdge(   node, myShapeID); break;
    case TopAbs_VERTEX: meshDS->SetNodeOnVertex( node, myShapeID); break;
    default: ;
    }
  }
  return node;
}
Esempio n. 14
0
void SMESHDS_GroupOnGeom::SetShape( const TopoDS_Shape& theShape)
{
  SMESHDS_Mesh* aMesh = const_cast<SMESHDS_Mesh*>( GetMesh() );
  mySubMesh = aMesh->MeshElements( aMesh->AddCompoundSubmesh( theShape ));
  myShape   = theShape;
}
Esempio n. 15
0
bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
                                     const TopoDS_Shape& aShape)
{
    MESSAGE("NETGENPlugin_NETGEN_3D::Compute with maxElmentsize = " << _maxElementVolume);

    SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();

    const int invalid_ID = -1;

    SMESH::Controls::Area areaControl;
    SMESH::Controls::TSequenceOfXYZ nodesCoords;

    // -------------------------------------------------------------------
    // get triangles on aShell and make a map of nodes to Netgen node IDs
    // -------------------------------------------------------------------

    SMESH_MesherHelper helper(aMesh);
    SMESH_MesherHelper* myTool = &helper;
    bool _quadraticMesh = myTool->IsQuadraticSubMesh(aShape);

    typedef map< const SMDS_MeshNode*, int, TIDCompare > TNodeToIDMap;
    TNodeToIDMap nodeToNetgenID;
    list< const SMDS_MeshElement* > triangles;
    list< bool >                    isReversed; // orientation of triangles

    TopAbs_ShapeEnum mainType = aMesh.GetShapeToMesh().ShapeType();
    bool checkReverse = ( mainType == TopAbs_COMPOUND || mainType == TopAbs_COMPSOLID );

    // for the degeneraged edge: ignore all but one node on it;
    // map storing ids of degen edges and vertices and their netgen id:
    map< int, int* > degenShapeIdToPtrNgId;
    map< int, int* >::iterator shId_ngId;
    list< int > degenNgIds;

    StdMeshers_QuadToTriaAdaptor Adaptor;
    Adaptor.Compute(aMesh,aShape);

    for (TopExp_Explorer exp(aShape,TopAbs_FACE); exp.More(); exp.Next())
    {
        const TopoDS_Shape& aShapeFace = exp.Current();
        const SMESHDS_SubMesh * aSubMeshDSFace = meshDS->MeshElements( aShapeFace );
        if ( aSubMeshDSFace )
        {
            bool isRev = false;
            if ( checkReverse && helper.NbAncestors(aShapeFace, aMesh, aShape.ShapeType()) > 1 )
                // IsReversedSubMesh() can work wrong on strongly curved faces,
                // so we use it as less as possible
                isRev = SMESH_Algo::IsReversedSubMesh( TopoDS::Face(aShapeFace), meshDS );

            SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
            while ( iteratorElem->more() ) // loop on elements on a face
            {
                // check element
                const SMDS_MeshElement* elem = iteratorElem->next();
                if ( !elem )
                    return error( COMPERR_BAD_INPUT_MESH, "Null element encounters");
                bool isTraingle = ( elem->NbNodes()==3 || (_quadraticMesh && elem->NbNodes()==6 ));
                if ( !isTraingle ) {
                    //return error( COMPERR_BAD_INPUT_MESH,
                    //              SMESH_Comment("Not triangle element ")<<elem->GetID());
                    // using adaptor
                    const list<const SMDS_FaceOfNodes*>* faces = Adaptor.GetTriangles(elem);
                    if(faces==0) {
                        return error( COMPERR_BAD_INPUT_MESH,
                                      SMESH_Comment("Not triangles in adaptor for element ")<<elem->GetID());
                    }
                    list<const SMDS_FaceOfNodes*>::const_iterator itf = faces->begin();
                    for(; itf!=faces->end(); itf++ ) {
                        triangles.push_back( (*itf) );
                        isReversed.push_back( isRev );
                        // put triange's nodes to nodeToNetgenID map
                        SMDS_ElemIteratorPtr triangleNodesIt = (*itf)->nodesIterator();
                        while ( triangleNodesIt->more() ) {
                            const SMDS_MeshNode * node =
                                static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
                            if(myTool->IsMedium(node))
                                continue;
                            nodeToNetgenID.insert( make_pair( node, invalid_ID ));
                        }
                    }
                }
                else {
                    // keep a triangle
                    triangles.push_back( elem );
                    isReversed.push_back( isRev );
                    // put elem nodes to nodeToNetgenID map
                    SMDS_ElemIteratorPtr triangleNodesIt = elem->nodesIterator();
                    while ( triangleNodesIt->more() ) {
                        const SMDS_MeshNode * node =
                            static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
                        if(myTool->IsMedium(node))
                            continue;
                        nodeToNetgenID.insert( make_pair( node, invalid_ID ));
                    }
                }
#ifdef _DEBUG_
                // check if a trainge is degenerated
                areaControl.GetPoints( elem, nodesCoords );
                double area = areaControl.GetValue( nodesCoords );
                if ( area <= DBL_MIN ) {
                    MESSAGE( "Warning: Degenerated " << elem );
                }
#endif
            }
            // look for degeneraged edges and vetices
            for (TopExp_Explorer expE(aShapeFace,TopAbs_EDGE); expE.More(); expE.Next())
            {
                TopoDS_Edge aShapeEdge = TopoDS::Edge( expE.Current() );
                if ( BRep_Tool::Degenerated( aShapeEdge ))
                {
                    degenNgIds.push_back( invalid_ID );
                    int* ptrIdOnEdge = & degenNgIds.back();
                    // remember edge id
                    int edgeID = meshDS->ShapeToIndex( aShapeEdge );
                    degenShapeIdToPtrNgId.insert( make_pair( edgeID, ptrIdOnEdge ));
                    // remember vertex id
                    int vertexID = meshDS->ShapeToIndex( TopExp::FirstVertex( aShapeEdge ));
                    degenShapeIdToPtrNgId.insert( make_pair( vertexID, ptrIdOnEdge ));
                }
            }
        }
    }
    // ---------------------------------
    // Feed the Netgen with surface mesh
    // ---------------------------------

    int Netgen_NbOfNodes = 0;
    int Netgen_param2ndOrder = 0;
    double Netgen_paramFine = 1.;
    double Netgen_paramSize = pow( 72, 1/6. ) * pow( _maxElementVolume, 1/3. );

    double Netgen_point[3];
    int Netgen_triangle[3];
    int Netgen_tetrahedron[4];

    Ng_Init();

    Ng_Mesh * Netgen_mesh = Ng_NewMesh();

    // set nodes and remember thier netgen IDs
    bool isDegen = false, hasDegen = !degenShapeIdToPtrNgId.empty();
    TNodeToIDMap::iterator n_id = nodeToNetgenID.begin();
    for ( ; n_id != nodeToNetgenID.end(); ++n_id )
    {
        const SMDS_MeshNode* node = n_id->first;

        // ignore nodes on degenerated edge
        if ( hasDegen ) {
            int shapeId = node->GetPosition()->GetShapeId();
            shId_ngId = degenShapeIdToPtrNgId.find( shapeId );
            isDegen = ( shId_ngId != degenShapeIdToPtrNgId.end() );
            if ( isDegen && *(shId_ngId->second) != invalid_ID ) {
                n_id->second = *(shId_ngId->second);
                continue;
            }
        }
        Netgen_point [ 0 ] = node->X();
        Netgen_point [ 1 ] = node->Y();
        Netgen_point [ 2 ] = node->Z();
        Ng_AddPoint(Netgen_mesh, Netgen_point);
        n_id->second = ++Netgen_NbOfNodes; // set netgen ID

        if ( isDegen ) // all nodes on a degen edge get one netgen ID
            *(shId_ngId->second) = n_id->second;
    }

    // set triangles
    list< const SMDS_MeshElement* >::iterator tria = triangles.begin();
    list< bool >::iterator                 reverse = isReversed.begin();
    for ( ; tria != triangles.end(); ++tria, ++reverse )
    {
        int i = 0;
        SMDS_ElemIteratorPtr triangleNodesIt = (*tria)->nodesIterator();
        while ( triangleNodesIt->more() ) {
            const SMDS_MeshNode * node =
                static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
            if(myTool->IsMedium(node))
                continue;
            Netgen_triangle[ *reverse ? 2 - i : i ] = nodeToNetgenID[ node ];
            ++i;
        }
        if ( !hasDegen ||
                // ignore degenerated triangles, they have 2 or 3 same ids
                (Netgen_triangle[0] != Netgen_triangle[1] &&
                 Netgen_triangle[0] != Netgen_triangle[2] &&
                 Netgen_triangle[2] != Netgen_triangle[1] ))
        {
            Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle);
        }
    }

    // -------------------------
    // Generate the volume mesh
    // -------------------------

    Ng_Meshing_Parameters Netgen_param;

    Netgen_param.secondorder = Netgen_param2ndOrder;
    Netgen_param.fineness = Netgen_paramFine;
    Netgen_param.maxh = Netgen_paramSize;

    Ng_Result status;

    try {
#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
        OCC_CATCH_SIGNALS;
#endif
        status = Ng_GenerateVolumeMesh(Netgen_mesh, &Netgen_param);
    }
    catch (Standard_Failure& exc) {
        error(COMPERR_OCC_EXCEPTION, exc.GetMessageString());
        status = NG_VOLUME_FAILURE;
    }
    catch (...) {
        error("Exception in Ng_GenerateVolumeMesh()");
        status = NG_VOLUME_FAILURE;
    }
    if ( GetComputeError()->IsOK() ) {
        switch ( status ) {
        case NG_SURFACE_INPUT_ERROR:
            error( status, "NG_SURFACE_INPUT_ERROR");
        case NG_VOLUME_FAILURE:
            error( status, "NG_VOLUME_FAILURE");
        case NG_STL_INPUT_ERROR:
            error( status, "NG_STL_INPUT_ERROR");
        case NG_SURFACE_FAILURE:
            error( status, "NG_SURFACE_FAILURE");
        case NG_FILE_NOT_FOUND:
            error( status, "NG_FILE_NOT_FOUND");
        };
    }

    int Netgen_NbOfNodesNew = Ng_GetNP(Netgen_mesh);

    int Netgen_NbOfTetra = Ng_GetNE(Netgen_mesh);

    MESSAGE("End of Volume Mesh Generation. status=" << status <<
            ", nb new nodes: " << Netgen_NbOfNodesNew - Netgen_NbOfNodes <<
            ", nb tetra: " << Netgen_NbOfTetra);

    // -------------------------------------------------------------------
    // Feed back the SMESHDS with the generated Nodes and Volume Elements
    // -------------------------------------------------------------------

    bool isOK = ( /*status == NG_OK &&*/ Netgen_NbOfTetra > 0 );// get whatever built
    if ( isOK )
    {
        // vector of nodes in which node index == netgen ID
        vector< const SMDS_MeshNode* > nodeVec ( Netgen_NbOfNodesNew + 1 );
        // insert old nodes into nodeVec
        for ( n_id = nodeToNetgenID.begin(); n_id != nodeToNetgenID.end(); ++n_id ) {
            nodeVec.at( n_id->second ) = n_id->first;
        }
        // create and insert new nodes into nodeVec
        int nodeIndex = Netgen_NbOfNodes + 1;
        int shapeID = meshDS->ShapeToIndex( aShape );
        for ( ; nodeIndex <= Netgen_NbOfNodesNew; ++nodeIndex )
        {
            Ng_GetPoint( Netgen_mesh, nodeIndex, Netgen_point );
            SMDS_MeshNode * node = meshDS->AddNode(Netgen_point[0],
                                                   Netgen_point[1],
                                                   Netgen_point[2]);
            meshDS->SetNodeInVolume(node, shapeID);
            nodeVec.at(nodeIndex) = node;
        }

        // create tetrahedrons
        for ( int elemIndex = 1; elemIndex <= Netgen_NbOfTetra; ++elemIndex )
        {
            Ng_GetVolumeElement(Netgen_mesh, elemIndex, Netgen_tetrahedron);
            SMDS_MeshVolume * elt = myTool->AddVolume (nodeVec.at( Netgen_tetrahedron[0] ),
                                    nodeVec.at( Netgen_tetrahedron[1] ),
                                    nodeVec.at( Netgen_tetrahedron[2] ),
                                    nodeVec.at( Netgen_tetrahedron[3] ));
            meshDS->SetMeshElementOnShape(elt, shapeID );
        }
    }

    Ng_DeleteMesh(Netgen_mesh);
    Ng_Exit();

    NETGENPlugin_Mesher::RemoveTmpFiles();

    return (status == NG_OK);
}
Esempio n. 16
0
PyObject* FemMeshPy::addFace(PyObject *args)
{
    SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
    SMESHDS_Mesh* meshDS = mesh->GetMeshDS();

    int n1,n2,n3;
    if (PyArg_ParseTuple(args, "iii",&n1,&n2,&n3))
    {
        // old form, deprecated
        try {
            const SMDS_MeshNode* node1 = meshDS->FindNode(n1);
            const SMDS_MeshNode* node2 = meshDS->FindNode(n2);
            const SMDS_MeshNode* node3 = meshDS->FindNode(n3);
            if (!node1 || !node2 || !node3)
                throw std::runtime_error("Failed to get node of the given indices");
            SMDS_MeshFace* face = meshDS->AddFace(node1, node2, node3);
            if (!face)
                throw std::runtime_error("Failed to add face");
            return Py::new_reference_to(Py::Long(face->GetID()));
        }
        catch (const std::exception& e) {
            PyErr_SetString(Base::BaseExceptionFreeCADError, e.what());
            return 0;
        }
    }
    PyErr_Clear();

    PyObject *obj;
    int ElementId=-1;
    if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId))
    {
        Py::List list(obj);
        std::vector<const SMDS_MeshNode*> Nodes;
        for (Py::List::iterator it = list.begin(); it != list.end(); ++it) {
#if PY_MAJOR_VERSION >= 3
            Py::Long NoNr(*it);
#else
            Py::Int NoNr(*it);
#endif
            const SMDS_MeshNode* node = meshDS->FindNode(NoNr);
            if (!node)
                throw std::runtime_error("Failed to get node of the given indices");
            Nodes.push_back(node);
        }

        SMDS_MeshFace* face=0;
        if(ElementId != -1) {
            switch(Nodes.size()){
                case 3:
                    face = meshDS->AddFaceWithID(Nodes[0],Nodes[1],Nodes[2],ElementId);
                    if (!face)
                        throw std::runtime_error("Failed to add triangular face with given ElementId");
                    break;
                case 4:
                    face = meshDS->AddFaceWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],ElementId);
                    if (!face)
                        throw std::runtime_error("Failed to add face with given ElementId");
                    break;
                case 6:
                    face = meshDS->AddFaceWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],ElementId);
                    if (!face)
                        throw std::runtime_error("Failed to add face with given ElementId");
                    break;
                case 8:
                    face = meshDS->AddFaceWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],ElementId);
                    if (!face)
                        throw std::runtime_error("Failed to add face with given ElementId");
                    break;
                default:
                    throw std::runtime_error("Unknown node count, [3|4|6|8] are allowed"); //unknown face type
            }
        }else{
            switch(Nodes.size()){
                case 3:
                    face = meshDS->AddFace(Nodes[0],Nodes[1],Nodes[2]);
                    if (!face)
                        throw std::runtime_error("Failed to add triangular face");
                    break;
                case 4:
                    face = meshDS->AddFace(Nodes[0],Nodes[1],Nodes[2],Nodes[3]);
                    if (!face)
                        throw std::runtime_error("Failed to add face");
                    break;
                case 6:
                    face = meshDS->AddFace(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5]);
                    if (!face)
                        throw std::runtime_error("Failed to add face");
                    break;
                case 8:
                    face = meshDS->AddFace(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7]);
                    if (!face)
                        throw std::runtime_error("Failed to add face");
                    break;
                default:
                    throw std::runtime_error("Unknown node count, [4|5|6|8] are allowed"); //unknown face type
            }
        }

        return Py::new_reference_to(Py::Long(face->GetID()));

    }
    PyErr_SetString(PyExc_TypeError, "addFace accepts:\n"
        "-- int,int,int\n"
        "-- [3|4|6|8 int],[int]\n");
    return 0;
}
Esempio n. 17
0
PyObject* FemMeshPy::addEdge(PyObject *args)
{
    SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
    SMESHDS_Mesh* meshDS = mesh->GetMeshDS();

    int n1,n2;
    if (PyArg_ParseTuple(args, "ii",&n1,&n2)) {
        try {
            const SMDS_MeshNode* node1 = meshDS->FindNode(n1);
            const SMDS_MeshNode* node2 = meshDS->FindNode(n2);
            if (!node1 || !node2)
                throw std::runtime_error("Failed to get node of the given indices");
            SMDS_MeshEdge* edge = meshDS->AddEdge(node1, node2);
            if (!edge)
                throw std::runtime_error("Failed to add edge");
            return Py::new_reference_to(Py::Long(edge->GetID()));
        }
        catch (const std::exception& e) {
            PyErr_SetString(Base::BaseExceptionFreeCADError, e.what());
            return 0;
        }
    }
    PyErr_Clear();

    PyObject *obj;
    int ElementId=-1;
    if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId))
    {
        Py::List list(obj);
        std::vector<const SMDS_MeshNode*> Nodes;
        for (Py::List::iterator it = list.begin(); it != list.end(); ++it) {
#if PY_MAJOR_VERSION >= 3
            Py::Long NoNr(*it);
#else
            Py::Int NoNr(*it);
#endif
            const SMDS_MeshNode* node = meshDS->FindNode(NoNr);
            if (!node)
                throw std::runtime_error("Failed to get node of the given indices");
            Nodes.push_back(node);
        }

        SMDS_MeshEdge* edge=0;
        if(ElementId != -1) {
            switch(Nodes.size()){
                case 2:
                    edge = meshDS->AddEdgeWithID(Nodes[0],Nodes[1],ElementId);
                    if (!edge)
                        throw std::runtime_error("Failed to add edge with given ElementId");
                    break;
                case 3:
                    edge = meshDS->AddEdgeWithID(Nodes[0],Nodes[1],Nodes[2],ElementId);
                    if (!edge)
                        throw std::runtime_error("Failed to add edge with given ElementId");
                    break;
                default:
                    throw std::runtime_error("Unknown node count, [2|3] are allowed"); //unknown edge type
            }
        }
        else {
            switch(Nodes.size()){
            case 2:
                edge = meshDS->AddEdge(Nodes[0],Nodes[1]);
                if (!edge)
                    throw std::runtime_error("Failed to add edge");
                break;
            case 3:
                edge = meshDS->AddEdge(Nodes[0],Nodes[1],Nodes[2]);
                if (!edge)
                    throw std::runtime_error("Failed to add edge");
                break;
            default:
                throw std::runtime_error("Unknown node count, [2|3] are allowed"); //unknown edge type
            }
        }
#if PY_MAJOR_VERSION >= 3
        return Py::new_reference_to(Py::Long(edge->GetID()));
#else
        return Py::new_reference_to(Py::Int(edge->GetID()));
#endif
    }
    PyErr_SetString(PyExc_TypeError, "addEdge accepts:\n"
        "-- int,int\n"
        "-- [2|3],[int]\n");
    return 0;
}
bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
                                     const TopoDS_Shape& aShape)
{
  netgen::multithread.terminate = 0;
  netgen::multithread.task = "Volume meshing";
  _progressByTic = -1.;

  SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();

  SMESH_MesherHelper helper(aMesh);
  bool _quadraticMesh = helper.IsQuadraticSubMesh(aShape);
  helper.SetElementsOnShape( true );

  int Netgen_NbOfNodes = 0;
  double Netgen_point[3];
  int Netgen_triangle[3];

  NETGENPlugin_NetgenLibWrapper ngLib;
  Ng_Mesh * Netgen_mesh = ngLib._ngMesh;

  // vector of nodes in which node index == netgen ID
  vector< const SMDS_MeshNode* > nodeVec;
  {
    const int invalid_ID = -1;

    SMESH::Controls::Area areaControl;
    SMESH::Controls::TSequenceOfXYZ nodesCoords;

    // maps nodes to ng ID
    typedef map< const SMDS_MeshNode*, int, TIDCompare > TNodeToIDMap;
    typedef TNodeToIDMap::value_type                     TN2ID;
    TNodeToIDMap nodeToNetgenID;

    // find internal shapes
    NETGENPlugin_Internals internals( aMesh, aShape, /*is3D=*/true );

    // ---------------------------------
    // Feed the Netgen with surface mesh
    // ---------------------------------

    TopAbs_ShapeEnum mainType = aMesh.GetShapeToMesh().ShapeType();
    bool checkReverse = ( mainType == TopAbs_COMPOUND || mainType == TopAbs_COMPSOLID );

    SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( aMesh ));
    if ( _viscousLayersHyp )
    {
      netgen::multithread.percent = 3;
      proxyMesh = _viscousLayersHyp->Compute( aMesh, aShape );
      if ( !proxyMesh )
        return false;
    }
    if ( aMesh.NbQuadrangles() > 0 )
    {
      netgen::multithread.percent = 6;
      StdMeshers_QuadToTriaAdaptor* Adaptor = new StdMeshers_QuadToTriaAdaptor;
      Adaptor->Compute(aMesh,aShape,proxyMesh.get());
      proxyMesh.reset( Adaptor );
    }

    for ( TopExp_Explorer exFa( aShape, TopAbs_FACE ); exFa.More(); exFa.Next())
    {
      const TopoDS_Shape& aShapeFace = exFa.Current();
      int faceID = meshDS->ShapeToIndex( aShapeFace );
      bool isInternalFace = internals.isInternalShape( faceID );
      bool isRev = false;
      if ( checkReverse && !isInternalFace &&
           helper.NbAncestors(aShapeFace, aMesh, aShape.ShapeType()) > 1 )
        // IsReversedSubMesh() can work wrong on strongly curved faces,
        // so we use it as less as possible
        isRev = helper.IsReversedSubMesh( TopoDS::Face( aShapeFace ));

      const SMESHDS_SubMesh * aSubMeshDSFace = proxyMesh->GetSubMesh( aShapeFace );
      if ( !aSubMeshDSFace ) continue;
      SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
      while ( iteratorElem->more() ) // loop on elements on a geom face
      {
        // check mesh face
        const SMDS_MeshElement* elem = iteratorElem->next();
        if ( !elem )
          return error( COMPERR_BAD_INPUT_MESH, "Null element encounters");
        if ( elem->NbCornerNodes() != 3 )
          return error( COMPERR_BAD_INPUT_MESH, "Not triangle element encounters");

        // Add nodes of triangles and triangles them-selves to netgen mesh

        // add three nodes of triangle
        bool hasDegen = false;
        for ( int iN = 0; iN < 3; ++iN )
        {
          const SMDS_MeshNode* node = elem->GetNode( iN );
          const int shapeID = node->getshapeId();
          if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_EDGE &&
               helper.IsDegenShape( shapeID ))
          {
            // ignore all nodes on degeneraged edge and use node on its vertex instead
            TopoDS_Shape vertex = TopoDS_Iterator( meshDS->IndexToShape( shapeID )).Value();
            node = SMESH_Algo::VertexNode( TopoDS::Vertex( vertex ), meshDS );
            hasDegen = true;
          }
          int& ngID = nodeToNetgenID.insert(TN2ID( node, invalid_ID )).first->second;
          if ( ngID == invalid_ID )
          {
            ngID = ++Netgen_NbOfNodes;
            Netgen_point [ 0 ] = node->X();
            Netgen_point [ 1 ] = node->Y();
            Netgen_point [ 2 ] = node->Z();
            Ng_AddPoint(Netgen_mesh, Netgen_point);
          }
          Netgen_triangle[ isRev ? 2-iN : iN ] = ngID;
        }
        // add triangle
        if ( hasDegen && (Netgen_triangle[0] == Netgen_triangle[1] ||
                          Netgen_triangle[0] == Netgen_triangle[2] ||
                          Netgen_triangle[2] == Netgen_triangle[1] ))
          continue;

        Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle);

        if ( isInternalFace && !proxyMesh->IsTemporary( elem ))
        {
          swap( Netgen_triangle[1], Netgen_triangle[2] );
          Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle);
        }
      } // loop on elements on a face
    } // loop on faces of a SOLID or SHELL

    // insert old nodes into nodeVec
    nodeVec.resize( nodeToNetgenID.size() + 1, 0 );
    TNodeToIDMap::iterator n_id = nodeToNetgenID.begin();
    for ( ; n_id != nodeToNetgenID.end(); ++n_id )
      nodeVec[ n_id->second ] = n_id->first;
    nodeToNetgenID.clear();

    if ( internals.hasInternalVertexInSolid() )
    {
      netgen::OCCGeometry occgeo;
      NETGENPlugin_Mesher::AddIntVerticesInSolids( occgeo,
                                                   (netgen::Mesh&) *Netgen_mesh,
                                                   nodeVec,
                                                   internals);
    }
  }

  // -------------------------
  // Generate the volume mesh
  // -------------------------

  return ( ngLib._isComputeOk = compute( aMesh, helper, nodeVec, Netgen_mesh));
}
Esempio n. 19
0
PyObject* FemMeshPy::addVolume(PyObject *args)
{
    SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
    SMESHDS_Mesh* meshDS = mesh->GetMeshDS();

    int n1,n2,n3,n4;
    if (PyArg_ParseTuple(args, "iiii",&n1,&n2,&n3,&n4))
    {
        try {
            const SMDS_MeshNode* node1 = meshDS->FindNode(n1);
            const SMDS_MeshNode* node2 = meshDS->FindNode(n2);
            const SMDS_MeshNode* node3 = meshDS->FindNode(n3);
            const SMDS_MeshNode* node4 = meshDS->FindNode(n4);
            if (!node1 || !node2 || !node3 || !node4)
                throw std::runtime_error("Failed to get node of the given indices");
            SMDS_MeshVolume* vol = meshDS->AddVolume(node1, node2, node3, node4);
            if (!vol)
                throw std::runtime_error("Failed to add volume");
            return Py::new_reference_to(Py::Int(vol->GetID()));
        }
        catch (const std::exception& e) {
            PyErr_SetString(Base::BaseExceptionFreeCADError, e.what());
            return 0;
        }
    }
    PyErr_Clear();

    PyObject *obj;
    int ElementId=-1;
    if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId))
    {
        Py::List list(obj);
        std::vector<const SMDS_MeshNode*> Nodes;
        for (Py::List::iterator it = list.begin(); it != list.end(); ++it) {
            Py::Int NoNr(*it);
            const SMDS_MeshNode* node = meshDS->FindNode(NoNr);
            if (!node)
                throw std::runtime_error("Failed to get node of the given indices");
            Nodes.push_back(node);
        }
        
        SMDS_MeshVolume* vol=0;
        if(ElementId != -1) {
            switch(Nodes.size()){
                case 4:
                    vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],ElementId);
                    if (!vol)
                        throw std::runtime_error("Failed to add Tet4 volume");
                    break;
                case 8:
                    vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],ElementId);
                    if (!vol)
                        throw std::runtime_error("Failed to add Tet10 volume");
                    break;
                case 10:
                    vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9],ElementId);
                    if (!vol)
                        throw std::runtime_error("Failed to add Tet10 volume");
                    break;

                default: throw std::runtime_error("Unknown node count, [4|5|6|8|10|13|18] are allowed"); //unknown face type
            }
        }else{
            switch(Nodes.size()){
                case 4:
                    vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3]);
                    if (!vol)
                        throw std::runtime_error("Failed to add Tet4 volume");
                    break;
                case 8:
                    vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7]);
                    if (!vol)
                        throw std::runtime_error("Failed to add Tet10 volume");
                    break;
                case 10:
                    vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9]);
                    if (!vol)
                        throw std::runtime_error("Failed to add Tet10 volume");
                    break;

                default: throw std::runtime_error("Unknown node count, [4|5|6|8|10|13|18] are allowed"); //unknown face type
            }

        }

        return Py::new_reference_to(Py::Int(vol->GetID()));

    }

    PyErr_SetString(PyExc_TypeError, "Line constructor accepts:\n"
        "-- empty parameter list\n"
        "-- Line\n"
        "-- Point, Point");
    return 0;

}
bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh&         aMesh,
                                          const TopoDS_Shape& aShape)
{
  MESSAGE("NETGENPlugin_NETGEN_2D_ONLY::Compute()");

  SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
  int faceID = meshDS->ShapeToIndex( aShape );

  SMESH_MesherHelper helper(aMesh);
  _quadraticMesh = helper.IsQuadraticSubMesh(aShape);
  helper.SetElementsOnShape( true );
  const bool ignoreMediumNodes = _quadraticMesh;
  
  // ------------------------
  // get all edges of a face
  // ------------------------
  const TopoDS_Face F = TopoDS::Face( aShape.Oriented( TopAbs_FORWARD ));
  TError problem;
  TSideVector wires = StdMeshers_FaceSide::GetFaceWires( F, aMesh, ignoreMediumNodes, problem );
  if ( problem && !problem->IsOK() )
    return error( problem );
  int nbWires = wires.size();
  if ( nbWires == 0 )
    return error( "Problem in StdMeshers_FaceSide::GetFaceWires()");
  if ( wires[0]->NbSegments() < 3 ) // ex: a circle with 2 segments
    return error(COMPERR_BAD_INPUT_MESH,
                 SMESH_Comment("Too few segments: ")<<wires[0]->NbSegments());

  // -------------------------
  // Make input netgen mesh
  // -------------------------

  Ng_Init();
  netgen::Mesh * ngMesh = new netgen::Mesh ();

  netgen::OCCGeometry occgeo;
  NETGENPlugin_Mesher::PrepareOCCgeometry( occgeo, F, aMesh );
  occgeo.fmap.Clear(); // face can be reversed, which is wrong in this case (issue 19978)
  occgeo.fmap.Add( F );

  vector< const SMDS_MeshNode* > nodeVec;
  problem = AddSegmentsToMesh( *ngMesh, occgeo, wires, helper, nodeVec );
  if ( problem && !problem->IsOK() ) {
    delete ngMesh; Ng_Exit();
    return error( problem );
  }

  // --------------------
  // compute edge length
  // --------------------

  double edgeLength = 0;
  if (_hypLengthFromEdges || (!_hypLengthFromEdges && !_hypMaxElementArea))
  {
    int nbSegments = 0;
    for ( int iW = 0; iW < nbWires; ++iW )
    {
      edgeLength += wires[ iW ]->Length();
      nbSegments += wires[ iW ]->NbSegments();
    }
    if ( nbSegments )
      edgeLength /= nbSegments;
  }
  if ( _hypMaxElementArea )
  {
    double maxArea = _hypMaxElementArea->GetMaxArea();
    edgeLength = sqrt(2. * maxArea/sqrt(3.0));
  }
  if ( edgeLength < DBL_MIN )
    edgeLength = occgeo.GetBoundingBox().Diam();

  //cout << " edgeLength = " << edgeLength << endl;

  netgen::mparam.maxh = edgeLength;
  netgen::mparam.quad = _hypQuadranglePreference ? 1 : 0;
  //ngMesh->SetGlobalH ( edgeLength );

  // -------------------------
  // Generate surface mesh
  // -------------------------

  char *optstr = 0;
  int startWith = MESHCONST_MESHSURFACE;
  int endWith   = MESHCONST_OPTSURFACE;
  int err = 1;

  try {
#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
    OCC_CATCH_SIGNALS;
#endif
#ifdef NETGEN_V5
    err = netgen::OCCGenerateMesh(occgeo, ngMesh,netgen::mparam, startWith, endWith);
#else
    err = netgen::OCCGenerateMesh(occgeo, ngMesh, startWith, endWith, optstr);
#endif
  }
  catch (Standard_Failure& ex) {
    string comment = ex.DynamicType()->Name();
    if ( ex.GetMessageString() && strlen( ex.GetMessageString() )) {
      comment += ": ";
      comment += ex.GetMessageString();
    }
    error(COMPERR_OCC_EXCEPTION, comment);
  }
  catch (NgException exc) {
    error( SMESH_Comment("NgException: ") << exc.What() );
  }
  catch (...) {
    error(COMPERR_EXCEPTION,"Exception in netgen::OCCGenerateMesh()");
  }

  // ----------------------------------------------------
  // Fill the SMESHDS with the generated nodes and faces
  // ----------------------------------------------------

  int nbNodes = ngMesh->GetNP();
  int nbFaces = ngMesh->GetNSE();

  int nbInputNodes = nodeVec.size();
  nodeVec.resize( nbNodes, 0 );

  // add nodes
  for ( int i = nbInputNodes + 1; i <= nbNodes; ++i )
  {
    const MeshPoint& ngPoint = ngMesh->Point(i);
    SMDS_MeshNode * node = meshDS->AddNode(ngPoint(0), ngPoint(1), ngPoint(2));
    nodeVec[ i-1 ] = node;
  }

  // create faces
  bool reverse = ( aShape.Orientation() == TopAbs_REVERSED );
  for ( int i = 1; i <= nbFaces ; ++i )
  {
    const Element2d& elem = ngMesh->SurfaceElement(i);
    vector<const SMDS_MeshNode*> nodes( elem.GetNP() );
    for (int j=1; j <= elem.GetNP(); ++j)
    {
      int pind = elem.PNum(j);
      const SMDS_MeshNode* node = nodeVec.at(pind-1);
      if ( reverse )
        nodes[ nodes.size()-j ] = node;
      else
        nodes[ j-1 ] = node;
      if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_3DSPACE )
      {
        const PointGeomInfo& pgi = elem.GeomInfoPi(j);
        meshDS->SetNodeOnFace((SMDS_MeshNode*)node, faceID, pgi.u, pgi.v);
      }
    }
    SMDS_MeshFace* face = 0;
    if ( elem.GetType() == TRIG )
      face = helper.AddFace(nodes[0],nodes[1],nodes[2]);
    else
      face = helper.AddFace(nodes[0],nodes[1],nodes[2],nodes[3]);
  }

  Ng_DeleteMesh((nglib::Ng_Mesh*)ngMesh);
  Ng_Exit();

  NETGENPlugin_Mesher::RemoveTmpFiles();

  return !err;
}
Esempio n. 21
0
PyObject* FemMeshPy::addVolume(PyObject *args)
{
    SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
    SMESHDS_Mesh* meshDS = mesh->GetMeshDS();

    int n1,n2,n3,n4;
    if (PyArg_ParseTuple(args, "iiii",&n1,&n2,&n3,&n4))
    {
        try {
            const SMDS_MeshNode* node1 = meshDS->FindNode(n1);
            const SMDS_MeshNode* node2 = meshDS->FindNode(n2);
            const SMDS_MeshNode* node3 = meshDS->FindNode(n3);
            const SMDS_MeshNode* node4 = meshDS->FindNode(n4);
            if (!node1 || !node2 || !node3 || !node4)
                throw std::runtime_error("Failed to get node of the given indices");
            SMDS_MeshVolume* vol = meshDS->AddVolume(node1, node2, node3, node4);
            if (!vol)
                throw std::runtime_error("Failed to add volume");
            return Py::new_reference_to(Py::Long(vol->GetID()));
        }
        catch (const std::exception& e) {
            PyErr_SetString(Base::BaseExceptionFreeCADError, e.what());
            return 0;
        }
    }
    PyErr_Clear();

    PyObject *obj;
    int ElementId=-1;
    if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId))
    {
        Py::List list(obj);
        std::vector<const SMDS_MeshNode*> Nodes;
        for (Py::List::iterator it = list.begin(); it != list.end(); ++it) {
#if PY_MAJOR_VERSION >= 3
            Py::Long NoNr(*it);
#else
            Py::Int NoNr(*it);
#endif
            const SMDS_MeshNode* node = meshDS->FindNode(NoNr);
            if (!node)
                throw std::runtime_error("Failed to get node of the given indices");
            Nodes.push_back(node);
        }

        SMDS_MeshVolume* vol=0;
        if(ElementId != -1) {
            switch(Nodes.size()){
                case 4:
                    vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],ElementId);
                    if (!vol)
                        throw std::runtime_error("Failed to add Tet4 volume with given ElementId");
                    break;
                case 5:
                    vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],ElementId);
                    if (!vol)
                        throw std::runtime_error("Failed to add Pyra5 volume with given ElementId");
                    break;
                case 6:
                    vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],ElementId);
                    if (!vol)
                        throw std::runtime_error("Failed to add Penta6 volume with given ElementId");
                    break;
                case 8:
                    vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],ElementId);
                    if (!vol)
                        throw std::runtime_error("Failed to add Hexa8 volume with given ElementId");
                    break;
                case 10:
                    vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9],ElementId);
                    if (!vol)
                        throw std::runtime_error("Failed to add Tet10 volume with given ElementId");
                    break;
                case 13:
                    vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9],Nodes[10],Nodes[11],Nodes[12],ElementId);
                    if (!vol)
                        throw std::runtime_error("Failed to add Pyra13 volume with given ElementId");
                    break;
                case 15:
                    vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9],Nodes[10],Nodes[11],Nodes[12],Nodes[13],Nodes[14],ElementId);
                    if (!vol)
                        throw std::runtime_error("Failed to add Penta15 volume with given ElementId");
                    break;
                case 20:
                    vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9],Nodes[10],Nodes[11],Nodes[12],Nodes[13],Nodes[14],Nodes[15],Nodes[16],Nodes[17],Nodes[18],Nodes[19],ElementId);
                    if (!vol)
                        throw std::runtime_error("Failed to add Hexa20 volume with given ElementId");
                    break;
                default: throw std::runtime_error("Unknown node count, [4|5|6|8|10|13|15|20] are allowed"); //unknown volume type
            }
        }else{
            switch(Nodes.size()){
                case 4:
                    vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3]);
                    if (!vol)
                        throw std::runtime_error("Failed to add Tet4 volume");
                    break;
                case 5:
                    vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4]);
                    if (!vol)
                        throw std::runtime_error("Failed to add Pyra5 volume");
                    break;
                case 6:
                    vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5]);
                    if (!vol)
                        throw std::runtime_error("Failed to add Penta6 volume");
                    break;
                case 8:
                    vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7]);
                    if (!vol)
                        throw std::runtime_error("Failed to add Hexa8 volume");
                    break;
                case 10:
                    vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9]);
                    if (!vol)
                        throw std::runtime_error("Failed to add Tet10 volume");
                    break;
                case 13:
                    vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9],Nodes[10],Nodes[11],Nodes[12]);
                    if (!vol)
                        throw std::runtime_error("Failed to add Pyra13 volume");
                    break;
                case 15:
                    vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9],Nodes[10],Nodes[11],Nodes[12],Nodes[13],Nodes[14]);
                    if (!vol)
                        throw std::runtime_error("Failed to add Penta15 volume");
                    break;
                case 20:
                    vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9],Nodes[10],Nodes[11],Nodes[12],Nodes[13],Nodes[14],Nodes[15],Nodes[16],Nodes[17],Nodes[18],Nodes[19]);
                    if (!vol)
                        throw std::runtime_error("Failed to add Hexa20 volume");
                    break;
                default: throw std::runtime_error("Unknown node count, [4|5|6|8|10|13|15|20] are allowed"); //unknown volume type
            }
        }

        return Py::new_reference_to(Py::Long(vol->GetID()));

    }
    PyErr_SetString(PyExc_TypeError, "addVolume accepts:\n"
        "-- int,int,int,int\n"
        "-- [4|5|6|8|10|13|15|20 int],[int]\n");
    return 0;
}
Esempio n. 22
0
bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
                        const TopoDS_Shape &  aShape,
                        const bool            aShapeOnly /*=false*/,
                        const bool            anUpward /*=false*/,
                        const ::MeshDimension aDim /*=::MeshDim_3D*/,
                        TSetOfInt*            aShapesId /*=0*/)
{
  MESSAGE("SMESH_Gen::Compute");
  MEMOSTAT;

  bool ret = true;

  SMESH_subMesh *sm = aMesh.GetSubMesh(aShape);

  const bool includeSelf = true;
  const bool complexShapeFirst = true;
  const int  globalAlgoDim = 100;

  SMESH_subMeshIteratorPtr smIt;

  // Fix of Issue 22150. Due to !BLSURF->OnlyUnaryInput(), BLSURF computes edges
  // that must be computed by Projection 1D-2D when Projection asks to compute
  // one face only.
  SMESH_subMesh::compute_event computeEvent =
    aShapeOnly ? SMESH_subMesh::COMPUTE_SUBMESH : SMESH_subMesh::COMPUTE;

  if ( anUpward ) // is called from the below code in this method
  {
    // ===============================================
    // Mesh all the sub-shapes starting from vertices
    // ===============================================

    smIt = sm->getDependsOnIterator(includeSelf, !complexShapeFirst);
    while ( smIt->more() )
    {
      SMESH_subMesh* smToCompute = smIt->next();

      // do not mesh vertices of a pseudo shape
      const TopoDS_Shape&        shape = smToCompute->GetSubShape();
      const TopAbs_ShapeEnum shapeType = shape.ShapeType();
      if ( !aMesh.HasShapeToMesh() && shapeType == TopAbs_VERTEX )
        continue;

      // check for preview dimension limitations
      if ( aShapesId && GetShapeDim( shapeType ) > (int)aDim )
      {
        // clear compute state not to show previous compute errors
        //  if preview invoked less dimension less than previous
        smToCompute->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
        continue;
      }

      if (smToCompute->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE)
      {
        if (_compute_canceled)
          return false;
        setCurrentSubMesh( smToCompute );
        smToCompute->ComputeStateEngine( computeEvent );
        setCurrentSubMesh( NULL );
      }

      // we check all the sub-meshes here and detect if any of them failed to compute
      if (smToCompute->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE &&
          ( shapeType != TopAbs_EDGE || !SMESH_Algo::isDegenerated( TopoDS::Edge( shape ))))
        ret = false;
      else if ( aShapesId )
        aShapesId->insert( smToCompute->GetId() );
    }
    //aMesh.GetMeshDS()->Modified();
    return ret;
  }
  else
  {
    // ================================================================
    // Apply algos that do NOT require discreteized boundaries
    // ("all-dimensional") and do NOT support sub-meshes, starting from
    // the most complex shapes and collect sub-meshes with algos that 
    // DO support sub-meshes
    // ================================================================

    list< SMESH_subMesh* > smWithAlgoSupportingSubmeshes[4]; // for each dim

    // map to sort sm with same dim algos according to dim of
    // the shape the algo assigned to (issue 0021217).
    // Other issues influenced the algo applying order:
    // 21406, 21556, 21893, 20206
    multimap< int, SMESH_subMesh* > shDim2sm;
    multimap< int, SMESH_subMesh* >::reverse_iterator shDim2smIt;
    TopoDS_Shape algoShape;
    int prevShapeDim = -1, aShapeDim;

    smIt = sm->getDependsOnIterator(includeSelf, complexShapeFirst);
    while ( smIt->more() )
    {
      SMESH_subMesh* smToCompute = smIt->next();
      if ( smToCompute->GetComputeState() != SMESH_subMesh::READY_TO_COMPUTE )
        continue;

      const TopoDS_Shape& aSubShape = smToCompute->GetSubShape();
      aShapeDim = GetShapeDim( aSubShape );
      if ( aShapeDim < 1 ) break;
      
      // check for preview dimension limitations
      if ( aShapesId && aShapeDim > (int)aDim )
        continue;

      SMESH_Algo* algo = GetAlgo( smToCompute, &algoShape );
      if ( algo && !algo->NeedDiscreteBoundary() )
      {
        if ( algo->SupportSubmeshes() )
        {
          // reload sub-meshes from shDim2sm into smWithAlgoSupportingSubmeshes
          // so that more local algos to go first
          if ( prevShapeDim != aShapeDim )
          {
            prevShapeDim = aShapeDim;
            for ( shDim2smIt = shDim2sm.rbegin(); shDim2smIt != shDim2sm.rend(); ++shDim2smIt )
              if ( shDim2smIt->first == globalAlgoDim )
                smWithAlgoSupportingSubmeshes[ aShapeDim ].push_back( shDim2smIt->second );
              else
                smWithAlgoSupportingSubmeshes[ aShapeDim ].push_front( shDim2smIt->second );
            shDim2sm.clear();
          }
          // add smToCompute to shDim2sm map
          if ( algoShape.IsSame( aMesh.GetShapeToMesh() ))
          {
            aShapeDim = globalAlgoDim; // to compute last
          }
          else
          {
            aShapeDim = GetShapeDim( algoShape );
            if ( algoShape.ShapeType() == TopAbs_COMPOUND )
            {
              TopoDS_Iterator it( algoShape );
              aShapeDim += GetShapeDim( it.Value() );
            }
          }
          shDim2sm.insert( make_pair( aShapeDim, smToCompute ));
        }
        else // Compute w/o support of sub-meshes
        {
          if (_compute_canceled)
            return false;
          setCurrentSubMesh( smToCompute );
          smToCompute->ComputeStateEngine( computeEvent );
          setCurrentSubMesh( NULL );
          if ( aShapesId )
            aShapesId->insert( smToCompute->GetId() );
        }
      }
    }
    // reload sub-meshes from shDim2sm into smWithAlgoSupportingSubmeshes
    for ( shDim2smIt = shDim2sm.rbegin(); shDim2smIt != shDim2sm.rend(); ++shDim2smIt )
      if ( shDim2smIt->first == globalAlgoDim )
        smWithAlgoSupportingSubmeshes[3].push_back( shDim2smIt->second );
      else
        smWithAlgoSupportingSubmeshes[0].push_front( shDim2smIt->second );

    // ======================================================
    // Apply all-dimensional algorithms supporing sub-meshes
    // ======================================================

    std::vector< SMESH_subMesh* > smVec;
    for ( aShapeDim = 0; aShapeDim < 4; ++aShapeDim )
    {
      // ------------------------------------------------
      // sort list of sub-meshes according to mesh order
      // ------------------------------------------------
      smVec.assign( smWithAlgoSupportingSubmeshes[ aShapeDim ].begin(),
                    smWithAlgoSupportingSubmeshes[ aShapeDim ].end() );
      aMesh.SortByMeshOrder( smVec );

      // ------------------------------------------------------------
      // compute sub-meshes with local uni-dimensional algos under
      // sub-meshes with all-dimensional algos
      // ------------------------------------------------------------
      // start from lower shapes
      for ( size_t i = 0; i < smVec.size(); ++i )
      {
        sm = smVec[i];

        // get a shape the algo is assigned to
        if ( !GetAlgo( sm, & algoShape ))
          continue; // strange...

        // look for more local algos
        smIt = sm->getDependsOnIterator(!includeSelf, !complexShapeFirst);
        while ( smIt->more() )
        {
          SMESH_subMesh* smToCompute = smIt->next();

          const TopoDS_Shape& aSubShape = smToCompute->GetSubShape();
          const int aShapeDim = GetShapeDim( aSubShape );
          //if ( aSubShape.ShapeType() == TopAbs_VERTEX ) continue;
          if ( aShapeDim < 1 ) continue;

          // check for preview dimension limitations
          if ( aShapesId && GetShapeDim( aSubShape.ShapeType() ) > (int)aDim )
            continue;

          SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() );
          filter
            .And( SMESH_HypoFilter::IsApplicableTo( aSubShape ))
            .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape, aMesh ));

          if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( smToCompute, filter, true))
          {
            if ( ! subAlgo->NeedDiscreteBoundary() ) continue;
            SMESH_Hypothesis::Hypothesis_Status status;
            if ( subAlgo->CheckHypothesis( aMesh, aSubShape, status ))
              // mesh a lower smToCompute starting from vertices
              Compute( aMesh, aSubShape, aShapeOnly, /*anUpward=*/true, aDim, aShapesId );
          }
        }
      }
      // --------------------------------
      // apply the all-dimensional algos
      // --------------------------------
      for ( size_t i = 0; i < smVec.size(); ++i )
      {
        sm = smVec[i];
        if ( sm->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE)
        {
          const TopAbs_ShapeEnum shapeType = sm->GetSubShape().ShapeType();
          // check for preview dimension limitations
          if ( aShapesId && GetShapeDim( shapeType ) > (int)aDim )
            continue;

          if (_compute_canceled)
            return false;
          setCurrentSubMesh( sm );
          sm->ComputeStateEngine( computeEvent );
          setCurrentSubMesh( NULL );
          if ( aShapesId )
            aShapesId->insert( sm->GetId() );
        }
      }
    } // loop on shape dimensions

    // -----------------------------------------------
    // mesh the rest sub-shapes starting from vertices
    // -----------------------------------------------
    ret = Compute( aMesh, aShape, aShapeOnly, /*anUpward=*/true, aDim, aShapesId );
  }

  MESSAGE( "VSR - SMESH_Gen::Compute() finished, OK = " << ret);
  MEMOSTAT;

  SMESHDS_Mesh *myMesh = aMesh.GetMeshDS();
  MESSAGE("*** compactMesh after compute");
  myMesh->compactMesh();

  // fix quadratic mesh by bending iternal links near concave boundary
  if ( aShape.IsSame( aMesh.GetShapeToMesh() ) &&
       !aShapesId && // not preview
       ret ) // everything is OK
  {
    SMESH_MesherHelper aHelper( aMesh );
    if ( aHelper.IsQuadraticMesh() != SMESH_MesherHelper::LINEAR )
    {
      aHelper.FixQuadraticElements( sm->GetComputeError() );
    }
  }
  return ret;
}
Esempio n. 23
0
PyObject* FemMeshPy::addFace(PyObject *args)
{
    SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
    SMESHDS_Mesh* meshDS = mesh->GetMeshDS();

    int n1,n2,n3;
    if (PyArg_ParseTuple(args, "iii",&n1,&n2,&n3))
    {
        // old form, debrekadet
        try {
            const SMDS_MeshNode* node1 = meshDS->FindNode(n1);
            const SMDS_MeshNode* node2 = meshDS->FindNode(n2);
            const SMDS_MeshNode* node3 = meshDS->FindNode(n3);
            if (!node1 || !node2 || !node3)
                throw std::runtime_error("Failed to get node of the given indices");
            SMDS_MeshFace* face = meshDS->AddFace(node1, node2, node3);
            if (!face)
                throw std::runtime_error("Failed to add face");
            return Py::new_reference_to(Py::Int(face->GetID()));
        }
        catch (const std::exception& e) {
            PyErr_SetString(Base::BaseExceptionFreeCADError, e.what());
            return 0;
        }
    }
    PyErr_Clear();

    PyObject *obj;
    int ElementId=-1;
    if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId))
    {
        Py::List list(obj);
        std::vector<const SMDS_MeshNode*> Nodes;
        for (Py::List::iterator it = list.begin(); it != list.end(); ++it) {
            Py::Int NoNr(*it);
            const SMDS_MeshNode* node = meshDS->FindNode(NoNr);
            if (!node)
                throw std::runtime_error("Failed to get node of the given indices");
            Nodes.push_back(node);
        }
        
        SMDS_MeshFace* face=0;
        switch(Nodes.size()){
            case 3:
                face = meshDS->AddFace(Nodes[0],Nodes[1],Nodes[2]);
                if (!face)
                    throw std::runtime_error("Failed to add triangular face");
                break;

            default: throw std::runtime_error("Unknown node count, [3|4|6|8] are allowed"); //unknown face type
        }

        return Py::new_reference_to(Py::Int(face->GetID()));

    }

    PyErr_SetString(PyExc_TypeError, "Line constructor accepts:\n"
        "-- empty parameter list\n"
        "-- Line\n"
        "-- Point, Point");
    return 0;

}
Esempio n. 24
0
bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh& aMesh,
                                     SMESH_MesherHelper* aHelper)
{
    MESSAGE("NETGENPlugin_NETGEN_3D::Compute with maxElmentsize = " << _maxElementVolume);
    const int invalid_ID = -1;
    bool _quadraticMesh = false;
    typedef map< const SMDS_MeshNode*, int, TIDCompare > TNodeToIDMap;
    TNodeToIDMap nodeToNetgenID;
    list< const SMDS_MeshElement* > triangles;
    SMESHDS_Mesh* MeshDS = aHelper->GetMeshDS();

    SMESH_MesherHelper::MType MeshType = aHelper->IsQuadraticMesh();

    if(MeshType == SMESH_MesherHelper::COMP)
        return error( COMPERR_BAD_INPUT_MESH,
                      SMESH_Comment("Mesh with linear and quadratic elements given."));
    else if (MeshType == SMESH_MesherHelper::QUADRATIC)
        _quadraticMesh = true;

    StdMeshers_QuadToTriaAdaptor Adaptor;
    Adaptor.Compute(aMesh);

    SMDS_FaceIteratorPtr fIt = MeshDS->facesIterator();
    TIDSortedElemSet sortedFaces; //  0020279: control the "random" use when using mesh algorithms
    while( fIt->more()) sortedFaces.insert( fIt->next() );

    TIDSortedElemSet::iterator itFace = sortedFaces.begin(), fEnd = sortedFaces.end();
    for ( ; itFace != fEnd; ++itFace ) {
        // check element
        const SMDS_MeshElement* elem = *itFace;
        if ( !elem )
            return error( COMPERR_BAD_INPUT_MESH, "Null element encounters");
        bool isTraingle = ( elem->NbNodes()==3 || (_quadraticMesh && elem->NbNodes()==6 ));
        if ( !isTraingle ) {
            //return error( COMPERR_BAD_INPUT_MESH,
            //              SMESH_Comment("Not triangle element ")<<elem->GetID());
            // using adaptor
            const list<const SMDS_FaceOfNodes*>* faces = Adaptor.GetTriangles(elem);
            if(faces==0) {
                return error( COMPERR_BAD_INPUT_MESH,
                              SMESH_Comment("Not triangles in adaptor for element ")<<elem->GetID());
            }
            list<const SMDS_FaceOfNodes*>::const_iterator itf = faces->begin();
            for(; itf!=faces->end(); itf++ ) {
                triangles.push_back( (*itf) );
                // put triange's nodes to nodeToNetgenID map
                SMDS_ElemIteratorPtr triangleNodesIt = (*itf)->nodesIterator();
                while ( triangleNodesIt->more() ) {
                    const SMDS_MeshNode * node =
                        static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
                    if(aHelper->IsMedium(node))
                        continue;
                    nodeToNetgenID.insert( make_pair( node, invalid_ID ));
                }
            }
        }
        else {
            // keep a triangle
            triangles.push_back( elem );
            // put elem nodes to nodeToNetgenID map
            SMDS_ElemIteratorPtr triangleNodesIt = elem->nodesIterator();
            while ( triangleNodesIt->more() ) {
                const SMDS_MeshNode * node =
                    static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
                if(aHelper->IsMedium(node))
                    continue;
                nodeToNetgenID.insert( make_pair( node, invalid_ID ));
            }
        }
    }

    // ---------------------------------
    // Feed the Netgen with surface mesh
    // ---------------------------------

    int Netgen_NbOfNodes = 0;
    int Netgen_param2ndOrder = 0;
    double Netgen_paramFine = 1.;
    double Netgen_paramSize = pow( 72, 1/6. ) * pow( _maxElementVolume, 1/3. );

    double Netgen_point[3];
    int Netgen_triangle[3];
    int Netgen_tetrahedron[4];

    Ng_Init();

    Ng_Mesh * Netgen_mesh = Ng_NewMesh();

    // set nodes and remember thier netgen IDs

    TNodeToIDMap::iterator n_id = nodeToNetgenID.begin();
    for ( ; n_id != nodeToNetgenID.end(); ++n_id )
    {
        const SMDS_MeshNode* node = n_id->first;

        Netgen_point [ 0 ] = node->X();
        Netgen_point [ 1 ] = node->Y();
        Netgen_point [ 2 ] = node->Z();
        Ng_AddPoint(Netgen_mesh, Netgen_point);
        n_id->second = ++Netgen_NbOfNodes; // set netgen ID

    }

    // set triangles
    list< const SMDS_MeshElement* >::iterator tria = triangles.begin();
    for ( ; tria != triangles.end(); ++tria)
    {
        int i = 0;
        SMDS_ElemIteratorPtr triangleNodesIt = (*tria)->nodesIterator();
        while ( triangleNodesIt->more() ) {
            const SMDS_MeshNode * node =
                static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
            if(aHelper->IsMedium(node))
                continue;
            Netgen_triangle[ i ] = nodeToNetgenID[ node ];
            ++i;
        }

        Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle);
    }

    // -------------------------
    // Generate the volume mesh
    // -------------------------

    Ng_Meshing_Parameters Netgen_param;

    Netgen_param.secondorder = Netgen_param2ndOrder;
    Netgen_param.fineness = Netgen_paramFine;
    Netgen_param.maxh = Netgen_paramSize;

    Ng_Result status;

    try {
#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
        OCC_CATCH_SIGNALS;
#endif
        status = Ng_GenerateVolumeMesh(Netgen_mesh, &Netgen_param);
    }
    catch (Standard_Failure& exc) {
        error(COMPERR_OCC_EXCEPTION, exc.GetMessageString());
        status = NG_VOLUME_FAILURE;
    }
    catch (...) {
        error("Bad mesh input!!!");
        status = NG_VOLUME_FAILURE;
    }
    if ( GetComputeError()->IsOK() ) {
        error( status, "Bad mesh input!!!");
    }

    int Netgen_NbOfNodesNew = Ng_GetNP(Netgen_mesh);

    int Netgen_NbOfTetra = Ng_GetNE(Netgen_mesh);

    MESSAGE("End of Volume Mesh Generation. status=" << status <<
            ", nb new nodes: " << Netgen_NbOfNodesNew - Netgen_NbOfNodes <<
            ", nb tetra: " << Netgen_NbOfTetra);

    // -------------------------------------------------------------------
    // Feed back the SMESHDS with the generated Nodes and Volume Elements
    // -------------------------------------------------------------------

    bool isOK = ( Netgen_NbOfTetra > 0 );// get whatever built
    if ( isOK )
    {
        // vector of nodes in which node index == netgen ID
        vector< const SMDS_MeshNode* > nodeVec ( Netgen_NbOfNodesNew + 1 );
        // insert old nodes into nodeVec
        for ( n_id = nodeToNetgenID.begin(); n_id != nodeToNetgenID.end(); ++n_id ) {
            nodeVec.at( n_id->second ) = n_id->first;
        }
        // create and insert new nodes into nodeVec
        int nodeIndex = Netgen_NbOfNodes + 1;

        for ( ; nodeIndex <= Netgen_NbOfNodesNew; ++nodeIndex )
        {
            Ng_GetPoint( Netgen_mesh, nodeIndex, Netgen_point );
            SMDS_MeshNode * node = aHelper->AddNode(Netgen_point[0],
                                                    Netgen_point[1],
                                                    Netgen_point[2]);
            nodeVec.at(nodeIndex) = node;
        }

        // create tetrahedrons
        for ( int elemIndex = 1; elemIndex <= Netgen_NbOfTetra; ++elemIndex )
        {
            Ng_GetVolumeElement(Netgen_mesh, elemIndex, Netgen_tetrahedron);
            aHelper->AddVolume (nodeVec.at( Netgen_tetrahedron[0] ),
                                nodeVec.at( Netgen_tetrahedron[1] ),
                                nodeVec.at( Netgen_tetrahedron[2] ),
                                nodeVec.at( Netgen_tetrahedron[3] ));
        }
    }

    Ng_DeleteMesh(Netgen_mesh);
    Ng_Exit();

    NETGENPlugin_Mesher::RemoveTmpFiles();

    return (status == NG_OK);
}
Esempio n. 25
0
/*!
 * Special function for search or creation medium node
 */
const SMDS_MeshNode* SMESH_MesherHelper::GetMediumNode(const SMDS_MeshNode* n1,
                                                       const SMDS_MeshNode* n2,
                                                       bool force3d)
{
  TopAbs_ShapeEnum shapeType = myShape.IsNull() ? TopAbs_SHAPE : myShape.ShapeType();

  NLink link(( n1 < n2 ? n1 : n2 ), ( n1 < n2 ? n2 : n1 ));
  ItNLinkNode itLN = myNLinkNodeMap.find( link );
  if ( itLN != myNLinkNodeMap.end() ) {
    return (*itLN).second;
  }
  else {
    // create medium node
    SMDS_MeshNode* n12;
    SMESHDS_Mesh* meshDS = GetMeshDS();
    int faceID = -1, edgeID = -1;
    const SMDS_PositionPtr Pos1 = n1->GetPosition();
    const SMDS_PositionPtr Pos2 = n2->GetPosition();
  
    if( myShape.IsNull() )
    {
      if( Pos1->GetTypeOfPosition()==SMDS_TOP_FACE ) {
        faceID = Pos1->GetShapeId();
      }
      else if( Pos2->GetTypeOfPosition()==SMDS_TOP_FACE ) {
        faceID = Pos2->GetShapeId();
      }

      if( Pos1->GetTypeOfPosition()==SMDS_TOP_EDGE ) {
        edgeID = Pos1->GetShapeId();
      }
      if( Pos2->GetTypeOfPosition()==SMDS_TOP_EDGE ) {
        edgeID = Pos2->GetShapeId();
      }
    }

    if(!force3d) {
      // we try to create medium node using UV parameters of
      // nodes, else - medium between corresponding 3d points
      if(faceID>-1 || shapeType == TopAbs_FACE) {
	// obtaining a face and 2d points for nodes
	TopoDS_Face F;
	if( myShape.IsNull() )
          F = TopoDS::Face(meshDS->IndexToShape(faceID));
	else {
          F = TopoDS::Face(myShape);
          faceID = myShapeID;
        }

	gp_XY p1 = GetNodeUV(F,n1,n2);
        gp_XY p2 = GetNodeUV(F,n2,n1);

	if ( IsDegenShape( Pos1->GetShapeId() ))
	  p1.SetCoord( myParIndex, p2.Coord( myParIndex ));
	else if ( IsDegenShape( Pos2->GetShapeId() ))
	  p2.SetCoord( myParIndex, p1.Coord( myParIndex ));

	//checking if surface is periodic
	Handle(Geom_Surface) S = BRep_Tool::Surface(F);
	Standard_Real UF,UL,VF,VL;
	S->Bounds(UF,UL,VF,VL);

	Standard_Real u,v;
	Standard_Boolean isUPeriodic = S->IsUPeriodic();
	if(isUPeriodic) {
	  Standard_Real UPeriod = S->UPeriod();
	  Standard_Real p2x = p2.X()+ShapeAnalysis::AdjustByPeriod(p2.X(),p1.X(),UPeriod);
	  Standard_Real pmid = (p1.X()+p2x)/2.;
	  u = pmid+ShapeAnalysis::AdjustToPeriod(pmid,UF,UL);
	}
	else 
	  u= (p1.X()+p2.X())/2.;

	Standard_Boolean isVPeriodic = S->IsVPeriodic();
	if(isVPeriodic) {
	  Standard_Real VPeriod = S->VPeriod();
	  Standard_Real p2y = p2.Y()+ShapeAnalysis::AdjustByPeriod(p2.Y(),p1.Y(),VPeriod);
	  Standard_Real pmid = (p1.Y()+p2y)/2.;
	  v = pmid+ShapeAnalysis::AdjustToPeriod(pmid,VF,VL);
	}
	else
	  v = (p1.Y()+p2.Y())/2.;

        gp_Pnt P = S->Value(u, v);
        n12 = meshDS->AddNode(P.X(), P.Y(), P.Z());
        meshDS->SetNodeOnFace(n12, faceID, u, v);
        myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n12));
        return n12;
      }
      if (edgeID>-1 || shapeType == TopAbs_EDGE) {

	TopoDS_Edge E;
	if( myShape.IsNull() )
          E = TopoDS::Edge(meshDS->IndexToShape(edgeID));
	else {
          E = TopoDS::Edge(myShape);
          edgeID = myShapeID;
        }

	double p1 = GetNodeU(E,n1);
	double p2 = GetNodeU(E,n2);

	double f,l;
	Handle(Geom_Curve) C = BRep_Tool::Curve(E, f, l);
	if(!C.IsNull()) {

	  Standard_Boolean isPeriodic = C->IsPeriodic();
	  double u;
	  if(isPeriodic) {
	    Standard_Real Period = C->Period();
	    Standard_Real p = p2+ShapeAnalysis::AdjustByPeriod(p2,p1,Period);
	    Standard_Real pmid = (p1+p)/2.;
	    u = pmid+ShapeAnalysis::AdjustToPeriod(pmid,C->FirstParameter(),C->LastParameter());
	  }
	  else
	    u = (p1+p2)/2.;

          gp_Pnt P = C->Value( u );
          n12 = meshDS->AddNode(P.X(), P.Y(), P.Z());
          meshDS->SetNodeOnEdge(n12, edgeID, u);
          myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n12));
          return n12;
	}
      }
    }
    // 3d variant
    double x = ( n1->X() + n2->X() )/2.;
    double y = ( n1->Y() + n2->Y() )/2.;
    double z = ( n1->Z() + n2->Z() )/2.;
    n12 = meshDS->AddNode(x,y,z);
    if(edgeID>-1)
        meshDS->SetNodeOnEdge(n12, edgeID);
    else if(faceID>-1)
        meshDS->SetNodeOnFace(n12, faceID);
    else
      meshDS->SetNodeInVolume(n12, myShapeID);
    myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n12));
    return n12;
  }
}
bool StdMeshers_CompositeSegment_1D::Compute(SMESH_Mesh &         aMesh,
                                             const TopoDS_Shape & aShape)
{
  TopoDS_Edge edge = TopoDS::Edge( aShape );
  SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();

  // Get edges to be discretized as a whole
  TopoDS_Face nullFace;
  auto_ptr< StdMeshers_FaceSide > side( GetFaceSide(aMesh, edge, nullFace, true ));
  //side->dump("IN COMPOSITE SEG");

  if ( side->NbEdges() < 2 )
    return StdMeshers_Regular_1D::Compute( aMesh, aShape );

  // update segment lenght computed by StdMeshers_AutomaticLength
  const list <const SMESHDS_Hypothesis * > & hyps = GetUsedHypothesis(aMesh, aShape);
  if ( !hyps.empty() ) {
    StdMeshers_AutomaticLength * autoLenHyp = const_cast<StdMeshers_AutomaticLength *>
      (dynamic_cast <const StdMeshers_AutomaticLength * >(hyps.front()));
    if ( autoLenHyp )
      _value[ BEG_LENGTH_IND ]= autoLenHyp->GetLength( &aMesh, side->Length() );
  }

  // Compute node parameters
  auto_ptr< BRepAdaptor_CompCurve > C3d ( side->GetCurve3d() );
  double f = C3d->FirstParameter(), l = C3d->LastParameter();
  list< double > params;
  if ( !computeInternalParameters ( aMesh, *C3d, side->Length(), f, l, params, false ))
    return false;

  // Redistribute parameters near ends
  TopoDS_Vertex VFirst = side->FirstVertex();
  TopoDS_Vertex VLast  = side->LastVertex();
  redistributeNearVertices( aMesh, *C3d, side->Length(), params, VFirst, VLast );

  params.push_front(f);
  params.push_back(l);
  int nbNodes = params.size();

  // Create mesh

  const SMDS_MeshNode * nFirst = SMESH_Algo::VertexNode( VFirst, meshDS );
  const SMDS_MeshNode * nLast  = SMESH_Algo::VertexNode( VLast, meshDS );
  if (!nFirst)
    return error(COMPERR_BAD_INPUT_MESH, TComm("No node on vertex ")
                 <<meshDS->ShapeToIndex(VFirst));
  if (!nLast)
    return error(COMPERR_BAD_INPUT_MESH, TComm("No node on vertex ")
                 <<meshDS->ShapeToIndex(VLast));

  vector<const SMDS_MeshNode*> nodes( nbNodes, (const SMDS_MeshNode*)0 );
  nodes.front() = nFirst;
  nodes.back()  = nLast;

  // create internal nodes
  list< double >::iterator parIt = params.begin();
  double prevPar = *parIt;
  Standard_Real u;
  for ( int iN = 0; parIt != params.end(); ++iN, ++parIt)
  {
    if ( !nodes[ iN ] ) {
      gp_Pnt p = C3d->Value( *parIt );
      SMDS_MeshNode* n = meshDS->AddNode( p.X(), p.Y(), p.Z());
      C3d->Edge( *parIt, edge, u );
      meshDS->SetNodeOnEdge( n, edge, u );
//       cout << "new NODE: par="<<*parIt<<" ePar="<<u<<" e="<<edge.TShape().operator->()
//            << " " << n << endl;
      nodes[ iN ] = n;
    }
    // create edges
    if ( iN ) {
      double mPar = ( prevPar + *parIt )/2;
      if ( _quadraticMesh ) {
        // create medium node
        double segLen = GCPnts_AbscissaPoint::Length(*C3d, prevPar, *parIt);
        GCPnts_AbscissaPoint ruler( *C3d, segLen/2., prevPar );
        if ( ruler.IsDone() )
          mPar = ruler.Parameter();
        gp_Pnt p = C3d->Value( mPar );
        SMDS_MeshNode* n = meshDS->AddNode( p.X(), p.Y(), p.Z());
        //cout << "new NODE "<< n << endl;
        meshDS->SetNodeOnEdge( n, edge, u );
        SMDS_MeshEdge * seg = meshDS->AddEdge(nodes[ iN-1 ], nodes[ iN ], n);
        meshDS->SetMeshElementOnShape(seg, edge);
      }
      else {
        C3d->Edge( mPar, edge, u );
        SMDS_MeshEdge * seg = meshDS->AddEdge(nodes[ iN-1 ], nodes[ iN ]);
        meshDS->SetMeshElementOnShape(seg, edge);
      }
    }
    prevPar = *parIt;
  }

  // remove nodes on internal vertices
  for ( int iE = 1; iE < side->NbEdges(); ++iE )
  {
    TopoDS_Vertex V = side->FirstVertex( iE );
    while ( const SMDS_MeshNode * n = SMESH_Algo::VertexNode( V, meshDS ))
      meshDS->RemoveNode( n );
  }

  // Update submeshes state for all edges and internal vertices,
  // make them look computed even if none edge or node is set on them
  careOfSubMeshes( *side, _EventListener );

  return true;
}
Esempio n. 27
0
gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face&   F,
                                    const SMDS_MeshNode* n,
                                    const SMDS_MeshNode* n2) const
{
  gp_Pnt2d uv( 1e100, 1e100 );
  const SMDS_PositionPtr Pos = n->GetPosition();
  if(Pos->GetTypeOfPosition()==SMDS_TOP_FACE)
  {
    // node has position on face
    const SMDS_FacePosition* fpos =
      static_cast<const SMDS_FacePosition*>(n->GetPosition().get());
    uv = gp_Pnt2d(fpos->GetUParameter(),fpos->GetVParameter());
  }
  else if(Pos->GetTypeOfPosition()==SMDS_TOP_EDGE)
  {
    // node has position on edge => it is needed to find
    // corresponding edge from face, get pcurve for this
    // edge and recieve value from this pcurve
    const SMDS_EdgePosition* epos =
      static_cast<const SMDS_EdgePosition*>(n->GetPosition().get());
    SMESHDS_Mesh* meshDS = GetMeshDS();
    int edgeID = Pos->GetShapeId();
    TopoDS_Edge E = TopoDS::Edge(meshDS->IndexToShape(edgeID));
    double f, l;
    Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
    uv = C2d->Value( epos->GetUParameter() );
    // for a node on a seam edge select one of UVs on 2 pcurves
    if ( n2 && IsSeamShape( edgeID ) )
      uv = GetUVOnSeam( uv, GetNodeUV( F, n2, 0 ));
  }
  else if(Pos->GetTypeOfPosition()==SMDS_TOP_VERTEX)
  {
    if ( int vertexID = n->GetPosition()->GetShapeId() ) {
      bool ok = true;
      const TopoDS_Vertex& V = TopoDS::Vertex(GetMeshDS()->IndexToShape(vertexID));
      try {
        uv = BRep_Tool::Parameters( V, F );
      }
      catch (Standard_Failure& exc) {
        ok = false;
      }
      if ( !ok ) {
        for ( TopExp_Explorer vert(F,TopAbs_VERTEX); !ok && vert.More(); vert.Next() )
          ok = ( V == vert.Current() );
        if ( !ok ) {
#ifdef _DEBUG_
          MESSAGE ( "SMESH_MesherHelper::GetNodeUV(); Vertex " << vertexID
               << " not in face " << GetMeshDS()->ShapeToIndex( F ) );
#endif
          // get UV of a vertex closest to the node
          double dist = 1e100;
          gp_Pnt pn ( n->X(),n->Y(),n->Z() );
          for ( TopExp_Explorer vert(F,TopAbs_VERTEX); !ok && vert.More(); vert.Next() ) {
            TopoDS_Vertex curV = TopoDS::Vertex( vert.Current() );
            gp_Pnt p = BRep_Tool::Pnt( curV );
            double curDist = p.SquareDistance( pn );
            if ( curDist < dist ) {
              dist = curDist;
              uv = BRep_Tool::Parameters( curV, F );
              if ( dist < DBL_MIN ) break;
            }
          }
        }
        else {
          TopTools_ListIteratorOfListOfShape it( myMesh->GetAncestors( V ));
          for ( ; it.More(); it.Next() ) {
            if ( it.Value().ShapeType() == TopAbs_EDGE ) {
              const TopoDS_Edge & edge = TopoDS::Edge( it.Value() );
              double f,l;
              Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edge, F, f, l);
              if ( !C2d.IsNull() ) {
                double u = ( V == TopExp::FirstVertex( edge ) ) ?  f : l;
                uv = C2d->Value( u );
                break;
              }
            }
          }
        }
      }
      if ( n2 && IsSeamShape( vertexID ) )
        uv = GetUVOnSeam( uv, GetNodeUV( F, n2, 0 ));
    }
  }
  return uv.XY();
}
Esempio n. 28
0
void SMESH_MesherHelper::SetSubShape(const TopoDS_Shape& aSh)
{
  if ( myShape.IsSame( aSh ))
    return;

  myShape = aSh;
  mySeamShapeIds.clear();
  myDegenShapeIds.clear();

  if ( myShape.IsNull() ) {
    myShapeID  = -1;
    return;
  }
  SMESHDS_Mesh* meshDS = GetMeshDS();
  myShapeID = meshDS->ShapeToIndex(aSh);

  // treatment of periodic faces
  for ( TopExp_Explorer eF( aSh, TopAbs_FACE ); eF.More(); eF.Next() )
  {
    const TopoDS_Face& face = TopoDS::Face( eF.Current() );
    BRepAdaptor_Surface surface( face );
    if ( surface.IsUPeriodic() || surface.IsVPeriodic() )
    {
      for (TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next())
      {
        // look for a seam edge
        const TopoDS_Edge& edge = TopoDS::Edge( exp.Current() );
        if ( BRep_Tool::IsClosed( edge, face )) {
          // initialize myPar1, myPar2 and myParIndex
          if ( mySeamShapeIds.empty() ) {
            gp_Pnt2d uv1, uv2;
            BRep_Tool::UVPoints( edge, face, uv1, uv2 );
            if ( Abs( uv1.Coord(1) - uv2.Coord(1) ) < Abs( uv1.Coord(2) - uv2.Coord(2) ))
            {
              myParIndex = 1; // U periodic
              myPar1 = surface.FirstUParameter();
              myPar2 = surface.LastUParameter();
            }
            else {
              myParIndex = 2;  // V periodic
              myPar1 = surface.FirstVParameter();
              myPar2 = surface.LastVParameter();
            }
          }
          // store seam shape indices, negative if shape encounters twice
          int edgeID = meshDS->ShapeToIndex( edge );
          mySeamShapeIds.insert( IsSeamShape( edgeID ) ? -edgeID : edgeID );
          for ( TopExp_Explorer v( edge, TopAbs_VERTEX ); v.More(); v.Next() ) {
            int vertexID = meshDS->ShapeToIndex( v.Current() );
            mySeamShapeIds.insert( IsSeamShape( vertexID ) ? -vertexID : vertexID );
          }
        }

        // look for a degenerated edge
        if ( BRep_Tool::Degenerated( edge )) {
          myDegenShapeIds.insert( meshDS->ShapeToIndex( edge ));
          for ( TopExp_Explorer v( edge, TopAbs_VERTEX ); v.More(); v.Next() )
            myDegenShapeIds.insert( meshDS->ShapeToIndex( v.Current() ));
        }
      }
    }
  }
}
//=============================================================================
bool NETGENPlugin_Mesher::Compute()
{
#ifdef WNT
  netgen::MeshingParameters& mparams = netgen::GlobalMeshingParameters();
#else
  netgen::MeshingParameters& mparams = netgen::mparam;
#endif  
  MESSAGE("Compute with:\n"
          " max size = " << mparams.maxh << "\n"
          " segments per edge = " << mparams.segmentsperedge);
  MESSAGE("\n"
          " growth rate = " << mparams.grading << "\n"
          " elements per radius = " << mparams.curvaturesafety << "\n"
          " second order = " << mparams.secondorder << "\n"
          " quad allowed = " << mparams.quad);

  SMESH_ComputeErrorPtr error = SMESH_ComputeError::New();
  nglib::Ng_Init();

  // -------------------------
  // Prepare OCC geometry
  // -------------------------

  netgen::OCCGeometry occgeo;
  list< SMESH_subMesh* > meshedSM;
  PrepareOCCgeometry( occgeo, _shape, *_mesh, &meshedSM );

  // -------------------------
  // Generate the mesh
  // -------------------------

  netgen::Mesh *ngMesh = NULL;

  SMESH_Comment comment;
  int err = 0;
  int nbInitNod = 0;
  int nbInitSeg = 0;
  int nbInitFac = 0;
  // vector of nodes in which node index == netgen ID
  vector< SMDS_MeshNode* > nodeVec;
  try
  {
    // ----------------
    // compute 1D mesh
    // ----------------
    // pass 1D simple parameters to NETGEN
    if ( _simpleHyp ) {
      if ( int nbSeg = _simpleHyp->GetNumberOfSegments() ) {
        // nb of segments
        mparams.segmentsperedge = nbSeg + 0.1;
        mparams.maxh = occgeo.boundingbox.Diam();
        mparams.grading = 0.01;
      }
      else {
        // segment length
        mparams.segmentsperedge = 1;
        mparams.maxh = _simpleHyp->GetLocalLength();
      }
    }
    // let netgen create ngMesh and calculate element size on not meshed shapes
    char *optstr = 0;
    int startWith = netgen::MESHCONST_ANALYSE;
    int endWith   = netgen::MESHCONST_ANALYSE;
    err = netgen::OCCGenerateMesh(occgeo, ngMesh, startWith, endWith, optstr);
    if (err) comment << "Error in netgen::OCCGenerateMesh() at MESHCONST_ANALYSE step";

    // fill ngMesh with nodes and elements of computed submeshes
    err = ! fillNgMesh(occgeo, *ngMesh, nodeVec, meshedSM);
    nbInitNod = ngMesh->GetNP();
    nbInitSeg = ngMesh->GetNSeg();
    nbInitFac = ngMesh->GetNSE();

    // compute mesh
    if (!err)
    {
      startWith = endWith = netgen::MESHCONST_MESHEDGES;
      err = netgen::OCCGenerateMesh(occgeo, ngMesh, startWith, endWith, optstr);
      if (err) comment << "Error in netgen::OCCGenerateMesh() at 1D mesh generation";
    }
    // ---------------------
    // compute surface mesh
    // ---------------------
    if (!err)
    {
      // pass 2D simple parameters to NETGEN
      if ( _simpleHyp ) {
        if ( double area = _simpleHyp->GetMaxElementArea() ) {
          // face area
          mparams.maxh = sqrt(2. * area/sqrt(3.0));
          mparams.grading = 0.4; // moderate size growth
        }
        else {
          // length from edges
          double length = 0;
          TopTools_MapOfShape tmpMap;
          for ( TopExp_Explorer exp( _shape, TopAbs_EDGE ); exp.More(); exp.Next() )
            if( tmpMap.Add(exp.Current()) )
              length += SMESH_Algo::EdgeLength( TopoDS::Edge( exp.Current() ));

          if ( ngMesh->GetNSeg() ) {
            // we have to multiply length by 2 since for each TopoDS_Edge there
            // are double set of NETGEN edges or, in other words, we have to
            // divide ngMesh->GetNSeg() on 2.
            mparams.maxh = 2*length / ngMesh->GetNSeg();
          }
          else
            mparams.maxh = 1000;
          mparams.grading = 0.2; // slow size growth
        }
        mparams.maxh = min( mparams.maxh, occgeo.boundingbox.Diam()/2 );
        ngMesh->SetGlobalH (mparams.maxh);
        netgen::Box<3> bb = occgeo.GetBoundingBox();
        bb.Increase (bb.Diam()/20);
        ngMesh->SetLocalH (bb.PMin(), bb.PMax(), mparams.grading);
      }
      // let netgen compute 2D mesh
      startWith = netgen::MESHCONST_MESHSURFACE;
      endWith = _optimize ? netgen::MESHCONST_OPTSURFACE : netgen::MESHCONST_MESHSURFACE;
      err = netgen::OCCGenerateMesh(occgeo, ngMesh, startWith, endWith, optstr);
      if (err) comment << "Error in netgen::OCCGenerateMesh() at surface mesh generation";
    }
    // ---------------------
    // generate volume mesh
    // ---------------------
    if (!err && _isVolume)
    {
      // add ng face descriptors of meshed faces
      std::map< int, std::pair<int,int> >::iterator fId_soIds = _faceDescriptors.begin();
      for ( ; fId_soIds != _faceDescriptors.end(); ++fId_soIds ) {
        int faceID   = fId_soIds->first;
        int solidID1 = fId_soIds->second.first;
        int solidID2 = fId_soIds->second.second;
        ngMesh->AddFaceDescriptor (netgen::FaceDescriptor(faceID, solidID1, solidID2, 0));
      }
      // pass 3D simple parameters to NETGEN
      const NETGENPlugin_SimpleHypothesis_3D* simple3d =
        dynamic_cast< const NETGENPlugin_SimpleHypothesis_3D* > ( _simpleHyp );
      if ( simple3d ) {
        if ( double vol = simple3d->GetMaxElementVolume() ) {
          // max volume
          mparams.maxh = pow( 72, 1/6. ) * pow( vol, 1/3. );
          mparams.maxh = min( mparams.maxh, occgeo.boundingbox.Diam()/2 );
        }
        else {
          // length from faces
          mparams.maxh = ngMesh->AverageH();
        }
//      netgen::ARRAY<double> maxhdom;
//      maxhdom.SetSize (occgeo.NrSolids());
//      maxhdom = mparams.maxh;
//      ngMesh->SetMaxHDomain (maxhdom);
        ngMesh->SetGlobalH (mparams.maxh);
        mparams.grading = 0.4;
        ngMesh->CalcLocalH();
      }
      // let netgen compute 3D mesh
      startWith = netgen::MESHCONST_MESHVOLUME;
      endWith = _optimize ? netgen::MESHCONST_OPTVOLUME : netgen::MESHCONST_MESHVOLUME;
      err = netgen::OCCGenerateMesh(occgeo, ngMesh, startWith, endWith, optstr);
      if (err) comment << "Error in netgen::OCCGenerateMesh()";
    }
    if (!err && mparams.secondorder > 0)
    {
      netgen::OCCRefinementSurfaces ref (occgeo);
      ref.MakeSecondOrder (*ngMesh);
    }
  }
  catch (netgen::NgException exc)
  {
    error->myName = err = COMPERR_ALGO_FAILED;
    comment << exc.What();
  }

  int nbNod = ngMesh->GetNP();
  int nbSeg = ngMesh->GetNSeg();
  int nbFac = ngMesh->GetNSE();
  int nbVol = ngMesh->GetNE();

  MESSAGE((err ? "Mesh Generation failure" : "End of Mesh Generation") <<
          ", nb nodes: " << nbNod <<
          ", nb segments: " << nbSeg <<
          ", nb faces: " << nbFac <<
          ", nb volumes: " << nbVol);

  // -----------------------------------------------------------
  // Feed back the SMESHDS with the generated Nodes and Elements
  // -----------------------------------------------------------

  SMESHDS_Mesh* meshDS = _mesh->GetMeshDS();
  bool isOK = ( !err && (_isVolume ? (nbVol > 0) : (nbFac > 0)) );
  if ( true /*isOK*/ ) // get whatever built
  {
    // map of nodes assigned to submeshes
    NCollection_Map<int> pindMap;
    // create and insert nodes into nodeVec
    nodeVec.resize( nbNod + 1 );
    int i;
    for (i = nbInitNod+1; i <= nbNod /*&& isOK*/; ++i )
    {
      const netgen::MeshPoint& ngPoint = ngMesh->Point(i);
      SMDS_MeshNode* node = NULL;
      bool newNodeOnVertex = false;
      TopoDS_Vertex aVert;
      if (i-nbInitNod <= occgeo.vmap.Extent())
      {
        // point on vertex
        aVert = TopoDS::Vertex(occgeo.vmap(i-nbInitNod));
        SMESHDS_SubMesh * submesh = meshDS->MeshElements(aVert);
        if (submesh)
        {
          SMDS_NodeIteratorPtr it = submesh->GetNodes();
          if (it->more())
          {
            node = const_cast<SMDS_MeshNode*> (it->next());
            pindMap.Add(i);
          }
        }
        if (!node)
          newNodeOnVertex = true;
      }
      if (!node)
        node = meshDS->AddNode(ngPoint.X(), ngPoint.Y(), ngPoint.Z());
      if (!node)
      {
        MESSAGE("Cannot create a mesh node");
        if ( !comment.size() ) comment << "Cannot create a mesh node";
        nbSeg = nbFac = nbVol = isOK = 0;
        break;
      }
      nodeVec.at(i) = node;
      if (newNodeOnVertex)
      {
        // point on vertex
        meshDS->SetNodeOnVertex(node, aVert);
        pindMap.Add(i);
      }
    }

    // create mesh segments along geometric edges
    NCollection_Map<Link> linkMap;
    for (i = nbInitSeg+1; i <= nbSeg/* && isOK*/; ++i )
    {
      const netgen::Segment& seg = ngMesh->LineSegment(i);
      Link link(seg.p1, seg.p2);
      if (linkMap.Contains(link))
        continue;
      linkMap.Add(link);
      TopoDS_Edge aEdge;
      int pinds[3] = { seg.p1, seg.p2, seg.pmid };
      int nbp = 0;
      double param2 = 0;
      for (int j=0; j < 3; ++j)
      {
        int pind = pinds[j];
        if (pind <= 0) continue;
        ++nbp;
        double param;
        if (j < 2)
        {
          if (aEdge.IsNull())
          {
            int aGeomEdgeInd = seg.epgeominfo[j].edgenr;
            if (aGeomEdgeInd > 0 && aGeomEdgeInd <= occgeo.emap.Extent())
              aEdge = TopoDS::Edge(occgeo.emap(aGeomEdgeInd));
          }
          param = seg.epgeominfo[j].dist;
          param2 += param;
        }
        else
          param = param2 * 0.5;
        if (pind <= nbInitNod || pindMap.Contains(pind))
          continue;
        if (!aEdge.IsNull())
        {
          meshDS->SetNodeOnEdge(nodeVec.at(pind), aEdge, param);
          pindMap.Add(pind);
        }
      }
      SMDS_MeshEdge* edge;
      if (nbp < 3) // second order ?
        edge = meshDS->AddEdge(nodeVec.at(pinds[0]), nodeVec.at(pinds[1]));
      else
        edge = meshDS->AddEdge(nodeVec.at(pinds[0]), nodeVec.at(pinds[1]),
                                nodeVec.at(pinds[2]));
      if (!edge)
      {
        if ( !comment.size() ) comment << "Cannot create a mesh edge";
        MESSAGE("Cannot create a mesh edge");
        nbSeg = nbFac = nbVol = isOK = 0;
        break;
      }
      if (!aEdge.IsNull())
        meshDS->SetMeshElementOnShape(edge, aEdge);
    }

    // create mesh faces along geometric faces
    for (i = nbInitFac+1; i <= nbFac/* && isOK*/; ++i )
    {
      const netgen::Element2d& elem = ngMesh->SurfaceElement(i);
      int aGeomFaceInd = elem.GetIndex();
      TopoDS_Face aFace;
      if (aGeomFaceInd > 0 && aGeomFaceInd <= occgeo.fmap.Extent())
        aFace = TopoDS::Face(occgeo.fmap(aGeomFaceInd));
      vector<SMDS_MeshNode*> nodes;
      for (int j=1; j <= elem.GetNP(); ++j)
      {
        int pind = elem.PNum(j);
        SMDS_MeshNode* node = nodeVec.at(pind);
        nodes.push_back(node);
        if (pind <= nbInitNod || pindMap.Contains(pind))
          continue;
        if (!aFace.IsNull())
        {
          const netgen::PointGeomInfo& pgi = elem.GeomInfoPi(j);
          meshDS->SetNodeOnFace(node, aFace, pgi.u, pgi.v);
          pindMap.Add(pind);
        }
      }
      SMDS_MeshFace* face = NULL;
      switch (elem.GetType())
      {
      case netgen::TRIG:
        face = meshDS->AddFace(nodes[0],nodes[1],nodes[2]);
        break;
      case netgen::QUAD:
        face = meshDS->AddFace(nodes[0],nodes[1],nodes[2],nodes[3]);
        break;
      case netgen::TRIG6:
        face = meshDS->AddFace(nodes[0],nodes[1],nodes[2],nodes[5],nodes[3],nodes[4]);
        break;
      case netgen::QUAD8:
        face = meshDS->AddFace(nodes[0],nodes[1],nodes[2],nodes[3],
                               nodes[4],nodes[7],nodes[5],nodes[6]);
        break;
      default:
        MESSAGE("NETGEN created a face of unexpected type, ignoring");
        continue;
      }
      if (!face)
      {
        if ( !comment.size() ) comment << "Cannot create a mesh face";
        MESSAGE("Cannot create a mesh face");
        nbSeg = nbFac = nbVol = isOK = 0;
        break;
      }
      if (!aFace.IsNull())
        meshDS->SetMeshElementOnShape(face, aFace);
    }

    // create tetrahedra
    for (i = 1; i <= nbVol/* && isOK*/; ++i)
    {
      const netgen::Element& elem = ngMesh->VolumeElement(i);      
      int aSolidInd = elem.GetIndex();
      TopoDS_Solid aSolid;
      if (aSolidInd > 0 && aSolidInd <= occgeo.somap.Extent())
        aSolid = TopoDS::Solid(occgeo.somap(aSolidInd));
      vector<SMDS_MeshNode*> nodes;
      for (int j=1; j <= elem.GetNP(); ++j)
      {
        int pind = elem.PNum(j);
        SMDS_MeshNode* node = nodeVec.at(pind);
        nodes.push_back(node);
        if (pind <= nbInitNod || pindMap.Contains(pind))
          continue;
        if (!aSolid.IsNull())
        {
          // point in solid
          meshDS->SetNodeInVolume(node, aSolid);
          pindMap.Add(pind);
        }
      }
      SMDS_MeshVolume* vol = NULL;
      switch (elem.GetType())
      {
      case netgen::TET:
        vol = meshDS->AddVolume(nodes[0],nodes[1],nodes[2],nodes[3]);
        break;
      case netgen::TET10:
        vol = meshDS->AddVolume(nodes[0],nodes[1],nodes[2],nodes[3],
                                nodes[4],nodes[7],nodes[5],nodes[6],nodes[8],nodes[9]);
        break;
      default:
        MESSAGE("NETGEN created a volume of unexpected type, ignoring");
        continue;
      }
      if (!vol)
      {
        if ( !comment.size() ) comment << "Cannot create a mesh volume";
        MESSAGE("Cannot create a mesh volume");
        nbSeg = nbFac = nbVol = isOK = 0;
        break;
      }
      if (!aSolid.IsNull())
        meshDS->SetMeshElementOnShape(vol, aSolid);
    }
  }

  if ( error->IsOK() && ( !isOK || comment.size() > 0 ))
    error->myName = COMPERR_ALGO_FAILED;
  if ( !comment.empty() )
    error->myComment = comment;

  // set bad compute error to subshapes of all failed subshapes shapes
  if ( !error->IsOK() && err )
  {
    for (int i = 1; i <= occgeo.fmap.Extent(); i++) {
      int status = occgeo.facemeshstatus[i-1];
      if (status == 1 ) continue;
      if ( SMESH_subMesh* sm = _mesh->GetSubMeshContaining( occgeo.fmap( i ))) {
        SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
        if ( !smError || smError->IsOK() ) {
          if ( status == -1 )
            smError.reset( new SMESH_ComputeError( error->myName, error->myComment ));
          else
            smError.reset( new SMESH_ComputeError( COMPERR_ALGO_FAILED, "Ignored" ));
        }
      }
    }
  }

  nglib::Ng_DeleteMesh((nglib::Ng_Mesh*)ngMesh);
  nglib::Ng_Exit();

  RemoveTmpFiles();

  return error->IsOK();
}
bool StdMeshers_RadialPrism_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape)
{
  TopExp_Explorer exp;
  SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();

  myHelper = new SMESH_MesherHelper( aMesh );
  myHelper->IsQuadraticSubMesh( aShape );
  // to delete helper at exit from Compute()
  std::auto_ptr<SMESH_MesherHelper> helperDeleter( myHelper );

  // get 2 shells
  TopoDS_Solid solid = TopoDS::Solid( aShape );
  TopoDS_Shell outerShell = BRepClass3d::OuterShell( solid );
  TopoDS_Shape innerShell;
  int nbShells = 0;
  for ( TopoDS_Iterator It (solid); It.More(); It.Next(), ++nbShells )
    if ( !outerShell.IsSame( It.Value() ))
      innerShell = It.Value();
  if ( nbShells != 2 )
    return error(COMPERR_BAD_SHAPE, SMESH_Comment("Must be 2 shells but not ")<<nbShells);

  // ----------------------------------
  // Associate sub-shapes of the shells
  // ----------------------------------

  ProjectionUtils::TShapeShapeMap shape2ShapeMaps[2];
  bool mapOk1 = ProjectionUtils::FindSubShapeAssociation( innerShell, &aMesh,
                                                          outerShell, &aMesh,
                                                          shape2ShapeMaps[0]);
  bool mapOk2 = ProjectionUtils::FindSubShapeAssociation( innerShell.Reversed(), &aMesh,
                                                          outerShell, &aMesh,
                                                          shape2ShapeMaps[1]);
  if ( !mapOk1 && !mapOk2 )
    return error(COMPERR_BAD_SHAPE,"Topology of inner and outer shells seems different" );

  int iMap;
  if ( shape2ShapeMaps[0].Extent() == shape2ShapeMaps[1].Extent() )
  {
    // choose an assiciation by shortest distance between VERTEXes
    double dist1 = 0, dist2 = 0;
    TopTools_DataMapIteratorOfDataMapOfShapeShape ssIt( shape2ShapeMaps[0]._map1to2 );
    for (; ssIt.More(); ssIt.Next() )
    {
      if ( ssIt.Key().ShapeType() != TopAbs_VERTEX ) continue;
      gp_Pnt pIn   = BRep_Tool::Pnt( TopoDS::Vertex( ssIt.Key() ));
      gp_Pnt pOut1 = BRep_Tool::Pnt( TopoDS::Vertex( ssIt.Value() ));
      gp_Pnt pOut2 = BRep_Tool::Pnt( TopoDS::Vertex( shape2ShapeMaps[1]( ssIt.Key() )));
      dist1 += pIn.SquareDistance( pOut1 );
      dist2 += pIn.SquareDistance( pOut2 );
    }
    iMap = ( dist1 < dist2 ) ? 0 : 1;
  }
  else
  {
    iMap = ( shape2ShapeMaps[0].Extent() > shape2ShapeMaps[1].Extent() ) ? 0 : 1;
  }
  ProjectionUtils::TShapeShapeMap& shape2ShapeMap = shape2ShapeMaps[iMap];

  // ------------------
  // Make mesh
  // ------------------

  TNode2ColumnMap node2columnMap;
  myLayerPositions.clear();

  for ( exp.Init( outerShell, TopAbs_FACE ); exp.More(); exp.Next() )
  {
    // Corresponding sub-shapes
    TopoDS_Face outFace = TopoDS::Face( exp.Current() );
    TopoDS_Face inFace;
    if ( !shape2ShapeMap.IsBound( outFace, /*isOut=*/true )) {
      return error(SMESH_Comment("Corresponding inner face not found for face #" )
                   << meshDS->ShapeToIndex( outFace ));
    } else {
      inFace = TopoDS::Face( shape2ShapeMap( outFace, /*isOut=*/true ));
    }

    // Find matching nodes of in and out faces
    ProjectionUtils::TNodeNodeMap nodeIn2OutMap;
    if ( ! ProjectionUtils::FindMatchingNodesOnFaces( inFace, &aMesh, outFace, &aMesh,
                                                      shape2ShapeMap, nodeIn2OutMap ))
      return error(COMPERR_BAD_INPUT_MESH,SMESH_Comment("Mesh on faces #")
                   << meshDS->ShapeToIndex( outFace ) << " and "
                   << meshDS->ShapeToIndex( inFace ) << " seems different" );

    // Create volumes

    SMDS_ElemIteratorPtr faceIt = meshDS->MeshElements( inFace )->GetElements();
    while ( faceIt->more() ) // loop on faces on inFace
    {
      const SMDS_MeshElement* face = faceIt->next();
      if ( !face || face->GetType() != SMDSAbs_Face )
        continue;
      int nbNodes = face->NbNodes();
      if ( face->IsQuadratic() )
        nbNodes /= 2;

      // find node columns for each node
      vector< const TNodeColumn* > columns( nbNodes );
      for ( int i = 0; i < nbNodes; ++i )
      {
        const SMDS_MeshNode* nIn = face->GetNode( i );
        TNode2ColumnMap::iterator n_col = node2columnMap.find( nIn );
        if ( n_col != node2columnMap.end() ) {
          columns[ i ] = & n_col->second;
        }
        else {
          TNodeNodeMap::iterator nInOut = nodeIn2OutMap.find( nIn );
          if ( nInOut == nodeIn2OutMap.end() )
            RETURN_BAD_RESULT("No matching node for "<< nIn->GetID() <<
                              " in face "<< face->GetID());
          columns[ i ] = makeNodeColumn( node2columnMap, nIn, nInOut->second );
        }
      }

      StdMeshers_Prism_3D::AddPrisms( columns, myHelper );
    }
  } // loop on faces of out shell

  return true;
}