// SPDX-License-Identifier: LGPL-2.1-or-later /**************************************************************************** * * * Copyright (c) 2023 Ondsel * * * * This file is part of FreeCAD. * * * * FreeCAD is free software: you can redistribute it and/or modify it * * under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 2.1 of the * * License, or (at your option) any later version. * * * * FreeCAD 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 * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with FreeCAD. If not, see * * . * * * ***************************************************************************/ #ifndef ASSEMBLY_AssemblyObject_H #define ASSEMBLY_AssemblyObject_H #include #include #include #include #include #include namespace MbD { class ASMTPart; class ASMTAssembly; class ASMTJoint; class ASMTMarker; class ASMTPart; } // namespace MbD namespace App { class PropertyXLinkSub; } // namespace App namespace Base { class Placement; class Rotation; } // namespace Base namespace Assembly { class JointGroup; class ViewGroup; struct ObjRef { App::DocumentObject* obj; App::PropertyXLinkSub* ref; }; // This enum has to be the same as the one in JointObject.py enum class JointType { Fixed, Revolute, Cylindrical, Slider, Ball, Distance, Parallel, Perpendicular, Angle, RackPinion, Screw, Gears, Belt, }; enum class DistanceType { PointPoint, LineLine, LineCircle, CircleCircle, PlanePlane, PlaneCylinder, PlaneSphere, PlaneCone, PlaneTorus, CylinderCylinder, CylinderSphere, CylinderCone, CylinderTorus, ConeCone, ConeTorus, ConeSphere, TorusTorus, TorusSphere, SphereSphere, PointPlane, PointCylinder, PointSphere, PointCone, PointTorus, LinePlane, LineCylinder, LineSphere, LineCone, LineTorus, CurvePlane, CurveCylinder, CurveSphere, CurveCone, CurveTorus, PointLine, PointCurve, Other, }; class AssemblyExport AssemblyObject: public App::Part { PROPERTY_HEADER_WITH_OVERRIDE(Assembly::AssemblyObject); public: AssemblyObject(); ~AssemblyObject() override; PyObject* getPyObject() override; /// returns the type name of the ViewProvider const char* getViewProviderName() const override { return "AssemblyGui::ViewProviderAssembly"; } App::DocumentObjectExecReturn* execute() override; /* Solve the assembly. It will update first the joints, solve, update placements of the parts and redraw the joints Args : enableRedo : This store initial positions to enable undo while being in an active transaction (joint creation).*/ int solve(bool enableRedo = false, bool updateJCS = true); void preDrag(std::vector dragParts); void doDragStep(); void postDrag(); void savePlacementsForUndo(); void undoSolve(); void clearUndo(); void exportAsASMT(std::string fileName); Base::Placement getMbdPlacement(std::shared_ptr mbdPart); bool validateNewPlacements(); void setNewPlacements(); void recomputeJointPlacements(std::vector joints); void redrawJointPlacements(std::vector joints); // Ondsel Solver interface std::shared_ptr makeMbdAssembly(); std::shared_ptr makeMbdPart(std::string& name, Base::Placement plc = Base::Placement(), double mass = 1.0); std::shared_ptr getMbDPart(App::DocumentObject* obj); std::shared_ptr makeMbdMarker(std::string& name, Base::Placement& plc); std::vector> makeMbdJoint(App::DocumentObject* joint); std::shared_ptr makeMbdJointOfType(App::DocumentObject* joint, JointType jointType); std::shared_ptr makeMbdJointDistance(App::DocumentObject* joint); std::string handleOneSideOfJoint(App::DocumentObject* joint, const char* propRefName, const char* propPlcName); void getRackPinionMarkers(App::DocumentObject* joint, std::string& markerNameI, std::string& markerNameJ); int slidingPartIndex(App::DocumentObject* joint); void jointParts(std::vector joints); JointGroup* getJointGroup(); ViewGroup* getExplodedViewGroup(); std::vector getJoints(bool updateJCS = true, bool delBadJoints = false); std::vector getGroundedJoints(); std::vector getJointsOfObj(App::DocumentObject* obj); std::vector getJointsOfPart(App::DocumentObject* part); App::DocumentObject* getJointOfPartConnectingToGround(App::DocumentObject* part, std::string& name); std::vector getGroundedParts(); std::vector fixGroundedParts(); void fixGroundedPart(App::DocumentObject* obj, Base::Placement& plc, std::string& jointName); bool isJointConnectingPartToGround(App::DocumentObject* joint, const char* partPropName); bool isJointTypeConnecting(App::DocumentObject* joint); bool isObjInSetOfObjRefs(App::DocumentObject* obj, const std::vector& pairs); void removeUnconnectedJoints(std::vector& joints, std::vector groundedObjs); void traverseAndMarkConnectedParts(App::DocumentObject* currentPart, std::vector& connectedParts, const std::vector& joints); std::vector getConnectedParts(App::DocumentObject* part, const std::vector& joints); bool isPartGrounded(App::DocumentObject* part); bool isPartConnected(App::DocumentObject* part); std::vector getDownstreamParts(App::DocumentObject* part, App::DocumentObject* joint); std::vector getUpstreamParts(App::DocumentObject* part, int limit = 0); App::DocumentObject* getUpstreamMovingPart(App::DocumentObject* part, App::DocumentObject*& joint, std::string& name); double getObjMass(App::DocumentObject* obj); void setObjMasses(std::vector> objectMasses); std::vector getSubAssemblies(); void updateGroundedJointsPlacements(); private: std::shared_ptr mbdAssembly; std::unordered_map> objectPartMap; std::vector> objMasses; std::vector> dragMbdParts; std::vector> previousPositions; // void handleChangedPropertyType(Base::XMLReader &reader, const char *TypeName, App::Property // *prop) override; public: // ---------------- Utils ------------------- // Can't put the functions by themselves in AssemblyUtils.cpp : // see https://forum.freecad.org/viewtopic.php?p=729577#p729577 static void swapJCS(App::DocumentObject* joint); static bool isEdgeType(App::DocumentObject* obj, std::string& elName, GeomAbs_CurveType type); static bool isFaceType(App::DocumentObject* obj, std::string& elName, GeomAbs_SurfaceType type); static double getFaceRadius(App::DocumentObject* obj, std::string& elName); static double getEdgeRadius(App::DocumentObject* obj, std::string& elName); static DistanceType getDistanceType(App::DocumentObject* joint); // getters to get from properties static void setJointActivated(App::DocumentObject* joint, bool val); static bool getJointActivated(App::DocumentObject* joint); static double getJointDistance(App::DocumentObject* joint); static double getJointDistance2(App::DocumentObject* joint); static JointType getJointType(App::DocumentObject* joint); static std::string getElementFromProp(App::DocumentObject* obj, const char* propName); static std::string getElementTypeFromProp(App::DocumentObject* obj, const char* propName); static App::DocumentObject* getObjFromProp(App::DocumentObject* joint, const char* propName); static App::DocumentObject* getObjFromRef(App::PropertyXLinkSub* prop); static App::DocumentObject* getObjFromRef(App::DocumentObject* joint, const char* propName); App::DocumentObject* getMovingPartFromRef(App::DocumentObject* obj, std::string& sub); App::DocumentObject* getMovingPartFromRef(App::PropertyXLinkSub* prop); App::DocumentObject* getMovingPartFromRef(App::DocumentObject* joint, const char* propName); static App::DocumentObject* getLinkedObjFromRef(App::DocumentObject* joint, const char* propName); static std::vector getSubAsList(App::PropertyXLinkSub* prop); static std::vector getSubAsList(App::DocumentObject* joint, const char* propName); static std::vector splitSubName(const std::string& subName); static Base::Placement getPlacementFromProp(App::DocumentObject* obj, const char* propName); static Base::Placement getGlobalPlacement(App::DocumentObject* targetObj, App::DocumentObject* rootObj, const std::string& sub); static Base::Placement getGlobalPlacement(App::DocumentObject* targetObj, App::PropertyXLinkSub* prop); }; // using AssemblyObjectPython = App::FeaturePythonT; } // namespace Assembly #endif // ASSEMBLY_AssemblyObject_H