Merge pull request #12483 from bgbsww/bgbsww-toponamingMakeElementThickSolid

Toponaming/Part make element thick solid
This commit is contained in:
Chris Hennes
2024-02-18 15:46:49 -06:00
committed by GitHub
3 changed files with 175 additions and 11 deletions

View File

@@ -194,6 +194,14 @@ enum class MapElement
map
};
/// Defines how to fill the holes that may appear after offset two adjacent faces
enum class JoinType
{
Arc,
Tangent,
Intersection,
};
/** The representation for a CAD Shape
*/
// NOLINTNEXTLINE cppcoreguidelines-special-member-functions
@@ -780,6 +788,53 @@ public:
}
//@}
/** Make a hollowed solid by removing some faces from a given solid
*
* @param source: input shape
* @param faces: list of faces to remove, must be sub shape of the input shape
* @param offset: thickness of the walls
* @param tol: tolerance criterion for coincidence in generated shapes
* @param intersection: whether to check intersection in all generated parallel.
* @param selfInter: whether to eliminate self intersection.
* @param offsetMode: defines the construction type of parallels applied to free edges
* @param join: join type. Only support JoinType::Arc and JoinType::Intersection.
* @param op: optional string to be encoded into topo naming for indicating
* the operation
*
* @return 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 &makeElementThickSolid(const TopoShape &source, const std::vector<TopoShape> &faces,
double offset, double tol, bool intersection = false, bool selfInter = false,
short offsetMode = 0, JoinType join = JoinType::Arc, const char *op=nullptr);
/** Make a hollowed solid by removing some faces from a given solid
*
* @param source: input shape
* @param faces: list of faces to remove, must be sub shape of the input shape
* @param offset: thickness of the walls
* @param tol: tolerance criterion for coincidence in generated shapes
* @param intersection: whether to check intersection in all generated parallel
* (OCCT document states the option is not fully implemented)
* @param selfInter: whether to eliminate self intersection
* (OCCT document states the option is not implemented)
* @param offsetMode: defines the construction type of parallels applied to free edges
* (OCCT document states the option is not implemented)
* @param join: join type. Only support JoinType::Arc and JoinType::Intersection.
* @param op: optional string to be encoded into topo naming for indicating
* the operation
*
* @return Return the generated new shape. The TopoShape itself is not modified.
*/
TopoShape makeElementThickSolid(const std::vector<TopoShape> &faces,
double offset, double tol, bool intersection = false, bool selfInter = false,
short offsetMode = 0, JoinType join = JoinType::Arc, const char *op=nullptr) const {
return TopoShape(0,Hasher).makeElementThickSolid(*this,faces,offset,tol,intersection,selfInter,
offsetMode,join,op);
}
/* Make a shell or solid by sweeping profile wire along a spine
*
* @params sources: source shapes. The first shape is used as spine. The

View File

@@ -52,6 +52,7 @@
#include <BRepLib.hxx>
#include <BRepOffsetAPI_DraftAngle.hxx>
#include <BRepOffsetAPI_MakePipe.hxx>
#include <BRepOffsetAPI_MakeThickSolid.hxx>
#include <BRepTools_WireExplorer.hxx>
#include <ShapeUpgrade_ShellSewing.hxx>
#include <TopTools_HSequenceOfShape.hxx>
@@ -2072,6 +2073,76 @@ TopoShape& TopoShape::makeElementPipeShell(const std::vector<TopoShape>& shapes,
return makeElementShape(mkPipeShell, shapes, op);
}
TopoShape& TopoShape::makeElementThickSolid(const TopoShape& shape,
const std::vector<TopoShape>& faces,
double offset,
double tol,
bool intersection,
bool selfInter,
short offsetMode,
JoinType join,
const char* op)
{
if (!op) {
op = Part::OpCodes::Thicken;
}
// we do not offer tangent join type
switch (join) {
case JoinType::Arc:
case JoinType::Intersection:
break;
default:
join = JoinType::Intersection;
}
if (shape.isNull()) {
FC_THROWM(NullShapeException, "Null shape");
}
if (faces.empty()) {
FC_THROWM(NullShapeException, "Null input shape");
}
if (fabs(offset) <= 2 * tol) {
*this = shape;
return *this;
}
TopTools_ListOfShape remFace;
for (auto& face : faces) {
if (face.isNull()) {
FC_THROWM(NullShapeException, "Null input shape");
}
if (!shape.findShape(face.getShape())) {
FC_THROWM(Base::CADKernelError, "face does not belong to the shape");
}
remFace.Append(face.getShape());
}
#if OCC_VERSION_HEX < 0x070200
BRepOffsetAPI_MakeThickSolid mkThick(shape.getShape(),
remFace,
offset,
tol,
BRepOffset_Mode(offsetMode),
intersection ? Standard_True : Standard_False,
selfInter ? Standard_True : Standard_False,
GeomAbs_JoinType(join));
#else
BRepOffsetAPI_MakeThickSolid mkThick;
mkThick.MakeThickSolidByJoin(shape.getShape(),
remFace,
offset,
tol,
BRepOffset_Mode(offsetMode),
intersection ? Standard_True : Standard_False,
selfInter ? Standard_True : Standard_False,
GeomAbs_JoinType(join));
#endif
return makeElementShape(mkThick, shape, op);
}
TopoShape& TopoShape::makeElementWires(const std::vector<TopoShape>& shapes,
const char* op,
double tol,

View File

@@ -1231,15 +1231,24 @@ TEST_F(TopoShapeExpansionTest, makeElementLinearizeFace)
TEST_F(TopoShapeExpansionTest, makeElementRuledSurfaceEdges)
{
// Arrange
auto [cube1, cube2] = CreateTwoCubes();
TopoShape cube1TS {cube1, 1L};
std::vector<TopoShape> subEdges = cube1TS.getSubTopoShapes(TopAbs_EDGE);
std::vector<TopoShape> shapes2 = {subEdges[0], subEdges[1]};
auto edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(0.0, 0.0, 8.0)).Edge();
auto edge2 = BRepBuilderAPI_MakeEdge(gp_Pnt(2.5, 0.0, 0.0), gp_Pnt(2.5, 0.0, 8.0)).Edge();
TopoShape edge1ts {edge1, 2L};
TopoShape edge2ts {edge2, 3L};
TopoShape topoShape {1L};
// Act
TopoShape result2 = cube1TS.makeElementRuledSurface(shapes2, 0); // TODO: direction as enum?
topoShape.makeElementRuledSurface({edge1ts, edge2ts}, 0); // TODO: orientation as enum?
auto elements = elementMap(topoShape);
// Assert
EXPECT_EQ(result2.countSubElements("Wire"), 1);
EXPECT_FLOAT_EQ(getArea(result2.getShape()), 0.32953611);
EXPECT_EQ(topoShape.countSubElements("Wire"), 1);
EXPECT_FLOAT_EQ(getArea(topoShape.getShape()), 20);
// Assert that we're creating a correct element map
EXPECT_TRUE(topoShape.getMappedChildElements().empty());
// TODO: Revisit these when resetElementMap() is fully worked through. Suspect that last loop
// of makeElementRuledSurface is dependent on this to create elementMaps.
// EXPECT_EQ(elements.size(), 24);
// EXPECT_EQ(elements.count(IndexedName("Edge", 1)), 1);
// EXPECT_EQ(elements[IndexedName("Edge", 1)], MappedName("Vertex1;:G;PSH;:H2:7,E"));
}
TEST_F(TopoShapeExpansionTest, makeElementRuledSurfaceWires)
@@ -1248,12 +1257,19 @@ TEST_F(TopoShapeExpansionTest, makeElementRuledSurfaceWires)
auto [cube1, cube2] = CreateTwoCubes();
TopoShape cube1TS {cube1, 1L};
std::vector<TopoShape> subWires = cube1TS.getSubTopoShapes(TopAbs_WIRE);
std::vector<TopoShape> shapes = {subWires[0], subWires[1]};
// Act
TopoShape result = cube1TS.makeElementRuledSurface(shapes, 0); // TODO: direction as enum?
cube1TS.makeElementRuledSurface({subWires[0], subWires[1]}, 0); // TODO: orientation as enum?
auto elements = elementMap(cube1TS);
// Assert
EXPECT_EQ(result.countSubElements("Wire"), 4);
EXPECT_FLOAT_EQ(getArea(result.getShape()), 2.023056);
EXPECT_EQ(cube1TS.countSubElements("Wire"), 4);
EXPECT_FLOAT_EQ(getArea(cube1TS.getShape()), 2.023056);
// Assert that we're creating a correct element map
EXPECT_TRUE(cube1TS.getMappedChildElements().empty());
// TODO: Revisit these when resetElementMap() is fully worked through. Suspect that last loop
// of makeElementRuledSurface is dependent on this to create elementMaps.
// EXPECT_EQ(elements.size(), 24);
// EXPECT_EQ(elements.count(IndexedName("Edge", 1)), 1);
// EXPECT_EQ(elements[IndexedName("Edge", 1)], MappedName("Vertex1;:G;PSH;:H2:7,E"));
}
TEST_F(TopoShapeExpansionTest, makeElementLoft)
@@ -1326,4 +1342,26 @@ TEST_F(TopoShapeExpansionTest, makeElementPipeShell)
EXPECT_EQ(elements[IndexedName("Edge", 1)], MappedName("Vertex1;:G;PSH;:H2:7,E"));
}
TEST_F(TopoShapeExpansionTest, makeElementThickSolid)
{
// Arrange
auto [cube1, cube2] = CreateTwoCubes();
TopoShape cube1TS {cube1, 1L};
std::vector<TopoShape> subFaces = cube1TS.getSubTopoShapes(TopAbs_FACE);
subFaces[0].Tag = 2L;
subFaces[1].Tag = 3L;
std::vector<TopoShape> shapes = {subFaces[0], subFaces[1]};
// Act
cube1TS.makeElementThickSolid(cube1TS, shapes, 0.1, 1e-07);
auto elements = elementMap(cube1TS);
// Assert
EXPECT_EQ(cube1TS.countSubElements("Wire"), 16);
EXPECT_FLOAT_EQ(getArea(cube1TS.getShape()), 9.4911509);
// Assert that we're creating a correct element map
EXPECT_TRUE(cube1TS.getMappedChildElements().empty());
EXPECT_EQ(elements.size(), 74);
EXPECT_EQ(elements.count(IndexedName("Edge", 1)), 1);
EXPECT_EQ(elements[IndexedName("Edge", 1)], MappedName("Edge11;THK;:H1:4,E"));
}
// NOLINTEND(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers)