X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGEOMImpl%2FGEOMImpl_IShapesOperations.cxx;h=e916f423202d39dd4fb1c055c29e6a85cd6a8919;hb=aab55c4f104405b4539e5a96f07f89bffb8201db;hp=47433ca3d4a20e6606723e7caf1b6f359164800a;hpb=e2dcf4323c7d7c36e8e1a4fda4dd6cf86c99be81;p=modules%2Fgeom.git diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx index 47433ca3d..e916f4232 100644 --- a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx @@ -1,41 +1,82 @@ +// Copyright (C) 2007-2010 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 +// +// 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. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : GEOMImpl_IShapesOperations.cxx +// Created : +// Author : modified by Lioka RAZAFINDRAZAKA (CEA) 22/06/2007 +// Project : SALOME +// $Header$ + #include -#include +#include "GEOMImpl_IShapesOperations.hxx" -#include +#include "GEOMImpl_Types.hxx" -#include -#include -#include -#include +#include "GEOMImpl_VectorDriver.hxx" +#include "GEOMImpl_ShapeDriver.hxx" +#include "GEOMImpl_CopyDriver.hxx" +#include "GEOMImpl_GlueDriver.hxx" -#include -#include -#include +#include "GEOMImpl_IVector.hxx" +#include "GEOMImpl_IShapes.hxx" +#include "GEOMImpl_IGlue.hxx" -#include +#include "GEOMImpl_Block6Explorer.hxx" -#include -#include +#include "GEOM_Function.hxx" +#include "GEOM_ISubShape.hxx" +#include "GEOM_PythonDump.hxx" -#include +#include "GEOMAlgo_FinderShapeOn1.hxx" +#include "GEOMAlgo_FinderShapeOnQuad.hxx" +#include "GEOMAlgo_FinderShapeOn2.hxx" +#include "GEOMAlgo_ClsfBox.hxx" +#include "GEOMAlgo_ClsfSolid.hxx" +#include "GEOMAlgo_Gluer1.hxx" +#include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx" +#include "GEOMAlgo_CoupleOfShapes.hxx" +#include "GEOMAlgo_ListOfCoupleOfShapes.hxx" #include "utilities.h" -#include -#include +#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 @@ -44,13 +85,16 @@ #include #include #include +#include #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -61,21 +105,35 @@ #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 + +#include +#include +#include + +#include +#include +#include + //============================================================================= /*! * constructor: @@ -97,7 +155,6 @@ GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations() MESSAGE("GEOMImpl_IShapesOperations::~GEOMImpl_IShapesOperations"); } - //============================================================================= /*! * MakeEdge @@ -131,6 +188,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge //Compute the Edge value try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Vector driver failed"); return NULL; @@ -150,15 +210,148 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge return anEdge; } +//============================================================================= +/*! + * MakeEdgeWire + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeWire + (Handle(GEOM_Object) theWire, + const Standard_Real theLinearTolerance, + const Standard_Real theAngularTolerance) +{ + SetErrorCode(KO); + + if (theWire.IsNull()) return NULL; + + //Add a new Edge object + Handle(GEOM_Object) anEdge = GetEngine()->AddObject(GetDocID(), GEOM_EDGE); + + //Add a new Vector function + Handle(GEOM_Function) aFunction = + anEdge->AddFunction(GEOMImpl_ShapeDriver::GetID(), EDGE_WIRE); + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL; + + GEOMImpl_IShapes aCI (aFunction); + + Handle(GEOM_Function) aWire = theWire->GetLastFunction(); + + if (aWire.IsNull()) return NULL; + + aCI.SetBase(aWire); + aCI.SetTolerance(theLinearTolerance); + aCI.SetAngularTolerance(theAngularTolerance); + + //Compute the Edge value + try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + 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()); + return NULL; + } + + const double DEF_LIN_TOL = Precision::Confusion(); + const double DEF_ANG_TOL = Precision::Angular(); + //Make a Python command + if ( theAngularTolerance == DEF_ANG_TOL ) { + if ( theLinearTolerance == DEF_LIN_TOL ) + GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire(" + << theWire << ")"; + else + GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire(" + << theWire << ", " << theLinearTolerance << ")"; + } + else { + GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire(" + << theWire << ", " << theLinearTolerance << ", " + << theAngularTolerance << ")"; + } + + SetErrorCode(OK); + return anEdge; +} + //============================================================================= /*! * MakeWire */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire - (list theShapes) + (std::list theShapes, + const Standard_Real theTolerance) { - return MakeShape(theShapes, GEOM_WIRE, WIRE_EDGES, "MakeWire"); + SetErrorCode(KO); + + //Add a new object + Handle(GEOM_Object) aWire = GetEngine()->AddObject(GetDocID(), GEOM_WIRE); + + //Add a new function + Handle(GEOM_Function) aFunction = + aWire->AddFunction(GEOMImpl_ShapeDriver::GetID(), WIRE_EDGES); + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL; + + GEOMImpl_IShapes aCI (aFunction); + aCI.SetTolerance(theTolerance); + + Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient; + + // Shapes + std::list::iterator it = theShapes.begin(); + for (; it != theShapes.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); + + //Compute the shape + try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + 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()); + return NULL; + } + + //Make a Python command + GEOM::TPythonDump pd (aFunction); + pd << aWire << " = geompy.MakeWire(["; + + // Shapes + it = theShapes.begin(); + if (it != theShapes.end()) { + pd << (*it++); + while (it != theShapes.end()) { + pd << ", " << (*it++); + } + } + pd << "], " << theTolerance << ")"; + + SetErrorCode(OK); + return aWire; } //============================================================================= @@ -195,6 +388,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) th //Compute the Face value try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed to compute a face"); return NULL; @@ -220,7 +416,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) th */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires - (list theShapes, + (std::list theShapes, const bool isPlanarWanted) { SetErrorCode(KO); @@ -241,7 +437,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient; // Shapes - list::iterator it = theShapes.begin(); + std::list::iterator it = theShapes.begin(); for (; it != theShapes.end(); it++) { Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction(); if (aRefSh.IsNull()) { @@ -256,6 +452,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires //Compute the shape try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed"); return NULL; @@ -291,7 +490,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell - (list theShapes) + (std::list theShapes) { return MakeShape(theShapes, GEOM_SHELL, SHELL_FACES, "MakeShell"); } @@ -302,60 +501,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShell */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShells - (list theShapes) -{ - return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolidShells"); -} - -//============================================================================= -/*! - * MakeSolidShell - */ -//============================================================================= -Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Object) theShell) + (std::list theShapes) { - SetErrorCode(KO); - - if (theShell.IsNull()) return NULL; - - //Add a new Solid object - Handle(GEOM_Object) aSolid = GetEngine()->AddObject(GetDocID(), GEOM_SOLID); - - //Add a new Solid function for creation of a solid from a shell - Handle(GEOM_Function) aFunction = - aSolid->AddFunction(GEOMImpl_ShapeDriver::GetID(), SOLID_SHELL); - 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(GEOM_Function) aRefShell = theShell->GetLastFunction(); - - if (aRefShell.IsNull()) return NULL; - - aCI.SetBase(aRefShell); - - //Compute the Solid value - try { - if (!GetSolver()->ComputeFunction(aFunction)) { - SetErrorCode("Solid driver failed"); - return NULL; - } - } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); - return NULL; - } - - //Make a Python command - GEOM::TPythonDump(aFunction) << aSolid - << " = geompy.MakeSolid(" << theShell << ")"; - - SetErrorCode(OK); - return aSolid; + return MakeShape(theShapes, GEOM_SOLID, SOLID_SHELLS, "MakeSolid"); } //============================================================================= @@ -364,7 +512,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeSolidShell (Handle(GEOM_Obje */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound - (list theShapes) + (std::list theShapes) { return MakeShape(theShapes, GEOM_COMPOUND, COMPOUND_SHAPES, "MakeCompound"); } @@ -375,10 +523,10 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeCompound */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape - (list theShapes, - const Standard_Integer theObjectType, - const Standard_Integer theFunctionType, - const TCollection_AsciiString theMethodName) + (std::list theShapes, + const Standard_Integer theObjectType, + const Standard_Integer theFunctionType, + const TCollection_AsciiString& theMethodName) { SetErrorCode(KO); @@ -398,7 +546,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient; // Shapes - list::iterator it = theShapes.begin(); + std::list::iterator it = theShapes.begin(); for (; it != theShapes.end(); it++) { Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction(); if (aRefSh.IsNull()) { @@ -411,6 +559,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape //Compute the shape try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed"); return NULL; @@ -447,7 +598,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape //============================================================================= Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces (Handle(GEOM_Object) theShape, - const Standard_Real theTolerance) + const Standard_Real theTolerance, + const Standard_Boolean doKeepNonSolids) { SetErrorCode(KO); @@ -471,10 +623,14 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces aCI.SetBase(aRefShape); aCI.SetTolerance(theTolerance); + aCI.SetKeepNonSolids(doKeepNonSolids); //Compute the sub-shape value Standard_Boolean isWarning = Standard_False; try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Shape driver failed to glue faces"); return NULL; @@ -502,17 +658,13 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces //============================================================================= /*! - * MakeExplode + * GetGlueFaces */ //============================================================================= -Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode - (Handle(GEOM_Object) theShape, - const Standard_Integer theShapeType, - const Standard_Boolean isSorted) +Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces + (Handle(GEOM_Object) theShape, + const Standard_Real theTolerance) { -// OSD_Timer timer1, timer2, timer3, timer4; -// timer1.Start(); - SetErrorCode(KO); if (theShape.IsNull()) return NULL; @@ -520,303 +672,338 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode if (aShape.IsNull()) return NULL; Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; - Handle(GEOM_Object) anObj; - Handle(GEOM_Function) aFunction; - TopTools_MapOfShape mapShape; - TopTools_ListOfShape listShape; - - if (aShape.ShapeType() == TopAbs_COMPOUND && - (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE || - TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID || - TopAbs_ShapeEnum(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()); - } - } - } - } else { - TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType)); - for (; exp.More(); exp.Next()) - if (mapShape.Add(exp.Current())) - listShape.Append(exp.Current()); - } - - if (listShape.IsEmpty()) { - SetErrorCode("The given shape has no sub-shapes of the requested type"); - return aSeq; - } -// timer1.Stop(); -// timer2.Start(); + Standard_Integer iErr; + TopoDS_Shape aS; + GEOMAlgo_Gluer1 aGluer; + GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS; + GEOMAlgo_CoupleOfShapes aCS; + GEOMAlgo_ListOfCoupleOfShapes aLCS; - if (isSorted) - SortShapes(listShape); + //aGluer = new GEOMAlgo_Gluer1; + aGluer.SetShape(aShape); + aGluer.SetTolerance(theTolerance); + aGluer.Perform(); + iErr = aGluer.ErrorStatus(); + if (iErr) return NULL; -// timer2.Stop(); -// timer3.Start(); + TopTools_ListOfShape listShape; + const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces(); + // Access to faces + aItCS.Initialize(aLCSG); + for (; aItCS.More(); aItCS.Next()) { + const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value(); + listShape.Append(aCSG.Shape1()); + } + TopTools_ListIteratorOfListOfShape itSub (listShape); + TCollection_AsciiString anAsciiList, anEntry; TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape, anIndices); Handle(TColStd_HArray1OfInteger) anArray; - - TopTools_ListIteratorOfListOfShape itSub (listShape); - TCollection_AsciiString anAsciiList, anEntry; + Handle(GEOM_Object) anObj; for (int index = 1; itSub.More(); itSub.Next(), ++index) { TopoDS_Shape aValue = itSub.Value(); anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(aValue)); anObj = GetEngine()->AddSubShape(theShape, anArray); - aSeq->Append(anObj); + if (!anObj.IsNull()) { + 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); - - aFunction = theShape->GetLastFunction(); - TCollection_AsciiString anOldDescr = aFunction->GetDescription(); - - GEOM::TPythonDump pd (aFunction); - pd << anOldDescr.ToCString() << "\n\t[" << anAsciiList.ToCString(); - pd << "] = geompy.SubShapeAll" << (isSorted ? "Sorted(" : "("); - pd << theShape << ", " << theShapeType << ")"; + if( anAsciiList.Length() > 0 ) { + anAsciiList.Trunc(anAsciiList.Length() - 1); + Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); + GEOM::TPythonDump pd (aFunction, /*append=*/true); + pd << "[" << anAsciiList.ToCString(); + pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")"; + } SetErrorCode(OK); -// timer4.Stop(); - -// cout << "Explosure takes:" << endl; -// timer1.Show(); -// cout << "Sorting takes:" << endl; -// timer2.Show(); -// cout << "Sub-shapes addition takes:" << endl; -// timer3.Show(); -// cout << "Update Description takes:" << endl; -// timer4.Show(); - return aSeq; } //============================================================================= /*! - * GetSubShapeAllIDs + * MakeGlueFacesByList */ //============================================================================= -Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs - (Handle(GEOM_Object) theShape, - const Standard_Integer theShapeType, - const Standard_Boolean isSorted) +Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFacesByList + (Handle(GEOM_Object) theShape, + const Standard_Real theTolerance, + std::list theFaces, + const Standard_Boolean doKeepNonSolids) { SetErrorCode(KO); if (theShape.IsNull()) return NULL; - TopoDS_Shape aShape = theShape->GetValue(); - if (aShape.IsNull()) return NULL; - Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger; - TopTools_MapOfShape mapShape; - TopTools_ListOfShape listShape; + //Add a new Glued object + Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED); - if (aShape.ShapeType() == TopAbs_COMPOUND && - (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE || - TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID || - TopAbs_ShapeEnum(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()); - } - } - } - } else { - TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType)); - for (; exp.More(); exp.Next()) - if (mapShape.Add(exp.Current())) - listShape.Append(exp.Current()); - } + //Add a new Glue function + Handle(GEOM_Function) aFunction; + aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_FACES_BY_LIST); + if (aFunction.IsNull()) return NULL; - if (listShape.IsEmpty()) { - SetErrorCode("The given shape has no sub-shapes of the requested type"); - return aSeq; - } + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL; - if (isSorted) - SortShapes(listShape); + GEOMImpl_IGlue aCI (aFunction); - TopTools_IndexedMapOfShape anIndices; - TopExp::MapShapes(aShape, anIndices); - Handle(TColStd_HArray1OfInteger) anArray; + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + if (aRefShape.IsNull()) return NULL; - TopTools_ListIteratorOfListOfShape itSub (listShape); - for (int index = 1; itSub.More(); itSub.Next(), ++index) { - TopoDS_Shape aValue = itSub.Value(); - aSeq->Append(anIndices.FindIndex(aValue)); + aCI.SetBase(aRefShape); + aCI.SetTolerance(theTolerance); + aCI.SetKeepNonSolids(doKeepNonSolids); + + 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); - Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); - TCollection_AsciiString anOldDescr = aFunction->GetDescription(); + //Compute the sub-shape value + Standard_Boolean isWarning = Standard_False; + try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + 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()); + // to provide warning + if (!aFunction->GetValue().IsNull()) { + isWarning = Standard_True; + } else { + return NULL; + } + } //Make a Python command - GEOM::TPythonDump pd (aFunction); - pd << anOldDescr.ToCString() << "\n\tlistSubShapeIDs = geompy.SubShapeAll"; - pd << (isSorted ? "SortedIDs(" : "IDs("); - pd << theShape << ", " << theShapeType << ")"; - SetErrorCode(OK); - return aSeq; + 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 << "])"; + + // to provide warning + if (!isWarning) SetErrorCode(OK); + return aGlued; } //============================================================================= /*! - * GetSubShape + * GetExistingSubObjects */ //============================================================================= -Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape - (Handle(GEOM_Object) theMainShape, - const Standard_Integer theID) +Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetExistingSubObjects + (Handle(GEOM_Object) theShape, + const Standard_Boolean theGroupsOnly) { SetErrorCode(KO); - if (theMainShape.IsNull()) return NULL; - - Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); - anArray->SetValue(1, theID); - Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true); - if (anObj.IsNull()) { - SetErrorCode("Can not get a sub-shape with the given ID"); - return NULL; - } - - Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); + if (theShape.IsNull()) return NULL; - //Make a Python command - GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape(" - << theMainShape << ", [" << theID << "])"; + Handle(GEOM_Function) aMainShape = theShape->GetLastFunction(); + if (aMainShape.IsNull()) return NULL; - SetErrorCode(OK); - return anObj; -} + Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; + SetErrorCode(NOT_FOUND_ANY); + if (!aMainShape->HasSubShapeReferences()) return aSeq; + const TDataStd_ListOfExtendedString& aListEntries = aMainShape->GetSubShapeReferences(); + if (aListEntries.IsEmpty()) return aSeq; -//============================================================================= -/*! - * NumberOfFaces - */ -//============================================================================= -Standard_Integer GEOMImpl_IShapesOperations::NumberOfFaces (Handle(GEOM_Object) theShape) -{ SetErrorCode(KO); - Standard_Integer nb = 0; + 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]; + anEntry.ToUTF8CString(anEntryStr); + Handle(GEOM_Object) anObj = GetEngine()->GetObject(GetDocID(), anEntryStr, false); + if (!anObj.IsNull()) { + if (!theGroupsOnly || anObj->GetType() == GEOM_GROUP) { + aSeq->Append(anObj); + + // for python command + anAsciiList += anEntryStr; + anAsciiList += ","; + } + } + delete [] anEntryStr; + } - if (theShape.IsNull()) return -1; - TopoDS_Shape aShape = theShape->GetValue(); - if (aShape.IsNull()) return -1; + if (aSeq->Length() == 0) { + SetErrorCode(NOT_FOUND_ANY); + return aSeq; + } - TopTools_MapOfShape mapShape; + //Make a Python command + anAsciiList.Trunc(anAsciiList.Length() - 1); - TopExp_Explorer exp (aShape, TopAbs_FACE); - for (; exp.More(); exp.Next()) - if (mapShape.Add(exp.Current())) - nb++; + GEOM::TPythonDump pd (aMainShape, /*append=*/true); + pd << "[" << anAsciiList.ToCString(); + pd << "] = geompy.GetExistingSubObjects("; + pd << theShape << ", " << (int)theGroupsOnly << ")"; SetErrorCode(OK); - return nb; + + return aSeq; } //============================================================================= /*! - * NumberOfEdges + * MakeExplode */ //============================================================================= -Standard_Integer GEOMImpl_IShapesOperations::NumberOfEdges (Handle(GEOM_Object) theShape) +Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode + (Handle(GEOM_Object) theShape, + const Standard_Integer theShapeType, + const Standard_Boolean isSorted, + const Standard_Boolean isOldSorting) { SetErrorCode(KO); - Standard_Integer nb = 0; - - if (theShape.IsNull()) return -1; + if (theShape.IsNull()) return NULL; TopoDS_Shape aShape = theShape->GetValue(); - if (aShape.IsNull()) return -1; - - TopTools_MapOfShape mapShape; - - TopExp_Explorer exp (aShape, TopAbs_EDGE); - for (; exp.More(); exp.Next()) - if (mapShape.Add(exp.Current())) - nb++; + if (aShape.IsNull()) return NULL; - SetErrorCode(OK); - return nb; -} + Handle(GEOM_Function) aMainShape = theShape->GetLastFunction(); -//============================================================================= -/*! - * ReverseShape - */ -//============================================================================= -Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape) -{ - SetErrorCode(KO); + Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; + Handle(GEOM_Object) anObj; + TopTools_MapOfShape mapShape; + TopTools_ListOfShape listShape; - if (theShape.IsNull()) return NULL; + if (aShape.ShapeType() == TopAbs_COMPOUND && + (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE || + TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID || + TopAbs_ShapeEnum(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()); + } + } + } + } + else if ( aShape.ShapeType() != theShapeType ) // issue 0021079, prevent from returning aShape + { + TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType)); + for (; exp.More(); exp.Next()) + if (mapShape.Add(exp.Current())) + listShape.Append(exp.Current()); + } - //Add a new reversed object - Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType()); + if (listShape.IsEmpty()) { + //SetErrorCode("The given shape has no sub-shapes of the requested type"); + SetErrorCode(NOT_FOUND_ANY); // NPAL18017 + return aSeq; + } - //Add a new Revese function - Handle(GEOM_Function) aFunction; - aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION); - if (aFunction.IsNull()) return NULL; + if (isSorted) + SortShapes(listShape, isOldSorting); - //Check if the function is set correctly - if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL; + TopTools_IndexedMapOfShape anIndices; + TopExp::MapShapes(aShape, anIndices); + Handle(TColStd_HArray1OfInteger) anArray; - GEOMImpl_IShapes aSI (aFunction); + TopTools_ListIteratorOfListOfShape itSub (listShape); + TCollection_AsciiString anAsciiList, anEntry; + for (int index = 1; itSub.More(); itSub.Next(), ++index) + { + TopoDS_Shape aValue = itSub.Value(); + anArray = new TColStd_HArray1OfInteger(1,1); + anArray->SetValue(1, anIndices.FindIndex(aValue)); - Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); - if (aRefShape.IsNull()) return NULL; + //anObj = GetEngine()->AddSubShape(theShape, anArray); + { + anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE); + Handle(GEOM_Function) aFunction = anObj->AddFunction(GEOM_Object::GetSubShapeID(), 1); + if (aFunction.IsNull()) return aSeq; + + GEOM_ISubShape aSSI (aFunction); + aSSI.SetMainShape(aMainShape); + aSSI.SetIndices(anArray); + + // Set function value directly, as we know it. + // Usage of Solver here would lead to significant loss of time, + // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape + // on the main shape for each being calculated sub-shape separately. + aFunction->SetValue(aValue); + } - aSI.SetBase(aRefShape); + if (!anObj.IsNull()) { + aSeq->Append(anObj); - //Compute the sub-shape value - try { - if (!GetSolver()->ComputeFunction(aFunction)) { - SetErrorCode("Shape driver failed to reverse shape"); - return NULL; + // for python command + TDF_Tool::Entry(anObj->GetEntry(), anEntry); + anAsciiList += anEntry; + anAsciiList += ","; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); - return NULL; - } //Make a Python command - GEOM::TPythonDump(aFunction) << aReversed - << " = geompy.ChangeOrientation(" << theShape << ")"; + anAsciiList.Trunc(anAsciiList.Length() - 1); + + GEOM::TPythonDump pd (aMainShape, /*append=*/true); + pd << "[" << anAsciiList.ToCString(); + if (isSorted) + pd << "] = geompy.SubShapeAllSorted" << (isOldSorting ? "(" : "Centres("); + else + pd << "] = geompy.SubShapeAll("; + pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")"; SetErrorCode(OK); - return aReversed; + + return aSeq; } //============================================================================= /*! - * GetFreeFacesIDs + * SubShapeAllIDs */ //============================================================================= -Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs - (Handle(GEOM_Object) theShape) +Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs + (Handle(GEOM_Object) theShape, + const Standard_Integer theShapeType, + const Standard_Boolean isSorted, + const Standard_Boolean isOldSorting) { SetErrorCode(KO); @@ -825,36 +1012,59 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs if (aShape.IsNull()) return NULL; Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger; + TopTools_MapOfShape mapShape; + TopTools_ListOfShape listShape; - TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks; - GEOMImpl_Block6Explorer::MapShapesAndAncestors - (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks); - - Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent(); + if (aShape.ShapeType() == TopAbs_COMPOUND && + (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE || + TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID || + TopAbs_ShapeEnum(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()); + } + } + } + } else if ( aShape.ShapeType() != theShapeType ) // issue 0021079, prevent from returning aShape + { + TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType)); + for (; exp.More(); exp.Next()) + if (mapShape.Add(exp.Current())) + listShape.Append(exp.Current()); + } - if (nbFaces == 0) { - SetErrorCode("The given shape has no faces"); + if (listShape.IsEmpty()) { + //SetErrorCode("The given shape has no sub-shapes of the requested type"); + SetErrorCode(NOT_FOUND_ANY); // NPAL18017 return aSeq; } + if (isSorted) + SortShapes(listShape, isOldSorting); + TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape, anIndices); + Handle(TColStd_HArray1OfInteger) anArray; - Standard_Integer id; - for (; ind <= nbFaces; ind++) { - if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) { - id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind)); - aSeq->Append(id); - } + TopTools_ListIteratorOfListOfShape itSub (listShape); + for (int index = 1; itSub.More(); itSub.Next(), ++index) { + TopoDS_Shape aValue = itSub.Value(); + aSeq->Append(anIndices.FindIndex(aValue)); } - //The explode doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); - TCollection_AsciiString anOldDescr = aFunction->GetDescription(); //Make a Python command - GEOM::TPythonDump(aFunction) << anOldDescr.ToCString() - << "\n\tlistFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")"; + GEOM::TPythonDump pd (aFunction, /*append=*/true); + pd << "listSubShapeIDs = geompy.SubShapeAll"; + if (isSorted) + pd << "Sorted" << (isOldSorting ? "IDs(" : "CentresIDs("); + else + pd << "IDs("; + pd << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")"; SetErrorCode(OK); return aSeq; @@ -862,98 +1072,1217 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs //============================================================================= /*! - * GetSharedShapes + * GetSubShape */ //============================================================================= -Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes - (Handle(GEOM_Object) theShape1, - Handle(GEOM_Object) theShape2, - const Standard_Integer theShapeType) +Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape + (Handle(GEOM_Object) theMainShape, + const Standard_Integer theID) { SetErrorCode(KO); - if (theShape1.IsNull() || theShape2.IsNull()) return NULL; - - TopoDS_Shape aShape1 = theShape1->GetValue(); - TopoDS_Shape aShape2 = theShape2->GetValue(); + if (theMainShape.IsNull()) return NULL; - if (aShape1.IsNull() || aShape2.IsNull()) return NULL; + Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); + anArray->SetValue(1, theID); + Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theMainShape, anArray,true); + if (anObj.IsNull()) { + SetErrorCode("Can not get a sub-shape with the given ID"); + return NULL; + } - TopTools_IndexedMapOfShape anIndices; - TopExp::MapShapes(aShape1, anIndices); - Handle(TColStd_HArray1OfInteger) anArray; + Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); + + //Make a Python command + GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape(" + << theMainShape << ", [" << theID << "])"; + + SetErrorCode(OK); + return anObj; +} + +//============================================================================= +/*! + * GetSubShapeIndex + */ +//============================================================================= +Standard_Integer GEOMImpl_IShapesOperations::GetSubShapeIndex (Handle(GEOM_Object) theMainShape, + Handle(GEOM_Object) theSubShape) +{ + SetErrorCode(KO); + + TopoDS_Shape aMainShape = theMainShape->GetValue(); + TopoDS_Shape aSubShape = theSubShape->GetValue(); + + if (aMainShape.IsNull() || aSubShape.IsNull()) return -1; + + TopTools_IndexedMapOfShape anIndices; + TopExp::MapShapes(aMainShape, anIndices); + if (anIndices.Contains(aSubShape)) { + SetErrorCode(OK); + return anIndices.FindIndex(aSubShape); + } + + return -1; +} + +//============================================================================= +/*! + * GetTopologyIndex + */ +//============================================================================= +Standard_Integer GEOMImpl_IShapesOperations::GetTopologyIndex (Handle(GEOM_Object) theMainShape, + Handle(GEOM_Object) theSubShape) +{ + SetErrorCode(OK); + + TopoDS_Shape aMainShape = theMainShape->GetValue(); + TopoDS_Shape aSubShape = theSubShape->GetValue(); + + if (aMainShape.IsNull() || aSubShape.IsNull()) { + SetErrorCode("Null argument shape given"); + return -1; + } + + int index = 1; + if (aSubShape.ShapeType() == TopAbs_COMPOUND) { + TopoDS_Iterator it; + TopTools_ListOfShape CL; + CL.Append(aMainShape); + TopTools_ListIteratorOfListOfShape itC; + for (itC.Initialize(CL); itC.More(); itC.Next()) { + for (it.Initialize(itC.Value()); it.More(); it.Next()) { + if (it.Value().ShapeType() == TopAbs_COMPOUND) { + if (it.Value().IsSame(aSubShape)) + return index; + else + index++; + CL.Append(it.Value()); + } + } + } + } else { + TopExp_Explorer anExp (aMainShape, aSubShape.ShapeType()); + TopTools_MapOfShape M; + for (; anExp.More(); anExp.Next()) { + if (M.Add(anExp.Current())) { + if (anExp.Current().IsSame(aSubShape)) + return index; + index++; + } + } + } + + SetErrorCode("The sub-shape does not belong to the main shape"); + return -1; +} + +//============================================================================= +/*! + * GetShapeTypeString + */ +//============================================================================= +TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(GEOM_Object) theShape) +{ + SetErrorCode(KO); + + TCollection_AsciiString aTypeName ("Null Shape"); + + TopoDS_Shape aShape = theShape->GetValue(); + if (aShape.IsNull()) + return aTypeName; + + switch (aShape.ShapeType() ) + { + case TopAbs_COMPOUND: + aTypeName = "Compound"; + break; + case TopAbs_COMPSOLID: + aTypeName = "Compound Solid"; + break; + case TopAbs_SOLID: + aTypeName = "Solid"; + break; + case TopAbs_SHELL: + aTypeName = "Shell"; + break; + case TopAbs_FACE: + { + BRepAdaptor_Surface surf (TopoDS::Face(aShape)); + if (surf.GetType() == GeomAbs_Plane) + aTypeName = "Plane"; + else if (surf.GetType() == GeomAbs_Cylinder) + aTypeName = "Cylindrical Face"; + else if (surf.GetType() == GeomAbs_Sphere) + aTypeName = "Spherical Face"; + else if (surf.GetType() == GeomAbs_Torus) + aTypeName = "Toroidal Face"; + else if (surf.GetType() == GeomAbs_Cone) + aTypeName = "Conical Face"; + else + aTypeName = "GEOM::FACE"; + } + break; + case TopAbs_WIRE: + aTypeName = "Wire"; + break; + case TopAbs_EDGE: + { + BRepAdaptor_Curve curv (TopoDS::Edge(aShape)); + if (curv.GetType() == GeomAbs_Line) { + if ((Abs(curv.FirstParameter()) >= 1E6) || + (Abs(curv.LastParameter()) >= 1E6)) + aTypeName = "Line"; + else + aTypeName = "Edge"; + } else if (curv.GetType() == GeomAbs_Circle) { + if (curv.IsClosed()) + aTypeName = "Circle"; + else + aTypeName = "Arc"; + } else { + aTypeName = "Edge"; + } + } + break; + case TopAbs_VERTEX: + aTypeName = "Vertex"; + break; + case TopAbs_SHAPE: + aTypeName = "Shape"; + break; + default: + aTypeName = "Shape of unknown type"; + } + + return aTypeName; +} + +//============================================================================= +/*! + * NumberOfSubShapes + */ +//============================================================================= +Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes + (Handle(GEOM_Object) theShape, + const Standard_Integer theShapeType) +{ + SetErrorCode(KO); + Standard_Integer nbShapes = 0; + + if (theShape.IsNull()) return -1; + TopoDS_Shape aShape = theShape->GetValue(); + if (aShape.IsNull()) return -1; + + /* + TopTools_MapOfShape mapShape; + + if (aShape.ShapeType() == TopAbs_COMPOUND && + (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE || + TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID || + TopAbs_ShapeEnum(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()) { + nbShapes++; + } + } + } + } else { + TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType)); + for (; exp.More(); exp.Next()) + if (mapShape.Add(exp.Current())) + nbShapes++; + } + */ + + try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + 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 (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()); + return -1; + } + + SetErrorCode(OK); + return nbShapes; +} + +//============================================================================= +/*! + * ReverseShape + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) theShape) +{ + SetErrorCode(KO); + + if (theShape.IsNull()) return NULL; + + //Add a new reversed object + Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType()); + + //Add a new Revese function + Handle(GEOM_Function) aFunction; + aFunction = aReversed->AddFunction(GEOMImpl_ShapeDriver::GetID(), REVERSE_ORIENTATION); + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL; + + GEOMImpl_IShapes aSI (aFunction); + + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + if (aRefShape.IsNull()) return NULL; + + aSI.SetBase(aRefShape); + + //Compute the sub-shape value + try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + 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()); + return NULL; + } + + //Make a Python command + GEOM::TPythonDump(aFunction) << aReversed + << " = geompy.ChangeOrientation(" << theShape << ")"; + + SetErrorCode(OK); + return aReversed; +} + +//============================================================================= +/*! + * GetFreeFacesIDs + */ +//============================================================================= +Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs + (Handle(GEOM_Object) theShape) +{ + SetErrorCode(KO); + + if (theShape.IsNull()) return NULL; + TopoDS_Shape aShape = theShape->GetValue(); + if (aShape.IsNull()) return NULL; + + Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger; + + TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks; + GEOMImpl_Block6Explorer::MapShapesAndAncestors + (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks); + + Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent(); + + if (nbFaces == 0) { + SetErrorCode("The given shape has no faces"); + return aSeq; + } + + TopTools_IndexedMapOfShape anIndices; + TopExp::MapShapes(aShape, anIndices); + + Standard_Integer id; + for (; ind <= nbFaces; ind++) { + if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) { + id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind)); + aSeq->Append(id); + } + } + + //The explode doesn't change object so no new function is required. + Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); + + //Make a Python command + GEOM::TPythonDump(aFunction, /*append=*/true) + << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")"; + + SetErrorCode(OK); + return aSeq; +} + +//======================================================================= +//function : GetSharedShapes +//purpose : +//======================================================================= +Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes + (Handle(GEOM_Object) theShape1, + Handle(GEOM_Object) theShape2, + const Standard_Integer theShapeType) +{ + SetErrorCode(KO); + + if (theShape1.IsNull() || theShape2.IsNull()) return NULL; + + TopoDS_Shape aShape1 = theShape1->GetValue(); + TopoDS_Shape aShape2 = theShape2->GetValue(); + + if (aShape1.IsNull() || aShape2.IsNull()) return NULL; + + TopTools_IndexedMapOfShape anIndices; + TopExp::MapShapes(aShape1, anIndices); + Handle(TColStd_HArray1OfInteger) anArray; TopTools_IndexedMapOfShape mapShape1; TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1); - Handle(GEOM_Object) anObj; - Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; - TCollection_AsciiString anAsciiList, anEntry; + Handle(GEOM_Object) anObj; + Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; + TCollection_AsciiString anAsciiList, anEntry; + + TopTools_MapOfShape mapShape2; + TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType)); + for (; exp.More(); exp.Next()) { + TopoDS_Shape aSS = exp.Current(); + if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) { + anArray = new TColStd_HArray1OfInteger(1,1); + anArray->SetValue(1, anIndices.FindIndex(aSS)); + anObj = GetEngine()->AddSubShape(theShape1, anArray); + aSeq->Append(anObj); + + // for python command + 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 + anAsciiList.Trunc(anAsciiList.Length() - 1); + + Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); + + GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString() + << "] = geompy.GetSharedShapes(" << theShape1 << ", " + << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")"; + + SetErrorCode(OK); + return aSeq; +} + +//======================================================================= +//function : GetSharedShapes +//purpose : +//======================================================================= +Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes + (std::list theShapes, + const Standard_Integer theShapeType) +{ + 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++); + 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++) { + Handle(GEOM_Function) aRefShape = (*it)->GetLastFunction(); + if (aRefShape.IsNull()) { + SetErrorCode("NULL shape for GetSharedShapes"); + return NULL; + } + + TopoDS_Compound aCompound; + B.MakeCompound(aCompound); + + TopoDS_Shape aShape2 = aRefShape->GetValue(); + if (aShape2.IsNull()) return NULL; + + 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); + } + } + + 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())); + anObj = GetEngine()->AddSubShape(aMainObj, anArray); + aSeq->Append(anObj); + + // for python command + 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 + anAsciiList.Trunc(anAsciiList.Length() - 1); + + GEOM::TPythonDump pd (aMainShape, /*append=*/true); + pd << "[" << anAsciiList.ToCString() + << "] = geompy.GetSharedShapesMulti(["; + + it = theShapes.begin(); + pd << (*it++); + while (it != theShapes.end()) { + pd << ", " << (*it++); + } + + pd << "], " << TopAbs_ShapeEnum(theShapeType) << ")"; + + SetErrorCode(OK); + return aSeq; +} + +//============================================================================= +/*! + * + */ +//============================================================================= +static GEOM::TPythonDump& operator<< (GEOM::TPythonDump& theDump, + const GEOMAlgo_State theState) +{ + switch (theState) { + case GEOMAlgo_ST_IN: + theDump << "geompy.GEOM.ST_IN"; + break; + case GEOMAlgo_ST_OUT: + theDump << "geompy.GEOM.ST_OUT"; + break; + case GEOMAlgo_ST_ON: + theDump << "geompy.GEOM.ST_ON"; + break; + case GEOMAlgo_ST_ONIN: + theDump << "geompy.GEOM.ST_ONIN"; + break; + case GEOMAlgo_ST_ONOUT: + theDump << "geompy.GEOM.ST_ONOUT"; + break; + default: + theDump << "geompy.GEOM.ST_UNKNOWN"; + break; + } + return theDump; +} + +//======================================================================= +//function : checkTypeShapesOn +/*! + * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK + * \param theShapeType - the shape type to check + * \retval bool - result of the check + */ +//======================================================================= +bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType) +{ + if (theShapeType != TopAbs_VERTEX && + theShapeType != TopAbs_EDGE && + theShapeType != TopAbs_FACE && + theShapeType != TopAbs_SOLID) { + SetErrorCode("Only solids, vertices, edges or faces can be found by this method"); + return false; + } + return true; +} + +//======================================================================= +//function : makePlane + /*! + * \brief Creates Geom_Plane + * \param theAx1 - shape object defining plane parameters + * \retval Handle(Geom_Surface) - resulting surface + */ +//======================================================================= +Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1) +{ + if (anAx1.ShapeType() != TopAbs_EDGE) return NULL; + TopoDS_Edge anEdge = TopoDS::Edge(anAx1); + TopoDS_Vertex V1, V2; + TopExp::Vertices(anEdge, V1, V2, Standard_True); + if (V1.IsNull() || V2.IsNull()) { + SetErrorCode("Bad edge given for the plane normal vector"); + return NULL; + } + gp_Pnt aLoc = BRep_Tool::Pnt(V1); + gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2)); + if (aVec.Magnitude() < Precision::Confusion()) { + SetErrorCode("Vector with null magnitude given"); + return NULL; + } + return new Geom_Plane(aLoc, aVec); +} + +//======================================================================= +//function : makeCylinder + /*! + * \brief Creates Geom_CylindricalSurface + * \param theAx1 - edge defining cylinder axis + * \param theRadius - cylinder radius + * \retval Handle(Geom_Surface) - resulting surface + */ +//======================================================================= +Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis, + const Standard_Real theRadius) +{ + //Axis of the cylinder + if (anAxis.ShapeType() != TopAbs_EDGE) { + SetErrorCode("Not an edge given for the axis"); + return NULL; + } + TopoDS_Edge anEdge = TopoDS::Edge(anAxis); + TopoDS_Vertex V1, V2; + TopExp::Vertices(anEdge, V1, V2, Standard_True); + if (V1.IsNull() || V2.IsNull()) { + SetErrorCode("Bad edge given for the axis"); + return NULL; + } + gp_Pnt aLoc = BRep_Tool::Pnt(V1); + gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2)); + if (aVec.Magnitude() < Precision::Confusion()) { + SetErrorCode("Vector with null magnitude given"); + return NULL; + } + + gp_Ax3 anAx3 (aLoc, aVec); + return new Geom_CylindricalSurface(anAx3, theRadius); +} + +//======================================================================= +//function : getShapesOnBoxIDs + /*! + * \brief Find IDs of subshapes complying with given status about surface + * \param theBox - the box to check state of subshapes against + * \param theShape - the shape to explore + * \param theShapeType - type of subshape of theShape + * \param theState - required state + * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes + */ +//======================================================================= +Handle(TColStd_HSequenceOfInteger) + GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox, + const Handle(GEOM_Object)& theShape, + const Standard_Integer theShapeType, + GEOMAlgo_State theState) +{ + Handle(TColStd_HSequenceOfInteger) aSeqOfIDs; + + TopoDS_Shape aBox = theBox->GetValue(); + TopoDS_Shape aShape = theShape->GetValue(); + + // Check presence of triangulation, build if need + if (!CheckTriangulation(aShape)) { + SetErrorCode("Cannot build triangulation on the shape"); + return aSeqOfIDs; + } + + // Call algo + GEOMAlgo_FinderShapeOn2 aFinder; + Standard_Real aTol = 0.0001; // default value + + Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox; + aClsfBox->SetBox(aBox); + + aFinder.SetShape(aShape); + aFinder.SetTolerance(aTol); + aFinder.SetClsf(aClsfBox); + aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType ); + aFinder.SetState(theState); + aFinder.Perform(); + + // Interprete results + Standard_Integer iErr = aFinder.ErrorStatus(); + // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx + if (iErr) { + MESSAGE(" iErr : " << iErr); + TCollection_AsciiString aMsg (" iErr : "); + aMsg += TCollection_AsciiString(iErr); + SetErrorCode(aMsg); + return aSeqOfIDs; + } + Standard_Integer iWrn = aFinder.WarningStatus(); + // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx + if (iWrn) { + MESSAGE(" *** iWrn : " << iWrn); + } + + const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result + + if (listSS.Extent() < 1) { + //SetErrorCode("Not a single sub-shape of the requested type found on the given surface"); + SetErrorCode(NOT_FOUND_ANY); // NPAL18017 + return aSeqOfIDs; + } + + // Fill sequence of object IDs + aSeqOfIDs = new TColStd_HSequenceOfInteger; + + TopTools_IndexedMapOfShape anIndices; + TopExp::MapShapes(aShape, anIndices); + + TopTools_ListIteratorOfListOfShape itSub (listSS); + for (int index = 1; itSub.More(); itSub.Next(), ++index) { + int id = anIndices.FindIndex(itSub.Value()); + aSeqOfIDs->Append(id); + } + + return aSeqOfIDs; +} + +//======================================================================= +//function : GetShapesOnBoxIDs +/*! + * \brief Find subshapes complying with given status about surface + * \param theBox - the box to check state of subshapes against + * \param theShape - the shape to explore + * \param theShapeType - type of subshape of theShape + * \param theState - required state + * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes + */ +//======================================================================= +Handle(TColStd_HSequenceOfInteger) + GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox, + const Handle(GEOM_Object)& theShape, + const Standard_Integer theShapeType, + GEOMAlgo_State theState) +{ + // Find subshapes ids + Handle(TColStd_HSequenceOfInteger) aSeqOfIDs = + getShapesOnBoxIDs (theBox, theShape, theShapeType, theState); + if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 ) + return NULL; + + // The GetShapesOnBox() doesn't change object so no new function is required. + Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction(); + + // Make a Python command + GEOM::TPythonDump(aFunction) + << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs(" + << theBox << ", " + << theShape << ", " + << TopAbs_ShapeEnum(theShapeType) << ", " + << theState << ")"; + + SetErrorCode(OK); + return aSeqOfIDs; +} + +//======================================================================= +//function : GetShapesOnBox +/*! + * \brief Find subshapes complying with given status about surface + * \param theBox - the box to check state of subshapes against + * \param theShape - the shape to explore + * \param theShapeType - type of subshape of theShape + * \param theState - required state + * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes + */ +//======================================================================= +Handle(TColStd_HSequenceOfTransient) + GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox, + const Handle(GEOM_Object)& theShape, + const Standard_Integer theShapeType, + GEOMAlgo_State theState) +{ + // Find subshapes ids + Handle(TColStd_HSequenceOfInteger) aSeqOfIDs = + getShapesOnBoxIDs (theBox, theShape, theShapeType, theState); + if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 ) + return NULL; + + // Find objects by indices + TCollection_AsciiString anAsciiList; + Handle(TColStd_HSequenceOfTransient) aSeq; + aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList ); + if ( aSeq.IsNull() || aSeq->IsEmpty() ) + 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.GetShapesOnBox(" + << theBox << ", " + << theShape << ", " + << TopAbs_ShapeEnum(theShapeType) << ", " + << theState << ")"; + + SetErrorCode(OK); + return aSeq; +} + +//======================================================================= +//function : getShapesOnShapeIDs +/*! + * \brief Find IDs of subshapes complying with given status about surface + * \param theCheckShape - the shape to check state of subshapes against + * \param theShape - the shape to explore + * \param theShapeType - type of subshape of theShape + * \param theState - required state + * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes + */ +//======================================================================= +Handle(TColStd_HSequenceOfInteger) + GEOMImpl_IShapesOperations::getShapesOnShapeIDs + (const Handle(GEOM_Object)& theCheckShape, + const Handle(GEOM_Object)& theShape, + const Standard_Integer theShapeType, + GEOMAlgo_State theState) +{ + Handle(TColStd_HSequenceOfInteger) aSeqOfIDs; + + TopoDS_Shape aCheckShape = theCheckShape->GetValue(); + TopoDS_Shape aShape = theShape->GetValue(); + TopTools_ListOfShape res; - TopTools_MapOfShape mapShape2; - TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType)); - for (; exp.More(); exp.Next()) { - TopoDS_Shape aSS = exp.Current(); - if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) { - anArray = new TColStd_HArray1OfInteger(1,1); - anArray->SetValue(1, anIndices.FindIndex(aSS)); - anObj = GetEngine()->AddSubShape(theShape1, anArray); - aSeq->Append(anObj); + // Check presence of triangulation, build if need + if (!CheckTriangulation(aShape)) { + SetErrorCode("Cannot build triangulation on the shape"); + return aSeqOfIDs; + } - // for python command - TDF_Tool::Entry(anObj->GetEntry(), anEntry); - anAsciiList += anEntry; - anAsciiList += ","; + // Call algo + GEOMAlgo_FinderShapeOn2 aFinder; + Standard_Real aTol = 0.0001; // default value + + Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid; + aClsfSolid->SetShape(aCheckShape); + + aFinder.SetShape(aShape); + aFinder.SetTolerance(aTol); + aFinder.SetClsf(aClsfSolid); + aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType ); + aFinder.SetState(theState); + aFinder.Perform(); + + // Interprete results + Standard_Integer iErr = aFinder.ErrorStatus(); + // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx + if (iErr) { + if (iErr == 41) { + SetErrorCode("theCheckShape must be a solid"); } + else { + MESSAGE(" iErr : " << iErr); + TCollection_AsciiString aMsg (" iErr : "); + aMsg += TCollection_AsciiString(iErr); + SetErrorCode(aMsg); + } + return aSeqOfIDs; + } + Standard_Integer iWrn = aFinder.WarningStatus(); + // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx + if (iWrn) { + MESSAGE(" *** iWrn : " << iWrn); } - if (aSeq->IsEmpty()) { - SetErrorCode("The given shapes have no shared sub-shapes of the requested type"); - return aSeq; + const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result + + if (listSS.Extent() < 1) { + //SetErrorCode("Not a single sub-shape of the requested type found on the given surface"); + SetErrorCode(NOT_FOUND_ANY); // NPAL18017 } - //Make a Python command - anAsciiList.Trunc(anAsciiList.Length() - 1); + // Fill sequence of object IDs + aSeqOfIDs = new TColStd_HSequenceOfInteger; + + TopTools_IndexedMapOfShape anIndices; + TopExp::MapShapes(aShape, anIndices); + + TopTools_ListIteratorOfListOfShape itSub (listSS); + for (int index = 1; itSub.More(); itSub.Next(), ++index) { + int id = anIndices.FindIndex(itSub.Value()); + aSeqOfIDs->Append(id); + } + + return aSeqOfIDs; +} + +//======================================================================= +//function : GetShapesOnShapeIDs +/*! + * \brief Find subshapes complying with given status about surface + * \param theCheckShape - the shape to check state of subshapes against + * \param theShape - the shape to explore + * \param theShapeType - type of subshape of theShape + * \param theState - required state + * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes + */ +//======================================================================= +Handle(TColStd_HSequenceOfInteger) + GEOMImpl_IShapesOperations::GetShapesOnShapeIDs + (const Handle(GEOM_Object)& theCheckShape, + const Handle(GEOM_Object)& theShape, + const Standard_Integer theShapeType, + GEOMAlgo_State theState) +{ + Handle(TColStd_HSequenceOfInteger) aSeqOfIDs = + getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState); + + if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 ) + return NULL; + + // The GetShapesOnShape() doesn't change object so no new function is required. + Handle(GEOM_Function) aFunction = + GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction(); + + // Make a Python command + GEOM::TPythonDump(aFunction) + << "listShapesOnBoxIDs = geompy.GetShapesOnShapeIDs(" + << theCheckShape << ", " + << theShape << ", " + << TopAbs_ShapeEnum(theShapeType) << ", " + << theState << ")"; + + SetErrorCode(OK); + return aSeqOfIDs; +} + +//======================================================================= +//function : GetShapesOnShape +/*! + * \brief Find subshapes complying with given status about surface + * \param theCheckShape - the shape to check state of subshapes against + * \param theShape - the shape to explore + * \param theShapeType - type of subshape of theShape + * \param theState - required state + * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes + */ +//======================================================================= +Handle(TColStd_HSequenceOfTransient) + GEOMImpl_IShapesOperations::GetShapesOnShape + (const Handle(GEOM_Object)& theCheckShape, + const Handle(GEOM_Object)& theShape, + const Standard_Integer theShapeType, + GEOMAlgo_State theState) +{ + Handle(TColStd_HSequenceOfInteger) aSeqOfIDs = + getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState); + if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 ) + return NULL; + + // Find objects by indices + TCollection_AsciiString anAsciiList; + Handle(TColStd_HSequenceOfTransient) aSeq; + aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList ); + + if ( aSeq.IsNull() || aSeq->IsEmpty() ) + 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.GetSharedShapes(" << theShape1 << ", " - << theShape2 << ", " << theShapeType << ")"; + GEOM::TPythonDump(aFunction) + << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape(" + << theCheckShape << ", " + << theShape << ", " + << TopAbs_ShapeEnum(theShapeType) << ", " + << theState << ")"; SetErrorCode(OK); return aSeq; } -//============================================================================= +//======================================================================= +//function : GetShapesOnShapeAsCompound +//======================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound + (const Handle(GEOM_Object)& theCheckShape, + const Handle(GEOM_Object)& theShape, + const Standard_Integer theShapeType, + GEOMAlgo_State theState) +{ + Handle(TColStd_HSequenceOfInteger) aSeqOfIDs = + getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState); + + if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 ) + return NULL; + + // Find objects by indices + TCollection_AsciiString anAsciiList; + Handle(TColStd_HSequenceOfTransient) aSeq; + aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList ); + + if ( aSeq.IsNull() || aSeq->IsEmpty() ) + return NULL; + + TopoDS_Compound aCompound; + BRep_Builder B; + B.MakeCompound(aCompound); + int i = 1; + for(; i<=aSeq->Length(); i++) { + Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i)); + TopoDS_Shape aShape_i = anObj->GetValue(); + B.Add(aCompound,aShape_i); + } + + //Add a new result object + Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), GEOM_SHAPES_ON_SHAPE); + Handle(GEOM_Function) aFunction = + aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE); + aFunction->SetValue(aCompound); + + GEOM::TPythonDump(aFunction) + << aRes << " = geompy.GetShapesOnShapeAsCompound(" + << theCheckShape << ", " + << theShape << ", " + << TopAbs_ShapeEnum(theShapeType) << ", " + << theState << ")"; + + SetErrorCode(OK); + + return aRes; +} + +//======================================================================= +//function : getShapesOnSurfaceIDs + /*! + * \brief Find IDs of subshapes complying with given status about surface + * \param theSurface - the surface to check state of subshapes against + * \param theShape - the shape to explore + * \param theShapeType - type of subshape of theShape + * \param theState - required state + * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes + */ +//======================================================================= +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 (!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 { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + 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; + } + // 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); + + // 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); + + aFinder.Perform(); + + // Interprete results + Standard_Integer iErr = aFinder.ErrorStatus(); + // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx + if (iErr) { + MESSAGE(" iErr : " << iErr); + TCollection_AsciiString aMsg (" iErr : "); + aMsg += TCollection_AsciiString(iErr); + SetErrorCode(aMsg); + return aSeqOfIDs; + } + Standard_Integer iWrn = aFinder.WarningStatus(); + // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx + if (iWrn) { + MESSAGE(" *** iWrn : " << iWrn); + } + + const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result + + if (listSS.Extent() < 1) { + //SetErrorCode("Not a single sub-shape of the requested type found on the given surface"); + SetErrorCode(NOT_FOUND_ANY); // NPAL18017 + return aSeqOfIDs; + } + + // Fill sequence of object IDs + aSeqOfIDs = new TColStd_HSequenceOfInteger; + + TopTools_IndexedMapOfShape anIndices; + TopExp::MapShapes(theShape, anIndices); + + TopTools_ListIteratorOfListOfShape itSub (listSS); + for (int index = 1; itSub.More(); itSub.Next(), ++index) { + int id = anIndices.FindIndex(itSub.Value()); + aSeqOfIDs->Append(id); + } + + return aSeqOfIDs; +} + +//======================================================================= +//function : getObjectsShapesOn /*! - * + * \brief Find shape objects and their entries by their ids + * \param theShapeIDs - incoming shape ids + * \param theShapeEntries - outgoing entries like "entry1, entry2, ..." + * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects */ -//============================================================================= -static GEOM::TPythonDump& operator<< (GEOM::TPythonDump& theDump, - const GEOMAlgo_State theState) +//======================================================================= +Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations:: + getObjectsShapesOn(const Handle(GEOM_Object)& theShape, + const Handle(TColStd_HSequenceOfInteger)& theShapeIDs, + TCollection_AsciiString & theShapeEntries) { - switch (theState) { - case GEOMAlgo_ST_IN: - theDump << "geompy.GEOM.ST_IN"; - break; - case GEOMAlgo_ST_OUT: - theDump << "geompy.GEOM.ST_OUT"; - break; - case GEOMAlgo_ST_ON: - theDump << "geompy.GEOM.ST_ON"; - break; - case GEOMAlgo_ST_ONIN: - theDump << "geompy.GEOM.ST_ONIN"; - break; - case GEOMAlgo_ST_ONOUT: - theDump << "geompy.GEOM.ST_ONOUT"; - break; - default: - theDump << "geompy.GEOM.ST_UNKNOWN"; - break; + Handle(TColStd_HSequenceOfTransient) aSeq; + + if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 ) + { + aSeq = new TColStd_HSequenceOfTransient; + Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); + TCollection_AsciiString anEntry; + for ( int i = 1; i <= theShapeIDs->Length(); ++i ) + { + anArray->SetValue(1, theShapeIDs->Value( i )); + Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray); + aSeq->Append( anObj ); + + TDF_Tool::Entry(anObj->GetEntry(), anEntry); + if ( i != 1 ) theShapeEntries += ","; + theShapeEntries += anEntry; + } } - return theDump; + return aSeq; +} + +//======================================================================= +//function : getShapesOnSurface +/*! + * \brief Find subshapes complying with given status about surface + * \param theSurface - the surface to check state of subshapes against + * \param theShape - the shape to explore + * \param theShapeType - type of subshape of theShape + * \param theState - required state + * \param theShapeEntries - outgoing entries like "entry1, entry2, ..." + * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes + */ +//======================================================================= +Handle(TColStd_HSequenceOfTransient) + GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface, + const Handle(GEOM_Object)& theShape, + TopAbs_ShapeEnum theShapeType, + GEOMAlgo_State theState, + TCollection_AsciiString & theShapeEntries) +{ + // Find subshapes ids + Handle(TColStd_HSequenceOfInteger) aSeqOfIDs = + getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState); + if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 ) + return NULL; + + return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries ); } //============================================================================= @@ -969,10 +2298,6 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlan { SetErrorCode(KO); -// MESSAGE("--------------------------- GetShapesOnPlane phase 1 takes:"); -// OSD_Timer timer1; -// timer1.Start(); - if (theShape.IsNull() || theAx1.IsNull()) return NULL; TopoDS_Shape aShape = theShape->GetValue(); @@ -981,138 +2306,103 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlan if (aShape.IsNull() || anAx1.IsNull()) return NULL; TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); - if (aShapeType != TopAbs_VERTEX && - aShapeType != TopAbs_EDGE && - aShapeType != TopAbs_FACE && - aShapeType != TopAbs_SOLID) { - SetErrorCode("Only solids, vertices, edges or faces can be found by this method"); + if ( !checkTypeShapesOn( theShapeType )) return NULL; - } // Create plane - if (anAx1.ShapeType() != TopAbs_EDGE) return NULL; - TopoDS_Edge anEdge = TopoDS::Edge(anAx1); - TopoDS_Vertex V1, V2; - TopExp::Vertices(anEdge, V1, V2, Standard_True); - if (V1.IsNull() || V2.IsNull()) { - SetErrorCode("Bad edge given for the plane normal vector"); + Handle(Geom_Surface) aPlane = makePlane( anAx1 ); + if ( aPlane.IsNull() ) return NULL; - } - gp_Pnt aLoc = BRep_Tool::Pnt(V1); - gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2)); - if (aVec.Magnitude() < Precision::Confusion()) { - SetErrorCode("Vector with null magnitude given"); + + // Find objects + TCollection_AsciiString anAsciiList; + Handle(TColStd_HSequenceOfTransient) aSeq; + aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList ); + if ( aSeq.IsNull() || aSeq->Length() == 0 ) return NULL; - } - Handle(Geom_Plane) aPlane = new Geom_Plane(aLoc, aVec); + // Make a Python command - // Check presence of triangulation, build if need - if (!CheckTriangulation(aShape)) - return NULL; + Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 )); + Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); - // Call algo - GEOMAlgo_FinderShapeOn1 aFinder; - Standard_Real aTol = 0.0001; // default value + GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString() + << "] = geompy.GetShapesOnPlane(" << theShape << ", " + << aShapeType << ", " << theAx1 << ", " << theState << ")"; - aFinder.SetShape(aShape); - aFinder.SetTolerance(aTol); - aFinder.SetSurface(aPlane); - aFinder.SetShapeType(aShapeType); - aFinder.SetState(theState); + SetErrorCode(OK); + return aSeq; +} - // 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); +//============================================================================= +/*! + * GetShapesOnPlaneWithLocation + */ +//============================================================================= +Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation + (const Handle(GEOM_Object)& theShape, + const Standard_Integer theShapeType, + const Handle(GEOM_Object)& theAx1, + const Handle(GEOM_Object)& thePnt, + const GEOMAlgo_State theState) +{ + SetErrorCode(KO); -// timer1.Stop(); -// timer1.Show(); + if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL; -// MESSAGE("--------------------------- Perform on Plane takes:"); -// timer1.Reset(); -// timer1.Start(); - aFinder.Perform(); -// timer1.Stop(); -// timer1.Show(); + TopoDS_Shape aShape = theShape->GetValue(); + TopoDS_Shape anAx1 = theAx1->GetValue(); + TopoDS_Shape anPnt = thePnt->GetValue(); -// MESSAGE("--------------------------- GetShapesOnPlane phase 3 takes:"); -// timer1.Reset(); -// timer1.Start(); + if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL; - // Interprete results - Standard_Integer iErr = aFinder.ErrorStatus(); - // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx - if (iErr) { - MESSAGE(" iErr : " << iErr); - TCollection_AsciiString aMsg (" iErr : "); - aMsg += TCollection_AsciiString(iErr); - SetErrorCode(aMsg); + TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); + if ( !checkTypeShapesOn( theShapeType )) return NULL; - } - Standard_Integer iWrn = aFinder.WarningStatus(); - // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx - if (iWrn) { - MESSAGE(" *** iWrn : " << iWrn); - } - const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result + // Create plane + if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL; + TopoDS_Vertex V1, V2, V3; + TopoDS_Edge anEdge = TopoDS::Edge(anAx1); + TopExp::Vertices(anEdge, V1, V2, Standard_True); - if (listSS.Extent() < 1) { - SetErrorCode("Not a single sub-shape of the requested type found on the given plane"); + if (V1.IsNull() || V2.IsNull()) { + SetErrorCode("Bad edge given for the plane normal vector"); return NULL; } + V3 = TopoDS::Vertex(anPnt); -// timer1.Stop(); -// timer1.Show(); - -// MESSAGE("--------------------------- GetShapesOnPlane phase 4 takes:"); -// timer1.Reset(); -// timer1.Start(); - - // Fill sequence of objects - TopTools_IndexedMapOfShape anIndices; - TopExp::MapShapes(aShape, anIndices); - - Handle(GEOM_Object) anObj; - Handle(TColStd_HArray1OfInteger) anArray; - Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; - TCollection_AsciiString anAsciiList, anEntry; - - TopTools_ListIteratorOfListOfShape itSub (listSS); - for (int index = 1; itSub.More(); itSub.Next(), ++index) { - int id = anIndices.FindIndex(itSub.Value()); - anArray = new TColStd_HArray1OfInteger(1,1); - anArray->SetValue(1, id); - anObj = GetEngine()->AddSubShape(theShape, anArray); - aSeq->Append(anObj); + if(V3.IsNull()) { + SetErrorCode("Bad vertex given for the plane location"); + return NULL; + } + gp_Pnt aLoc = BRep_Tool::Pnt(V3); + gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2)); - // for python command - TDF_Tool::Entry(anObj->GetEntry(), anEntry); - anAsciiList += anEntry; - anAsciiList += ","; + if (aVec.Magnitude() < Precision::Confusion()) { + SetErrorCode("Vector with null magnitude given"); + return NULL; } + Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec); + + if ( aPlane.IsNull() ) + return NULL; -// timer1.Stop(); -// timer1.Show(); + // Find objects + TCollection_AsciiString anAsciiList; + Handle(TColStd_HSequenceOfTransient) aSeq; + aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList ); + if ( aSeq.IsNull() || aSeq->Length() == 0 ) + return NULL; -// MESSAGE("--------------------------- GetShapesOnPlane phase 5 takes:"); -// timer1.Reset(); -// timer1.Start(); - // Make a Python command - anAsciiList.Trunc(anAsciiList.Length() - 1); + Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 )); Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString() - << "] = geompy.GetShapesOnPlane(" << theShape << ", " - << theShapeType << ", " << theAx1 << ", " << theState << ")"; + << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", " + << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")"; SetErrorCode(OK); return aSeq; @@ -1140,110 +2430,100 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCyli if (aShape.IsNull() || anAxis.IsNull()) return NULL; TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); - if (aShapeType != TopAbs_VERTEX && - aShapeType != TopAbs_EDGE && - aShapeType != TopAbs_FACE && - aShapeType != TopAbs_SOLID) { - SetErrorCode("Only solids, vertices, edges or faces can be found by this method"); + if ( !checkTypeShapesOn( aShapeType )) return NULL; - } - //Axis of the cylinder - if (anAxis.ShapeType() != TopAbs_EDGE) { - SetErrorCode("Not an edge given for the axis"); - return NULL; - } - TopoDS_Edge anEdge = TopoDS::Edge(anAxis); - TopoDS_Vertex V1, V2; - TopExp::Vertices(anEdge, V1, V2, Standard_True); - if (V1.IsNull() || V2.IsNull()) { - SetErrorCode("Bad edge given for the axis"); + // Create a cylinder surface + Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius ); + if ( aCylinder.IsNull() ) return NULL; - } - gp_Pnt aLoc = BRep_Tool::Pnt(V1); - gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2)); - if (aVec.Magnitude() < Precision::Confusion()) { - SetErrorCode("Vector with null magnitude given"); + + // Find objects + TCollection_AsciiString anAsciiList; + Handle(TColStd_HSequenceOfTransient) aSeq; + aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList ); + if ( aSeq.IsNull() || aSeq->Length() == 0 ) return NULL; - } - gp_Ax3 anAx3 (aLoc, aVec); - Handle(Geom_CylindricalSurface) aCylinder = - new Geom_CylindricalSurface(anAx3, theRadius); + // Make a Python command - // Check presence of triangulation, build if need - if (!CheckTriangulation(aShape)) - return NULL; + Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 )); + Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); - // Call algo - GEOMAlgo_FinderShapeOn1 aFinder; - Standard_Real aTol = 0.0001; // default value + GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString() + << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType + << ", " << theAxis << ", " << theRadius << ", " << theState << ")"; - aFinder.SetShape(aShape); - aFinder.SetTolerance(aTol); - aFinder.SetSurface(aCylinder); - aFinder.SetShapeType(aShapeType); - aFinder.SetState(theState); + SetErrorCode(OK); + return aSeq; +} - aFinder.SetNbPntsMin(3); - aFinder.SetNbPntsMax(100); +//============================================================================= +/*! + * GetShapesOnCylinderWithLocation + */ +//============================================================================= +Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocation + (const Handle(GEOM_Object)& theShape, + const Standard_Integer theShapeType, + const Handle(GEOM_Object)& theAxis, + const Handle(GEOM_Object)& thePnt, + const Standard_Real theRadius, + const GEOMAlgo_State theState) +{ + SetErrorCode(KO); - aFinder.Perform(); + if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL; - // Interprete results - Standard_Integer iErr = aFinder.ErrorStatus(); - // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx - if (iErr) { - MESSAGE(" iErr : " << iErr); - TCollection_AsciiString aMsg (" iErr : "); - aMsg += TCollection_AsciiString(iErr); - SetErrorCode(aMsg); - return NULL; - } - Standard_Integer iWrn = aFinder.WarningStatus(); - // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx - if (iWrn) { - MESSAGE(" *** iWrn : " << iWrn); - } + TopoDS_Shape aShape = theShape->GetValue(); + TopoDS_Shape anAxis = theAxis->GetValue(); + TopoDS_Shape aPnt = thePnt->GetValue(); - const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result + if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL; - if (listSS.Extent() < 1) { - SetErrorCode("Not a single sub-shape of the requested type found on the given cylinder"); + if (aPnt.ShapeType() != TopAbs_VERTEX ) + { + SetErrorCode("Bottom location point must be vertex"); return NULL; } - // Fill sequence of objects - TopTools_IndexedMapOfShape anIndices; - TopExp::MapShapes(aShape, anIndices); - - Handle(GEOM_Object) anObj; - Handle(TColStd_HArray1OfInteger) anArray; - Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; - TCollection_AsciiString anAsciiList, anEntry; + TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); + if ( !checkTypeShapesOn( aShapeType )) + return NULL; - TopTools_ListIteratorOfListOfShape itSub (listSS); - for (int index = 1; itSub.More(); itSub.Next(), ++index) { - int id = anIndices.FindIndex(itSub.Value()); - anArray = new TColStd_HArray1OfInteger(1,1); - anArray->SetValue(1, id); - anObj = GetEngine()->AddSubShape(theShape, anArray); - aSeq->Append(anObj); + // Create a cylinder surface + Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius ); + if ( aCylinder.IsNull() ) + return NULL; - // for python command - TDF_Tool::Entry(anObj->GetEntry(), anEntry); - anAsciiList += anEntry; - anAsciiList += ","; + // translate the surface + Handle(Geom_CylindricalSurface) aCylSurface = + Handle(Geom_CylindricalSurface)::DownCast( aCylinder ); + if ( aCylSurface.IsNull() ) + { + SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface"); + return NULL; } - + gp_Pnt fromLoc = aCylSurface->Cylinder().Location(); + gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt )); + aCylinder->Translate( fromLoc, toLoc ); + + // Find objects + TCollection_AsciiString anAsciiList; + Handle(TColStd_HSequenceOfTransient) aSeq; + aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList ); + if ( aSeq.IsNull() || aSeq->Length() == 0 ) + return NULL; + // Make a Python command - anAsciiList.Trunc(anAsciiList.Length() - 1); + Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 )); Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); - GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString() - << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << theShapeType - << ", " << theAxis << ", " << theRadius << ", " << theState << ")"; + GEOM::TPythonDump(aFunction) + << "[" << anAsciiList.ToCString() + << "] = geompy.GetShapesOnCylinderWithLocation(" << theShape << ", " << aShapeType << ", " + << theAxis << ", " << thePnt << ", " << theRadius << ", " << theState << ")"; SetErrorCode(OK); return aSeq; @@ -1271,13 +2551,8 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphe if (aShape.IsNull() || aCenter.IsNull()) return NULL; TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); - if (aShapeType != TopAbs_VERTEX && - aShapeType != TopAbs_EDGE && - aShapeType != TopAbs_FACE && - aShapeType != TopAbs_SOLID) { - SetErrorCode("Only solids, vertices, edges or faces can be found by this method"); + if ( !checkTypeShapesOn( aShapeType )) return NULL; - } // Center of the sphere if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL; @@ -1287,83 +2562,26 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphe Handle(Geom_SphericalSurface) aSphere = new Geom_SphericalSurface(anAx3, theRadius); - // Check presence of triangulation, build if need - if (!CheckTriangulation(aShape)) - return NULL; - - // Call algo - GEOMAlgo_FinderShapeOn1 aFinder; - Standard_Real aTol = 0.0001; // default value - - aFinder.SetShape(aShape); - aFinder.SetTolerance(aTol); - aFinder.SetSurface(aSphere); - aFinder.SetShapeType(aShapeType); - aFinder.SetState(theState); - - aFinder.SetNbPntsMin(3); - aFinder.SetNbPntsMax(100); - - aFinder.Perform(); - - // Interprete results - Standard_Integer iErr = aFinder.ErrorStatus(); - // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx - if (iErr) { - MESSAGE(" iErr : " << iErr); - TCollection_AsciiString aMsg (" iErr : "); - aMsg += TCollection_AsciiString(iErr); - SetErrorCode(aMsg); - return NULL; - } - Standard_Integer iWrn = aFinder.WarningStatus(); - // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx - if (iWrn) { - MESSAGE(" *** iWrn : " << iWrn); - } - - const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result - - if (listSS.Extent() < 1) { - SetErrorCode("Not a single sub-shape of the requested type found on the given sphere"); + // Find objects + TCollection_AsciiString anAsciiList; + Handle(TColStd_HSequenceOfTransient) aSeq; + aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList ); + if ( aSeq.IsNull() || aSeq->Length() == 0 ) return NULL; - } - - // Fill sequence of objects - TopTools_IndexedMapOfShape anIndices; - TopExp::MapShapes(aShape, anIndices); - - Handle(GEOM_Object) anObj; - Handle(TColStd_HArray1OfInteger) anArray; - Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; - TCollection_AsciiString anAsciiList, anEntry; - - TopTools_ListIteratorOfListOfShape itSub (listSS); - for (int index = 1; itSub.More(); itSub.Next(), ++index) { - int id = anIndices.FindIndex(itSub.Value()); - anArray = new TColStd_HArray1OfInteger(1,1); - anArray->SetValue(1, id); - anObj = GetEngine()->AddSubShape(theShape, anArray); - aSeq->Append(anObj); - // for python command - TDF_Tool::Entry(anObj->GetEntry(), anEntry); - anAsciiList += anEntry; - anAsciiList += ","; - } - // Make a Python command - anAsciiList.Trunc(anAsciiList.Length() - 1); + Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 )); Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString() - << "] = geompy.GetShapesOnSphere(" << theShape << ", " << theShapeType + << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType << ", " << theCenter << ", " << theRadius << ", " << theState << ")"; SetErrorCode(OK); return aSeq; } + //============================================================================= /*! * GetShapesOnPlaneIDs @@ -1385,101 +2603,92 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneI if (aShape.IsNull() || anAx1.IsNull()) return NULL; TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); - if (aShapeType != TopAbs_VERTEX && - aShapeType != TopAbs_EDGE && - aShapeType != TopAbs_FACE && - aShapeType != TopAbs_SOLID) { - SetErrorCode("Only solids, vertices, edges or faces can be found by this method"); + if ( !checkTypeShapesOn( aShapeType )) return NULL; - } // Create plane - if (anAx1.ShapeType() != TopAbs_EDGE) return NULL; - TopoDS_Edge anEdge = TopoDS::Edge(anAx1); - TopoDS_Vertex V1, V2; - TopExp::Vertices(anEdge, V1, V2, Standard_True); - if (V1.IsNull() || V2.IsNull()) { - SetErrorCode("Bad edge given for the plane normal vector"); - return NULL; - } - gp_Pnt aLoc = BRep_Tool::Pnt(V1); - gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2)); - if (aVec.Magnitude() < Precision::Confusion()) { - SetErrorCode("Vector with null magnitude given"); + Handle(Geom_Surface) aPlane = makePlane( anAx1 ); + if ( aPlane.IsNull() ) return NULL; - } - Handle(Geom_Plane) aPlane = new Geom_Plane(aLoc, aVec); + // Find object IDs + Handle(TColStd_HSequenceOfInteger) aSeq; + aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState ); - // Check presence of triangulation, build if need - if (!CheckTriangulation(aShape)) - return NULL; + // The GetShapesOnPlaneIDs() doesn't change object so no new function is required. + Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction(); - // Call algo - GEOMAlgo_FinderShapeOn1 aFinder; - Standard_Real aTol = 0.0001; // default value + // Make a Python command + GEOM::TPythonDump(aFunction, /*append=*/true) + << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs" + << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")"; + + SetErrorCode(OK); + return aSeq; +} + +//============================================================================= +/*! + * GetShapesOnPlaneWithLocationIDs + */ +//============================================================================= +Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs + (const Handle(GEOM_Object)& theShape, + const Standard_Integer theShapeType, + const Handle(GEOM_Object)& theAx1, + const Handle(GEOM_Object)& thePnt, + const GEOMAlgo_State theState) +{ + SetErrorCode(KO); - aFinder.SetShape(aShape); - aFinder.SetTolerance(aTol); - aFinder.SetSurface(aPlane); - aFinder.SetShapeType(aShapeType); - aFinder.SetState(theState); + if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL; - aFinder.SetNbPntsMin(3); - aFinder.SetNbPntsMax(100); + TopoDS_Shape aShape = theShape->GetValue(); + TopoDS_Shape anAx1 = theAx1->GetValue(); + TopoDS_Shape anPnt = thePnt->GetValue(); - aFinder.Perform(); + if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL; - // Interprete results - Standard_Integer iErr = aFinder.ErrorStatus(); - // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx - if (iErr) { - MESSAGE(" iErr : " << iErr); - TCollection_AsciiString aMsg (" iErr : "); - aMsg += TCollection_AsciiString(iErr); - SetErrorCode(aMsg); + TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); + if ( !checkTypeShapesOn( aShapeType )) + return NULL; + + // Create plane + if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL; + TopoDS_Edge anEdge = TopoDS::Edge(anAx1); + TopoDS_Vertex V1, V2, V3; + TopExp::Vertices(anEdge, V1, V2, Standard_True); + if (V1.IsNull() || V2.IsNull()) { + SetErrorCode("Bad edge given for the plane normal vector"); return NULL; } - Standard_Integer iWrn = aFinder.WarningStatus(); - // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx - if (iWrn) { - MESSAGE(" *** iWrn : " << iWrn); + V3 = TopoDS::Vertex(anPnt); + if(V3.IsNull()) { + SetErrorCode("Bad vertex given for the plane location"); + return NULL; } - - const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result - - if (listSS.Extent() < 1) { - SetErrorCode("Not a single sub-shape of the requested type found on the given plane"); + gp_Pnt aLoc = BRep_Tool::Pnt(V3); + gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2)); + if (aVec.Magnitude() < Precision::Confusion()) { + SetErrorCode("Vector with null magnitude given"); return NULL; } - // Fill sequence of objects - TopTools_IndexedMapOfShape anIndices; - TopExp::MapShapes(aShape, anIndices); - - Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger; + Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec); + if ( aPlane.IsNull() ) + return NULL; - TopTools_ListIteratorOfListOfShape itSub (listSS); - for (int index = 1; itSub.More(); itSub.Next(), ++index) { - int id = anIndices.FindIndex(itSub.Value()); - aSeq->Append(id); - } + // Find object IDs + Handle(TColStd_HSequenceOfInteger) aSeq; + aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState ); - // The GetShapesOnPlane() doesn't change object so no new function is required. - Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); + // The GetShapesOnPlaneIDs() doesn't change object so no new function is required. + Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction(); // Make a Python command - TCollection_AsciiString anEntry, aDescr - ("\nlistShapesOnPlane = IShapesOperations.GetShapesOnPlaneIDs("); - TDF_Tool::Entry(theShape->GetEntry(), anEntry); - aDescr += anEntry + TCollection_AsciiString(theShapeType) + ","; - TDF_Tool::Entry(theAx1->GetEntry(), anEntry); - aDescr += anEntry + ","; - aDescr += TCollection_AsciiString(theState) + ")"; - - TCollection_AsciiString anOldDescr = aFunction->GetDescription(); - anOldDescr += aDescr; - aFunction->SetDescription(anOldDescr); + GEOM::TPythonDump(aFunction, /*append=*/true) + << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs" + << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", " << theState << ")"; SetErrorCode(OK); return aSeq; @@ -1507,107 +2716,94 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylind if (aShape.IsNull() || anAxis.IsNull()) return NULL; TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); - if (aShapeType != TopAbs_VERTEX && - aShapeType != TopAbs_EDGE && - aShapeType != TopAbs_FACE && - aShapeType != TopAbs_SOLID) { - SetErrorCode("Only solids, vertices, edges or faces can be found by this method"); + if ( !checkTypeShapesOn( aShapeType )) return NULL; - } - //Axis of the cylinder - if (anAxis.ShapeType() != TopAbs_EDGE) { - SetErrorCode("Not an edge given for the axis"); - return NULL; - } - TopoDS_Edge anEdge = TopoDS::Edge(anAxis); - TopoDS_Vertex V1, V2; - TopExp::Vertices(anEdge, V1, V2, Standard_True); - if (V1.IsNull() || V2.IsNull()) { - SetErrorCode("Bad edge given for the axis"); - return NULL; - } - gp_Pnt aLoc = BRep_Tool::Pnt(V1); - gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2)); - if (aVec.Magnitude() < Precision::Confusion()) { - SetErrorCode("Vector with null magnitude given"); + // Create a cylinder surface + Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius ); + if ( aCylinder.IsNull() ) return NULL; - } - gp_Ax3 anAx3 (aLoc, aVec); - Handle(Geom_CylindricalSurface) aCylinder = - new Geom_CylindricalSurface(anAx3, theRadius); + // Find object IDs + Handle(TColStd_HSequenceOfInteger) aSeq; + aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState ); - // Check presence of triangulation, build if need - if (!CheckTriangulation(aShape)) - return NULL; + // The GetShapesOnCylinder() doesn't change object so no new function is required. + Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction(); - // Call algo - GEOMAlgo_FinderShapeOn1 aFinder; - Standard_Real aTol = 0.0001; // default value + // Make a Python command + GEOM::TPythonDump(aFunction, /*append=*/true) + << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs" + << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", " + << theRadius << ", " << theState << ")"; - aFinder.SetShape(aShape); - aFinder.SetTolerance(aTol); - aFinder.SetSurface(aCylinder); - aFinder.SetShapeType(aShapeType); - aFinder.SetState(theState); + SetErrorCode(OK); + return aSeq; +} - aFinder.SetNbPntsMin(3); - aFinder.SetNbPntsMax(100); +//============================================================================= +/*! + * GetShapesOnCylinderWithLocationIDs + */ +//============================================================================= +Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderWithLocationIDs + (const Handle(GEOM_Object)& theShape, + const Standard_Integer theShapeType, + const Handle(GEOM_Object)& theAxis, + const Handle(GEOM_Object)& thePnt, + const Standard_Real theRadius, + const GEOMAlgo_State theState) +{ + SetErrorCode(KO); - aFinder.Perform(); + if (theShape.IsNull() || theAxis.IsNull() || thePnt.IsNull()) return NULL; - // Interprete results - Standard_Integer iErr = aFinder.ErrorStatus(); - // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx - if (iErr) { - MESSAGE(" iErr : " << iErr); - TCollection_AsciiString aMsg (" iErr : "); - aMsg += TCollection_AsciiString(iErr); - SetErrorCode(aMsg); - return NULL; - } - Standard_Integer iWrn = aFinder.WarningStatus(); - // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx - if (iWrn) { - MESSAGE(" *** iWrn : " << iWrn); - } + TopoDS_Shape aShape = theShape->GetValue(); + TopoDS_Shape anAxis = theAxis->GetValue(); + TopoDS_Shape aPnt = thePnt->GetValue(); - const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result + if (aShape.IsNull() || anAxis.IsNull() || aPnt.IsNull()) return NULL; - if (listSS.Extent() < 1) { - SetErrorCode("Not a single sub-shape of the requested type found on the given cylinder"); + if (aPnt.ShapeType() != TopAbs_VERTEX ) + { + SetErrorCode("Bottom location point must be vertex"); return NULL; } - // Fill sequence of objects - TopTools_IndexedMapOfShape anIndices; - TopExp::MapShapes(aShape, anIndices); + TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); + if ( !checkTypeShapesOn( aShapeType )) + return NULL; - Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger; + // Create a cylinder surface + Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius ); + if ( aCylinder.IsNull() ) + return NULL; - TopTools_ListIteratorOfListOfShape itSub (listSS); - for (int index = 1; itSub.More(); itSub.Next(), ++index) { - int id = anIndices.FindIndex(itSub.Value()); - aSeq->Append(id); + // translate the surface + Handle(Geom_CylindricalSurface) aCylSurface = + Handle(Geom_CylindricalSurface)::DownCast( aCylinder ); + if ( aCylSurface.IsNull() ) + { + SetErrorCode("Unexpected surface type instead of Geom_CylindricalSurface"); + return NULL; } - + gp_Pnt fromLoc = aCylSurface->Cylinder().Location(); + gp_Pnt toLoc = BRep_Tool::Pnt( TopoDS::Vertex( aPnt )); + aCylinder->Translate( fromLoc, toLoc ); + + // Find object IDs + Handle(TColStd_HSequenceOfInteger) aSeq; + aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState ); + // The GetShapesOnCylinder() doesn't change object so no new function is required. - Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); + Handle(GEOM_Function) aFunction = + GEOM::GetCreatedLast(theShape, GEOM::GetCreatedLast(thePnt,theAxis))->GetLastFunction(); // Make a Python command - TCollection_AsciiString anEntry, aDescr - ("\nlistShapesOnCylinder = IShapesOperations.GetShapesOnCylinderIDs("); - TDF_Tool::Entry(theShape->GetEntry(), anEntry); - aDescr += anEntry + TCollection_AsciiString(theShapeType) + ","; - TDF_Tool::Entry(theAxis->GetEntry(), anEntry); - aDescr += anEntry + ","; - aDescr += TCollection_AsciiString(theRadius) + ","; - aDescr += TCollection_AsciiString(theState) + ")"; - - TCollection_AsciiString anOldDescr = aFunction->GetDescription(); - anOldDescr += aDescr; - aFunction->SetDescription(anOldDescr); + GEOM::TPythonDump(aFunction, /*append=*/true) + << "listShapesOnCylinder = geompy.GetShapesOnCylinderWithLocationIDs" + << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", " + << thePnt << ", " << theRadius << ", " << theState << ")"; SetErrorCode(OK); return aSeq; @@ -1635,13 +2831,8 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphere if (aShape.IsNull() || aCenter.IsNull()) return NULL; TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); - if (aShapeType != TopAbs_VERTEX && - aShapeType != TopAbs_EDGE && - aShapeType != TopAbs_FACE && - aShapeType != TopAbs_SOLID) { - SetErrorCode("Only solids, vertices, edges or faces can be found by this method"); + if ( !checkTypeShapesOn( aShapeType )) return NULL; - } // Center of the sphere if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL; @@ -1651,21 +2842,107 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphere Handle(Geom_SphericalSurface) aSphere = new Geom_SphericalSurface(anAx3, theRadius); - // Check presence of triangulation, build if need - if (!CheckTriangulation(aShape)) + // Find object IDs + Handle(TColStd_HSequenceOfInteger) aSeq; + aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState ); + + // The GetShapesOnSphere() doesn't change object so no new function is required. + Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction(); + + // Make a Python command + GEOM::TPythonDump(aFunction, /*append=*/true) + << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs" + << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", " + << theRadius << ", " << theState << ")"; + + SetErrorCode(OK); + return aSeq; +} + +//======================================================================= +//function : getShapesOnQuadrangleIDs + /*! + * \brief Find IDs of subshapes complying with given status about quadrangle + * \param theShape - the shape to explore + * \param theShapeType - type of subshape of theShape + * \param theTopLeftPoint - top left quadrangle corner + * \param theTopRigthPoint - top right quadrangle corner + * \param theBottomLeftPoint - bottom left quadrangle corner + * \param theBottomRigthPoint - bottom right quadrangle corner + * \param theState - required state + * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes + */ +//======================================================================= +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)& theBottomLeftPoint, + const Handle(GEOM_Object)& theBottomRigthPoint, + const GEOMAlgo_State theState) +{ + SetErrorCode(KO); + + if ( theShape.IsNull() || + theTopLeftPoint.IsNull() || + theTopRigthPoint.IsNull() || + theBottomLeftPoint.IsNull() || + theBottomRigthPoint.IsNull() ) + return NULL; + + TopoDS_Shape aShape = theShape->GetValue(); + TopoDS_Shape aTL = theTopLeftPoint->GetValue(); + TopoDS_Shape aTR = theTopRigthPoint->GetValue(); + TopoDS_Shape aBL = theBottomLeftPoint->GetValue(); + TopoDS_Shape aBR = theBottomRigthPoint->GetValue(); + + if (aShape.IsNull() || + aTL.IsNull() || + aTR.IsNull() || + aBL.IsNull() || + aBR.IsNull() || + aTL.ShapeType() != TopAbs_VERTEX || + aTR.ShapeType() != TopAbs_VERTEX || + aBL.ShapeType() != TopAbs_VERTEX || + aBR.ShapeType() != TopAbs_VERTEX ) + return NULL; + + TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType); + if ( !checkTypeShapesOn( aShapeType )) return NULL; + Handle(TColStd_HSequenceOfInteger) aSeqOfIDs; + + // Check presence of triangulation, build if need + if (!CheckTriangulation(aShape)) { + SetErrorCode("Cannot build triangulation on the shape"); + return aSeqOfIDs; + } + // Call algo - GEOMAlgo_FinderShapeOn1 aFinder; + gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL)); + gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR)); + 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 ); Standard_Real aTol = 0.0001; // default value aFinder.SetShape(aShape); aFinder.SetTolerance(aTol); - aFinder.SetSurface(aSphere); + //aFinder.SetSurface(theSurface); aFinder.SetShapeType(aShapeType); 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 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); aFinder.Perform(); @@ -1678,7 +2955,7 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphere TCollection_AsciiString aMsg (" iErr : "); aMsg += TCollection_AsciiString(iErr); SetErrorCode(aMsg); - return NULL; + return aSeqOfIDs; } Standard_Integer iWrn = aFinder.WarningStatus(); // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx @@ -1686,54 +2963,380 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphere MESSAGE(" *** iWrn : " << iWrn); } - const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result + const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result + + if (listSS.Extent() < 1) { + //SetErrorCode("Not a single sub-shape of the requested type found on the given surface"); + SetErrorCode(NOT_FOUND_ANY); // NPAL18017 + return aSeqOfIDs; + } + + // Fill sequence of object IDs + aSeqOfIDs = new TColStd_HSequenceOfInteger; + + TopTools_IndexedMapOfShape anIndices; + TopExp::MapShapes(aShape, anIndices); + + TopTools_ListIteratorOfListOfShape itSub (listSS); + for (int index = 1; itSub.More(); itSub.Next(), ++index) { + int id = anIndices.FindIndex(itSub.Value()); + aSeqOfIDs->Append(id); + } + return aSeqOfIDs; +} + +//======================================================================= +//function : GetShapesOnQuadrangle + /*! + * \brief Find subshapes complying with given status about quadrangle + * \param theShape - the shape to explore + * \param theShapeType - type of subshape of theShape + * \param theTopLeftPoint - top left quadrangle corner + * \param theTopRigthPoint - top right quadrangle corner + * \param theBottomLeftPoint - bottom left quadrangle corner + * \param theBottomRigthPoint - bottom right quadrangle corner + * \param theState - required state + * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes + */ +//======================================================================= +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)& theBottomLeftPoint, + const Handle(GEOM_Object)& theBottomRigthPoint, + const GEOMAlgo_State theState) +{ + // Find indices + Handle(TColStd_HSequenceOfInteger) aSeqOfIDs = + getShapesOnQuadrangleIDs( theShape, + theShapeType, + theTopLeftPoint, + theTopRigthPoint, + theBottomLeftPoint, + theBottomRigthPoint, + theState); + if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() ) + return NULL; + + // Find objects by indices + TCollection_AsciiString anAsciiList; + Handle(TColStd_HSequenceOfTransient) aSeq; + aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList ); + if ( aSeq.IsNull() || aSeq->IsEmpty() ) + 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.GetShapesOnQuadrangle(" + << theShape << ", " + << TopAbs_ShapeEnum(theShapeType) << ", " + << theTopLeftPoint << ", " + << theTopRigthPoint << ", " + << theBottomLeftPoint << ", " + << theBottomRigthPoint << ", " + << theState << ")"; + + SetErrorCode(OK); + return aSeq; +} + +//======================================================================= +//function : GetShapesOnQuadrangleIDs + /*! + * \brief Find IDs of subshapes complying with given status about quadrangle + * \param theShape - the shape to explore + * \param theShapeType - type of subshape of theShape + * \param theTopLeftPoint - top left quadrangle corner + * \param theTopRigthPoint - top right quadrangle corner + * \param theBottomLeftPoint - bottom left quadrangle corner + * \param theBottomRigthPoint - bottom right quadrangle corner + * \param theState - required state + * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes + */ +//======================================================================= +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)& theBottomLeftPoint, + const Handle(GEOM_Object)& theBottomRigthPoint, + const GEOMAlgo_State theState) +{ + // Find indices + Handle(TColStd_HSequenceOfInteger) aSeqOfIDs = + getShapesOnQuadrangleIDs( theShape, + theShapeType, + theTopLeftPoint, + theTopRigthPoint, + theBottomLeftPoint, + theBottomRigthPoint, + theState); + if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() ) + return NULL; + + // 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); + lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint); + Handle(GEOM_Function) aFunction = lastObj->GetLastFunction(); + + GEOM::TPythonDump(aFunction, /*append=*/true) + << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs(" + << theShape << ", " + << TopAbs_ShapeEnum(theShapeType) << ", " + << theTopLeftPoint << ", " + << theTopRigthPoint << ", " + << theBottomLeftPoint << ", " + << theBottomRigthPoint << ", " + << theState << ")"; + + SetErrorCode(OK); + return aSeqOfIDs; +} + +//============================================================================= +/*! + * GetInPlaceOfShape + */ +//============================================================================= +static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction, + const TopTools_IndexedMapOfShape& theWhereIndices, + const TopoDS_Shape& theWhat, + TColStd_ListOfInteger& theModifiedList) +{ + 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; + } + + // try to find in history + TDF_Label aHistoryLabel = theWhereFunction->GetHistoryEntry(Standard_False); + + // search in history for all argument shapes + Standard_Boolean isFound = Standard_False; + Standard_Boolean isGood = Standard_False; + + TDF_LabelSequence aLabelSeq; + theWhereFunction->GetDependency(aLabelSeq); + Standard_Integer nbArg = aLabelSeq.Length(); + + for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) { + + 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; +} - if (listSS.Extent() < 1) { - SetErrorCode("Not a single sub-shape of the requested type found on the given sphere"); - return NULL; - } +namespace { - // Fill sequence of objects - TopTools_IndexedMapOfShape anIndices; - TopExp::MapShapes(aShape, anIndices); + //================================================================================ + /*! + * \brief Return normal to face at extrema point + */ + //================================================================================ - Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger; + 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 ); - TopTools_ListIteratorOfListOfShape itSub (listSS); - for (int index = 1; itSub.More(); itSub.Next(), ++index) { - int id = anIndices.FindIndex(itSub.Value()); - aSeq->Append(id); + return du ^ dv; + + } catch (Standard_Failure ) { + } + return defaultNorm; } - - // The GetShapesOnSphere() doesn't change object so no new function is required. - Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); - // Make a Python command - TCollection_AsciiString anEntry, aDescr - ("\nlistShapesOnSphere = IShapesOperations.GetShapesOnSphereIDs("); - TDF_Tool::Entry(theShape->GetEntry(), anEntry); - aDescr += anEntry + TCollection_AsciiString(theShapeType) + ","; - TDF_Tool::Entry(theCenter->GetEntry(), anEntry); - aDescr += anEntry + ","; - aDescr += TCollection_AsciiString(theRadius) + ","; - aDescr += TCollection_AsciiString(theState) + ")"; - - TCollection_AsciiString anOldDescr = aFunction->GetDescription(); - anOldDescr += aDescr; - aFunction->SetDescription(anOldDescr); + //================================================================================ + /*! + * \brief Return type of shape for explode. In case of compound it will be a type of sub shape. + */ + //================================================================================ - SetErrorCode(OK); - return aSeq; + TopAbs_ShapeEnum GetTypeOfSimplePart (const TopoDS_Shape& theShape) + { + TopAbs_ShapeEnum aType = theShape.ShapeType(); + if (aType == TopAbs_VERTEX) return TopAbs_VERTEX; + else if (aType == TopAbs_EDGE || aType == TopAbs_WIRE) return TopAbs_EDGE; + else if (aType == TopAbs_FACE || aType == TopAbs_SHELL) return TopAbs_FACE; + else if (aType == TopAbs_SOLID || aType == TopAbs_COMPSOLID) return TopAbs_SOLID; + else if (aType == TopAbs_COMPOUND) { + // Only the iType of the first shape in the compound is taken into account + TopoDS_Iterator It (theShape, Standard_False, Standard_False); + if (It.More()) { + return GetTypeOfSimplePart(It.Value()); + } + } + return TopAbs_SHAPE; + } } //============================================================================= /*! - * GetInPlace + * case GetInPlace: + * default: */ //============================================================================= -Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace - (Handle(GEOM_Object) theShapeWhere, - Handle(GEOM_Object) theShapeWhat) +Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere, + Handle(GEOM_Object) theShapeWhat) { SetErrorCode(KO); @@ -1741,106 +3344,282 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace TopoDS_Shape aWhere = theShapeWhere->GetValue(); TopoDS_Shape aWhat = theShapeWhat->GetValue(); + TopoDS_Shape aPntShape; + TopoDS_Vertex aVertex; - if (aWhere.IsNull() || aWhat.IsNull()) return NULL; - - //Fill array of indices - Handle(TColStd_HArray1OfInteger) aModifiedArray; + if (aWhere.IsNull() || aWhat.IsNull()) { + SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null."); + return NULL; + } Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction(); + if (aWhereFunction.IsNull()) { + SetErrorCode("Error: aWhereFunction is Null."); + return NULL; + } TopTools_IndexedMapOfShape aWhereIndices; TopExp::MapShapes(aWhere, aWhereIndices); - if (aWhereIndices.Contains(aWhat)) { - - // entity was not changed by the operation - Standard_Integer aWhatIndex = aWhereIndices.FindIndex(aWhat); - aModifiedArray = new TColStd_HArray1OfInteger(1,1); - aModifiedArray->SetValue(1, aWhatIndex); + 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 = GetTypeOfSimplePart(aWhat); + if (iType == TopAbs_SHAPE) { + SetErrorCode("Error: An attempt to extract a shape of not supported type."); + return NULL; + } - } else { + 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(); + } + } - TDF_Label aHistoryLabel = aWhereFunction->GetHistoryEntry(Standard_False); - if (aHistoryLabel.IsNull()) { - SetErrorCode("Modifications history does not exist for the shape under consideration."); - return NULL; + // 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 = 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; + } } + //if ( fabs( aWhat_Mass - aWhere_Mass ) <= Tol_Mass ) + //break; + } + + if (aModifiedList.Extent() == 0) { // Not found any Results + SetErrorCode(NOT_FOUND_ANY); + return NULL; + } + + 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); + if (aResult.IsNull()) { + SetErrorCode("Error in algorithm: result found, but cannot be returned."); + return NULL; + } - // search in history for all argument shapes - Standard_Boolean isFound = Standard_False; + if (aModifiedArray->Length() > 1) { + //Set a GROUP type + aResult->SetType(GEOM_GROUP); - TDF_LabelSequence aLabelSeq; - aWhereFunction->GetDependency(aLabelSeq); - Standard_Integer nbArg = aLabelSeq.Length(); + //Set a sub shape type + TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1)); + TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType(); - for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) { + TDF_Label aFreeLabel = aResult->GetFreeLabel(); + TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType); + } - TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg); + //Make a Python command + Handle(GEOM_Function) aFunction = aResult->GetFunction(1); - Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel); - TopoDS_Shape anArgumentShape = anArgumentObject->GetValue(); + GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace(" + << theShapeWhere << ", " << theShapeWhat << ")"; - TopTools_IndexedMapOfShape anArgumentIndices; - TopExp::MapShapes(anArgumentShape, anArgumentIndices); + SetErrorCode(OK); + return aResult; +} - if (anArgumentIndices.Contains(aWhat)) { - isFound = Standard_True; - Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(aWhat); +//======================================================================= +//function : GetInPlaceByHistory +//purpose : +//======================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory + (Handle(GEOM_Object) theShapeWhere, + Handle(GEOM_Object) theShapeWhat) +{ + SetErrorCode(KO); - // Find corresponding label in history - TDF_Label anArgumentHistoryLabel = - aWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False); - if (anArgumentHistoryLabel.IsNull()) { - // Lost History of operation argument. Possibly, all its entities was removed. - SetErrorCode(OK); - return NULL; - } + if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL; - TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False); - if (aWhatHistoryLabel.IsNull()) { - // Removed entity - SetErrorCode(OK); - return NULL; - } + TopoDS_Shape aWhere = theShapeWhere->GetValue(); + TopoDS_Shape aWhat = theShapeWhat->GetValue(); - Handle(TDataStd_IntegerArray) anIntegerArray; - if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) { - SetErrorCode("Error: Empty modifications history for the sought shape."); - return NULL; - } + if (aWhere.IsNull() || aWhat.IsNull()) return NULL; - aModifiedArray = anIntegerArray->Array(); - if (aModifiedArray->Length() == 0) { - SetErrorCode("Error: Empty modifications history for the sought shape."); - return NULL; - } - } - } + Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction(); + if (aWhereFunction.IsNull()) return NULL; - if (!isFound) { - SetErrorCode("The sought shape does not belong to any operation argument."); - return NULL; - } + //Fill array of indices + TopTools_IndexedMapOfShape aWhereIndices; + TopExp::MapShapes(aWhere, aWhereIndices); + + // process shape + TColStd_ListOfInteger aModifiedList; + bool isFound = GetInPlaceOfShape(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 = + 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 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) { //Set a GROUP type aResult->SetType(GEOM_GROUP); //Set a sub shape type + TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1)); + TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType(); + TDF_Label aFreeLabel = aResult->GetFreeLabel(); - TopAbs_ShapeEnum aShapeType = aWhat.ShapeType(); TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType); } //Make a Python command Handle(GEOM_Function) aFunction = aResult->GetFunction(1); - GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace(" + GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory(" << theShapeWhere << ", " << theShapeWhat << ")"; SetErrorCode(OK); @@ -1851,7 +3630,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace //function : SortShapes //purpose : //======================================================================= -void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL) +void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL, + const Standard_Boolean isOldSorting) { Standard_Integer MaxShapes = SL.Extent(); TopTools_Array1OfShape aShapes (1,MaxShapes); @@ -1870,37 +3650,88 @@ void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL) SL.Remove( it ); // == it.Next() aShapes(Index) = S; OrderInd.SetValue (Index, Index); - if (S.ShapeType() == TopAbs_VERTEX) - { + if (S.ShapeType() == TopAbs_VERTEX) { GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S )); Length.SetValue( Index, (Standard_Real) S.Orientation()); } - else - { - BRepGProp::LinearProperties (S, GPr); + else { + // BEGIN: fix for Mantis issue 0020842 + if (isOldSorting) { + BRepGProp::LinearProperties (S, GPr); + } + else { + if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) { + BRepGProp::LinearProperties (S, GPr); + } + else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) { + BRepGProp::SurfaceProperties(S, GPr); + } + else { + BRepGProp::VolumeProperties(S, GPr); + } + } + // END: fix for Mantis issue 0020842 GPoint = GPr.CentreOfMass(); - Length.SetValue( Index, GPr.Mass() ); + Length.SetValue(Index, GPr.Mass()); } MidXYZ.SetValue(Index, - GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9); + GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9); + //cout << Index << " L: " << Length(Index) << "CG: " << MidXYZ(Index) << endl; } + // Sorting Standard_Integer aTemp; Standard_Boolean exchange, Sort = Standard_True; + Standard_Real tol = Precision::Confusion(); while (Sort) { Sort = Standard_False; for (Index=1; Index < MaxShapes; Index++) { - if (MidXYZ(OrderInd(Index)) > MidXYZ(OrderInd(Index+1))) - exchange = Standard_True; - else if (MidXYZ(OrderInd(Index)) == MidXYZ(OrderInd(Index+1)) && - Length(OrderInd(Index)) > Length(OrderInd(Index+1)) ) - exchange = Standard_True; - else - exchange = Standard_False; + exchange = Standard_False; + Standard_Real dMidXYZ = MidXYZ(OrderInd(Index)) - MidXYZ(OrderInd(Index+1)); + Standard_Real dLength = Length(OrderInd(Index)) - Length(OrderInd(Index+1)); + if ( dMidXYZ >= tol ) { +// cout << "MidXYZ: " << MidXYZ(OrderInd(Index))<< " > " <= tol ) { +// cout << "Length: " << Length(OrderInd(Index))<< " > " <= tol ) { +// cout << "SquareExtent: " << box1.SquareExtent()<<" > "< val2; + if ((val1 - val2) >= tol) { + exchange = Standard_True; + } + //cout << "box: " << val1<<" > "<