* Copyright 2011 kubtek <kubtek@mail.com>
*
* This file is part of StarDict.
*
* StarDict is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* StarDict 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with StarDict. If not, see <http://www.gnu.org/licenses/>.
*/
#include "newton.h"
void newton_t::update(single t) {
init_newton_calculate();
calculate_spring_factor();
calculate_repulsion_factor();
calculate_friction_factor();
calculate_collide_factor();
calculate_new_position(t);
}
void newton_t::calculate_new_position(single t) {
_statchanged = false;
for(vector<partic_t *>::iterator it = _scene.get_partics().begin();
it != _scene.get_partics().end(); ++it) {
if (!(*it)->get_anchor()) {
vector_t v2 = (*it)->getV() + (*it)->getA().mul(t);
if (v2.powerlength() > _env.max_limt_powner_v*_env.max_limt_powner_v)
v2.scaleto(_env.max_limt_powner_v);
vector_t avgv = ((*it)->getV() + v2).div(2);
vector_t d = avgv.mul(t);
if (d.powerlength() > 0.5f) {
(*it)->getP().add(d);
if (!_statchanged) _statchanged = true;
}
(*it)->getV() = v2;
}
}
}
void newton_t::calculate_spring_factor() {
for(vector<spring_t *>::iterator it = _scene.get_springs().begin();
it != _scene.get_springs().end(); ++it) {
(*it)->getA().getF().add((*it)->getFa());
(*it)->getB().getF().add((*it)->getFb());
}
}
void newton_t::init_newton_calculate() {
for(vector<partic_t *>::iterator it = _scene.get_partics().begin();
it != _scene.get_partics().end(); ++it) {
(*it)->getF() = vector_t::zero;
}
}
void newton_t::calculate_repulsion_factor() {
for(size_t i = 0; i < _scene.get_partics().size(); ++i) {
partic_t * a = _scene.get_partics()[i];
for(size_t j = 0; j < _scene.get_partics().size(); ++j ) {
partic_t * b = _scene.get_partics()[j];
vector_t f = a->getP() - b->getP();
single dd = f.powerlength();
dd = dd > _env.min_repulsion_distance ? dd : _env.min_repulsion_distance;
single g = _env.G * a->getM()*b->getM()/dd;
f.set_length(g);
a->getF().add(f);
f.mul(-1);
b->getF().add(f);
}
}
}
void newton_t::calculate_friction_factor() {
for(vector<partic_t *>::iterator it = _scene.get_partics().begin();
it != _scene.get_partics().end(); ++it) {
vector_t f = (*it)->getV() * (-get_env().get_friction_factor());
(*it)->getF().add(f);
}
get_env().update_friction_factor();
}
void newton_t::calculate_collide_factor() {
for(size_t i = 0; i < _scene.get_partics().size(); ++i) {
partic_t * a = _scene.get_partics()[i];
for(size_t j = i+1; j < _scene.get_partics().size(); ++j) {
partic_t * b = _scene.get_partics()[j];
if(a->get_box().overlay(b->get_box())) {
vector_t d = a->getV() - b->getV();
vector_t t = d;
t.rot(M_PI_2);
vector_t f = d;
f.norm();
b->getF().add(f*(-b->getM()));
a->getF().add(f.mul(a->getM()));
}
}
}
}