PropertyExpressionEngine: convert to link type property

PropertyExpressionEngine is changed to derived from a new class
PropertyExpressionContainer, which is in turn derives from
PropertyXLinkContainer. This makes PropertyExpressionEngine a link type
property that is capable of external linking. It now uses the unified
link property APIs for dependency management and tracking of object
life time, re-labeling, etc.

ObjectIdentifier is modified to support sub-object reference, but is
not exposed to end-user, because expression syntax is kept mostly
unchanged, which will be submitted in future PR. There is, however,
one small change in expression syntax (ExpressionParser.y) to introduce
local property reference to avoid ambiguity mentioned in
FreeCAD/FreeCAD#1619

Modified Expression/ExpressionModifier interface to support various link
property API for link modification.
This commit is contained in:
Zheng, Lei
2019-06-29 17:30:51 +08:00
committed by wmayer
parent e85bf9cd0e
commit 93e60caa35
25 changed files with 3895 additions and 1645 deletions

View File

@@ -39,7 +39,10 @@
#include <Base/VectorPy.h>
#include <Base/MatrixPy.h>
#include <Base/PlacementPy.h>
#include <Base/QuantityPy.h>
#include "Document.h"
#include "DocumentObject.h"
#include "Placement.h"
#include "PropertyGeo.h"
#include "ObjectIdentifier.h"
@@ -193,14 +196,46 @@ void PropertyVector::Paste(const Property &from)
void PropertyVector::getPaths(std::vector<ObjectIdentifier> &paths) const
{
paths.push_back(ObjectIdentifier(getContainer()) << ObjectIdentifier::Component::SimpleComponent(getName())
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("x")));
paths.push_back(ObjectIdentifier(getContainer()) << ObjectIdentifier::Component::SimpleComponent(getName())
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("y")));
paths.push_back(ObjectIdentifier(getContainer()) << ObjectIdentifier::Component::SimpleComponent(getName())
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("z")));
paths.push_back(ObjectIdentifier(*this)
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("x")));
paths.push_back(ObjectIdentifier(*this)
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("y")));
paths.push_back(ObjectIdentifier(*this)
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("z")));
}
const boost::any PropertyVector::getPathValue(const ObjectIdentifier &path) const
{
Base::Unit unit = getUnit();
if(!unit.isEmpty()) {
std::string p = path.getSubPathStr();
if (p == ".x" || p == ".y" || p == ".z") {
// Convert double to quantity
return Base::Quantity(boost::any_cast<double>(Property::getPathValue(path)), unit);
}
}
return Property::getPathValue(path);
}
bool PropertyVector::getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const
{
Base::Unit unit = getUnit();
if(unit.isEmpty())
return false;
std::string p = path.getSubPathStr();
if (p == ".x") {
res = new QuantityPy(new Quantity(getValue().x,unit));
} else if(p == ".y") {
res = new QuantityPy(new Quantity(getValue().y,unit));
} else if(p == ".z") {
res = new QuantityPy(new Quantity(getValue().z,unit));
} else
return false;
return true;
}
//**************************************************************************
// PropertyVectorDistance
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -216,18 +251,6 @@ PropertyVectorDistance::PropertyVectorDistance()
}
const boost::any PropertyVectorDistance::getPathValue(const ObjectIdentifier &path) const
{
std::string p = path.getSubPathStr();
if (p == ".x" || p == ".y" || p == ".z") {
// Convert double to quantity
return Base::Quantity(boost::any_cast<double>(Property::getPathValue(path)), Unit::Length);
}
else
return Property::getPathValue(path);
}
PropertyVectorDistance::~PropertyVectorDistance()
{
@@ -253,18 +276,6 @@ PropertyPosition::~PropertyPosition()
}
const boost::any PropertyPosition::getPathValue(const ObjectIdentifier &path) const
{
std::string p = path.getSubPathStr();
if (p == ".x" || p == ".y" || p == ".z") {
// Convert double to quantity
return Base::Quantity(boost::any_cast<double>(Property::getPathValue(path)), Unit::Length);
}
else
return Property::getPathValue(path);
}
//**************************************************************************
// PropertyPosition
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -285,18 +296,6 @@ PropertyDirection::~PropertyDirection()
}
const boost::any PropertyDirection::getPathValue(const ObjectIdentifier &path) const
{
std::string p = path.getSubPathStr();
if (p == ".x" || p == ".y" || p == ".z") {
// Convert double to quantity
return Base::Quantity(boost::any_cast<double>(Property::getPathValue(path)), Unit::Length);
}
else
return Property::getPathValue(path);
}
//**************************************************************************
// PropertyVectorList
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -601,30 +600,30 @@ const Base::Placement & PropertyPlacement::getValue(void)const
void PropertyPlacement::getPaths(std::vector<ObjectIdentifier> &paths) const
{
paths.push_back(ObjectIdentifier(getContainer()) << ObjectIdentifier::Component::SimpleComponent(getName())
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("Base"))
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("x")));
paths.push_back(ObjectIdentifier(getContainer()) << ObjectIdentifier::Component::SimpleComponent(getName())
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("Base"))
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("y")));
paths.push_back(ObjectIdentifier(getContainer()) << ObjectIdentifier::Component::SimpleComponent(getName())
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("Base"))
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("z")));
paths.push_back(ObjectIdentifier(getContainer()) << ObjectIdentifier::Component::SimpleComponent(getName())
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("Rotation"))
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("Angle")));
paths.push_back(ObjectIdentifier(getContainer()) << ObjectIdentifier::Component::SimpleComponent(getName())
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("Rotation"))
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("Axis"))
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("x")));
paths.push_back(ObjectIdentifier(getContainer()) << ObjectIdentifier::Component::SimpleComponent(getName())
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("Rotation"))
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("Axis"))
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("y")));
paths.push_back(ObjectIdentifier(getContainer()) << ObjectIdentifier::Component::SimpleComponent(getName())
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("Rotation"))
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("Axis"))
<< ObjectIdentifier::Component::SimpleComponent(ObjectIdentifier::String("z")));
paths.push_back(ObjectIdentifier(*this)
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Base"))
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("x")));
paths.push_back(ObjectIdentifier(*this)
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Base"))
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("y")));
paths.push_back(ObjectIdentifier(*this)
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Base"))
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("z")));
paths.push_back(ObjectIdentifier(*this)
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Rotation"))
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Angle")));
paths.push_back(ObjectIdentifier(*this)
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Rotation"))
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Axis"))
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("x")));
paths.push_back(ObjectIdentifier(*this)
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Rotation"))
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Axis"))
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("y")));
paths.push_back(ObjectIdentifier(*this)
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Rotation"))
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Axis"))
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("z")));
}
void PropertyPlacement::setPathValue(const ObjectIdentifier &path, const boost::any &value)
@@ -669,6 +668,24 @@ const boost::any PropertyPlacement::getPathValue(const ObjectIdentifier &path) c
return Property::getPathValue(path);
}
bool PropertyPlacement::getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const
{
std::string p = path.getSubPathStr();
if (p == ".Rotation.Angle") {
Base::Vector3d axis; double angle;
_cPos.getRotation().getValue(axis,angle);
res = new QuantityPy(new Quantity(Base::toDegrees(angle),Unit::Angle));
} else if (p == ".Base.x") {
res = new QuantityPy(new Quantity(_cPos.getPosition().x,Unit::Length));
} else if (p == ".Base.y") {
res = new QuantityPy(new Quantity(_cPos.getPosition().y,Unit::Length));
} else if (p == ".Base.z") {
res = new QuantityPy(new Quantity(_cPos.getPosition().z,Unit::Length));
} else
return false;
return true;
}
PyObject *PropertyPlacement::getPyObject(void)
{
return new Base::PlacementPy(new Base::Placement(_cPos));