/* A unit vector from o to x in 2D */ CParticleF NormalizedDirection(CParticleF& x, CParticleF& o) { float dx = x.m_X - o.m_X; float dy = x.m_Y - o.m_Y; float len = sqrt(dx*dx + dy*dy); if (len > 1.0e-5) { return CParticleF(dx / len, dy / len); } else { return CParticleF(0.0f, 0.0f); } }
/* Check if lines a-b and c-d are parallel. */ bool isParallel(CParticleF& a, CParticleF& b, CParticleF& c, CParticleF& d, float precision) { CParticleF x = UnitVector(CParticleF(b.m_X - a.m_X, b.m_Y - a.m_Y, b.m_Z - a.m_Z)); CParticleF y = UnitVector(CParticleF(d.m_X - c.m_X, d.m_Y - c.m_Y, d.m_Z - c.m_Z)); CParticleF z = crossProduct(x, y); if (sqrt(z.m_X*z.m_X + z.m_Y*z.m_Y + z.m_Z*z.m_Z) < precision) { return true; } else { return false; } }
bool LinkedTriple::updateFate() { if (frontSupporters.size() == 0) return false; /*float sx = 0, sy = 0, st = 0; for (int i = 0; i < awaySupporters.size(); ++i) { LinkedTriple* t = awaySupporters[i]; float c = compatibility(t); float s = _timeToClosestEncounter(t); sx += s * v[0] * t->prob; sy += s * v[1] * t->prob; st += t->prob; } fate = CParticleF(p->getX() + sx / st, p->getY() + sy / st);*/ LinkedTriple* b = best(); if (b == NULL) return false; float s = this->_timeToClosestEncounter(b); fate = CParticleF(p->getX() + s * v[0], p->getY() + s * v[1]); return true; }
/* return a unit vector that bisects the angle formed by three points: a-o-b. */ CParticleF bisector(CParticleF& o, CParticleF& a, CParticleF& b) { CParticleF x = NormalizedDirection(a, o); CParticleF y = NormalizedDirection(b, o); CParticleF z((x.m_X + y.m_X) / 2, (x.m_Y + y.m_Y) / 2); float vx = z.m_X; float vy = z.m_Y; float len0 = sqrt(vx*vx + vy*vy); if (len0 <= 1.0e-5) //this is a colinear point. { float ang = GetVisualDirection(b.m_X, b.m_Y, a.m_X, a.m_Y) - PI / 2.0; vx = cos(ang); vy = sin(ang); } else { vx = vx / len0; vy = vy / len0; } CParticleF bs(o.m_X + vx, o.m_Y + vy); //There are two bisector directions. //We consistently choose one that is in clock-wise direction. vector<CParticleF> pnts(4); pnts[0] = o; pnts[1] = a; pnts[2] = bs; pnts[3] = b; if (ClockWise(pnts)<0) { vx = -vx; vy = -vy; } return CParticleF(vx, vy); }
bool ParticleSimulator::LoadParticles(vector<float>& F, const int* dims) { ParticleFactory* factory = ParticleFactory::getInstance(); factory->clean(); this->time = 0.0f; map<int, MovingParticle*> id2particle; vector<int> vchild1; vector<int> vchild2; vector<int> vparent1; vector<int> vparent2; vector<int> vprev; vector<int> vnext; vector<int> veq; vector<int> ver; for (int i = 0; i < dims[0]; ++i) { int id = (int)GetData2(F, i, 0, dims[0], dims[1], -1.0f); float x0 = GetData2(F, i, 1, dims[0], dims[1], std::numeric_limits<float>::quiet_NaN()); float y0 = GetData2(F, i, 2, dims[0], dims[1], std::numeric_limits<float>::quiet_NaN()); float x = GetData2(F, i, 3, dims[0], dims[1], std::numeric_limits<float>::quiet_NaN()); float y = GetData2(F, i, 4, dims[0], dims[1], std::numeric_limits<float>::quiet_NaN()); float vx = GetData2(F, i, 5, dims[0], dims[1], std::numeric_limits<float>::quiet_NaN()); float vy = GetData2(F, i, 6, dims[0], dims[1], std::numeric_limits<float>::quiet_NaN()); int pid = (int)GetData2(F, i, 7, dims[0], dims[1], -1.0f); int nid = (int)GetData2(F, i, 8, dims[0], dims[1], -1.0f); MovingParticleType type = int2ParticleType((int)GetData2(F, i, 9, dims[0], dims[1], -1.0f)); float created = GetData2(F, i, 10, dims[0], dims[1], 0.0f); float time = GetData2(F, i, 11, dims[0], dims[1], 0.0f); float ref = GetData2(F, i, 12, dims[0], dims[1], 0.0f); bool bActive = GetData2(F, i, 13, dims[0], dims[1], 0.0f)>0.0f ? true : false; bool bInitialized = (bool)GetData2(F, i, 14, dims[0], dims[1], 0.0f)>0.0f ? true : false; bool bUnstable = (bool)GetData2(F, i, 15, dims[0], dims[1], 0.0f)>0.0f ? true : false; int parent1 = (int)GetData2(F, i, 16, dims[0], dims[1], -1.0f); int parent2 = (int)GetData2(F, i, 17, dims[0], dims[1], -1.0f); int child1 = (int)GetData2(F, i, 18, dims[0], dims[1], -1.0f); int child2 = (int)GetData2(F, i, 19, dims[0], dims[1], -1.0f); EventType etype = int2EventType((int)GetData2(F, i, 20, dims[0], dims[1], 0.0f)); int eq = (int)GetData2(F, i, 21, dims[0], dims[1], -1.0f); int er = (int)GetData2(F, i, 22, dims[0], dims[1], -1.0f); float etime = GetData2(F, i, 23, dims[0], dims[1], 0.0f); MovingParticle* p = factory->makeParticle(CParticleF(x0, y0), type, created); p->p.m_X = x; p->p.m_Y = y; p->v[0] = vx; p->v[1] = vy; p->time = time; p->bActive = bActive; //p->bInitialized = bInitialized; p->bUnstable = bUnstable; p->event.type = etype; p->event.t = etime; p->reflexive = ref; vparent1.push_back(parent1); vparent2.push_back(parent2); vchild1.push_back(child1); vchild2.push_back(child2); p->event.p = p; vprev.push_back(pid); vnext.push_back(nid); veq.push_back(eq); ver.push_back(er); id2particle[p->id] = p; if (p->bActive==false) { factory->inactivate(p); } if (p->time > this->time) { this->time = p->time; } } //now set prev, next, etc. for (int i = 0; i < factory->particles.size(); ++i) { MovingParticle* p = factory->particles[i]; p->prev = vprev[i] >= 0 ? id2particle[vprev[i]] : NULL; p->next = vnext[i] >= 0 ? id2particle[vnext[i]] : NULL; p->event.q = veq[i] >= 0 ? id2particle[veq[i]] : NULL; p->event.r = ver[i] >= 0 ? id2particle[ver[i]] : NULL; p->parents[0] = vparent1[i] >= 0 ? id2particle[vparent1[i]] : NULL; p->parents[1] = vparent2[i] >= 0 ? id2particle[vparent2[i]] : NULL; p->children[0] = vchild1[i] >= 0 ? id2particle[vchild1[i]] : NULL; p->children[1] = vchild2[i] >= 0 ? id2particle[vchild2[i]] : NULL; if (p->id >= MovingParticle::_id) { MovingParticle::_id = p->id + 1; } } return true; }
/* Compute a unit vector normal to the side (p->q). The direction is to the left when we are at p and looking toward q. */ CParticleF perpDirection(CParticleF& p, CParticleF& q) { CParticleF nd = NormalizedDirection(q, p); return CParticleF(-nd.m_Y, nd.m_X); }
CParticleF crossProduct(CParticleF& a, CParticleF& b) { return CParticleF(a.m_Y*b.m_Z - a.m_Z*b.m_Y, a.m_Z*b.m_X - a.m_X*b.m_Z, a.m_X*b.m_Y - a.m_Y*b.m_X); }