diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index b04caf52ed..876b221e0e 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -33,7 +33,12 @@ #include #include #include - +#include +#include +#include +#include +#include +#include class gp_Ax1; class gp_Ax2; @@ -717,9 +722,9 @@ public: * a self reference so that multiple operations can be carried out * for the same shape in the same line of code. */ - // TopoShape& makeElementShellFromWires(const std::vector& wires, - // bool silent = true, - // const char* op = nullptr); + TopoShape& makeElementShellFromWires(const std::vector& wires, + bool silent = true, + const char* op = nullptr); /* Make a shell with input wires * * @param wires: input wires @@ -729,10 +734,10 @@ public: * * @return Return the new shape. The TopoShape itself is not modified. */ - // TopoShape& makeElementShellFromWires(bool silent = true, const char* op = nullptr) - // { - // return makeElementShellFromWires(getSubTopoShapes(TopAbs_WIRE), silent, op); - // } + TopoShape& makeElementShellFromWires(bool silent = true, const char* op = nullptr) + { + return makeElementShellFromWires(getSubTopoShapes(TopAbs_WIRE), silent, op); + } TopoShape& makeElementFace(const std::vector& shapes, const char* op = nullptr, @@ -822,6 +827,222 @@ public: CN, }; + + /** Generic shape making with mapped element name from shape history + * + * @param mkShape: OCCT shape maker. + * @param sources: list of source shapes. + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @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& makeElementShape(BRepBuilderAPI_MakeShape& mkShape, + const std::vector& sources, + const char* op = nullptr); + /** Generic shape making with mapped element name from shape history + * + * @param mkShape: OCCT shape maker. + * @param source: source shape. + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @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& makeElementShape(BRepBuilderAPI_MakeShape& mkShape, + const TopoShape& source, + const char* op = nullptr); + /** Generic shape making with mapped element name from shape history + * + * @param mkShape: OCCT shape maker. + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @return Returns the new shape built by the shape maker with mappend element + * name generated using this shape as the source. The shape itself + * is not modified. + */ + TopoShape makeElementShape(BRepBuilderAPI_MakeShape& mkShape, const char* op = nullptr) const + { + return TopoShape(0, Hasher).makeElementShape(mkShape, *this, op); + } + + /** Specialized shape making for BRepBuilderAPI_Sewing with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param sources: list of source shapes. + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @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& makeElementShape(BRepBuilderAPI_Sewing& mkShape, + const std::vector& sources, + const char* op = nullptr); + /** Specialized shape making for BRepBuilderAPI_Sewing with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param source: source shape. + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @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& makeElementShape(BRepBuilderAPI_Sewing& mkShape, + const TopoShape& source, + const char* op = nullptr); + /** Specialized shape making for BRepBuilderAPI_Sewing with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @return Returns the new shape built by the shape maker with mappend element + * name generated using this shape as the source. The shape itself + * is not modified. + */ + TopoShape makeElementShape(BRepBuilderAPI_Sewing& mkShape, const char* op = nullptr) const + { + return TopoShape(0, Hasher).makeElementShape(mkShape, *this, op); + } + + /** Specialized shape making for BRepBuilderAPI_ThruSections with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param sources: list of source shapes. + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @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& makeElementShape(BRepOffsetAPI_ThruSections& mkShape, + const std::vector& sources, + const char* op = nullptr); + /** Specialized shape making for BRepBuilderAPI_Sewing with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param source: source shape. + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @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& makeElementShape(BRepOffsetAPI_ThruSections& mkShape, + const TopoShape& source, + const char* op = nullptr); + /** Specialized shape making for BRepBuilderAPI_Sewing with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @return Returns the new shape built by the shape maker with mappend element + * name generated using this shape as the source. The shape itself + * is not modified. + */ + TopoShape makeElementShape(BRepOffsetAPI_ThruSections& mkShape, const char* op = nullptr) const + { + return TopoShape(0, Hasher).makeElementShape(mkShape, *this, op); + } + + /** Specialized shape making for BRepBuilderAPI_MakePipeShell with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param sources: list of source shapes. + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @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& makeElementShape(BRepOffsetAPI_MakePipeShell& mkShape, + const std::vector& sources, + const char* op = nullptr); + + /** Specialized shape making for BRepBuilderAPI_MakeHalfSpace with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param source: source shape. + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @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& makeElementShape(BRepPrimAPI_MakeHalfSpace& mkShape, + const TopoShape& source, + const char* op = nullptr); + /** Specialized shape making for BRepBuilderAPI_MakeHalfSpace with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @return Returns the new shape built by the shape maker with mappend element + * name generated using this shape as the source. The shape itself + * is not modified. + */ + TopoShape makeElementShape(BRepPrimAPI_MakeHalfSpace& mkShape, const char* op = nullptr) const + { + return TopoShape(0, Hasher).makeElementShape(mkShape, *this, op); + } + + /** Specialized shape making for BRepBuilderAPI_MakePrism with mapped element name + * + * @param mkShape: OCCT shape maker. + * @param sources: list of source shapes. + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * + * @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& makeElementShape(BRepFeat_MakePrism& mkShape, + const std::vector& sources, + const TopoShape& uptoface, + const char* op); + + /** Helper class to return the generated and modified shape given an input shape + * + * Shape history information is extracted using OCCT APIs + * BRepBuilderAPI_MakeShape::Generated/Modified(). However, there is often + * some glitches in various derived class. So we use this class as an + * abstraction, and create various derived classes to deal with the glitches. + */ + friend class TopoShapeCache; private: @@ -956,6 +1177,22 @@ private: }; + +/** Shape mapper for generic BRepBuilderAPI_MakeShape derived class + * + * Uses BRepBuilderAPI_MakeShape::Modified/Generated() function to extract + * shape history for generating mapped element names + */ +struct PartExport MapperMaker: TopoShape::Mapper +{ + BRepBuilderAPI_MakeShape& maker; + explicit MapperMaker(BRepBuilderAPI_MakeShape& maker) + : maker(maker) + {} + const std::vector& modified(const TopoDS_Shape& s) const override; + const std::vector& generated(const TopoDS_Shape& s) const override; +}; + } // namespace Part diff --git a/src/Mod/Part/App/TopoShapeExpansion.cpp b/src/Mod/Part/App/TopoShapeExpansion.cpp index eb6b03be29..b861b58eb4 100644 --- a/src/Mod/Part/App/TopoShapeExpansion.cpp +++ b/src/Mod/Part/App/TopoShapeExpansion.cpp @@ -42,12 +42,11 @@ #include "TopoShape.h" #include "TopoShapeCache.h" -#include "TopoShapeOpCode.h" #include "FaceMaker.h" +#include "TopoShapeOpCode.h" #include - FC_LOG_LEVEL_INIT("TopoShape", true, true) // NOLINT namespace Part @@ -263,6 +262,7 @@ size_t checkSubshapeCount(const TopoShape& topoShape1, } return count; } + } // namespace void TopoShape::setupChild(Data::ElementMap::MappedChildElements& child, @@ -316,7 +316,7 @@ void warnIfLogging() if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { FC_WARN("hasher mismatch"); // NOLINT } -}; +} void hasherMismatchError() { @@ -392,11 +392,11 @@ void TopoShape::mapSubElementTypeForShape(const TopoShape& other, sids.clear(); } } - std::ostringstream ss; char elementType {shapeName(type)[0]}; if (!elementMap()) { FC_THROWM(NullShapeException, "No element map"); // NOLINT } + std::ostringstream ss; elementMap()->encodeElementName(elementType, name, ss, &sids, Tag, op, other.Tag); elementMap()->setElementName(element, name, Tag, &sids); } @@ -530,7 +530,7 @@ struct ShapeInfo , shapetype(TopoShape::shapeName(type).c_str()) {} - int count() const + [[nodiscard]] int count() const { return cache.count(); } @@ -1298,6 +1298,142 @@ TopoShape::makeElementCompound(const std::vector& shapes, const char* return *this; } +struct MapperSewing: Part::TopoShape::Mapper +{ + BRepBuilderAPI_Sewing& maker; + explicit MapperSewing(BRepBuilderAPI_Sewing& maker) + : maker(maker) + {} + const std::vector& modified(const TopoDS_Shape& s) const override + { + _res.clear(); + try { + const auto& shape = maker.Modified(s); + if (!shape.IsNull() && !shape.IsSame(s)) { + _res.push_back(shape); + } + else { + const auto& sshape = maker.ModifiedSubShape(s); + if (!sshape.IsNull() && !sshape.IsSame(s)) { + _res.push_back(sshape); + } + } + } + catch (const Standard_Failure& e) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { + FC_WARN("Exception on shape mapper: " << e.GetMessageString()); + } + } + return _res; + } +}; + +struct MapperThruSections: MapperMaker +{ + TopoShape firstProfile; + TopoShape lastProfile; + + MapperThruSections(BRepOffsetAPI_ThruSections& tmaker, const std::vector& profiles) + : MapperMaker(tmaker) + { + if (!tmaker.FirstShape().IsNull()) { + firstProfile = profiles.front(); + } + if (!tmaker.LastShape().IsNull()) { + lastProfile = profiles.back(); + } + } + const std::vector& generated(const TopoDS_Shape& s) const override + { + MapperMaker::generated(s); + if ( ! _res.empty()) { + return _res; + } + try { + auto& tmaker = dynamic_cast(maker); + auto shape = tmaker.GeneratedFace(s); + if (!shape.IsNull()) { + _res.push_back(shape); + } + if (firstProfile.getShape().IsSame(s) || firstProfile.findShape(s)) { + _res.push_back(tmaker.FirstShape()); + } + else if (lastProfile.getShape().IsSame(s) || lastProfile.findShape(s)) { + _res.push_back(tmaker.LastShape()); + } + } + catch (const Standard_Failure& e) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { + FC_WARN("Exception on shape mapper: " << e.GetMessageString()); + } + } + return _res; + } +}; + + +TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_MakeShape& mkShape, + const TopoShape& source, + const char* op) +{ + std::vector sources(1, source); + return makeElementShape(mkShape, sources, op); +} + +TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_MakeShape& mkShape, + const std::vector& shapes, + const char* op) +{ + return makeShapeWithElementMap(mkShape.Shape(), MapperMaker(mkShape), shapes, op); +} + +TopoShape& +TopoShape::makeElementShape(BRepOffsetAPI_ThruSections& mk, const TopoShape& source, const char* op) +{ + if (!op) { + op = Part::OpCodes::ThruSections; + } + return makeElementShape(mk, std::vector(1, source), op); +} + +TopoShape& TopoShape::makeElementShape(BRepOffsetAPI_ThruSections& mk, + const std::vector& sources, + const char* op) +{ + if (!op) { + op = Part::OpCodes::ThruSections; + } + return makeShapeWithElementMap(mk.Shape(), MapperThruSections(mk, sources), sources, op); +} + +TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_Sewing& mk, + const std::vector& shapes, + const char* op) +{ + if (!op) { + op = Part::OpCodes::Sewing; + } + return makeShapeWithElementMap(mk.SewedShape(), MapperSewing(mk), shapes, op); +} + +TopoShape& +TopoShape::makeElementShape(BRepBuilderAPI_Sewing& mkShape, const TopoShape& source, const char* op) +{ + if (!op) { + op = Part::OpCodes::Sewing; + } + return makeElementShape(mkShape, std::vector(1, source), op); +} + +TopoShape& TopoShape::makeElementShape(BRepPrimAPI_MakeHalfSpace& mkShape, + const TopoShape& source, + const char* op) +{ + if (!op) { + op = Part::OpCodes::HalfSpace; + } + return makeShapeWithElementMap(mkShape.Solid(), MapperMaker(mkShape), {source}, op); +} TopoShape& TopoShape::makeElementFace(const TopoShape& shape, const char* op, @@ -1395,7 +1531,7 @@ Data::MappedName TopoShape::setElementComboName(const Data::IndexedName& element const Data::ElementIDRefs* _sids) { if (names.empty()) { - return Data::MappedName(); + return Data::MappedName {}; } std::string _marker; if (!marker) { @@ -1474,7 +1610,7 @@ TopoShape TopoShape::splitWires(std::vector* inner, SplitWireReorient tmp = BRepTools::OuterWire(TopoDS::Face(getSubShape(TopAbs_FACE, 1))); } if (tmp.IsNull()) { - return TopoShape(); + return TopoShape {}; } const auto& wires = getSubTopoShapes(TopAbs_WIRE); auto it = wires.begin(); @@ -1541,7 +1677,7 @@ TopoShape TopoShape::splitWires(std::vector* inner, SplitWireReorient } } } - return TopoShape(); + return TopoShape {}; } struct MapperFill: Part::TopoShape::Mapper @@ -1568,6 +1704,40 @@ struct MapperFill: Part::TopoShape::Mapper } }; +const std::vector& MapperMaker::modified(const TopoDS_Shape& s) const +{ + _res.clear(); + try { + TopTools_ListIteratorOfListOfShape it; + for (it.Initialize(maker.Modified(s)); it.More(); it.Next()) { + _res.push_back(it.Value()); + } + } + catch (const Standard_Failure& e) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { + FC_WARN("Exception on shape mapper: " << e.GetMessageString()); + } + } + return _res; +} + +const std::vector& MapperMaker::generated(const TopoDS_Shape& s) const +{ + _res.clear(); + try { + TopTools_ListIteratorOfListOfShape it; + for (it.Initialize(maker.Generated(s)); it.More(); it.Next()) { + _res.push_back(it.Value()); + } + } + catch (const Standard_Failure& e) { + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { + FC_WARN("Exception on shape mapper: " << e.GetMessageString()); + } + } + return _res; +} + // topo naming counterpart of TopoShape::makeShell() TopoShape& TopoShape::makeElementShell(bool silent, const char* op) { @@ -1659,26 +1829,26 @@ TopoShape& TopoShape::makeElementShell(bool silent, const char* op) return *this; } -// TopoShape& TopoShape::makeElementShellFromWires(const std::vector& wires, -// bool silent, -// const char* op) -// { -// BRepFill_Generator maker; -// for (auto& w : wires) { -// if (w.shapeType(silent) == TopAbs_WIRE) { -// maker.AddWire(TopoDS::Wire(w.getShape())); -// } -// } -// if (wires.empty()) { -// if (silent) { -// _Shape.Nullify(); -// return *this; -// } -// FC_THROWM(NullShapeException, "No input shapes"); -// } -// maker.Perform(); -// this->makeShapeWithElementMap(maker.Shell(), MapperFill(maker), wires, op); -// return *this; -// } +TopoShape& TopoShape::makeElementShellFromWires(const std::vector& wires, + bool silent, + const char* op) +{ + BRepFill_Generator maker; + for (auto& w : wires) { + if (w.shapeType(silent) == TopAbs_WIRE) { + maker.AddWire(TopoDS::Wire(w.getShape())); + } + } + if (wires.empty()) { + if (silent) { + _Shape.Nullify(); + return *this; + } + FC_THROWM(NullShapeException, "No input shapes"); + } + maker.Perform(); + this->makeShapeWithElementMap(maker.Shell(), MapperFill(maker), wires, op); + return *this; +} } // namespace Part diff --git a/tests/src/Mod/Part/App/CMakeLists.txt b/tests/src/Mod/Part/App/CMakeLists.txt index f239b3a27b..68f026f412 100644 --- a/tests/src/Mod/Part/App/CMakeLists.txt +++ b/tests/src/Mod/Part/App/CMakeLists.txt @@ -17,4 +17,5 @@ target_sources( ${CMAKE_CURRENT_SOURCE_DIR}/TopoShapeExpansion.cpp ${CMAKE_CURRENT_SOURCE_DIR}/TopoShapeMakeShapeWithElementMap.cpp ${CMAKE_CURRENT_SOURCE_DIR}/TopoShapeMapper.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TopoShapeMakeShape.cpp ) diff --git a/tests/src/Mod/Part/App/TopoShapeMakeShape.cpp b/tests/src/Mod/Part/App/TopoShapeMakeShape.cpp new file mode 100644 index 0000000000..11dd498309 --- /dev/null +++ b/tests/src/Mod/Part/App/TopoShapeMakeShape.cpp @@ -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 + +#include + +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* _sids = nullptr; + Part::TopoShape _shape; + Part::TopoShape::Mapper _mapper; +}; + +TEST_F(TopoShapeMakeShapeTests, nullShapeThrows) +{ + // Arrange + auto [cube1, cube2] = CreateTwoCubes(); + std::vector 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 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); +}