X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGeomAPI%2FGeomAPI_Shape.cpp;h=7168ccdb5ac04c8bfc87a3aec94ac45d3a7b6a2b;hb=264b53a6292f1a50fbe94ffc62b931c4a047c256;hp=634cd575d886538ae7150b59ad4117473c415848;hpb=48437a8cb93ea1854212cedc3097c462b5c4c350;p=modules%2Fshaper.git diff --git a/src/GeomAPI/GeomAPI_Shape.cpp b/src/GeomAPI/GeomAPI_Shape.cpp index 634cd575d..7168ccdb5 100644 --- a/src/GeomAPI/GeomAPI_Shape.cpp +++ b/src/GeomAPI/GeomAPI_Shape.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2019 CEA/DEN, EDF R&D +// Copyright (C) 2014-2021 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 @@ -26,11 +26,13 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -44,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +55,7 @@ #include #include +#include #include #include // for std::transform @@ -91,11 +95,10 @@ bool GeomAPI_Shape::isEqual(const std::shared_ptr theShape) const bool GeomAPI_Shape::isSame(const std::shared_ptr theShape) const { - if (!theShape.get()) - return false; + bool isNullShape = !theShape.get() || theShape->isNull();; if (isNull()) - return theShape->isNull(); - if (theShape->isNull()) + return isNullShape; + if (isNullShape) return false; return MY_SHAPE->IsSame(theShape->impl()) == Standard_True; @@ -146,6 +149,32 @@ bool GeomAPI_Shape::isCompound() const return !aShape.IsNull() && aShape.ShapeType() == TopAbs_COMPOUND; } +bool GeomAPI_Shape::isCollectionOfSolids() const +{ + const TopoDS_Shape& aShape = const_cast(this)->impl(); + if (aShape.IsNull()) + return false; + + if (aShape.ShapeType() == TopAbs_SOLID || + aShape.ShapeType() == TopAbs_COMPSOLID) + return true; + + if (aShape.ShapeType() != TopAbs_COMPOUND) + return false; + + TopTools_ListOfShape aLS; + TopTools_MapOfShape aMFence; + BOPTools_AlgoTools::TreatCompound(aShape, aLS, &aMFence); + TopTools_ListOfShape::Iterator it(aLS); + for (; it.More(); it.Next()) { + const TopoDS_Shape& aSx = it.Value(); + if (aSx.ShapeType() != TopAbs_SOLID && + aSx.ShapeType() != TopAbs_COMPSOLID) + return false; + } + return true; +} + bool GeomAPI_Shape::isCompoundOfSolids() const { const TopoDS_Shape& aShape = const_cast(this)->impl(); @@ -226,9 +255,9 @@ bool GeomAPI_Shape::isConnectedTopology() const // (if shapes are connected, vertices are connected for sure) TopExp_Explorer anExp2(aNewIter.Value(), TopAbs_VERTEX); for(; !aConnected && anExp2.More(); anExp2.Next()) { - NCollection_List::Iterator aNotIter(aNotVertices); - for(; aNotIter.More(); aNotIter.Next()) { - if (aNotIter.Value().IsSame(anExp2.Current())) { + NCollection_List::Iterator aNotVIter(aNotVertices); + for(; aNotVIter.More(); aNotVIter.Next()) { + if (aNotVIter.Value().IsSame(anExp2.Current())) { aConnected = true; break; } @@ -286,15 +315,13 @@ bool GeomAPI_Shape::isPlanar() const if(aShapeType == TopAbs_VERTEX) { return true; } else if(aShapeType == TopAbs_FACE) { - const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface(TopoDS::Face(aShape)); - Handle(Standard_Type) aType = aSurface->DynamicType(); - - if(aType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) { + Handle(Geom_Surface) aSurface = BRep_Tool::Surface(TopoDS::Face(aShape)); + if(aSurface->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) { Handle(Geom_RectangularTrimmedSurface) aTrimSurface = - Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface); - aType = aTrimSurface->BasisSurface()->DynamicType(); + Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface); + aSurface = aTrimSurface->BasisSurface(); } - return (aType == STANDARD_TYPE(Geom_Plane)) == Standard_True; + return GeomLib_IsPlanarSurface(aSurface).IsPlanar(); } else { BRepBuilderAPI_FindPlane aFindPlane(aShape); bool isFound = aFindPlane.Found() == Standard_True; @@ -468,7 +495,8 @@ GeomAPI_Shape::ShapeType GeomAPI_Shape::shapeType() const GeomAPI_Shape::ShapeType GeomAPI_Shape::shapeTypeByStr(std::string theType) { - std::transform(theType.begin(), theType.end(), theType.begin(), ::toupper); + std::transform(theType.begin(), theType.end(), theType.begin(), + [](char c) { return static_cast(::toupper(c)); }); if (theType == "COMPOUND" || theType == "COMPOUNDS") return COMPOUND; if (theType == "COMPSOLID" || theType == "COMPSOLIDS") @@ -550,8 +578,6 @@ GeomAPI_Shape::Orientation GeomAPI_Shape::orientation() const void GeomAPI_Shape::setOrientation(const GeomAPI_Shape::Orientation theOrientation) { - TopAbs_Orientation anOrientation = MY_SHAPE->Orientation(); - switch(theOrientation) { case FORWARD: MY_SHAPE->Orientation(TopAbs_FORWARD); break; case REVERSED: MY_SHAPE->Orientation(TopAbs_REVERSED); break; @@ -594,7 +620,19 @@ bool GeomAPI_Shape::computeSize(double& theXmin, double& theYmin, double& theZmi if (aShape.IsNull()) return false; Bnd_Box aBndBox; - BRepBndLib::Add(aShape, aBndBox, false); + // Workaround: compute optimal bounding box for the compounds of edges/vertices, because sometimes + // the bounding box of sketch is calculated if the transformation is applied twice (issue #20167). + bool isShape1D = false; + if (aShape.ShapeType() == TopAbs_COMPOUND) { + isShape1D = true; + for (TopoDS_Iterator anIt(aShape); anIt.More() && isShape1D; anIt.Next()) + if (anIt.Value().ShapeType() < TopAbs_WIRE) + isShape1D = false; + } + if (isShape1D) + BRepBndLib::AddOptimal(aShape, aBndBox, false, true); + else + BRepBndLib::Add(aShape, aBndBox, false); if (aBndBox.IsVoid()) return false; aBndBox.Get(theXmin, theYmin, theZmin, theXmax, theYmax, theZmax); @@ -637,11 +675,22 @@ GeomPointPtr GeomAPI_Shape::middlePoint() const } // LCOV_EXCL_START -std::string GeomAPI_Shape::getShapeStream() const +std::string GeomAPI_Shape::getShapeStream(const bool theWithTriangulation) const { std::ostringstream aStream; const TopoDS_Shape& aShape = const_cast(this)->impl(); - BRepTools::Write(aShape, aStream); + if (!theWithTriangulation) { // make a copy of shape without triangulation + BRepBuilderAPI_Copy aCopy(aShape, Standard_False, Standard_False); + const TopoDS_Shape& aCopyShape = aCopy.Shape(); + // make all faces unchecked to make the stream of shapes the same + TopExp_Explorer aFaceExp(aCopyShape, TopAbs_FACE); + for(; aFaceExp.More(); aFaceExp.Next()) { + aFaceExp.Current().TShape()->Checked(Standard_False); + } + BRepTools::Write(aCopyShape, aStream); + } else { + BRepTools::Write(aShape, aStream); + } return aStream.str(); } // LCOV_EXCL_STOP @@ -699,6 +748,12 @@ void GeomAPI_Shape::translate(const std::shared_ptr theDir, const d setImpl(new TopoDS_Shape(aResult)); } +void GeomAPI_Shape::move(const std::shared_ptr theTransformation) +{ + TopoDS_Shape aResult = MY_SHAPE->Moved(theTransformation->impl()); + setImpl(new TopoDS_Shape(aResult)); +} + bool GeomAPI_Shape::isSelfIntersected(const int theLevelOfCheck) const { BOPAlgo_CheckerSI aCSI; // checker of self-interferences @@ -718,7 +773,15 @@ bool GeomAPI_Shape::isSelfIntersected(const int theLevelOfCheck) const bool GeomAPI_Shape::Comparator::operator()(const std::shared_ptr& theShape1, const std::shared_ptr& theShape2) const { - return theShape1->impl().TShape() < theShape2->impl().TShape(); + const TopoDS_Shape& aShape1 = theShape1->impl(); + const TopoDS_Shape& aShape2 = theShape2->impl(); + bool isLess = aShape1.TShape() < aShape2.TShape(); + if (aShape1.TShape() == aShape2.TShape()) { + Standard_Integer aHash1 = aShape1.Location().HashCode(IntegerLast()); + Standard_Integer aHash2 = aShape2.Location().HashCode(IntegerLast()); + isLess = aHash1 < aHash2; + } + return isLess; } bool GeomAPI_Shape::ComparatorWithOri::operator()( @@ -727,7 +790,30 @@ bool GeomAPI_Shape::ComparatorWithOri::operator()( { const TopoDS_Shape& aShape1 = theShape1->impl(); const TopoDS_Shape& aShape2 = theShape2->impl(); - return (aShape1.TShape() < aShape2.TShape()) || - (aShape1.TShape() == aShape2.TShape() && - aShape1.Orientation() < aShape2.Orientation()); + bool isLess = aShape1.TShape() < aShape2.TShape(); + if (aShape1.TShape() == aShape2.TShape()) { + Standard_Integer aHash1 = aShape1.Location().HashCode(IntegerLast()); + Standard_Integer aHash2 = aShape2.Location().HashCode(IntegerLast()); + isLess = (aHash1 < aHash2) || + (aHash1 == aHash2 && aShape1.Orientation() < aShape2.Orientation()); + } + return isLess; +} + +int GeomAPI_Shape::Hash::operator()(const std::shared_ptr& theShape) const +{ + const TopoDS_Shape& aShape = theShape->impl(); + return aShape.HashCode(IntegerLast()); +} + +bool GeomAPI_Shape::Equal::operator()(const std::shared_ptr& theShape1, + const std::shared_ptr& theShape2) const +{ + const TopoDS_Shape& aShape1 = theShape1->impl(); + const TopoDS_Shape& aShape2 = theShape2->impl(); + + Standard_Integer aHash1 = aShape1.Location().HashCode(IntegerLast()); + Standard_Integer aHash2 = aShape2.Location().HashCode(IntegerLast()); + + return aShape1.TShape() == aShape2.TShape() && aHash1 == aHash2; }