X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGEOMUtils%2FGEOMUtils.cxx;h=9b7ca2d970de5f23e4ee4db05819d217ab8de3ed;hb=478182de8e9b70fd4d683ee7a714290cdad3f9f8;hp=95aca3a399335e6209c23db00d4ee9c2812dfa02;hpb=fa14a07690f382aa725c3b494d903a08ead4df52;p=modules%2Fgeom.git diff --git a/src/GEOMUtils/GEOMUtils.cxx b/src/GEOMUtils/GEOMUtils.cxx index 95aca3a39..9b7ca2d97 100644 --- a/src/GEOMUtils/GEOMUtils.cxx +++ b/src/GEOMUtils/GEOMUtils.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -26,7 +26,6 @@ #include -#include #include #include @@ -44,9 +43,14 @@ #include #include +#include + +#include #include +#include + #include #include #include @@ -82,26 +86,257 @@ #include #include +#include #include #include #include #include +#include #include #include #include // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC +#define MAX2(X, Y) (Abs(X) > Abs(Y) ? Abs(X) : Abs(Y)) +#define MAX3(X, Y, Z) (MAX2(MAX2(X,Y), Z)) + #define STD_SORT_ALGO 1 -namespace GEOMUtils { +// When the following macro is defined, ShapeFix_ShapeTolerance function is used to set max tolerance of curve +// in GEOMUtils::FixShapeCurves function; otherwise less restrictive BRep_Builder::UpdateEdge/UpdateVertex +// approach is used +// VSR (29/12/2014): macro disabled +//#define USE_LIMIT_TOLERANCE + +namespace +{ + /** + * This function constructs and returns modified shape from the original one + * for singular cases. It is used for the method GetMinDistanceSingular. + * + * \param theShape the original shape + * \param theModifiedShape output parameter. The modified shape. + * \param theAddDist output parameter. The added distance for modified shape. + * \retval true if the shape is modified; false otherwise. + * + * \internal + */ + Standard_Boolean ModifyShape(const TopoDS_Shape &theShape, + TopoDS_Shape &theModifiedShape, + Standard_Real &theAddDist) + { + TopExp_Explorer anExp; + int nbf = 0; + + theAddDist = 0.; + theModifiedShape.Nullify(); + + for ( anExp.Init( theShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) { + nbf++; + theModifiedShape = anExp.Current(); + } + if(nbf==1) { + TopoDS_Shape sh = theShape; + while(sh.ShapeType()==TopAbs_COMPOUND) { + TopoDS_Iterator it(sh); + sh = it.Value(); + } + Handle(Geom_Surface) S = BRep_Tool::Surface(TopoDS::Face(theModifiedShape)); + if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) || + S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) || + S->IsUPeriodic()) { + const Standard_Boolean isShell = + (sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE); + + if ( !isShell && S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ) { + Handle(Geom_SphericalSurface) SS = Handle(Geom_SphericalSurface)::DownCast(S); + gp_Pnt PC = SS->Location(); + BRep_Builder B; + TopoDS_Vertex V; + B.MakeVertex(V,PC,1.e-7); + theModifiedShape = V; + theAddDist = SS->Radius(); + return Standard_True; + } + if ( !isShell && S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) { + Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(S); + gp_Ax3 ax3 = TS->Position(); + Handle(Geom_Circle) C = new Geom_Circle(ax3.Ax2(),TS->MajorRadius()); + BRep_Builder B; + TopoDS_Edge E; + B.MakeEdge(E,C,1.e-7); + theModifiedShape = E; + theAddDist = TS->MinorRadius(); + return Standard_True; + } + + // non solid case or any periodic surface (Mantis 22454). + double U1,U2,V1,V2; + // changes for 0020677: EDF 1219 GEOM: MinDistance gives 0 instead of 20.88 + //S->Bounds(U1,U2,V1,V2); changed by + ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(theModifiedShape),U1,U2,V1,V2); + // end of changes for 020677 (dmv) + Handle(Geom_RectangularTrimmedSurface) TrS1 = + new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2); + Handle(Geom_RectangularTrimmedSurface) TrS2 = + new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2); + TopoDS_Shape aMShape; + + TopoDS_Face F1 = BRepBuilderAPI_MakeFace(TrS1, Precision::Confusion()); + TopoDS_Face F2 = BRepBuilderAPI_MakeFace(TrS2, Precision::Confusion()); + + if (isShell) { + BRep_Builder B; + B.MakeCompound(TopoDS::Compound(aMShape)); + B.Add(aMShape, F1); + B.Add(aMShape, F2); + } else { + // The original shape is a solid. + BRepBuilderAPI_Sewing aSewing (Precision::Confusion()*10.0); + aSewing.Add(F1); + aSewing.Add(F2); + aSewing.Perform(); + aMShape = aSewing.SewedShape(); + BRep_Builder B; + TopoDS_Solid aSolid; + B.MakeSolid(aSolid); + B.Add(aSolid, aMShape); + aMShape = aSolid; + } + + Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape; + sfs->Init(aMShape); + sfs->SetPrecision(1.e-6); + sfs->SetMaxTolerance(1.0); + sfs->Perform(); + theModifiedShape = sfs->Shape(); + return Standard_True; + } + } + + theModifiedShape = theShape; + return Standard_False; + } + + void parseWard( const GEOMUtils::LevelsList &theLevelList, std::string &treeStr ) + { + treeStr.append( "{" ); + for( GEOMUtils::LevelsList::const_iterator j = theLevelList.begin(); + j != theLevelList.end(); ++j ) { + if ( j != theLevelList.begin() ) { + treeStr.append( ";" ); + } + GEOMUtils::LevelInfo level = (*j); + GEOMUtils::LevelInfo::iterator upIter; + for ( upIter = level.begin(); upIter != level.end(); ++upIter ) { + if ( upIter != level.begin() ) { + treeStr.append( "," ); + } + treeStr.append( upIter->first ); + for ( std::vector::iterator k = upIter->second.begin(); k != upIter->second.end(); ++k ) { + treeStr.append( "_" ); + treeStr.append( *k ); + } + } + } + treeStr.append( "}" ); + } + + GEOMUtils::LevelsList parseWard( const std::string& theData, std::size_t& theCursor ) + { + std::size_t indexStart = theData.find( "{", theCursor ) + 1; + std::size_t indexEnd = theData.find( "}", indexStart ); + + std::string ward = theData.substr( indexStart, indexEnd - indexStart ); + std::stringstream ss(ward); + std::string substr; + std::vector levelsListStr; + while ( std::getline( ss, substr, ';' ) ) { + if ( !substr.empty() ) + levelsListStr.push_back( substr ); + } + GEOMUtils::LevelsList levelsListData; + for( int level = 0; level < levelsListStr.size(); level++ ) { + std::vector namesListStr; + std::stringstream ss1( levelsListStr[level] ); + while ( std::getline( ss1, substr, ',' ) ) { + if ( !substr.empty() ) + namesListStr.push_back( substr ); + } + GEOMUtils::LevelInfo levelInfoData; + for( int node = 0; node < namesListStr.size(); node++ ) { + std::vector linksListStr; + std::stringstream ss2( namesListStr[node] ); + while ( std::getline( ss2, substr, '_' ) ) { + if ( !substr.empty() ) + linksListStr.push_back( substr ); + } + std::string nodeItem = linksListStr[0]; + if( !nodeItem.empty() ) { + GEOMUtils::NodeLinks linksListData; + for( int link = 1; link < linksListStr.size(); link++ ) { + std::string linkItem = linksListStr[link]; + linksListData.push_back( linkItem ); + }// Links + levelInfoData[nodeItem] = linksListData; + } + }// Level's objects + levelsListData.push_back(levelInfoData); + }// Levels + + theCursor = indexEnd + 1; + return levelsListData; + } + +} + +//======================================================================= +//function : ShapeToDouble +//purpose : used by CompareShapes::operator() +//======================================================================= +std::pair GEOMUtils::ShapeToDouble (const TopoDS_Shape& S, bool isOldSorting) +{ + // Computing of CentreOfMass + gp_Pnt GPoint; + double Len; + + if (S.ShapeType() == TopAbs_VERTEX) { + GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S)); + Len = (double)S.Orientation(); + } + else { + GProp_GProps GPr; + // BEGIN: fix for Mantis issue 0020842 + if (isOldSorting) { + BRepGProp::LinearProperties(S, GPr); + } + else { + if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) { + BRepGProp::LinearProperties(S, GPr); + } + else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) { + BRepGProp::SurfaceProperties(S, GPr); + } + else { + BRepGProp::VolumeProperties(S, GPr); + } + } + // END: fix for Mantis issue 0020842 + GPoint = GPr.CentreOfMass(); + Len = GPr.Mass(); + } + + double dMidXYZ = GPoint.X() * 999.0 + GPoint.Y() * 99.0 + GPoint.Z() * 0.9; + return std::make_pair(dMidXYZ, Len); +} //======================================================================= //function : GetPosition //purpose : //======================================================================= -gp_Ax3 GetPosition (const TopoDS_Shape& theShape) +gp_Ax3 GEOMUtils::GetPosition (const TopoDS_Shape& theShape) { gp_Ax3 aResult; @@ -161,7 +396,7 @@ gp_Ax3 GetPosition (const TopoDS_Shape& theShape) //function : GetVector //purpose : //======================================================================= -gp_Vec GetVector (const TopoDS_Shape& theShape, +gp_Vec GEOMUtils::GetVector (const TopoDS_Shape& theShape, Standard_Boolean doConsiderOrientation) { if (theShape.IsNull()) @@ -186,51 +421,11 @@ gp_Vec GetVector (const TopoDS_Shape& theShape, return aV; } -//======================================================================= -//function : ShapeToDouble -//purpose : used by CompareShapes::operator() -//======================================================================= -std::pair ShapeToDouble (const TopoDS_Shape& S, bool isOldSorting) -{ - // Computing of CentreOfMass - gp_Pnt GPoint; - double Len; - - if (S.ShapeType() == TopAbs_VERTEX) { - GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S)); - Len = (double)S.Orientation(); - } - else { - GProp_GProps GPr; - // BEGIN: fix for Mantis issue 0020842 - if (isOldSorting) { - BRepGProp::LinearProperties(S, GPr); - } - else { - if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) { - BRepGProp::LinearProperties(S, GPr); - } - else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) { - BRepGProp::SurfaceProperties(S, GPr); - } - else { - BRepGProp::VolumeProperties(S, GPr); - } - } - // END: fix for Mantis issue 0020842 - GPoint = GPr.CentreOfMass(); - Len = GPr.Mass(); - } - - double dMidXYZ = GPoint.X() * 999.0 + GPoint.Y() * 99.0 + GPoint.Z() * 0.9; - return std::make_pair(dMidXYZ, Len); -} - //======================================================================= //function : CompareShapes::operator() //purpose : used by std::sort(), called from SortShapes() //======================================================================= -bool CompareShapes::operator() (const TopoDS_Shape& theShape1, +bool GEOMUtils::CompareShapes::operator() (const TopoDS_Shape& theShape1, const TopoDS_Shape& theShape2) { if (!myMap.IsBound(theShape1)) { @@ -290,7 +485,7 @@ bool CompareShapes::operator() (const TopoDS_Shape& theShape1, //function : SortShapes //purpose : //======================================================================= -void SortShapes (TopTools_ListOfShape& SL, +void GEOMUtils::SortShapes (TopTools_ListOfShape& SL, const Standard_Boolean isOldSorting) { #ifdef STD_SORT_ALGO @@ -428,7 +623,7 @@ void SortShapes (TopTools_ListOfShape& SL, //function : CompsolidToCompound //purpose : //======================================================================= -TopoDS_Shape CompsolidToCompound (const TopoDS_Shape& theCompsolid) +TopoDS_Shape GEOMUtils::CompsolidToCompound (const TopoDS_Shape& theCompsolid) { if (theCompsolid.ShapeType() != TopAbs_COMPSOLID) { return theCompsolid; @@ -455,7 +650,7 @@ TopoDS_Shape CompsolidToCompound (const TopoDS_Shape& theCompsolid) //function : AddSimpleShapes //purpose : //======================================================================= -void AddSimpleShapes (const TopoDS_Shape& theShape, TopTools_ListOfShape& theList) +void GEOMUtils::AddSimpleShapes (const TopoDS_Shape& theShape, TopTools_ListOfShape& theList) { if (theShape.ShapeType() != TopAbs_COMPOUND && theShape.ShapeType() != TopAbs_COMPSOLID) { @@ -483,7 +678,7 @@ void AddSimpleShapes (const TopoDS_Shape& theShape, TopTools_ListOfShape& theLis //function : CheckTriangulation //purpose : //======================================================================= -bool CheckTriangulation (const TopoDS_Shape& aShape) +bool GEOMUtils::CheckTriangulation (const TopoDS_Shape& aShape) { bool isTriangulation = true; @@ -533,7 +728,7 @@ bool CheckTriangulation (const TopoDS_Shape& aShape) //function : GetTypeOfSimplePart //purpose : //======================================================================= -TopAbs_ShapeEnum GetTypeOfSimplePart (const TopoDS_Shape& theShape) +TopAbs_ShapeEnum GEOMUtils::GetTypeOfSimplePart (const TopoDS_Shape& theShape) { TopAbs_ShapeEnum aType = theShape.ShapeType(); if (aType == TopAbs_VERTEX) return TopAbs_VERTEX; @@ -554,7 +749,7 @@ TopAbs_ShapeEnum GetTypeOfSimplePart (const TopoDS_Shape& theShape) //function : GetEdgeNearPoint //purpose : //======================================================================= -TopoDS_Shape GetEdgeNearPoint (const TopoDS_Shape& theShape, +TopoDS_Shape GEOMUtils::GetEdgeNearPoint (const TopoDS_Shape& theShape, const TopoDS_Vertex& thePoint) { TopoDS_Shape aResult; @@ -622,11 +817,13 @@ TopoDS_Shape GetEdgeNearPoint (const TopoDS_Shape& theShape, //function : PreciseBoundingBox //purpose : //======================================================================= -Standard_Boolean PreciseBoundingBox +Standard_Boolean GEOMUtils::PreciseBoundingBox (const TopoDS_Shape &theShape, Bnd_Box &theBox) { - Standard_Real aBound[6]; + if ( theBox.IsVoid() ) BRepBndLib::Add( theShape, theBox ); + if ( theBox.IsVoid() ) return Standard_False; + Standard_Real aBound[6]; theBox.Get(aBound[0], aBound[2], aBound[4], aBound[1], aBound[3], aBound[5]); Standard_Integer i; @@ -658,7 +855,7 @@ Standard_Boolean PreciseBoundingBox const Standard_Integer iHalf = i/2; const gp_Pln aPln(aPnt[i], aDir[iHalf]); BRepBuilderAPI_MakeFace aMkFace(aPln, -aPlnSize[iHalf], aPlnSize[iHalf], - -aPlnSize[iHalf], aPlnSize[iHalf]); + -aPlnSize[iHalf], aPlnSize[iHalf]); if (!aMkFace.IsDone()) { return Standard_False; @@ -668,7 +865,7 @@ Standard_Boolean PreciseBoundingBox // Get minimal distance between planar face and shape. Standard_Real aMinDist = - GetMinDistance(aFace, theShape, aPMin[0], aPMin[1]); + GEOMUtils::GetMinDistance(aFace, theShape, aPMin[0], aPMin[1]); if (aMinDist < 0.) { return Standard_False; @@ -684,128 +881,11 @@ Standard_Boolean PreciseBoundingBox return Standard_True; } -//======================================================================= -// function : ModifyShape -// purpose : This function constructs and returns modified shape -// from the original one for singular cases. -// It is used for the method GetMinDistanceSingular. -// -// \param theShape the original shape -// \param theModifiedShape output parameter. The modified shape. -// \param theAddDist output parameter. The added distance for modified shape. -// \retval true if the shape is modified; false otherwise. -// - -//======================================================================= -Standard_Boolean ModifyShape(const TopoDS_Shape &theShape, - TopoDS_Shape &theModifiedShape, - Standard_Real &theAddDist) -{ - Standard_Boolean isModified = Standard_False; - TopExp_Explorer anExp; - int nbf = 0; - - theAddDist = 0.; - theModifiedShape.Nullify(); - - for ( anExp.Init( theShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) { - nbf++; - theModifiedShape = anExp.Current(); - } - if(nbf==1) { - TopoDS_Shape sh = theShape; - while(sh.ShapeType()==TopAbs_COMPOUND) { - TopoDS_Iterator it(sh); - sh = it.Value(); - } - Handle(Geom_Surface) S = BRep_Tool::Surface(TopoDS::Face(theModifiedShape)); - if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) || - S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) || - S->IsUPeriodic()) { - const Standard_Boolean isShell = - (sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE); - - if( isShell || S->IsUPeriodic() ) { - // non solid case or any periodic surface (Mantis 22454). - double U1,U2,V1,V2; - // changes for 0020677: EDF 1219 GEOM: MinDistance gives 0 instead of 20.88 - //S->Bounds(U1,U2,V1,V2); changed by - ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(theModifiedShape),U1,U2,V1,V2); - // end of changes for 020677 (dmv) - Handle(Geom_RectangularTrimmedSurface) TrS1 = - new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2); - Handle(Geom_RectangularTrimmedSurface) TrS2 = - new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2); - BRep_Builder B; - TopoDS_Face F1,F2; - TopoDS_Shape aMShape; - - if (isShell) { - B.MakeCompound(TopoDS::Compound(aMShape)); - } else { - B.MakeShell(TopoDS::Shell(aMShape)); - } - - B.MakeFace(F1,TrS1,1.e-7); - B.Add(aMShape,F1); - B.MakeFace(F2,TrS2,1.e-7); - B.Add(aMShape,F2); - Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape; - - if (!isShell) { - // The original shape is a solid. - TopoDS_Solid aSolid; - - B.MakeSolid(aSolid); - B.Add(aSolid, aMShape); - aMShape = aSolid; - } - - sfs->Init(aMShape); - sfs->SetPrecision(1.e-6); - sfs->SetMaxTolerance(1.0); - sfs->Perform(); - theModifiedShape = sfs->Shape(); - isModified = Standard_True; - } - else { - if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ) { - Handle(Geom_SphericalSurface) SS = Handle(Geom_SphericalSurface)::DownCast(S); - gp_Pnt PC = SS->Location(); - BRep_Builder B; - TopoDS_Vertex V; - B.MakeVertex(V,PC,1.e-7); - theModifiedShape = V; - theAddDist = SS->Radius(); - isModified = Standard_True; - } - else { - Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(S); - gp_Ax3 ax3 = TS->Position(); - Handle(Geom_Circle) C = new Geom_Circle(ax3.Ax2(),TS->MajorRadius()); - BRep_Builder B; - TopoDS_Edge E; - B.MakeEdge(E,C,1.e-7); - theModifiedShape = E; - theAddDist = TS->MinorRadius(); - isModified = Standard_True; - } - } - } else { - theModifiedShape = theShape; - } - } - else - theModifiedShape = theShape; - - return isModified; -} - //======================================================================= //function : GetMinDistanceSingular //purpose : //======================================================================= -double GetMinDistanceSingular(const TopoDS_Shape& aSh1, +double GEOMUtils::GetMinDistanceSingular(const TopoDS_Shape& aSh1, const TopoDS_Shape& aSh2, gp_Pnt& Ptmp1, gp_Pnt& Ptmp2) { @@ -874,7 +954,7 @@ double GetMinDistanceSingular(const TopoDS_Shape& aSh1, //function : GetMinDistance //purpose : //======================================================================= -Standard_Real GetMinDistance +Standard_Real GEOMUtils::GetMinDistance (const TopoDS_Shape& theShape1, const TopoDS_Shape& theShape2, gp_Pnt& thePnt1, gp_Pnt& thePnt2) @@ -910,7 +990,7 @@ Standard_Real GetMinDistance // skl 30.06.2008 // additional workaround for bugs 19899, 19908 and 19910 from Mantis - double dist = GetMinDistanceSingular + double dist = GEOMUtils::GetMinDistanceSingular (theShape1, theShape2, thePnt1, thePnt2); if (dist > -1.0) { @@ -941,7 +1021,7 @@ Standard_Real GetMinDistance // function : ConvertClickToPoint() // purpose : Returns the point clicked in 3D view //======================================================================= -gp_Pnt ConvertClickToPoint( int x, int y, Handle(V3d_View) aView ) +gp_Pnt GEOMUtils::ConvertClickToPoint( int x, int y, Handle(V3d_View) aView ) { V3d_Coordinate XEye, YEye, ZEye, XAt, YAt, ZAt; aView->Eye( XEye, YEye, ZEye ); @@ -967,130 +1047,192 @@ gp_Pnt ConvertClickToPoint( int x, int y, Handle(V3d_View) aView ) // function : ConvertTreeToString() // purpose : Returns the string representation of dependency tree //======================================================================= -void ConvertTreeToString( const TreeModel &tree, - std::string &treeStr ) +void GEOMUtils::ConvertTreeToString( const TreeModel& tree, + std::string& dependencyStr ) { TreeModel::const_iterator i; for ( i = tree.begin(); i != tree.end(); ++i ) { - treeStr.append( i->first ); - treeStr.append( "-" ); + dependencyStr.append( i->first ); + dependencyStr.append( "-" ); std::vector upLevelList = i->second.first; - treeStr.append( "upward" ); - treeStr.append( "{" ); - for( std::vector::iterator j = upLevelList.begin(); - j != upLevelList.end(); ++j ) { - LevelInfo level = (*j); - LevelInfo::iterator upIter; - for ( upIter = level.begin(); upIter != level.end(); ++upIter ) { - treeStr.append( upIter->first ); - for ( std::vector::iterator k = upIter->second.begin(); - k != upIter->second.end(); ++k ) { - treeStr.append( "_" ); - treeStr.append( *k ); - } - treeStr.append( upIter++ == level.end() ? ";" : "," ); - upIter--; - } - } - treeStr.append( "}" ); + dependencyStr.append( "upward" ); + parseWard( upLevelList, dependencyStr ); std::vector downLevelList = i->second.second; - treeStr.append( "downward" ); - treeStr.append( "{" ); - for( std::vector::iterator j = downLevelList.begin(); - j != downLevelList.end(); ++j ) { - LevelInfo level = (*j); - LevelInfo::iterator downIter; - for ( downIter = level.begin(); downIter != level.end(); ++downIter ) { - treeStr.append( downIter->first ); - for ( std::vector::iterator k = downIter->second.begin(); - k != downIter->second.end(); ++k ) { - treeStr.append( "_" ); - treeStr.append( *k ); - } - treeStr.append( downIter++ == level.end() ? ";" : "," ); - downIter--; - } - } - treeStr.append("}"); + dependencyStr.append( "downward" ); + parseWard( downLevelList, dependencyStr ); } } -LevelsList parseWard( const std::string& theData, std::size_t& theCursor ) -{ - std::size_t indexStart = theData.find( "{", theCursor ) + 1; - std::size_t indexEnd = theData.find( "}", indexStart ); - - std::string ward = theData.substr( indexStart, indexEnd - indexStart ); - std::stringstream ss(ward); - std::string substr; - std::vector levelsListStr; - while ( std::getline( ss, substr, ';' ) ) { - if ( !substr.empty() ) - levelsListStr.push_back( substr ); - } - LevelsList levelsListData; - for( int level = 0; level < levelsListStr.size(); level++ ) { - std::cout<<" Level" << level + 1 << ":" << std::endl; - std::vector namesListStr; - ss.str( levelsListStr[level] ); - while ( std::getline( ss, substr, ',' ) ) { - if ( !substr.empty() ) - namesListStr.push_back( substr ); - } - LevelInfo levelInfoData; - for( int node = 0; node < namesListStr.size(); node++ ) { - std::vector linksListStr; - ss.str( namesListStr[node] ); - while ( std::getline( ss, substr, '_' ) ) { - if ( !substr.empty() ) - linksListStr.push_back( substr ); - } - std::string nodeItem = linksListStr[0]; - if( !nodeItem.empty() ) { - NodeLinks linksListData; - std::cout<<" " << nodeItem << " - "; - for( int link = 1; link < linksListStr.size(); link++ ) { - std::string linkItem = linksListStr[link]; - linksListData.push_back( linkItem ); - std::cout << linkItem << ", "; - }// Links - levelInfoData[nodeItem] = linksListData; - std::cout << std::endl; - } - }// Level's objects - levelsListData.push_back(levelInfoData); - }// Levels - - theCursor = indexEnd + 1; - return levelsListData; -} - //======================================================================= // function : ConvertStringToTree() // purpose : Returns the dependency tree //======================================================================= -void ConvertStringToTree( const std::string &theData, - TreeModel &tree ) +void GEOMUtils::ConvertStringToTree( const std::string& dependencyStr, + TreeModel& tree ) { std::size_t cursor = 0; - while( theData.find('-',cursor) != std::string::npos ) //find next selected object + while( dependencyStr.find('-',cursor) != std::string::npos ) //find next selected object { - std::size_t objectIndex = theData.find( '-', cursor ); - std::string objectEntry = theData.substr( cursor, objectIndex - cursor ); - std::cout<<"\n\nMainObject = " << objectEntry <( upwardList, downwardList ); } } -} //namespace GEOMUtils +bool GEOMUtils::CheckShape( TopoDS_Shape& shape, + bool checkGeometry ) +{ + BRepCheck_Analyzer analyzer( shape, checkGeometry ); + return analyzer.IsValid(); +} + +bool GEOMUtils::FixShapeTolerance( TopoDS_Shape& shape, + TopAbs_ShapeEnum type, + Standard_Real tolerance, + bool checkGeometry ) +{ + ShapeFix_ShapeTolerance aSft; + aSft.LimitTolerance( shape, tolerance, tolerance, type ); + Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape( shape ); + aSfs->Perform(); + shape = aSfs->Shape(); + return CheckShape( shape, checkGeometry ); +} + +bool GEOMUtils::FixShapeTolerance( TopoDS_Shape& shape, + Standard_Real tolerance, + bool checkGeometry ) +{ + return FixShapeTolerance( shape, TopAbs_SHAPE, tolerance, checkGeometry ); +} + +bool GEOMUtils::FixShapeTolerance( TopoDS_Shape& shape, + bool checkGeometry ) +{ + return FixShapeTolerance( shape, Precision::Confusion(), checkGeometry ); +} + +bool GEOMUtils::FixShapeCurves( TopoDS_Shape& shape ) +{ + Standard_Real aT, aTolE, aD, aDMax; + TopExp_Explorer aExpF, aExpE; + NCollection_DataMap aDMETol; + aExpF.Init(shape, TopAbs_FACE); + for (; aExpF.More(); aExpF.Next()) { + const TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current(); + aExpE.Init(aF, TopAbs_EDGE); + for (; aExpE.More(); aExpE.Next()) { + const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current(); + try { + if (!BOPTools_AlgoTools::ComputeTolerance(aF, aE, aDMax, aT)) { + continue; + } + } + catch(...) { + continue; + } + aTolE = BRep_Tool::Tolerance(aE); + if (aDMax < aTolE) continue; + if (aDMETol.IsBound(aE)) { + aD = aDMETol.Find(aE); + if (aDMax > aD) { + aDMETol.UnBind(aE); + aDMETol.Bind(aE, aDMax); + } + } + else { + aDMETol.Bind(aE, aDMax); + } + } + } + NCollection_DataMap::Iterator aDMETolIt(aDMETol); +#ifdef USE_LIMIT_TOLERANCE + ShapeFix_ShapeTolerance sat; +#else + BRep_Builder b; +#endif + for (; aDMETolIt.More(); aDMETolIt.Next()) { +#ifdef USE_LIMIT_TOLERANCE + sat.LimitTolerance(aDMETolIt.Key(), aDMETolIt.Value()*1.001); +#else + TopoDS_Iterator itv(aDMETolIt.Key()); + for (; itv.More(); itv.Next()) + b.UpdateVertex(TopoDS::Vertex(itv.Value()), aDMETolIt.Value()*1.001); + b.UpdateEdge(aDMETolIt.Key(), aDMETolIt.Value()*1.001); +#endif + } + return CheckShape( shape ); +} + +bool GEOMUtils::Write( const TopoDS_Shape& shape, const char* fileName ) +{ + return BRepTools::Write( shape, fileName ); +} + +TopoDS_Shape GEOMUtils::ReduceCompound( const TopoDS_Shape& shape ) +{ + TopoDS_Shape result = shape; + + if ( shape.ShapeType() == TopAbs_COMPOUND || + shape.ShapeType() == TopAbs_COMPSOLID ) { + + TopTools_ListOfShape l; + + TopoDS_Iterator it ( shape ); + for ( ; it.More(); it.Next() ) + l.Append( it.Value() ); + if ( l.Extent() == 1 && l.First() != shape ) + result = ReduceCompound( l.First() ); + } + + return result; +} + +void GEOMUtils::MeshShape( const TopoDS_Shape shape, + double deflection, bool theForced ) +{ + Standard_Real aDeflection = ( deflection <= 0 ) ? DefaultDeflection() : deflection; + + // Is shape triangulated? + Standard_Boolean alreadyMeshed = true; + TopExp_Explorer ex; + TopLoc_Location aLoc; + for ( ex.Init( shape, TopAbs_FACE ); ex.More() && alreadyMeshed; ex.Next() ) { + const TopoDS_Face& aFace = TopoDS::Face( ex.Current() ); + Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation( aFace, aLoc ); + alreadyMeshed = !aPoly.IsNull(); + } + + if ( !alreadyMeshed || theForced ) { + // Compute bounding box + Bnd_Box B; + BRepBndLib::Add( shape, B ); + if ( B.IsVoid() ) + return; // NPAL15983 (Bug when displaying empty groups) + Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; + B.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax ); + + // This magic line comes from Prs3d_ShadedShape.gxx in OCCT + aDeflection = MAX3(aXmax-aXmin, aYmax-aYmin, aZmax-aZmin) * aDeflection * 4; + + // Clean triangulation before compute incremental mesh + BRepTools::Clean( shape ); + + // Compute triangulation + BRepMesh_IncrementalMesh mesh( shape, aDeflection ); + } +} + +double GEOMUtils::DefaultDeflection() +{ + return 0.001; +}