Merge branch 'main' of https://github.com/FreeCAD/FreeCAD.git into toponamingTopoShapeWire
# Conflicts: # src/Mod/Part/App/TopoShape.h # src/Mod/Part/App/TopoShapeExpansion.cpp
This commit is contained in:
@@ -444,7 +444,7 @@ TEST_F(ComplexGeoDataTest, saveDocFileWithNoElementMap)
|
||||
{
|
||||
// Arrange
|
||||
Base::StringWriter writer;
|
||||
cgd().resetElementMap(nullptr, true); // Force undefined map
|
||||
cgd().resetElementMap(nullptr, Data::AllowNoMap); // Force undefined map
|
||||
|
||||
// Act
|
||||
cgd().SaveDocFile(writer);
|
||||
|
||||
@@ -145,4 +145,10 @@ TEST(BaseToolsSuite, TestJoinList)
|
||||
{
|
||||
EXPECT_EQ(Base::Tools::joinList({"AB", "CD"}), "AB, CD, ");
|
||||
}
|
||||
TEST(BaseToolsSuite, TestEscapeQuotesFromString)
|
||||
{
|
||||
EXPECT_EQ(Base::Tools::escapeQuotesFromString("\'"), "\\\'");
|
||||
EXPECT_EQ(Base::Tools::escapeQuotesFromString("\""), "\\\"");
|
||||
EXPECT_EQ(Base::Tools::escapeQuotesFromString("\\"), "\\");
|
||||
}
|
||||
// NOLINTEND(cppcoreguidelines-*,readability-*)
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
add_subdirectory(Material)
|
||||
add_subdirectory(Mesh)
|
||||
add_subdirectory(Part)
|
||||
add_subdirectory(Points)
|
||||
add_subdirectory(Sketcher)
|
||||
if(BUILD_MATERIAL)
|
||||
add_subdirectory(Material)
|
||||
endif(BUILD_MATERIAL)
|
||||
if(BUILD_MESH)
|
||||
add_subdirectory(Mesh)
|
||||
endif(BUILD_MESH)
|
||||
if(BUILD_PART)
|
||||
add_subdirectory(Part)
|
||||
endif(BUILD_PART)
|
||||
if(BUILD_POINTS)
|
||||
add_subdirectory(Points)
|
||||
endif(BUILD_POINTS)
|
||||
if(BUILD_SKETCHER)
|
||||
add_subdirectory(Sketcher)
|
||||
endif(BUILD_SKETCHER)
|
||||
|
||||
@@ -15,6 +15,8 @@ target_sources(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TopoShape.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TopoShapeCache.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TopoShapeExpansion.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TopoShapeMakeElementRefine.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TopoShapeMakeShapeWithElementMap.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TopoShapeMapper.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TopoShapeMakeShape.cpp
|
||||
)
|
||||
|
||||
@@ -770,7 +770,6 @@ 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));
|
||||
// Arrange
|
||||
Part::TopoShape topoShape {cube1};
|
||||
std::vector<Part::TopoShape> shapes;
|
||||
for (const auto& face : topoShape.getSubShapes(TopAbs_FACE)) {
|
||||
@@ -783,7 +782,7 @@ TEST_F(TopoShapeExpansionTest, makeElementShellIntersecting)
|
||||
// Act
|
||||
Part::TopoShape topoShape1 {1L};
|
||||
topoShape1.makeElementCompound(shapes, "D");
|
||||
// Act / Assert
|
||||
// Assert
|
||||
EXPECT_THROW(topoShape1.makeElementShell(false, nullptr), Base::CADKernelError);
|
||||
}
|
||||
|
||||
|
||||
53
tests/src/Mod/Part/App/TopoShapeMakeElementRefine.cpp
Normal file
53
tests/src/Mod/Part/App/TopoShapeMakeElementRefine.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <src/App/InitApplication.h>
|
||||
|
||||
#include "PartTestHelpers.h"
|
||||
|
||||
class FeaturePartMakeElementRefineTest: public ::testing::Test,
|
||||
public PartTestHelpers::PartTestHelperClass
|
||||
{
|
||||
protected:
|
||||
static void SetUpTestSuite()
|
||||
{
|
||||
tests::initApplication();
|
||||
}
|
||||
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
createTestDoc();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{}
|
||||
};
|
||||
|
||||
TEST_F(FeaturePartMakeElementRefineTest, makeElementRefineBoxes)
|
||||
{
|
||||
// Arrange
|
||||
auto _doc = App::GetApplication().getActiveDocument();
|
||||
auto _fuse = dynamic_cast<Part::Fuse*>(_doc->addObject("Part::Fuse"));
|
||||
_fuse->Base.setValue(_boxes[0]);
|
||||
_fuse->Tool.setValue(_boxes[3]);
|
||||
// Act
|
||||
_fuse->execute();
|
||||
Part::TopoShape ts = _fuse->Shape.getValue();
|
||||
Part::TopoShape refined = ts.makeElementRefine();
|
||||
double volume = PartTestHelpers::getVolume(ts.getShape());
|
||||
double refinedVolume = PartTestHelpers::getVolume(refined.getShape());
|
||||
Base::BoundBox3d bb = ts.getBoundBox();
|
||||
// Assert
|
||||
EXPECT_TRUE(bb.IsValid());
|
||||
EXPECT_DOUBLE_EQ(volume, 12.0);
|
||||
EXPECT_DOUBLE_EQ(refinedVolume, 12.0); // Refine shouldn't change the volume
|
||||
EXPECT_EQ(ts.countSubElements("Face"), 10); // Two boxes touching each loose one face
|
||||
EXPECT_EQ(ts.countSubElements("Edge"), 20); // Two boxes touching loose 4 edges
|
||||
EXPECT_EQ(refined.countSubElements("Face"), 6); // After refining it is one box
|
||||
EXPECT_EQ(refined.countSubElements("Edge"), 12); // 12 edges in a box
|
||||
// TODO: Make sure we have an elementMap for the refine.
|
||||
// Refine doesn't work on compounds, so we're going to need a binary operation or the
|
||||
// like, and those don't exist yet. Once they do, this test can be expanded
|
||||
}
|
||||
129
tests/src/Mod/Part/App/TopoShapeMakeShape.cpp
Normal file
129
tests/src/Mod/Part/App/TopoShapeMakeShape.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
// Tests for the makeShape methods, extracted from the main set of tests for TopoShape
|
||||
// due to length and complexity.
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/App/InitApplication.h"
|
||||
#include "PartTestHelpers.h"
|
||||
#include <Mod/Part/App/TopoShape.h>
|
||||
|
||||
#include <BRepBuilderAPI_MakeVertex.hxx>
|
||||
|
||||
using namespace Data;
|
||||
using namespace Part;
|
||||
using namespace PartTestHelpers;
|
||||
|
||||
class TopoShapeMakeShapeTests: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
static void SetUpTestSuite()
|
||||
{
|
||||
tests::initApplication();
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
_docName = App::GetApplication().getUniqueDocumentName("test");
|
||||
App::GetApplication().newDocument(_docName.c_str(), "testUser");
|
||||
_sids = &_sid;
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
App::GetApplication().closeDocument(_docName.c_str());
|
||||
}
|
||||
|
||||
Part::TopoShape* Shape()
|
||||
{
|
||||
return &_shape;
|
||||
}
|
||||
|
||||
Part::TopoShape::Mapper* Mapper()
|
||||
{
|
||||
return &_mapper;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _docName;
|
||||
Data::ElementIDRefs _sid;
|
||||
QVector<App::StringIDRef>* _sids = nullptr;
|
||||
Part::TopoShape _shape;
|
||||
Part::TopoShape::Mapper _mapper;
|
||||
};
|
||||
|
||||
TEST_F(TopoShapeMakeShapeTests, nullShapeThrows)
|
||||
{
|
||||
// Arrange
|
||||
auto [cube1, cube2] = CreateTwoCubes();
|
||||
std::vector<Part::TopoShape> sources {cube1, cube2};
|
||||
TopoDS_Vertex nullShape;
|
||||
|
||||
// Act and assert
|
||||
EXPECT_THROW(Shape()->makeShapeWithElementMap(nullShape, *Mapper(), sources),
|
||||
Part::NullShapeException);
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeMakeShapeTests, shapeVertex)
|
||||
{
|
||||
// Arrange
|
||||
BRepBuilderAPI_MakeVertex vertexMaker = BRepBuilderAPI_MakeVertex(gp_Pnt(10, 10, 10));
|
||||
TopoShape topoShape(vertexMaker.Vertex(), 1L);
|
||||
// Act
|
||||
TopoShape& result = topoShape.makeElementShape(vertexMaker, topoShape);
|
||||
auto elements = elementMap(result);
|
||||
// Assert
|
||||
EXPECT_EQ(elements.size(), 1);
|
||||
EXPECT_EQ(elements.count(IndexedName("Vertex", 1)), 1);
|
||||
EXPECT_EQ(elements[IndexedName("Vertex", 1)], MappedName("Vertex1;MAK;:H:4,V"));
|
||||
EXPECT_EQ(getArea(result.getShape()), 0);
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeMakeShapeTests, thruSections)
|
||||
{
|
||||
// Arrange
|
||||
auto [face1, wire1, edge1, edge2, edge3, edge4] = CreateRectFace();
|
||||
TopoDS_Wire wire2 = wire1;
|
||||
auto transform {gp_Trsf()};
|
||||
transform.SetTranslation(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(0.0, 0.5, 1.0));
|
||||
wire2.Move(TopLoc_Location(transform));
|
||||
TopoShape wire1ts {wire1, 1L};
|
||||
TopoShape wire2ts {wire2, 2L};
|
||||
BRepOffsetAPI_ThruSections thruMaker;
|
||||
thruMaker.AddWire(wire1);
|
||||
thruMaker.AddWire(wire2);
|
||||
TopoShape topoShape {};
|
||||
// Act
|
||||
TopoShape& result = topoShape.makeElementShape(thruMaker, {wire1ts, wire2ts});
|
||||
auto elements = elementMap(result);
|
||||
// Assert
|
||||
EXPECT_EQ(elements.size(), 24);
|
||||
EXPECT_EQ(elements.count(IndexedName("Vertex", 1)), 1);
|
||||
EXPECT_EQ(elements[IndexedName("Vertex", 1)], MappedName("Vertex1;TRU;:H1:4,V"));
|
||||
EXPECT_EQ(getVolume(result.getShape()), 4);
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeMakeShapeTests, sewing)
|
||||
{
|
||||
// Arrange
|
||||
auto [face1, wire1, edge1, edge2, edge3, edge4] = CreateRectFace();
|
||||
auto face2 = face1;
|
||||
auto transform {gp_Trsf()};
|
||||
transform.SetTranslation(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(0.5, 0.5, 0.0));
|
||||
face2.Move(TopLoc_Location(transform));
|
||||
BRepBuilderAPI_Sewing sewer;
|
||||
sewer.Add(face1);
|
||||
sewer.Add(face2);
|
||||
sewer.Perform();
|
||||
std::vector<TopoShape> sources {{face1, 1L}, {face2, 2L}};
|
||||
TopoShape topoShape {};
|
||||
// Act
|
||||
TopoShape& result = topoShape.makeElementShape(sewer, sources);
|
||||
auto elements = elementMap(result);
|
||||
// Assert
|
||||
EXPECT_EQ(&result, &topoShape);
|
||||
EXPECT_EQ(elements.size(), 18); // Now a single cube
|
||||
EXPECT_EQ(elements.count(IndexedName("Vertex", 1)), 1);
|
||||
EXPECT_EQ(elements[IndexedName("Vertex", 1)], MappedName("Vertex1;SEW;:H1:4,V"));
|
||||
EXPECT_EQ(getArea(result.getShape()), 12);
|
||||
}
|
||||
@@ -340,3 +340,48 @@ TEST_F(TopoShapeMakeShapeWithElementMapTests, findMakerOpInElementMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string composeTagInfo(const MappedElement& element, const TopoShape& shape)
|
||||
{
|
||||
std::string elementNameStr {element.name.constPostfix()};
|
||||
std::string tagInfo = POSTFIX_TAG + std::to_string(shape.Tag);
|
||||
tagInfo +=
|
||||
":" + std::to_string(elementNameStr.substr(0, elementNameStr.find(tagInfo)).length());
|
||||
|
||||
return tagInfo;
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeMakeShapeWithElementMapTests, findTagInfoInMappedName)
|
||||
{
|
||||
// Arrange
|
||||
auto [cube1, cube2] = PartTestHelpers::CreateTwoCubes();
|
||||
std::vector<Part::TopoShape> sources {cube1, cube2};
|
||||
sources[0].Tag = 1; // setting Tag explicitly otherwise it is likely that this test will be
|
||||
// more or less the same of nonMappableSources
|
||||
sources[1].Tag = 2; // setting Tag explicitly otherwise it is likely that this test will be
|
||||
// more or less the same of nonMappableSources
|
||||
|
||||
// Act and assert
|
||||
// Testing with all the source TopoShapes
|
||||
for (const auto& source : sources) {
|
||||
Part::TopoShape tmpShape {source.getShape()};
|
||||
tmpShape.makeShapeWithElementMap(source.getShape(), *Mapper(), sources);
|
||||
|
||||
// Make sure that there's at least 1 mapped element
|
||||
ASSERT_GE(tmpShape.getElementMap().size(), 1);
|
||||
|
||||
// For all the mappedElements ...
|
||||
for (const auto& mappedElement : tmpShape.getElementMap()) {
|
||||
|
||||
std::string tagInfo = composeTagInfo(mappedElement, source);
|
||||
|
||||
EXPECT_NE(mappedElement.name.find(tagInfo),
|
||||
-1); // ... we check that in the name postfix there's the source tag
|
||||
// preceded by the POSTFIX_TAG, followed by a semicolon and the
|
||||
// number of characters, in Hex, from the beginning of the name
|
||||
// postfix to the beginning of the POSTFIX_TAG of the given
|
||||
// source's tag. VALID ONLY FOR SINGLE SHAPES!!! For complex
|
||||
// shapes the number of characters is calculated differently
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user