| /*************************************************************************** | |
| * Copyright (c) 2013 Jan Rheinländer * | |
| * <jrheinlaender@users.sourceforge.net> * | |
| * * | |
| * This file is part of the FreeCAD CAx development system. * | |
| * * | |
| * This library is free software; you can redistribute it and/or * | |
| * modify it under the terms of the GNU Library General Public * | |
| * License as published by the Free Software Foundation; either * | |
| * version 2 of the License, or (at your option) any later version. * | |
| * * | |
| * This library is distributed in the hope that it will be useful, * | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
| * GNU Library General Public License for more details. * | |
| * * | |
| * You should have received a copy of the GNU Library General Public * | |
| * License along with this library; see the file COPYING.LIB. If not, * | |
| * write to the Free Software Foundation, Inc., 59 Temple Place, * | |
| * Suite 330, Boston, MA 02111-1307, USA * | |
| * * | |
| ***************************************************************************/ | |
| namespace Fem | |
| { | |
| /** | |
| * @brief Base class of all Constraint Objects of the Fem module. | |
| * | |
| * @details | |
| * @ref Constraint isn't intended to be used directly. Actual Constraints | |
| * used to specify a simulation are children of this class. The base class | |
| * essentially does two things: Most importantely it has a property @ref | |
| * Constraint::References which is a list of all sub objects the constraint | |
| * applies to. Defining it in the base class exposes a common interface to code | |
| * using different constraints. | |
| * | |
| * The second purpose of @ref Constraint is to support the redering to the | |
| * screen done by the View Provider @ref FemGui::ViewProviderFemConstraint. | |
| * The rendering is decoupled from the objects listed in the @ref References | |
| * property by using a point cloud a normal vector and a scale factor which is | |
| * generated by this class. The View Provider doesn't know of the references | |
| * it just asks @ref Constraint for those values and renders a widget for each | |
| * point scaled by the scale factor pointing in the direction of the normal | |
| * vector. These values are exposed by the two properties @ref NormalDirection | |
| * and @ref Scale and the protected method @ref getPoints(points&, normals&, | |
| * scale&). | |
| */ | |
| class FemExport Constraint: public App::DocumentObject, public App::SuppressibleExtension | |
| { | |
| PROPERTY_HEADER_WITH_OVERRIDE(Fem::Constraint); | |
| public: | |
| Constraint(); | |
| ~Constraint() override; | |
| /** | |
| * @brief List of objects the constraints applies to. | |
| * | |
| * @details | |
| * This is a list of subobjects (e.g. Faces, Edges, ...) the constraint | |
| * applies to. It's only supposed to contain objects of or derived from | |
| * Part::Feature. Altering this property triggers a update of @ref | |
| * NormalDirection and @ref Scale. | |
| * | |
| * @note | |
| * Undefined behaviour if a unsupported (not derived from Part::Feature) | |
| * Document Object is added to the @References. | |
| */ | |
| App::PropertyLinkSubList References; | |
| /** | |
| * @brief Vector pointing into the effective direction of the constraint. | |
| * | |
| * @details | |
| * If @ref References contains only one face of a shape than @ref | |
| * NormalDirection is the normal vector of that face. If more than one | |
| * face is referenced that it is the normal vector of the first face. If | |
| * @ref References is empty or doesn't contain a face the value of @ref | |
| * NormalDirection is the Z-axis or its previous value. | |
| */ | |
| App::PropertyVector NormalDirection; | |
| /** | |
| * @brief Supposed to reflect the size of the @ref References. | |
| * | |
| * @details | |
| * This property should be a scale factor for the widgets rendered by the | |
| * View Provider but it's always 1. It isn't updated when @ref References | |
| * changes. | |
| */ | |
| App::PropertyFloatConstraint Scale; | |
| // Read-only (calculated values). These trigger changes in the ViewProvider | |
| App::PropertyVectorList Points; | |
| App::PropertyVectorList Normals; | |
| /** | |
| * @brief Updates @ref NormalDirection. | |
| * | |
| * @details | |
| * Updates @ref NormalDirection using new @ref References. It does so by | |
| * calling @ref onChanged once with the @ref References property and once | |
| * with the @ref Scale property. The second call doesn't do anything. | |
| * | |
| * @note | |
| * Calling @ref onChanged does touch the Document Object but that flag is | |
| * cleared right after the @ref execute call by the recompute mechanism. | |
| * See Document::recompute() and DocumentObject::purgeTouched(). | |
| */ | |
| App::DocumentObjectExecReturn* execute() override; | |
| /** | |
| * @brief Calculates scale factor based on characteristic length of shape. | |
| * | |
| * @details | |
| * Used to calculate the scale factor returned by @ref getPoints when the | |
| */ | |
| double calcSizeFactor(double characLen) const; | |
| const char* getViewProviderName() const override | |
| { | |
| return "FemGui::ViewProviderFemConstraint"; | |
| } | |
| /** | |
| * @brief Returns Scale * sizeFactor. | |
| */ | |
| float getScaleFactor() const; | |
| protected: | |
| /** | |
| * @brief Updates NormalDirection if References change. | |
| */ | |
| void onChanged(const App::Property* prop) override; | |
| /** | |
| * @brief Triggers @ref onChanged to update View Provider. | |
| * | |
| * @note | |
| * This should not be necessary and is properly a bug in the View Provider | |
| * of FemConstraint. | |
| */ | |
| void onDocumentRestored() override; | |
| void onSettingDocument() override; | |
| void unsetupObject() override; | |
| void handleChangedPropertyType( | |
| Base::XMLReader& reader, | |
| const char* TypeName, | |
| App::Property* prop | |
| ) override; | |
| /** | |
| * @brief Returns data based on References relevant for rendering widgets. | |
| * | |
| * @details | |
| * Extracts data from all objects inside References relevant for widget | |
| * rendering by the View Provider. This includes the points at which | |
| * widgets shall be drawn, a vector per point indicating the direction the | |
| * widget should face and a global scale factor for all widgets. Two | |
| * vectors of equal length are used to return the points and their normal | |
| * vectors. The normal vector of points[i] can be found with the same | |
| * index in normals[i]. | |
| * | |
| * @param[out] points | |
| * For each vertex a point equal to the location of that vertex is pushed | |
| * into the points vector. For each edge at least to points, the beginning | |
| * and the end of the edge, are pushed into the vector. Depending on the | |
| * length of the edge more points may be added in between. For each face a | |
| * number of points depending on the size of the face and the step size | |
| * calculated internally are pushed into the vector. | |
| * @param[out] normals | |
| * For vertexes and edges normal vectors equal to the NormalDirection are | |
| * pushed onto the vector. For each point of a face a Base::Vector3d equal | |
| * to the normal vector of the face at that position is added to the | |
| * vector. | |
| * @param[out] scale | |
| * The scale contains a scale value for the object in References that was | |
| * processed last. For calculation various versions of @ref | |
| * calcDrawScaleFactor are used. | |
| * | |
| * @return | |
| * If the calculation of points, normals and scale was successful it | |
| * returns true. If an error occurred and the data couldn't be extracted | |
| * properly false is returned. | |
| */ | |
| bool getPoints( | |
| std::vector<Base::Vector3d>& points, | |
| std::vector<Base::Vector3d>& normals, | |
| double* scale | |
| ) const; | |
| /** | |
| * @brief Calculate point of cylindrical face where to render widget. | |
| * | |
| * @note | |
| * This method is very specific and doesn't require access to member | |
| * variables. It should be rewritten at a different place. | |
| */ | |
| Base::Vector3d getBasePoint( | |
| const Base::Vector3d& base, | |
| const Base::Vector3d& axis, | |
| const App::PropertyLinkSub& location, | |
| const double& dist | |
| ); | |
| /** | |
| * @brief Get normal vector of point calculated by @ref getBasePoint. | |
| * | |
| * @note | |
| * This method is very specific and doesn't require access to member | |
| * variables. It should be rewritten at a different place. | |
| */ | |
| const Base::Vector3d getDirection(const App::PropertyLinkSub& direction); | |
| private: | |
| /** | |
| * @brief Symbol size factor determined from the size of the shape. | |
| */ | |
| double sizeFactor; | |
| void slotChangedObject(const App::DocumentObject& Obj, const App::Property& Prop); | |
| fastsignals::connection connDocChangedObject; | |
| }; | |
| using ConstraintPython = App::FeaturePythonT<Constraint>; | |
| } // namespace Fem | |