X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGEOMImpl%2FGEOMImpl_IShapesOperations.cxx;h=12b7f46924e6a38c045eab0e40e1321325ecd534;hb=11cbc17d51c4ea7226b75d501ea7d5ca2a1e1480;hp=0f91f4b5e0844e9240b6da1a03ed4e3e78d6eaf7;hpb=a05e9c326e3526542a7f9dc4bd1f966b4e9c60f7;p=modules%2Fgeom.git diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx index 0f91f4b5e..12b7f4692 100644 --- a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2020 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 @@ -6,7 +6,7 @@ // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either -// version 2.1 of the License. +// version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,7 +25,7 @@ // Author : modified by Lioka RAZAFINDRAZAKA (CEA) 22/06/2007 // Project : SALOME -#include +//#include #include "GEOMImpl_IShapesOperations.hxx" @@ -33,17 +33,20 @@ #include "GEOMImpl_VectorDriver.hxx" #include "GEOMImpl_ShapeDriver.hxx" -#include "GEOMImpl_CopyDriver.hxx" #include "GEOMImpl_GlueDriver.hxx" +#include "GEOMImpl_FillingDriver.hxx" +#include "GEOMImpl_IExtract.hxx" #include "GEOMImpl_IVector.hxx" #include "GEOMImpl_IShapes.hxx" +#include "GEOMImpl_IShapeExtend.hxx" #include "GEOMImpl_IGlue.hxx" +#include "GEOMImpl_IFilling.hxx" #include "GEOMImpl_Block6Explorer.hxx" #include "GEOMImpl_IHealingOperations.hxx" -#include +#include "GEOMImpl_Gen.hxx" #include "GEOM_Function.hxx" #include "GEOM_ISubShape.hxx" @@ -52,105 +55,129 @@ #include "GEOMUtils.hxx" #include "GEOMAlgo_ClsfBox.hxx" +#include "GEOMAlgo_ClsfQuad.hxx" #include "GEOMAlgo_ClsfSolid.hxx" -#include "GEOMAlgo_CoupleOfShapes.hxx" -#include "GEOMAlgo_FinderShapeOn1.hxx" -#include "GEOMAlgo_FinderShapeOnQuad.hxx" +#include "GEOMAlgo_ClsfSurf.hxx" #include "GEOMAlgo_FinderShapeOn2.hxx" #include "GEOMAlgo_GetInPlace.hxx" +#include "GEOMAlgo_GetInPlaceAPI.hxx" #include "GEOMAlgo_GlueDetector.hxx" -#include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx" -#include "GEOMAlgo_ListOfCoupleOfShapes.hxx" -#include +#include -#include "utilities.h" -#include "OpUtil.hxx" -#include "Utils_ExceptHandlers.hxx" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include #include #include -#include -#include - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include -#include #include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include #include #include -#include -#include -#include #include #include // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC -// Includes added for GetInPlace algorithm improvement +// VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump +// Next macro, when defined, causes appearing of SubShapeAllIDs(), SubShapeAllSortedIDs(), GetSameIDs() +// and other such commands in Python dump. +// See also GEOM_Engine.cxx. +// --------------------------------------- +// #define DUMP_SUBSHAPE_IDS +// --------------------------------------- -#include -#include -#include +namespace { -#include -#include -#include + void AddFlatSubShapes(const TopoDS_Shape& S, TopTools_ListOfShape& L, TopTools_MapOfShape& M) + { + if (S.ShapeType() != TopAbs_COMPOUND) { + L.Append(S); + } + else { + TopoDS_Iterator It(S, Standard_True, Standard_True); + for (; It.More(); It.Next()) { + TopoDS_Shape SS = It.Value(); + if (M.Add(SS)) + AddFlatSubShapes(SS, L, M); + } + } + } +} + +namespace +{ + const double MAX_TOLERANCE = 1.e-7; + + /** + * \brief Returns the vertex from theWhere shape that is coincident with + * theVertex. + * + * \param theWhere the shape where the coincident vertex is searched. + * \param theVertex the vertex to be searched. + * \return the coincident vertex if it is found. Otherwise null object. + */ + static TopoDS_Vertex getSameVertex(const TopoDS_Shape &theWhere, + const TopoDS_Vertex &theVertex) + { + TopoDS_Vertex aResult; + gp_Pnt aPoint = BRep_Tool::Pnt(theVertex); + TopExp_Explorer anExp(theWhere, TopAbs_VERTEX); + TopTools_MapOfShape aMap; + + for(; anExp.More(); anExp.Next()) { + const TopoDS_Shape &aLocalShape = anExp.Current(); + + if(!aMap.Add(aLocalShape)) { + continue; + } + + TopoDS_Vertex aVertex = TopoDS::Vertex(aLocalShape); + gp_Pnt aPoint2 = BRep_Tool::Pnt(aVertex); + + if(aPoint.Distance(aPoint2) <= MAX_TOLERANCE) { + aResult = aVertex; + break; + } + } + + return aResult; + } +} // end of namespace //============================================================================= /*! * constructor: */ //============================================================================= -GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine, int theDocID) -: GEOM_IOperations(theEngine, theDocID) +GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations (GEOM_Engine* theEngine) +: GEOM_IOperations(theEngine) { MESSAGE("GEOMImpl_IShapesOperations::GEOMImpl_IShapesOperations"); } @@ -178,7 +205,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge if (thePnt1.IsNull() || thePnt2.IsNull()) return NULL; //Add a new Edge object - Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE); + Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GEOM_EDGE); //Add a new Vector function Handle(GEOM_Function) aFunction = @@ -198,17 +225,14 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge //Compute the Edge value try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Vector driver failed"); return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return NULL; } @@ -235,7 +259,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeOnCurveByLength if (theRefCurve.IsNull()) return NULL; //Add a new Edge object - Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE); + Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GEOM_EDGE); //Add a new Vector function Handle(GEOM_Function) aFunction = @@ -259,17 +283,14 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeOnCurveByLength //Compute the Edge value try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Vector driver failed"); return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return NULL; } @@ -296,7 +317,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeWire if (theWire.IsNull()) return NULL; //Add a new Edge object - Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE); + Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GEOM_EDGE); //Add a new Vector function Handle(GEOM_Function) aFunction = @@ -317,17 +338,14 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeWire //Compute the Edge value try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed"); return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return NULL; } @@ -364,7 +382,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire SetErrorCode(KO); //Add a new object - Handle(GEOM_Object) aWire = GetEngine()->AddObject(GetDocID(), GEOM_WIRE); + Handle(GEOM_Object) aWire = GetEngine()->AddObject(GEOM_WIRE); //Add a new function Handle(GEOM_Function) aFunction = @@ -393,17 +411,14 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire //Compute the shape try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed"); return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return NULL; } @@ -438,7 +453,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) th if (theWire.IsNull()) return NULL; //Add a new Face object - Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE); + Handle(GEOM_Object) aFace = GetEngine()->AddObject(GEOM_FACE); //Add a new Shape function for creation of a face from a wire Handle(GEOM_Function) aFunction = @@ -460,17 +475,14 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) th //Compute the Face value Standard_Boolean isWarning = Standard_False; try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed to compute a face"); return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); // to provide warning if (!aFunction->GetValue().IsNull()) { isWarning = Standard_True; @@ -500,7 +512,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires SetErrorCode(KO); //Add a new object - Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FACE); + Handle(GEOM_Object) aShape = GetEngine()->AddObject(GEOM_FACE); //Add a new function Handle(GEOM_Function) aFunction = @@ -531,17 +543,14 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires //Compute the shape Standard_Boolean isWarning = Standard_False; try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed"); return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); // to provide warning if (!aFunction->GetValue().IsNull()) { isWarning = Standard_True; @@ -569,6 +578,180 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires return aShape; } +//============================================================================= +/*! + * MakeFaceFromSurface + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceFromSurface + (Handle(GEOM_Object) theFace, + Handle(GEOM_Object) theWire) +{ + SetErrorCode(KO); + + //Add a new object + Handle(GEOM_Object) aShape = GetEngine()->AddObject(GEOM_FACE); + + //Add a new function + Handle(GEOM_Function) aFunction = + aShape->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_FROM_SURFACE); + + if (aFunction.IsNull()) { + return NULL; + } + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) { + return NULL; + } + + GEOMImpl_IShapes aCI (aFunction); + Handle(TColStd_HSequenceOfTransient) aShapesSeq = + new TColStd_HSequenceOfTransient; + Handle(GEOM_Function) aRefFace = theFace->GetLastFunction(); + Handle(GEOM_Function) aRefWire = theWire->GetLastFunction(); + + if (aRefFace.IsNull()) { + SetErrorCode("NULL argument face for the face construction"); + return NULL; + } + + if (aRefWire.IsNull()) { + SetErrorCode("NULL argument wire for the face construction"); + return NULL; + } + + aShapesSeq->Append(aRefFace); + aShapesSeq->Append(aRefWire); + + aCI.SetShapes(aShapesSeq); + + //Compute the face + try { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Shape driver failed"); + return NULL; + } + } + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); + return NULL; + } + + //Make a Python command + GEOM::TPythonDump (aFunction) << aShape + << " = geompy.MakeFaceFromSurface(" << theFace << ", " << theWire << ")"; + + SetErrorCode(OK); + + return aShape; +} + +//============================================================================= +/*! + * MakeFaceWithConstraints + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWithConstraints + (std::list theConstraints) +{ + SetErrorCode(KO); + + //Add a new object + Handle(GEOM_Object) aShape = GetEngine()->AddObject(GEOM_FILLING); + + //Add a new function + Handle(GEOM_Function) aFunction = + aShape->AddFunction(GEOMImpl_FillingDriver::GetID(), FILLING_ON_CONSTRAINTS); + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_FillingDriver::GetID()) return NULL; + + GEOMImpl_IFilling aCI (aFunction); + Handle(TColStd_HSequenceOfTransient) aConstraints = new TColStd_HSequenceOfTransient; + + // Shapes + std::list::iterator it = theConstraints.begin(); + while (it != theConstraints.end()) { + Handle(GEOM_Object) anObject = (*it); + if ( anObject.IsNull() || anObject->GetValue().ShapeType() != TopAbs_EDGE ) { + SetErrorCode("NULL argument edge for the face construction"); + return NULL; + } + Handle(GEOM_Function) aRefSh = anObject->GetLastFunction(); + aConstraints->Append(aRefSh); + it++; + if ( it != theConstraints.end() ) { + Handle(GEOM_Object) aFace = (*it); + if ( aFace.IsNull() ) { + // null constraint face - it is a valid case + it++; + continue; + } + if ( aFace->GetValue().ShapeType() != TopAbs_FACE ) + // constraint face can be omitted - it is a valid case + continue; + // Keep the old error code as IsSubShapeBelongsTo changes it. + TCollection_AsciiString anOldCode = GetErrorCode(); + + if ( IsSubShapeBelongsTo( anObject, 0, aFace, 0 ) ) { + // valid constraint + SetErrorCode(anOldCode); + aRefSh = aFace->GetLastFunction(); + aConstraints->Append(aRefSh); + it++; + } + else { + // bad constraint + SetErrorCode("Face is NULL or not connected to the Edge"); + return NULL; + } + } + } + aCI.SetShapes( aConstraints ); + + //Compute the shape + Standard_Boolean isWarning = Standard_False; + try { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Shape driver failed"); + return NULL; + } + } + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); + // to provide warning + if (!aFunction->GetValue().IsNull()) { + isWarning = Standard_True; + } else { + return NULL; + } + } + + //Make a Python command + GEOM::TPythonDump pd (aFunction); + pd << aShape << " = geompy.MakeFaceWithConstraints(["; + + // Constraints + it = theConstraints.begin(); + if (it != theConstraints.end() ) { + pd << (*it++); + while (it != theConstraints.end()) { + Handle(GEOM_Object) anObject = (*it++); + if( !anObject.IsNull() ) + pd << ", " << anObject; + } + } + pd << "])"; + + // to provide warning + if (!isWarning) SetErrorCode(OK); + return aShape; +} + //============================================================================= /*! * MakeShell @@ -616,7 +799,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape SetErrorCode(KO); //Add a new object - Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), theObjectType); + Handle(GEOM_Object) aShape = GetEngine()->AddObject(theObjectType); //Add a new function Handle(GEOM_Function) aFunction = @@ -644,17 +827,14 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape //Compute the shape try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed"); return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return NULL; } @@ -676,22 +856,96 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape return aShape; } +//============================================================================= +/*! + * MakeSolidFromConnectedFaces + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidFromConnectedFaces + (std::list theFacesOrShells, + const Standard_Boolean isIntersect) +{ + SetErrorCode(KO); + + //Add a new object + Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GEOM_SOLID); + + //Add a new function + Handle(GEOM_Function) aFunction = + aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_FACES); + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL; + + GEOMImpl_IShapes aCI (aFunction); + + Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient; + + // Shapes + std::list::iterator it = theFacesOrShells.begin(); + for (; it != theFacesOrShells.end(); it++) { + Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction(); + if (aRefSh.IsNull()) { + SetErrorCode("NULL argument shape for the shape construction"); + return NULL; + } + aShapesSeq->Append(aRefSh); + } + aCI.SetShapes(aShapesSeq); + aCI.SetIsIntersect(isIntersect); + + //Compute the shape + try { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Shape driver failed"); + return NULL; + } + } + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); + return NULL; + } + + //Make a Python command + GEOM::TPythonDump pd (aFunction); + pd << aSolid << " = geompy.MakeSolidFromConnectedFaces(["; + + // Shapes + it = theFacesOrShells.begin(); + if (it != theFacesOrShells.end()) { + pd << (*it++); + while (it != theFacesOrShells.end()) { + pd << ", " << (*it++); + } + } + pd << "]," << (isIntersect ? "True" : "False") << ")"; + + SetErrorCode(OK); + return aSolid; +} + //============================================================================= /*! * MakeGlueFaces */ //============================================================================= -Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces - (Handle(GEOM_Object) theShape, - const Standard_Real theTolerance, - const Standard_Boolean doKeepNonSolids) +Handle(GEOM_Object) +GEOMImpl_IShapesOperations::MakeGlueFaces (std::list< Handle(GEOM_Object) >& theShapes, + const Standard_Real theTolerance, + const Standard_Boolean doKeepNonSolids) { SetErrorCode(KO); - if (theShape.IsNull()) return NULL; + Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes ); + if ( objects.IsNull() || objects->IsEmpty() ) { + SetErrorCode("NULL argument shape"); + return NULL; + } //Add a new Glued object - Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED); + Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GEOM_GLUED); //Add a new Glue function Handle(GEOM_Function) aFunction; @@ -703,27 +957,21 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces GEOMImpl_IGlue aCI (aFunction); - Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); - if (aRefShape.IsNull()) return NULL; - - aCI.SetBase(aRefShape); + aCI.SetBase( objects ); aCI.SetTolerance(theTolerance); aCI.SetKeepNonSolids(doKeepNonSolids); //Compute the sub-shape value Standard_Boolean isWarning = Standard_False; try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed to glue faces"); return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); // to provide warning if (!aFunction->GetValue().IsNull()) { isWarning = Standard_True; @@ -734,7 +982,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces //Make a Python command GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueFaces(" - << theShape << ", " << theTolerance << ")"; + << theShapes << ", " << theTolerance << ")"; // to provide warning if (!isWarning) SetErrorCode(OK); @@ -823,19 +1071,28 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces * MakeGlueFacesByList */ //============================================================================= -Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFacesByList - (Handle(GEOM_Object) theShape, - const Standard_Real theTolerance, - std::list theFaces, - const Standard_Boolean doKeepNonSolids, - const Standard_Boolean doGlueAllEdges) +Handle(GEOM_Object) +GEOMImpl_IShapesOperations::MakeGlueFacesByList(std::list< Handle(GEOM_Object) >& theShapes, + const Standard_Real theTolerance, + std::list & theFaces, + const Standard_Boolean doKeepNonSolids, + const Standard_Boolean doGlueAllEdges) { SetErrorCode(KO); - if (theShape.IsNull()) return NULL; + Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes ); + if ( objects.IsNull() || objects->IsEmpty() ) { + SetErrorCode("NULL argument shape"); + return NULL; + } + Handle(TColStd_HSequenceOfTransient) aFaces = GEOM_Object::GetLastFunctions( theFaces ); + if ( aFaces.IsNull() ) { + SetErrorCode("NULL argument shape for the shape construction"); + return NULL; + } //Add a new Glued object - Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED); + Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GEOM_GLUED); //Add a new Glue function Handle(GEOM_Function) aFunction; @@ -847,40 +1104,23 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFacesByList GEOMImpl_IGlue aCI (aFunction); - Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); - if (aRefShape.IsNull()) return NULL; - - aCI.SetBase(aRefShape); + aCI.SetBase( objects ); aCI.SetTolerance(theTolerance); aCI.SetKeepNonSolids(doKeepNonSolids); aCI.SetGlueAllEdges(doGlueAllEdges); - - Handle(TColStd_HSequenceOfTransient) aFaces = new TColStd_HSequenceOfTransient; - std::list::iterator it = theFaces.begin(); - for (; it != theFaces.end(); it++) { - Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction(); - if (aRefSh.IsNull()) { - SetErrorCode("NULL argument shape for the shape construction"); - return NULL; - } - aFaces->Append(aRefSh); - } aCI.SetFaces(aFaces); //Compute the sub-shape value Standard_Boolean isWarning = Standard_False; try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed to glue faces"); return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); // to provide warning if (!aFunction->GetValue().IsNull()) { isWarning = Standard_True; @@ -893,16 +1133,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFacesByList GEOM::TPythonDump pd(aFunction); pd << aGlued << " = geompy.MakeGlueFacesByList(" - << theShape << ", " << theTolerance << ", ["; - // Faces - it = theFaces.begin(); - if (it != theFaces.end()) { - pd << (*it++); - while (it != theFaces.end()) { - pd << ", " << (*it++); - } - } - pd << "], " << (bool)doKeepNonSolids << ", " << (bool)doGlueAllEdges << ")"; + << theShapes << ", " << theTolerance << ", " << theFaces << ", " + << (bool)doKeepNonSolids << ", " << (bool)doGlueAllEdges << ")"; // to provide warning if (!isWarning) SetErrorCode(OK); @@ -914,16 +1146,20 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFacesByList * MakeGlueEdges */ //============================================================================= -Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueEdges - (Handle(GEOM_Object) theShape, - const Standard_Real theTolerance) +Handle(GEOM_Object) +GEOMImpl_IShapesOperations::MakeGlueEdges (std::list< Handle(GEOM_Object) >& theShapes, + const Standard_Real theTolerance) { SetErrorCode(KO); - if (theShape.IsNull()) return NULL; + Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes ); + if ( objects.IsNull() || objects->IsEmpty() ) { + SetErrorCode("NULL argument shape"); + return NULL; + } //Add a new Glued object - Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED); + Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GEOM_GLUED); //Add a new Glue function Handle(GEOM_Function) aFunction; @@ -935,27 +1171,21 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueEdges GEOMImpl_IGlue aCI (aFunction); - Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); - if (aRefShape.IsNull()) return NULL; - - aCI.SetBase(aRefShape); + aCI.SetBase( objects ); aCI.SetTolerance(theTolerance); aCI.SetKeepNonSolids(true); //Compute the sub-shape value Standard_Boolean isWarning = Standard_False; try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed to glue edges"); return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); // to provide warning if (!aFunction->GetValue().IsNull()) { isWarning = Standard_True; @@ -966,7 +1196,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueEdges //Make a Python command GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueEdges(" - << theShape << ", " << theTolerance << ")"; + << theShapes << ", " << theTolerance << ")"; // to provide warning if (!isWarning) SetErrorCode(OK); @@ -978,16 +1208,36 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueEdges * GetGlueShapes */ //============================================================================= -Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueShapes - (Handle(GEOM_Object) theShape, - const Standard_Real theTolerance, - const TopAbs_ShapeEnum theType) +Handle(TColStd_HSequenceOfTransient) +GEOMImpl_IShapesOperations::GetGlueShapes (std::list< Handle(GEOM_Object) >& theShapes, + const Standard_Real theTolerance, + const TopAbs_ShapeEnum theType) { SetErrorCode(KO); - if (theShape.IsNull()) return NULL; - TopoDS_Shape aShape = theShape->GetValue(); - if (aShape.IsNull()) return NULL; + TopoDS_Shape aShape; + TopTools_SequenceOfShape shapes; + std::list< Handle(GEOM_Object) >::iterator s = theShapes.begin(); + Handle(GEOM_BaseObject) lastCreatedGO; + for ( ; s != theShapes.end(); ++s ) + { + Handle(GEOM_Object) go = *s; + if ( go.IsNull() ) return NULL; + aShape = go->GetValue(); + if ( aShape.IsNull() ) return NULL; + shapes.Append( aShape ); + lastCreatedGO = GEOM::GetCreatedLast( lastCreatedGO, go ); + } + if ( shapes.Length() > 1 ) + { + TopoDS_Compound compound; + BRep_Builder builder; + builder.MakeCompound( compound ); + for ( int i = 1; i <= shapes.Length(); ++i ) + builder.Add( compound, shapes( i ) ); + + aShape = compound; + } Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; @@ -998,9 +1248,7 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueShapes Standard_Integer iErr = aGluer.ErrorStatus(); if (iErr) return NULL; - TCollection_AsciiString anAsciiList, anEntry; - TopTools_IndexedMapOfShape anIndices; - TopExp::MapShapes(aShape, anIndices); + std::vector< TopTools_IndexedMapOfShape* > anIndices( shapes.Length(), NULL ); Handle(TColStd_HArray1OfInteger) anArray; Handle(GEOM_Object) anObj; @@ -1027,31 +1275,40 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueShapes GEOMUtils::SortShapes(listOnePerSet, Standard_False); TopTools_ListIteratorOfListOfShape aListIt (listOnePerSet); - for (; aListIt.More(); aListIt.Next()) { + for (; aListIt.More(); aListIt.Next()) + { TopoDS_Shape aValue = aListIt.Value(); - anArray = new TColStd_HArray1OfInteger(1,1); - anArray->SetValue(1, anIndices.FindIndex(aValue)); - anObj = GetEngine()->AddSubShape(theShape, anArray); - if (!anObj.IsNull()) { - aSeq->Append(anObj); - - // for python command - TDF_Tool::Entry(anObj->GetEntry(), anEntry); - anAsciiList += anEntry; - anAsciiList += ","; + // find a shape to add aValue as a sub-shape + anObj.Nullify(); + s = theShapes.begin(); + for ( int i = 0; i < shapes.Length(); ++i, ++s ) + { + Handle(GEOM_Object) object = *s; + if ( !anIndices[i] ) { + anIndices[i] = new TopTools_IndexedMapOfShape; + TopExp::MapShapes( object->GetValue(), *anIndices[i]); + } + if (int index = anIndices[i]->FindIndex( aValue )) { + anArray = new TColStd_HArray1OfInteger(1,1); + anArray->SetValue(1, index); + anObj = GetEngine()->AddSubShape( object, anArray); + break; + } } + if (!anObj.IsNull()) + aSeq->Append(anObj); } + for ( size_t i = 0 ; i < anIndices.size(); ++i ) + delete anIndices[i]; // Make a Python command - if (anAsciiList.Length() > 0) { - anAsciiList.Trunc(anAsciiList.Length() - 1); - Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); + if ( aSeq->Length() > 0) + { + Handle(GEOM_Function) aFunction = lastCreatedGO->GetLastFunction(); GEOM::TPythonDump pd (aFunction, /*append=*/true); - pd << "[" << anAsciiList.ToCString(); - if (theType == TopAbs_FACE) - pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")"; - else if (theType == TopAbs_EDGE) - pd << "] = geompy.GetGlueEdges(" << theShape << ", " << theTolerance << ")"; + pd << aSeq + << " = geompy." << (theType == TopAbs_FACE ? "GetGlueFaces" : "GetGlueEdges" ) + << "( " << theShapes << ", " << theTolerance << ")"; } SetErrorCode(OK); @@ -1064,17 +1321,25 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueShapes * MakeGlueEdgesByList */ //============================================================================= -Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueEdgesByList - (Handle(GEOM_Object) theShape, - const Standard_Real theTolerance, - std::list theEdges) +Handle(GEOM_Object) +GEOMImpl_IShapesOperations::MakeGlueEdgesByList (std::list< Handle(GEOM_Object) >& theShapes, + const Standard_Real theTolerance, + std::list& theEdges) { SetErrorCode(KO); - if (theShape.IsNull()) return NULL; - + Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theShapes ); + if ( objects.IsNull() || objects->IsEmpty() ) { + SetErrorCode("NULL argument shape"); + return NULL; + } + Handle(TColStd_HSequenceOfTransient) anEdges = GEOM_Object::GetLastFunctions( theEdges ); + if ( anEdges.IsNull() ) { + SetErrorCode("NULL argument shape for the shape construction"); + return NULL; + } //Add a new Glued object - Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED); + Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GEOM_GLUED); //Add a new Glue function Handle(GEOM_Function) aFunction; @@ -1086,39 +1351,22 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueEdgesByList GEOMImpl_IGlue aCI (aFunction); - Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); - if (aRefShape.IsNull()) return NULL; - - aCI.SetBase(aRefShape); + aCI.SetBase( objects ); aCI.SetTolerance(theTolerance); aCI.SetKeepNonSolids(true); - - Handle(TColStd_HSequenceOfTransient) anEdges = new TColStd_HSequenceOfTransient; - std::list::iterator it = theEdges.begin(); - for (; it != theEdges.end(); it++) { - Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction(); - if (aRefSh.IsNull()) { - SetErrorCode("NULL argument shape for the shape construction"); - return NULL; - } - anEdges->Append(aRefSh); - } aCI.SetFaces(anEdges); //Compute the sub-shape value Standard_Boolean isWarning = Standard_False; try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed to glue edges"); return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); // to provide warning if (!aFunction->GetValue().IsNull()) { isWarning = Standard_True; @@ -1131,16 +1379,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueEdgesByList GEOM::TPythonDump pd (aFunction); pd << aGlued << " = geompy.MakeGlueEdgesByList(" - << theShape << ", " << theTolerance << ", ["; - // Edges - it = theEdges.begin(); - if (it != theEdges.end()) { - pd << (*it++); - while (it != theEdges.end()) { - pd << ", " << (*it++); - } - } - pd << "])"; + << theShapes << ", " << theTolerance << ", " << theEdges << " )"; // to provide warning if (!isWarning) SetErrorCode(OK); @@ -1152,9 +1391,38 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueEdgesByList * GetExistingSubObjects */ //============================================================================= -Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetExistingSubObjects - (Handle(GEOM_Object) theShape, - const Standard_Boolean theGroupsOnly) +Handle(TColStd_HSequenceOfTransient) +GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object) theShape, + const Standard_Boolean theGroupsOnly) +{ + // note: this method does not return fields + + Standard_Integer types = theGroupsOnly ? Groups : Groups|SubShapes; + Handle(TColStd_HSequenceOfTransient) results = GetExistingSubObjects(theShape, types); + + Handle(GEOM_BaseObject) lastCreatedGO = GEOM::GetCreatedLast(results); + lastCreatedGO = GEOM::GetCreatedLast(lastCreatedGO, theShape); + + if (results->Length() > 0) { + // Make a Python command + GEOM::TPythonDump pd (lastCreatedGO->GetLastFunction(), /*append=*/true); + pd << "["; + Standard_Integer i, aLen = results->Length(); + for (i = 1; i <= aLen; i++) + { + Handle(GEOM_BaseObject) obj = Handle(GEOM_BaseObject)::DownCast(results->Value(i)); + pd << obj << ((i < aLen) ? ", " : ""); + } + pd << "] = geompy.GetExistingSubObjects("; + pd << theShape << ", " << (bool)theGroupsOnly << ")"; + } + + return results; +} + +Handle(TColStd_HSequenceOfTransient) +GEOMImpl_IShapesOperations::GetExistingSubObjects(Handle(GEOM_Object) theShape, + const Standard_Integer theTypes) { SetErrorCode(KO); @@ -1172,23 +1440,21 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetExistingSubO SetErrorCode(KO); - TCollection_AsciiString anAsciiList; - TDataStd_ListIteratorOfListOfExtendedString anIt (aListEntries); for (; anIt.More(); anIt.Next()) { TCollection_ExtendedString anEntry = anIt.Value(); Standard_Integer aStrLen = anEntry.LengthOfCString(); char* anEntryStr = new char[aStrLen+1]; anEntry.ToUTF8CString(anEntryStr); - Handle(GEOM_Object) anObj = GetEngine()->GetObject(GetDocID(), anEntryStr, false); - if (!anObj.IsNull()) { - if (!theGroupsOnly || anObj->GetType() == GEOM_GROUP) { + Handle(GEOM_BaseObject) anObj = GetEngine()->GetObject(anEntryStr, false); + if (!anObj.IsNull() ) { + bool isGroup = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() == GEOM_GROUP; + bool isSubShape = anObj->IsKind(STANDARD_TYPE(GEOM_Object)) && anObj->GetType() != GEOM_GROUP; + bool isField = anObj->IsKind(STANDARD_TYPE(GEOM_Field)); + if ((theTypes & Groups && isGroup ) || + (theTypes & SubShapes && isSubShape ) || + (theTypes & Fields && isField )) aSeq->Append(anObj); - - // for python command - anAsciiList += anEntryStr; - anAsciiList += ","; - } } delete [] anEntryStr; } @@ -1198,14 +1464,6 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetExistingSubO return aSeq; } - //Make a Python command - anAsciiList.Trunc(anAsciiList.Length() - 1); - - GEOM::TPythonDump pd (aMainShape, /*append=*/true); - pd << "[" << anAsciiList.ToCString(); - pd << "] = geompy.GetExistingSubObjects("; - pd << theShape << ", " << (bool)theGroupsOnly << ")"; - SetErrorCode(OK); return aSeq; @@ -1236,17 +1494,20 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode TopTools_ListOfShape listShape; if (aShape.ShapeType() == TopAbs_COMPOUND && - (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE || - TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID || - TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) + (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND)) { TopoDS_Iterator It (aShape, Standard_True, Standard_True); for (; It.More(); It.Next()) { - if (mapShape.Add(It.Value())) { - if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE || - TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) { - listShape.Append(It.Value()); + TopoDS_Shape SS = It.Value(); + if (mapShape.Add(SS)) { + if (theShapeType == TopAbs_FLAT) { + AddFlatSubShapes(SS, listShape, mapShape); + } + else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) { + listShape.Append(SS); } + // VSR: for EXPLODE_NEW_INCLUDE_MAIN and EXPLODE_OLD_INCLUDE_MAIN: + // it seems it is necessary to add top-level shape if theShapeType == TopAbs_COMPOUND } } } @@ -1258,7 +1519,7 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode listShape.Append(exp.Current()); } - if (listShape.IsEmpty()) { + if (listShape.IsEmpty()){ //SetErrorCode("The given shape has no sub-shapes of the requested type"); SetErrorCode(NOT_FOUND_ANY); // NPAL18017 return aSeq; @@ -1285,7 +1546,7 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode //anObj = GetEngine()->AddSubShape(theShape, anArray); { - anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE); + anObj = GetEngine()->AddObject(GEOM_SUBSHAPE); Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1); if (aFunction.IsNull()) return aSeq; @@ -1302,16 +1563,15 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode // Put this subshape in the list of sub-shapes of theMainShape aMainShape->AddSubShapeReference(aFunction); } - if (!anObj.IsNull()) { - aSeq->Append(anObj); + aSeq->Append(anObj); - // for python command - TDF_Tool::Entry(anObj->GetEntry(), anEntry); - anAsciiList += anEntry; - anAsciiList += ","; - } - } + // for python command + TDF_Tool::Entry(anObj->GetEntry(), anEntry); + anAsciiList += anEntry; + anAsciiList += ","; + } + } //Make a Python command anAsciiList.Trunc(anAsciiList.Length() - 1); @@ -1360,16 +1620,17 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs TopTools_ListOfShape listShape; if (aShape.ShapeType() == TopAbs_COMPOUND && - (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE || - TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID || - TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) + (theShapeType == TopAbs_SHAPE || theShapeType == TopAbs_FLAT || theShapeType == TopAbs_COMPOUND)) { TopoDS_Iterator It (aShape, Standard_True, Standard_True); for (; It.More(); It.Next()) { - if (mapShape.Add(It.Value())) { - if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE || - TopAbs_ShapeEnum(theShapeType) == It.Value().ShapeType()) { - listShape.Append(It.Value()); + TopoDS_Shape SS = It.Value(); + if (mapShape.Add(SS)) { + if (theShapeType == TopAbs_FLAT) { + AddFlatSubShapes(SS, listShape, mapShape); + } + else if (theShapeType == TopAbs_SHAPE || theShapeType == SS.ShapeType()) { + listShape.Append(SS); } } } @@ -1407,6 +1668,8 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); + // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump +#ifdef DUMP_SUBSHAPE_IDS //Make a Python command GEOM::TPythonDump pd (aFunction, /*append=*/true); pd << "listSubShapeIDs = geompy.SubShapeAll"; @@ -1423,6 +1686,7 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs break; default: ; } +#endif // DUMP_SUBSHAPE_IDS SetErrorCode(OK); return aSeq; @@ -1498,7 +1762,7 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeSubShapes anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, id); - anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE); + anObj = GetEngine()->AddObject(GEOM_SUBSHAPE); if (!anObj.IsNull()) { Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1); if (aFunction.IsNull()) return aSeq; @@ -1747,6 +2011,48 @@ TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(G return aTypeName; } +//============================================================================= +/*! + * IsSubShapeBelongsTo + */ +//============================================================================= +Standard_Boolean GEOMImpl_IShapesOperations::IsSubShapeBelongsTo( Handle(GEOM_Object) theSubObject, + const Standard_Integer theSubObjectIndex, + Handle(GEOM_Object) theObject, + const Standard_Integer theObjectIndex) +{ + SetErrorCode(KO); + + if ( theObject.IsNull() || theSubObject.IsNull() ) + return false; + + TopoDS_Shape shape = theObject->GetValue(); + TopoDS_Shape subShape = theSubObject->GetValue(); + + if ( shape.IsNull() || subShape.IsNull() ) + return false; + + TopTools_IndexedMapOfShape anIndices; + if ( theObjectIndex > 0 ) { + TopExp::MapShapes( shape, anIndices ); + shape = anIndices.FindKey(theObjectIndex); + anIndices.Clear(); + } + if ( theSubObjectIndex > 0 ) { + TopExp::MapShapes( subShape, anIndices ); + subShape = anIndices.FindKey(theSubObjectIndex); + anIndices.Clear(); + } + + TopExp::MapShapes( shape, anIndices ); + + const Standard_Boolean isBelongTo = anIndices.Contains(subShape); + + SetErrorCode(OK); + + return isBelongTo; +} + //============================================================================= /*! * NumberOfSubShapes @@ -1788,39 +2094,44 @@ Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes */ try { -#if OCC_VERSION_LARGE > 0x06010000 - OCC_CATCH_SIGNALS; -#endif - int iType, nbTypes [TopAbs_SHAPE]; - for (iType = 0; iType < TopAbs_SHAPE; ++iType) - nbTypes[iType] = 0; - nbTypes[aShape.ShapeType()]++; - - TopTools_MapOfShape aMapOfShape; - aMapOfShape.Add(aShape); - TopTools_ListOfShape aListOfShape; - aListOfShape.Append(aShape); - - TopTools_ListIteratorOfListOfShape itL (aListOfShape); - for (; itL.More(); itL.Next()) { - TopoDS_Iterator it (itL.Value()); - for (; it.More(); it.Next()) { - TopoDS_Shape s = it.Value(); - if (aMapOfShape.Add(s)) { - aListOfShape.Append(s); - nbTypes[s.ShapeType()]++; + if (theShapeType == TopAbs_FLAT) { + TopTools_MapOfShape aMapOfShape; + TopTools_ListOfShape aListOfShape; + AddFlatSubShapes(aShape, aListOfShape, aMapOfShape); + nbShapes = aListOfShape.Extent(); + } + else { + OCC_CATCH_SIGNALS; + int iType, nbTypes [TopAbs_SHAPE]; + for (iType = 0; iType < TopAbs_SHAPE; ++iType) + nbTypes[iType] = 0; + nbTypes[aShape.ShapeType()]++; + + TopTools_MapOfShape aMapOfShape; + aMapOfShape.Add(aShape); + TopTools_ListOfShape aListOfShape; + aListOfShape.Append(aShape); + + TopTools_ListIteratorOfListOfShape itL (aListOfShape); + for (; itL.More(); itL.Next()) { + TopoDS_Iterator it (itL.Value()); + for (; it.More(); it.Next()) { + TopoDS_Shape s = it.Value(); + if (aMapOfShape.Add(s)) { + aListOfShape.Append(s); + nbTypes[s.ShapeType()]++; + } } } + + if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE) + nbShapes = aMapOfShape.Extent(); + else + nbShapes = nbTypes[theShapeType]; } - - if (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE) - nbShapes = aMapOfShape.Extent(); - else - nbShapes = nbTypes[theShapeType]; } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return -1; } @@ -1841,7 +2152,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) /* //Add a new reversed object - Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType()); + Handle(GEOM_Object) aReversed = GetEngine()->AddObject(theShape->GetType()); //Add a new Revese function Handle(GEOM_Function) aFunction; @@ -1860,17 +2171,14 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) //Compute the sub-shape value try { -#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; -#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed to reverse shape"); return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return NULL; } @@ -1889,7 +2197,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) if (aGen) { GEOMImpl_IHealingOperations* anIHealingOperations = - aGen->GetIHealingOperations(GetDocID()); + aGen->GetIHealingOperations(); aReversed = anIHealingOperations->ChangeOrientationCopy(theShape); SetErrorCode(anIHealingOperations->GetErrorCode()); } @@ -1938,9 +2246,12 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs //The explode doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); + // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump +#ifdef DUMP_SUBSHAPE_IDS //Make a Python command GEOM::TPythonDump(aFunction, /*append=*/true) << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")"; +#endif // DUMP_SUBSHAPE_IDS SetErrorCode(OK); return aSeq; @@ -1993,7 +2304,7 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes } if (aSeq->IsEmpty()) { - SetErrorCode("The given shapes have no shared sub-shapes of the requested type"); + SetErrorCode(NOT_FOUND_ANY); return aSeq; } @@ -2013,118 +2324,168 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes //======================================================================= //function : GetSharedShapes //purpose : +// +// NOTE on the implementation +// +// 1) Resulting sub-shapes are published as a children of the 1st input shape +// from theShapes list. Due to this reason only direct sub-shapes of the 1st +// shape can be contained in the result of the operation (i.e. shares between +// 2nd/3rd, etc couples cannot be retrieved. +// 2) An exception from above case is when a single compound is specified as an +// input. In this case we search shares between its top-level content, so we +// are able to search shares between all possible couples of shapes. +// 3) Parameter theMultiShare controls what types of shares to search: +// - True: get sub-shapes that are shared between ALL input shapes; +// - False: get shares between couples of input sub-shapes (see points 1 and 2). +// +// Thus, we have the following cases: +// [1] theShapes = N shapes (N>1), theMultiShare = True +// Result: sub-shapes that are shared by all theShapes +// [2] theShapes = N shapes (N>1), theMultiShare = False +// Result: sub-shapes of 1st shape from theShapes that are shared with any shape +// from theShapes +// [3] theShapes = 1 shape, theMultiShare = True +// Result: sub-shapes that are shared by all top-level sub-objects of theShapes[0] +// [4] theShapes = 1 shape, theMultiShare = False +// Result: sub-shapes of all possible couples of all top-level sub-objects of +// theShapes[0]. //======================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes - (std::list theShapes, - const Standard_Integer theShapeType) + (std::list & theShapes, + const Standard_Integer theShapeType, + const bool theMultiShare) { SetErrorCode(KO); int aLen = theShapes.size(); if (aLen < 1) return NULL; - int ind = 1; std::list::iterator it = theShapes.begin(); - Handle(GEOM_Object) aMainObj = (*it++); + // main object is always first in the input list + // it is the object from which sub-shapes indices are taken + // and where results are published + Handle(GEOM_Object) aMainObj = *it; Handle(GEOM_Function) aMainShape = aMainObj->GetLastFunction(); - if (aMainShape.IsNull()) { - SetErrorCode("NULL shape for GetSharedShapes"); - return NULL; - } - - TopoDS_Shape aShape1 = aMainShape->GetValue(); - if (aShape1.IsNull()) return NULL; - - TopTools_IndexedMapOfShape anIndices; - TopExp::MapShapes(aShape1, anIndices); - - TopTools_IndexedMapOfShape mapSelected; - TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapSelected); - // Find shared shapes - BRep_Builder B; - TopoDS_Compound aCurrSelection; - - for (; it != theShapes.end(); it++, ind++) { + // collect all shapes from the input list (including first one) for processing + TopTools_SequenceOfShape shapeSeq; + for (; it != theShapes.end(); it++) { Handle(GEOM_Function) aRefShape = (*it)->GetLastFunction(); if (aRefShape.IsNull()) { SetErrorCode("NULL shape for GetSharedShapes"); return NULL; } + TopoDS_Shape aShape = aRefShape->GetValue(); + if (aShape.IsNull()) { + SetErrorCode("NULL shape for GetSharedShapes"); + return NULL; + } + shapeSeq.Append( aShape ); + } - TopoDS_Compound aCompound; - B.MakeCompound(aCompound); + // if only single shape is specified as input + // collect all ites top-level sub-shapes for processing + if ( shapeSeq.Length() == 1 ) + { + TopoDS_Shape aShape = shapeSeq.First(); + shapeSeq.Clear(); + for ( TopoDS_Iterator it( aShape ); it.More(); it.Next() ) + shapeSeq.Append( it.Value() ); + } - TopoDS_Shape aShape2 = aRefShape->GetValue(); - if (aShape2.IsNull()) return NULL; + // map all sub-shapes in a main shape to their indices + TopTools_IndexedMapOfShape anIndices; + TopExp::MapShapes(aMainShape->GetValue(), anIndices); + TopTools_MapOfShape mapShape; - TopTools_MapOfShape mapShape2; - TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType)); - for (; exp.More(); exp.Next()) { - TopoDS_Shape aSS = exp.Current(); - if (mapShape2.Add(aSS) && mapSelected.Contains(aSS)) { - B.Add(aCompound, aSS); + // find shared shapes + + // here we will collect all shares + TopTools_ListOfShape aShared; + + // number of iterations + int nbIters = theMultiShare || theShapes.size() > 1 ? 1 : shapeSeq.Length()-1; + // numShares factor to search (i.e. by what nb of shapes each found sub-shape should be shared) + int nbShares = theMultiShare ? shapeSeq.Length()-1 : 1; + + for ( int iter = 1; iter <= nbIters; iter++) { + for ( int ind = iter+1; ind <= shapeSeq.Length(); ind++) { + if ( ind-1+nbShares > shapeSeq.Length() ) break; + TopoDS_Compound aCurrSelection; + TopoDS_Shape aShape1 = shapeSeq.Value( iter ); + TopTools_IndexedMapOfShape mapSelected; + TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapSelected); + for ( int s = 0; s < nbShares; s++ ) { + BRep_Builder B; + TopoDS_Compound aCompound; + B.MakeCompound(aCompound); + const TopoDS_Shape& aShape2 = shapeSeq.Value( ind+s ); + TopTools_MapOfShape mapShape2; + TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType)); + for (; exp.More(); exp.Next()) { + const TopoDS_Shape& aSS = exp.Current(); + if (mapShape2.Add(aSS) && mapSelected.Contains(aSS)) { + B.Add(aCompound, aSS); + } + } + mapSelected.Clear(); + aCurrSelection = aCompound; + TopExp::MapShapes(aCurrSelection, TopAbs_ShapeEnum(theShapeType), mapSelected); + } + TopoDS_Iterator itSel(aCurrSelection, Standard_True, Standard_True); + for (; itSel.More(); itSel.Next()) { + const TopoDS_Shape& aSS = itSel.Value(); + if (mapShape.Add(aSS) ) + aShared.Append(aSS); } } - - mapSelected.Clear(); - TopExp::MapShapes(aCompound, TopAbs_ShapeEnum(theShapeType), mapSelected); - aCurrSelection = aCompound; } - // Create GEOM_Object for each found shared shape (collected in aCurrSelection) - Handle(GEOM_Object) anObj; - Handle(TColStd_HArray1OfInteger) anArray; Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; - TCollection_AsciiString anAsciiList, anEntry; - TopoDS_Iterator itSel (aCurrSelection, Standard_True, Standard_True); - for (; itSel.More(); itSel.Next()) { - anArray = new TColStd_HArray1OfInteger(1,1); - anArray->SetValue(1, anIndices.FindIndex(itSel.Value())); + if (aShared.IsEmpty()){ + SetErrorCode(NOT_FOUND_ANY); + return aSeq; + } + + // create GEOM_Object for each found shared shape (collected in aShared) + TCollection_AsciiString anAsciiList; + Handle(GEOM_Object) anObj; + TopTools_ListIteratorOfListOfShape itSub (aShared); + for (; itSub.More(); itSub.Next()) { + TopoDS_Shape aValue = itSub.Value(); + Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); + anArray->SetValue(1, anIndices.FindIndex(aValue)); anObj = GetEngine()->AddSubShape(aMainObj, anArray); aSeq->Append(anObj); // for python command + TCollection_AsciiString anEntry; TDF_Tool::Entry(anObj->GetEntry(), anEntry); anAsciiList += anEntry; anAsciiList += ","; } - if (aSeq->IsEmpty()) { - SetErrorCode("The given shapes have no shared sub-shapes of the requested type"); - return aSeq; - } - - // Make a Python command + // make a Python command anAsciiList.Trunc(anAsciiList.Length() - 1); - // IPAL22904: TC6.5.0: order of python commands is wrong after dump study - Handle(TColStd_HSequenceOfTransient) anObjects = new TColStd_HSequenceOfTransient; - for( it = theShapes.begin(); it != theShapes.end(); it++ ) - { - Handle(GEOM_Object) anObj = *it; - if( !anObj.IsNull() ) - anObjects->Append( anObj ); - } - - // Get the function of the latest published object - Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast( anObjects )->GetLastFunction(); - if( aFunction.IsNull() ) // just in case - aFunction = aMainShape; - - GEOM::TPythonDump pd (aFunction, /*append=*/true); + GEOM::TPythonDump pd (anObj->GetLastFunction()); pd << "[" << anAsciiList.ToCString() - << "] = geompy.GetSharedShapesMulti(["; + << "] = geompy.GetSharedShapesMulti("; + + if ( aLen > 1 ) + pd << "["; it = theShapes.begin(); pd << (*it++); while (it != theShapes.end()) { pd << ", " << (*it++); } + if ( aLen > 1 ) + pd << "]"; - pd << "], " << TopAbs_ShapeEnum(theShapeType) << ")"; + pd << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theMultiShare << ")"; SetErrorCode(OK); return aSeq; @@ -2266,7 +2627,7 @@ Handle(TColStd_HSequenceOfInteger) TopoDS_Shape aShape = theShape->GetValue(); // Check presence of triangulation, build if need - if (!GEOMUtils::CheckTriangulation(aShape)) { + if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) { SetErrorCode("Cannot build triangulation on the shape"); return aSeqOfIDs; } @@ -2285,9 +2646,9 @@ Handle(TColStd_HSequenceOfInteger) aFinder.SetState(theState); aFinder.Perform(); - // Interprete results + // Interpret results Standard_Integer iErr = aFinder.ErrorStatus(); - // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx + // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx if (iErr) { MESSAGE(" iErr : " << iErr); TCollection_AsciiString aMsg (" iErr : "); @@ -2296,7 +2657,7 @@ Handle(TColStd_HSequenceOfInteger) return aSeqOfIDs; } Standard_Integer iWrn = aFinder.WarningStatus(); - // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx + // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx if (iWrn) { MESSAGE(" *** iWrn : " << iWrn); } @@ -2350,6 +2711,8 @@ Handle(TColStd_HSequenceOfInteger) // The GetShapesOnBox() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction(); + // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump +#ifdef DUMP_SUBSHAPE_IDS // Make a Python command GEOM::TPythonDump(aFunction, /*append=*/true) << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs(" @@ -2357,6 +2720,7 @@ Handle(TColStd_HSequenceOfInteger) << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theState << ")"; +#endif // DUMP_SUBSHAPE_IDS SetErrorCode(OK); return aSeqOfIDs; @@ -2433,14 +2797,36 @@ Handle(TColStd_HSequenceOfInteger) TopTools_ListOfShape res; // Check presence of triangulation, build if need - if (!GEOMUtils::CheckTriangulation(aShape)) { + if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) { SetErrorCode("Cannot build triangulation on the shape"); return aSeqOfIDs; } + // Compute classification tolerance. + TopTools_IndexedMapOfShape aMapVtx; + Standard_Real aTol = Precision::Confusion(); + + TopExp::MapShapes(aShape, TopAbs_VERTEX, aMapVtx); + + Standard_Integer i; + Standard_Integer aNbVtx = aMapVtx.Extent(); + + for (i = 1; i <= aNbVtx; ++i) { + const TopoDS_Vertex aVtx = TopoDS::Vertex(aMapVtx.FindKey(i)); + const Standard_Real aVtxTol = BRep_Tool::Tolerance(aVtx); + + if (aTol < aVtxTol) { + aTol = aVtxTol; + } + } + + // Bound the tolerance value. + if (aTol > 0.0001) { + aTol = 0.0001; + } + // Call algo GEOMAlgo_FinderShapeOn2 aFinder; - Standard_Real aTol = 0.0001; // default value Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid; aClsfSolid->SetShape(aCheckShape); @@ -2452,9 +2838,9 @@ Handle(TColStd_HSequenceOfInteger) aFinder.SetState(theState); aFinder.Perform(); - // Interprete results + // Interpret results Standard_Integer iErr = aFinder.ErrorStatus(); - // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx + // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx if (iErr) { if (iErr == 41) { SetErrorCode("theCheckShape must be a solid"); @@ -2468,7 +2854,7 @@ Handle(TColStd_HSequenceOfInteger) return aSeqOfIDs; } Standard_Integer iWrn = aFinder.WarningStatus(); - // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx + // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx if (iWrn) { MESSAGE(" *** iWrn : " << iWrn); } @@ -2523,13 +2909,16 @@ Handle(TColStd_HSequenceOfInteger) Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction(); + // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump +#ifdef DUMP_SUBSHAPE_IDS // Make a Python command GEOM::TPythonDump(aFunction, /*append=*/true) - << "listShapesOnBoxIDs = geompy.GetShapesOnShapeIDs(" + << "listShapesOnShapeIDs = geompy.GetShapesOnShapeIDs(" << theCheckShape << ", " << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theState << ")"; +#endif // DUMP_SUBSHAPE_IDS SetErrorCode(OK); return aSeqOfIDs; @@ -2616,11 +3005,20 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound } //Add a new result object - Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), GEOM_SHAPES_ON_SHAPE); + Handle(GEOM_Object) aRes = GetEngine()->AddObject(GEOM_SHAPES_ON_SHAPE); Handle(GEOM_Function) aFunction = aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE); aFunction->SetValue(aCompound); + aSeq->Clear(); + aSeq->Append( theCheckShape->GetLastFunction() ); + aSeq->Append( theShape->GetLastFunction() ); + + GEOMImpl_IShapes aCI( aFunction ); + aCI.SetShapes( aSeq ); + aCI.SetSubShapeType( theShapeType ); + aCI.SetTolerance( theState ); + GEOM::TPythonDump(aFunction) << aRes << " = geompy.GetShapesOnShapeAsCompound(" << theCheckShape << ", " @@ -2633,78 +3031,315 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound return aRes; } -//======================================================================= -//function : getShapesOnSurfaceIDs - /*! - * \brief Find IDs of sub-shapes complying with given status about surface - * \param theSurface - the surface to check state of sub-shapes against - * \param theShape - the shape to explore - * \param theShapeType - type of sub-shape of theShape - * \param theState - required state - * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes - */ -//======================================================================= -Handle(TColStd_HSequenceOfInteger) - GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface, - const TopoDS_Shape& theShape, - TopAbs_ShapeEnum theShapeType, - GEOMAlgo_State theState) +//============================================================================= +/*! + * GetSubShapeEdgeSorted + */ +//============================================================================= +Handle(TColStd_HSequenceOfTransient) + GEOMImpl_IShapesOperations::GetSubShapeEdgeSorted + (const Handle(GEOM_Object) &theShape, + const Handle(GEOM_Object) &theStartPoint) { - Handle(TColStd_HSequenceOfInteger) aSeqOfIDs; + // Get the sorted edges indices. + Handle(TColStd_HSequenceOfInteger) aSortedIDs = + getSubShapeEdgeSortedIDs(theShape, theStartPoint); - // Check presence of triangulation, build if need - if (!GEOMUtils::CheckTriangulation(theShape)) { - SetErrorCode("Cannot build triangulation on the shape"); - return aSeqOfIDs; - } + // Get object by indices. + TCollection_AsciiString anAsciiList; + Handle(TColStd_HSequenceOfTransient) aSeq = + getObjectsShapesOn(theShape, aSortedIDs, anAsciiList); - // BEGIN: Mantis issue 0020961: Error on a pipe T-Shape - // Compute tolerance - Standard_Real T, VertMax = -RealLast(); - try { -#if OCC_VERSION_LARGE > 0x06010000 - OCC_CATCH_SIGNALS; -#endif - for (TopExp_Explorer ExV (theShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) { - TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current()); - T = BRep_Tool::Tolerance(Vertex); - if (T > VertMax) - VertMax = T; - } - } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); - return aSeqOfIDs; + if (aSeq.IsNull() || aSeq->IsEmpty()) { + SetErrorCode("Empty sequence of edges"); + return NULL; } - // END: Mantis issue 0020961 - - // Call algo - GEOMAlgo_FinderShapeOn1 aFinder; - //Standard_Real aTol = 0.0001; // default value - Standard_Real aTol = VertMax; // Mantis issue 0020961 - aFinder.SetShape(theShape); - aFinder.SetTolerance(aTol); - aFinder.SetSurface(theSurface); - aFinder.SetShapeType(theShapeType); - aFinder.SetState(theState); + // Make a Python command + Handle(GEOM_Object) anObj = + Handle(GEOM_Object)::DownCast(aSeq->Value(1)); + Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); - // Sets the minimal number of inner points for the faces that do not have own - // inner points at all (for e.g. rectangular planar faces have just 2 triangles). - // Default value=3 - aFinder.SetNbPntsMin(3); - // Sets the maximal number of inner points for edges or faces. - // It is usefull for the cases when this number is very big (e.g =2000) to improve - // the performance. If this value =0, all inner points will be taken into account. - // Default value=0 - aFinder.SetNbPntsMax(100); + GEOM::TPythonDump(aFunction) + << "[" << anAsciiList.ToCString() << "] = geompy.GetSubShapeEdgeSorted(" + << theShape << ", " << theStartPoint << ")"; - aFinder.Perform(); + SetErrorCode(OK); - // Interprete results + return aSeq; +} + +//============================================================================= +/*! + * GetSubShapesWithTolerance + */ +//============================================================================= +Handle(TColStd_HSequenceOfTransient) + GEOMImpl_IShapesOperations::GetSubShapesWithTolerance + (const Handle(GEOM_Object) &theShape, + const Standard_Integer theShapeType, + const GEOMUtils::ComparisonCondition theCondition, + const Standard_Real theTolerance) +{ + if (theShape.IsNull()) { + SetErrorCode("NULL GEOM object"); + return NULL; + } + + TopoDS_Shape aShape = theShape->GetValue(); + + if (aShape.IsNull()) { + SetErrorCode("NULL Shape"); + return NULL; + } + + if (theShapeType != TopAbs_FACE && theShapeType != TopAbs_EDGE && + theShapeType != TopAbs_VERTEX && aShape.ShapeType() >= theShapeType) { + SetErrorCode("Invalid shape type"); + return NULL; + } + + TopTools_IndexedMapOfShape anIndices; + TopTools_MapOfShape aMapFence; + TopExp_Explorer anExp(aShape, + (TopAbs_ShapeEnum) theShapeType); + Handle(TColStd_HSequenceOfInteger) anIDs = new TColStd_HSequenceOfInteger; + + TopExp::MapShapes(aShape, anIndices); + + for (; anExp.More(); anExp.Next()) { + const TopoDS_Shape &aSubShape = anExp.Current(); + + if (aMapFence.Add(aSubShape)) { + // Compute tolerance + Standard_Real aTolerance = -1.; + + switch (aSubShape.ShapeType()) { + case TopAbs_FACE: + aTolerance = BRep_Tool::Tolerance(TopoDS::Face(aSubShape)); + break; + case TopAbs_EDGE: + aTolerance = BRep_Tool::Tolerance(TopoDS::Edge(aSubShape)); + break; + case TopAbs_VERTEX: + aTolerance = BRep_Tool::Tolerance(TopoDS::Vertex(aSubShape)); + break; + default: + break; + } + + if (aTolerance < 0.) { + continue; + } + + // Compare the tolerance with reference value. + if (GEOMUtils::IsFitCondition (theCondition, aTolerance, theTolerance)) { + anIDs->Append(anIndices.FindIndex(aSubShape)); + } + } + } + + if (anIDs->IsEmpty()) { + SetErrorCode("Empty sequence of sub-shapes"); + return NULL; + } + + // Get objects by indices. + TCollection_AsciiString anAsciiList; + Handle(TColStd_HSequenceOfTransient) aSeq = + getObjectsShapesOn(theShape, anIDs, anAsciiList); + + if (aSeq.IsNull() || aSeq->IsEmpty()) { + SetErrorCode("Empty sequence of edges"); + return NULL; + } + + // Make a Python command + Handle(GEOM_Object) anObj = + Handle(GEOM_Object)::DownCast(aSeq->Value(1)); + Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); + + GEOM::TPythonDump(aFunction) + << "[" << anAsciiList.ToCString() << "] = geompy.GetSubShapesWithTolerance(" + << theShape << ", " << theShapeType << ", " << theCondition << ", " + << theTolerance << ")"; + + SetErrorCode(OK); + + return aSeq; +} + +//============================================================================= +/*! + * MakeExtraction + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeExtraction + (const Handle(GEOM_Object) &theShape, + const Handle(TColStd_HArray1OfInteger) &theSubShapeIDs, + std::list &theStats) +{ + SetErrorCode(KO); + + if (theShape.IsNull()) { + return NULL; + } + + //Add a new Result object + Handle(GEOM_Object) aResult = + GetEngine()->AddObject(GEOM_EXTRACTION); + + //Add a new Extraction function + Handle(GEOM_Function) aFunction = + aResult->AddFunction(GEOMImpl_ShapeDriver::GetID(), EXTRACTION); + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) { + return NULL; + } + + Handle(GEOM_Function) aShape = theShape->GetLastFunction(); + + if (aShape.IsNull()) { + return NULL; + } + + GEOMImpl_IExtract aCI (aFunction); + + aCI.SetShape(aShape); + aCI.SetSubShapeIDs(theSubShapeIDs); + + //Compute the Edge value + try { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Shape driver failed"); + + return NULL; + } + } + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); + + return NULL; + } + + // Fill in statistics. + theStats.clear(); + + Handle(TColStd_HArray1OfInteger) aStatIDsArray[3] = + { aCI.GetRemovedIDs(), aCI.GetModifiedIDs(), aCI.GetAddedIDs() }; + int i; + int j; + + for (j = 0; j < 3; ++j) { + if (!aStatIDsArray[j].IsNull()) { + const int anUpperID = aStatIDsArray[j]->Upper(); + ExtractionStat aStat; + + for (i = aStatIDsArray[j]->Lower(); i <= anUpperID; ++i) { + aStat.indices.push_back(aStatIDsArray[j]->Value(i)); + } + + aStat.type = (ExtractionStatType) j; + theStats.push_back(aStat); + } + } + + //Make a Python command + GEOM::TPythonDump pd(aFunction); + + pd << aResult << " = geompy.MakeExtraction(" << theShape << ", ["; + + if (!theSubShapeIDs.IsNull()) { + const int aNbIDs = theSubShapeIDs->Upper(); + + for (i = theSubShapeIDs->Lower(); i < aNbIDs; ++i) { + pd << theSubShapeIDs->Value(i) << ", "; + } + + // Dump the last value without a comma. + pd << theSubShapeIDs->Value(i); + } + + pd << "])"; + + SetErrorCode(OK); + + return aResult; +} + +//======================================================================= +//function : getShapesOnSurfaceIDs + /*! + * \brief Find IDs of sub-shapes complying with given status about surface + * \param theSurface - the surface to check state of sub-shapes against + * \param theShape - the shape to explore + * \param theShapeType - type of sub-shape of theShape + * \param theState - required state + * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes + */ +//======================================================================= +Handle(TColStd_HSequenceOfInteger) + GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface, + const TopoDS_Shape& theShape, + TopAbs_ShapeEnum theShapeType, + GEOMAlgo_State theState) +{ + Handle(TColStd_HSequenceOfInteger) aSeqOfIDs; + + // Check presence of triangulation, build if need + if (theShapeType != TopAbs_VERTEX && + !GEOMUtils::CheckTriangulation(theShape)) { + SetErrorCode("Cannot build triangulation on the shape"); + return aSeqOfIDs; + } + + // BEGIN: Mantis issue 0020961: Error on a pipe T-Shape + // Compute tolerance + Standard_Real T, VertMax = -RealLast(); + try { + OCC_CATCH_SIGNALS; + for (TopExp_Explorer ExV (theShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) { + TopoDS_Vertex Vertex = TopoDS::Vertex(ExV.Current()); + T = BRep_Tool::Tolerance(Vertex); + if (T > VertMax) + VertMax = T; + } + } + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); + return aSeqOfIDs; + } + // END: Mantis issue 0020961 + + // Call algo + GEOMAlgo_FinderShapeOn2 aFinder; + Handle(GEOMAlgo_ClsfSurf) aClsfSurf = new GEOMAlgo_ClsfSurf; + Standard_Real aTol = VertMax; // Mantis issue 0020961 + + aClsfSurf->SetSurface(theSurface); + aFinder.SetShape(theShape); + aFinder.SetTolerance(aTol); + aFinder.SetClsf(aClsfSurf); + aFinder.SetShapeType(theShapeType); + aFinder.SetState(theState); + + // Sets the minimal number of inner points for the faces that do not have own + // inner points at all (for e.g. rectangular planar faces have just 2 triangles). + // Default value=3 + aFinder.SetNbPntsMin(3); + // Sets the maximal number of inner points for edges or faces. + // It is useful for the cases when this number is very big (e.g =2000) to improve + // the performance. If this value =0, all inner points will be taken into account. + // Default value=0 + aFinder.SetNbPntsMax(100); + + aFinder.Perform(); + + // Interpret results Standard_Integer iErr = aFinder.ErrorStatus(); - // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx + // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx if (iErr) { MESSAGE(" iErr : " << iErr); TCollection_AsciiString aMsg (" iErr : "); @@ -2713,7 +3348,7 @@ Handle(TColStd_HSequenceOfInteger) return aSeqOfIDs; } Standard_Integer iWrn = aFinder.WarningStatus(); - // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx + // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx if (iWrn) { MESSAGE(" *** iWrn : " << iWrn); } @@ -2776,6 +3411,152 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations:: return aSeq; } +//============================================================================= +/*! + * getSubShapeEdgeSortedIDs + */ +//============================================================================= +Handle(TColStd_HSequenceOfInteger) + GEOMImpl_IShapesOperations::getSubShapeEdgeSortedIDs + (const Handle(GEOM_Object) &theShape, + const Handle(GEOM_Object) &theStartPoint) +{ + Handle(TColStd_HSequenceOfInteger) aResult; + + if (theShape.IsNull() || theStartPoint.IsNull()) { + SetErrorCode("NULL GEOM object"); + return aResult; + } + + const TopoDS_Shape aShape = theShape->GetValue(); + const TopoDS_Shape aStartPoint = theStartPoint->GetValue(); + + if (aShape.IsNull() || aStartPoint.IsNull()) { + SetErrorCode("NULL Shape"); + return aResult; + } + + if (aStartPoint.ShapeType() != TopAbs_VERTEX) { + SetErrorCode("Starting point is not a vertex"); + return aResult; + } + + TopExp_Explorer anExp(aShape, TopAbs_EDGE); + TopTools_MapOfShape aMapFence; + TopTools_ListOfShape anEdges; + + for (; anExp.More(); anExp.Next()) { + const TopoDS_Shape &anEdge = anExp.Current(); + + if (aMapFence.Add(anEdge)) { + anEdges.Append(anEdge); + } + } + + if (anEdges.IsEmpty()) { + SetErrorCode("Shape doesn't contain edges"); + return aResult; + } + + // Step 1: Sort edges + GEOMUtils::SortShapes(anEdges, Standard_False); + + TopTools_ListIteratorOfListOfShape anIter(anEdges); + TopoDS_Vertex aV[2]; + TopTools_DataMapOfShapeListOfShape aMapVE; + + // Step 2: Fill the map vertex - list of edges. + for (; anIter.More(); anIter.Next()) { + TopoDS_Edge anEdge = TopoDS::Edge(anIter.Value()); + + TopExp::Vertices(anEdge, aV[0], aV[1]); + + const Standard_Integer aNbV = aV[0].IsSame(aV[1]) ? 1 : 2; + Standard_Integer i; + + for (i = 0; i < aNbV; ++i) { + if (aV[i].IsNull() == Standard_False) { + if (!aMapVE.IsBound(aV[i])) { + // There is no this vertex in the map. + aMapVE.Bind(aV[i], TopTools_ListOfShape()); + } + + // Add the edge to the list bound with the vertex aV[i]. + TopTools_ListOfShape &aLEdges = aMapVE.ChangeFind(aV[i]); + + aLEdges.Append(anEdge); + } + } + } + + // Step 3: Find starting point in aMapVE. + TopoDS_Vertex aStartVtx = TopoDS::Vertex(aStartPoint); + + if (!aMapVE.IsBound(aStartVtx)) { + aStartVtx = getSameVertex(aShape, aStartVtx); + + if (aStartVtx.IsNull()) { + SetErrorCode("Invalid Starting point"); + return aResult; + } + } + + TopTools_IndexedMapOfShape anIndices; + TopTools_MapOfShape aMapVFence; + TopoDS_Shape aCurVtx = aStartVtx; + TopoDS_Edge aCurEdge = + TopoDS::Edge(aMapVE.Find(aCurVtx).First()); + + aResult = new TColStd_HSequenceOfInteger; + TopExp::MapShapes(aShape, anIndices); + + // Step 4: Fill the list of sorted edges. + while (aMapVFence.Add(aCurVtx)) { + // Append the ID of the current edge to the list of sorted. + aResult->Append(anIndices.FindIndex(aCurEdge)); + TopExp::Vertices(aCurEdge, aV[0], aV[1]); + + // Get the next vertex. + if (aCurVtx.IsSame(aV[0])) { + if (aCurVtx.IsSame(aV[1])) { + // There is no next vertex. + break; + } else { + aCurVtx = aV[1]; + } + } else { + aCurVtx = aV[0]; + } + + if (aCurVtx.IsNull()) { + // There is no next vertex. + break; + } + + // Get the next edge. + const TopTools_ListOfShape &aLEdges = aMapVE.Find(aCurVtx); + TopTools_ListIteratorOfListOfShape anEIter(aLEdges); + + for (; anEIter.More(); anEIter.Next()) { + const TopoDS_Shape &aLocalEdge = anEIter.Value(); + + if (aLocalEdge.IsNull() == Standard_False) { + if (!aCurEdge.IsSame(aLocalEdge)) { + aCurEdge = TopoDS::Edge(aLocalEdge); + break; + } + } + } + + if (!anEIter.More()) { + // There is no next edge. + break; + } + } + + return aResult; +} + //======================================================================= //function : getShapesOnSurface /*! @@ -3137,10 +3918,13 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneI // The GetShapesOnPlaneIDs() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction(); + // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump +#ifdef DUMP_SUBSHAPE_IDS // Make a Python command GEOM::TPythonDump(aFunction, /*append=*/true) << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs" << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")"; +#endif // DUMP_SUBSHAPE_IDS SetErrorCode(OK); return aSeq; @@ -3204,10 +3988,13 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneW // The GetShapesOnPlaneIDs() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction(); + // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump +#ifdef DUMP_SUBSHAPE_IDS // Make a Python command GEOM::TPythonDump(aFunction, /*append=*/true) << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs" << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", " << theState << ")"; +#endif // DUMP_SUBSHAPE_IDS SetErrorCode(OK); return aSeq; @@ -3250,11 +4037,14 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylind // The GetShapesOnCylinder() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction(); + // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump +#ifdef DUMP_SUBSHAPE_IDS // Make a Python command GEOM::TPythonDump(aFunction, /*append=*/true) << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs" << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", " << theRadius << ", " << theState << ")"; +#endif // DUMP_SUBSHAPE_IDS SetErrorCode(OK); return aSeq; @@ -3318,11 +4108,14 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylind Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape, GEOM::GetCreatedLast(thePnt,theAxis))->GetLastFunction(); + // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump +#ifdef DUMP_SUBSHAPE_IDS // Make a Python command GEOM::TPythonDump(aFunction, /*append=*/true) << "listShapesOnCylinder = geompy.GetShapesOnCylinderWithLocationIDs" << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", " << thePnt << ", " << theRadius << ", " << theState << ")"; +#endif // DUMP_SUBSHAPE_IDS SetErrorCode(OK); return aSeq; @@ -3368,11 +4161,14 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphere // The GetShapesOnSphere() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction(); + // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump +#ifdef DUMP_SUBSHAPE_IDS // Make a Python command GEOM::TPythonDump(aFunction, /*append=*/true) - << "listShapesOnCylinder = geompy.GetShapesOnSphereIDs" + << "listShapesOnSphere = geompy.GetShapesOnSphereIDs" << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", " << theRadius << ", " << theState << ")"; +#endif // DUMP_SUBSHAPE_IDS SetErrorCode(OK); return aSeq; @@ -3385,9 +4181,9 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphere * \param theShape - the shape to explore * \param theShapeType - type of sub-shape of theShape * \param theTopLeftPoint - top left quadrangle corner - * \param theTopRigthPoint - top right quadrangle corner + * \param theTopRightPoint - top right quadrangle corner * \param theBottomLeftPoint - bottom left quadrangle corner - * \param theBottomRigthPoint - bottom right quadrangle corner + * \param theBottomRightPoint - bottom right quadrangle corner * \param theState - required state * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes */ @@ -3396,25 +4192,25 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, const Handle(GEOM_Object)& theTopLeftPoint, - const Handle(GEOM_Object)& theTopRigthPoint, + const Handle(GEOM_Object)& theTopRightPoint, const Handle(GEOM_Object)& theBottomLeftPoint, - const Handle(GEOM_Object)& theBottomRigthPoint, + const Handle(GEOM_Object)& theBottomRightPoint, const GEOMAlgo_State theState) { SetErrorCode(KO); if ( theShape.IsNull() || theTopLeftPoint.IsNull() || - theTopRigthPoint.IsNull() || + theTopRightPoint.IsNull() || theBottomLeftPoint.IsNull() || - theBottomRigthPoint.IsNull() ) + theBottomRightPoint.IsNull() ) return NULL; TopoDS_Shape aShape = theShape->GetValue(); TopoDS_Shape aTL = theTopLeftPoint->GetValue(); - TopoDS_Shape aTR = theTopRigthPoint->GetValue(); + TopoDS_Shape aTR = theTopRightPoint->GetValue(); TopoDS_Shape aBL = theBottomLeftPoint->GetValue(); - TopoDS_Shape aBR = theBottomRigthPoint->GetValue(); + TopoDS_Shape aBR = theBottomRightPoint->GetValue(); if (aShape.IsNull() || aTL.IsNull() || @@ -3434,7 +4230,7 @@ Handle(TColStd_HSequenceOfInteger) Handle(TColStd_HSequenceOfInteger) aSeqOfIDs; // Check presence of triangulation, build if need - if (!GEOMUtils::CheckTriangulation(aShape)) { + if (theShapeType != TopAbs_VERTEX && !GEOMUtils::CheckTriangulation(aShape)) { SetErrorCode("Cannot build triangulation on the shape"); return aSeqOfIDs; } @@ -3445,12 +4241,15 @@ Handle(TColStd_HSequenceOfInteger) gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL)); gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR)); - GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR ); + GEOMAlgo_FinderShapeOn2 aFinder; + Handle(GEOMAlgo_ClsfQuad) aClsfQuad = new GEOMAlgo_ClsfQuad; + Standard_Real aTol = 0.0001; // default value + aClsfQuad->SetCorners(aPntTL, aPntTR, aPntBL, aPntBR); aFinder.SetShape(aShape); aFinder.SetTolerance(aTol); - //aFinder.SetSurface(theSurface); + aFinder.SetClsf(aClsfQuad); aFinder.SetShapeType(aShapeType); aFinder.SetState(theState); @@ -3459,16 +4258,16 @@ Handle(TColStd_HSequenceOfInteger) // Default value=3 aFinder.SetNbPntsMin(3); // Sets the maximal number of inner points for edges or faces. - // It is usefull for the cases when this number is very big (e.g =2000) to improve + // It is useful for the cases when this number is very big (e.g =2000) to improve // the performance. If this value =0, all inner points will be taken into account. // Default value=0 aFinder.SetNbPntsMax(100); aFinder.Perform(); - // Interprete results + // Interpret results Standard_Integer iErr = aFinder.ErrorStatus(); - // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx + // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx if (iErr) { MESSAGE(" iErr : " << iErr); TCollection_AsciiString aMsg (" iErr : "); @@ -3477,7 +4276,7 @@ Handle(TColStd_HSequenceOfInteger) return aSeqOfIDs; } Standard_Integer iWrn = aFinder.WarningStatus(); - // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx + // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx if (iWrn) { MESSAGE(" *** iWrn : " << iWrn); } @@ -3511,9 +4310,9 @@ Handle(TColStd_HSequenceOfInteger) * \param theShape - the shape to explore * \param theShapeType - type of sub-shape of theShape * \param theTopLeftPoint - top left quadrangle corner - * \param theTopRigthPoint - top right quadrangle corner + * \param theTopRightPoint - top right quadrangle corner * \param theBottomLeftPoint - bottom left quadrangle corner - * \param theBottomRigthPoint - bottom right quadrangle corner + * \param theBottomRightPoint - bottom right quadrangle corner * \param theState - required state * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes */ @@ -3522,9 +4321,9 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, const Handle(GEOM_Object)& theTopLeftPoint, - const Handle(GEOM_Object)& theTopRigthPoint, + const Handle(GEOM_Object)& theTopRightPoint, const Handle(GEOM_Object)& theBottomLeftPoint, - const Handle(GEOM_Object)& theBottomRigthPoint, + const Handle(GEOM_Object)& theBottomRightPoint, const GEOMAlgo_State theState) { // Find indices @@ -3532,9 +4331,9 @@ Handle(TColStd_HSequenceOfTransient) getShapesOnQuadrangleIDs( theShape, theShapeType, theTopLeftPoint, - theTopRigthPoint, + theTopRightPoint, theBottomLeftPoint, - theBottomRigthPoint, + theBottomRightPoint, theState); if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() ) return NULL; @@ -3556,9 +4355,9 @@ Handle(TColStd_HSequenceOfTransient) << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theTopLeftPoint << ", " - << theTopRigthPoint << ", " + << theTopRightPoint << ", " << theBottomLeftPoint << ", " - << theBottomRigthPoint << ", " + << theBottomRightPoint << ", " << theState << ")"; SetErrorCode(OK); @@ -3572,9 +4371,9 @@ Handle(TColStd_HSequenceOfTransient) * \param theShape - the shape to explore * \param theShapeType - type of sub-shape of theShape * \param theTopLeftPoint - top left quadrangle corner - * \param theTopRigthPoint - top right quadrangle corner + * \param theTopRightPoint - top right quadrangle corner * \param theBottomLeftPoint - bottom left quadrangle corner - * \param theBottomRigthPoint - bottom right quadrangle corner + * \param theBottomRightPoint - bottom right quadrangle corner * \param theState - required state * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found sub-shapes */ @@ -3583,9 +4382,9 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape, const Standard_Integer theShapeType, const Handle(GEOM_Object)& theTopLeftPoint, - const Handle(GEOM_Object)& theTopRigthPoint, + const Handle(GEOM_Object)& theTopRightPoint, const Handle(GEOM_Object)& theBottomLeftPoint, - const Handle(GEOM_Object)& theBottomRigthPoint, + const Handle(GEOM_Object)& theBottomRightPoint, const GEOMAlgo_State theState) { // Find indices @@ -3593,9 +4392,9 @@ Handle(TColStd_HSequenceOfInteger) getShapesOnQuadrangleIDs( theShape, theShapeType, theTopLeftPoint, - theTopRigthPoint, + theTopRightPoint, theBottomLeftPoint, - theBottomRigthPoint, + theBottomRightPoint, theState); if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() ) return NULL; @@ -3603,21 +4402,24 @@ Handle(TColStd_HSequenceOfInteger) // Make a Python command // The GetShapesOnCylinder() doesn't change object so no new function is required. - Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint); - lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint); - lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint); + Handle(GEOM_BaseObject) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint); + lastObj = GEOM::GetCreatedLast(lastObj,theTopRightPoint); + lastObj = GEOM::GetCreatedLast(lastObj,theBottomRightPoint); lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint); Handle(GEOM_Function) aFunction = lastObj->GetLastFunction(); + // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump +#ifdef DUMP_SUBSHAPE_IDS GEOM::TPythonDump(aFunction, /*append=*/true) << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs(" << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theTopLeftPoint << ", " - << theTopRigthPoint << ", " + << theTopRightPoint << ", " << theBottomLeftPoint << ", " - << theBottomRigthPoint << ", " + << theBottomRightPoint << ", " << theState << ")"; +#endif // DUMP_SUBSHAPE_IDS SetErrorCode(OK); return aSeqOfIDs; @@ -3625,331 +4427,64 @@ Handle(TColStd_HSequenceOfInteger) //============================================================================= /*! - * GetInPlaceOfShape + * case GetInPlace: + * default: */ //============================================================================= -static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction, - const TopTools_IndexedMapOfShape& theWhereIndices, - const TopoDS_Shape& theWhat, - TColStd_ListOfInteger& theModifiedList) +Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere, + Handle(GEOM_Object) theShapeWhat) { - if (theWhereFunction.IsNull() || theWhat.IsNull()) return false; - - if (theWhereIndices.Contains(theWhat)) { - // entity was not changed by the operation - Standard_Integer aWhatIndex = theWhereIndices.FindIndex(theWhat); - theModifiedList.Append(aWhatIndex); - return true; - } + SetErrorCode(KO); - // try to find in history - TDF_Label aHistoryLabel = theWhereFunction->GetHistoryEntry(Standard_False); + if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL; - // search in history for all argument shapes - Standard_Boolean isFound = Standard_False; - Standard_Boolean isGood = Standard_False; + TopoDS_Shape aWhere = theShapeWhere->GetValue(); + TopoDS_Shape aWhat = theShapeWhat->GetValue(); - TDF_LabelSequence aLabelSeq; - theWhereFunction->GetDependency(aLabelSeq); - Standard_Integer nbArg = aLabelSeq.Length(); + if (aWhere.IsNull() || aWhat.IsNull()) { + SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null."); + return NULL; + } - for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) { + // Searching for the sub-shapes inside the ShapeWhere shape + GEOMAlgo_GetInPlace aGIP; - TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg); - - Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel); - TopoDS_Shape anArgumentShape = anArgumentObject->GetValue(); - - TopTools_IndexedMapOfShape anArgumentIndices; - TopExp::MapShapes(anArgumentShape, anArgumentIndices); - - if (anArgumentIndices.Contains(theWhat)) { - isFound = Standard_True; - Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat); - - // Find corresponding label in history - TDF_Label anArgumentHistoryLabel = - theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False); - if (anArgumentHistoryLabel.IsNull()) { - // Lost History of operation argument. Possibly, all its entities was removed. - isGood = Standard_True; - } - else { - TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False); - - if (aWhatHistoryLabel.IsNull()) { - // Removed entity ? Compound ? Compsolid ? Shell ? Wire - isGood = Standard_False; - } else { - Handle(TDataStd_IntegerArray) anIntegerArray; - if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) { - //Error: Empty modifications history for the sought shape. - isGood = Standard_False; - } - else { - isGood = Standard_True; - Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length(); - for (imod = 1; imod <= aModifLen; imod++) { - theModifiedList.Append(anIntegerArray->Array()->Value(imod)); - } - } - } - } - } - } - - isFound = isGood; - - if (!isFound) { - // try compound/compsolid/shell/wire element by element - bool isFoundAny = false; - TopTools_MapOfShape mapShape; - - if (theWhat.ShapeType() == TopAbs_COMPOUND || - theWhat.ShapeType() == TopAbs_COMPSOLID) { - // recursive processing of compound/compsolid - TopoDS_Iterator anIt (theWhat, Standard_True, Standard_True); - for (; anIt.More(); anIt.Next()) { - if (mapShape.Add(anIt.Value())) { - TopoDS_Shape curWhat = anIt.Value(); - isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList); - if (isFoundAny) isFound = Standard_True; - } - } - } - else if (theWhat.ShapeType() == TopAbs_SHELL) { - // try to replace a shell by its faces images - TopExp_Explorer anExp (theWhat, TopAbs_FACE); - for (; anExp.More(); anExp.Next()) { - if (mapShape.Add(anExp.Current())) { - TopoDS_Shape curWhat = anExp.Current(); - isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList); - if (isFoundAny) isFound = Standard_True; - } - } - } - else if (theWhat.ShapeType() == TopAbs_WIRE) { - // try to replace a wire by its edges images - TopExp_Explorer anExp (theWhat, TopAbs_EDGE); - for (; anExp.More(); anExp.Next()) { - if (mapShape.Add(anExp.Current())) { - TopoDS_Shape curWhat = anExp.Current(); - isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList); - if (isFoundAny) isFound = Standard_True; - } - } - } - else { - // Removed entity - } - } - - return isFound; -} - -//============================================================================= -/*! - * GetShapeProperties - */ -//============================================================================= -void GEOMImpl_IShapesOperations::GetShapeProperties( const TopoDS_Shape aShape, Standard_Real tab[], - gp_Pnt & aVertex ) -{ - GProp_GProps theProps; - gp_Pnt aCenterMass; - //TopoDS_Shape aPntShape; - Standard_Real aShapeSize; - - if (aShape.ShapeType() == TopAbs_VERTEX) aCenterMass = BRep_Tool::Pnt( TopoDS::Vertex( aShape ) ); - else if (aShape.ShapeType() == TopAbs_EDGE) BRepGProp::LinearProperties(aShape, theProps); - else if (aShape.ShapeType() == TopAbs_FACE) BRepGProp::SurfaceProperties(aShape, theProps); - else BRepGProp::VolumeProperties(aShape, theProps); - - if (aShape.ShapeType() == TopAbs_VERTEX) - aShapeSize = 1; - else { - aCenterMass = theProps.CentreOfMass(); - aShapeSize = theProps.Mass(); - } - -// aPntShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape(); -// aVertex = BRep_Tool::Pnt( TopoDS::Vertex( aPntShape ) ); - aVertex = aCenterMass; - tab[0] = aVertex.X(); - tab[1] = aVertex.Y(); - tab[2] = aVertex.Z(); - tab[3] = aShapeSize; - return; -} - -namespace { - - //================================================================================ - /*! - * \brief Return normal to face at extrema point - */ - //================================================================================ - - gp_Vec GetNormal (const TopoDS_Face& face, const BRepExtrema_DistShapeShape& extrema) - { - gp_Vec defaultNorm(1,0,0); // to have same normals on different faces - try { - // get UV at extrema point - Standard_Real u,v, f,l; - switch ( extrema.SupportTypeShape2(1) ) { - case BRepExtrema_IsInFace: { - extrema.ParOnFaceS2(1, u, v ); - break; - } - case BRepExtrema_IsOnEdge: { - TopoDS_Edge edge = TopoDS::Edge( extrema.SupportOnShape2(1)); - Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( edge, face, f,l ); - extrema.ParOnEdgeS2( 1, u ); - gp_Pnt2d uv = pcurve->Value( u ); - u = uv.Coord(1); - v = uv.Coord(2); - break; - } - case BRepExtrema_IsVertex: return defaultNorm; - } - // get derivatives - BRepAdaptor_Surface surface( face, false ); - gp_Vec du, dv; gp_Pnt p; - surface.D1( u, v, p, du, dv ); - - return du ^ dv; - - } catch (Standard_Failure ) { - } - return defaultNorm; - } -} - -//============================================================================= -/*! - * case GetInPlace: - * default: - */ -//============================================================================= -Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere, - Handle(GEOM_Object) theShapeWhat) -{ - SetErrorCode(KO); - - if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL; - - TopoDS_Shape aWhere = theShapeWhere->GetValue(); - TopoDS_Shape aWhat = theShapeWhat->GetValue(); - TopoDS_Shape aPntShape; - TopoDS_Vertex aVertex; - - if (aWhere.IsNull() || aWhat.IsNull()) { - SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null."); + if (!GEOMAlgo_GetInPlaceAPI::GetInPlace(aWhere, aWhat, aGIP)) { + SetErrorCode("Error in GEOMAlgo_GetInPlace"); return NULL; } - Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction(); - if (aWhereFunction.IsNull()) { - SetErrorCode("Error: aWhereFunction is Null."); - return NULL; - } + // Add direct result. + TopTools_ListOfShape aLSA; + const TopoDS_Shape &aShapeResult = aGIP.Result(); + TopTools_MapOfShape aMFence; + TopTools_IndexedMapOfShape aWhereIndices; + Standard_Integer aShapeType = -1; - TopTools_IndexedMapOfShape aWhereIndices; TopExp::MapShapes(aWhere, aWhereIndices); - TopAbs_ShapeEnum iType = TopAbs_SOLID; - Standard_Real dl_l = 1e-3; - Standard_Real min_l, Tol_0D, Tol_1D, Tol_2D, Tol_3D, Tol_Mass; - Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; - Bnd_Box BoundingBox; - gp_Pnt aPnt, aPnt_aWhat, tab_Pnt[2]; - GProp_GProps aProps; - - // Find the iType of the aWhat shape - iType = GEOMUtils::GetTypeOfSimplePart(aWhat); - if (iType == TopAbs_SHAPE) { - SetErrorCode("Error: An attempt to extract a shape of not supported type."); - return NULL; - } + if (aShapeResult.IsNull() == Standard_False) { + TopoDS_Iterator anIt(aShapeResult); - TopExp_Explorer Exp_aWhat ( aWhat, iType ); - TopExp_Explorer Exp_aWhere ( aWhere, iType ); - TopExp_Explorer Exp_Edge ( aWhere, TopAbs_EDGE ); - - // Find the shortest edge in theShapeWhere shape - BRepBndLib::Add(aWhere, BoundingBox); - BoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); - min_l = fabs(aXmax - aXmin); - if( min_l < fabs(aYmax - aYmin) ) min_l = fabs(aYmax - aYmin); - if( min_l < fabs(aZmax - aZmin) ) min_l = fabs(aZmax - aZmin); - min_l /= dl_l; - // Mantis issue 0020908 BEGIN - if (!Exp_Edge.More()) { - min_l = Precision::Confusion(); - } - // Mantis issue 0020908 END - for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) { - TopExp_Explorer Exp_Vertex( Exp_Edge.Current(), TopAbs_VERTEX); - for ( Standard_Integer nbVertex = 0; Exp_Vertex.More(); Exp_Vertex.Next(), nbVertex++ ) { - aPnt = BRep_Tool::Pnt( TopoDS::Vertex( Exp_Vertex.Current() ) ); - tab_Pnt[nbVertex] = aPnt; - } - if ( ! tab_Pnt[0].IsEqual(tab_Pnt[1], dl_l) ) { - BRepGProp::LinearProperties(Exp_Edge.Current(), aProps); - if ( aProps.Mass() < min_l ) min_l = aProps.Mass(); - } - } - - // Compute tolerances - Tol_0D = dl_l; - Tol_1D = dl_l * min_l; - Tol_2D = dl_l * ( min_l * min_l) * ( 2. + dl_l); - Tol_3D = dl_l * ( min_l * min_l * min_l ) * ( 3. + (3 * dl_l) + (dl_l * dl_l) ); - - if (Tol_0D < Precision::Confusion()) Tol_0D = Precision::Confusion(); - if (Tol_1D < Precision::Confusion()) Tol_1D = Precision::Confusion(); - if (Tol_2D < Precision::Confusion()) Tol_2D = Precision::Confusion(); - if (Tol_3D < Precision::Confusion()) Tol_3D = Precision::Confusion(); + for (; anIt.More(); anIt.Next()) { + const TopoDS_Shape &aPart = anIt.Value(); - Tol_Mass = Tol_3D; - if ( iType == TopAbs_VERTEX ) Tol_Mass = Tol_0D; - else if ( iType == TopAbs_EDGE ) Tol_Mass = Tol_1D; - else if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D; - - // Searching for the sub-shapes inside the ShapeWhere shape - GEOMAlgo_GetInPlace aGIP; - aGIP.SetTolerance(Tol_1D); - aGIP.SetTolMass(Tol_Mass); - aGIP.SetTolCG(Tol_1D); + if(aWhereIndices.Contains(aPart) && aMFence.Add(aPart)) { + const TopAbs_ShapeEnum aType = aPart.ShapeType(); - aGIP.SetArgument(aWhat); - aGIP.SetShapeWhere(aWhere); - - aGIP.Perform(); - int iErr = aGIP.ErrorStatus(); - if (iErr) { - SetErrorCode("Error in GEOMAlgo_GetInPlace"); - return NULL; - } - - // aGIP.IsFound() returns true only when the whole theShapeWhat - // is found (as one shape or several parts). But we are also interested - // in the partial result, that is why this check is commented. - //if (!aGIP.IsFound()) { - // SetErrorCode(NOT_FOUND_ANY); - // return NULL; - //} + if (aShapeType == -1) { + // Initialization. + aShapeType = aType; + } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) { + // Different types. + aShapeType = TopAbs_SHAPE; + } - const TopTools_DataMapOfShapeListOfShape& aDMSLS = aGIP.Images(); - if (!aDMSLS.IsBound(aWhat)) { - SetErrorCode(NOT_FOUND_ANY); - return NULL; + aLSA.Append(aPart); + } + } } - // the list of shapes aLSA contains the shapes - // of the Shape For Search that corresponds - // to the Argument aWhat - const TopTools_ListOfShape& aLSA = aDMSLS.Find(aWhat); if (aLSA.Extent() == 0) { SetErrorCode(NOT_FOUND_ANY); // Not found any Results return NULL; @@ -3958,13 +4493,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) Handle(TColStd_HArray1OfInteger) aModifiedArray = new TColStd_HArray1OfInteger (1, aLSA.Extent()); TopTools_ListIteratorOfListOfShape anIterModif (aLSA); for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) { - if (aWhereIndices.Contains(anIterModif.Value())) { - aModifiedArray->SetValue(imod, aWhereIndices.FindIndex(anIterModif.Value())); - } - else { - SetErrorCode("Error: wrong sub-shape returned"); - return NULL; - } + aModifiedArray->SetValue(imod, aWhereIndices.FindIndex(anIterModif.Value())); } //Add a new object @@ -3974,7 +4503,10 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) return NULL; } - if (aModifiedArray->Length() > 1 || theShapeWhat->GetType() == GEOM_GROUP) { + const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE); + + if ((aModifiedArray->Length() > 1 && isSameType) || + theShapeWhat->GetType() == GEOM_GROUP) { //Set a GROUP type aResult->SetType(GEOM_GROUP); @@ -4002,207 +4534,78 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) * default: */ //============================================================================= -Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceOld (Handle(GEOM_Object) theShapeWhere, - Handle(GEOM_Object) theShapeWhat) +Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceOld + (Handle(GEOM_Object) theShapeWhere, + Handle(GEOM_Object) theShapeWhat) { SetErrorCode(KO); if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL; - TopoDS_Shape aWhere = theShapeWhere->GetValue(); - TopoDS_Shape aWhat = theShapeWhat->GetValue(); - TopoDS_Shape aPntShape; - TopoDS_Vertex aVertex; + TopoDS_Shape aWhere = theShapeWhere->GetValue(); + TopoDS_Shape aWhat = theShapeWhat->GetValue(); + TopTools_ListOfShape aModifiedList; + const Standard_Integer iErr = + GEOMAlgo_GetInPlaceAPI::GetInPlaceOld(aWhere, aWhat, aModifiedList); - if (aWhere.IsNull() || aWhat.IsNull()) { - SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null."); - return NULL; - } + if (iErr) { + switch (iErr) { + case 1: + SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null."); + break; + case 2: + SetErrorCode + ("Error: An attempt to extract a shape of not supported type."); + break; + case 3: + SetErrorCode(NOT_FOUND_ANY); + break; + default: + SetErrorCode("Shape driver failed"); + break; + } - Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction(); - if (aWhereFunction.IsNull()) { - SetErrorCode("Error: aWhereFunction is Null."); return NULL; } TopTools_IndexedMapOfShape aWhereIndices; TopExp::MapShapes(aWhere, aWhereIndices); - TColStd_ListOfInteger aModifiedList; - Standard_Integer aWhereIndex; - Handle(TColStd_HArray1OfInteger) aModifiedArray; - Handle(GEOM_Object) aResult; - - bool isFound = false; - TopAbs_ShapeEnum iType = TopAbs_SOLID; - //Standard_Real aWhat_Mass = 0., aWhere_Mass = 0.; - Standard_Real tab_aWhat[4], tab_aWhere[4]; - Standard_Real dl_l = 1e-3; - Standard_Real min_l, Tol_0D, Tol_1D, Tol_2D, Tol_3D, Tol_Mass; - Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; - Bnd_Box BoundingBox; - gp_Pnt aPnt, aPnt_aWhat, tab_Pnt[2]; - GProp_GProps aProps; - - // Find the iType of the aWhat shape - /* - if ( aWhat.ShapeType() == TopAbs_VERTEX ) iType = TopAbs_VERTEX; - else if ( aWhat.ShapeType() == TopAbs_EDGE || aWhat.ShapeType() == TopAbs_WIRE ) iType = TopAbs_EDGE; - else if ( aWhat.ShapeType() == TopAbs_FACE || aWhat.ShapeType() == TopAbs_SHELL ) iType = TopAbs_FACE; - else if ( aWhat.ShapeType() == TopAbs_SOLID || aWhat.ShapeType() == TopAbs_COMPSOLID ) iType = TopAbs_SOLID; - else if ( aWhat.ShapeType() == TopAbs_COMPOUND ) { - // Only the iType of the first shape in the compound is taken into account - TopoDS_Iterator It (aWhat, Standard_False, Standard_False); - if ( !It.More() ) { - SetErrorCode("Error: theShapeWhat is an empty COMPOUND."); - return NULL; - } - TopAbs_ShapeEnum compType = It.Value().ShapeType(); - if ( compType == TopAbs_VERTEX ) iType = TopAbs_VERTEX; - else if ( compType == TopAbs_EDGE || compType == TopAbs_WIRE ) iType = TopAbs_EDGE; - else if ( compType == TopAbs_FACE || compType == TopAbs_SHELL) iType = TopAbs_FACE; - else if ( compType == TopAbs_SOLID || compType == TopAbs_COMPSOLID) iType = TopAbs_SOLID; - } - else { - SetErrorCode("Error: An attempt to extract a shape of not supported type."); - return NULL; - } - */ - iType = GEOMUtils::GetTypeOfSimplePart(aWhat); - if (iType == TopAbs_SHAPE) { - SetErrorCode("Error: An attempt to extract a shape of not supported type."); - return NULL; - } - - TopExp_Explorer Exp_aWhat ( aWhat, iType ); - TopExp_Explorer Exp_aWhere ( aWhere, iType ); - TopExp_Explorer Exp_Edge ( aWhere, TopAbs_EDGE ); - - // Find the shortest edge in theShapeWhere shape - BRepBndLib::Add(aWhere, BoundingBox); - BoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); - min_l = fabs(aXmax - aXmin); - if( min_l < fabs(aYmax - aYmin) ) min_l = fabs(aYmax - aYmin); - if( min_l < fabs(aZmax - aZmin) ) min_l = fabs(aZmax - aZmin); - min_l /= dl_l; - // Mantis issue 0020908 BEGIN - if (!Exp_Edge.More()) { - min_l = Precision::Confusion(); - } - // Mantis issue 0020908 END - for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) { - TopExp_Explorer Exp_Vertex( Exp_Edge.Current(), TopAbs_VERTEX); - for ( Standard_Integer nbVertex = 0; Exp_Vertex.More(); Exp_Vertex.Next(), nbVertex++ ) { - aPnt = BRep_Tool::Pnt( TopoDS::Vertex( Exp_Vertex.Current() ) ); - tab_Pnt[nbVertex] = aPnt; - } - if ( ! tab_Pnt[0].IsEqual(tab_Pnt[1], dl_l) ) { - BRepGProp::LinearProperties(Exp_Edge.Current(), aProps); - if ( aProps.Mass() < min_l ) min_l = aProps.Mass(); - } - } - - // Compute tolerances - Tol_0D = dl_l; - Tol_1D = dl_l * min_l; - Tol_2D = dl_l * ( min_l * min_l) * ( 2. + dl_l); - Tol_3D = dl_l * ( min_l * min_l * min_l ) * ( 3. + (3 * dl_l) + (dl_l * dl_l) ); - - if (Tol_0D < Precision::Confusion()) Tol_0D = Precision::Confusion(); - if (Tol_1D < Precision::Confusion()) Tol_1D = Precision::Confusion(); - if (Tol_2D < Precision::Confusion()) Tol_2D = Precision::Confusion(); - if (Tol_3D < Precision::Confusion()) Tol_3D = Precision::Confusion(); - - //if (Tol_1D > 1.0) Tol_1D = 1.0; - //if (Tol_2D > 1.0) Tol_2D = 1.0; - //if (Tol_3D > 1.0) Tol_3D = 1.0; - - Tol_Mass = Tol_3D; - if ( iType == TopAbs_VERTEX ) Tol_Mass = Tol_0D; - else if ( iType == TopAbs_EDGE ) Tol_Mass = Tol_1D; - else if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D; - - // Compute the ShapeWhat Mass - /* - for ( ; Exp_aWhat.More(); Exp_aWhat.Next() ) { - if ( iType == TopAbs_VERTEX ) { - aWhat_Mass += 1; - continue; - } - else if ( iType == TopAbs_EDGE ) BRepGProp::LinearProperties(Exp_aWhat.Current(), aProps); - else if ( iType == TopAbs_FACE ) BRepGProp::SurfaceProperties(Exp_aWhat.Current(), aProps); - else BRepGProp::VolumeProperties(Exp_aWhat.Current(), aProps); - aWhat_Mass += aProps.Mass(); - } - */ - - // Searching for the sub-shapes inside the ShapeWhere shape - TopTools_MapOfShape map_aWhere; - for ( Exp_aWhere.ReInit(); Exp_aWhere.More(); Exp_aWhere.Next() ) { - if (!map_aWhere.Add(Exp_aWhere.Current())) - continue; // skip repeated shape to avoid mass addition - GetShapeProperties( Exp_aWhere.Current(), tab_aWhere, aPnt ); - for ( Exp_aWhat.ReInit(); Exp_aWhat.More(); Exp_aWhat.Next() ) { - GetShapeProperties( Exp_aWhat.Current(), tab_aWhat, aPnt_aWhat ); - if ( fabs(tab_aWhat[3] - tab_aWhere[3]) <= Tol_Mass && aPnt_aWhat.Distance(aPnt) <= Tol_1D ) - isFound = true; - else { - if ( (tab_aWhat[3] - tab_aWhere[3]) > Tol_Mass ) { - aPntShape = BRepBuilderAPI_MakeVertex( aPnt ).Shape(); - aVertex = TopoDS::Vertex( aPntShape ); - BRepExtrema_DistShapeShape aWhereDistance ( aVertex, Exp_aWhere.Current() ); - BRepExtrema_DistShapeShape aWhatDistance ( aVertex, Exp_aWhat.Current() ); - if ( aWhereDistance.IsDone() && aWhatDistance.IsDone() && - fabs(aWhereDistance.Value() - aWhatDistance.Value()) <= Tol_1D ) - { - // 0020162: "EDF 961 GEOM : Getinplace is getting additionnal orthogonal faces" - // aVertex must be projected to the same point on Where and on What - gp_Pnt pOnWhat = aWhatDistance.PointOnShape2(1); - gp_Pnt pOnWhere = aWhereDistance.PointOnShape2(1); - isFound = ( pOnWhat.Distance(pOnWhere) <= Tol_1D ); - if ( isFound && iType == TopAbs_FACE ) - { - // check normals at pOnWhat and pOnWhere - const double angleTol = M_PI/180.; - gp_Vec normToWhat = GetNormal( TopoDS::Face(Exp_aWhat.Current()), aWhatDistance); - gp_Vec normToWhere = GetNormal( TopoDS::Face(Exp_aWhere.Current()), aWhereDistance); - if ( normToWhat * normToWhere < 0 ) - normToWhat.Reverse(); - isFound = ( normToWhat.Angle( normToWhere ) < angleTol ); - } - } - } - } - if ( isFound ) { - aWhereIndex = aWhereIndices.FindIndex(Exp_aWhere.Current()); - aModifiedList.Append(aWhereIndex); - //aWhere_Mass += tab_aWhere[3]; - isFound = false; - break; - } + Handle(TColStd_HArray1OfInteger) aModifiedArray = + new TColStd_HArray1OfInteger (1, aModifiedList.Extent()); + TopTools_ListIteratorOfListOfShape anIterModif (aModifiedList); + Standard_Integer imod; + Standard_Integer aShapeType = -1; + + for (imod = 1; anIterModif.More(); anIterModif.Next(), imod++) { + const Standard_Integer anIndex = + aWhereIndices.FindIndex(anIterModif.Value()); + const TopAbs_ShapeEnum aType = anIterModif.Value().ShapeType(); + + if (aShapeType == -1) { + // Initialization. + aShapeType = aType; + } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) { + // Different types. + aShapeType = TopAbs_SHAPE; } - //if ( fabs( aWhat_Mass - aWhere_Mass ) <= Tol_Mass ) - //break; - } - if (aModifiedList.Extent() == 0) { // Not found any Results - SetErrorCode(NOT_FOUND_ANY); - return NULL; + aModifiedArray->SetValue(imod, anIndex); } - aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent()); - TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList); - for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) - aModifiedArray->SetValue(imod, anIterModif.Value()); - //Add a new object - aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray); + Handle(GEOM_Object) aResult = + GetEngine()->AddSubShape(theShapeWhere, aModifiedArray); + if (aResult.IsNull()) { SetErrorCode("Error in algorithm: result found, but cannot be returned."); return NULL; } - if (aModifiedArray->Length() > 1 || theShapeWhat->GetType() == GEOM_GROUP) { + const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE); + + if ((aModifiedArray->Length() > 1 && isSameType) || + theShapeWhat->GetType() == GEOM_GROUP) { //Set a GROUP type aResult->SetType(GEOM_GROUP); @@ -4221,6 +4624,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceOld (Handle(GEOM_Objec << theShapeWhere << ", " << theShapeWhat << ", False)"; SetErrorCode(OK); + return aResult; } @@ -4246,22 +4650,39 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory //Fill array of indices TopTools_IndexedMapOfShape aWhereIndices; + TopExp::MapShapes(aWhere, aWhereIndices); // process shape - TColStd_ListOfInteger aModifiedList; - bool isFound = GetInPlaceOfShape(aWhereFunction, aWhereIndices, aWhat, aModifiedList); + TopTools_ListOfShape aModifiedList; + bool isFound = GEOMAlgo_GetInPlaceAPI::GetInPlaceByHistory + (aWhereFunction, aWhereIndices, aWhat, aModifiedList); if (!isFound || aModifiedList.Extent() < 1) { SetErrorCode("Error: No history found for the sought shape or its sub-shapes."); return NULL; } - Handle(TColStd_HArray1OfInteger) aModifiedArray = + Handle(TColStd_HArray1OfInteger) aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent()); - TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList); - for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) { - aModifiedArray->SetValue(imod, anIterModif.Value()); + TopTools_ListIteratorOfListOfShape anIterModif (aModifiedList); + Standard_Integer imod; + Standard_Integer aShapeType = -1; + + for (imod = 1; anIterModif.More(); anIterModif.Next(), imod++) { + const Standard_Integer anIndex = + aWhereIndices.FindIndex(anIterModif.Value()); + const TopAbs_ShapeEnum aType = anIterModif.Value().ShapeType(); + + if (aShapeType == -1) { + // Initialization. + aShapeType = aType; + } else if (aShapeType != TopAbs_SHAPE && aShapeType != aType) { + // Different types. + aShapeType = TopAbs_SHAPE; + } + + aModifiedArray->SetValue(imod, anIndex); } //Add a new object @@ -4271,7 +4692,10 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory return NULL; } - if (aModifiedArray->Length() > 1) { + const Standard_Boolean isSameType = (aShapeType != TopAbs_SHAPE); + + if ((aModifiedArray->Length() > 1 && isSameType) || + theShapeWhat->GetType() == GEOM_GROUP) { //Set a GROUP type aResult->SetType(GEOM_GROUP); @@ -4287,13 +4711,47 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory Handle(GEOM_Function) aFunction = aResult->GetFunction(1); GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory(" - << theShapeWhere << ", " << theShapeWhat << ")"; + << theShapeWhere << ", " << theShapeWhat << ")"; SetErrorCode(OK); return aResult; } -#define MAX_TOLERANCE 1.e-7 +//======================================================================= +//function : GetInPlaceMap +//purpose : +//======================================================================= +void GEOMImpl_IShapesOperations::GetInPlaceMap (Handle(GEOM_Object) theShapeWhere, + Handle(GEOM_Object) theShapeWhat, + std::vector< std::vector< int > > & theResVec) +{ + SetErrorCode(KO); + + if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return; + + TopoDS_Shape aWhere = theShapeWhere->GetValue(); + TopoDS_Shape aWhat = theShapeWhat->GetValue(); + + if (aWhere.IsNull() || aWhat.IsNull()) return; + + Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction(); + if (aWhereFunction.IsNull()) return; + + bool isFound = GEOMAlgo_GetInPlaceAPI::GetInPlaceMap( aWhereFunction, aWhat, theResVec ); + + if ( isFound ) + SetErrorCode(OK); + + Handle(GEOM_Function) aFunction = + GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction(); + + GEOM::TPythonDump(aFunction, /*append=*/true) + << "resultList = geompy.GetInPlaceMap( " + << theShapeWhere << ", " + << theShapeWhat << ")"; + + return; +} //======================================================================= //function : isSameEdge @@ -4329,7 +4787,6 @@ static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2) double U11, U12, U21, U22; Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12); Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22); - if(C1->DynamicType() == C2->DynamicType()) return true; //Check that both edges has the same geometry double range = U12-U11; @@ -4338,6 +4795,12 @@ static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2) U = U11+range*2.0/3.0; gp_Pnt P2 = C1->Value(U); //Compute a point on two thirds of the edge's length + C2 = new Geom_TrimmedCurve(C2, U21, U22); + // vsr 04/10/2018: 0023312 - As curve may be periodic, its parameters may be normalized + // so, we re-take them from trimmed curve + U21 = C2->FirstParameter(); + U22 = C2->LastParameter(); + if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) || U < U21 || U > U22) return false; @@ -4351,7 +4814,6 @@ static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2) return true; } -#include //======================================================================= //function : isSameFace //purpose : Returns True if two faces coincide @@ -4546,17 +5008,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object switch (aWhat.ShapeType()) { case TopAbs_VERTEX: { - gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat)); - TopExp_Explorer E(aWhere, TopAbs_VERTEX); - for(; E.More(); E.Next()) { - if(!aMap.Add(E.Current())) continue; - gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current())); - if(P.Distance(P2) <= MAX_TOLERANCE) { - isFound = true; - aSubShape = E.Current(); - break; - } - } + aSubShape = getSameVertex(aWhere, TopoDS::Vertex(aWhat)); + isFound = !aSubShape.IsNull(); break; } case TopAbs_EDGE: { @@ -4719,14 +5172,210 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetSameIDs // The GetSameIDs() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction(); + // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump +#ifdef DUMP_SUBSHAPE_IDS // Make a Python command GEOM::TPythonDump(aFunction, /*append=*/true) << "listSameIDs = geompy.GetSameIDs(" << theShapeWhere << ", " << theShapeWhat << ")"; +#endif // DUMP_SUBSHAPE_IDS return aSeq; } else { SetErrorCode(NOT_FOUND_ANY); return NULL; } } + +//======================================================================= +//function : ExtendEdge +//purpose : +//======================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendEdge + (const Handle(GEOM_Object) &theEdge, + const Standard_Real theMin, + const Standard_Real theMax) +{ + SetErrorCode(KO); + + if (theEdge.IsNull()) { + return NULL; + } + + //Add a new Edge object + Handle(GEOM_Object) aResEdge = GetEngine()->AddObject(GEOM_EDGE); + + //Add a new Vector function + Handle(GEOM_Function) aFunction = + aResEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_UV); + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) { + return NULL; + } + + GEOMImpl_IShapeExtend aCI (aFunction); + + Handle(GEOM_Function) anEdge = theEdge->GetLastFunction(); + + if (anEdge.IsNull()) { + return NULL; + } + + aCI.SetShape(anEdge); + aCI.SetUMin(theMin); + aCI.SetUMax(theMax); + + //Compute the Edge value + try { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Shape driver failed"); + + return NULL; + } + } + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); + + return NULL; + } + + //Make a Python command + GEOM::TPythonDump(aFunction) + << aResEdge << " = geompy.ExtendEdge(" + << theEdge << ", " << theMin << ", " << theMax << ")"; + + SetErrorCode(OK); + + return aResEdge; +} + +//======================================================================= +//function : ExtendFace +//purpose : +//======================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::ExtendFace + (const Handle(GEOM_Object) &theFace, + const Standard_Real theUMin, + const Standard_Real theUMax, + const Standard_Real theVMin, + const Standard_Real theVMax) +{ + SetErrorCode(KO); + + if (theFace.IsNull()) { + return NULL; + } + + //Add a new Face object + Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GEOM_FACE); + + //Add a new Vector function + Handle(GEOM_Function) aFunction = + aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), FACE_UV); + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) { + return NULL; + } + + GEOMImpl_IShapeExtend aCI (aFunction); + + Handle(GEOM_Function) aFace = theFace->GetLastFunction(); + + if (aFace.IsNull()) { + return NULL; + } + + aCI.SetShape(aFace); + aCI.SetUMin(theUMin); + aCI.SetUMax(theUMax); + aCI.SetVMin(theVMin); + aCI.SetVMax(theVMax); + + //Compute the Face value + try { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Shape driver failed"); + + return NULL; + } + } + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); + + return NULL; + } + + //Make a Python command + GEOM::TPythonDump(aFunction) + << aResFace << " = geompy.ExtendFace(" + << theFace << ", " << theUMin << ", " << theUMax << ", " + << theVMin << ", " << theVMax << ")"; + + SetErrorCode(OK); + + return aResFace; +} + +//======================================================================= +//function : MakeSurfaceFromFace +//purpose : +//======================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSurfaceFromFace + (const Handle(GEOM_Object) &theFace) +{ + SetErrorCode(KO); + + if (theFace.IsNull()) { + return NULL; + } + + //Add a new Face object + Handle(GEOM_Object) aResFace = GetEngine()->AddObject(GEOM_FACE); + + //Add a new Vector function + Handle(GEOM_Function) aFunction = + aResFace->AddFunction(GEOMImpl_ShapeDriver::GetID(), SURFACE_FROM_FACE); + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) { + return NULL; + } + + GEOMImpl_IShapeExtend aCI (aFunction); + + Handle(GEOM_Function) aFace = theFace->GetLastFunction(); + + if (aFace.IsNull()) { + return NULL; + } + + aCI.SetShape(aFace); + + //Compute the Face value + try { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Shape driver failed"); + + return NULL; + } + } + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); + + return NULL; + } + + //Make a Python command + GEOM::TPythonDump(aFunction) + << aResFace << " = geompy.MakeSurfaceFromFace(" + << theFace << ")"; + + SetErrorCode(OK); + + return aResFace; +}