Sketcher new feature: Select Conflict and Redundant Constraints
Based (and solves) Mantis ticket: http://www.freecadweb.org/tracker/view.php?id=1643 The ticket refers only to redundant, and ask for deletion. Two commands are created, one for redundant constraints and other for conflicting constraints. As usually removing one constraint of the "at least one" is sufficient, the implementation selects the constraints (but does not delete them). The user therefore easily identify the constraints involved and decide to delete them. This implementation takes into account the edit->Actsketch that ViewProvidedSketch creates for solving, as it is this instance the one that generates the messages in the Sketcher Taskbar. No buttons in the toolbar by default (can be added by the user), but an hyperlink in the solver messages which triggers the selection of the appropriate command (conflicting or redundant).
This commit is contained in:
parent
bdbf5140f9
commit
34cc7c3136
|
@ -108,6 +108,7 @@ App::DocumentObjectExecReturn *SketchObject::execute(void)
|
|||
}
|
||||
|
||||
Sketch sketch;
|
||||
|
||||
int dofs = sketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(),
|
||||
getExternalGeometryCount());
|
||||
if (dofs < 0) { // over-constrained sketch
|
||||
|
|
|
@ -448,6 +448,114 @@ bool CmdSketcherSelectHorizontalAxis::isActive(void)
|
|||
return isSketcherAcceleratorActive( getActiveGuiDocument(), false );
|
||||
}
|
||||
|
||||
DEF_STD_CMD_A(CmdSketcherSelectRedundantConstraints);
|
||||
|
||||
CmdSketcherSelectRedundantConstraints::CmdSketcherSelectRedundantConstraints()
|
||||
:Command("Sketcher_SelectRedundantConstraints")
|
||||
{
|
||||
sAppModule = "Sketcher";
|
||||
sGroup = QT_TR_NOOP("Sketcher");
|
||||
sMenuText = QT_TR_NOOP("Select Redundant Constraints");
|
||||
sToolTipText = QT_TR_NOOP("Select Redundant Constraints");
|
||||
sWhatsThis = sToolTipText;
|
||||
sStatusTip = sToolTipText;
|
||||
sPixmap = "Sketcher_SelectRedundantConstraints";
|
||||
sAccel = "CTRL+SHIFT+R";
|
||||
eType = ForEdit;
|
||||
}
|
||||
|
||||
void CmdSketcherSelectRedundantConstraints::activated(int iMsg)
|
||||
{
|
||||
Gui::Document * doc= getActiveGuiDocument();
|
||||
|
||||
SketcherGui::ViewProviderSketch* vp = dynamic_cast<SketcherGui::ViewProviderSketch*>(doc->getInEdit());
|
||||
|
||||
Sketcher::SketchObject* Obj= vp->getSketchObject();
|
||||
|
||||
std::string doc_name = Obj->getDocument()->getName();
|
||||
std::string obj_name = Obj->getNameInDocument();
|
||||
std::stringstream ss;
|
||||
|
||||
// get the needed lists and objects
|
||||
const std::vector< int > &solverredundant = dynamic_cast<SketcherGui::ViewProviderSketch*>(doc->getInEdit())->getRedundant();
|
||||
const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
|
||||
|
||||
getSelection().clearSelection();
|
||||
|
||||
// push the constraints
|
||||
int i=1;
|
||||
for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();it != vals.end(); ++it,++i) {
|
||||
for(std::vector< int >::const_iterator itc= solverredundant.begin();itc != solverredundant.end(); ++itc) {
|
||||
if ( (*itc) == i){
|
||||
ss.str(std::string());
|
||||
ss << "Constraint" << i;
|
||||
Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool CmdSketcherSelectRedundantConstraints::isActive(void)
|
||||
{
|
||||
return isSketcherAcceleratorActive( getActiveGuiDocument(), false );
|
||||
}
|
||||
|
||||
DEF_STD_CMD_A(CmdSketcherSelectConflictingConstraints);
|
||||
|
||||
CmdSketcherSelectConflictingConstraints::CmdSketcherSelectConflictingConstraints()
|
||||
:Command("Sketcher_SelectConflictingConstraints")
|
||||
{
|
||||
sAppModule = "Sketcher";
|
||||
sGroup = QT_TR_NOOP("Sketcher");
|
||||
sMenuText = QT_TR_NOOP("Select Conflicting Constraints");
|
||||
sToolTipText = QT_TR_NOOP("Select Conflicting Constraints");
|
||||
sWhatsThis = sToolTipText;
|
||||
sStatusTip = sToolTipText;
|
||||
sPixmap = "Sketcher_SelectConflictingConstraints";
|
||||
sAccel = "CTRL+SHIFT+E";
|
||||
eType = ForEdit;
|
||||
}
|
||||
|
||||
void CmdSketcherSelectConflictingConstraints::activated(int iMsg)
|
||||
{
|
||||
Gui::Document * doc= getActiveGuiDocument();
|
||||
|
||||
SketcherGui::ViewProviderSketch* vp = dynamic_cast<SketcherGui::ViewProviderSketch*>(doc->getInEdit());
|
||||
|
||||
Sketcher::SketchObject* Obj= vp->getSketchObject();
|
||||
|
||||
std::string doc_name = Obj->getDocument()->getName();
|
||||
std::string obj_name = Obj->getNameInDocument();
|
||||
std::stringstream ss;
|
||||
|
||||
// get the needed lists and objects
|
||||
const std::vector< int > &solverconflicting = dynamic_cast<SketcherGui::ViewProviderSketch*>(doc->getInEdit())->getConflicting();
|
||||
const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
|
||||
|
||||
getSelection().clearSelection();
|
||||
|
||||
// push the constraints
|
||||
int i=1;
|
||||
for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();it != vals.end(); ++it,++i) {
|
||||
for(std::vector< int >::const_iterator itc= solverconflicting.begin();itc != solverconflicting.end(); ++itc) {
|
||||
if ( (*itc) == i){
|
||||
ss.str(std::string());
|
||||
ss << "Constraint" << i;
|
||||
Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CmdSketcherSelectConflictingConstraints::isActive(void)
|
||||
{
|
||||
return isSketcherAcceleratorActive( getActiveGuiDocument(), false );
|
||||
}
|
||||
|
||||
DEF_STD_CMD_A(CmdSketcherSelectElementsAssociatedWithConstraints);
|
||||
|
||||
CmdSketcherSelectElementsAssociatedWithConstraints::CmdSketcherSelectElementsAssociatedWithConstraints()
|
||||
|
@ -573,7 +681,6 @@ bool CmdSketcherSelectElementsAssociatedWithConstraints::isActive(void)
|
|||
return isSketcherAcceleratorActive( getActiveGuiDocument(), true );
|
||||
}
|
||||
|
||||
// Add Accelerator Commands
|
||||
void CreateSketcherCommandsConstraintAccel(void)
|
||||
{
|
||||
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
|
||||
|
@ -584,5 +691,7 @@ void CreateSketcherCommandsConstraintAccel(void)
|
|||
rcCmdMgr.addCommand(new CmdSketcherSelectOrigin());
|
||||
rcCmdMgr.addCommand(new CmdSketcherSelectVerticalAxis());
|
||||
rcCmdMgr.addCommand(new CmdSketcherSelectHorizontalAxis());
|
||||
rcCmdMgr.addCommand(new CmdSketcherSelectRedundantConstraints());
|
||||
rcCmdMgr.addCommand(new CmdSketcherSelectConflictingConstraints());
|
||||
rcCmdMgr.addCommand(new CmdSketcherSelectElementsAssociatedWithConstraints());
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <Gui/ViewProvider.h>
|
||||
#include <Gui/WaitCursor.h>
|
||||
#include <Gui/Selection.h>
|
||||
#include <Gui/Command.h>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
|
@ -56,6 +57,13 @@ TaskSketcherMessages::TaskSketcherMessages(ViewProviderSketch *sketchView)
|
|||
|
||||
connectionSetUp = sketchView->signalSetUp.connect(boost::bind(&SketcherGui::TaskSketcherMessages::slotSetUp, this,_1));
|
||||
connectionSolved = sketchView->signalSolved.connect(boost::bind(&SketcherGui::TaskSketcherMessages::slotSolved, this,_1));
|
||||
|
||||
ui->labelConstrainStatus->setOpenExternalLinks(false);
|
||||
|
||||
QObject::connect(
|
||||
ui->labelConstrainStatus, SIGNAL(linkActivated(const QString &)),
|
||||
this , SLOT (on_labelConstrainStatus_linkActivated(const QString &))
|
||||
);
|
||||
}
|
||||
|
||||
TaskSketcherMessages::~TaskSketcherMessages()
|
||||
|
@ -75,4 +83,14 @@ void TaskSketcherMessages::slotSolved(QString msg)
|
|||
ui->labelSolverStatus->setText(msg);
|
||||
}
|
||||
|
||||
void TaskSketcherMessages::on_labelConstrainStatus_linkActivated(const QString &str)
|
||||
{
|
||||
if( str == QString::fromLatin1("#conflicting"))
|
||||
Gui::Application::Instance->commandManager().runCommandByName("Sketcher_SelectConflictingConstraints");
|
||||
|
||||
if( str == QString::fromLatin1("#redundant"))
|
||||
Gui::Application::Instance->commandManager().runCommandByName("Sketcher_SelectRedundantConstraints");
|
||||
}
|
||||
|
||||
|
||||
#include "moc_TaskSketcherMessages.cpp"
|
||||
|
|
|
@ -51,6 +51,7 @@ public:
|
|||
void slotSolved(QString msg);
|
||||
|
||||
private Q_SLOTS:
|
||||
void on_labelConstrainStatus_linkActivated(const QString &);
|
||||
|
||||
protected:
|
||||
ViewProviderSketch *sketchView;
|
||||
|
|
|
@ -3688,8 +3688,8 @@ QString ViewProviderSketch::appendConflictMsg(const std::vector<int> &conflictin
|
|||
if (conflicting.size() > 0) {
|
||||
if (conflicting.size() == 1)
|
||||
ss << tr("Please remove the following constraint:");
|
||||
else
|
||||
ss << tr("Please remove at least one of the following constraints:");
|
||||
else
|
||||
ss << tr("Please remove at least one of the following constraints:");
|
||||
ss << "\n";
|
||||
ss << conflicting[0];
|
||||
for (unsigned int i=1; i < conflicting.size(); i++)
|
||||
|
@ -3712,11 +3712,22 @@ QString ViewProviderSketch::appendRedundantMsg(const std::vector<int> &redundant
|
|||
ss << redundant[0];
|
||||
for (unsigned int i=1; i < redundant.size(); i++)
|
||||
ss << ", " << redundant[i];
|
||||
|
||||
ss << "\n";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
const std::vector<int> &ViewProviderSketch::getConflicting(void) const
|
||||
{
|
||||
return edit->ActSketch.getConflicting();
|
||||
}
|
||||
|
||||
const std::vector<int> &ViewProviderSketch::getRedundant(void) const
|
||||
{
|
||||
return edit->ActSketch.getRedundant();
|
||||
}
|
||||
|
||||
void ViewProviderSketch::solveSketch(void)
|
||||
{
|
||||
// set up the sketch and diagnose possible conflicts
|
||||
|
@ -3730,29 +3741,33 @@ void ViewProviderSketch::solveSketch(void)
|
|||
else if (dofs < 0) { // over-constrained sketch
|
||||
std::string msg;
|
||||
SketchObject::appendConflictMsg(edit->ActSketch.getConflicting(), msg);
|
||||
signalSetUp(QString::fromLatin1("<font color='red'>%1<br/>%2</font>")
|
||||
.arg(tr("Over-constrained sketch"))
|
||||
.arg(QString::fromStdString(msg)));
|
||||
signalSetUp(QString::fromLatin1("<font color='red'>%1<a href=\"#conflicting\"><span style=\" text-decoration: underline; color:#0000ff;\">%2</span></a><br/>%3</font><br/>")
|
||||
.arg(tr("Over-constrained sketch "))
|
||||
.arg(tr("(click to select)"))
|
||||
.arg(QString::fromStdString(msg)));
|
||||
signalSolved(QString());
|
||||
}
|
||||
else if (edit->ActSketch.hasConflicts()) { // conflicting constraints
|
||||
signalSetUp(QString::fromLatin1("<font color='red'>%1<br/>%2</font>")
|
||||
.arg(tr("Sketch contains conflicting constraints"))
|
||||
signalSetUp(QString::fromLatin1("<font color='red'>%1<a href=\"#conflicting\"><span style=\" text-decoration: underline; color:#0000ff;\">%2</span></a><br/>%3</font><br/>")
|
||||
.arg(tr("Sketch contains conflicting constraints "))
|
||||
.arg(tr("(click to select)"))
|
||||
.arg(appendConflictMsg(edit->ActSketch.getConflicting())));
|
||||
signalSolved(QString());
|
||||
}
|
||||
else {
|
||||
if (edit->ActSketch.hasRedundancies()) { // redundant constraints
|
||||
signalSetUp(QString::fromLatin1("<font color='orange'>%1<br/>%2</font>")
|
||||
.arg(tr("Sketch contains redundant constraints"))
|
||||
signalSetUp(QString::fromLatin1("<font color='DarkOrange'>%1<a href=\"#redundant\"><span style=\" text-decoration: underline; color:#0000ff;\">%2</span></a><br/>%3</font><br/>")
|
||||
.arg(tr("Sketch contains redundant constraints "))
|
||||
.arg(tr("(click to select)"))
|
||||
.arg(appendRedundantMsg(edit->ActSketch.getRedundant())));
|
||||
}
|
||||
if (edit->ActSketch.solve() == 0) { // solving the sketch
|
||||
if (dofs == 0) {
|
||||
// color the sketch as fully constrained
|
||||
edit->FullyConstrained = true;
|
||||
if (!edit->ActSketch.hasRedundancies())
|
||||
if (!edit->ActSketch.hasRedundancies()) {
|
||||
signalSetUp(QString::fromLatin1("<font color='green'>%1</font>").arg(tr("Fully constrained sketch")));
|
||||
}
|
||||
}
|
||||
else if (!edit->ActSketch.hasRedundancies()) {
|
||||
if (dofs == 1)
|
||||
|
@ -3760,6 +3775,7 @@ void ViewProviderSketch::solveSketch(void)
|
|||
else
|
||||
signalSetUp(tr("Under-constrained sketch with %1 degrees of freedom").arg(dofs));
|
||||
}
|
||||
|
||||
signalSolved(tr("Solved in %1 sec").arg(edit->ActSketch.SolveTime));
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -220,7 +220,12 @@ public:
|
|||
/// signals if the elements list has changed
|
||||
boost::signal<void ()> signalElementsChanged;
|
||||
|
||||
|
||||
/** @name Act sketch interface */
|
||||
//@{
|
||||
const std::vector<int> &getConflicting(void) const;
|
||||
const std::vector<int> &getRedundant(void) const;
|
||||
//@}
|
||||
|
||||
protected:
|
||||
virtual bool setEdit(int ModNum);
|
||||
virtual void unsetEdit(int ModNum);
|
||||
|
|
|
@ -210,14 +210,15 @@ inline void SketcherAddWorkbenchTools<Gui::MenuItem>(Gui::MenuItem& consaccel){
|
|||
<< "Sketcher_SelectOrigin"
|
||||
<< "Sketcher_SelectVerticalAxis"
|
||||
<< "Sketcher_SelectHorizontalAxis"
|
||||
<< "Sketcher_SelectRedundantConstraints"
|
||||
<< "Sketcher_SelectConflictingConstraints"
|
||||
<< "Sketcher_SelectElementsAssociatedWithConstraints";
|
||||
}
|
||||
template <>
|
||||
inline void SketcherAddWorkbenchTools<Gui::ToolBarItem>(Gui::ToolBarItem& consaccel){
|
||||
consaccel << "Sketcher_CloseShape"
|
||||
<< "Sketcher_ConnectLines"
|
||||
<< "Sketcher_SelectConstraints"
|
||||
<< "Sketcher_SelectElementsAssociatedWithConstraints";
|
||||
<< "Sketcher_SelectConstraints";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
Loading…
Reference in New Issue
Block a user