Sketcher: Driving/reference creation improvements and some other fixes

======================================================================

- Changing from Driving to reference does not include unnecessary solvings.
- Added some checks to avoid making Driving constraints when calling directly from python and involving only external geometry (would give redundant constraints).
- New python command toggleDriving to just change the status from reference to Driving
- New UI toolbar Command to toggle constraints
- Fix to allow switching from/to construction mode during continuous mode creation.
- Enable/Disable for constraints in constraints widget has changed to operate on multiselection and now effects "toggle" instead of enable/disable.
- Disable the option to directly create a SnellsLaw non-driving constraint (this constraint does not support direct creation, it can be toggled to non-driving after creation though).
This commit is contained in:
Abdullah Tahiri 2015-05-26 14:37:22 +02:00 committed by wmayer
parent 4dfc96e102
commit a1c3b942aa
9 changed files with 180 additions and 52 deletions

View File

@ -234,7 +234,10 @@ int SketchObject::setDriving(int ConstrId, bool isdriving)
type != Radius &&
type != Angle &&
type != SnellsLaw)
return -1;
return -2;
if (!(vals[ConstrId]->First>=0 || vals[ConstrId]->Second>=0 || vals[ConstrId]->Third>=0) && isdriving==true)
return -3; // a constraint that does not have at least one element as not-external-geometry can never be driving.
// copy the list
std::vector<Constraint *> newVals(vals);
@ -245,11 +248,7 @@ int SketchObject::setDriving(int ConstrId, bool isdriving)
this->Constraints.setValues(newVals);
delete constNew;
int err = solve();
if (err)
this->Constraints.setValues(vals);
return err;
return 0;
}
int SketchObject::getDriving(int ConstrId, bool &isdriving)
@ -273,6 +272,38 @@ int SketchObject::getDriving(int ConstrId, bool &isdriving)
return 0;
}
int SketchObject::toggleDriving(int ConstrId)
{
const std::vector<Constraint *> &vals = this->Constraints.getValues();
if (ConstrId < 0 || ConstrId >= int(vals.size()))
return -1;
ConstraintType type = vals[ConstrId]->Type;
if (type != Distance &&
type != DistanceX &&
type != DistanceY &&
type != Radius &&
type != Angle &&
type != SnellsLaw)
return -2;
if (!(vals[ConstrId]->First>=0 || vals[ConstrId]->Second>=0 || vals[ConstrId]->Third>=0) && vals[ConstrId]->isDriving==false)
return -3; // a constraint that does not have at least one element as not-external-geometry can never be driving.
// copy the list
std::vector<Constraint *> newVals(vals);
// clone the changed Constraint
Constraint *constNew = vals[ConstrId]->clone();
constNew->isDriving = !constNew->isDriving;
newVals[ConstrId] = constNew;
this->Constraints.setValues(newVals);
delete constNew;
return 0;
}
int SketchObject::movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toPoint, bool relative)
{
Sketch sketch;
@ -489,7 +520,7 @@ int SketchObject::setConstruction(int GeoId, bool on)
newVals[GeoId]=geoNew;
this->Geometry.setValues(newVals);
this->Constraints.acceptGeometry(getCompleteGeometry());
//this->Constraints.acceptGeometry(getCompleteGeometry()); <= This is not necessary for a toggle. Reducing redundant solving. Abdullah
return 0;
}

View File

@ -114,6 +114,8 @@ public:
int setDriving(int ConstrId, bool isdriving);
/// get the driving status of this constraint
int getDriving(int ConstrId, bool &isdriving);
/// toggle the driving status of this constraint
int toggleDriving(int ConstrId);
/// move this point to a new location and solve
int movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toPoint, bool relative=false);
/// retrieves the coordinates of a point

View File

@ -87,6 +87,11 @@
<Documentation>
<UserDocu>Get the Driving status of a datum constraint</UserDocu>
</Documentation>
</Methode>
<Methode Name="toggleDriving">
<Documentation>
<UserDocu>toggle the Driving status of a datum constraint</UserDocu>
</Documentation>
</Methode>
<Methode Name="movePoint">
<Documentation>

View File

@ -49,7 +49,7 @@ using namespace Sketcher;
// returns a string which represents the object e.g. when printed in python
std::string SketchObjectPy::representation(void) const
{
{
return "<Sketcher::SketchObject>";
}
@ -578,7 +578,7 @@ PyObject* SketchObjectPy::setDriving(PyObject *args)
if (this->getSketchObjectPtr()->setDriving(constrid, PyObject_IsTrue(driving) ? true : false)) {
std::stringstream str;
str << "Not able set Driving for constraint with the given index: " << constrid;
str << "Not able set Driving/reference for constraint with the given index: " << constrid;
PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0;
}
@ -603,6 +603,23 @@ PyObject* SketchObjectPy::getDriving(PyObject *args)
return Py::new_reference_to(Py::Boolean(driving));
}
PyObject* SketchObjectPy::toggleDriving(PyObject *args)
{
int constrid;
if (!PyArg_ParseTuple(args, "i", &constrid))
return 0;
if (this->getSketchObjectPtr()->toggleDriving(constrid)) {
std::stringstream str;
str << "Not able toggle Driving for constraint with the given index: " << constrid;
PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0;
}
Py_Return;
}
PyObject* SketchObjectPy::movePoint(PyObject *args)
{

View File

@ -2869,10 +2869,10 @@ void CmdSketcherConstrainSnellsLaw::activated(int iMsg)
std::swap(PosId2,PosId3);
}
bool allexternal=false;
//a bunch of validity checks
if ((GeoId1 < 0 && GeoId2 < 0 && GeoId3 < 0)) {
allexternal=true;
strError = QObject::tr("Can not create constraint with external geometry only!!", dmbg);
throw(Base::Exception(""));
}
if (!(isVertex(GeoId1,PosId1) && !isSimpleVertex(Obj, GeoId1, PosId1) &&
@ -2884,29 +2884,27 @@ void CmdSketcherConstrainSnellsLaw::activated(int iMsg)
double n2divn1=0;
if(!allexternal){
//the essence.
//Unlike other constraints, we'll ask for a value immediately.
QDialog dlg(Gui::getMainWindow());
Ui::InsertDatum ui_Datum;
ui_Datum.setupUi(&dlg);
dlg.setWindowTitle(EditDatumDialog::tr("Refractive index ratio", dmbg));
ui_Datum.label->setText(EditDatumDialog::tr("Ratio n2/n1:", dmbg));
Base::Quantity init_val;
init_val.setUnit(Base::Unit());
init_val.setValue(0.0);
//the essence.
//Unlike other constraints, we'll ask for a value immediately.
QDialog dlg(Gui::getMainWindow());
Ui::InsertDatum ui_Datum;
ui_Datum.setupUi(&dlg);
dlg.setWindowTitle(EditDatumDialog::tr("Refractive index ratio", dmbg));
ui_Datum.label->setText(EditDatumDialog::tr("Ratio n2/n1:", dmbg));
Base::Quantity init_val;
init_val.setUnit(Base::Unit());
init_val.setValue(0.0);
ui_Datum.labelEdit->setValue(init_val);
ui_Datum.labelEdit->setParamGrpPath(QByteArray("User parameter:BaseApp/History/SketcherRefrIndexRatio"));
ui_Datum.labelEdit->setToLastUsedValue();
ui_Datum.labelEdit->selectNumber();
ui_Datum.labelEdit->setValue(init_val);
ui_Datum.labelEdit->setParamGrpPath(QByteArray("User parameter:BaseApp/History/SketcherRefrIndexRatio"));
ui_Datum.labelEdit->setToLastUsedValue();
ui_Datum.labelEdit->selectNumber();
if (dlg.exec() != QDialog::Accepted) return;
ui_Datum.labelEdit->pushToHistory();
if (dlg.exec() != QDialog::Accepted) return;
ui_Datum.labelEdit->pushToHistory();
Base::Quantity newQuant = ui_Datum.labelEdit->value();
n2divn1 = newQuant.getValue();
}
Base::Quantity newQuant = ui_Datum.labelEdit->value();
n2divn1 = newQuant.getValue();
//add constraint
openCommand("add Snell's law constraint");
@ -2925,12 +2923,12 @@ void CmdSketcherConstrainSnellsLaw::activated(int iMsg)
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('SnellsLaw',%d,%d,%d,%d,%d,%.12f)) ",
selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,GeoId3,n2divn1);
if (allexternal || constraintCreationMode==Reference) { // it is a constraint on a external line, make it non-driving
/*if (allexternal || constraintCreationMode==Reference) { // it is a constraint on a external line, make it non-driving
const std::vector<Sketcher::Constraint *> &ConStr = Obj->Constraints.getValues();
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)",
selection[0].getFeatName(),ConStr.size()-1,"False");
}
}*/
commitCommand();
updateActive();
@ -3437,6 +3435,83 @@ bool CmdSketcherConstraintCreationMode::isActive(void)
return false;
}
/* Constrain commands =======================================================*/
DEF_STD_CMD_A(CmdSketcherToggleDrivingConstraint);
CmdSketcherToggleDrivingConstraint::CmdSketcherToggleDrivingConstraint()
:Command("Sketcher_ToggleDrivingConstraint")
{
sAppModule = "Sketcher";
sGroup = QT_TR_NOOP("Sketcher");
sMenuText = QT_TR_NOOP("Toggle reference/driving constraint");
sToolTipText = QT_TR_NOOP("Toggles the currently selected constraint to/from reference mode");
sWhatsThis = "Sketcher_ToggleDrivingConstraint";
sStatusTip = sToolTipText;
sPixmap = "Sketcher_ToggleDrivingConstraint";
sAccel = "";
eType = ForEdit;
}
void CmdSketcherToggleDrivingConstraint::activated(int iMsg)
{
// get the selection
std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
// only one sketch with its subelements are allowed to be selected
if (selection.size() != 1) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Select constraint(s) from the sketch."));
return;
}
// get the needed lists and objects
const std::vector<std::string> &SubNames = selection[0].getSubNames();
if (SubNames.empty()) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Select constraint(s) from the sketch."));
return;
}
// make sure the selected object is the sketch in edit mode
const App::DocumentObject* obj = selection[0].getObject();
ViewProviderSketch* sketchView = static_cast<ViewProviderSketch*>
(Gui::Application::Instance->getViewProvider(obj));
// undo command open
openCommand("Toggle driving from/to non-driving");
int succesful=SubNames.size();
// go through the selected subelements
for (std::vector<std::string>::const_iterator it=SubNames.begin();it!=SubNames.end();++it){
// only handle constraints
if (it->size() > 10 && it->substr(0,10) == "Constraint") {
int ConstrId = std::atoi(it->substr(10,4000).c_str()) - 1;
try {
// issue the actual commands to toggle
doCommand(Doc,"App.ActiveDocument.%s.toggleDriving(%d) ",selection[0].getFeatName(),ConstrId);
}
catch(const Base::Exception& e) {
succesful--;
}
}
}
if(succesful>0)
commitCommand();
else
abortCommand();
updateActive();
// clear the selection (convenience)
getSelection().clearSelection();
}
bool CmdSketcherToggleDrivingConstraint::isActive(void)
{
return isCreateConstraintActive( getActiveGuiDocument() );
}
void CreateSketcherCommandsConstraints(void)
{
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
@ -3459,5 +3534,5 @@ void CreateSketcherCommandsConstraints(void)
rcCmdMgr.addCommand(new CmdSketcherConstrainSnellsLaw());
rcCmdMgr.addCommand(new CmdSketcherConstrainInternalAlignment());
rcCmdMgr.addCommand(new CmdSketcherConstraintCreationMode());
rcCmdMgr.addCommand(new CmdSketcherToggleDrivingConstraint());
}

View File

@ -5350,7 +5350,16 @@ void CmdSketcherGeometryCreationMode::activated(int iMsg)
bool CmdSketcherGeometryCreationMode::isActive(void)
{
return isCreateGeoActive(getActiveGuiDocument());
Gui::Document * doc=getActiveGuiDocument();
if (doc) {
// checks if a Sketch Viewprovider is in Edit and is in no special mode
if (doc->getInEdit() && doc->getInEdit()->isDerivedFrom
(SketcherGui::ViewProviderSketch::getClassTypeId())) {
return true;
}
}
return false;
}
void CreateSketcherCommandsCreateGeo(void)

View File

@ -136,7 +136,7 @@ void ConstraintView::contextMenuEvent (QContextMenuEvent* event)
{
ConstraintItem *it = dynamic_cast<ConstraintItem*>(item);
QAction* driven = menu.addAction(it->isDriving?tr("Change to reference"):tr("Change to driving"), this, SLOT(updateDrivingStatus()));
QAction* driven = menu.addAction(tr("Toggle to/from reference"), this, SLOT(updateDrivingStatus()));
// if its the right constraint
if ((it->Type == Sketcher::Distance ||
it->Type == Sketcher::DistanceX ||
@ -349,21 +349,8 @@ void TaskSketcherConstrains::on_listWidgetConstraints_updateDrivingStatus(QListW
ConstraintItem *it = dynamic_cast<ConstraintItem*>(item);
if (!item) return;
const std::vector< Sketcher::Constraint * > &vals = sketchView->getSketchObject()->Constraints.getValues();
try {
Gui::Command::openCommand("Modify driving status of constraint");
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setDriving(%i,%s)",
this->sketchView->getSketchObject()->getNameInDocument(),
it->ConstraintNbr,
status?"True":"False");
Gui::Command::commitCommand();
Gui::Command::updateActive();
}
catch (const Base::Exception& e) {
Gui::Command::abortCommand();
}
Gui::Application::Instance->commandManager().runCommandByName("Sketcher_ToggleDrivingConstraint");
slotConstraintsChanged();
}

View File

@ -50,7 +50,7 @@
</item>
<item>
<property name="text">
<string>Non-Driving</string>
<string>Reference</string>
</property>
</item>
</widget>

View File

@ -206,6 +206,7 @@ inline void SketcherAddWorkbenchConstraints<Gui::MenuItem>(Gui::MenuItem& cons){
<< "Sketcher_ConstrainSnellsLaw"
<< "Sketcher_ConstrainInternalAlignment"
<< "Separator"
<< "Sketcher_ToggleDrivingConstraint"
<< "Sketcher_ConstraintCreationMode";
}
@ -229,6 +230,7 @@ inline void SketcherAddWorkbenchConstraints<Gui::ToolBarItem>(Gui::ToolBarItem&
<< "Sketcher_ConstrainAngle"
<< "Sketcher_ConstrainSnellsLaw"
<< "Separator"
<< "Sketcher_ToggleDrivingConstraint"
<< "Sketcher_ConstraintCreationMode";
}