Skip to content

Commit

Permalink
Merge pull request FreeCAD#12528 from bgbsww/bgbsww-toponamingMoveEqu…
Browse files Browse the repository at this point in the history
…alOperator

Toponaming/Part:  Bring in = operator, resetMap and flushMap overrides, and fix affecte…
  • Loading branch information
chennes authored Feb 21, 2024
2 parents 456fa53 + d7f14d3 commit 14d2915
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 118 deletions.
8 changes: 0 additions & 8 deletions src/Mod/Part/App/TopoShape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -593,14 +593,6 @@ void TopoShape::setPyObject(PyObject* obj)
}
}

void TopoShape::operator = (const TopoShape& sh)
{
if (this != &sh) {
this->Tag = sh.Tag;
this->_Shape = sh._Shape;
}
}

void TopoShape::convertTogpTrsf(const Base::Matrix4D& mtrx, gp_Trsf& trsf)
{
trsf.SetValues(mtrx[0][0],mtrx[0][1],mtrx[0][2],mtrx[0][3],
Expand Down
4 changes: 4 additions & 0 deletions src/Mod/Part/App/TopoShape.h
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,10 @@ class PartExport TopoShape: public Data::ComplexGeoData
void mapSubElementsTo(std::vector<TopoShape>& shapes, const char* op = nullptr) const;
bool hasPendingElementMap() const;

void flushElementMap() const override;

virtual Data::ElementMapPtr resetElementMap(

Check warning on line 1009 in src/Mod/Part/App/TopoShape.h

View workflow job for this annotation

GitHub Actions / Lint / Lint

'Part::TopoShape::resetElementMap' hides overloaded virtual function [-Woverloaded-virtual]

Check warning on line 1009 in src/Mod/Part/App/TopoShape.h

View workflow job for this annotation

GitHub Actions / Lint / Lint

'Part::TopoShape::resetElementMap' hides overloaded virtual function [-Woverloaded-virtual]
Data::ElementMapPtr elementMap=Data::ElementMapPtr());

/** Helper class to return the generated and modified shape given an input shape
*
Expand Down
54 changes: 54 additions & 0 deletions src/Mod/Part/App/TopoShapeExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,48 @@ void TopoShape::initCache(int reset) const
}
}

Data::ElementMapPtr TopoShape::resetElementMap(Data::ElementMapPtr elementMap)
{
if (_cache && elementMap != this->elementMap(false)) {
for (auto& info : _cache->shapeAncestryCache) {
info.clear();
}
}
else {
initCache();
}
if (elementMap) {
_cache->cachedElementMap = elementMap;
_cache->subLocation.Identity();
_subLocation.Identity();
_parentCache.reset();
}
return Data::ComplexGeoData::resetElementMap(elementMap);
}

void TopoShape::flushElementMap() const
{
initCache();
if (!elementMap(false) && this->_cache) {
if (this->_cache->cachedElementMap) {
const_cast<TopoShape*>(this)->resetElementMap(this->_cache->cachedElementMap);
}
else if (this->_parentCache) {
TopoShape parent(this->Tag, this->Hasher, this->_parentCache->shape);
parent._cache = _parentCache;
parent.flushElementMap();
TopoShape self(this->Tag,
this->Hasher,
this->_Shape.Located(this->_subLocation * this->_cache->subLocation));
self._cache = _cache;
self.mapSubElement(parent);
this->_parentCache.reset();
this->_subLocation.Identity();
const_cast<TopoShape*>(this)->resetElementMap(self.elementMap());
}
}
}

void TopoShape::setShape(const TopoDS_Shape& shape, bool resetElementMap)
{
if (resetElementMap) {
Expand Down Expand Up @@ -207,6 +249,18 @@ TopoDS_Shape TopoShape::located(const TopoDS_Shape& tds, const gp_Trsf& transfer
return moved(sCopy, transfer);
}

void TopoShape::operator = (const TopoShape& sh)
{
if (this != &sh) {
this->setShape(sh._Shape, true);
this->Tag = sh.Tag;
this->Hasher = sh.Hasher;
this->_cache = sh._cache;
this->_parentCache = sh._parentCache;
this->_subLocation = sh._subLocation;
resetElementMap(sh.elementMap(false));
}
}

int TopoShape::findShape(const TopoDS_Shape& subshape) const
{
Expand Down
34 changes: 34 additions & 0 deletions tests/src/Mod/Part/App/PartTestHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,40 @@ std::map<IndexedName, MappedName> elementMap(const TopoShape& shape)
return result;
}

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() << "\", ";
}
output << "}";
return testing::AssertionFailure() << output.str();
}
return testing::AssertionSuccess();
}

testing::AssertionResult allElementsMatch(const TopoShape& shape,
const std::vector<std::string>& names)
{
auto elements = shape.getElementMap();
if (elements.size() != names.size()) {
return testing::AssertionFailure()
<< elements.size() << " != " << names.size() << " elements in map";
}
return elementsMatch(shape, names);
}

std::pair<TopoDS_Shape, TopoDS_Shape> CreateTwoCubes()
{
auto boxMaker1 = BRepPrimAPI_MakeBox(1.0, 1.0, 1.0);
Expand Down
26 changes: 26 additions & 0 deletions tests/src/Mod/Part/App/PartTestHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,33 @@ boxesMatch(const Base::BoundBox3d& b1, const Base::BoundBox3d& b2, double prec =

std::map<IndexedName, MappedName> elementMap(const TopoShape& shape);

/**
* Checks that all the names occur in the shape's element map. Map can contain additional names
* @param shape The Shape
* @param names The Names
* @return A test result, suitable for display by the gtest framework
*/
testing::AssertionResult elementsMatch(const TopoShape& shape,
const std::vector<std::string>& names);

/**
* Checks that all the names occur in the shape's element map and that there are no additional names
* @param shape The Shape
* @param names The Names
* @return A test result, suitable for display by the gtest framework
*/
testing::AssertionResult allElementsMatch(const TopoShape& shape,
const std::vector<std::string>& names);

/**
*
* @return Two raw shape cubes without element maps
*/
std::pair<TopoDS_Shape, TopoDS_Shape> CreateTwoCubes();

/**
*
* @return Two TopoShape cubes with elementMaps
*/
std::pair<TopoShape, TopoShape> CreateTwoTopoShapeCubes();
} // namespace PartTestHelpers
104 changes: 68 additions & 36 deletions tests/src/Mod/Part/App/TopoShapeExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,38 +127,67 @@ 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();
TopoShape topoShape {edge1};
std::vector<TopoShape> shapes {edge1, edge2};

TopoShape topoShape {1L};
std::vector<TopoShape> shapes {TopoShape(edge1, 2L), TopoShape(edge2, 3L)};
// Act
topoShape.makeElementCompound(shapes);

// Assert
EXPECT_EQ(4, topoShape.getMappedChildElements().size()); // two vertices and two edges
auto elements = elementMap((topoShape));
Base::BoundBox3d bb = topoShape.getBoundBox();
// Assert shape is correct
EXPECT_FLOAT_EQ(getLength(topoShape.getShape()), 2);
EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0, 0, 0, 2, 0, 0)));
// Assert map is correct
EXPECT_TRUE(topoShape.getMappedChildElements().empty());
EXPECT_EQ(elements.size(), 6);
EXPECT_EQ(elements[IndexedName("Edge", 1)], MappedName("Edge1;:H2,E"));
EXPECT_EQ(elements[IndexedName("Edge", 2)], MappedName("Edge1;:H3,E"));
EXPECT_EQ(elements[IndexedName("Vertex", 1)], MappedName("Vertex1;:H2,V"));
EXPECT_EQ(elements[IndexedName("Vertex", 2)], MappedName("Vertex2;:H2,V"));
EXPECT_EQ(elements[IndexedName("Vertex", 3)], MappedName("Vertex1;:H3,V"));
EXPECT_EQ(elements[IndexedName("Vertex", 4)], MappedName("Vertex2;:H3,V"));
}

TEST_F(TopoShapeExpansionTest, makeElementCompoundTwoCubes)
{
// Arrange
auto [cube1, cube2] = CreateTwoCubes();
TopoShape cube1TS {cube1};
cube1TS.Tag = 1;
TopoShape cube2TS {cube2};
cube2TS.Tag = 2;

auto [cube1TS, cube2TS] = CreateTwoTopoShapeCubes();
// Act
TopoShape topoShape;
TopoShape topoShape {3L};
topoShape.makeElementCompound({cube1TS, cube2TS});

// Assert
auto elementMap = topoShape.getElementMap();
EXPECT_EQ(52, elementMap.size());
auto elementMap = cube1TS.getElementMap();
Base::BoundBox3d bb = topoShape.getBoundBox();
// Assert shape is correct
EXPECT_EQ(6, topoShape.getMappedChildElements().size());
EXPECT_FLOAT_EQ(getVolume(topoShape.getShape()), 2);
EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0, 0, 0, 2, 1, 1)));
// Assert map is correct
// Two cubes, each consisting of:
// 8 Vertices
// 12 Edges
// 6 Faces
// ----------
// 26 subshapes each
EXPECT_TRUE(
allElementsMatch(topoShape,
{
"Edge1;:H1,E;:H7,E", "Edge2;:H1,E;:H7,E", "Edge3;:H1,E;:H7,E",
"Edge4;:H1,E;:H7,E", "Edge1;:H2,E;:H7,E", "Edge2;:H2,E;:H7,E",
"Edge3;:H2,E;:H7,E", "Edge4;:H2,E;:H7,E", "Edge1;:H3,E;:H7,E",
"Edge2;:H3,E;:H7,E", "Edge3;:H3,E;:H7,E", "Edge4;:H3,E;:H7,E",
"Edge1;:H8,E;:He,E", "Edge2;:H8,E;:He,E", "Edge3;:H8,E;:He,E",
"Edge4;:H8,E;:He,E", "Edge1;:H9,E;:He,E", "Edge2;:H9,E;:He,E",
"Edge3;:H9,E;:He,E", "Edge4;:H9,E;:He,E", "Edge1;:Ha,E;:He,E",
"Edge2;:Ha,E;:He,E", "Edge3;:Ha,E;:He,E", "Edge4;:Ha,E;:He,E",
"Vertex1;:H8,V;:He,V", "Vertex2;:H8,V;:He,V", "Vertex3;:H8,V;:He,V",
"Vertex4;:H8,V;:He,V", "Vertex1;:H9,V;:He,V", "Vertex2;:H9,V;:He,V",
"Vertex3;:H9,V;:He,V", "Vertex4;:H9,V;:He,V", "Face1;:H1,F;:H7,F",
"Face1;:H2,F;:H7,F", "Face1;:H3,F;:H7,F", "Face1;:H4,F;:H7,F",
"Face1;:H5,F;:H7,F", "Face1;:H6,F;:H7,F", "Face1;:H8,F;:He,F",
"Face1;:H9,F;:He,F", "Face1;:Ha,F;:He,F", "Face1;:Hb,F;:He,F",
"Face1;:Hc,F;:He,F", "Face1;:Hd,F;:He,F", "Vertex1;:H1,V;:H7,V",
"Vertex2;:H1,V;:H7,V", "Vertex3;:H1,V;:H7,V", "Vertex4;:H1,V;:H7,V",
"Vertex1;:H2,V;:H7,V", "Vertex2;:H2,V;:H7,V", "Vertex3;:H2,V;:H7,V",
"Vertex4;:H2,V;:H7,V",
}));
}

TEST_F(TopoShapeExpansionTest, MapperMakerModified)
Expand Down Expand Up @@ -368,7 +397,7 @@ TEST_F(TopoShapeExpansionTest, makeElementWiresCombinesAdjacent)
topoShape.makeElementWires(shapes);
auto elementMap = topoShape.getElementMap();
// Assert
EXPECT_EQ(0, elementMap.size()); // TODO: What is the correct value?
EXPECT_EQ(6, elementMap.size());
}

TEST_F(TopoShapeExpansionTest, makeElementWiresCombinesWires)
Expand All @@ -386,19 +415,22 @@ TEST_F(TopoShapeExpansionTest, makeElementWiresCombinesWires)
auto& wire2 = (new TopoShape {})->makeElementWires(shapes2);
auto& topoShape = (new TopoShape {})->makeElementWires({wire1, wire2});
auto elements = elementMap((topoShape));
// Assert
EXPECT_EQ(elements.size(), 10);
EXPECT_EQ(elements.count(IndexedName("Edge", 1)), 1);
EXPECT_EQ(elements[IndexedName("Edge", 1)], MappedName("Edge1;:H,E"));
EXPECT_EQ(elements[IndexedName("Edge", 2)], MappedName("Edge2;:H,E"));
EXPECT_EQ(elements[IndexedName("Edge", 3)], MappedName("Edge1;:C1;:H:4,E"));
EXPECT_EQ(elements[IndexedName("Edge", 4)], MappedName("Edge2;:C1;:H:4,E"));
EXPECT_EQ(elements[IndexedName("Vertex", 1)], MappedName("Vertex1;:H,V"));
EXPECT_EQ(elements[IndexedName("Vertex", 2)], MappedName("Vertex2;:H,V"));
EXPECT_EQ(elements[IndexedName("Vertex", 3)], MappedName("Vertex3;:H,V"));
EXPECT_EQ(elements[IndexedName("Vertex", 4)], MappedName("Vertex1;:C1;:H:4,V"));
EXPECT_EQ(elements[IndexedName("Vertex", 5)], MappedName("Vertex2;:C1;:H:4,V"));
EXPECT_EQ(elements[IndexedName("Vertex", 6)], MappedName("Vertex3;:C1;:H:4,V"));
Base::BoundBox3d bb = topoShape.getBoundBox();
// Assert shape is correct
EXPECT_FLOAT_EQ(getLength(topoShape.getShape()), 4.4142137);
EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0, 0, 0, 3, 2, 0)));
// Assert map is correct
EXPECT_TRUE(allElementsMatch(topoShape,
{"Edge1;WIR",
"Edge1;WIR;D1",
"Edge1;WIR;D2",
"Edge1;WIR;D1;D1",
"Vertex1;WIR",
"Vertex2;WIR",
"Vertex2;WIR;D1",
"Vertex1;WIR;D1",
"Vertex2;WIR;D2",
"Vertex2;WIR;D1;D1"}));
}

TEST_F(TopoShapeExpansionTest, makeElementFaceNull)
Expand Down Expand Up @@ -622,7 +654,7 @@ TEST_F(TopoShapeExpansionTest, setElementComboNameCompound)
OpCodes::Common,
op);
// ASSERT
EXPECT_STREQ(result.toString().c_str(), "Edge1;:H,E;CMN(Face7|Face8);Copy");
EXPECT_STREQ(result.toString().c_str(), "Edge1;CMN(Face7|Face8);Copy");
// The detailed forms of names are covered in encodeElementName tests
}

Expand Down Expand Up @@ -1308,10 +1340,10 @@ TEST_F(TopoShapeExpansionTest, makeElementDraftTopoShapes)
EXPECT_TRUE(result.getMappedChildElements().empty());
EXPECT_EQ(elements.size(), 26);
EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1);
EXPECT_EQ(elements[IndexedName("Face", 1)], MappedName("Face1;:G;DFT;:He:7,F"));
EXPECT_EQ(elements[IndexedName("Face", 1)], MappedName("Face1;:H8,F;:G;DFT;:He:7,F"));
EXPECT_NEAR(getVolume(result.getShape()), 4.3333333333, 1e-06); // Truncated pyramid
EXPECT_EQ(result2.getElementMap().size(), 0); // No element map in non reference call.
EXPECT_EQ(result3.getElementMap().size(), 0); // No element map in non reference call.
EXPECT_EQ(result2.getElementMap().size(), 26);
EXPECT_EQ(result3.getElementMap().size(), 26);
}

TEST_F(TopoShapeExpansionTest, linearizeEdge)
Expand Down
8 changes: 3 additions & 5 deletions tests/src/Mod/Part/App/TopoShapeMakeShape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,10 @@ TEST_F(TopoShapeMakeShapeTests, shapeVertex)
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);
EXPECT_EQ(result.getElementMap().size(), 0);
EXPECT_EQ(result.countSubElements("Vertex"), 1);
EXPECT_EQ(result.countSubShapes("Vertex"), 1);
}

TEST_F(TopoShapeMakeShapeTests, thruSections)
Expand Down
Loading

0 comments on commit 14d2915

Please sign in to comment.