-// Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2022 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
#include <GEOMUtils.hxx>
-#include <Basics_OCCTVersion.hxx>
-
-#include <OpUtil.hxx>
#include <Utils_ExceptHandlers.hxx>
// OCCT Includes
#include <BRepGProp.hxx>
#include <BRepTools.hxx>
+#include <BRepClass_FaceClassifier.hxx>
#include <BRepClass3d_SolidClassifier.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <Bnd_Box.hxx>
+#include <BOPAlgo_ArgumentAnalyzer.hxx>
#include <BOPTools_AlgoTools.hxx>
#include <TopAbs.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TopTools_Array1OfShape.hxx>
+#include <GeomAPI_ProjectPointOnSurf.hxx>
+
#include <Geom_Circle.hxx>
#include <Geom_Surface.hxx>
#include <Geom_Plane.hxx>
#include <sstream>
#include <algorithm>
+#include <V3d_Coordinate.hxx>
+
#include <Standard_Failure.hxx>
#include <Standard_NullObject.hxx>
#include <Standard_ErrorHandler.hxx> // 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
+#define DEFAULT_TOLERANCE_TOLERANCE 1.e-02
+#define DEFAULT_MAX_TOLERANCE_TOLERANCE 1.e-06
+
// 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
levelsListStr.push_back( substr );
}
GEOMUtils::LevelsList levelsListData;
- for( int level = 0; level < levelsListStr.size(); level++ ) {
+ for( size_t level = 0; level < levelsListStr.size(); level++ ) {
std::vector<std::string> namesListStr;
std::stringstream ss1( levelsListStr[level] );
while ( std::getline( ss1, substr, ',' ) ) {
namesListStr.push_back( substr );
}
GEOMUtils::LevelInfo levelInfoData;
- for( int node = 0; node < namesListStr.size(); node++ ) {
+ for( size_t node = 0; node < namesListStr.size(); node++ ) {
std::vector<std::string> linksListStr;
std::stringstream ss2( namesListStr[node] );
while ( std::getline( ss2, substr, '_' ) ) {
std::string nodeItem = linksListStr[0];
if( !nodeItem.empty() ) {
GEOMUtils::NodeLinks linksListData;
- for( int link = 1; link < linksListStr.size(); link++ ) {
+ for( size_t link = 1; link < linksListStr.size(); link++ ) {
std::string linkItem = linksListStr[link];
linksListData.push_back( linkItem );
}// Links
// skl 30.06.2008
// additional workaround for bugs 19899, 19908 and 19910 from Mantis
- double dist = GEOMUtils::GetMinDistanceSingular
- (theShape1, theShape2, thePnt1, thePnt2);
+ aResult = GEOMUtils::GetMinDistanceSingular(theShape1, theShape2, thePnt1, thePnt2);
+ /*
if (dist > -1.0) {
return dist;
}
+ */
BRepExtrema_DistShapeShape dst (theShape1, theShape2);
if (dst.IsDone()) {
P2 = dst.PointOnShape2(i);
Standard_Real Dist = P1.Distance(P2);
- if (aResult > Dist) {
+ if (aResult < 0 || aResult > Dist) {
aResult = Dist;
thePnt1 = P1;
thePnt2 = P2;
return aResult;
}
+//=======================================================================
+// function : ProjectPointOnFace()
+// purpose : Returns the projection (3d point) if found, throws an exception otherwise
+//=======================================================================
+gp_Pnt GEOMUtils::ProjectPointOnFace(const gp_Pnt& thePoint,
+ const TopoDS_Shape& theFace,
+ double& theU, double& theV)
+{
+ if (theFace.IsNull() || theFace.ShapeType() != TopAbs_FACE)
+ Standard_TypeMismatch::Raise
+ ("Projection aborted : the target shape is not a face");
+
+ TopoDS_Face aFace = TopoDS::Face(theFace);
+ Handle(Geom_Surface) surface = BRep_Tool::Surface(aFace);
+ double U1, U2, V1, V2;
+ BRepTools::UVBounds(aFace, U1, U2, V1, V2);
+
+ // projector
+ Standard_Real tol = 1.e-4;
+ GeomAPI_ProjectPointOnSurf proj;
+ proj.Init(surface, U1, U2, V1, V2, tol);
+ proj.Perform(thePoint);
+ if (!proj.IsDone())
+ StdFail_NotDone::Raise("Projection aborted : the algorithm failed");
+ int nbPoints = proj.NbPoints();
+ if (nbPoints < 1)
+ Standard_ConstructionError::Raise("Projection aborted : No solution found");
+ proj.LowerDistanceParameters(theU, theV);
+ gp_Pnt2d aProjPnt (theU, theV);
+
+ // classifier
+ BRepClass_FaceClassifier aClsf (aFace, aProjPnt, tol);
+ if (aClsf.State() != TopAbs_IN && aClsf.State() != TopAbs_ON) {
+ bool isSol = false;
+ double minDist = RealLast();
+ for (int i = 1; i <= nbPoints; i++) {
+ Standard_Real Ui, Vi;
+ proj.Parameters(i, Ui, Vi);
+ aProjPnt = gp_Pnt2d(Ui, Vi);
+ aClsf.Perform(aFace, aProjPnt, tol);
+ if (aClsf.State() == TopAbs_IN || aClsf.State() == TopAbs_ON) {
+ isSol = true;
+ double dist = proj.Distance(i);
+ if (dist < minDist) {
+ minDist = dist;
+ theU = Ui;
+ theV = Vi;
+ }
+ }
+ }
+ if (!isSol) {
+ Standard_ConstructionError::Raise("Projection aborted : No solution found");
+ }
+ }
+
+ gp_Pnt surfPnt = surface->Value(theU, theV);
+ return surfPnt;
+}
+
//=======================================================================
// function : ConvertClickToPoint()
// purpose : Returns the point clicked in 3D view
//=======================================================================
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 );
-
- aView->At( XAt, YAt, ZAt );
- gp_Pnt EyePoint( XEye, YEye, ZEye );
- gp_Pnt AtPoint( XAt, YAt, ZAt );
+ // We can't rely on Eye and At points to get EyeDir, because they collapse
+ // for views with flat bounding boxes. For example if you create a circle and
+ // switch to the top view, then both camera's Eye and At points will fall to zero
+ // inside V3d_View::FitMinMax() method. It's by occt design.
+ // So, we should use camera direction instead.
- gp_Vec EyeVector( EyePoint, AtPoint );
- gp_Dir EyeDir( EyeVector );
+ V3d_Coordinate XAt, YAt, ZAt;
+ aView->At(XAt, YAt, ZAt);
+ gp_Pnt AtPoint(XAt, YAt, ZAt);
- gp_Pln PlaneOfTheView = gp_Pln( AtPoint, EyeDir );
+ gp_Pln PlaneOfTheView = gp_Pln( AtPoint, aView->Camera()->Direction() );
Standard_Real X, Y, Z;
aView->Convert( x, y, X, Y, Z );
gp_Pnt ConvertedPoint( X, Y, Z );
std::string objectEntry = dependencyStr.substr( cursor, objectIndex - cursor );
cursor = objectIndex;
- std::size_t upwardIndexBegin = dependencyStr.find("{",cursor) + 1;
- std::size_t upwardIndexFinish = dependencyStr.find("}",upwardIndexBegin);
+ //std::size_t upwardIndexBegin = dependencyStr.find("{",cursor) + 1;
+ //std::size_t upwardIndexFinish = dependencyStr.find("}",upwardIndexBegin);
LevelsList upwardList = parseWard( dependencyStr, cursor );
LevelsList downwardList = parseWard( dependencyStr, cursor );
return analyzer.IsValid();
}
+bool GEOMUtils::CheckBOPArguments(const TopoDS_Shape &theShape)
+{
+ BOPAlgo_ArgumentAnalyzer aChecker;
+
+ aChecker.SetShape1(theShape);
+
+ // Set default options
+ aChecker.ArgumentTypeMode() = Standard_True;
+ aChecker.SelfInterMode() = Standard_True;
+ aChecker.SmallEdgeMode() = Standard_True;
+ aChecker.RebuildFaceMode() = Standard_True;
+ aChecker.ContinuityMode() = Standard_True;
+ aChecker.CurveOnSurfaceMode() = Standard_True;
+
+ aChecker.StopOnFirstFaulty() = Standard_True;
+ aChecker.Perform();
+
+ // process result of checking
+ const bool isValid = !aChecker.HasFaulty();
+
+ return isValid;
+}
+
bool GEOMUtils::FixShapeTolerance( TopoDS_Shape& shape,
TopAbs_ShapeEnum type,
Standard_Real tolerance,
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;
+}
+
+//=======================================================================
+//function : IsOpenPath
+//purpose :
+//=======================================================================
+bool GEOMUtils::IsOpenPath(const TopoDS_Shape &theShape)
+{
+ bool isOpen = true;
+
+ if (theShape.IsNull() == Standard_False) {
+ if (theShape.Closed()) {
+ // The shape is closed
+ isOpen = false;
+ } else {
+ const TopAbs_ShapeEnum aType = theShape.ShapeType();
+
+ if (aType == TopAbs_EDGE || aType == TopAbs_WIRE) {
+ // Check if path ends are coincident.
+ TopoDS_Vertex aV[2];
+
+ if (aType == TopAbs_EDGE) {
+ // Edge
+ TopExp::Vertices(TopoDS::Edge(theShape), aV[0], aV[1]);
+ } else {
+ // Wire
+ TopExp::Vertices(TopoDS::Wire(theShape), aV[0], aV[1]);
+ }
+
+ if (aV[0].IsNull() == Standard_False &&
+ aV[1].IsNull() == Standard_False) {
+ if (aV[0].IsSame(aV[1])) {
+ // The shape is closed
+ isOpen = false;
+ } else {
+ const Standard_Real aTol1 = BRep_Tool::Tolerance(aV[0]);
+ const Standard_Real aTol2 = BRep_Tool::Tolerance(aV[1]);
+ const gp_Pnt aPnt1 = BRep_Tool::Pnt(aV[0]);
+ const gp_Pnt aPnt2 = BRep_Tool::Pnt(aV[1]);
+
+ if (aPnt1.Distance(aPnt2) <= aTol1 + aTol2) {
+ // The shape is closed
+ isOpen = false;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return isOpen;
+}
+
+//=======================================================================
+//function : CompareToleranceValues
+//purpose :
+//=======================================================================
+int GEOMUtils::CompareToleranceValues(const double theTolShape,
+ const double theTolRef)
+{
+ const double aTolTol = Min(DEFAULT_MAX_TOLERANCE_TOLERANCE,
+ theTolRef*DEFAULT_TOLERANCE_TOLERANCE);
+
+ int aResult = 0;
+
+ if (theTolShape < theTolRef - aTolTol) {
+ aResult = -1;
+ } else if (theTolShape > theTolRef + aTolTol) {
+ aResult = 1;
+ }
+
+ return aResult;
+}
+
+//=======================================================================
+//function : IsFitCondition
+//purpose :
+//=======================================================================
+bool GEOMUtils::IsFitCondition(const ComparisonCondition theCondition,
+ const double theTolShape,
+ const double theTolRef)
+{
+ const int aCompValue = CompareToleranceValues(theTolShape, theTolRef);
+ bool isFit = false;
+
+ switch (theCondition) {
+ case CC_GT:
+ isFit = aCompValue == 1;
+ break;
+ case GEOMUtils::CC_GE:
+ isFit = aCompValue != -1;
+ break;
+ case GEOMUtils::CC_LT:
+ isFit = aCompValue == -1;
+ break;
+ case GEOMUtils::CC_LE:
+ isFit = aCompValue != 1;
+ break;
+ default:
+ break;
+ }
+
+ return isFit;
+}