Merge pull request #13084 from bgbsww/bgbsww-toponamingSketcherGetElementName

Toponaming/Part: Move sketcher override of getElementName over
This commit is contained in:
Chris Hennes
2024-03-25 23:00:04 -05:00
committed by GitHub
4 changed files with 142 additions and 29 deletions

View File

@@ -230,6 +230,36 @@ public:
ElementIDRefs *sid = nullptr,
bool copy = false) const;
/** Add a sub-element name mapping.
*
* @param element: the original \c Type + \c Index element name
* @param name: the mapped sub-element name. May or may not start with
* elementMapPrefix().
* @param sid: in case you use a hasher to hash the element name, pass in
* the string id reference using this parameter. You can have more than one
* string id associated with the same name.
* @param overwrite: if true, it will overwrite existing names
*
* @return Returns the stored mapped element name.
*
* An element can have multiple mapped names. However, a name can only be
* mapped to one element
*
* Note: the original proc was in the context of ComplexGeoData, which provided `Tag` access,
* now you must pass in `long masterTag` explicitly.
*/
MappedName setElementName(const IndexedName& element,
const MappedName& name,
long masterTag,
const ElementIDRefs* sid = nullptr,
bool overwrite = false) {
return _elementMap -> setElementName(element, name, masterTag, sid, overwrite);
}
bool hasElementMap() {
return _elementMap != nullptr;
}
/** Get mapped element names
*
* @param element: original element name with \c Type + \c Index

View File

@@ -243,7 +243,7 @@ App::DocumentObjectExecReturn* SketchObject::execute()
// this is not necessary for sketch representation in edit mode, unless we want to trigger an
// update of the objects that depend on this sketch (like pads)
Shape.setValue(solvedSketch.toShape());
buildShape();
return App::DocumentObject::StdReturn;
}
@@ -280,30 +280,37 @@ void SketchObject::buildShape()
// shapes.push_back(getEdge(geo, convertSubName(
// Data::IndexedName::fromConst("ExternalEdge", i-1), false).c_str()));
// }
// if(shapes.empty() && vertices.empty())
// Shape.setValue(Part::TopoShape());
// else if (vertices.empty()) {
// // Notice here we supply op code Part::OpCodes::Sketch to makEWires().
// Shape.setValue(Part::TopoShape().makEWires(shapes,Part::OpCodes::Sketch));
// } else {
// std::vector<Part::TopoShape> results;
// if (!shapes.empty()) {
// // This call of makEWires() does not have the op code, in order to
// // avoid duplication. Because we'll going to make a compound (to
// // include the vertices) below with the same op code.
// //
// // Note, that we HAVE TO add the Part::OpCodes::Sketch op code to all
// // geometry exposed through the Shape property, because
// // SketchObject::getElementName() relies on this op code to
// // differentiate geometries that are exposed with those in edit
// // mode.
// auto wires = Part::TopoShape().makEWires(shapes);
// for (const auto &wire : wires.getSubTopoShapes(TopAbs_WIRE))
// results.push_back(wire);
// }
// results.insert(results.end(), vertices.begin(), vertices.end());
// Shape.setValue(Part::TopoShape().makECompound(results, Part::OpCodes::Sketch));
// }
if(shapes.empty() && vertices.empty())
Shape.setValue(Part::TopoShape());
else if (vertices.empty()) {
// Notice here we supply op code Part::OpCodes::Sketch to makEWires().
Shape.setValue(Part::TopoShape().makeElementWires(shapes,Part::OpCodes::Sketch));
} else {
std::vector<Part::TopoShape> results;
if (!shapes.empty()) {
// This call of makeElementWires() does not have the op code, in order to
// avoid duplication. Because we'll going to make a compound (to
// include the vertices) below with the same op code.
//
// Note, that we HAVE TO add the Part::OpCodes::Sketch op code to all
// geometry exposed through the Shape property, because
// SketchObject::getElementName() relies on this op code to
// differentiate geometries that are exposed with those in edit
// mode.
auto wires = Part::TopoShape().makeElementWires(shapes);
for (const auto &wire : wires.getSubTopoShapes(TopAbs_WIRE))
results.push_back(wire);
}
results.insert(results.end(), vertices.begin(), vertices.end());
Shape.setValue(Part::TopoShape().makeElementCompound(results, Part::OpCodes::Sketch));
}
}
static const char *hasSketchMarker(const char *name) {
static std::string marker(Part::TopoShape::elementMapPrefix()+Part::OpCodes::Sketch);
if (!name)
return nullptr;
return strstr(name,marker.c_str());
}
int SketchObject::hasConflicts() const
@@ -9514,11 +9521,54 @@ void SketchObject::setExpression(const App::ObjectIdentifier& path,
}
}
std::pair<std::string,std::string> SketchObject::getElementName(
const char *name, ElementNameType type) const
{
std::pair<std::string, std::string> ret;
if(!name) return ret;
if(hasSketchMarker(name))
return Part2DObject::getElementName(name,type);
const char *mapped = Data::isMappedElement(name);
if(!mapped) {
auto occindex = Part::TopoShape::shapeTypeAndIndex(name);
if (occindex.second)
return Part2DObject::getElementName(name,type);
Data::IndexedName index = checkSubName(name);
ret.first = convertSubName(index, true);
if(!Data::isMappedElement(ret.first.c_str()))
ret.first.clear();
index.appendToStringBuffer(ret.second);
return ret;
}
Data::IndexedName index = checkSubName(name);
if(index) {
index.appendToStringBuffer(ret.second);
ret.first = convertSubName(index, true);
if(type==ElementNameType::Export) {
if(boost::starts_with(ret.second,"Vertex"))
ret.second[0] = 'v';
else if(boost::starts_with(ret.second,"Edge"))
ret.second[0] = 'e';
}
}
return ret;
}
Part::TopoShape SketchObject::getEdge(const Part::Geometry *geo, const char *name) const
{
Part::TopoShape shape(geo->toShape());
// shape.setElementName(Data::IndexedName::fromConst("Edge", 1),
// Data::MappedName::fromRawData(name));
// Originally in ComplexGeoData::setElementName
// LinkStable/src/App/ComplexGeoData.cpp#L1631
// No longer possible after map separated in ElementMap.cpp
if ( !shape.hasElementMap() ) {
shape.resetElementMap(std::make_shared<Data::ElementMap>());
}
shape.setElementName(Data::IndexedName::fromConst("Edge", 1),
Data::MappedName::fromRawData(name),0L);
TopTools_IndexedMapOfShape vmap;
TopExp::MapShapes(shape.getShape(), TopAbs_VERTEX, vmap);
std::ostringstream ss;
@@ -9530,8 +9580,8 @@ Part::TopoShape SketchObject::getEdge(const Part::Geometry *geo, const char *nam
if(getPoint(geo,pos[j]) == pt) {
ss.str("");
ss << name << 'v' << static_cast<int>(pos[j]);
// shape.setElementName(Data::IndexedName::fromConst("Vertex", i),
// Data::MappedName::fromRawData(ss.str().c_str()));
shape.setElementName(Data::IndexedName::fromConst("Vertex", i),
Data::MappedName::fromRawData(ss.str().c_str()),0L);
break;
}
}

View File

@@ -701,6 +701,9 @@ public:
std::string convertSubName(const Data::IndexedName&, bool postfix = true) const;
std::pair<std::string, std::string> getElementName(const char* name,
ElementNameType type) const override;
bool isPerformingInternalTransaction() const
{
return internaltransaction;

View File

@@ -253,3 +253,33 @@ TEST_F(SketchObjectTest, testReverseAngleConstraintToSupplementaryExpressionAppl
// Assert
EXPECT_EQ(std::string("32 °"), getObject()->getConstraintExpression(id));
}
TEST_F(SketchObjectTest, testGetElementName)
{
// Arrange
Base::Vector3d p1(0.0, 0.0, 0.0), p2(1.0, 0.0, 0.0);
std::unique_ptr<Part::Geometry> geoline(new Part::GeomLineSegment());
static_cast<Part::GeomLineSegment*>(geoline.get())->setPoints(p1, p2);
getObject()->addGeometry(geoline.get());
getObject()->recomputeFeature(); // or ->execute()
// Act
// unless it's Export, we are really just testing the superclass App::GeoFeature::getElementName
// call.
auto forward_normal_name =
getObject()->getElementName("g39;SKT", App::GeoFeature::ElementNameType::Normal);
auto reverse_normal_name =
getObject()->getElementName("Vertex2", App::GeoFeature::ElementNameType::Normal);
auto reverse_export_name =
getObject()->getElementName("Vertex1", App::GeoFeature::ElementNameType::Export);
auto map = getObject()->Shape.getShape().getElementMap();
ASSERT_EQ(map.size(), 3);
EXPECT_STREQ(map[0].name.toString().c_str(), "g39;SKT");
EXPECT_EQ(map[0].index.toString(), "Edge1");
// Assert
EXPECT_STREQ(forward_normal_name.first.c_str(), ";g39;SKT.Edge1");
EXPECT_STREQ(forward_normal_name.second.c_str(), "Edge1");
EXPECT_STREQ(reverse_normal_name.first.c_str(), ";g39v2;SKT.Vertex2");
EXPECT_STREQ(reverse_normal_name.second.c_str(), "Vertex2");
EXPECT_STREQ(reverse_export_name.first.c_str(), ";g39v1;SKT.Vertex1");
EXPECT_STREQ(reverse_export_name.second.c_str(), "Vertex1");
}