File indexing completed on 2024-03-03 03:59:22

0001 /*
0002     SPDX-FileCopyrightText: 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 /** \file world.h
0008  *  \brief Item, Body, Force and Tool interfaces, World class
0009  */
0010 
0011 #ifndef STEPCORE_WORLD_H
0012 #define STEPCORE_WORLD_H
0013 
0014 
0015 // stdc++
0016 #include <vector> // XXX: replace if QT is enabled
0017 
0018 // Qt
0019 #include <QHash>
0020 
0021 // Stepcore
0022 #include "types.h"
0023 #include "util.h"
0024 #include "vector.h"
0025 #include "object.h"
0026 #include "item.h"
0027 #include "body.h"
0028 #include "force.h"
0029 #include "joint.h"
0030 #include "itemgroup.h"
0031 
0032 
0033 // TODO: split this file
0034 
0035 namespace StepCore
0036 {
0037 
0038 class World;
0039 class Solver;
0040 class Item;
0041 class CollisionSolver;
0042 class ConstraintSolver;
0043 
0044 
0045 /** \ingroup tools
0046  *  \brief Interface for tools
0047  *
0048  *  Tools are not physical objects in simulation but utilities to control
0049  *  simulation or obtain some information
0050  */
0051 class Tool
0052 {
0053     STEPCORE_OBJECT(Tool)
0054 public:
0055     virtual ~Tool() {}
0056 };
0057 
0058 /** \ingroup world
0059  *  \brief Contains multiple Item, Solver and general properties such as time
0060  *  \todo Redesign to avoid variable copying (scatter/gatherVariables)
0061  */
0062 class World : public ItemGroup
0063 {
0064     /*Q_OBJECT*/
0065     STEPCORE_OBJECT(World)
0066 
0067 public:
0068     /** Constructs empty World */
0069     World();
0070     /** Constructs a copy of world (deep copy) */
0071     World(const World& world);
0072     /** Destroys World and all objects which belongs to it */
0073     ~World();
0074 
0075     /** Assignment operator (deep copy) */
0076     World& operator=(const World& world);
0077 
0078 
0079     /** Clear world (removes all items, solver and resets time) */
0080     void clear();
0081 
0082     /** Get current time */
0083     double time() const { return _time; }
0084     /** Set current time */
0085     void setTime(double t) { _time = t; }
0086 
0087     /** Get simulation speed scale */
0088     double timeScale() const { return _timeScale; }
0089     /** Set simulation speed scale */
0090     void setTimeScale(double timeScale) { _timeScale = timeScale; }
0091 
0092     /** Is errors calculation enabled */
0093     bool errorsCalculation() const { return _errorsCalculation; }
0094     /** Enable or disable errors calculation */
0095     void setErrorsCalculation(bool errorsCalculation) {
0096         _errorsCalculation = errorsCalculation; }
0097 
0098     /** Add new item to the world */
0099     //void addItem(Item* item);
0100     /** Remove item from the world (you should delete item yourself) */
0101     //void removeItem(Item* item);
0102     /** Delete item from the world (it actually deletes item) */
0103     //void deleteItem(Item* item) { removeItem(item); delete item; }
0104     /** Finds item in items() */
0105     //int  itemIndex(const Item* item) const;
0106 
0107     /** Get item by its index */
0108     //Item* item(int index) const { return _items[index]; }
0109     /** Get item by its name */
0110     //Item* item(const QString& name) const;
0111     /** Get object (item, solver, *Solver or world itself) by its name */
0112     Object* object(const QString& name);
0113 
0114     /** Get list of all items (not including sub-items) in the World */
0115     //const ItemList&  items() const  { return _items; }
0116     /** Get list of all bodies (including sub-items) in the World */
0117     const BodyList&  bodies() const { return _bodies; }
0118     /** Get list of all forces (including sub-items) in the World */
0119     const ForceList& forces() const { return _forces; }
0120     /** Get list of all joints (including sub-items) in the World */
0121     const JointList& joints() const { return _joints; }
0122 
0123     /** Get current Solver */
0124     Solver* solver() const { return _solver; }
0125     /** Set new Solver (and delete the old one) */
0126     void setSolver(Solver* solver);
0127     /** Get current Solver and remove it from world */
0128     Solver* removeSolver();
0129 
0130     /** Get current CollisionSolver */
0131     CollisionSolver* collisionSolver() const { return _collisionSolver; }
0132     /** Set new CollisionSolver (and delete the old one) */
0133     void setCollisionSolver(CollisionSolver* collisionSolver);
0134     /** Get current CollisionSolver and remove it from world */
0135     CollisionSolver* removeCollisionSolver();
0136 
0137     /** Get current ConstraintSolver */
0138     ConstraintSolver* constraintSolver() const { return _constraintSolver; }
0139     /** Set new ConstraintSolver (and delete the old one) */
0140     void setConstraintSolver(ConstraintSolver* constraintSolver);
0141     /** Get current ConstraintSolver and remove it from world */
0142     ConstraintSolver* removeConstraintSolver();
0143 
0144     /** Calculate all forces */
0145     int doCalcFn();
0146     /** Integrate.
0147      *  \param delta Integration interval
0148      *  \return the same as Solver::doEvolve
0149      *  \todo Provide error message
0150      */
0151     int doEvolve(double delta);
0152     
0153     /** Get evolveAbort flag (can be called from separate thread) */
0154     bool evolveAbort() { return _evolveAbort; }
0155     /** Set evolveAbort flag (can be called from separate thread). When the flag is set
0156      *  current (or any subsequent) doEvolve operation will be aborted as soon as possible. */
0157     void setEvolveAbort(bool evolveAbort = true) { _evolveAbort = evolveAbort; }
0158 
0159 private:
0160     friend class ItemGroup;
0161 
0162     /** \internal Creates a map between pointers to items in two groups
0163      *  (groups should contain identical items). */
0164     void fillCopyMap(QHash<const Object*, Object*>* map,
0165                         const ItemGroup* g1, ItemGroup* g2);
0166     /** \internal Maps all links to other objects in obj using the map */
0167     void applyCopyMap(QHash<const Object*, Object*>* map, Object* obj);
0168     /** \internal Recursively add item and all its children into
0169      *  bodies, forces and joints arrays. Calls applyCopyMap for them.
0170      *  Called by World::operator=() */
0171     void worldItemCopied(QHash<const Object*, Object*>* map, Item* item);
0172     /** \internal Recursively add item and all its children into
0173      *  bodies, forces and joints arrays. Called by ItemGroup::addItem() */
0174     void worldItemAdded(Item* item);
0175     /** \internal Recursively remove item and all its children from
0176      *  bodies, forces and joints arrays. Called by ItemGroup::removeItem()
0177      *  and ItemGroup::clear() */
0178     void worldItemRemoved(Item* item) override;
0179 
0180     /** \internal This function iterates over all bodies, assigns indexes
0181      *  for them in the global array (_variables), calculates total
0182      *  variables count and reallocates (if necessary) _variables and
0183      *  _variances arrays. It does the same for joints. */
0184     void checkVariablesCount();
0185 
0186     /** \internal Gathers acceleration (and possibly their variances)
0187      *  from all bodies into one array */
0188     void gatherAccelerations(double* acceleration, double* variance);
0189 
0190     /** \internal Gathers variables (and possibly their variances)
0191      *  from all bodies into one array */
0192     void gatherVariables(double* variables, double* variances);
0193 
0194     /** \internal Scatters variable (and possibly their variances)
0195      *  from one array to all bodies */
0196     void scatterVariables(const double* variables, const double* variances);
0197 
0198     /** \internal Gather information from all joints */
0199     void gatherJointsInfo(ConstraintsInfo* info);
0200 
0201     /** \internal Static wrapper for World::solverFunction */ 
0202     static int solverFunction(double t, const double* y, const double* yvar,
0203                                  double* f, double* fvar, void* params);
0204     /** \internal Called by solver to calculate variable derivatives.
0205      * This function:
0206      *      1. Checks collisions between bodies and resolves them if it is possible
0207      *      2. Iterates over all forces to calculate total force for each body
0208      *      3. Iterates over all joints and calls constraintSolver to solve them
0209      */
0210     int solverFunction(double t, const double* y, const double* yvar,
0211                                  double* f, double* fvar);
0212 
0213 private:
0214     double    _time;
0215     double    _timeScale;
0216     bool      _errorsCalculation;
0217 
0218     //ItemList  _items;
0219     BodyList  _bodies;
0220     ForceList _forces;
0221     JointList _joints;
0222 
0223     Solver*           _solver;
0224     CollisionSolver*  _collisionSolver;
0225     ConstraintSolver* _constraintSolver;
0226 
0227     int             _variablesCount;  ///< \internal Count of positions (not including velocities)
0228     VectorXd    _variables;       ///< \internal Positions and velocities (size == _variablesCount*2)
0229     VectorXd    _variances;       ///< \internal Variances of positions and velocities
0230     VectorXd    _tempArray;       ///< \internal Temporary array used in various places
0231     ConstraintsInfo _constraintsInfo; ///< \internal Constraints information
0232 
0233     bool    _stopOnCollision;
0234     bool    _stopOnIntersection;
0235     bool    _evolveAbort;
0236 };
0237 
0238 } // namespace StepCore
0239 
0240 /** \defgroup world World */
0241 /** \defgroup vector Fixed-size vector */
0242 /** \defgroup constants Physical constants */
0243 /** \defgroup bodies Physical bodies */
0244 /** \defgroup forces Physical forces */
0245 /** \defgroup joints Rigid joints */
0246 /** \defgroup tools Various tools */
0247 /** \defgroup solvers ODE Solvers */
0248 /** \defgroup contacts Collision and constraint solvers */
0249 /** \defgroup reflections Reflections */
0250 /** \defgroup xmlfile XML file IO */
0251 /** \defgroup errors ObjectErrors classes */
0252 
0253 #endif
0254