Sketcher: Added support for expressions.
This commit is contained in:
@@ -46,6 +46,9 @@
|
||||
# include <vector>
|
||||
#endif // #ifndef _PreComp_
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <App/Document.h>
|
||||
#include <Base/Writer.h>
|
||||
#include <Base/Reader.h>
|
||||
#include <Base/Tools.h>
|
||||
@@ -93,6 +96,11 @@ SketchObject::SketchObject()
|
||||
solverNeedsUpdate=false;
|
||||
|
||||
noRecomputes=false;
|
||||
|
||||
ExpressionEngine.setValidator(boost::bind(&Sketcher::SketchObject::validateExpression, this, _1, _2));
|
||||
|
||||
constraintsRemovedConn = Constraints.signalConstraintsRemoved.connect(boost::bind(&Sketcher::SketchObject::constraintsRemoved, this, _1));
|
||||
constraintsRenamedConn = Constraints.signalConstraintsRenamed.connect(boost::bind(&Sketcher::SketchObject::constraintsRenamed, this, _1));
|
||||
}
|
||||
|
||||
SketchObject::~SketchObject()
|
||||
@@ -247,7 +255,7 @@ int SketchObject::setDatum(int ConstrId, double Datum)
|
||||
std::vector<Constraint *> newVals(vals);
|
||||
// clone the changed Constraint
|
||||
Constraint *constNew = vals[ConstrId]->clone();
|
||||
constNew->Value = Datum;
|
||||
constNew->setValue(Datum);
|
||||
newVals[ConstrId] = constNew;
|
||||
this->Constraints.setValues(newVals);
|
||||
delete constNew;
|
||||
@@ -286,6 +294,8 @@ int SketchObject::setDriving(int ConstrId, bool isdriving)
|
||||
constNew->isDriving = isdriving;
|
||||
newVals[ConstrId] = constNew;
|
||||
this->Constraints.setValues(newVals);
|
||||
if (isdriving)
|
||||
setExpression(Constraints.createPath(ConstrId), boost::shared_ptr<App::Expression>());
|
||||
delete constNew;
|
||||
|
||||
if(noRecomputes) // if we do not have a recompute, the sketch must be solved to update the DoF of the solver
|
||||
@@ -342,6 +352,8 @@ int SketchObject::toggleDriving(int ConstrId)
|
||||
constNew->isDriving = !constNew->isDriving;
|
||||
newVals[ConstrId] = constNew;
|
||||
this->Constraints.setValues(newVals);
|
||||
if (constNew->isDriving)
|
||||
setExpression(Constraints.createPath(ConstrId), boost::shared_ptr<App::Expression>());
|
||||
delete constNew;
|
||||
|
||||
if(noRecomputes) // if we do not have a recompute, the sketch must be solved to update the DoF of the solver
|
||||
@@ -2268,7 +2280,7 @@ int SketchObject::addCopy(const std::vector<int> &geoIdList, const Base::Vector3
|
||||
constNew->Type = Sketcher::Distance;
|
||||
constNew->First = rowrefgeoid;
|
||||
constNew->FirstPos = Sketcher::none;
|
||||
constNew->Value = perpendicularDisplacement.Length();
|
||||
constNew->setValue(perpendicularDisplacement.Length());
|
||||
newconstrVals.push_back(constNew);
|
||||
}
|
||||
|
||||
@@ -2329,14 +2341,14 @@ int SketchObject::addCopy(const std::vector<int> &geoIdList, const Base::Vector3
|
||||
constNew->Type = Sketcher::Distance;
|
||||
constNew->First = colrefgeoid;
|
||||
constNew->FirstPos = Sketcher::none;
|
||||
constNew->Value = displacement.Length();
|
||||
constNew->setValue(displacement.Length());
|
||||
newconstrVals.push_back(constNew);
|
||||
|
||||
constNew = new Constraint();
|
||||
constNew->Type = Sketcher::Angle;
|
||||
constNew->First = colrefgeoid;
|
||||
constNew->FirstPos = Sketcher::none;
|
||||
constNew->Value = atan2(displacement.y,displacement.x);
|
||||
constNew->setValue(atan2(displacement.y,displacement.x));
|
||||
newconstrVals.push_back(constNew);
|
||||
}
|
||||
else { // any other element
|
||||
@@ -3499,6 +3511,38 @@ void SketchObject::validateConstraints()
|
||||
}
|
||||
}
|
||||
|
||||
std::string SketchObject::validateExpression(const App::ObjectIdentifier &path, boost::shared_ptr<const App::Expression> expr)
|
||||
{
|
||||
const App::Property * prop = path.getProperty();
|
||||
|
||||
assert(expr != 0);
|
||||
|
||||
if (!prop)
|
||||
return "Property not found";
|
||||
|
||||
if (prop == &Constraints) {
|
||||
const Constraint * constraint = Constraints.getConstraint(path);
|
||||
|
||||
if (!constraint->isDriving)
|
||||
return "Reference constraints cannot be set!";
|
||||
}
|
||||
|
||||
std::set<App::ObjectIdentifier> deps;
|
||||
expr->getDeps(deps);
|
||||
|
||||
for (std::set<App::ObjectIdentifier>::const_iterator i = deps.begin(); i != deps.end(); ++i) {
|
||||
const App::Property * prop = (*i).getProperty();
|
||||
|
||||
if (prop == &Constraints) {
|
||||
const Constraint * constraint = Constraints.getConstraint(*i);
|
||||
|
||||
if (!constraint->isDriving)
|
||||
return "Reference constraint from this sketch cannot be used in this expression.";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//This function is necessary for precalculation of an angle when adding
|
||||
// an angle constraint. It is also used here, in SketchObject, to
|
||||
// lock down the type of tangency/perpendicularity.
|
||||
@@ -3546,6 +3590,23 @@ double SketchObject::calculateAngleViaPoint(int GeoId1, int GeoId2, double px, d
|
||||
*/
|
||||
}
|
||||
|
||||
void SketchObject::constraintsRenamed(const std::map<App::ObjectIdentifier, App::ObjectIdentifier> &renamed)
|
||||
{
|
||||
ExpressionEngine.renameExpressions(renamed);
|
||||
|
||||
getDocument()->renameObjectIdentifiers(renamed);
|
||||
}
|
||||
|
||||
void SketchObject::constraintsRemoved(const std::set<App::ObjectIdentifier> &removed)
|
||||
{
|
||||
std::set<App::ObjectIdentifier>::const_iterator i = removed.begin();
|
||||
|
||||
while (i != removed.end()) {
|
||||
ExpressionEngine.setValue(*i, boost::shared_ptr<App::Expression>(), 0);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
//Tests if the provided point lies exactly in a curve (satisfies
|
||||
// point-on-object constraint). It is used to decide whether it is nesessary to
|
||||
// constrain a point onto curves when 3-element selection tangent-via-point-like
|
||||
@@ -3841,10 +3902,10 @@ bool SketchObject::AutoLockTangencyAndPerpty(Constraint *cstr, bool bForce, bool
|
||||
{
|
||||
try{
|
||||
//assert ( cstr->Type == Tangent || cstr->Type == Perpendicular);
|
||||
if(cstr->Value != 0.0 && ! bForce) /*tangency type already set. If not bForce - don't touch.*/
|
||||
if(cstr->getValue() != 0.0 && ! bForce) /*tangency type already set. If not bForce - don't touch.*/
|
||||
return true;
|
||||
if(!bLock){
|
||||
cstr->Value=0.0;//reset
|
||||
cstr->setValue(0.0);//reset
|
||||
} else {
|
||||
//decide on tangency type. Write the angle value into the datum field of the constraint.
|
||||
int geoId1, geoId2, geoIdPt;
|
||||
@@ -3880,7 +3941,7 @@ bool SketchObject::AutoLockTangencyAndPerpty(Constraint *cstr, bool bForce, bool
|
||||
if(fabs(angleErr) > M_PI/2 )
|
||||
angleDesire += M_PI;
|
||||
|
||||
cstr->Value = angleDesire + angleOffset; //external tangency. The angle stored is offset by Pi/2 so that a value of 0.0 is invalid and threated as "undecided".
|
||||
cstr->setValue(angleDesire + angleOffset); //external tangency. The angle stored is offset by Pi/2 so that a value of 0.0 is invalid and threated as "undecided".
|
||||
}
|
||||
}
|
||||
} catch (Base::Exception& e){
|
||||
@@ -3891,6 +3952,15 @@ bool SketchObject::AutoLockTangencyAndPerpty(Constraint *cstr, bool bForce, bool
|
||||
return true;
|
||||
}
|
||||
|
||||
void SketchObject::setExpression(const App::ObjectIdentifier &path, boost::shared_ptr<App::Expression> expr, const char * comment)
|
||||
{
|
||||
DocumentObject::setExpression(path, expr, comment);
|
||||
|
||||
if(noRecomputes) // if we do not have a recompute, the sketch must be solved to update the DoF of the solver, constraints and UI
|
||||
solve();
|
||||
}
|
||||
|
||||
|
||||
// Python Sketcher feature ---------------------------------------------------------
|
||||
|
||||
namespace App {
|
||||
|
||||
Reference in New Issue
Block a user