+//================================================================================
+/*!
+ * \brief Compute a mesh basing on discrete CAD description
+ */
+//================================================================================
+
+bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh & aMesh, SMESH_MesherHelper* aHelper)
+{
+ if ( aMesh.NbFaces() == 0 )
+ return error( COMPERR_BAD_INPUT_MESH, "2D elements are missing" );
+
+ context_t *ctx = context_new();
+ if (!ctx) return error("Pb in context_new()");
+
+ BLSURF_Cleaner cleaner( ctx );
+
+ message_cb_user_data mcud;
+ mcud._error = & this->SMESH_Algo::_comment;
+ mcud._progress = & this->SMESH_Algo::_progress;
+ mcud._verbosity =
+ _hypothesis ? _hypothesis->GetVerbosity() : BLSURFPlugin_Hypothesis::GetDefaultVerbosity();
+ meshgems_status_t ret = context_set_message_callback(ctx, message_cb, &mcud);
+ if (ret != STATUS_OK) return error("Pb. in context_set_message_callback() ");
+
+ cadsurf_session_t * css = cadsurf_session_new(ctx);
+ if(!css) return error( "Pb. in cadsurf_session_new() " );
+ cleaner._css = css;
+
+
+ // Fill an input mesh
+
+ mesh_t * msh = meshgems_mesh_new_in_memory( ctx );
+ if ( !msh ) return error("Pb. in meshgems_mesh_new_in_memory()");
+
+ // mark nodes used by 2D elements
+ SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
+ SMDS_NodeIteratorPtr nodeIt = meshDS->nodesIterator();
+ while ( nodeIt->more() )
+ {
+ const SMDS_MeshNode* n = nodeIt->next();
+ n->setIsMarked( n->NbInverseElements( SMDSAbs_Face ));
+ }
+ meshgems_mesh_set_vertex_count( msh, meshDS->NbNodes() );
+
+ // set node coordinates
+ if ( meshDS->NbNodes() != meshDS->MaxNodeID() )
+ {
+ meshDS->CompactMesh();
+ }
+ SMESH_NodeXYZ nXYZ;
+ nodeIt = meshDS->nodesIterator();
+ meshgems_integer i;
+ for ( i = 1; nodeIt->more(); ++i )
+ {
+ nXYZ.Set( nodeIt->next() );
+ meshgems_mesh_set_vertex_coordinates( msh, i, nXYZ.ChangeData() );
+ }
+
+ // set nodes of faces
+ meshgems_mesh_set_triangle_count ( msh, meshDS->GetMeshInfo().NbTriangles() );
+ meshgems_mesh_set_quadrangle_count( msh, meshDS->GetMeshInfo().NbQuadrangles() );
+ meshgems_integer nodeIDs[4];
+ meshgems_integer iT = 1, iQ = 1;
+ SMDS_FaceIteratorPtr faceIt = meshDS->facesIterator();
+ while ( faceIt->more() )
+ {
+ const SMDS_MeshElement* face = faceIt->next();
+ meshgems_integer nbNodes = face->NbCornerNodes();
+ if ( nbNodes > 4 || face->IsPoly() ) continue;
+
+ for ( i = 0; i < nbNodes; ++i )
+ nodeIDs[i] = face->GetNode( i )->GetID();
+ if ( nbNodes == 3 )
+ meshgems_mesh_set_triangle_vertices ( msh, iT++, nodeIDs );
+ else
+ meshgems_mesh_set_quadrangle_vertices( msh, iQ++, nodeIDs );
+ }
+
+ ret = cadsurf_set_mesh(css, msh);
+ if ( ret != STATUS_OK ) return error("Pb in cadsurf_set_mesh()");
+
+
+ // Compute the mesh
+
+ SetParameters(_hypothesis, css, aMesh.GetShapeToMesh() );
+
+ ret = cadsurf_compute_mesh(css);
+ if ( ret != STATUS_OK ) return false;
+
+ mesh_t *omsh = 0;
+ cadsurf_get_mesh(css, &omsh);
+ if ( !omsh ) return error( "Pb. in cadsurf_get_mesh()" );
+
+
+ // Update SALOME mesh
+
+ // remove quadrangles and triangles
+ for ( faceIt = meshDS->facesIterator(); faceIt->more(); )
+ {
+ const SMDS_MeshElement* face = faceIt->next();
+ if ( !face->IsPoly() )
+ meshDS->RemoveFreeElement( face, /*sm=*/0, /*fromGroups=*/true );
+ }
+ // remove edges that bound the just removed faces
+ for ( SMDS_EdgeIteratorPtr edgeIt = meshDS->edgesIterator(); edgeIt->more(); )
+ {
+ const SMDS_MeshElement* edge = edgeIt->next();
+ const SMDS_MeshNode* n0 = edge->GetNode(0);
+ const SMDS_MeshNode* n1 = edge->GetNode(1);
+ if ( n0->isMarked() &&
+ n1->isMarked() &&
+ n0->NbInverseElements( SMDSAbs_Volume ) == 0 &&
+ n1->NbInverseElements( SMDSAbs_Volume ) == 0 )
+ meshDS->RemoveFreeElement( edge, /*sm=*/0, /*fromGroups=*/true );
+ }
+ // remove nodes that just became free
+ for ( nodeIt = meshDS->nodesIterator(); nodeIt->more(); )
+ {
+ const SMDS_MeshNode* n = nodeIt->next();
+ if ( n->isMarked() && n->NbInverseElements() == 0 )
+ meshDS->RemoveFreeNode( n, /*sm=*/0, /*fromGroups=*/true );
+ }
+
+ // add nodes
+ meshgems_integer nbvtx = 0, nodeID;
+ meshgems_mesh_get_vertex_count( omsh, &nbvtx );
+ meshgems_real xyz[3];
+ for ( i = 1; i <= nbvtx; ++i )
+ {
+ meshgems_mesh_get_vertex_coordinates( omsh, i, xyz );
+ SMDS_MeshNode* n = meshDS->AddNode( xyz[0], xyz[1], xyz[2] );
+ nodeID = n->GetID();
+ meshgems_mesh_set_vertex_tag( omsh, i, &nodeID ); // save mapping of IDs in MG and SALOME meshes
+ }
+
+ // add triangles
+ meshgems_integer nbtri = 0;
+ meshgems_mesh_get_triangle_count( omsh, &nbtri );
+ const SMDS_MeshNode* nodes[4];
+ for ( i = 1; i <= nbtri; ++i )
+ {
+ meshgems_mesh_get_triangle_vertices( omsh, i, nodeIDs );
+ for ( int j = 0; j < 3; ++j )
+ {
+ meshgems_mesh_get_vertex_tag( omsh, nodeIDs[j], &nodeID );
+ nodes[j] = meshDS->FindNode( nodeID );
+ }
+ meshDS->AddFace( nodes[0], nodes[1], nodes[2] );
+ }
+
+ // add quadrangles
+ meshgems_integer nbquad = 0;
+ meshgems_mesh_get_quadrangle_count( omsh, &nbquad );
+ for ( i = 1; i <= nbquad; ++i )
+ {
+ meshgems_mesh_get_quadrangle_vertices( omsh, i, nodeIDs );
+ for ( int j = 0; j < 4; ++j )
+ {
+ meshgems_mesh_get_vertex_tag( omsh, nodeIDs[j], &nodeID );
+ nodes[j] = meshDS->FindNode( nodeID );
+ }
+ meshDS->AddFace( nodes[0], nodes[1], nodes[2], nodes[3] );
+ }
+
+ if ( _hypothesis )
+ {
+ std::string GMFFileName = _hypothesis->GetGMFFile();
+ if ( !GMFFileName.empty() )
+ {
+ bool asciiFound = (GMFFileName.find(".mesh", GMFFileName.size()-5) != std::string::npos);
+ bool binaryFound = (GMFFileName.find(".meshb",GMFFileName.size()-6) != std::string::npos);
+ if ( !asciiFound && !binaryFound )
+ GMFFileName.append(".mesh");
+ mesh_write_mesh(msh, GMFFileName.c_str());
+ }
+ }
+
+ cadsurf_regain_mesh(css, omsh);
+
+ // as we don't assign the new triangles to a shape (the pseudo-shape),
+ // we mark the shape as always computed to avoid the error messages
+ // that no elements assigned to the shape
+ aMesh.GetSubMesh( aHelper->GetSubShape() )->SetIsAlwaysComputed( true );
+
+ return true;
+}
+