X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGEOMImpl%2FGEOMImpl_IShapesOperations.cxx;h=bc1b8cbce2a85c4a26a261acd71b915cc0125ab2;hb=2fba9e59a7a545a4afecb4faff16614ab66e57da;hp=e916f423202d39dd4fb1c055c29e6a85cd6a8919;hpb=aab55c4f104405b4539e5a96f07f89bffb8201db;p=modules%2Fgeom.git diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx index e916f4232..bc1b8cbce 100644 --- a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx @@ -1,29 +1,28 @@ -// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2011 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 +// 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 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. +// 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 +// 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$ +// 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 #include @@ -41,21 +40,27 @@ #include "GEOMImpl_IGlue.hxx" #include "GEOMImpl_Block6Explorer.hxx" +#include "GEOMImpl_IHealingOperations.hxx" + +#include #include "GEOM_Function.hxx" #include "GEOM_ISubShape.hxx" #include "GEOM_PythonDump.hxx" +#include "GEOMAlgo_ClsfBox.hxx" +#include "GEOMAlgo_ClsfSolid.hxx" +#include "GEOMAlgo_CoupleOfShapes.hxx" #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_GetInPlace.hxx" +#include "GEOMAlgo_GlueDetector.hxx" #include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx" -#include "GEOMAlgo_CoupleOfShapes.hxx" #include "GEOMAlgo_ListOfCoupleOfShapes.hxx" +#include + #include "utilities.h" #include "OpUtil.hxx" #include "Utils_ExceptHandlers.hxx" @@ -78,11 +83,12 @@ #include #include #include -#include #include #include #include +#include +#include #include #include #include @@ -91,13 +97,12 @@ #include #include #include -#include -#include -#include -#include #include -#include +#include #include +#include +#include +#include #include #include @@ -119,6 +124,8 @@ #include #include +#include +#include #include #include @@ -134,6 +141,8 @@ #include #include +#define STD_SORT_ALGO 1 + //============================================================================= /*! * constructor: @@ -188,7 +197,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge //Compute the Edge value try { -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 +#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { @@ -210,6 +219,67 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdge return anEdge; } +//============================================================================= +/*! + * MakeEdgeOnCurveByLength + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeOnCurveByLength + (Handle(GEOM_Object) theRefCurve, + const Standard_Real theLength, + Handle(GEOM_Object) theStartPoint) +{ + SetErrorCode(KO); + + if (theRefCurve.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_CURVE_LENGTH); + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) return NULL; + + GEOMImpl_IVector aPI (aFunction); + + Handle(GEOM_Function) aRef1 = theRefCurve->GetLastFunction(); + if (aRef1.IsNull()) return NULL; + aPI.SetPoint1(aRef1); + + if (!theStartPoint.IsNull()) { + Handle(GEOM_Function) aRef2 = theStartPoint->GetLastFunction(); + aPI.SetPoint2(aRef2); + } + + aPI.SetParameter(theLength); + + //Compute the Edge value + try { +#if OCC_VERSION_LARGE > 0x06010000 + OCC_CATCH_SIGNALS; +#endif + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Vector driver failed"); + return NULL; + } + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + return NULL; + } + + //Make a Python command + GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeOnCurveByLength(" + << theRefCurve << ", " << theLength << ", " << theStartPoint << ")"; + + SetErrorCode(OK); + return anEdge; +} + //============================================================================= /*! * MakeEdgeWire @@ -246,7 +316,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeWire //Compute the Edge value try { -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 +#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { @@ -267,7 +337,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeEdgeWire if ( theLinearTolerance == DEF_LIN_TOL ) GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire(" << theWire << ")"; - else + else GEOM::TPythonDump(aFunction) << anEdge << " = geompy.MakeEdgeWire(" << theWire << ", " << theLinearTolerance << ")"; } @@ -322,7 +392,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeWire //Compute the shape try { -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 +#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { @@ -387,8 +457,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) th aCI.SetIsPlanar(isPlanarWanted); //Compute the Face value + Standard_Boolean isWarning = Standard_False; try { -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 +#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { @@ -399,14 +470,20 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFace (Handle(GEOM_Object) th catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); - return NULL; + // to provide warning + if (!aFunction->GetValue().IsNull()) { + isWarning = Standard_True; + } else { + return NULL; + } } //Make a Python command GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeFace(" << theWire << ", " << (int)isPlanarWanted << ")"; - SetErrorCode(OK); + // to provide warning + if (!isWarning) SetErrorCode(OK); return aFace; } @@ -451,8 +528,9 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires aCI.SetIsPlanar(isPlanarWanted); //Compute the shape + Standard_Boolean isWarning = Standard_False; try { -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 +#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { @@ -463,7 +541,12 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); - return NULL; + // to provide warning + if (!aFunction->GetValue().IsNull()) { + isWarning = Standard_True; + } else { + return NULL; + } } //Make a Python command @@ -480,7 +563,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWires } pd << "], " << (int)isPlanarWanted << ")"; - SetErrorCode(OK); + // to provide warning + if (!isWarning) SetErrorCode(OK); return aShape; } @@ -559,7 +643,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeShape //Compute the shape try { -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 +#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { @@ -628,7 +712,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces //Compute the sub-shape value Standard_Boolean isWarning = Standard_False; try { -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 +#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { @@ -661,6 +745,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFaces * GetGlueFaces */ //============================================================================= +/* Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces (Handle(GEOM_Object) theShape, const Standard_Real theTolerance) @@ -721,7 +806,7 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces if( anAsciiList.Length() > 0 ) { anAsciiList.Trunc(anAsciiList.Length() - 1); Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); - GEOM::TPythonDump pd (aFunction, /*append=*/true); + GEOM::TPythonDump pd (aFunction, true); pd << "[" << anAsciiList.ToCString(); pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")"; } @@ -730,6 +815,7 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueFaces return aSeq; } +*/ //============================================================================= /*! @@ -740,7 +826,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFacesByList (Handle(GEOM_Object) theShape, const Standard_Real theTolerance, std::list theFaces, - const Standard_Boolean doKeepNonSolids) + const Standard_Boolean doKeepNonSolids, + const Standard_Boolean doGlueAllEdges) { SetErrorCode(KO); @@ -765,6 +852,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFacesByList aCI.SetBase(aRefShape); aCI.SetTolerance(theTolerance); aCI.SetKeepNonSolids(doKeepNonSolids); + aCI.SetGlueAllEdges(doGlueAllEdges); Handle(TColStd_HSequenceOfTransient) aFaces = new TColStd_HSequenceOfTransient; std::list::iterator it = theFaces.begin(); @@ -781,7 +869,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFacesByList //Compute the sub-shape value Standard_Boolean isWarning = Standard_False; try { -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 +#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { @@ -813,6 +901,244 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueFacesByList pd << ", " << (*it++); } } + pd << "], " << (bool)doKeepNonSolids << ", " << (bool)doGlueAllEdges << ")"; + + // to provide warning + if (!isWarning) SetErrorCode(OK); + return aGlued; +} + +//============================================================================= +/*! + * MakeGlueEdges + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueEdges + (Handle(GEOM_Object) theShape, + const Standard_Real theTolerance) +{ + SetErrorCode(KO); + + if (theShape.IsNull()) return NULL; + + //Add a new Glued object + Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED); + + //Add a new Glue function + Handle(GEOM_Function) aFunction; + aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES); + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL; + + GEOMImpl_IGlue aCI (aFunction); + + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + if (aRefShape.IsNull()) return NULL; + + aCI.SetBase(aRefShape); + aCI.SetTolerance(theTolerance); + aCI.SetKeepNonSolids(true); + + //Compute the sub-shape value + Standard_Boolean isWarning = Standard_False; + try { +#if OCC_VERSION_LARGE > 0x06010000 + OCC_CATCH_SIGNALS; +#endif + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Shape driver failed to glue edges"); + return NULL; + } + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + // to provide warning + if (!aFunction->GetValue().IsNull()) { + isWarning = Standard_True; + } else { + return NULL; + } + } + + //Make a Python command + GEOM::TPythonDump(aFunction) << aGlued << " = geompy.MakeGlueEdges(" + << theShape << ", " << theTolerance << ")"; + + // to provide warning + if (!isWarning) SetErrorCode(OK); + return aGlued; +} + +//============================================================================= +/*! + * GetGlueShapes + */ +//============================================================================= +Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetGlueShapes + (Handle(GEOM_Object) theShape, + const Standard_Real theTolerance, + const TopAbs_ShapeEnum theType) +{ + SetErrorCode(KO); + + if (theShape.IsNull()) return NULL; + TopoDS_Shape aShape = theShape->GetValue(); + if (aShape.IsNull()) return NULL; + + Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; + + GEOMAlgo_GlueDetector aGluer; + aGluer.SetArgument(aShape); + aGluer.SetTolerance(theTolerance); + aGluer.Perform(); + Standard_Integer iErr = aGluer.ErrorStatus(); + if (iErr) return NULL; + + TCollection_AsciiString anAsciiList, anEntry; + TopTools_IndexedMapOfShape anIndices; + TopExp::MapShapes(aShape, anIndices); + Handle(TColStd_HArray1OfInteger) anArray; + Handle(GEOM_Object) anObj; + + TopTools_ListOfShape listOnePerSet; + + const TopTools_DataMapOfShapeListOfShape& aImages = aGluer.Images(); + TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDMSLS (aImages); + for (int index = 1; aItDMSLS.More(); aItDMSLS.Next(), ++index) { + // some key shape + //const TopoDS_Shape& aSkey = aItDMSLS.Key(); + + // list of shapes of the argument that can be glued + const TopTools_ListOfShape& aLSD = aItDMSLS.Value(); + + //listShape.Append(aLSD.First()); + TopoDS_Shape aValue = aLSD.First(); + + if (aValue.ShapeType() == theType) { + listOnePerSet.Append(aValue); + } + } + + // for stable order of returned entities + GEOMImpl_IShapesOperations::SortShapes(listOnePerSet, Standard_False); + + TopTools_ListIteratorOfListOfShape aListIt (listOnePerSet); + for (; aListIt.More(); aListIt.Next()) { + TopoDS_Shape aValue = aListIt.Value(); + anArray = new TColStd_HArray1OfInteger(1,1); + anArray->SetValue(1, anIndices.FindIndex(aValue)); + anObj = GetEngine()->AddSubShape(theShape, anArray); + if (!anObj.IsNull()) { + aSeq->Append(anObj); + + // for python command + TDF_Tool::Entry(anObj->GetEntry(), anEntry); + anAsciiList += anEntry; + anAsciiList += ","; + } + } + + // Make a Python command + if (anAsciiList.Length() > 0) { + anAsciiList.Trunc(anAsciiList.Length() - 1); + Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); + GEOM::TPythonDump pd (aFunction, /*append=*/true); + pd << "[" << anAsciiList.ToCString(); + if (theType == TopAbs_FACE) + pd << "] = geompy.GetGlueFaces(" << theShape << ", " << theTolerance << ")"; + else if (theType == TopAbs_EDGE) + pd << "] = geompy.GetGlueEdges(" << theShape << ", " << theTolerance << ")"; + } + + SetErrorCode(OK); + + return aSeq; +} + +//============================================================================= +/*! + * MakeGlueEdgesByList + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeGlueEdgesByList + (Handle(GEOM_Object) theShape, + const Standard_Real theTolerance, + std::list theEdges) +{ + SetErrorCode(KO); + + if (theShape.IsNull()) return NULL; + + //Add a new Glued object + Handle(GEOM_Object) aGlued = GetEngine()->AddObject(GetDocID(), GEOM_GLUED); + + //Add a new Glue function + Handle(GEOM_Function) aFunction; + aFunction = aGlued->AddFunction(GEOMImpl_GlueDriver::GetID(), GLUE_EDGES_BY_LIST); + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_GlueDriver::GetID()) return NULL; + + GEOMImpl_IGlue aCI (aFunction); + + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + if (aRefShape.IsNull()) return NULL; + + aCI.SetBase(aRefShape); + aCI.SetTolerance(theTolerance); + aCI.SetKeepNonSolids(true); + + Handle(TColStd_HSequenceOfTransient) anEdges = new TColStd_HSequenceOfTransient; + std::list::iterator it = theEdges.begin(); + for (; it != theEdges.end(); it++) { + Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction(); + if (aRefSh.IsNull()) { + SetErrorCode("NULL argument shape for the shape construction"); + return NULL; + } + anEdges->Append(aRefSh); + } + aCI.SetFaces(anEdges); + + //Compute the sub-shape value + Standard_Boolean isWarning = Standard_False; + try { +#if OCC_VERSION_LARGE > 0x06010000 + OCC_CATCH_SIGNALS; +#endif + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Shape driver failed to glue edges"); + return NULL; + } + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + // to provide warning + if (!aFunction->GetValue().IsNull()) { + isWarning = Standard_True; + } else { + return NULL; + } + } + + //Make a Python command + + GEOM::TPythonDump pd (aFunction); + pd << aGlued << " = geompy.MakeGlueEdgesByList(" + << theShape << ", " << theTolerance << ", ["; + // Edges + it = theEdges.begin(); + if (it != theEdges.end()) { + pd << (*it++); + while (it != theEdges.end()) { + pd << ", " << (*it++); + } + } pd << "])"; // to provide warning @@ -877,7 +1203,7 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetExistingSubO GEOM::TPythonDump pd (aMainShape, /*append=*/true); pd << "[" << anAsciiList.ToCString(); pd << "] = geompy.GetExistingSubObjects("; - pd << theShape << ", " << (int)theGroupsOnly << ")"; + pd << theShape << ", " << (bool)theGroupsOnly << ")"; SetErrorCode(OK); @@ -893,7 +1219,7 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode (Handle(GEOM_Object) theShape, const Standard_Integer theShapeType, const Standard_Boolean isSorted, - const Standard_Boolean isOldSorting) + const ExplodeType theExplodeType) { SetErrorCode(KO); @@ -911,7 +1237,8 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode if (aShape.ShapeType() == TopAbs_COMPOUND && (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE || TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID || - TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) { + TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) + { TopoDS_Iterator It (aShape, Standard_True, Standard_True); for (; It.More(); It.Next()) { if (mapShape.Add(It.Value())) { @@ -922,7 +1249,7 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode } } } - else if ( aShape.ShapeType() != theShapeType ) // issue 0021079, prevent from returning aShape + else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079 { TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType)); for (; exp.More(); exp.Next()) @@ -936,8 +1263,12 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode return aSeq; } - if (isSorted) + if (isSorted) { + bool isOldSorting = false; + if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN) + isOldSorting = true; SortShapes(listShape, isOldSorting); + } TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape, anIndices); @@ -966,6 +1297,9 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode // because GEOM_SubShapeDriver will build TopTools_IndexedMapOfShape // on the main shape for each being calculated sub-shape separately. aFunction->SetValue(aValue); + + // Put this subshape in the list of subshapes of theMainShape + aMainShape->AddSubShapeReference(aFunction); } if (!anObj.IsNull()) { @@ -982,13 +1316,22 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeExplode 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) << ")"; - + pd << "[" << anAsciiList.ToCString() << "] = geompy."; + switch (theExplodeType) { + case EXPLODE_NEW_EXCLUDE_MAIN: + pd << "ExtractShapes(" << theShape << ", " + << TopAbs_ShapeEnum(theShapeType) << ", " << (isSorted ? "True" : "False") << ")"; + break; + case EXPLODE_NEW_INCLUDE_MAIN: + pd << "SubShapeAll" << (isSorted ? "SortedCentres(" : "(") + << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")"; + break; + case EXPLODE_OLD_INCLUDE_MAIN: + pd << "SubShapeAll" << (isSorted ? "Sorted(" : "(") + << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")"; + break; + default: ; + } SetErrorCode(OK); return aSeq; @@ -1003,7 +1346,7 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs (Handle(GEOM_Object) theShape, const Standard_Integer theShapeType, const Standard_Boolean isSorted, - const Standard_Boolean isOldSorting) + const ExplodeType theExplodeType) { SetErrorCode(KO); @@ -1018,7 +1361,8 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs if (aShape.ShapeType() == TopAbs_COMPOUND && (TopAbs_ShapeEnum(theShapeType) == TopAbs_SHAPE || TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPSOLID || - TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) { + TopAbs_ShapeEnum(theShapeType) == TopAbs_COMPOUND)) + { TopoDS_Iterator It (aShape, Standard_True, Standard_True); for (; It.More(); It.Next()) { if (mapShape.Add(It.Value())) { @@ -1028,7 +1372,8 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs } } } - } else if ( aShape.ShapeType() != theShapeType ) // issue 0021079, prevent from returning aShape + } + else if (theExplodeType != EXPLODE_NEW_EXCLUDE_MAIN || aShape.ShapeType() != theShapeType) // issue 0021079 { TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType)); for (; exp.More(); exp.Next()) @@ -1042,8 +1387,12 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs return aSeq; } - if (isSorted) + if (isSorted) { + bool isOldSorting = false; + if (theExplodeType == EXPLODE_OLD_INCLUDE_MAIN) + isOldSorting = true; SortShapes(listShape, isOldSorting); + } TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aShape, anIndices); @@ -1060,11 +1409,19 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs //Make a Python command 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) << ")"; + switch (theExplodeType) { + case EXPLODE_NEW_EXCLUDE_MAIN: + break; + case EXPLODE_NEW_INCLUDE_MAIN: + pd << (isSorted ? "SortedCentresIDs(" : "IDs(") + << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")"; + break; + case EXPLODE_OLD_INCLUDE_MAIN: + pd << (isSorted ? "SortedIDs(" : "IDs(") + << theShape << ", " << TopAbs_ShapeEnum(theShapeType) << ")"; + break; + default: ; + } SetErrorCode(OK); return aSeq; @@ -1081,24 +1438,107 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSubShape { SetErrorCode(KO); - if (theMainShape.IsNull()) return NULL; + 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(); + + //Make a Python command + GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape(" + << theMainShape << ", [" << theID << "])"; + + SetErrorCode(OK); + return anObj; +} + +//============================================================================= +/*! + * MakeSubShapes + */ +//============================================================================= +Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::MakeSubShapes + (Handle(GEOM_Object) theMainShape, + Handle(TColStd_HArray1OfInteger) theIndices) +{ + SetErrorCode(KO); + + Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; + + if (!theIndices->Length()) { + SetErrorCode(NOT_FOUND_ANY); + return aSeq; + } + + if (theMainShape.IsNull()) return NULL; + TopoDS_Shape aShape = theMainShape->GetValue(); + if (aShape.IsNull()) return NULL; + + Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction(); + + TopTools_IndexedMapOfShape anIndices; + TopExp::MapShapes(aShape, anIndices); + + Handle(TColStd_HArray1OfInteger) anArray; + Handle(GEOM_Object) anObj; + + TCollection_AsciiString anAsciiList, anEntry; + Standard_Integer i, low = theIndices->Lower(), up = theIndices->Upper(); + for (i = low; i <= up; i++) { + int id = theIndices->Value(i); + if (1 <= id && id <= anIndices.Extent()) { + TopoDS_Shape aValue = anIndices.FindKey(id); + anArray = new TColStd_HArray1OfInteger(1,1); + anArray->SetValue(1, id); + + anObj = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE); + if (!anObj.IsNull()) { + 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); - 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; - } + // 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); - Handle(GEOM_Function) aFunction = anObj->GetLastFunction(); + // Put this subshape in the list of subshapes of theMainShape + aMainShape->AddSubShapeReference(aFunction); + + aSeq->Append(anObj); + + // for python command + TDF_Tool::Entry(anObj->GetEntry(), anEntry); + anAsciiList += anEntry; + anAsciiList += ","; + } + } + } //Make a Python command - GEOM::TPythonDump(aFunction) << anObj << " = geompy.GetSubShape(" - << theMainShape << ", [" << theID << "])"; + anAsciiList.Trunc(anAsciiList.Length() - 1); + + GEOM::TPythonDump pd (aMainShape, /*append=*/true); + pd << "[" << anAsciiList.ToCString() << "] = geompy.SubShapes(" + << theMainShape << ", [" ; + for (i = low; i <= up - 1; i++) { + pd << theIndices->Value(i) << ", "; + } + pd << theIndices->Value(up) << "])"; SetErrorCode(OK); - return anObj; + + return aSeq; } //============================================================================= @@ -1299,7 +1739,7 @@ Standard_Integer GEOMImpl_IShapesOperations::NumberOfSubShapes */ try { -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 +#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif int iType, nbTypes [TopAbs_SHAPE]; @@ -1350,6 +1790,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) if (theShape.IsNull()) return NULL; + /* //Add a new reversed object Handle(GEOM_Object) aReversed = GetEngine()->AddObject(GetDocID(), theShape->GetType()); @@ -1370,7 +1811,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) //Compute the sub-shape value try { -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 +#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif if (!GetSolver()->ComputeFunction(aFunction)) { @@ -1389,6 +1830,21 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::ReverseShape(Handle(GEOM_Object) << " = geompy.ChangeOrientation(" << theShape << ")"; SetErrorCode(OK); + */ + + Handle(GEOM_Object) aReversed; + + GEOM_Engine* anEngine = GetEngine(); + //GEOMImpl_Gen* aGen = dynamic_cast(anEngine); + GEOMImpl_Gen* aGen = (GEOMImpl_Gen*)anEngine; + + if (aGen) { + GEOMImpl_IHealingOperations* anIHealingOperations = + aGen->GetIHealingOperations(GetDocID()); + aReversed = anIHealingOperations->ChangeOrientationCopy(theShape); + SetErrorCode(anIHealingOperations->GetErrorCode()); + } + return aReversed; } @@ -2143,7 +2599,7 @@ Handle(TColStd_HSequenceOfInteger) // Compute tolerance Standard_Real T, VertMax = -RealLast(); try { -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 +#if OCC_VERSION_LARGE > 0x06010000 OCC_CATCH_SIGNALS; #endif for (TopExp_Explorer ExV (theShape, TopAbs_VERTEX); ExV.More(); ExV.Next()) { @@ -3304,29 +3760,28 @@ namespace { } return defaultNorm; } +} - //================================================================================ - /*! - * \brief Return type of shape for explode. In case of compound it will be a type of sub shape. - */ - //================================================================================ - - 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()); - } +//================================================================================ +/*! + * \brief Return type of shape for explode. In case of compound it will be a type of sub shape. + */ +//================================================================================ +TopAbs_ShapeEnum GEOMImpl_IShapesOperations::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; } + return TopAbs_SHAPE; } //============================================================================= @@ -3361,6 +3816,177 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) TopTools_IndexedMapOfShape aWhereIndices; TopExp::MapShapes(aWhere, aWhereIndices); + TopAbs_ShapeEnum iType = TopAbs_SOLID; + Standard_Real dl_l = 1e-3; + Standard_Real min_l, Tol_0D, Tol_1D, Tol_2D, Tol_3D, Tol_Mass; + Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; + Bnd_Box BoundingBox; + gp_Pnt aPnt, aPnt_aWhat, tab_Pnt[2]; + GProp_GProps aProps; + + // Find the iType of the aWhat shape + iType = GetTypeOfSimplePart(aWhat); + if (iType == TopAbs_SHAPE) { + SetErrorCode("Error: An attempt to extract a shape of not supported type."); + return NULL; + } + + TopExp_Explorer Exp_aWhat ( aWhat, iType ); + TopExp_Explorer Exp_aWhere ( aWhere, iType ); + TopExp_Explorer Exp_Edge ( aWhere, TopAbs_EDGE ); + + // Find the shortest edge in theShapeWhere shape + BRepBndLib::Add(aWhere, BoundingBox); + BoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); + min_l = fabs(aXmax - aXmin); + if( min_l < fabs(aYmax - aYmin) ) min_l = fabs(aYmax - aYmin); + if( min_l < fabs(aZmax - aZmin) ) min_l = fabs(aZmax - aZmin); + min_l /= dl_l; + // Mantis issue 0020908 BEGIN + if (!Exp_Edge.More()) { + min_l = Precision::Confusion(); + } + // Mantis issue 0020908 END + for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) { + TopExp_Explorer Exp_Vertex( Exp_Edge.Current(), TopAbs_VERTEX); + for ( Standard_Integer nbVertex = 0; Exp_Vertex.More(); Exp_Vertex.Next(), nbVertex++ ) { + aPnt = BRep_Tool::Pnt( TopoDS::Vertex( Exp_Vertex.Current() ) ); + tab_Pnt[nbVertex] = aPnt; + } + if ( ! tab_Pnt[0].IsEqual(tab_Pnt[1], dl_l) ) { + BRepGProp::LinearProperties(Exp_Edge.Current(), aProps); + if ( aProps.Mass() < min_l ) min_l = aProps.Mass(); + } + } + + // Compute tolerances + Tol_0D = dl_l; + Tol_1D = dl_l * min_l; + Tol_2D = dl_l * ( min_l * min_l) * ( 2. + dl_l); + Tol_3D = dl_l * ( min_l * min_l * min_l ) * ( 3. + (3 * dl_l) + (dl_l * dl_l) ); + + if (Tol_0D < Precision::Confusion()) Tol_0D = Precision::Confusion(); + if (Tol_1D < Precision::Confusion()) Tol_1D = Precision::Confusion(); + if (Tol_2D < Precision::Confusion()) Tol_2D = Precision::Confusion(); + if (Tol_3D < Precision::Confusion()) Tol_3D = Precision::Confusion(); + + Tol_Mass = Tol_3D; + if ( iType == TopAbs_VERTEX ) Tol_Mass = Tol_0D; + else if ( iType == TopAbs_EDGE ) Tol_Mass = Tol_1D; + else if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D; + + // Searching for the sub-shapes inside the ShapeWhere shape + GEOMAlgo_GetInPlace aGIP; + aGIP.SetTolerance(Tol_1D); + aGIP.SetTolMass(Tol_Mass); + aGIP.SetTolCG(Tol_1D); + + aGIP.SetArgument(aWhat); + aGIP.SetShapeWhere(aWhere); + + aGIP.Perform(); + int iErr = aGIP.ErrorStatus(); + if (iErr) { + SetErrorCode("Error in GEOMAlgo_GetInPlace"); + return NULL; + } + + // aGIP.IsFound() returns true only when the whole theShapeWhat + // is found (as one shape or several parts). But we are also interested + // in the partial result, that is why this check is commented. + //if (!aGIP.IsFound()) { + // SetErrorCode(NOT_FOUND_ANY); + // return NULL; + //} + + const TopTools_DataMapOfShapeListOfShape& aDMSLS = aGIP.Images(); + if (!aDMSLS.IsBound(aWhat)) { + SetErrorCode(NOT_FOUND_ANY); + return NULL; + } + + // the list of shapes aLSA contains the shapes + // of the Shape For Search that corresponds + // to the Argument aWhat + const TopTools_ListOfShape& aLSA = aDMSLS.Find(aWhat); + if (aLSA.Extent() == 0) { + SetErrorCode(NOT_FOUND_ANY); // Not found any Results + return NULL; + } + + Handle(TColStd_HArray1OfInteger) aModifiedArray = new TColStd_HArray1OfInteger (1, aLSA.Extent()); + TopTools_ListIteratorOfListOfShape anIterModif (aLSA); + for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) { + if (aWhereIndices.Contains(anIterModif.Value())) { + aModifiedArray->SetValue(imod, aWhereIndices.FindIndex(anIterModif.Value())); + } + else { + SetErrorCode("Error: wrong sub shape returned"); + return NULL; + } + } + + //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 = aLSA.First(); + TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType(); + + TDF_Label aFreeLabel = aResult->GetFreeLabel(); + TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType); + } + + //Make a Python command + Handle(GEOM_Function) aFunction = aResult->GetFunction(1); + + GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace(" + << theShapeWhere << ", " << theShapeWhat << ", True)"; + + SetErrorCode(OK); + return aResult; +} + +//============================================================================= +/*! + * case GetInPlaceOld: + * default: + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceOld (Handle(GEOM_Object) theShapeWhere, + Handle(GEOM_Object) theShapeWhat) +{ + SetErrorCode(KO); + + if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL; + + TopoDS_Shape aWhere = theShapeWhere->GetValue(); + TopoDS_Shape aWhat = theShapeWhat->GetValue(); + TopoDS_Shape aPntShape; + TopoDS_Vertex aVertex; + + 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); + TColStd_ListOfInteger aModifiedList; Standard_Integer aWhereIndex; Handle(TColStd_HArray1OfInteger) aModifiedArray; @@ -3496,7 +4122,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) if ( isFound && iType == TopAbs_FACE ) { // check normals at pOnWhat and pOnWhere - const double angleTol = PI/180.; + const double angleTol = M_PI/180.; gp_Vec normToWhat = GetNormal( TopoDS::Face(Exp_aWhat.Current()), aWhatDistance); gp_Vec normToWhere = GetNormal( TopoDS::Face(Exp_aWhere.Current()), aWhereDistance); if ( normToWhat * normToWhere < 0 ) @@ -3551,7 +4177,7 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) Handle(GEOM_Function) aFunction = aResult->GetFunction(1); GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace(" - << theShapeWhere << ", " << theShapeWhat << ")"; + << theShapeWhere << ", " << theShapeWhat << ", False)"; SetErrorCode(OK); return aResult; @@ -3626,6 +4252,106 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory return aResult; } +//======================================================================= +//function : ShapeToDouble +//purpose : used by CompareShapes::operator() +//======================================================================= +std::pair ShapeToDouble (const TopoDS_Shape& S, bool isOldSorting) +{ + // Computing of CentreOfMass + gp_Pnt GPoint; + double Len; + + if (S.ShapeType() == TopAbs_VERTEX) { + GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S)); + Len = (double)S.Orientation(); + } + else { + GProp_GProps GPr; + // BEGIN: fix for Mantis issue 0020842 + if (isOldSorting) { + BRepGProp::LinearProperties(S, GPr); + } + else { + if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) { + BRepGProp::LinearProperties(S, GPr); + } + else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) { + BRepGProp::SurfaceProperties(S, GPr); + } + else { + BRepGProp::VolumeProperties(S, GPr); + } + } + // END: fix for Mantis issue 0020842 + GPoint = GPr.CentreOfMass(); + Len = GPr.Mass(); + } + + double dMidXYZ = GPoint.X() * 999.0 + GPoint.Y() * 99.0 + GPoint.Z() * 0.9; + return std::make_pair(dMidXYZ, Len); +} + +//======================================================================= +//function : CompareShapes::operator() +//purpose : used by std::sort(), called from SortShapes() +//======================================================================= +bool GEOMImpl_IShapesOperations::CompareShapes::operator()(const TopoDS_Shape& theShape1, + const TopoDS_Shape& theShape2) +{ + if (!myMap.IsBound(theShape1)) { + myMap.Bind(theShape1, ShapeToDouble(theShape1, myIsOldSorting)); + } + + if (!myMap.IsBound(theShape2)) { + myMap.Bind(theShape2, ShapeToDouble(theShape2, myIsOldSorting)); + } + + std::pair val1 = myMap.Find(theShape1); + std::pair val2 = myMap.Find(theShape2); + + double tol = Precision::Confusion(); + bool exchange = Standard_False; + + double dMidXYZ = val1.first - val2.first; + if (dMidXYZ >= tol) { + exchange = Standard_True; + } + else if (Abs(dMidXYZ) < tol) { + double dLength = val1.second - val2.second; + if (dLength >= tol) { + exchange = Standard_True; + } + else if (Abs(dLength) < tol && theShape1.ShapeType() <= TopAbs_FACE) { + // PAL17233 + // equal values possible on shapes such as two halves of a sphere and + // a membrane inside the sphere + Bnd_Box box1,box2; + BRepBndLib::Add(theShape1, box1); + if (!box1.IsVoid()) { + BRepBndLib::Add(theShape2, box2); + Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent(); + if (dSquareExtent >= tol) { + exchange = Standard_True; + } + else if (Abs(dSquareExtent) < tol) { + Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2; + box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); + val1 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9; + box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); + val2 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9; + if ((val1 - val2) >= tol) { + exchange = Standard_True; + } + } + } + } + } + + //return val1 < val2; + return !exchange; +} + //======================================================================= //function : SortShapes //purpose : @@ -3633,6 +4359,26 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL, const Standard_Boolean isOldSorting) { +#ifdef STD_SORT_ALGO + std::vector aShapesVec; + aShapesVec.reserve(SL.Extent()); + + TopTools_ListIteratorOfListOfShape it (SL); + for (; it.More(); it.Next()) { + aShapesVec.push_back(it.Value()); + } + SL.Clear(); + + CompareShapes shComp (isOldSorting); + std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp); + //std::sort(aShapesVec.begin(), aShapesVec.end(), shComp); + + std::vector::const_iterator anIter = aShapesVec.begin(); + for (; anIter != aShapesVec.end(); ++anIter) { + SL.Append(*anIter); + } +#else + // old implementation Standard_Integer MaxShapes = SL.Extent(); TopTools_Array1OfShape aShapes (1,MaxShapes); TColStd_Array1OfInteger OrderInd(1,MaxShapes); @@ -3674,8 +4420,7 @@ void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL, GPoint = GPr.CentreOfMass(); Length.SetValue(Index, GPr.Mass()); } - MidXYZ.SetValue(Index, - GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9); + MidXYZ.SetValue(Index, GPoint.X()*999.0 + GPoint.Y()*99.0 + GPoint.Z()*0.9); //cout << Index << " L: " << Length(Index) << "CG: " << MidXYZ(Index) << endl; } @@ -3742,6 +4487,7 @@ void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL, for (Index=1; Index <= MaxShapes; Index++) SL.Append( aShapes( OrderInd(Index) )); +#endif } //======================================================================= @@ -4062,7 +4808,17 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object TopoDS_Shape aSubShape; TopTools_MapOfShape aMap; - switch(aWhat.ShapeType()) { + if (aWhat.ShapeType() == TopAbs_COMPOUND || aWhat.ShapeType() == TopAbs_COMPSOLID) { + TopoDS_Iterator It (aWhat, Standard_True, Standard_True); + if (It.More()) aWhat = It.Value(); + It.Next(); + if (It.More()) { + SetErrorCode("Compounds of two or more shapes are not allowed for aWhat argument"); + return NULL; + } + } + + switch (aWhat.ShapeType()) { case TopAbs_VERTEX: { gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat)); TopExp_Explorer E(aWhere, TopAbs_VERTEX); @@ -4077,12 +4833,12 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object } break; } - case TopAbs_FACE: { - TopoDS_Face aFace = TopoDS::Face(aWhat); - TopExp_Explorer E(aWhere, TopAbs_FACE); + case TopAbs_EDGE: { + TopoDS_Edge anEdge = TopoDS::Edge(aWhat); + TopExp_Explorer E(aWhere, TopAbs_EDGE); for(; E.More(); E.Next()) { if(!aMap.Add(E.Current())) continue; - if(isSameFace(aFace, TopoDS::Face(E.Current()))) { + if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) { aSubShape = E.Current(); isFound = true; break; @@ -4090,12 +4846,12 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object } break; } - case TopAbs_EDGE: { - TopoDS_Edge anEdge = TopoDS::Edge(aWhat); - TopExp_Explorer E(aWhere, TopAbs_EDGE); + case TopAbs_FACE: { + TopoDS_Face aFace = TopoDS::Face(aWhat); + TopExp_Explorer E(aWhere, TopAbs_FACE); for(; E.More(); E.Next()) { if(!aMap.Add(E.Current())) continue; - if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) { + if(isSameFace(aFace, TopoDS::Face(E.Current()))) { aSubShape = E.Current(); isFound = true; break; @@ -4120,14 +4876,14 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object return NULL; } - if(isFound) { + if (isFound) { TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aWhere, anIndices); if (anIndices.Contains(aSubShape)) anIndex = anIndices.FindIndex(aSubShape); } - if(anIndex < 0) return NULL; + if (anIndex < 0) return NULL; Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);