Toponaming: fix bug with points in sketches

This commit is contained in:
bgbsww
2024-05-31 20:45:15 -04:00
committed by Chris Hennes
parent 5feb963f9d
commit a495280693

View File

@@ -664,6 +664,103 @@ unsigned validateSketches(std::vector<App::DocumentObject*>& sketches,
return freeSketches;
}
/**
* Partially pulled from Linkstage3 importExternalObjects for toponaming element map
* compatibility with sketches that contain point objects. By adding an empty
* subobject when appropriate, we allow those sketches to be used as profiles without error.
*
* @param prop The property ( generally a Profile link )
* @param _sobjs Subobjects to use
* @param report True if we should raise a dialog, otherwise raise and exception
* @return True if elements were found
*/
bool importExternalElements(App::PropertyLinkSub& prop, std::vector<App::SubObjectT> _sobjs)
{
if (!prop.getName() || !prop.getName()[0]) {
FC_THROWM(Base::RuntimeError, "Invalid property");
}
auto editObj = Base::freecad_dynamic_cast<App::DocumentObject>(prop.getContainer());
if (!editObj) {
FC_THROWM(Base::RuntimeError, "Editing object not found");
}
auto body = PartDesign::Body::findBodyOf(editObj);
if (!body) {
FC_THROWM(Base::RuntimeError,
"No body for editing object: " << editObj->getNameInDocument());
}
std::map<App::DocumentObject*, std::vector<std::string>> links;
std::vector<App::SubObjectT> sobjs;
auto docName = editObj->getDocument()->getName();
auto inList = editObj->getInListEx(true);
for (auto sobjT : _sobjs) {
auto sobj = sobjT.getSubObject();
if (sobj == editObj) {
continue;
}
if (!sobj) {
FC_THROWM(Base::RuntimeError,
"Object not found: " << sobjT.getSubObjectFullName(docName));
}
if (inList.count(sobj)) {
FC_THROWM(Base::RuntimeError,
"Cyclic dependency on object " << sobjT.getSubObjectFullName(docName));
}
sobjT.normalized();
// Make sure that if a subelement is chosen for some object,
// we exclude whole object reference for that object.
auto& subs = links[sobj];
std::string element = sobjT.getOldElementName();
if (element.size()) {
if (subs.size() == 1 && subs.front().empty()) {
for (auto it = sobjs.begin(); it != sobjs.end();) {
if (it->getSubObject() == sobj) {
sobjs.erase(it);
break;
}
}
}
}
else if (subs.size() > 0) {
continue;
}
subs.push_back(std::move(element));
sobjs.push_back(sobjT);
}
int import = 0;
App::DocumentObject* obj = nullptr;
std::vector<std::string> subs;
for (const auto& sobjT : sobjs) {
auto sobj = sobjT.getSubObject();
if (PartDesign::Body::findBodyOf(sobj) != body) {
import = 1;
break;
}
if (!obj) {
obj = sobj;
}
else if (obj != sobj) {
if (!import) {
import = -1;
}
break;
}
subs.push_back(sobjT.getOldElementName());
}
if (!import) {
if (subs.empty()) {
subs.emplace_back();
}
if (obj == prop.getValue() && prop.getSubValues() == subs) {
return false;
}
prop.setValue(obj, std::move(subs));
return true;
}
return false;
}
void prepareProfileBased(PartDesign::Body *pcActiveBody, Gui::Command* cmd, const std::string& which,
std::function<void (Part::Feature*, App::DocumentObject*)> func)
{
@@ -687,6 +784,15 @@ void prepareProfileBased(PartDesign::Body *pcActiveBody, Gui::Command* cmd, cons
auto objCmd = Gui::Command::getObjectCmd(feature);
// Populate the subs parameter by checking for external elements before
// we construct our command.
auto ProfileFeature = Base::freecad_dynamic_cast<PartDesign::ProfileBased>(Feat);
std::vector<std::string>& cmdSubs = const_cast<vector<std::string>&>(subs);
if (subs.size() == 0) {
importExternalElements(ProfileFeature->Profile, {feature});
cmdSubs = ProfileFeature->Profile.getSubValues();
}
// run the command in console to set the profile (without selected subelements)
auto runProfileCmd =
[=]() {
@@ -698,7 +804,7 @@ void prepareProfileBased(PartDesign::Body *pcActiveBody, Gui::Command* cmd, cons
auto runProfileCmdWithSubs =
[=]() {
std::ostringstream ss;
for (auto &s : subs)
for (auto &s : cmdSubs)
ss << "'" << s << "',";
FCMD_OBJ_CMD(Feat,"Profile = (" << objCmd << ", [" << ss.str() << "])");
};
@@ -772,10 +878,8 @@ void prepareProfileBased(PartDesign::Body *pcActiveBody, Gui::Command* cmd, cons
}
}
else {
if (feature->isDerivedFrom(Part::Part2DObject::getClassTypeId()) || subs.empty())
runProfileCmd();
else
runProfileCmdWithSubs();
// Always use the subs
runProfileCmdWithSubs();
}
func(static_cast<Part::Feature*>(feature), Feat);