Toponaming/Part: Transfer makeElementBoolean in

This commit is contained in:
Zheng, Lei
2024-01-22 19:58:54 -05:00
committed by bgbsww
parent 03b41403fa
commit 10d95b9ce9
3 changed files with 388 additions and 78 deletions

View File

@@ -911,6 +911,61 @@ public:
return TopoShape(Tag, Hasher).makeElementCopy(*this, op, copyGeom, copyMesh);
}
/** Generalized shape making with mapped element name from shape history
*
* @param maker: op code from OpCodes
* @param sources: list of source shapes.
* @param op: optional string to be encoded into topo naming for indicating
* the operation
* @param tol: tolerance option available to some shape making algorithm
*
* @return The original content of this TopoShape is discarded and replaced
* with the new shape built by the shape maker. 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& makeElementBoolean(const char* maker,
const std::vector<TopoShape>& sources,
const char* op = nullptr,
double tol = 0.0);
/** Generalized shape making with mapped element name from shape history
*
* @param maker: op code from TopoShapeOpCodes
* @param source: source shape.
* @param op: optional string to be encoded into topo naming for indicating
* the operation
* @param tol: tolerance option available to some shape making algorithm
*
* @return The original content of this TopoShape is discarded and replaced
* with the new shape built by the shape maker. 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& makeElementBoolean(const char* maker,
const TopoShape& source,
const char* op = nullptr,
double tol = 0.0);
/** Generalized shape making with mapped element name from shape history
*
* @param maker: op code from TopoShapeOpCodes
* @param op: optional string to be encoded into topo naming for indicating
* the operation
* @param tol: tolerance option available to some shape making algorithm
*
* @return Returns the new shape with mappend element name generated from
* shape history using this shape as the source. The shape itself
* is not modified.
*/
TopoShape
makeElementBoolean(const char* maker, const char* op = nullptr, double tol = 0.0) const
{
return TopoShape(0, Hasher).makeElementBoolean(maker, *this, op, tol);
}
/* Make a shell using this shape
* @param silent: whether to throw exception on failure
* @param op: optional string to be encoded into topo naming for indicating

View File

@@ -34,11 +34,26 @@
#include <BRepFill_Generator.hxx>
#include <BRepTools.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepAlgoAPI_BooleanOperation.hxx>
#include <BRepAlgoAPI_Common.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepAlgoAPI_Fuse.hxx>
#include <BRepAlgoAPI_Section.hxx>
#include <BRepBuilderAPI_Copy.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepCheck_Analyzer.hxx>
#include <BRepOffsetAPI_MakePipe.hxx>
#include <ShapeUpgrade_ShellSewing.hxx>
#include <TopTools_HSequenceOfShape.hxx>
#include <Precision.hxx>
#include <ShapeBuild_ReShape.hxx>
#include <ShapeAnalysis_FreeBounds.hxx>
#include <BRepTools.hxx>
#include <ShapeFix_Shape.hxx>
#include <ShapeFix_ShapeTolerance.hxx>
#include <ShapeUpgrade_ShellSewing.hxx>
#include <gp_Pln.hxx>
#include <utility>
@@ -46,6 +61,7 @@
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <TopTools_HSequenceOfShape.hxx>
#include <ShapeAnalysis_FreeBounds.hxx>
#endif
#include "TopoShape.h"
@@ -56,12 +72,27 @@
#include "TopoShapeOpCode.h"
#include <App/ElementNamingUtils.h>
#include <BRepLib.hxx>
#include <OSD_Parallel.hxx>
FC_LOG_LEVEL_INIT("TopoShape", true, true) // NOLINT
namespace Part
{
static void expandCompound(const TopoShape& shape, std::vector<TopoShape>& res)
{
if (shape.isNull()) {
FC_THROWM(NullShapeException, "Null input shape");
}
if (shape.getShape().ShapeType() != TopAbs_COMPOUND) {
res.push_back(shape);
return;
}
for (auto& s : shape.getSubTopoShapes()) {
expandCompound(s, res);
}
}
void TopoShape::initCache(int reset) const
{
if (reset > 0 || !_cache || _cache->isTouched(_Shape)) {
@@ -2362,4 +2393,227 @@ bool TopoShape::fixSolidOrientation()
return false;
}
TopoShape&
TopoShape::makeElementBoolean(const char* maker, const TopoShape& shape, const char* op, double tolerance)
{
return makeElementBoolean(maker, std::vector<TopoShape>(1, shape), op, tolerance);
}
TopoShape& TopoShape::makeElementBoolean(const char* maker,
const std::vector<TopoShape>& shapes,
const char* op,
double tolerance)
{
#if OCC_VERSION_HEX <= 0x060800
if (tolerance > 0.0) {
Standard_Failure::Raise("Fuzzy Booleans are not supported in this version of OCCT");
}
#endif
if (!maker) {
FC_THROWM(Base::CADKernelError, "no maker");
}
if (!op) {
op = maker;
}
if (shapes.empty()) {
FC_THROWM(NullShapeException, "Null shape");
}
if (strcmp(maker, Part::OpCodes::Compound) == 0) {
return makeElementCompound(shapes, op, SingleShapeCompoundCreationPolicy::returnShape);
}
else if (boost::starts_with(maker, Part::OpCodes::Face)) {
std::string prefix(Part::OpCodes::Face);
prefix += '.';
const char* face_maker = 0;
if (boost::starts_with(maker, prefix)) {
face_maker = maker + prefix.size();
}
return makeElementFace(shapes, op, face_maker);
}
else if (strcmp(maker, Part::OpCodes::Wire) == 0) {
return makeElementWires(shapes, op);
}
else if (strcmp(maker, Part::OpCodes::Compsolid) == 0) {
BRep_Builder builder;
TopoDS_CompSolid Comp;
builder.MakeCompSolid(Comp);
for (auto& s : shapes) {
if (!s.isNull()) {
builder.Add(Comp, s.getShape());
}
}
setShape(Comp);
mapSubElement(shapes, op);
return *this;
}
if (strcmp(maker, Part::OpCodes::Pipe) == 0) {
if (shapes.size() != 2) {
FC_THROWM(Base::CADKernelError, "Not enough input shapes");
}
if (shapes[0].isNull() || shapes[1].isNull()) {
FC_THROWM(Base::CADKernelError, "Cannot sweep along empty spine");
}
if (shapes[0].getShape().ShapeType() != TopAbs_WIRE) {
FC_THROWM(Base::CADKernelError, "Spine shape is not a wire");
}
BRepOffsetAPI_MakePipe mkPipe(TopoDS::Wire(shapes[0].getShape()), shapes[1].getShape());
return makeElementShape(mkPipe, shapes, op);
}
if (strcmp(maker, Part::OpCodes::Shell) == 0) {
BRep_Builder builder;
TopoDS_Shell shell;
builder.MakeShell(shell);
for (auto& s : shapes) {
builder.Add(shell, s.getShape());
}
setShape(shell);
mapSubElement(shapes, op);
BRepCheck_Analyzer check(shell);
if (!check.IsValid()) {
ShapeUpgrade_ShellSewing sewShell;
setShape(sewShell.ApplySewing(shell), false);
// TODO confirm the above won't change OCCT topological naming
}
return *this;
}
bool buildShell = true;
std::vector<TopoShape> _shapes;
if (strcmp(maker, Part::OpCodes::Fuse) == 0) {
for (auto it = shapes.begin(); it != shapes.end(); ++it) {
auto& s = *it;
if (s.isNull()) {
FC_THROWM(NullShapeException, "Null input shape");
}
if (s.shapeType() == TopAbs_COMPOUND) {
if (_shapes.empty()) {
_shapes.insert(_shapes.end(), shapes.begin(), it);
}
expandCompound(s, _shapes);
}
else if (_shapes.size()) {
_shapes.push_back(s);
}
}
}
else if (strcmp(maker, Part::OpCodes::Cut) == 0) {
for (unsigned i = 1; i < shapes.size(); ++i) {
auto& s = shapes[i];
if (s.isNull()) {
FC_THROWM(NullShapeException, "Null input shape");
}
if (s.shapeType() == TopAbs_COMPOUND) {
if (_shapes.empty()) {
_shapes.insert(_shapes.end(), shapes.begin(), shapes.begin() + i);
}
expandCompound(s, _shapes);
}
else if (_shapes.size()) {
_shapes.push_back(s);
}
}
}
if (tolerance > 0.0 && _shapes.empty()) {
_shapes = shapes;
}
const auto& inputs = _shapes.size() ? _shapes : shapes;
if (inputs.empty()) {
FC_THROWM(NullShapeException, "Null input shape");
}
if (inputs.size() == 1) {
*this = inputs[0];
if (shapes.size() == 1) {
// _shapes has fewer items than shapes due to compound expansion.
// Only warn if the caller paseses one shape.
FC_WARN("Boolean operation with only one shape input");
}
return *this;
}
std::unique_ptr<BRepAlgoAPI_BooleanOperation> mk;
if (strcmp(maker, Part::OpCodes::Fuse) == 0) {
mk.reset(new BRepAlgoAPI_Fuse);
}
else if (strcmp(maker, Part::OpCodes::Cut) == 0) {
mk.reset(new BRepAlgoAPI_Cut);
}
else if (strcmp(maker, Part::OpCodes::Common) == 0) {
mk.reset(new BRepAlgoAPI_Common);
}
else if (strcmp(maker, Part::OpCodes::Section) == 0) {
mk.reset(new BRepAlgoAPI_Section);
buildShell = false;
}
else {
FC_THROWM(Base::CADKernelError, "Unknown maker");
}
TopTools_ListOfShape shapeArguments, shapeTools;
int i = -1;
for (const auto& shape : inputs) {
if (shape.isNull()) {
FC_THROWM(NullShapeException, "Null input shape");
}
if (++i == 0) {
shapeArguments.Append(shape.getShape());
}
else if (tolerance > 0.0) {
auto& s = _shapes[i];
// workaround for http://dev.opencascade.org/index.php?q=node/1056#comment-520
s.setShape(BRepBuilderAPI_Copy(s.getShape()).Shape(), false);
shapeTools.Append(s.getShape());
}
else {
shapeTools.Append(shape.getShape());
}
}
#if OCC_VERSION_HEX >= 0x070500
// Can't find this threshold value anywhere. Go ahead assuming it is true.
// if (PartParams::getParallelRunThreshold() > 0) {
mk->SetRunParallel(Standard_True);
OSD_Parallel::SetUseOcctThreads(Standard_True);
// }
#else
// Only run parallel
if (shapeArguments.Size() + shapeTools.Size() > 2) {
mk->SetRunParallel(true);
}
else if (PartParams::getParallelRunThreshold() > 0) {
int total = 0;
for (const auto& shape : inputs) {
total += shape.countSubShapes(TopAbs_FACE);
if (total > PartParams::getParallelRunThreshold()) {
mk->SetRunParallel(true);
break;
}
}
}
#endif
mk->SetArguments(shapeArguments);
mk->SetTools(shapeTools);
if (tolerance > 0.0) {
mk->SetFuzzyValue(tolerance);
}
mk->Build();
makeElementShape(*mk, inputs, op);
if (buildShell) {
makeElementShell();
}
return *this;
}
} // namespace Part

View File

@@ -19,6 +19,7 @@
// NOLINTBEGIN(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers)
using namespace Part;
using namespace PartTestHelpers;
class TopoShapeExpansionTest: public ::testing::Test
@@ -53,13 +54,13 @@ TEST_F(TopoShapeExpansionTest, makeElementCompoundOneShapeReturnsShape)
{
// Arrange
auto edge = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge();
Part::TopoShape topoShape {edge};
std::vector<Part::TopoShape> shapes {topoShape};
TopoShape topoShape {edge};
std::vector<TopoShape> shapes {topoShape};
// Act
topoShape.makeElementCompound(shapes,
"C",
Part::TopoShape::SingleShapeCompoundCreationPolicy::
TopoShape::SingleShapeCompoundCreationPolicy::
returnShape /*Don't force the creation*/);
// Assert
@@ -70,14 +71,14 @@ TEST_F(TopoShapeExpansionTest, makeElementCompoundOneShapeForceReturnsCompound)
{
// Arrange
auto edge = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge();
Part::TopoShape topoShape {edge};
std::vector<Part::TopoShape> shapes {topoShape};
TopoShape topoShape {edge};
std::vector<TopoShape> shapes {topoShape};
// Act
topoShape.makeElementCompound(
shapes,
"C",
Part::TopoShape::SingleShapeCompoundCreationPolicy::forceCompound /*Force the creation*/);
TopoShape::SingleShapeCompoundCreationPolicy::forceCompound /*Force the creation*/);
// Assert
EXPECT_NE(edge.ShapeType(), topoShape.getShape().ShapeType()); // No longer the same thing
@@ -88,8 +89,8 @@ TEST_F(TopoShapeExpansionTest, makeElementCompoundTwoShapesReturnsCompound)
// Arrange
auto edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge();
auto edge2 = BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 0.0, 0.0), gp_Pnt(2.0, 0.0, 0.0)).Edge();
Part::TopoShape topoShape {edge1};
std::vector<Part::TopoShape> shapes {edge1, edge2};
TopoShape topoShape {edge1};
std::vector<TopoShape> shapes {edge1, edge2};
// Act
topoShape.makeElementCompound(shapes);
@@ -102,8 +103,8 @@ TEST_F(TopoShapeExpansionTest, makeElementCompoundEmptyShapesReturnsEmptyCompoun
{
// Arrange
auto edge = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge();
Part::TopoShape topoShape {edge};
std::vector<Part::TopoShape> shapes;
TopoShape topoShape {edge};
std::vector<TopoShape> shapes;
// Act
topoShape.makeElementCompound(shapes);
@@ -121,8 +122,8 @@ TEST_F(TopoShapeExpansionTest, makeElementCompoundTwoShapesGeneratesMap)
// Arrange
auto edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge();
auto edge2 = BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 0.0, 0.0), gp_Pnt(2.0, 0.0, 0.0)).Edge();
Part::TopoShape topoShape {edge1};
std::vector<Part::TopoShape> shapes {edge1, edge2};
TopoShape topoShape {edge1};
std::vector<TopoShape> shapes {edge1, edge2};
// Act
topoShape.makeElementCompound(shapes);
@@ -135,13 +136,13 @@ TEST_F(TopoShapeExpansionTest, makeElementCompoundTwoCubes)
{
// Arrange
auto [cube1, cube2] = CreateTwoCubes();
Part::TopoShape cube1TS {cube1};
TopoShape cube1TS {cube1};
cube1TS.Tag = 1;
Part::TopoShape cube2TS {cube2};
TopoShape cube2TS {cube2};
cube2TS.Tag = 2;
// Act
Part::TopoShape topoShape;
TopoShape topoShape;
topoShape.makeElementCompound({cube1TS, cube2TS});
// Assert
@@ -261,8 +262,8 @@ TEST_F(TopoShapeExpansionTest, MapperMakerGenerated)
// // Arrange
// auto edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge();
// auto edge2 = BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 0.0, 0.0), gp_Pnt(2.0, 0.0, 0.0)).Edge();
// Part::TopoShape topoShape;
// std::vector<Part::TopoShape> shapes {edge1, edge2};
// TopoShape topoShape;
// std::vector<TopoShape> shapes {edge1, edge2};
// // Act
// topoShape.makeElementWires(shapes);
@@ -281,11 +282,11 @@ TEST_F(TopoShapeExpansionTest, makeElementFaceNull)
const float Wid = 2;
const float Rad = 1;
auto [face1, wire1, wire2] = CreateFaceWithRoundHole(Len, Wid, Rad);
Part::TopoShape topoShape {face1};
TopoShape topoShape {face1};
double area = getArea(face1);
double area1 = getArea(topoShape.getShape());
// Act
Part::TopoShape newFace = topoShape.makeElementFace(nullptr);
TopoShape newFace = topoShape.makeElementFace(nullptr);
double area2 = getArea(newFace.getShape());
double area3 = getArea(topoShape.getShape());
// Assert
@@ -304,11 +305,11 @@ TEST_F(TopoShapeExpansionTest, makeElementFaceSimple)
const float Wid = 2;
const float Rad = 1;
auto [face1, wire1, wire2] = CreateFaceWithRoundHole(Len, Wid, Rad);
Part::TopoShape topoShape {face1};
TopoShape topoShape {face1};
double area = getArea(face1);
double area1 = getArea(topoShape.getShape());
// Act
Part::TopoShape newFace = topoShape.makeElementFace(wire1);
TopoShape newFace = topoShape.makeElementFace(wire1);
double area2 = getArea(newFace.getShape());
double area3 = getArea(topoShape.getShape());
// Assert
@@ -328,11 +329,11 @@ TEST_F(TopoShapeExpansionTest, makeElementFaceParams)
const float Wid = 2;
const float Rad = 1;
auto [face1, wire1, wire2] = CreateFaceWithRoundHole(Len, Wid, Rad);
Part::TopoShape topoShape {face1, 1L};
TopoShape topoShape {face1, 1L};
double area = getArea(face1);
double area1 = getArea(topoShape.getShape());
// Act
Part::TopoShape newFace =
TopoShape newFace =
topoShape.makeElementFace(wire1, "Cut", "Part::FaceMakerBullseye", nullptr);
double area2 = getArea(newFace.getShape());
double area3 = getArea(topoShape.getShape());
@@ -353,11 +354,11 @@ TEST_F(TopoShapeExpansionTest, makeElementFaceFromFace)
const float Wid = 2;
const float Rad = 1;
auto [face1, wire1, wire2] = CreateFaceWithRoundHole(Len, Wid, Rad);
Part::TopoShape topoShape {face1, 1L};
TopoShape topoShape {face1, 1L};
double area = getArea(face1);
double area1 = getArea(topoShape.getShape());
// Act
Part::TopoShape newFace =
TopoShape newFace =
topoShape.makeElementFace(face1, "Cut", "Part::FaceMakerBullseye", nullptr);
double area2 = getArea(newFace.getShape());
double area3 = getArea(topoShape.getShape());
@@ -379,11 +380,11 @@ TEST_F(TopoShapeExpansionTest, makeElementFaceOpenWire)
const float Wid = 2;
const float Rad = 1;
auto [face1, wire1, wire2] = CreateFaceWithRoundHole(Len, Wid, Rad);
Part::TopoShape topoShape {wire1, 1L};
TopoShape topoShape {wire1, 1L};
double area = getArea(face1);
double area1 = getArea(topoShape.getShape());
// Act
Part::TopoShape newFace = topoShape.makeElementFace(wire1, "Cut", nullptr, nullptr);
TopoShape newFace = topoShape.makeElementFace(wire1, "Cut", nullptr, nullptr);
double area2 = getArea(newFace.getShape());
double area3 = getArea(topoShape.getShape());
// Assert
@@ -404,11 +405,11 @@ TEST_F(TopoShapeExpansionTest, makeElementFaceClosedWire)
const float Wid = 2;
const float Rad = 1;
auto [face1, wire1, wire2] = CreateFaceWithRoundHole(Len, Wid, Rad);
Part::TopoShape topoShape {wire2, 1L};
TopoShape topoShape {wire2, 1L};
double area = getArea(face1);
double area1 = getArea(topoShape.getShape());
// Act
Part::TopoShape newFace =
TopoShape newFace =
topoShape.makeElementFace(wire2, "Cut", "Part::FaceMakerBullseye", nullptr);
double area2 = getArea(newFace.getShape());
double area3 = getArea(topoShape.getShape());
@@ -432,7 +433,7 @@ TEST_F(TopoShapeExpansionTest, makeElementFaceClosedWire)
TEST_F(TopoShapeExpansionTest, setElementComboNameNothing)
{
// Arrange
Part::TopoShape topoShape(1L);
TopoShape topoShape(1L);
// Act
Data::MappedName result = topoShape.setElementComboName(Data::IndexedName(), {});
// ASSERT
@@ -444,7 +445,7 @@ TEST_F(TopoShapeExpansionTest, setElementComboNameSimple)
{
// Arrange
auto edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge();
Part::TopoShape topoShape(edge1, 1L);
TopoShape topoShape(edge1, 1L);
topoShape.setElementMap({}); // Initialize the map to avoid a segfault.
// Also, maybe the end of TopoShape::mapSubElementTypeForShape should enforce that elementMap()
// isn't nullptr to eliminate the segfault.
@@ -460,7 +461,7 @@ TEST_F(TopoShapeExpansionTest, setElementComboNameSimple)
TEST_F(TopoShapeExpansionTest, setElementComboName)
{
// Arrange
Part::TopoShape topoShape(2L);
TopoShape topoShape(2L);
topoShape.setElementMap({});
Data::MappedName edgeName =
topoShape.getMappedName(Data::IndexedName::fromConst("Edge", 1), true);
@@ -472,7 +473,7 @@ TEST_F(TopoShapeExpansionTest, setElementComboName)
// Act
Data::MappedName result = topoShape.setElementComboName(Data::IndexedName::fromConst("Edge", 1),
{edgeName, faceName, faceName2},
Part::OpCodes::Common,
OpCodes::Common,
op);
// Assert
EXPECT_STREQ(result.toString().c_str(), "Edge1;CMN(Face7|Face8);Copy");
@@ -485,7 +486,7 @@ TEST_F(TopoShapeExpansionTest, setElementComboNameCompound)
auto edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge();
auto wire1 = BRepBuilderAPI_MakeWire({edge1}).Wire();
auto wire2 = BRepBuilderAPI_MakeWire({edge1}).Wire();
Part::TopoShape topoShape(2L);
TopoShape topoShape(2L);
topoShape.makeElementCompound({wire1, wire2}); // Quality of shape doesn't matter
Data::MappedName edgeName =
topoShape.getMappedName(Data::IndexedName::fromConst("Edge", 1), true);
@@ -497,7 +498,7 @@ TEST_F(TopoShapeExpansionTest, setElementComboNameCompound)
// Act
Data::MappedName result = topoShape.setElementComboName(Data::IndexedName::fromConst("Edge", 1),
{edgeName, faceName, faceName2},
Part::OpCodes::Common,
OpCodes::Common,
op);
// ASSERT
EXPECT_STREQ(result.toString().c_str(), "Edge1;:H,E;CMN(Face7|Face8);Copy");
@@ -511,18 +512,18 @@ TEST_F(TopoShapeExpansionTest, splitWires)
const float Wid = 2;
const float Rad = 1;
auto [face1, wire1, wire2] = CreateFaceWithRoundHole(Len, Wid, Rad);
Part::TopoShape topoShape {face1, 1L};
std::vector<Part::TopoShape> inner;
TopoShape topoShape {face1, 1L};
std::vector<TopoShape> inner;
// Act
EXPECT_EQ(topoShape.getShape().Orientation(), TopAbs_FORWARD);
Part::TopoShape wire =
topoShape.splitWires(&inner, Part::TopoShape::SplitWireReorient::ReorientReversed);
TopoShape wire =
topoShape.splitWires(&inner, TopoShape::SplitWireReorient::ReorientReversed);
// Assert
EXPECT_EQ(inner.size(), 1);
EXPECT_FLOAT_EQ(getLength(wire.getShape()), 2 + 2 + 3 + 3);
EXPECT_FLOAT_EQ(getLength(inner.front().getShape()), M_PI * Rad * 2);
EXPECT_EQ(wire.getShape().Orientation(), TopAbs_REVERSED);
for (Part::TopoShape& shape : inner) {
for (TopoShape& shape : inner) {
EXPECT_EQ(shape.getShape().Orientation(), TopAbs_FORWARD);
}
}
@@ -536,28 +537,28 @@ TEST_F(TopoShapeExpansionTest, mapSubElementInvalidParm)
{
// Arrange
auto [cube1, cube2] = CreateTwoCubes();
Part::TopoShape cube1TS {cube1};
TopoShape cube1TS {cube1};
cube1TS.Tag = 1;
// Act
std::vector<Part::TopoShape> subShapes = cube1TS.getSubTopoShapes(TopAbs_FACE);
Part::TopoShape face1 = subShapes.front();
std::vector<TopoShape> subShapes = cube1TS.getSubTopoShapes(TopAbs_FACE);
TopoShape face1 = subShapes.front();
face1.Tag = 2;
// Assert
EXPECT_THROW(cube1TS.mapSubElement(face1), Part::NullShapeException); // No subshapes
EXPECT_THROW(cube1TS.mapSubElement(face1), NullShapeException); // No subshapes
}
TEST_F(TopoShapeExpansionTest, mapSubElementFindShapeByNames)
{
// Arrange
auto [cube1, cube2] = CreateTwoCubes();
Part::TopoShape cube1TS {cube1};
Part::TopoShape cube2TS {cube2};
TopoShape cube1TS {cube1};
TopoShape cube2TS {cube2};
cube1TS.Tag = 1;
cube2TS.Tag = 2;
Part::TopoShape topoShape;
Part::TopoShape topoShape1;
TopoShape topoShape;
TopoShape topoShape1;
// Act
int fs1 = topoShape1.findShape(cube1);
@@ -585,11 +586,11 @@ TEST_F(TopoShapeExpansionTest, mapSubElementFindShapeByType)
{
// Arrange
auto [cube1, cube2] = CreateTwoCubes();
Part::TopoShape cube1TS {cube1};
Part::TopoShape cube2TS {cube2};
TopoShape cube1TS {cube1};
TopoShape cube2TS {cube2};
cube1TS.Tag = 1;
cube2TS.Tag = 2;
Part::TopoShape topoShape;
TopoShape topoShape;
topoShape.makeElementCompound({cube1TS, cube2TS});
topoShape.mapSubElement(cube2TS, "Name", false);
@@ -607,11 +608,11 @@ TEST_F(TopoShapeExpansionTest, mapSubElementFindAncestor)
{
// Arrange
auto [cube1, cube2] = CreateTwoCubes();
Part::TopoShape cube1TS {cube1};
Part::TopoShape cube2TS {cube2};
TopoShape cube1TS {cube1};
TopoShape cube2TS {cube2};
cube1TS.Tag = 1;
cube2TS.Tag = 2;
Part::TopoShape topoShape;
TopoShape topoShape;
topoShape.makeElementCompound({cube1TS, cube2TS});
topoShape.mapSubElement(cube2TS, "Name", false);
@@ -634,21 +635,21 @@ TEST_F(TopoShapeExpansionTest, mapSubElementFindAncestors)
tr.SetTranslation(gp_Vec(gp_XYZ(0, 1, 0)));
cube3.Move(TopLoc_Location(tr));
cube4.Move(TopLoc_Location(tr));
Part::TopoShape cube1TS {cube1};
Part::TopoShape cube2TS {cube2};
Part::TopoShape cube3TS {cube3};
Part::TopoShape cube4TS {cube4};
TopoShape cube1TS {cube1};
TopoShape cube2TS {cube2};
TopoShape cube3TS {cube3};
TopoShape cube4TS {cube4};
cube1TS.Tag = 1;
cube2TS.Tag = 2;
cube3TS.Tag = 3;
cube4TS.Tag = 4;
Part::TopoShape topoShape;
Part::TopoShape topoShape1;
Part::TopoShape topoShape2;
Part::TopoShape topoShape3;
Part::TopoShape topoShape4;
Part::TopoShape topoShape5;
Part::TopoShape topoShape6;
TopoShape topoShape;
TopoShape topoShape1;
TopoShape topoShape2;
TopoShape topoShape3;
TopoShape topoShape4;
TopoShape topoShape5;
TopoShape topoShape6;
topoShape.makeElementCompound({cube1TS, cube2TS});
topoShape1.makeElementCompound({cube3TS, cube4TS});
topoShape2.makeElementCompound({cube1TS, cube3TS});
@@ -688,7 +689,7 @@ TEST_F(TopoShapeExpansionTest, mapSubElementFindAncestors)
TEST_F(TopoShapeExpansionTest, makeElementShellInvalid)
{
// Arrange
Part::TopoShape topoShape {1L};
TopoShape topoShape {1L};
// Act / Assert
EXPECT_THROW(topoShape.makeElementShell(false, nullptr), Base::CADKernelError);
}
@@ -699,9 +700,9 @@ TEST_F(TopoShapeExpansionTest, makeElementShellSingle)
const float Len = 3;
const float Wid = 2;
auto [face1, wire1, edge1, edge2, edge3, _] = CreateRectFace(Len, Wid);
Part::TopoShape topoShape {face1, 1L};
TopoShape topoShape {face1, 1L};
// Act
Part::TopoShape result = topoShape.makeElementShell(false, nullptr);
TopoShape result = topoShape.makeElementShell(false, nullptr);
// Assert
#if OCC_VERSION_HEX >= 0x070400
EXPECT_EQ(result.getShape().NbChildren(), 1);
@@ -727,9 +728,9 @@ TEST_F(TopoShapeExpansionTest, makeElementShellOpen)
builder.MakeCompound(compound1);
builder.Add(compound1, face1);
builder.Add(compound1, face2);
Part::TopoShape topoShape {compound1, 1L};
TopoShape topoShape {compound1, 1L};
// Act
Part::TopoShape result = topoShape.makeElementShell(true, nullptr);
TopoShape result = topoShape.makeElementShell(true, nullptr);
// Assert
#if OCC_VERSION_HEX >= 0x070400
EXPECT_EQ(result.getShape().NbChildren(), 2);
@@ -744,16 +745,16 @@ TEST_F(TopoShapeExpansionTest, makeElementShellClosed)
{
// Arrange
auto [cube1, cube2] = CreateTwoCubes();
Part::TopoShape topoShape {cube1};
std::vector<Part::TopoShape> shapes;
TopoShape topoShape {cube1};
std::vector<TopoShape> shapes;
for (const auto& face : topoShape.getSubShapes(TopAbs_FACE)) {
shapes.emplace_back(face);
}
// Act
Part::TopoShape topoShape1 {1L};
TopoShape topoShape1 {1L};
topoShape1.makeElementCompound(shapes, "D");
// Assert
Part::TopoShape result = topoShape1.makeElementShell(false, "SH1");
TopoShape result = topoShape1.makeElementShell(false, "SH1");
#if OCC_VERSION_HEX >= 0x070400
EXPECT_EQ(result.getShape().NbChildren(), 6);
#endif
@@ -770,8 +771,8 @@ TEST_F(TopoShapeExpansionTest, makeElementShellIntersecting)
auto transform {gp_Trsf()};
transform.SetTranslation(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(0.5, 0.5, 0.0));
cube2.Move(TopLoc_Location(transform));
Part::TopoShape topoShape {cube1};
std::vector<Part::TopoShape> shapes;
TopoShape topoShape {cube1};
std::vector<TopoShape> shapes;
for (const auto& face : topoShape.getSubShapes(TopAbs_FACE)) {
shapes.emplace_back(face);
}
@@ -780,7 +781,7 @@ TEST_F(TopoShapeExpansionTest, makeElementShellIntersecting)
shapes.emplace_back(face);
}
// Act
Part::TopoShape topoShape1 {1L};
TopoShape topoShape1 {1L};
topoShape1.makeElementCompound(shapes, "D");
// Assert
EXPECT_THROW(topoShape1.makeElementShell(false, nullptr), Base::CADKernelError);