Merge pull request #12525 from bgbsww/bgbsww-toponamingMakeElementSolid

Toponaming/Part: make element solid
This commit is contained in:
Chris Hennes
2024-02-22 21:18:51 -06:00
committed by GitHub
3 changed files with 127 additions and 0 deletions

View File

@@ -1750,6 +1750,46 @@ public:
CN,
};
/** Make a solid using shells or CompSolid
*
* @param shapes: input shapes of either shells or CompSolid.
* @param op: optional string to be encoded into topo naming for indicating
* the operation
*
* @return The function produces a solid. The original content of this
* TopoShape is discarded and replaced with the new shape. The
* function returns the TopoShape itself as a self reference so
* that multiple operations can be carried out for the same shape
* in the same line of code.
*/
// TODO: This does not appear to be called, and the implementation seems impossible
// TopoShape &makeElementSolid(const std::vector<TopoShape> &shapes, const char *op=nullptr);
/** Make a solid using shells or CompSolid
*
* @param shape: input shape of either a shell, a compound of shells, or a
* CompSolid.
* @param op: optional string to be encoded into topo naming for indicating
* the operation
*
* @return The function produces a solid. The original content of this
* TopoShape is discarded and replaced with the new shape. The
* function returns the TopoShape itself as a self reference so
* that multiple operations can be carried out for the same shape
* in the same line of code.
*/
TopoShape &makeElementSolid(const TopoShape &shape, const char *op=nullptr);
/** Make a solid using this shape
*
* @param op: optional string to be encoded into topo naming for indicating
* the operation
*
* @return The function returns a new solid using the shell or CompSolid
* inside this shape. The shape itself is not modified.
*/
TopoShape makeElementSolid(const char *op=nullptr) const {
return TopoShape(0,Hasher).makeElementSolid(*this,op);
}
/** Generic shape making with mapped element name from shape history
*

View File

@@ -50,6 +50,7 @@
#include <BRepBuilderAPI_Copy.hxx>
#include <BRepBuilderAPI_GTransform.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeSolid.hxx>
#include <BRepFilletAPI_MakeChamfer.hxx>
#include <BRepFilletAPI_MakeFillet.hxx>
#include <BRepBuilderAPI_Transform.hxx>
@@ -2700,6 +2701,65 @@ struct MapperThruSections: MapperMaker
}
};
// TODO: This method does not appear to ever be called in the codebase, and it is probably
// broken, because using TopoShape() with no parameters means the result will not have an
// element Map.
//TopoShape& TopoShape::makeElementSolid(const std::vector<TopoShape>& shapes, const char* op)
//{
// return makeElementSolid(TopoShape().makeElementCompound(shapes), op);
//}
TopoShape& TopoShape::makeElementSolid(const TopoShape& shape, const char* op)
{
if (!op) {
op = Part::OpCodes::Solid;
}
if (shape.isNull()) {
FC_THROWM(NullShapeException, "Null shape");
}
// first, if we were given a compsolid, try making a solid out of it
TopoDS_CompSolid compsolid;
int count = 0;
for (const auto& s : shape.getSubShapes(TopAbs_COMPSOLID)) {
++count;
compsolid = TopoDS::CompSolid(s);
if (count > 1) {
break;
}
}
if (count == 0) {
// no compsolids. Get shells...
BRepBuilderAPI_MakeSolid mkSolid;
count = 0;
for (const auto& s : shape.getSubShapes(TopAbs_SHELL)) {
++count;
mkSolid.Add(TopoDS::Shell(s));
}
if (count == 0) { // no shells?
FC_THROWM(Base::CADKernelError, "No shells or compsolids found in shape");
}
makeElementShape(mkSolid, shape, op);
TopoDS_Solid solid = TopoDS::Solid(_Shape);
BRepLib::OrientClosedSolid(solid);
setShape(solid, false);
}
else if (count == 1) {
BRepBuilderAPI_MakeSolid mkSolid(compsolid);
makeElementShape(mkSolid, shape, op);
}
else { // if (count > 1)
FC_THROWM(Base::CADKernelError,
"Only one compsolid can be accepted. "
"Provided shape has more than one compsolid.");
}
return *this;
}
TopoShape& TopoShape::makeElementFillet(const TopoShape& shape,
const std::vector<TopoShape>& edges,
double radius1,

View File

@@ -1939,4 +1939,31 @@ TEST_F(TopoShapeExpansionTest, makeElementGTransformWithMap)
// Not testing _makeElementTransform as it is a thin wrapper that calls the same places as the four
// preceding tests.
TEST_F(TopoShapeExpansionTest, makeElementSolid)
{
// Arrange
auto [cube1, cube2] = CreateTwoCubes();
auto tr {gp_Trsf()};
tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0)));
cube2.Move(TopLoc_Location(tr));
TopoShape topoShape1 {cube1, 1L};
TopoShape topoShape2 {cube2, 2L};
// Act
TopExp_Explorer exp(topoShape1.getShape(), TopAbs_SHELL);
auto shell1 = exp.Current();
exp.Init(topoShape2.getShape(), TopAbs_SHELL);
auto shell2 = exp.Current();
TopoShape& topoShape3 = topoShape1.makeElementCompound({shell1, shell2});
TopoShape& result = topoShape1.makeElementSolid(topoShape3); // Need the single parm form
auto elements = elementMap(result);
Base::BoundBox3d bb = result.getBoundBox();
// Assert shape is correct
EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0.0, -0.5, 0.0, 1.5, 1.0, 1.0)));
EXPECT_FLOAT_EQ(getVolume(result.getShape()), 2);
// Assert elementMap is correct
EXPECT_EQ(elements.size(), 52);
EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1);
EXPECT_EQ(elements[IndexedName("Face", 1)], MappedName("Face1;SLD;:H1:4,F"));
}
// NOLINTEND(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers)