Toponaming: Transfer in SketchObject::InternalShape

This commit is contained in:
Zheng, Lei
2024-07-18 17:16:04 -04:00
committed by bgbsww
parent a19f4dd398
commit a600952665
2 changed files with 146 additions and 14 deletions

View File

@@ -82,6 +82,7 @@
#include <Mod/Part/App/DatumFeature.h>
#include <Mod/Part/App/GeometryMigrationExtension.h>
#include <Mod/Part/App/TopoShapeOpCode.h>
#include <Mod/Part/App/WireJoiner.h>
#include "SketchObject.h"
#include "SketchObjectPy.h"
@@ -125,6 +126,14 @@ SketchObject::SketchObject()
(App::PropertyType)(App::Prop_Output | App::Prop_ReadOnly | App::Prop_Hidden),
"Sketch is fully constrained");
ADD_PROPERTY(InternalShape,
(Part::TopoShape()));
ADD_PROPERTY_TYPE(MakeInternals,
(false),
"Internal Geometry",
App::Prop_None,
"Make internal geometry, e.g. split intersecting edges, face of closed wires.");
Geometry.setOrderRelevant(true);
allowOtherBody = true;
@@ -173,6 +182,8 @@ SketchObject::SketchObject()
internaltransaction = false;
managedoperation = false;
registerElementCache(internalPrefix(), &InternalShape);
}
SketchObject::~SketchObject()
@@ -186,6 +197,17 @@ SketchObject::~SketchObject()
delete analyser;
}
void SketchObject::setupObject()
{
ParameterGrp::handle hGrpp = App::GetApplication().GetParameterGroupByPath(
"User parameter:BaseApp/Preferences/Mod/Sketcher");
// ArcFitTolerance.setValue(hGrpp->GetFloat("ArcFitTolerance", Precision::Confusion()*10.0));
// ExternalBSplineMaxDegree.setValue(hGrpp->GetInt("ExternalBSplineMaxDegree", 5));
// ExternalBSplineTolerance.setValue(hGrpp->GetFloat("ExternalBSplineTolerance", 1e-4));
MakeInternals.setValue(hGrpp->GetBool("MakeInternals", false));
inherited::setupObject();
}
short SketchObject::mustExecute() const
{
if (Geometry.isTouched())
@@ -309,7 +331,11 @@ void SketchObject::buildShape()
shapes.push_back(getEdge(geo, convertSubName(
Data::IndexedName::fromConst("ExternalEdge", i-1), false).c_str()));
}
internalElementMap.clear();
if(shapes.empty() && vertices.empty()) {
InternalShape.setValue(Part::TopoShape());
Shape.setValue(Part::TopoShape());
return;
}
@@ -337,9 +363,89 @@ void SketchObject::buildShape()
result.makeElementCompound(results, Part::OpCodes::Sketch);
}
result.Tag = getID();
InternalShape.setValue(buildInternals(result.located(TopLoc_Location())));
// Must set Shape property after InternalShape so that
// GeoFeature::updateElementReference() can run properly on change of Shape
// property, because some reference may pointing to the InternalShape
Shape.setValue(result);
}
const std::map<std::string,std::string> SketchObject::getInternalElementMap() const
{
if (!internalElementMap.empty() || !MakeInternals.getValue())
return internalElementMap;
auto internalShape = InternalShape.getShape();
auto shape = Shape.getShape().located(TopLoc_Location());
if (!internalShape.isNull() && !shape.isNull()) {
std::vector<std::string> names;
std::string prefix;
const std::array<TopAbs_ShapeEnum, 2> types = {TopAbs_VERTEX, TopAbs_EDGE};
for (const auto &type : types) {
prefix = internalPrefix() + Part::TopoShape::shapeName(type);
std::size_t len = prefix.size();
int i=0;
for (const auto &v : internalShape.getSubTopoShapes(type)) {
++i;
shape.findSubShapesWithSharedVertex(v, &names, Data::SearchOption::CheckGeometry
|Data::SearchOption::SingleResult);
if (names.empty())
continue;
prefix += std::to_string(i);
internalElementMap[prefix] = names.front();
internalElementMap[names.front()] = prefix;
prefix.resize(len);
names.clear();
}
}
}
return internalElementMap;
}
Part::TopoShape SketchObject::buildInternals(const Part::TopoShape &edges) const
{
if (!MakeInternals.getValue())
return Part::TopoShape();
try {
Part::WireJoiner joiner;
// joiner.setTolerance(InternalTolerance.getValue());
joiner.setTightBound(true);
joiner.setMergeEdges(true);
joiner.addShape(edges);
Part::TopoShape result(getID(), getDocument()->getStringHasher());
if (!joiner.Shape().IsNull()) {
joiner.getResultWires(result, "SKF");
// NOTE: we set minElementNames to 2 (i.e to use at least two
// unused edge name to construct face name) in order to reduce the
// chance of face jumping.
result = result.makeElementFace(result.getSubTopoShapes(TopAbs_WIRE),
/*op*/"",
/*maker*/"Part::FaceMakerRing",
/*pln*/nullptr
#if 1
// /*minElementNames (revert to 1 for now, see how it fares)*/1
#else
/*minElementNames*/2
#endif
);
}
Part::TopoShape openWires(getID(), getDocument()->getStringHasher());
joiner.getOpenWires(openWires, "SKF");
if (openWires.isNull())
return result;
if (result.isNull())
return openWires;
return result.makeElementCompound({result, openWires});
} catch (Base::Exception &e) {
FC_WARN("Failed to make face for sketch: " << e.what());
} catch (Standard_Failure &e) {
FC_WARN("Failed to make face for sketch: " << e.GetMessageString());
}
return Part::TopoShape();
}
static const char *hasSketchMarker(const char *name) {
static std::string marker(Part::TopoShape::elementMapPrefix()+Part::OpCodes::Sketch);
if (!name)
@@ -9514,11 +9620,11 @@ App::DocumentObject *SketchObject::getSubObject(
if (auto realType = convertInternalName(indexedName.getType())) {
if (realType[0] == '\0')
subshape = Shape.getShape();
subshape = InternalShape.getShape();
else {
auto shapeType = Part::TopoShape::shapeType(realType, true);
if (shapeType != TopAbs_SHAPE)
subshape = Shape.getShape().getSubTopoShape(shapeType, indexedName.getIndex(), true);
subshape = InternalShape.getShape().getSubTopoShape(shapeType, indexedName.getIndex(), true);
}
if (subshape.isNull())
return nullptr;
@@ -9662,13 +9768,12 @@ App::ElementNamePair SketchObject::getElementName(
if (auto realName = convertInternalName(ret.oldName.c_str())) {
Data::MappedElement mappedElement;
(void)realName;
// Todo: Do we need to add the InternalShape?
// if (mapped)
// mappedElement = InternalShape.getShape().getElementName(name);
// else if (type == ElementNameType::Export)
// ret.newName = getExportElementName(InternalShape.getShape(), realName).first;
// else
// mappedElement = InternalShape.getShape().getElementName(realName);
if (mapped)
mappedElement = InternalShape.getShape().getElementName(name);
else if (type == ElementNameType::Export)
ret.first = getExportElementName(InternalShape.getShape(), realName).first;
else
mappedElement = InternalShape.getShape().getElementName(realName);
if (mapped || type != ElementNameType::Export) {
if (mappedElement.index) {
@@ -9832,9 +9937,25 @@ bool SketchObject::geoIdFromShapeType(const Data::IndexedName & indexedName,
return true;
}
std::string SketchObject::convertSubName(const Data::IndexedName & indexedName, bool postfix) const
std::string SketchObject::convertSubName(const char *subname, bool postfix) const
{
return convertSubName(checkSubName(subname), postfix);
}
std::string SketchObject::convertSubName(const Data::IndexedName & indexedName, bool postfix) const{
std::ostringstream ss;
if (auto realType = convertInternalName(indexedName.getType())) {
auto mapped = InternalShape.getShape().getMappedName(
Data::IndexedName::fromConst(realType, indexedName.getIndex()));
if (!mapped) {
if (postfix)
ss << indexedName;
} else if (postfix)
ss << Data::ComplexGeoData::elementMapPrefix() << mapped << '.' << indexedName;
else
ss << mapped;
return ss.str();
}
int geoId;
PointPos posId;
if(!geoIdFromShapeType(indexedName,geoId,posId)) {

View File

@@ -46,6 +46,7 @@ class SketchAnalysis;
class SketcherExport SketchObject: public Part::Part2DObject
{
typedef Part::Part2DObject inherited;
PROPERTY_HEADER_WITH_OVERRIDE(Sketcher::SketchObject);
public:
@@ -66,6 +67,8 @@ public:
Sketcher::PropertyConstraintList Constraints;
App ::PropertyLinkSubList ExternalGeometry;
App ::PropertyBool FullyConstrained;
Part ::PropertyPartShape InternalShape;
App ::PropertyBool MakeInternals;
/** @name methods override Feature */
//@{
short mustExecute() const override;
@@ -78,6 +81,7 @@ public:
{
return "SketcherGui::ViewProviderSketch";
}
void setupObject() override;
//@}
/** SketchObject can work in two modes: Recompute Mode and noRecomputes Mode
@@ -695,10 +699,7 @@ public:
return geoIdFromShapeType(shapetype, geoId, posId);
}
std::string convertSubName(const char* subname, bool postfix = true) const
{
return convertSubName(checkSubName(subname), postfix);
}
std::string convertSubName(const char* subname, bool postfix = true) const;
std::string convertSubName(const std::string& subname, bool postfix = true) const
{
@@ -769,6 +770,15 @@ public:
// Validation routines
std::vector<Base::Vector3d> getOpenVertices() const;
// Signaled when solver has done update
boost::signals2::signal<void()> signalSolverUpdate;
boost::signals2::signal<void()> signalElementsChanged;
Part::TopoShape buildInternals(const Part::TopoShape& edges) const;
/// Get a map from internal element to the same geometry in normal shape
const std::map<std::string, std::string> getInternalElementMap() const;
public: // geometry extension functionalities for single element sketch object user convenience
int setGeometryId(int GeoId, long id);
int getGeometryId(int GeoId, long& id) const;
@@ -920,6 +930,7 @@ private:
// indicates whether changes to properties are the deed of SketchObject or not (for input
// validation)
bool managedoperation;
mutable std::map<std::string, std::string> internalElementMap;
};
inline int SketchObject::initTemporaryMove(int geoId, PointPos pos, bool fine /*=true*/)