Add tests, reformat to modern C++, clean

This commit is contained in:
bgbsww
2024-01-21 15:34:46 -05:00
parent e425b5b2db
commit d405fdadc4
6 changed files with 422 additions and 86 deletions

View File

@@ -14,6 +14,21 @@ double getVolume(const TopoDS_Shape& shape)
return prop.Mass();
}
double getArea(const TopoDS_Shape& shape)
{
GProp_GProps prop;
BRepGProp::SurfaceProperties(shape, prop);
return prop.Mass();
}
double getLength(const TopoDS_Shape& shape)
{
GProp_GProps prop;
BRepGProp::LinearProperties(shape, prop);
return prop.Mass();
}
void PartTestHelperClass::createTestDoc()
{
_docName = App::GetApplication().getUniqueDocumentName("test");
@@ -48,7 +63,8 @@ _getFilletEdges(const std::vector<int>& edges, double startRadius, double endRad
return filletElements;
}
void executePython(const std::vector<std::string>& python)
void ExecutePython(const std::vector<std::string>& python)
{
Base::InterpreterSingleton is = Base::InterpreterSingleton();
@@ -68,16 +84,9 @@ void rectangle(double height, double width, char* name)
boost::str(boost::format("V4 = FreeCAD.Vector(0, %d, 0)") % width),
"P1 = Part.makePolygon([V1, V2, V3, V4],True)",
"F1 = Part.Face(P1)", // Make the face or the volume calc won't work right.
// "L1 = Part.LineSegment(V1, V2)",
// "L2 = Part.LineSegment(V2, V3)",
// "L3 = Part.LineSegment(V3, V4)",
// "L4 = Part.LineSegment(V4, V1)",
// "S1 = Part.Shape([L1,L2,L3,L4])",
// "W1 = Part.Wire(S1.Edges)",
// "F1 = Part.Face(W1)", // Make the face or the volume calc won't work right.
boost::str(boost::format("Part.show(F1,'%s')") % name),
};
executePython(rectstring);
ExecutePython(rectstring);
}
testing::AssertionResult

View File

@@ -1,21 +1,25 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#include "gtest/gtest.h"
#include <boost/format.hpp>
#include <App/Application.h>
#include <App/Document.h>
#include "Base/Interpreter.h"
#include <Base/Precision.h>
#include "Mod/Part/App/FeaturePartBox.h"
#include "Mod/Part/App/FeaturePartFuse.h"
#include "Mod/Part/App/FeatureFillet.h"
#include <BRepGProp.hxx>
#include "Base/Interpreter.h"
#include <boost/format.hpp>
namespace PartTestHelpers
{
double getVolume(const TopoDS_Shape& shape);
double getArea(const TopoDS_Shape& shape);
double getLength(const TopoDS_Shape& shape);
std::vector<Part::FilletElement>
_getFilletEdges(const std::vector<int>& edges, double startRadius, double endRadius);

View File

@@ -3,12 +3,18 @@
#include "gtest/gtest.h"
#include "src/App/InitApplication.h"
#include <Mod/Part/App/TopoShape.h>
#include <Mod/Part/App/TopoShapeOpCode.h>
#include "PartTestHelpers.h"
#include <BRepAlgoAPI_Fuse.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <GC_MakeCircle.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <BRep_Builder.hxx>
// NOLINTBEGIN(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers)
@@ -34,6 +40,7 @@ protected:
App::GetApplication().closeDocument(_docName.c_str());
}
private:
std::string _docName;
Data::ElementIDRefs _sid;
@@ -161,4 +168,272 @@ TEST_F(TopoShapeExpansionTest, makeElementCompoundTwoCubes)
// 26 subshapes each
}
std::tuple<TopoDS_Face, TopoDS_Wire, TopoDS_Edge, TopoDS_Edge, TopoDS_Edge, TopoDS_Edge>
CreateRectFace(float len = 2.0, float wid = 3.0)
{
auto edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(len, 0.0, 0.0)).Edge();
auto edge2 = BRepBuilderAPI_MakeEdge(gp_Pnt(len, 0.0, 0.0), gp_Pnt(len, wid, 0.0)).Edge();
auto edge3 = BRepBuilderAPI_MakeEdge(gp_Pnt(len, wid, 0.0), gp_Pnt(0.0, wid, 0.0)).Edge();
auto edge4 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, wid, 0.0), gp_Pnt(0.0, 0.0, 0.0)).Edge();
auto wire1 = BRepBuilderAPI_MakeWire({edge1, edge2, edge3, edge4}).Wire();
auto face1 = BRepBuilderAPI_MakeFace(wire1).Face();
return {face1, wire1, edge1, edge2, edge3, edge4};
}
std::tuple<TopoDS_Face, TopoDS_Wire, TopoDS_Wire>
CreateFaceWithRoundHole(float len = 2.0, float wid = 3.0, float radius = 1.0)
{
auto [face1, wire1, edge1, edge2, edge3, edge4] = CreateRectFace(len, wid);
auto circ1 =
GC_MakeCircle(gp_Pnt(len / 2.0, wid / 2.0, 0), gp_Dir(0.0, 0.0, 1.0), radius).Value();
auto edge5 = BRepBuilderAPI_MakeEdge(circ1).Edge();
auto wire2 = BRepBuilderAPI_MakeWire(edge5).Wire();
auto face2 = BRepBuilderAPI_MakeFace(face1, wire2).Face();
return {face2, wire1, wire2};
}
TEST_F(TopoShapeExpansionTest, makeElementFaceNull)
{
// Arrange
const double L = 3, W = 2, R = 1;
auto [face1, wire1, wire2] = CreateFaceWithRoundHole(L, W, R);
Part::TopoShape topoShape {face1};
double area = PartTestHelpers::getArea(face1);
double area1 = PartTestHelpers::getArea(topoShape.getShape());
// Act
Part::TopoShape newFace = topoShape.makeElementFace(nullptr);
double area2 = PartTestHelpers::getArea(newFace.getShape());
double area3 = PartTestHelpers::getArea(topoShape.getShape());
// Assert
EXPECT_FALSE(face1.IsEqual(newFace.getShape()));
EXPECT_FLOAT_EQ(area, L * W + M_PI * R * R);
EXPECT_FLOAT_EQ(area1, L * W + M_PI * R * R);
EXPECT_FLOAT_EQ(area2, L * W - M_PI * R * R);
EXPECT_FLOAT_EQ(area3, L * W + M_PI * R * R);
EXPECT_STREQ(newFace.shapeName().c_str(), "Face");
}
TEST_F(TopoShapeExpansionTest, makeElementFaceSimple)
{
// Arrange
const double L = 3, W = 2, R = 1;
auto [face1, wire1, wire2] = CreateFaceWithRoundHole(L, W, R);
Part::TopoShape topoShape {face1};
double area = PartTestHelpers::getArea(face1);
double area1 = PartTestHelpers::getArea(topoShape.getShape());
// Act
Part::TopoShape newFace = topoShape.makeElementFace(wire1);
double area2 = PartTestHelpers::getArea(newFace.getShape());
double area3 = PartTestHelpers::getArea(topoShape.getShape());
// Assert
EXPECT_TRUE(newFace.getShape().IsEqual(topoShape.getShape())); // topoShape was altered
EXPECT_FALSE(face1.IsEqual(newFace.getShape()));
EXPECT_FLOAT_EQ(area, L * W + M_PI * R * R);
EXPECT_FLOAT_EQ(area1, L * W + M_PI * R * R);
EXPECT_FLOAT_EQ(area2, L * W);
EXPECT_FLOAT_EQ(area3, L * W);
EXPECT_STREQ(newFace.shapeName().c_str(), "Face");
}
TEST_F(TopoShapeExpansionTest, makeElementFaceParams)
{
// Arrange
const double L = 3, W = 2, R = 1;
auto [face1, wire1, wire2] = CreateFaceWithRoundHole(L, W, R);
Part::TopoShape topoShape {face1, 1L};
double area = PartTestHelpers::getArea(face1);
double area1 = PartTestHelpers::getArea(topoShape.getShape());
// Act
Part::TopoShape newFace =
topoShape.makeElementFace(wire1, "Cut", "Part::FaceMakerBullseye", nullptr);
double area2 = PartTestHelpers::getArea(newFace.getShape());
double area3 = PartTestHelpers::getArea(topoShape.getShape());
// Assert
EXPECT_TRUE(newFace.getShape().IsEqual(topoShape.getShape())); // topoShape was altered
EXPECT_FALSE(face1.IsEqual(newFace.getShape()));
EXPECT_FLOAT_EQ(area, L * W + M_PI * R * R);
EXPECT_FLOAT_EQ(area1, L * W + M_PI * R * R);
EXPECT_FLOAT_EQ(area2, L * W);
EXPECT_FLOAT_EQ(area3, L * W);
EXPECT_STREQ(newFace.shapeName().c_str(), "Face");
}
TEST_F(TopoShapeExpansionTest, makeElementFaceFromFace)
{
// Arrange
const double L = 3, W = 2, R = 1;
auto [face1, wire1, wire2] = CreateFaceWithRoundHole(L, W, R);
Part::TopoShape topoShape {face1, 1L};
double area = PartTestHelpers::getArea(face1);
double area1 = PartTestHelpers::getArea(topoShape.getShape());
// Act
Part::TopoShape newFace =
topoShape.makeElementFace(face1, "Cut", "Part::FaceMakerBullseye", nullptr);
double area2 = PartTestHelpers::getArea(newFace.getShape());
double area3 = PartTestHelpers::getArea(topoShape.getShape());
// Assert
EXPECT_TRUE(newFace.getShape().IsEqual(topoShape.getShape())); // topoShape was altered
EXPECT_FALSE(face1.IsEqual(newFace.getShape()));
EXPECT_FLOAT_EQ(area, L * W + M_PI * R * R);
EXPECT_FLOAT_EQ(area1, L * W + M_PI * R * R);
EXPECT_FLOAT_EQ(area2, L * W - M_PI * R * R);
EXPECT_FLOAT_EQ(area3, L * W - M_PI * R * R);
EXPECT_STREQ(newFace.shapeName().c_str(), "Face");
}
TEST_F(TopoShapeExpansionTest, makeElementFaceOpenWire)
{
// Arrange
const double L = 3, W = 2, R = 1;
auto [face1, wire1, wire2] = CreateFaceWithRoundHole(L, W, R);
Part::TopoShape topoShape {wire1, 1L};
double area = PartTestHelpers::getArea(face1);
double area1 = PartTestHelpers::getArea(topoShape.getShape());
// Act
Part::TopoShape newFace = topoShape.makeElementFace(wire1, "Cut", nullptr, nullptr);
double area2 = PartTestHelpers::getArea(newFace.getShape());
double area3 = PartTestHelpers::getArea(topoShape.getShape());
// Assert
EXPECT_TRUE(newFace.getShape().IsEqual(topoShape.getShape())); // topoShape was altered
EXPECT_FALSE(face1.IsEqual(newFace.getShape()));
EXPECT_FLOAT_EQ(area, L * W + M_PI * R * R);
EXPECT_FLOAT_EQ(area1, 0); // L * W - M_PI * R * R);
EXPECT_FLOAT_EQ(area2, L * W);
EXPECT_FLOAT_EQ(area3, L * W);
EXPECT_STREQ(newFace.shapeName().c_str(), "Face");
}
TEST_F(TopoShapeExpansionTest, makeElementFaceClosedWire)
{
// Arrange
const double L = 3, W = 2, R = 1;
auto [face1, wire1, wire2] = CreateFaceWithRoundHole(L, W, R);
Part::TopoShape topoShape {wire2, 1L};
double area = PartTestHelpers::getArea(face1);
double area1 = PartTestHelpers::getArea(topoShape.getShape());
// Act
Part::TopoShape newFace =
topoShape.makeElementFace(wire2, "Cut", "Part::FaceMakerBullseye", nullptr);
double area2 = PartTestHelpers::getArea(newFace.getShape());
double area3 = PartTestHelpers::getArea(topoShape.getShape());
// Assert
EXPECT_TRUE(newFace.getShape().IsEqual(topoShape.getShape())); // topoShape was altered
EXPECT_FALSE(face1.IsEqual(newFace.getShape()));
EXPECT_FLOAT_EQ(area, L * W + M_PI * R * R);
EXPECT_FLOAT_EQ(area1, 0); // L * W - M_PI * R * R);
EXPECT_FLOAT_EQ(area2, M_PI * R * R);
EXPECT_FLOAT_EQ(area3, M_PI * R * R);
EXPECT_STREQ(newFace.shapeName().c_str(), "Face");
}
// Possible future makeElementFace tests:
// Overlapping wire
// Compound of wires
// Compound of faces
// Compound of other shape types
TEST_F(TopoShapeExpansionTest, setElementComboNameNothing)
{
// Arrange
Part::TopoShape topoShape(1L);
// Act
Data::MappedName result = topoShape.setElementComboName(Data::IndexedName(), {});
// ASSERT
EXPECT_STREQ(result.toString().c_str(), "");
}
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.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.
Data::MappedName edgeName("testname");
// Act
Data::MappedName result =
topoShape.setElementComboName(Data::IndexedName::fromConst("Edge", 1), {edgeName});
// Assert
EXPECT_STREQ(result.toString().c_str(), "testname;");
}
TEST_F(TopoShapeExpansionTest, setElementComboName)
{
// Arrange
Part::TopoShape topoShape(2L);
topoShape.setElementMap({});
Data::MappedName edgeName =
topoShape.getMappedName(Data::IndexedName::fromConst("Edge", 1), true);
Data::MappedName faceName =
topoShape.getMappedName(Data::IndexedName::fromConst("Face", 7), true);
Data::MappedName faceName2 =
topoShape.getMappedName(Data::IndexedName::fromConst("Face", 8), true);
char* op = "Copy";
// Act
Data::MappedName result = topoShape.setElementComboName(Data::IndexedName::fromConst("Edge", 1),
{edgeName, faceName, faceName2},
Part::OpCodes::Common,
op);
// Assert
EXPECT_STREQ(result.toString().c_str(), "Edge1;CMN(Face7|Face8);Copy");
// The detailed forms of names are covered in encodeElementName tests
}
TEST_F(TopoShapeExpansionTest, setElementComboNameCompound)
{
// Arrange
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.makeElementCompound({wire1, wire2}); // Quality of shape doesn't matter
Data::MappedName edgeName =
topoShape.getMappedName(Data::IndexedName::fromConst("Edge", 1), true);
Data::MappedName faceName =
topoShape.getMappedName(Data::IndexedName::fromConst("Face", 7), true);
Data::MappedName faceName2 =
topoShape.getMappedName(Data::IndexedName::fromConst("Face", 8), true);
char* op = "Copy";
// Act
Data::MappedName result = topoShape.setElementComboName(Data::IndexedName::fromConst("Edge", 1),
{edgeName, faceName, faceName2},
Part::OpCodes::Common,
op);
// ASSERT
EXPECT_STREQ(result.toString().c_str(), "Edge1;:H,E;CMN(Face7|Face8);Copy");
// The detailed forms of names are covered in encodeElementName tests
}
TEST_F(TopoShapeExpansionTest, splitWires)
{
// Arrange
const double L = 3, W = 2, R = 1;
auto [face1, wire1, wire2] = CreateFaceWithRoundHole(L, W, R);
Part::TopoShape topoShape {face1, 1L};
std::vector<Part::TopoShape> inner;
// Act
EXPECT_EQ(topoShape.getShape().Orientation(), TopAbs_FORWARD);
Part::TopoShape wire =
topoShape.splitWires(&inner, Part::TopoShape::SplitWireReorient::ReorientReversed);
// Assert
EXPECT_EQ(inner.size(), 1);
EXPECT_FLOAT_EQ(PartTestHelpers::getLength(wire.getShape()), 2 + 2 + 3 + 3);
EXPECT_FLOAT_EQ(PartTestHelpers::getLength(inner.front().getShape()), M_PI * R * 2);
EXPECT_EQ(wire.getShape().Orientation(), TopAbs_REVERSED);
for (Part::TopoShape ts : inner) {
EXPECT_EQ(ts.getShape().Orientation(), TopAbs_FORWARD);
}
}
// Possible future tests:
// splitWires without inner Wires
// splitWires with allfour reorientation values NoReorient, ReOrient, ReorientForward,
// ReorientRevesed
// NOLINTEND(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers)