X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGeomAlgoAPI%2FGeomAlgoAPI_NExplode.cpp;h=c6013a5a712d4626890f45361d13888aadadb798;hb=fc72d43b677baa05ae7fd317346fd8b723b799ed;hp=6af492d61febc04a4e28d34ad087c1304414115a;hpb=c4eab94a20a0d93100549a210582d46409fec1cc;p=modules%2Fshaper.git diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_NExplode.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_NExplode.cpp index 6af492d61..c6013a5a7 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_NExplode.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_NExplode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2017-2019 CEA/DEN, EDF R&D +// Copyright (C) 2017-2023 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -19,150 +19,176 @@ #include "GeomAlgoAPI_NExplode.h" -#include +#include +#include + +#include #include -#include -#include +#include #include -#include +#include #include -#include -#include -#include -#include +#include +#include -#include #include +#include +#include -static std::pair ShapeToDouble (const TopoDS_Shape& S) +namespace NExplodeTools { - // Computing of CentreOfMass - gp_Pnt GPoint; - double Len; + void dummy(gp_Pnt&) + { + // do nothing (new approach to order shapes) + } - if (S.ShapeType() == TopAbs_VERTEX) { - GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S)); - Len = (double)S.Orientation(); + void pointToDouble(gp_Pnt& thePoint) + { + // old approach to order shapes + double dMidXYZ = thePoint.X() * 999.0 + thePoint.Y() * 99.0 + thePoint.Z() * 0.9; + thePoint.SetCoord(dMidXYZ, 0.0, 0.0); } - else { - GProp_GProps GPr; - 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); + + std::pair ShapeToDouble(const GeomShapePtr& theShape, + void(*convertPoint)(gp_Pnt&)) + { + // Computing of CentreOfMass + gp_Pnt GPoint; + double Len; + + TopoDS_Shape S = theShape->impl(); + if (S.ShapeType() == TopAbs_VERTEX) { + GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S)); + Len = (double)S.Orientation(); } else { - BRepGProp::VolumeProperties(S, GPr); + GProp_GProps GPr; + 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); + } + GPoint = GPr.CentreOfMass(); + Len = GPr.Mass(); } - 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); -} + (*convertPoint)(GPoint); + GeomPointPtr aMidPoint(new GeomAPI_Pnt(GPoint.X(), GPoint.Y(), GPoint.Z())); + return std::make_pair(aMidPoint, Len); + } -/*! -* \brief Sort shapes in the list by their coordinates. -*/ -struct CompareShapes : public std::binary_function -{ - typedef NCollection_DataMap > DataMapOfShapeDouble; + /*! + * \brief Sort shapes in the list by their coordinates. + */ + struct CompareShapes : public std::binary_function + { + typedef std::unordered_map, + GeomAPI_Shape::Hash, + GeomAPI_Shape::Equal > DataMapOfShapeDouble; - CompareShapes(DataMapOfShapeDouble* theCashMap) : myMap(theCashMap) {} + CompareShapes(void(*convertPoint)(gp_Pnt&)) + : myConvertPoint(convertPoint) {} - bool operator() (const TopoDS_Shape& lhs, const TopoDS_Shape& rhs); + bool operator() (const GeomShapePtr& lhs, const GeomShapePtr& rhs); - DataMapOfShapeDouble* myMap; -}; + DataMapOfShapeDouble myMap; + void(*myConvertPoint)(gp_Pnt&); + }; +} -bool CompareShapes::operator() (const TopoDS_Shape& theShape1, - const TopoDS_Shape& theShape2) +bool NExplodeTools::CompareShapes::operator() (const GeomShapePtr& lhs, const GeomShapePtr& rhs) { - if (!myMap->IsBound(theShape1)) { - myMap->Bind(theShape1, ShapeToDouble(theShape1)); + if (myMap.find(lhs) == myMap.end()) { + myMap[lhs] = ShapeToDouble(lhs, myConvertPoint); } - if (!myMap->IsBound(theShape2)) { - myMap->Bind(theShape2, ShapeToDouble(theShape2)); + if (myMap.find(rhs) == myMap.end()) { + myMap[rhs] = ShapeToDouble(rhs, myConvertPoint); } - std::pair val1 = myMap->Find(theShape1); - std::pair val2 = myMap->Find(theShape2); + const std::pair& val1 = myMap.at(lhs); + const std::pair& val2 = myMap.at(rhs); - double tol = Precision::Confusion(); + double tol = 10.0 * Precision::Confusion(); bool exchange = Standard_False; - double dMidXYZ = val1.first - val2.first; - if (dMidXYZ >= tol) { + // compare coordinates of center points + if (val2.first->isLess(val1.first, tol)) { exchange = Standard_True; } - else if (Abs(dMidXYZ) < tol) { + else if (!val1.first->isLess(val2.first, tol)) { double dLength = val1.second - val2.second; if (dLength >= tol) { exchange = Standard_True; } - else if (Abs(dLength) < tol && theShape1.ShapeType() <= TopAbs_FACE) { + else if (Abs(dLength) < tol && lhs->shapeType() <= GeomAPI_Shape::FACE) { // 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); + Bnd_Box box1, box2; + BRepBndLib::Add(lhs->impl(), box1); if (!box1.IsVoid()) { - BRepBndLib::Add(theShape2, box2); + BRepBndLib::Add(rhs->impl(), 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; + Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, value1, value2; box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); - val1 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9; + value1 = (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) { + value2 = (aXmin + aXmax)*999.0 + (aYmin + aYmax)*99.0 + (aZmin + aZmax)*0.9; + if (value1 - value2 >= tol) { exchange = Standard_True; } - else // compare adresses if shapes are geometrically equal - exchange = theShape1.TShape().get() > theShape2.TShape().get(); + else { // compare adresses if shapes are geometrically equal + exchange = lhs->impl().TShape().get() > + rhs->impl().TShape().get(); + } } } - } else // compare adresses if shapes are geometrically equal - exchange = theShape1.TShape().get() > theShape2.TShape().get(); + } + else { // compare adresses if shapes are geometrically equal + exchange = lhs->impl().TShape().get() > + rhs->impl().TShape().get(); + } } //return val1 < val2; return !exchange; } -GeomAlgoAPI_NExplode::GeomAlgoAPI_NExplode( - const GeomShapePtr theContext, const GeomAPI_Shape::ShapeType theShapeType) +GeomAlgoAPI_NExplode::GeomAlgoAPI_NExplode(const GeomShapePtr theContext, + const GeomAPI_Shape::ShapeType theShapeType, + const ShapeOrder theOrder) { - std::vector aShapesVec; - - const TopoDS_Shape& aContext = theContext->impl(); - TopExp_Explorer anExp(aContext, (TopAbs_ShapeEnum)theShapeType); - TopTools_MapOfShape aMapShape; - for(; anExp.More(); anExp.Next()) { - if (aMapShape.Add(anExp.Current())) - aShapesVec.push_back(anExp.Current()); + std::set aMapShape; + GeomAPI_ShapeExplorer anExp(theContext, theShapeType); + for (; anExp.more(); anExp.next()) { + GeomShapePtr aCurrent = anExp.current(); + if (aMapShape.find(aCurrent) == aMapShape.end()) { + mySorted.push_back(aCurrent); + aMapShape.insert(aCurrent); + } } + reorder(theOrder); +} - CompareShapes::DataMapOfShapeDouble aCash; - CompareShapes shComp(&aCash); - std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp); - - std::vector::const_iterator anIter = aShapesVec.begin(); - for (; anIter != aShapesVec.end(); ++anIter) { - GeomShapePtr aShapePtr(new GeomAPI_Shape); - aShapePtr->setImpl(new TopoDS_Shape(*anIter)); - mySorted.push_back(aShapePtr); - } +GeomAlgoAPI_NExplode::GeomAlgoAPI_NExplode(const ListOfShape& theShapes, + const ShapeOrder theOrder) + : mySorted(theShapes.begin(), theShapes.end()) +{ + reorder(theOrder); } int GeomAlgoAPI_NExplode::index(const GeomShapePtr theSubShape) { - ListOfShape::iterator anIter = mySorted.begin(); + std::vector::iterator anIter = mySorted.begin(); for(int anIndex = 1; anIter != mySorted.end(); anIter++, anIndex++) { if ((*anIter)->isSame(theSubShape)) return anIndex; @@ -172,10 +198,17 @@ int GeomAlgoAPI_NExplode::index(const GeomShapePtr theSubShape) GeomShapePtr GeomAlgoAPI_NExplode::shape(const int theIndex) { - ListOfShape::iterator anIter = mySorted.begin(); + std::vector::iterator anIter = mySorted.begin(); for(int anIndex = 1; anIter != mySorted.end(); anIter++, anIndex++) { if (anIndex == theIndex) return *anIter; } return GeomShapePtr(); // not found } + +void GeomAlgoAPI_NExplode::reorder(const ShapeOrder theNewOrder) +{ + NExplodeTools::CompareShapes shComp( + theNewOrder == ORDER_BY_HASH_VALUE ? NExplodeTools::pointToDouble : NExplodeTools::dummy); + std::stable_sort(mySorted.begin(), mySorted.end(), shComp); +}