diff --git a/src/App/Application.cpp b/src/App/Application.cpp
index 2cdda7d8f5..fb2755571f 100644
--- a/src/App/Application.cpp
+++ b/src/App/Application.cpp
@@ -1810,6 +1810,7 @@ void Application::initTypes(void)
App ::PropertyPlacement ::init();
App ::PropertyPlacementList ::init();
App ::PropertyPlacementLink ::init();
+ App ::PropertyRotation ::init();
App ::PropertyGeometry ::init();
App ::PropertyComplexGeoData ::init();
App ::PropertyColor ::init();
diff --git a/src/App/PropertyGeo.cpp b/src/App/PropertyGeo.cpp
index 02909b32d5..062e78a7b9 100644
--- a/src/App/PropertyGeo.cpp
+++ b/src/App/PropertyGeo.cpp
@@ -40,6 +40,7 @@
#include
#include
#include
+#include
#include "Document.h"
#include "DocumentObject.h"
@@ -938,6 +939,183 @@ void PropertyPlacementLink::Paste(const Property &from)
hasSetValue();
}
+//**************************************************************************
+//**************************************************************************
+// PropertyRotation
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+TYPESYSTEM_SOURCE(App::PropertyRotation , App::Property)
+
+PropertyRotation::PropertyRotation()
+{
+
+}
+
+
+PropertyRotation::~PropertyRotation()
+{
+
+}
+
+void PropertyRotation::setValue(const Base::Rotation &rot)
+{
+ aboutToSetValue();
+ _rot = rot;
+ hasSetValue();
+}
+
+bool PropertyRotation::setValueIfChanged(const Base::Rotation &rot, double atol)
+{
+ if (_rot.isSame(rot, atol)) {
+ return false;
+ }
+
+ setValue(rot);
+ return true;
+}
+
+
+const Base::Rotation & PropertyRotation::getValue() const
+{
+ return _rot;
+}
+
+void PropertyRotation::getPaths(std::vector &paths) const
+{
+ paths.push_back(ObjectIdentifier(*this)
+ << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Angle")));
+ paths.push_back(ObjectIdentifier(*this)
+ << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Axis"))
+ << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("x")));
+ paths.push_back(ObjectIdentifier(*this)
+ << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Axis"))
+ << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("y")));
+ paths.push_back(ObjectIdentifier(*this)
+ << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Axis"))
+ << ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("z")));
+}
+
+void PropertyRotation::setPathValue(const ObjectIdentifier &path, const boost::any &value)
+{
+ if (path.getSubPathStr() == ".Angle") {
+ double avalue;
+
+ if (value.type() == typeid(Base::Quantity))
+ avalue = boost::any_cast(value).getValue();
+ else if (value.type() == typeid(double))
+ avalue = boost::any_cast(value);
+ else if (value.type() == typeid(int))
+ avalue = boost::any_cast(value);
+ else if (value.type() == typeid(unsigned int))
+ avalue = boost::any_cast(value);
+ else if (value.type() == typeid(short))
+ avalue = boost::any_cast(value);
+ else if (value.type() == typeid(unsigned short))
+ avalue = boost::any_cast(value);
+ else if (value.type() == typeid(long))
+ avalue = boost::any_cast(value);
+ else if (value.type() == typeid(unsigned long))
+ avalue = boost::any_cast(value);
+ else
+ throw std::bad_cast();
+
+ Property::setPathValue(path, Base::toRadians(avalue));
+ }
+ else {
+ Property::setPathValue(path, value);
+ }
+}
+
+const boost::any PropertyRotation::getPathValue(const ObjectIdentifier &path) const
+{
+ std::string p = path.getSubPathStr();
+
+ if (p == ".Angle") {
+ // Convert angle to degrees
+ return Base::Quantity(Base::toDegrees(boost::any_cast(Property::getPathValue(path))), Unit::Angle);
+ }
+ else {
+ return Property::getPathValue(path);
+ }
+}
+
+bool PropertyRotation::getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const
+{
+ std::string p = path.getSubPathStr();
+ if (p == ".Angle") {
+ Base::Vector3d axis; double angle;
+ _rot.getValue(axis,angle);
+ res = Py::asObject(new QuantityPy(new Quantity(Base::toDegrees(angle),Unit::Angle)));
+ return true;
+ }
+
+ return false;
+}
+
+PyObject *PropertyRotation::getPyObject()
+{
+ return new Base::RotationPy(new Base::Rotation(_rot));
+}
+
+void PropertyRotation::setPyObject(PyObject *value)
+{
+ if (PyObject_TypeCheck(value, &(Base::MatrixPy::Type))) {
+ Base::MatrixPy *object = static_cast(value);
+ Base::Matrix4D mat = object->value();
+ Base::Rotation p;
+ p.setValue(mat);
+ setValue(p);
+ }
+ else if (PyObject_TypeCheck(value, &(Base::RotationPy::Type))) {
+ setValue(*static_cast(value)->getRotationPtr());
+ }
+ else {
+ std::string error = std::string("type must be 'Matrix' or 'Rotation', not ");
+ error += value->ob_type->tp_name;
+ throw Base::TypeError(error);
+ }
+}
+
+void PropertyRotation::Save (Base::Writer &writer) const
+{
+ Vector3d axis;
+ double rfAngle;
+ _rot.getValue(axis, rfAngle);
+
+ writer.Stream() << writer.ind() << "\n";
+}
+
+void PropertyRotation::Restore(Base::XMLReader &reader)
+{
+ reader.readElement("PropertyRotation");
+ aboutToSetValue();
+
+ _rot = Rotation(Vector3d(reader.getAttributeAsFloat("Ox"),
+ reader.getAttributeAsFloat("Oy"),
+ reader.getAttributeAsFloat("Oz")),
+ reader.getAttributeAsFloat("A"));
+ hasSetValue();
+}
+
+Property *PropertyRotation::Copy() const
+{
+ PropertyRotation *p = new PropertyRotation();
+ p->_rot = _rot;
+ return p;
+}
+
+void PropertyRotation::Paste(const Property &from)
+{
+ aboutToSetValue();
+ _rot = dynamic_cast(from)._rot;
+ hasSetValue();
+}
+
// ------------------------------------------------------------
TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyGeometry , App::Property)
diff --git a/src/App/PropertyGeo.h b/src/App/PropertyGeo.h
index 99103b7b29..f22be71507 100644
--- a/src/App/PropertyGeo.h
+++ b/src/App/PropertyGeo.h
@@ -35,6 +35,7 @@
#include "Property.h"
#include "PropertyLinks.h"
#include "ComplexGeoData.h"
+#include
namespace Base {
class Writer;
@@ -281,8 +282,9 @@ private:
Base::Matrix4D _cMat;
};
-/** Vector properties
- * This is the father of all properties handling Integers.
+/// Property representing a placement
+/*!
+ * Encapsulates a Base::Placement in a Property
*/
class AppExport PropertyPlacement: public Property
{
@@ -408,6 +410,73 @@ protected:
};
+/// Property representing a rotation
+/*!
+ * Encapsulates a Base::Rotation in a Property
+ */
+class AppExport PropertyRotation : public Property
+{
+ TYPESYSTEM_HEADER_WITH_OVERRIDE();
+
+public:
+ /**
+ * A constructor.
+ * A more elaborate description of the constructor.
+ */
+ PropertyRotation();
+
+ /**
+ * A destructor.
+ * A more elaborate description of the destructor.
+ */
+ virtual ~PropertyRotation();
+
+ /** Sets the property
+ */
+ void setValue(const Base::Rotation &rot);
+
+ /** Sets property only if changed
+ * @param pos: input placement
+ * @param tol: position tolerance
+ * @param atol: angular tolerance
+ */
+ bool setValueIfChanged(const Base::Rotation &rot, double atol=1e-12);
+
+ /** This method returns a string representation of the property
+ */
+ const Base::Rotation &getValue() const;
+
+ /// Get valid paths for this property; used by auto completer
+ void getPaths(std::vector &paths) const override;
+
+ void setPathValue(const ObjectIdentifier &path, const boost::any &value) override;
+
+ virtual const boost::any getPathValue(const ObjectIdentifier &path) const override;
+
+ virtual bool getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const override;
+
+ const char* getEditorName() const override {
+ return "Gui::PropertyEditor::PropertyRotationItem";
+ }
+
+ virtual PyObject *getPyObject() override;
+ virtual void setPyObject(PyObject *) override;
+
+ virtual void Save (Base::Writer &writer) const override;
+ virtual void Restore(Base::XMLReader &reader) override;
+
+ virtual Property *Copy() const override;
+ virtual void Paste(const Property &from) override;
+
+ virtual unsigned int getMemSize () const override {
+ return sizeof(Base::Placement);
+ }
+
+private:
+ Base::Rotation _rot;
+};
+
+
/** The base class for all basic geometry properties.
* @author Werner Mayer
*/