45 QT_TR_NOOP("Enable global error calculation"), errorsCalculation, setErrorsCalculation))
47 Item& Item::operator=(const Item& item)
49 Object::operator=(item);
54 if(item._objectErrors) {
55 _objectErrors =
static_cast<ObjectErrors*
>(
56 item._objectErrors->metaObject()->cloneObject(*item._objectErrors) );
57 _objectErrors->setOwner(
this);
81 ItemList::const_iterator end = _items.end();
82 for(ItemList::const_iterator it = _items.begin(); it != end; ++it)
83 (*it)->setWorld(world);
89 ItemList::const_iterator end = _items.end();
90 for(ItemList::const_iterator it = _items.begin(); it != end; ++it)
91 (*it)->worldItemRemoved(item);
96 _items.push_back(item);
111 ItemList::iterator i = std::find(_items.begin(), _items.end(),
item);
118 ItemList::const_iterator end = _items.end();
119 for(ItemList::const_iterator it = _items.begin(); it != end; ++it) {
120 (*it)->setWorld(NULL);
121 (*it)->setGroup(NULL);
125 for(ItemList::const_iterator it = _items.begin(); it != end; ++it) {
152 if(
this == &group)
return *
this;
156 _items.reserve(group._items.size());
158 const ItemList::const_iterator gr_end = group._items.end();
159 for(ItemList::const_iterator it = group._items.begin(); it != gr_end; ++it) {
161 _items.push_back(item);
164 const ItemList::const_iterator end = _items.end();
165 for(ItemList::const_iterator it = _items.begin(); it != end; ++it) {
166 (*it)->setGroup(
this);
178 ItemList::const_iterator o = std::find(_items.begin(), _items.end(),
item);
180 return std::distance(_items.begin(), o);
185 ItemList::const_iterator end = _items.end();
186 for(ItemList::const_iterator it = _items.begin(); it != end; ++it)
187 if((*it)->name() ==
name)
return *it;
193 if(name.
isEmpty())
return NULL;
194 ItemList::const_iterator end = _items.end();
195 for(ItemList::const_iterator it = _items.begin(); it != end; ++it) {
196 if((*it)->name() ==
name)
return *it;
197 if((*it)->metaObject()->inherits<
ItemGroup>()) {
207 items->reserve(_items.size());
208 ItemList::const_iterator end = _items.end();
209 for(ItemList::const_iterator it = _items.begin(); it != end; ++it) {
210 items->push_back(*it);
211 if((*it)->metaObject()->inherits<
ItemGroup>())
221 int totalConstraintsCount = newConstraintsCount+newContactsCount;
223 jacobian.resize(totalConstraintsCount, newVariablesCount);
226 force.resize(newVariablesCount);
227 value.resize(totalConstraintsCount);
229 if (totalConstraintsCount>0)
234 forceMin.resize(totalConstraintsCount);
235 forceMax.resize(totalConstraintsCount);
260 : _time(0), _timeScale(1), _errorsCalculation(false),
261 _solver(NULL), _collisionSolver(NULL), _constraintSolver(NULL),
270 :
ItemGroup(), _time(0), _timeScale(1), _errorsCalculation(false),
271 _solver(NULL), _collisionSolver(NULL), _constraintSolver(NULL),
285 if(_collisionSolver) _collisionSolver->
resetCaches();
296 delete _solver; _solver = NULL;
297 delete _collisionSolver; _collisionSolver = NULL;
298 delete _constraintSolver; _constraintSolver = NULL;
301 _variables.resize(0);
302 _variances.resize(0);
303 _tempArray.resize(0);
312 _errorsCalculation =
false;
314 _stopOnCollision =
false;
315 _stopOnIntersection =
false;
316 _evolveAbort =
false;
318 #ifdef STEPCORE_WITH_QT
325 if(
this == &world)
return *
this;
332 world._solver->metaObject()->cloneObject(*(world._solver))));
335 if(world._collisionSolver) {
337 world._collisionSolver->metaObject()->cloneObject(*(world._collisionSolver))));
341 world._constraintSolver->metaObject()->cloneObject(*(world._constraintSolver))));
345 _timeScale = world._timeScale;
346 _errorsCalculation = world._errorsCalculation;
348 _stopOnCollision = world._stopOnCollision;
349 _stopOnIntersection = world._stopOnIntersection;
350 _evolveAbort = world._evolveAbort;
354 copyMap.
insert(NULL, NULL);
355 copyMap.
insert(&world,
this);
356 if(_solver) copyMap.
insert(world._solver, _solver);
357 if(_collisionSolver) copyMap.
insert(world._collisionSolver, _collisionSolver);
358 if(_constraintSolver) copyMap.
insert(world._constraintSolver, _constraintSolver);
359 fillCopyMap(©Map, &world,
this);
361 applyCopyMap(©Map,
this);
362 if(_solver) applyCopyMap(©Map, _solver);
363 if(_collisionSolver) applyCopyMap(©Map, _collisionSolver);
364 if(_constraintSolver) applyCopyMap(©Map, _constraintSolver);
366 const ItemList::const_iterator end =
items().end();
367 for(ItemList::const_iterator it =
items().begin(); it != end; ++it) {
368 worldItemCopied(©Map, *it);
373 checkVariablesCount();
381 const ItemList::const_iterator end = g1->
items().end();
382 for(ItemList::const_iterator it1 = g1->
items().begin(),
383 it2 = g2->
items().begin();
384 it1 != end; ++it1, ++it2) {
387 fillCopyMap(map, static_cast<ItemGroup*>(*it1), static_cast<ItemGroup*>(*it2));
396 if(pr->
userTypeId() == qMetaTypeId<Object*>()) {
406 applyCopyMap(map, item);
408 if(item->metaObject()->inherits<Force>())
409 _forces.push_back(dynamic_cast<Force*>(item));
410 if(item->metaObject()->inherits<Joint>())
411 _joints.push_back(dynamic_cast<Joint*>(item));
412 if(item->metaObject()->inherits<Body>())
413 _bodies.push_back(dynamic_cast<Body*>(item));
415 if(item->metaObject()->inherits<
ItemGroup>()) {
417 ItemList::const_iterator end = group->items().end();
418 for(ItemList::const_iterator it = group->items().begin(); it != end; ++it) {
419 worldItemCopied(map, *it);
424 void World::worldItemAdded(Item* item)
426 if(item->metaObject()->inherits<Force>())
427 _forces.push_back(dynamic_cast<Force*>(item));
429 if(item->metaObject()->inherits<Joint>())
430 _joints.push_back(dynamic_cast<Joint*>(item));
432 if(item->metaObject()->inherits<Body>()) {
433 Body* body =
dynamic_cast<Body*
>(
item);
434 _bodies.push_back(body);
435 if(_collisionSolver) _collisionSolver->
bodyAdded(_bodies, body);
438 if(item->metaObject()->inherits<
ItemGroup>()) {
440 ItemList::const_iterator end = group->items().end();
441 for(ItemList::const_iterator it = group->items().begin(); it != end; ++it) {
446 checkVariablesCount();
449 void World::worldItemRemoved(Item* item)
451 if(item->metaObject()->inherits<
ItemGroup>()) {
453 ItemList::const_iterator end = group->items().end();
454 for(ItemList::const_iterator it = group->items().begin(); it != end; ++it) {
455 worldItemRemoved(*it);
459 const ItemList::const_iterator end =
items().end();
460 for(ItemList::const_iterator it =
items().begin(); it != end; ++it) {
461 (*it)->worldItemRemoved(item);
464 if(item->metaObject()->inherits<Body>()) {
465 Body* body =
dynamic_cast<Body*
>(
item);
466 if(_collisionSolver) _collisionSolver->
bodyRemoved(_bodies, body);
467 BodyList::iterator b = std::find(_bodies.begin(), _bodies.end(), body);
472 if(item->metaObject()->inherits<Joint>()) {
473 JointList::iterator j = std::find(_joints.begin(), _joints.end(),
474 dynamic_cast<Joint*
>(
item));
479 if(item->metaObject()->inherits<Force>()) {
480 ForceList::iterator f = std::find(_forces.begin(), _forces.end(),
481 dynamic_cast<Force*
>(
item));
487 checkVariablesCount();
551 if(name.
isEmpty())
return NULL;
552 if(this->
name() ==
name)
return this;
553 else if(_solver && _solver->
name() ==
name)
return _solver;
554 else if(_collisionSolver && _collisionSolver->
name() ==
name)
return _collisionSolver;
555 else if(_constraintSolver && _constraintSolver->
name() ==
name)
return _constraintSolver;
556 else return item(name);
579 delete _collisionSolver;
586 _collisionSolver = NULL;
592 delete _constraintSolver;
599 _constraintSolver = NULL;
603 void World::checkVariablesCount()
605 int variablesCount = 0;
606 for(BodyList::iterator b = _bodies.begin(); b != _bodies.end(); ++b) {
607 (*b)->setVariablesOffset(variablesCount);
608 variablesCount += (*b)->variablesCount();
611 int constraintsCount = 0;
612 for(JointList::iterator j = _joints.begin(); j != _joints.end(); ++j) {
613 constraintsCount += (*j)->constraintsCount();
616 _constraintsInfo.
setDimension(variablesCount, constraintsCount, 0);
618 if(variablesCount != _variablesCount) {
619 _variablesCount = variablesCount;
620 _variables.resize(_variablesCount*2);
621 _variances.resize(_variablesCount*2);
622 _tempArray.resize(_variablesCount*2);
627 void World::gatherAccelerations(
double* acceleration,
double* accelerationVariance)
629 if(accelerationVariance)
630 memset(accelerationVariance, 0, _variablesCount*
sizeof(*accelerationVariance));
633 const BodyList::const_iterator it_end = _bodies.end();
634 for(BodyList::iterator b = _bodies.begin(); b != it_end; ++b) {
635 (*b)->getAccelerations(acceleration + index, accelerationVariance ? accelerationVariance + index : NULL);
636 index += (*b)->variablesCount();
640 void World::gatherVariables(
double* variables,
double* variances)
642 if(variances) memset(variances, 0, _variablesCount*2*
sizeof(*variances));
645 const BodyList::const_iterator it_end = _bodies.end();
646 for(BodyList::iterator b = _bodies.begin(); b != it_end; ++b) {
647 (*b)->getVariables(variables + index, variables + _variablesCount + index,
648 variances ? variances + index : NULL,
649 variances ? variances + _variablesCount + index : NULL);
650 index += (*b)->variablesCount();
654 void World::scatterVariables(
const double* variables,
const double* variances)
657 const BodyList::const_iterator it_end = _bodies.end();
658 for(BodyList::iterator b = _bodies.begin(); b != it_end; ++b) {
659 (*b)->setVariables(variables + index, variables + _variablesCount + index,
660 variances ? variances + index : NULL,
661 variances ? variances + _variablesCount + index : NULL);
662 index += (*b)->variablesCount();
666 void World::gatherJointsInfo(ConstraintsInfo* info)
671 const BodyList::const_iterator b_end = _bodies.end();
672 for(BodyList::iterator body = _bodies.begin(); body != b_end; ++body) {
673 (*body)->getInverseMass(&(info->inverseMass), NULL, offset);
674 offset += (*body)->variablesCount();
678 const JointList::const_iterator j_end = _joints.end();
679 for(JointList::iterator joint = _joints.begin(); joint != j_end; ++joint) {
680 (*joint)->getConstraintsInfo(info, offset);
681 offset += (*joint)->constraintsCount();
691 _stopOnCollision =
false;
692 _stopOnIntersection =
false;
693 checkVariablesCount();
694 gatherVariables(_variables.data(), _errorsCalculation ? _variances.data() : NULL);
695 return _solver->
doCalcFn(&_time, &_variables, _errorsCalculation ? &_variances : NULL,
696 NULL, _errorsCalculation ? &_variances : NULL);
703 checkVariablesCount();
704 gatherVariables(_variables.data(), _errorsCalculation ? _variances.data() : NULL);
707 double targetTime = _time + delta*_timeScale;
709 if(_collisionSolver) {
715 while(_time < targetTime) {
717 if( !( targetTime - _time > _solver->
stepSize() / 1000 ) ) {
718 qDebug(
"* %e %e %e", targetTime, _time, _solver->
stepSize());
722 _stopOnCollision =
true;
723 _stopOnIntersection =
true;
725 ret = _solver->
doEvolve(&time, targetTime, &_variables,
726 _errorsCalculation ? &_variances : NULL);
742 double stepSize = fmin(_solver->
stepSize() / 2, targetTime - _time);
743 double collisionEndTime = targetTime - _time > stepSize*3.01 ? _time + stepSize*3 : targetTime;
745 _stopOnCollision =
false;
748 double endTime = collisionEndTime - time > stepSize*1.01 ? time+stepSize : collisionEndTime;
750 ret = _solver->
doEvolve(&time, endTime, &_variables,
751 _errorsCalculation ? &_variances : NULL);
758 stepSize = fmin(stepSize/2, targetTime - _time);
759 collisionEndTime = targetTime - _time > stepSize*3.01 ? _time + stepSize*3 : targetTime;
771 scatterVariables(_variables.data(), _errorsCalculation ? _variances.data() : NULL);
774 int contactsCount = 0;
775 int status = _collisionSolver->
checkContacts(_bodies,
true, &contactsCount);
783 _tempArray.setZero();
785 ::new (&_constraintsInfo.
velocity)
MappedVector(_variables.data()+_variablesCount, _variablesCount);
789 gatherJointsInfo(&_constraintsInfo);
798 ret = _constraintSolver->
solve(&_constraintsInfo);
806 }
while(_time + stepSize/100 <= collisionEndTime);
811 scatterVariables(_variables.data(), _errorsCalculation ? _variances.data() : NULL);
815 inline int World::solverFunction(
double t,
const double* y,
816 const double* yvar,
double* f,
double* fvar)
821 scatterVariables(y, yvar);
824 bool calcVariances = (fvar != NULL);
825 const ForceList::const_iterator f_end = _forces.end();
826 for(ForceList::iterator force = _forces.begin(); force != f_end; ++force) {
827 (*force)->calcForce(calcVariances);
830 std::memcpy(f, y+_variablesCount, _variablesCount*
sizeof(*f));
831 if(fvar) std::memcpy(fvar, y+_variablesCount, _variablesCount*
sizeof(*fvar));
832 gatherAccelerations(f+_variablesCount, fvar ? fvar+_variablesCount : NULL);
834 if (_constraintSolver)
840 if(_collisionSolver) {
841 int contactsCount = 0;
842 state = _collisionSolver->
checkContacts(_bodies,
false, &contactsCount);
852 if(_variablesCount>0)
855 ::new (&_constraintsInfo.velocity)
MappedVector(y+_variablesCount, _variablesCount);
856 ::new (&_constraintsInfo.acceleration)
MappedVector(f+_variablesCount, _variablesCount);
862 gatherJointsInfo(&_constraintsInfo);
865 if(_collisionSolver) {
866 _collisionSolver->getContactsInfo(_constraintsInfo,
false);
888 if(_constraintsInfo.constraintsCount + _constraintsInfo.contactsCount > 0) {
890 int state = _constraintSolver->
solve(&_constraintsInfo);
894 const BodyList::const_iterator b_end = _bodies.end();
895 for(BodyList::iterator body = _bodies.begin(); body != b_end; ++body) {
896 (*body)->addForce(&_constraintsInfo.force[offset], NULL);
897 (*body)->getAccelerations(f+_variablesCount+offset, NULL);
898 offset += (*body)->variablesCount();
906 int World::solverFunction(
double t,
const double* y,
907 const double* yvar,
double* f,
double* fvar,
void* params)
909 return static_cast<World*
>(params)->solverFunction(t, y, yvar, f, fvar);
DynSparseRowMatrix jacobianDerivative
Time-derivative of constraintsJacobian.
CollisionSolver * removeCollisionSolver()
Get current CollisionSolver and remove it from world.
ConstraintSolver * constraintSolver() const
Get current ConstraintSolver.
void deleteObjectErrors()
Delete objectErrors.
Item * item(const QString &name) const
Get any descendant item by its name.
iterator insert(const Key &key, const T &value)
Object * object(const QString &name)
Add new item to the world.
VectorXd value
Current constarints values (amount of brokenness)
MappedVector acceleration
Accelerations of the bodies before applying constraints.
virtual int doEvolve(double *t, double t1, VectorXd *y, VectorXd *yvar)=0
Integrate.
#define STEPCORE_ASSERT_NOABORT(expr)
virtual int solve(ConstraintsInfo *info)=0
ConstraintSolver * removeConstraintSolver()
Get current ConstraintSolver and remove it from world.
void worldItemRemoved(Item *item)
Recursively call worldItemRemoved for all children objects.
int contactsCount
Number of additional constrains equations due to contacts.
Item & operator=(const Item &item)
Assignment operator (copies objectErrors if necessary)
Root of the StepCore classes hierarchy.
int variablesCount
Number of dynamic variables.
~ItemGroup()
Destroys the group and all its subitems.
virtual void setGroup(ItemGroup *group)
Set/change pointer to ItemGroup in which this object lives.
MappedVector velocity
Velocities of the bodies.
Generic Solver interface.
void clear()
Deletes all items.
Item * childItem(int index) const
Get direct child item by its index.
STEPCORE_SUPER_CLASS(CollisionSolver)
World()
Constructs empty World.
VectorXd forceMin
Constraints force lower limit.
void setDimension(int newVariablesCount, int newConstraintsCount, int newContactsCount=0)
Set variablesCount, constraintsCount and reset contactsCount, resize all arrays appropriately.
CollisionSolver interface.
virtual void removeItem(Item *item)
Remove item from the group (you should delete item youself)
int constraintsCount
Number of constraints equations.
virtual void getContactsInfo(ConstraintsInfo &info, bool collisions=false)=0
Fill the constraint info structure with the contacts computed by checkContacts()
int doEvolve(double delta)
Integrate.
World * world() const
Get pointer to World in which this object lives.
Item, Body, Force and Tool interfaces, World class.
virtual void addItem(Item *item)
Add new item to the group.
DynSparseRowMatrix jacobian
Position-derivative of constraints values.
QT_TRANSLATE_NOOP("ObjectClass","GJKCollisionSolver")
ItemGroup * group() const
Get pointer to ItemGroup in which this object lives.
Eigen::Map< Eigen::VectorXd > MappedVector
void setColor(Color color)
Set item color (for use in GUI)
VectorXd forceMax
Constraints force upper limit.
~World()
Destroys World and all objects which belongs to it.
virtual void bodyRemoved(BodyList &, Body *)
Solver * solver() const
Get current Solver.
ConstraintSolver interface.
void setSolver(Solver *solver)
Set new Solver (and delete the old one)
virtual void setParams(void *params)
Set callback function params.
The root class for any world items (bodies and forces)
int childItemIndex(const Item *item) const
Finds direct child item in items()
VectorXd derivative
Time-derivative of constraints values.
virtual ObjectErrors * createObjectErrors()
Base class for all errors objects.
const QString & name() const
Returns name of the object.
Object(const QString &name=QString())
QT_TR_NOOP("Errors class for CoulombForce")
STEPCORE_PROPERTY_RW(double, depth, QT_TRANSLATE_NOOP("PropertyName","depth"), QT_TRANSLATE_NOOP("Units","J"), QT_TR_NOOP("Potential depth"), depth, setDepth) STEPCORE_PROPERTY_RW(double
const T value(const Key &key) const
Groups several items together.
Collision solver interface.
QVariant fromValue(const T &value)
virtual void setFunction(Function function)
Set callback function.
std::vector< Item * > ItemList
List of pointers to Item.
#define STEPCORE_UNITS_NULL
virtual void bodyAdded(BodyList &, Body *)
CollisionSolver * collisionSolver() const
Get current CollisionSolver.
void setWorld(World *world)
Recursively call setWorld for all children objects.
STEPCORE_PROPERTY_RW_D(StepCore::Vector2d, positionVariance, QT_TRANSLATE_NOOP("PropertyName","positionVariance"), QT_TRANSLATE_NOOP("Units","m"), QT_TR_NOOP("position variance"), positionVariance, setPositionVariance) STEPCORE_PROPERTY_RW_D(double
void setCollisionSolver(CollisionSolver *collisionSolver)
Set new CollisionSolver (and delete the old one)
World & operator=(const World &world)
Assignment operator (deep copy)
void clear()
Clear world (removes all items, solver and resets time)
ObjectErrors * objectErrors()
Get existing ObjectErrors or try to create it.
virtual int checkContacts(BodyList &bodies, bool collisions=false, int *count=NULL)=0
Check (and update) state of the contact.
void setName(const QString &name)
Set name of the object.
double stepSize() const
Get step size.
virtual int doCalcFn(double *t, const VectorXd *y, const VectorXd *yvar=0, VectorXd *f=0, VectorXd *fvar=0)=0
Calculate function value.
VectorXd inverseMass
Diagonal coefficients of the inverse mass matrix of the system.
const ItemList & items() const
Get list of all direct child items in the ItemGroup.
virtual void setWorld(World *world)
Set/change pointer to World in which this object lives.
STEPCORE_META_OBJECT(CollisionSolver, QT_TRANSLATE_NOOP("ObjectClass","CollisionSolver"),"CollisionSolver", MetaObject::ABSTRACT, STEPCORE_SUPER_CLASS(Object), STEPCORE_PROPERTY_RW(double, toleranceAbs, QT_TRANSLATE_NOOP("PropertyName","toleranceAbs"), STEPCORE_UNITS_1, QT_TR_NOOP("Allowed absolute tolerance"), toleranceAbs, setToleranceAbs) STEPCORE_PROPERTY_R_D(double, localError, QT_TRANSLATE_NOOP("PropertyName","localError"), STEPCORE_UNITS_1, QT_TR_NOOP("Maximal local error during last step"), localError)) STEPCORE_META_OBJECT(GJKCollisionSolver
virtual void setDimension(int dimension)
Set ODE dimension.
MappedVector position
Positions of the bodies.
Solver * removeSolver()
Get current Solver and remove it from world.
VectorXd force
Resulting constraints force.
Constraint solver interface.
ItemGroup & operator=(const ItemGroup &group)
Assignment operator (deep copy)
void clear()
Clear the structure.
Contains multiple Item, Solver and general properties such as time.
void setConstraintSolver(ConstraintSolver *constraintSolver)
Set new ConstraintSolver (and delete the old one)
bool collisionFlag
True if there is a collision to be resolved.
ItemGroup(const QString &name=QString())
Constructs empty group.
virtual void resetCaches()
Reset internal caches of collision information.
double time() const
Get current time.
int doCalcFn()
Calculate all forces.
ItemList allItems() const
Get list of all items in the ItemGroup.