mxArray* ParticleSimulator::SaveConvexity() { ParticleFactory* factory = ParticleFactory::getInstance(); const int dims[] = { factory->particles.size(), 3 }; vector<float> F(dims[0] * dims[1]); for (int i = 0; i < dims[0]; ++i) { MovingParticle* p = factory->particles[i]; CParticleF pr = p->project(p->created + 0.1); SetData2(F, i, 0, dims[0], dims[1], pr.m_X); SetData2(F, i, 1, dims[0], dims[1], pr.m_Y); SetData2(F, i, 2, dims[0], dims[1], p->reflexive<=0 ? 0.0f: 1.0f); } return StoreData(F, mxSINGLE_CLASS, 2, dims); }
StraightOffsetPolygon::StraightOffsetPolygon(const vector<MovingParticle*>& vertices, float time) { particles = vertices; this->created = time; //set the neighborhood for (int i = 0; i < particles.size(); ++i) { MovingParticle* p = particles[i]; MovingParticle* q = particles[i == particles.size() - 1 ? 0 : i + 1]; MovingParticle* r = particles[i == 0 ? particles.size() - 1 : i - 1]; MovingParticle::setNeighbors(p, r, q); pset.insert(p); } //calculate velocity if necessary for (int i = 0; i < particles.size(); ++i) { MovingParticle* p = particles[i]; if (p->isInitialized()) continue; CParticleF o = p->getP(); MovingParticle* q = particles[i == particles.size() - 1 ? 0 : i + 1]; MovingParticle* r = particles[i == 0 ? particles.size() - 1 : i - 1]; if (o == a) //leaf node { float ang = GetVisualDirection(o.m_X, o.m_Y, b.m_X, b.m_Y) + PI / 2.0; a.m_X = o.m_X + cos(ang); a.m_Y = o.m_Y + sin(ang); } else if (o == b) //leaf node { float ang = GetVisualDirection(o.m_X, o.m_Y, a.m_X, a.m_Y) - PI / 2.0; b.m_X = o.m_X + cos(ang); b.m_Y = o.m_Y + sin(ang); } float vx, vy; calculateBisectorVelocity(r->getP(), p->getP(), q->getP(), vx, vy); p->setVelocity(vx, vy); } //find the next event for each particle. //we only need to compute for those whose event has not been set of its participants no longer part of this polygon. for (int i = 0; i < particles.size(); ++i) { //MovingParticle* p = particles[i]; //p->updateEvent(); /*EventStruct event = p->getEvent(); if (event.type == UnknownEvent || pset.find(event.q) == pset.end() || pset.find(event.r) == pset.end()) { p->updateEvent(particles); }*/ } }
mxArray* ParticleSimulator::SaveParticles() { ParticleFactory* factory = ParticleFactory::getInstance(); const int dims[] = { factory->particles.size(), ParticleDumpSize }; vector<float> F(dims[0] * dims[1]); for (int i = 0; i < dims[0]; ++i) { MovingParticle* p = factory->particles[i]; vector<float> v = p->dump2vector(); for (int j = 0; j < dims[1]; ++j) { SetData2(F, i, j, dims[0], dims[1], v[j]); } } return StoreData(F, mxSINGLE_CLASS, 2, dims); }
bool ParticleSimulator::Simulate(float endtime, float delta, bool bdebug) { ParticleFactory* factory = ParticleFactory::getInstance(); float snapTime = delta; bool bSuccess = true; for (set<MovingParticle*>::iterator it = factory->activeSet.begin(); it != factory->activeSet.end(); ++it) { (*it)->updateEvent(); } { vector<Snapshot> shots = Snapshot::TakeSnapshot(time); snapshots.insert(snapshots.end(), shots.begin(), shots.end()); } int iter = 0; while (time < endtime) { iter++; vector<Snapshot> shots = Snapshot::TakeSnapshot(time); //temporary MovingParticle* p = MovingParticle::getNextEvent(); if (p == NULL) break; if (p->getEvent().t > endtime) break; if (p->id == 255) p->id += 0; for (set<MovingParticle*>::iterator it = factory->activeSet.begin(); it != factory->activeSet.end(); ++it) { (*it)->update(p->getEvent().t - time); } time = p->getEvent().t; if (p->applyEvent() == false) break; p->getEvent().print(); MovingParticle::removeUnstable(); if (time >= snapTime) { vector<Snapshot> shots = Snapshot::TakeSnapshot(time); snapshots.insert(snapshots.end(), shots.begin(), shots.end()); snapTime += delta; } MovingParticle::quickFinish(); if (bdebug && MovingParticle::sanityCheck() == false) { printf("Violation of sanity check found at %f.\n", time); vector<Snapshot> shots = Snapshot::TakeSnapshot(time); snapshots.insert(snapshots.end(), shots.begin(), shots.end()); bSuccess = false; break; } //find closed regions vector<vector<MovingParticle*>> regions = MovingParticle::clusterParticles(); for (int i = 0; i < regions.size(); ++i) { //if (clockWise(regions[i]) > 0) { vector<MovingParticle*> tr = MovingParticle::traceBackPolygon(regions[i]); vector<vector<MovingParticle*>> areas = MovingParticle::closedRegions(tr); for (int j = 0; j < areas.size(); ++j) { Snapshot shot(0.0f, areas[j]); if (find(closedRegions.begin(), closedRegions.end(), shot) == closedRegions.end()) { closedRegions.push_back(shot); } } //if (tr.size() > 10) //forget small ones { Snapshot shot(0.0f, tr); if (find(traces.begin(), traces.end(), shot) == traces.end()) { traces.push_back(Snapshot(0, tr)); polygons.push_back(Snapshot(time, regions[i])); } } } } doneEvents.push_back(p->getEvent()); //for (set<MovingParticle*>::iterator it = factory->updateQueue.begin(); it != factory->updateQueue.end(); ++it) for (set<MovingParticle*>::iterator it = factory->activeSet.begin(); it != factory->activeSet.end(); ++it) { (*it)->updateEvent(); } factory->updateQueue.clear(); } for (int i = 0; i < factory->particles.size(); ++i) { MovingParticle* p = factory->particles[i]; if (p->bActive == false && p->time > p->init_event_time && p->init_event_time >= 0) { printf("%d %f %f %f %d\n", p->id, p->created, p->time, p->init_event_time, p->event.type); } } return bSuccess; }
/* a snapshot provides neighborhood information at a particular point in time. We try to reproduce the configuration of the system as accurately as possible. We need to consider the following steps. 1. all particles that are created after the time point need to be removed from the system. 2. all particles that are still active at the time point need to be activated. 3. children of a particle need to be erased if they are created after the time point. */ bool ParticleSimulator::Restore(vector<Snapshot>& snapshots) { ParticleFactory* factory = ParticleFactory::getInstance(); float time0 = 0; for (int i = 0; i < snapshots.size(); ++i) { if (snapshots[i].getTime() > time0) { time0 = snapshots[i].getTime(); } } time = time0; for (int i = 0; i < factory->particles.size(); ++i) { MovingParticle* p = factory->particles[i]; for (int j = 0; j < 2; ++j) { if (p->children[j] != NULL && p->children[j]->created > time) { p->children[j] = NULL; } } } vector<MovingParticle*> toremove; for (int i = 0; i < factory->particles.size(); ++i) { MovingParticle* p = factory->particles[i]; if (p->created > time) { toremove.push_back(p); } } //activate those that are still active. vector<MovingParticle*> toactivate; for (int i = 0; i < factory->particles.size(); ++i) { MovingParticle* p = factory->particles[i]; if (p->bActive == false && p->created < time && p->time > time) { toactivate.push_back(p); } } //set neighbors for (int i = 0; i < snapshots.size(); ++i) { float t = snapshots[i].getTime(); for (int j = 0; j < snapshots[i].size(); ++j) { int id = snapshots[i].get(j); int id0 = snapshots[i].get(j == 0 ? snapshots[i].size() - 1 : j - 1); int id2 = snapshots[i].get(j == snapshots[i].size() - 1 ? 0 : j + 1); MovingParticle* p = factory->get(id); if (p == NULL) { return false; } p->setNeighbors(p, factory->get(id0), factory->get(id2)); } } //delete future particles from memory for (int i = 0; i < toremove.size(); ++i) { factory->remove(toremove[i]); } //factory->activeSet.clear(); for (int i = 0; i < toactivate.size(); ++i) { factory->activeSet.insert(toactivate[i]); } //recalculate positions for (set<MovingParticle*>::iterator it = factory->activeSet.begin(); it != factory->activeSet.end(); ++it) { MovingParticle* p = *it; p->p = p->project(time); p->time = time; } //recalculate events for (set<MovingParticle*>::iterator it = factory->activeSet.begin(); it != factory->activeSet.end(); ++it) { (*it)->event.type == UnknownEvent; (*it)->updateEvent(); } return true; }
bool ParticleSimulator::Simulate(float endtime, float delta, bool bdebug) { ParticleFactory& factory = ParticleFactory::getInstance(); PolygonFactory& pfactory = PolygonFactory::getInstance(); float snapTime = delta; bool bSuccess = true; for (set<MovingParticle*>::iterator it = factory.activeSet.begin(); it != factory.activeSet.end(); ++it) { (*it)->updateEvent(); } { vector<Snapshot> shots = Snapshot::TakeSnapshot(time); snapshots.insert(snapshots.end(), shots.begin(), shots.end()); } int iter = 0; while (time < endtime) { iter++; MovingParticle* p = MovingParticle::getNextEvent(); if (p == NULL) break; if (p->getEvent().t > endtime) break; if (p->id == 19 && p->event.q->id == 22) iter += 0; for (set<MovingParticle*>::iterator it = factory.activeSet.begin(); it != factory.activeSet.end(); ++it) { (*it)->update(p->getEvent().t - time); } time = p->getEvent().t; pair<MovingParticle*, MovingParticle*> pnew = p->applyEvent(); /*if (p->event.type == SplitEvent || p->event.type == CollisionEvent) { if (p->polygon->getId() == p->event.q->polygon->getId()) { //split the same polygon into two dag.add(p->polygon, pnew.first->polygon); dag.add(p->polygon, pnew.second->polygon); } else { //merge two polygons into one dag.add(pnew.first->polygon, p->polygon); dag.add(pnew.first->polygon, p->event.q->polygon); } }*/ p->getEvent().print(); //MovingParticle::removeUnstable(); if (time >= snapTime) { vector<Snapshot> shots = Snapshot::TakeSnapshot(time); snapshots.insert(snapshots.end(), shots.begin(), shots.end()); snapTime += delta; } MovingParticle::quickFinish(); if (bdebug && MovingParticle::sanityCheck() == false) { printf("Violation of sanity check found at %f.\n", time); vector<Snapshot> shots = Snapshot::TakeSnapshot(time); snapshots.insert(snapshots.end(), shots.begin(), shots.end()); bSuccess = false; break; } //find closed regions vector<vector<MovingParticle*>> regions = MovingParticle::clusterParticles(); for (int i = 0; i < regions.size(); ++i) { vector<MovingParticle*> tr = MovingParticle::traceBackPolygon(regions[i]); vector<vector<MovingParticle*>> areas = MovingParticle::closedRegions(tr); Snapshot shot0(time, time, regions[i]); for (int j = 0; j < areas.size(); ++j) { Snapshot shot(time, 0.0f, areas[j]); if (find(closedRegions.begin(), closedRegions.end(), shot) == closedRegions.end()) { closedRegions.push_back(shot); //Polygon* poly = pfactory.makePolygon(areas[j], time); traces.push_back(shot0); } } /*if (find(traces.begin(), traces.end(), shot0) == traces.end()) { polygons.push_back(Snapshot(time, time, regions[i])); }*/ } doneEvents.push_back(p->getEvent()); //for (set<MovingParticle*>::iterator it = factory->updateQueue.begin(); it != factory->updateQueue.end(); ++it) for (set<MovingParticle*>::iterator it = factory.activeSet.begin(); it != factory.activeSet.end(); ++it) { (*it)->updateEvent(); } factory.updateQueue.clear(); } for (int i = 0; i < factory.particles.size(); ++i) { //factory.particles[i]->printParentTree("\t"); } return bSuccess; }