Toposhape/Part: Cleanups and tests for makeElementSlice, makeElementSlices, and makeElementMirror
This commit is contained in:
@@ -44,6 +44,7 @@
|
||||
#endif
|
||||
|
||||
#include "CrossSection.h"
|
||||
#include "TopoShapeOpCode.h"
|
||||
|
||||
|
||||
using namespace Part;
|
||||
@@ -224,87 +225,103 @@ TopoCrossSection::TopoCrossSection(double a, double b, double c, const TopoShape
|
||||
{
|
||||
}
|
||||
|
||||
void TopoCrossSection::slice(int idx, double d, std::vector<TopoShape> &wires) const {
|
||||
void TopoCrossSection::slice(int idx, double d, std::vector<TopoShape>& wires) const
|
||||
{
|
||||
// Fixes: 0001228: Cross section of Torus in Part Workbench fails or give wrong results
|
||||
// Fixes: 0001137: Incomplete slices when using Part.slice on a torus
|
||||
bool found = false;
|
||||
for(auto &s : shape.getSubTopoShapes(TopAbs_SOLID)) {
|
||||
for (auto& s : shape.getSubTopoShapes(TopAbs_SOLID)) {
|
||||
sliceSolid(idx, d, s, wires);
|
||||
found = true;
|
||||
}
|
||||
if(!found) {
|
||||
for(auto &s : shape.getSubTopoShapes(TopAbs_SHELL)) {
|
||||
if (!found) {
|
||||
for (auto& s : shape.getSubTopoShapes(TopAbs_SHELL)) {
|
||||
sliceNonSolid(idx, d, s, wires);
|
||||
found = true;
|
||||
}
|
||||
if(!found) {
|
||||
for(auto &s : shape.getSubTopoShapes(TopAbs_FACE))
|
||||
if (!found) {
|
||||
for (auto& s : shape.getSubTopoShapes(TopAbs_FACE)) {
|
||||
sliceNonSolid(idx, d, s, wires);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TopoShape TopoCrossSection::slice(int idx, double d) const {
|
||||
TopoShape TopoCrossSection::slice(int idx, double d) const
|
||||
{
|
||||
std::vector<TopoShape> wires;
|
||||
slice(idx,d,wires);
|
||||
return TopoShape().makECompound(wires,0,false);
|
||||
slice(idx, d, wires);
|
||||
return TopoShape().makeElementCompound(
|
||||
wires,
|
||||
0,
|
||||
TopoShape::SingleShapeCompoundCreationPolicy::returnShape);
|
||||
}
|
||||
|
||||
void TopoCrossSection::sliceNonSolid(int idx, double d,
|
||||
const TopoShape& shape, std::vector<TopoShape>& wires) const
|
||||
void TopoCrossSection::sliceNonSolid(int idx,
|
||||
double d,
|
||||
const TopoShape& shape,
|
||||
std::vector<TopoShape>& wires) const
|
||||
{
|
||||
BRepAlgoAPI_Section cs(shape.getShape(), gp_Pln(a,b,c,-d));
|
||||
BRepAlgoAPI_Section cs(shape.getShape(), gp_Pln(a, b, c, -d));
|
||||
if (cs.IsDone()) {
|
||||
std::string prefix(op);
|
||||
if(idx>1) {
|
||||
if (idx > 1) {
|
||||
prefix += '_';
|
||||
prefix += std::to_string(idx);
|
||||
}
|
||||
auto res = TopoShape().makEShape(cs,shape,prefix.c_str()).makEWires().getSubTopoShapes(TopAbs_WIRE);
|
||||
wires.insert(wires.end(),res.begin(),res.end());
|
||||
auto res = TopoShape()
|
||||
.makeElementShape(cs, shape, prefix.c_str())
|
||||
.makeElementWires()
|
||||
.getSubTopoShapes(TopAbs_WIRE);
|
||||
wires.insert(wires.end(), res.begin(), res.end());
|
||||
}
|
||||
}
|
||||
|
||||
void TopoCrossSection::sliceSolid(int idx, double d,
|
||||
const TopoShape& shape, std::vector<TopoShape>& wires) const
|
||||
void TopoCrossSection::sliceSolid(int idx,
|
||||
double d,
|
||||
const TopoShape& shape,
|
||||
std::vector<TopoShape>& wires) const
|
||||
{
|
||||
gp_Pln slicePlane(a,b,c,-d);
|
||||
gp_Pln slicePlane(a, b, c, -d);
|
||||
BRepBuilderAPI_MakeFace mkFace(slicePlane);
|
||||
TopoShape face(idx);
|
||||
face.setShape(mkFace.Face());
|
||||
|
||||
// Make sure to choose a point that does not lie on the plane (fixes #0001228)
|
||||
gp_Vec tempVector(a,b,c);
|
||||
tempVector.Normalize();//just in case.
|
||||
tempVector *= (d+1.0);
|
||||
gp_Vec tempVector(a, b, c);
|
||||
tempVector.Normalize(); // just in case.
|
||||
tempVector *= (d + 1.0);
|
||||
gp_Pnt refPoint(0.0, 0.0, 0.0);
|
||||
refPoint.Translate(tempVector);
|
||||
|
||||
BRepPrimAPI_MakeHalfSpace mkSolid(TopoDS::Face(face.getShape()), refPoint);
|
||||
TopoShape solid(idx);
|
||||
std::string prefix(op);
|
||||
if(idx>1) {
|
||||
if (idx > 1) {
|
||||
prefix += '_';
|
||||
prefix += std::to_string(idx);
|
||||
}
|
||||
solid.makEShape(mkSolid,face,prefix.c_str());
|
||||
solid.makeElementShape(mkSolid, face, prefix.c_str());
|
||||
BRepAlgoAPI_Cut mkCut(shape.getShape(), solid.getShape());
|
||||
|
||||
if (mkCut.IsDone()) {
|
||||
TopoShape res(shape.Tag,shape.Hasher);
|
||||
TopoShape res(shape.Tag, shape.Hasher);
|
||||
std::vector<TopoShape> shapes;
|
||||
shapes.push_back(shape);
|
||||
shapes.push_back(solid);
|
||||
res.makEShape(mkCut,shapes,prefix.c_str());
|
||||
for(auto &face : res.getSubTopoShapes(TopAbs_FACE)) {
|
||||
res.makeElementShape(mkCut, shapes, prefix.c_str());
|
||||
for (auto& face : res.getSubTopoShapes(TopAbs_FACE)) {
|
||||
BRepAdaptor_Surface adapt(TopoDS::Face(face.getShape()));
|
||||
if (adapt.GetType() == GeomAbs_Plane) {
|
||||
gp_Pln plane = adapt.Plane();
|
||||
if (plane.Axis().IsParallel(slicePlane.Axis(), Precision::Confusion()) &&
|
||||
plane.Distance(slicePlane.Location()) < Precision::Confusion()) {
|
||||
auto repaired_wires = TopoShape(face.Tag).makEWires(
|
||||
face.getSubTopoShapes(TopAbs_EDGE),prefix.c_str(),true).getSubTopoShapes(TopAbs_WIRE);
|
||||
wires.insert(wires.end(),repaired_wires.begin(),repaired_wires.end());
|
||||
if (plane.Axis().IsParallel(slicePlane.Axis(), Precision::Confusion())
|
||||
&& plane.Distance(slicePlane.Location()) < Precision::Confusion()) {
|
||||
auto repaired_wires = TopoShape(face.Tag)
|
||||
.makeElementWires(face.getSubTopoShapes(TopAbs_EDGE),
|
||||
prefix.c_str(),
|
||||
true)
|
||||
.getSubTopoShapes(TopAbs_WIRE);
|
||||
wires.insert(wires.end(), repaired_wires.begin(), repaired_wires.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,8 +56,8 @@ private:
|
||||
class PartExport TopoCrossSection
|
||||
{
|
||||
public:
|
||||
TopoCrossSection(double a, double b, double c, const TopoShape& s, const char *op=0);
|
||||
void slice(int idx, double d, std::vector<TopoShape> &wires) const;
|
||||
TopoCrossSection(double a, double b, double c, const TopoShape& s, const char* op = 0);
|
||||
void slice(int idx, double d, std::vector<TopoShape>& wires) const;
|
||||
TopoShape slice(int idx, double d) const;
|
||||
|
||||
private:
|
||||
@@ -65,11 +65,11 @@ private:
|
||||
void sliceSolid(int idx, double d, const TopoShape&, std::vector<TopoShape>& wires) const;
|
||||
|
||||
private:
|
||||
double a,b,c;
|
||||
double a, b, c;
|
||||
const TopoShape& shape;
|
||||
const char *op;
|
||||
const char* op;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace Part
|
||||
|
||||
#endif // PART_CROSSSECTION_H
|
||||
|
||||
@@ -1342,7 +1342,8 @@ public:
|
||||
* a self reference so that multiple operations can be carried out
|
||||
* for the same shape in the same line of code.
|
||||
*/
|
||||
TopoShape &makEMirror(const TopoShape &source, const gp_Ax2& axis, const char *op=nullptr);
|
||||
TopoShape&
|
||||
makeElementMirror(const TopoShape& source, const gp_Ax2& axis, const char* op = nullptr);
|
||||
/** Make a mirrored shape
|
||||
*
|
||||
* @param source: the source shape
|
||||
@@ -1352,15 +1353,16 @@ public:
|
||||
*
|
||||
* @return Return the new shape. The TopoShape itself is not modified.
|
||||
*/
|
||||
TopoShape makEMirror(const gp_Ax2& ax, const char *op=nullptr) const {
|
||||
return TopoShape(0,Hasher).makEMirror(*this,ax,op);
|
||||
TopoShape makeElementMirror(const gp_Ax2& ax, const char* op = nullptr) const
|
||||
{
|
||||
return TopoShape(0, Hasher).makeElementMirror(*this, ax, op);
|
||||
}
|
||||
|
||||
/** Make a cross section slice
|
||||
*
|
||||
* @param source: the source shape
|
||||
* @param dir: direction of the normal of the section plane
|
||||
* @param d: distance to move the section plane
|
||||
* @param distance: distance to move the section plane
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
*
|
||||
@@ -1369,19 +1371,23 @@ public:
|
||||
* a self reference so that multiple operations can be carried out
|
||||
* for the same shape in the same line of code.
|
||||
*/
|
||||
TopoShape &makESlice(const TopoShape &source, const Base::Vector3d& dir, double d, const char *op=nullptr);
|
||||
TopoShape& makeElementSlice(const TopoShape& source,
|
||||
const Base::Vector3d& dir,
|
||||
double distance,
|
||||
const char* op = nullptr);
|
||||
/** Make a cross section slice
|
||||
*
|
||||
* @param source: the source shape
|
||||
* @param dir: direction of the normal of the section plane
|
||||
* @param d: distance to move the section plane
|
||||
* @param distance: distance to move the section plane
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
*
|
||||
* @return Return the new shape. The TopoShape itself is not modified.
|
||||
*/
|
||||
TopoShape makESlice(const Base::Vector3d& dir, double d, const char *op=nullptr) const {
|
||||
return TopoShape(0,Hasher).makESlice(*this,dir,d,op);
|
||||
TopoShape makeElementSlice(const Base::Vector3d& dir, double distance, const char* op = nullptr) const
|
||||
{
|
||||
return TopoShape(0, Hasher).makeElementSlice(*this, dir, distance, op);
|
||||
}
|
||||
|
||||
/** Make multiple cross section slices
|
||||
@@ -1397,8 +1403,10 @@ public:
|
||||
* a self reference so that multiple operations can be carried out
|
||||
* for the same shape in the same line of code.
|
||||
*/
|
||||
TopoShape &makESlices(const TopoShape &source, const Base::Vector3d& dir,
|
||||
const std::vector<double> &distances, const char *op=nullptr);
|
||||
TopoShape& makeElementSlices(const TopoShape& source,
|
||||
const Base::Vector3d& dir,
|
||||
const std::vector<double>& distances,
|
||||
const char* op = nullptr);
|
||||
/** Make multiple cross section slices
|
||||
*
|
||||
* @param source: the source shape
|
||||
@@ -1409,8 +1417,11 @@ public:
|
||||
*
|
||||
* @return Return the new shape. The TopoShape itself is not modified.
|
||||
*/
|
||||
TopoShape makESlices(const Base::Vector3d &dir, const std::vector<double> &distances, const char *op=nullptr) const {
|
||||
return TopoShape(0,Hasher).makESlices(*this,dir,distances,op);
|
||||
TopoShape makeElementSlices(const Base::Vector3d& dir,
|
||||
const std::vector<double>& distances,
|
||||
const char* op = nullptr) const
|
||||
{
|
||||
return TopoShape(0, Hasher).makeElementSlices(*this, dir, distances, op);
|
||||
}
|
||||
|
||||
/* Make fillet shape
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <BRepAlgoAPI_Section.hxx>
|
||||
#include <BRepBuilderAPI_Copy.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_Transform.hxx>
|
||||
#include <BRepFilletAPI_MakeChamfer.hxx>
|
||||
#include <BRepFilletAPI_MakeFillet.hxx>
|
||||
#include <BRepLib.hxx>
|
||||
@@ -75,6 +76,7 @@
|
||||
#endif
|
||||
|
||||
#include "modelRefine.h"
|
||||
#include "CrossSection.h"
|
||||
#include "TopoShape.h"
|
||||
#include "TopoShapeOpCode.h"
|
||||
#include "TopoShapeCache.h"
|
||||
@@ -2596,28 +2598,52 @@ struct MapperThruSections: MapperMaker
|
||||
}
|
||||
};
|
||||
|
||||
TopoShape &TopoShape::makESlice(const TopoShape &shape,
|
||||
const Base::Vector3d& dir, double d, const char *op)
|
||||
TopoShape& TopoShape::makeElementMirror(const TopoShape& shape, const gp_Ax2& ax2, const char* op)
|
||||
{
|
||||
if(shape.isNull())
|
||||
HANDLE_NULL_SHAPE;
|
||||
TopoCrossSection cs(dir.x, dir.y, dir.z,shape,op);
|
||||
TopoShape res = cs.slice(1,d);
|
||||
if (!op) {
|
||||
op = Part::OpCodes::Mirror;
|
||||
}
|
||||
|
||||
if (shape.isNull()) {
|
||||
FC_THROWM(NullShapeException, "Null shape");
|
||||
}
|
||||
gp_Trsf mat;
|
||||
mat.SetMirror(ax2);
|
||||
TopLoc_Location loc = shape.getShape().Location();
|
||||
gp_Trsf placement = loc.Transformation();
|
||||
mat = placement * mat;
|
||||
BRepBuilderAPI_Transform mkTrf(shape.getShape(), mat);
|
||||
return makeElementShape(mkTrf, shape, op);
|
||||
}
|
||||
|
||||
TopoShape& TopoShape::makeElementSlice(const TopoShape& shape,
|
||||
const Base::Vector3d& dir,
|
||||
double distance,
|
||||
const char* op)
|
||||
{
|
||||
if (shape.isNull()) {
|
||||
FC_THROWM(NullShapeException, "Null shape");
|
||||
}
|
||||
TopoCrossSection cs(dir.x, dir.y, dir.z, shape, op);
|
||||
TopoShape res = cs.slice(1, distance);
|
||||
setShape(res._Shape);
|
||||
Hasher = res.Hasher;
|
||||
resetElementMap(res.elementMap());
|
||||
return *this;
|
||||
}
|
||||
|
||||
TopoShape &TopoShape::makESlices(const TopoShape &shape,
|
||||
const Base::Vector3d& dir, const std::vector<double> &d, const char *op)
|
||||
TopoShape& TopoShape::makeElementSlices(const TopoShape& shape,
|
||||
const Base::Vector3d& dir,
|
||||
const std::vector<double>& distances,
|
||||
const char* op)
|
||||
{
|
||||
std::vector<TopoShape> wires;
|
||||
TopoCrossSection cs(dir.x, dir.y, dir.z, shape,op);
|
||||
int i=0;
|
||||
for(auto &dd : d)
|
||||
cs.slice(++i,dd,wires);
|
||||
return makECompound(wires,op,false);
|
||||
TopoCrossSection cs(dir.x, dir.y, dir.z, shape, op);
|
||||
int index = 0;
|
||||
for (auto& distance : distances) {
|
||||
cs.slice(++index, distance, wires);
|
||||
}
|
||||
return makeElementCompound(wires, op, SingleShapeCompoundCreationPolicy::returnShape);
|
||||
}
|
||||
|
||||
TopoShape& TopoShape::makeElementFillet(const TopoShape& shape,
|
||||
@@ -2774,7 +2800,14 @@ TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_MakeShape& mkShape,
|
||||
const std::vector<TopoShape>& shapes,
|
||||
const char* op)
|
||||
{
|
||||
return makeShapeWithElementMap(mkShape.Shape(), MapperMaker(mkShape), shapes, op);
|
||||
TopoDS_Shape shape;
|
||||
// OCCT 7.3.x requires calling Solid() and not Shape() to function correctly
|
||||
if ( typeid(mkShape) == typeid(BRepPrimAPI_MakeHalfSpace) ) {
|
||||
shape = static_cast<BRepPrimAPI_MakeHalfSpace&>(mkShape).Solid();
|
||||
} else {
|
||||
shape = mkShape.Shape();
|
||||
}
|
||||
return makeShapeWithElementMap(shape, MapperMaker(mkShape), shapes, op);
|
||||
}
|
||||
|
||||
TopoShape& TopoShape::makeElementLoft(const std::vector<TopoShape>& shapes,
|
||||
|
||||
@@ -141,21 +141,23 @@ testing::AssertionResult elementsMatch(const TopoShape& shape,
|
||||
const std::vector<std::string>& names)
|
||||
{
|
||||
auto elements = shape.getElementMap();
|
||||
if (std::find_first_of(elements.begin(),
|
||||
elements.end(),
|
||||
names.begin(),
|
||||
names.end(),
|
||||
[&](const Data::MappedElement& element, const std::string& name) {
|
||||
return element.name.toString() == name;
|
||||
})
|
||||
== elements.end()) {
|
||||
std::stringstream output;
|
||||
output << "{";
|
||||
for (const auto& element : elements) {
|
||||
output << "\"" << element.name.toString() << "\", ";
|
||||
if (!elements.empty() || !names.empty()) {
|
||||
if (std::find_first_of(elements.begin(),
|
||||
elements.end(),
|
||||
names.begin(),
|
||||
names.end(),
|
||||
[&](const Data::MappedElement& element, const std::string& name) {
|
||||
return element.name.toString() == name;
|
||||
})
|
||||
== elements.end()) {
|
||||
std::stringstream output;
|
||||
output << "{";
|
||||
for (const auto& element : elements) {
|
||||
output << "\"" << element.name.toString() << "\", ";
|
||||
}
|
||||
output << "}";
|
||||
return testing::AssertionFailure() << output.str();
|
||||
}
|
||||
output << "}";
|
||||
return testing::AssertionFailure() << output.str();
|
||||
}
|
||||
return testing::AssertionSuccess();
|
||||
}
|
||||
|
||||
@@ -1612,7 +1612,7 @@ TEST_F(TopoShapeExpansionTest, makeElementChamfer)
|
||||
// Act
|
||||
cube1TS.makeElementChamfer({cube1TS}, edges, .05, .05);
|
||||
auto elements = elementMap(cube1TS);
|
||||
// Assert
|
||||
// Assert shape is correct
|
||||
EXPECT_EQ(cube1TS.countSubElements("Wire"), 26);
|
||||
EXPECT_FLOAT_EQ(getArea(cube1TS.getShape()), 5.640996);
|
||||
// Assert that we're creating a correct element map
|
||||
@@ -1729,7 +1729,7 @@ TEST_F(TopoShapeExpansionTest, makeElementFillet)
|
||||
// Act
|
||||
cube1TS.makeElementFillet({cube1TS}, edges, .05, .05);
|
||||
auto elements = elementMap(cube1TS);
|
||||
// Assert
|
||||
// Assert shape is correct
|
||||
EXPECT_EQ(cube1TS.countSubElements("Wire"), 26);
|
||||
EXPECT_FLOAT_EQ(getArea(cube1TS.getShape()), 5.739646);
|
||||
// Assert that we're creating a correct element map
|
||||
@@ -1845,4 +1845,113 @@ TEST_F(TopoShapeExpansionTest, makeElementFillet)
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, makeElementSlice)
|
||||
{
|
||||
// Arrange
|
||||
auto [cube1, cube2] = CreateTwoCubes(); // TopoShape version works too
|
||||
TopoShape cube1TS {cube1}; // Adding a tag here only adds text in each mapped name
|
||||
auto faces = cube1TS.getSubShapes(TopAbs_FACE);
|
||||
TopoShape slicer {faces[0]};
|
||||
Base::Vector3d direction {1.0, 0.0, 0.0};
|
||||
// Act
|
||||
auto& result = slicer.makeElementSlice(cube1TS, direction, 0.5);
|
||||
// Assert shape is correct
|
||||
EXPECT_FLOAT_EQ(getLength(result.getShape()), 4);
|
||||
EXPECT_EQ(TopAbs_ShapeEnum::TopAbs_WIRE, result.getShape().ShapeType());
|
||||
// Assert that we're creating a correct element map
|
||||
EXPECT_TRUE(result.getMappedChildElements().empty());
|
||||
EXPECT_TRUE(allElementsMatch(result,
|
||||
{
|
||||
"Edge1;SLC;D1;MAK",
|
||||
"Edge1;SLC;D2;MAK",
|
||||
"Edge1;SLC;D3;MAK",
|
||||
"Edge1;SLC;MAK",
|
||||
"Vertex1;SLC;D1;MAK",
|
||||
"Vertex1;SLC;D2;MAK",
|
||||
"Vertex1;SLC;MAK",
|
||||
"Vertex2;SLC;D1;MAK",
|
||||
"Vertex2;SLC;D2;MAK",
|
||||
"Vertex2;SLC;MAK",
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, makeElementSlices)
|
||||
{
|
||||
// Arrange
|
||||
auto [cube1, cube2] = CreateTwoCubes();
|
||||
TopoShape cube1TS {cube1, 1L};
|
||||
auto faces = cube1TS.getSubShapes(TopAbs_FACE);
|
||||
TopoShape slicer {faces[0]};
|
||||
Base::Vector3d direction {1.0, 0.0, 0.0};
|
||||
// Act
|
||||
auto& result = slicer.makeElementSlices(cube1TS, direction, {0.25, 0.5, 0.75});
|
||||
auto subTopoShapes = result.getSubTopoShapes(TopAbs_WIRE);
|
||||
// Assert shape is correct
|
||||
EXPECT_EQ(result.countSubElements("Wire"), 3);
|
||||
EXPECT_FLOAT_EQ(getLength(result.getShape()), 12);
|
||||
EXPECT_FLOAT_EQ(getLength(subTopoShapes[0].getShape()), 4);
|
||||
EXPECT_EQ(TopAbs_ShapeEnum::TopAbs_COMPOUND, result.getShape().ShapeType());
|
||||
EXPECT_EQ(TopAbs_ShapeEnum::TopAbs_WIRE, subTopoShapes[0].getShape().ShapeType());
|
||||
EXPECT_EQ(TopAbs_ShapeEnum::TopAbs_WIRE, subTopoShapes[1].getShape().ShapeType());
|
||||
EXPECT_EQ(TopAbs_ShapeEnum::TopAbs_WIRE, subTopoShapes[2].getShape().ShapeType());
|
||||
// Assert that we're creating a correct element map
|
||||
EXPECT_TRUE(result.getMappedChildElements().empty());
|
||||
EXPECT_TRUE(elementsMatch(result, {"Edge1;SLC;:H1:4,E;D1;:H1:3,E;MAK;:H1:4,E",
|
||||
"Edge1;SLC;:H1:4,E;D2;:H1:3,E;MAK;:H1:4,E",
|
||||
"Edge1;SLC;:H1:4,E;D3;:H1:3,E;MAK;:H1:4,E",
|
||||
"Edge1;SLC;:H1:4,E;MAK;:H1:4,E",
|
||||
"Edge1;SLC_2;:H1:6,E;D1;:H1:3,E;MAK;:H1:4,E",
|
||||
"Edge1;SLC_2;:H1:6,E;D2;:H1:3,E;MAK;:H1:4,E",
|
||||
"Edge1;SLC_2;:H1:6,E;D3;:H1:3,E;MAK;:H1:4,E",
|
||||
"Edge1;SLC_2;:H1:6,E;MAK;:H1:4,E",
|
||||
"Edge1;SLC_3;:H1:6,E;D1;:H1:3,E;MAK;:H1:4,E",
|
||||
"Edge1;SLC_3;:H1:6,E;D2;:H1:3,E;MAK;:H1:4,E",
|
||||
"Edge1;SLC_3;:H1:6,E;D3;:H1:3,E;MAK;:H1:4,E",
|
||||
"Edge1;SLC_3;:H1:6,E;MAK;:H1:4,E",
|
||||
"Vertex1;SLC;:H1:4,V;D2;:H1:3,V;MAK;:H1:4,V",
|
||||
"Vertex1;SLC;:H1:4,V;MAK;:H1:4,V",
|
||||
"Vertex1;SLC_2;:H1:6,V;D2;:H1:3,V;MAK;:H1:4,V",
|
||||
"Vertex1;SLC_2;:H1:6,V;MAK;:H1:4,V",
|
||||
"Vertex1;SLC_3;:H1:6,V;D2;:H1:3,V;MAK;:H1:4,V",
|
||||
"Vertex1;SLC_3;:H1:6,V;MAK;:H1:4,V",
|
||||
"Vertex2;SLC;:H1:4,V;D1;:H1:3,V;MAK;:H1:4,V",
|
||||
"Vertex2;SLC;:H1:4,V;MAK;:H1:4,V",
|
||||
"Vertex2;SLC_2;:H1:6,V;D1;:H1:3,V;MAK;:H1:4,V",
|
||||
"Vertex2;SLC_2;:H1:6,V;MAK;:H1:4,V",
|
||||
"Vertex2;SLC_3;:H1:6,V;D1;:H1:3,V;MAK;:H1:4,V",
|
||||
"Vertex2;SLC_3;:H1:6,V;MAK;:H1:4,V"}));
|
||||
EXPECT_TRUE(subTopoShapes[0].getElementMap().empty());
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, makeElementMirror)
|
||||
{
|
||||
// Arrange
|
||||
auto [cube1, cube2] = CreateTwoCubes();
|
||||
TopoShape cube1TS {cube1, 1L};
|
||||
auto edges = cube1TS.getSubTopoShapes(TopAbs_EDGE);
|
||||
gp_Ax2 axis {gp_Pnt {0, 0, 0}, gp_Dir {1, 0, 0}};
|
||||
// Act
|
||||
auto& result = cube1TS.makeElementMirror(cube1TS, axis);
|
||||
auto elements = elementMap(cube1TS);
|
||||
Base::BoundBox3d bb = result.getBoundBox();
|
||||
// Assert shape is correct
|
||||
EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(-1, 0, 0, 0, 1, 1)));
|
||||
EXPECT_EQ(result.countSubElements("Wire"), 6);
|
||||
EXPECT_FLOAT_EQ(getVolume(result.getShape()), 1);
|
||||
EXPECT_EQ(TopAbs_ShapeEnum::TopAbs_SOLID, result.getShape().ShapeType());
|
||||
// Assert that we're creating a correct element map
|
||||
EXPECT_TRUE(result.getMappedChildElements().empty());
|
||||
EXPECT_TRUE(
|
||||
elementsMatch(result,
|
||||
{"Edge10;:M;MIR;:H1:7,E", "Edge11;:M;MIR;:H1:7,E", "Edge12;:M;MIR;:H1:7,E",
|
||||
"Edge1;:M;MIR;:H1:7,E", "Edge2;:M;MIR;:H1:7,E", "Edge3;:M;MIR;:H1:7,E",
|
||||
"Edge4;:M;MIR;:H1:7,E", "Edge5;:M;MIR;:H1:7,E", "Edge6;:M;MIR;:H1:7,E",
|
||||
"Edge7;:M;MIR;:H1:7,E", "Edge8;:M;MIR;:H1:7,E", "Edge9;:M;MIR;:H1:7,E",
|
||||
"Face1;:M;MIR;:H1:7,F", "Face2;:M;MIR;:H1:7,F", "Face3;:M;MIR;:H1:7,F",
|
||||
"Face4;:M;MIR;:H1:7,F", "Face5;:M;MIR;:H1:7,F", "Face6;:M;MIR;:H1:7,F",
|
||||
"Vertex1;:M;MIR;:H1:7,V", "Vertex2;:M;MIR;:H1:7,V", "Vertex3;:M;MIR;:H1:7,V",
|
||||
"Vertex4;:M;MIR;:H1:7,V", "Vertex5;:M;MIR;:H1:7,V", "Vertex6;:M;MIR;:H1:7,V",
|
||||
"Vertex7;:M;MIR;:H1:7,V", "Vertex8;:M;MIR;:H1:7,V"}));
|
||||
}
|
||||
|
||||
// NOLINTEND(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers)
|
||||
|
||||
Reference in New Issue
Block a user