//======================================================================= //function : MakeScaledPrism //purpose : //======================================================================= TopoDS_Shape GEOMImpl_PrismDriver::MakeScaledPrism (const TopoDS_Shape& theShapeBase, const gp_Vec& theVector, const Standard_Real theScaleFactor, const gp_Pnt& theCDG, bool isCDG) { TopoDS_Shape aShape; BRep_Builder B; // 1. aCDG = geompy.MakeCDG(theBase) gp_Pnt aCDG = theCDG; if (!isCDG) { gp_Ax3 aPos = GEOMImpl_IMeasureOperations::GetPosition(theShapeBase); aCDG = aPos.Location(); } TopoDS_Shape aShapeCDG_1 = BRepBuilderAPI_MakeVertex(aCDG).Shape(); // Process case of several given shapes if (theShapeBase.ShapeType() == TopAbs_COMPOUND || theShapeBase.ShapeType() == TopAbs_SHELL) { int nbSub = 0; TopoDS_Shape aShapeI; TopoDS_Compound aCompound; B.MakeCompound(aCompound); TopoDS_Iterator It (theShapeBase, Standard_True, Standard_True); for (; It.More(); It.Next()) { nbSub++; aShapeI = MakeScaledPrism(It.Value(), theVector, theScaleFactor, aCDG, true); B.Add(aCompound, aShapeI); } if (nbSub == 1) aShape = aShapeI; else if (nbSub > 1) aShape = GEOMImpl_GlueDriver::GlueFaces(aCompound, Precision::Confusion(), Standard_True); return aShape; } // 2. Scale = geompy.MakeScaleTransform(theBase, aCDG, theScaleFactor) // Bug 6839: Check for standalone (not included in faces) degenerated edges TopTools_IndexedDataMapOfShapeListOfShape aEFMap; TopExp::MapShapesAndAncestors(theShapeBase, TopAbs_EDGE, TopAbs_FACE, aEFMap); Standard_Integer i, nbE = aEFMap.Extent(); for (i = 1; i <= nbE; i++) { TopoDS_Shape anEdgeSh = aEFMap.FindKey(i); if (BRep_Tool::Degenerated(TopoDS::Edge(anEdgeSh))) { const TopTools_ListOfShape& aFaces = aEFMap.FindFromIndex(i); if (aFaces.IsEmpty()) Standard_ConstructionError::Raise ("Scaling aborted : cannot scale standalone degenerated edge"); } } // Perform Scaling gp_Trsf aTrsf; aTrsf.SetScale(aCDG, theScaleFactor); BRepBuilderAPI_Transform aBRepTrsf (theShapeBase, aTrsf, Standard_False); TopoDS_Shape aScale = aBRepTrsf.Shape(); // 3. aBase2 = geompy.MakeTranslationVectorDistance(Scale, theVec, theH) gp_Trsf aTrsf3; aTrsf3.SetTranslation(theVector); TopLoc_Location aLocOrig = aScale.Location(); gp_Trsf aTrsfOrig = aLocOrig.Transformation(); TopLoc_Location aLocRes (aTrsf3 * aTrsfOrig); TopoDS_Shape aBase2 = aScale.Located(aLocRes); // 4. aCDG_2 = geompy.MakeTranslationVectorDistance(aCDG, theVec, theH) gp_Pnt aCDG_2 = aCDG.Translated(theVector); TopoDS_Shape aShapeCDG_2 = BRepBuilderAPI_MakeVertex(aCDG_2).Shape(); // 5. Vector = geompy.MakeVector(aCDG, aCDG_2) TopoDS_Shape aShapeVec = BRepBuilderAPI_MakeEdge(aCDG, aCDG_2).Shape(); TopoDS_Edge anEdge = TopoDS::Edge(aShapeVec); TopoDS_Wire aWirePath = BRepBuilderAPI_MakeWire(anEdge); // 6. aPrism = geompy.MakePipeWithDifferentSections([theBase, aBase2], [aCDG, aCDG_2], Vector, False, False) Handle(TopTools_HSequenceOfShape) aBases = new TopTools_HSequenceOfShape; aBases->Append(theShapeBase); aBases->Append(aBase2); Handle(TopTools_HSequenceOfShape) aLocs = new TopTools_HSequenceOfShape; aLocs->Append(aShapeCDG_1); aLocs->Append(aShapeCDG_2); aShape = GEOMImpl_PipeDriver::CreatePipeWithDifferentSections(aWirePath, aBases, aLocs, false, false); // 7. Make a solid, if possible if (theShapeBase.ShapeType() == TopAbs_FACE) { BRepBuilderAPI_Sewing aSewing (Precision::Confusion()*10.0); TopExp_Explorer expF (aShape, TopAbs_FACE); Standard_Integer ifa = 0; for (; expF.More(); expF.Next()) { aSewing.Add(expF.Current()); ifa++; } if (ifa > 0) { aSewing.Perform(); TopoDS_Shape aShell; TopoDS_Shape sh = aSewing.SewedShape(); if (sh.ShapeType() == TopAbs_FACE && ifa == 1) { // case for creation of shell from one face TopoDS_Shell ss; B.MakeShell(ss); B.Add(ss,sh); aShell = ss; } else { TopExp_Explorer exp (sh, TopAbs_SHELL); Standard_Integer ish = 0; for (; exp.More(); exp.Next()) { aShell = exp.Current(); ish++; } if (ish != 1) aShell = sh; } BRepCheck_Shell chkShell (TopoDS::Shell(aShell)); if (chkShell.Closed() == BRepCheck_NoError) { TopoDS_Solid Sol; B.MakeSolid(Sol); B.Add(Sol, aShell); BRepClass3d_SolidClassifier SC (Sol); SC.PerformInfinitePoint(Precision::Confusion()); if (SC.State() == TopAbs_IN) { B.MakeSolid(Sol); B.Add(Sol, aShell.Reversed()); } aShape = Sol; } } } return aShape; }
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; }