Toponaming: fix bug with points in sketches
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user