From 16ae568549d7c06215fe0e9dba2ddeea960cee11 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 29 Oct 2021 12:40:32 +0200 Subject: [PATCH] App: add class PropertyRotation --- src/App/Application.cpp | 1 + src/App/PropertyGeo.cpp | 178 ++++++++++++++++++++++++++++++++++++++++ src/App/PropertyGeo.h | 73 +++++++++++++++- 3 files changed, 250 insertions(+), 2 deletions(-) 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 */