-// Copyright (C) 2014-2020 CEA/DEN, EDF R&D
+// Copyright (C) 2014-2024 CEA, EDF
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
#include <Geom_Plane.hxx>
#include <Geom_RectangularTrimmedSurface.hxx>
#include <Geom_TrimmedCurve.hxx>
+#include <GeomLib_IsPlanarSurface.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Iterator.hxx>
#include <BOPAlgo_CheckerSI.hxx>
#include <BOPDS_DS.hxx>
+#include <BOPTools_AlgoTools.hxx>
#include <sstream>
#include <algorithm> // for std::transform
return !aShape.IsNull() && aShape.ShapeType() == TopAbs_COMPOUND;
}
+bool GeomAPI_Shape::isCollectionOfSolids() const
+{
+ const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
+ 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<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
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;
- if(!isFound && aShapeType == TopAbs_EDGE) {
- Standard_Real aFirst, aLast;
- Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(aShape), aFirst, aLast);
- Handle(Standard_Type) aType = aCurve->DynamicType();
+ if(!isFound) {
- if(aType == STANDARD_TYPE(Geom_TrimmedCurve)) {
- Handle(Geom_TrimmedCurve) aTrimCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve);
- aType = aTrimCurve->BasisCurve()->DynamicType();
- }
+ auto checkEdge = [](const TopoDS_Shape& theShape){
+ if(theShape.ShapeType()!= TopAbs_EDGE)
+ return false;
- if(aType == STANDARD_TYPE(Geom_Line)
- || aType == STANDARD_TYPE(Geom_Conic)
- || aType == STANDARD_TYPE(Geom_Circle)
- || aType == STANDARD_TYPE(Geom_Ellipse)
- || aType == STANDARD_TYPE(Geom_Hyperbola)
- || aType == STANDARD_TYPE(Geom_Parabola)) {
- isFound = true;
+ Standard_Real aFirst, aLast;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(theShape), aFirst, aLast);
+ Handle(Standard_Type) aType = aCurve->DynamicType();
+ if(aType == STANDARD_TYPE(Geom_TrimmedCurve)) {
+ Handle(Geom_TrimmedCurve) aTrimCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve);
+ aType = aTrimCurve->BasisCurve()->DynamicType();
+ }
+
+ if(aType == STANDARD_TYPE(Geom_Line)
+ || aType == STANDARD_TYPE(Geom_Conic)
+ || aType == STANDARD_TYPE(Geom_Circle)
+ || aType == STANDARD_TYPE(Geom_Ellipse)
+ || aType == STANDARD_TYPE(Geom_Hyperbola)
+ || aType == STANDARD_TYPE(Geom_Parabola)) {
+ return true;
+ }
+ return false;
+ };
+
+ if(aShapeType == TopAbs_WIRE){
+ //check if wire consist of only one edge
+ int aNbEdges = 0;
+ TopExp_Explorer anExp(aShape, TopAbs_EDGE);
+ for (TopExp_Explorer anExp(aShape, TopAbs_EDGE); anExp.More(); anExp.Next()) {
+ aNbEdges++;
+ if(aNbEdges == 1){
+ const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current());
+ isFound = checkEdge(anEdge);
+ }
+ else{
+ //if more than one edge, check is not valid
+ isFound = false;
+ break;
+ }
+ }
+ }
+ else if(aShapeType == TopAbs_EDGE){
+ isFound = checkEdge(aShape);
}
}
}
std::list<std::shared_ptr<GeomAPI_Shape> >
-GeomAPI_Shape::subShapes(ShapeType theSubShapeType) const
+GeomAPI_Shape::subShapes(const ShapeType theSubShapeType, const bool theOnlyUnique) const
{
ListOfShape aSubs;
const TopoDS_Shape& aShape = impl<TopoDS_Shape>();
if (aShape.IsNull())
return aSubs;
+ TopTools_MapOfShape alreadyThere;
+
// process multi-level compounds
if (shapeType() == COMPOUND && theSubShapeType == COMPOUND) {
for (TopoDS_Iterator anIt(aShape); anIt.More(); anIt.Next()) {
const TopoDS_Shape& aCurrent = anIt.Value();
if (aCurrent.ShapeType() == TopAbs_COMPOUND) {
- GeomShapePtr aSub(new GeomAPI_Shape);
- aSub->setImpl(new TopoDS_Shape(aCurrent));
- aSubs.push_back(aSub);
+ if (!theOnlyUnique || alreadyThere.Add(aCurrent)) {
+ GeomShapePtr aSub(new GeomAPI_Shape);
+ aSub->setImpl(new TopoDS_Shape(aCurrent));
+ aSubs.push_back(aSub);
+ }
}
}
// add self
else {
for (TopExp_Explorer anExp(aShape, (TopAbs_ShapeEnum)theSubShapeType);
anExp.More(); anExp.Next()) {
- GeomShapePtr aSub(new GeomAPI_Shape);
- aSub->setImpl(new TopoDS_Shape(anExp.Current()));
- aSubs.push_back(aSub);
+ if (!theOnlyUnique || alreadyThere.Add(anExp.Current())) {
+ GeomShapePtr aSub(new GeomAPI_Shape);
+ aSub->setImpl(new TopoDS_Shape(anExp.Current()));
+ aSubs.push_back(aSub);
+ }
}
}
return aSubs;
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<char>(::toupper(c)); });
if (theType == "COMPOUND" || theType == "COMPOUNDS")
return COMPOUND;
if (theType == "COMPSOLID" || theType == "COMPSOLIDS")
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);