vector<MovingParticle*>
ParticleSimulator::initializePolygon(vector<Edge<CParticleF>*>& edges)
{
	ParticleFactory* factory = ParticleFactory::getInstance();
	vector<MovingParticle*> particles;
	for (int i = 0; i < edges.size(); ++i)
	{
		particles.push_back(factory->makeParticle(edges[i]->u->key, Initial, 0.0f));
		if (edges[i]->u->aList.size() <= 1) //leaf node.
		{
			particles.push_back(factory->makeParticle(edges[i]->u->key, Initial, 0.0f));
		}
	}
	//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);
	}
	//calculate velocity 
	for (int i = 0; i < particles.size(); ++i)
	{
		particles[i]->initializeVelocity();
	}
	return particles;
}
/*
Trace a tree around it to construct particles representing vertices of a straight polygon.
The implementation is not pretty and may be simplified. But I am not sure at this time.
*/
void
_trace(Vertex<CParticleF>* u, Vertex<CParticleF>*prev, vector<MovingParticle*>& points)
{
	ParticleFactory* factory = ParticleFactory::getInstance();
	MovingParticle* particle = factory->makeParticle(u->key, Initial, 0.0f);
	points.push_back(particle);
	u->color = Black;
	CParticleF pu = u->key;
	CParticleF qu = prev == NULL ? CParticleF(pu.m_X - 1.0, pu.m_Y) : prev->key;
	int count = 1;
	while (true)
	{
		Vertex<CParticleF>* v = NULL;
		float minAngle = 3 * PI;
		//Walk in clock-wise  order.
		for (int i = 0; i < u->aList.size(); ++i)
		{
			Vertex<CParticleF>* w = u->aList[i]->v;
			if (w->color == White)
			{
				float ang = GetVisualAngle2(qu.m_X, qu.m_Y, w->key.m_X, w->key.m_Y, pu.m_X, pu.m_Y);
				if (ang <= 0) ang += 2 * PI;
				if (ang < minAngle)
				{
					minAngle = ang;
					v = w;
				}
			}
		}
		if (v != NULL)
		{
			count++;
			_trace(v, u, points);
			MovingParticle* particle2 = factory->makeParticle(u->key, Initial, 0.0f);
			points.push_back(particle2); //every branch will result in a new particle.
		}
		else
		{
			break;
		}
		qu = v->key; //update where we are coming from
	}
	//at a leaf, we need to provide additional one to account for two corners
	if (count < 2)
	{
		MovingParticle* particle2 = factory->makeParticle(u->key, Initial, 0.0f);
		points.push_back(particle2);
	}
	//When this is the first node of the trace, the last one is extra unless this is also a leaf node.
	if (prev == NULL && count > 2)
	{
		MovingParticle* p = *(points.end() - 1);
		factory->inactivate(p);
		points.erase(points.end() - 1);
	}
}
Exemple #3
0
void f6_structure::update()
{

	// UPDATE TRACKER
	//t.update();

	// UPDATE LISTENER
	Listener& listener = Listener::getInstance();
	listener.update();
	mVolume = listener.getVolume();

	// UPDATE PARTICLE SYSTEMS
	int particleCount = 0;
	for (int i = 0; i < pss.size(); i++ )
	{

		pss[i].update(mMousePosition);
		pf.create(mMousePosition, pss[i]);
		particleCount += pss[i].mParticles.size();
	}
	mTotalParticles = particleCount;
}
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;
}
/*
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;
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{   
	printf("%s: This build was compiled at %s %s\n", "StraightMedialAxis", __DATE__, __TIME__);
	if (nrhs < 1 || nlhs < 0)
	{
		mexErrMsgTxt("Usage: [X Y] = StraightMedialAxis(P, [iter delta])");
		return;
	}
	//Points
	vector<CParticleF> points;
	const int* dimsP;
	{
		vector<float> P0;
		mxClassID classIdP;
		int ndimP;
		LoadData(P0, prhs[0], classIdP, ndimP, &dimsP);
		for(int i=0; i<dimsP[0]; ++i)
		{
			float x = GetData2(P0, i, 0, dimsP[0], dimsP[1], (float)0);
			float y = GetData2(P0, i, 1, dimsP[0], dimsP[1], (float)0);
			//points.push_back(CParticleF(x, y));
			points.insert(points.begin(), CParticleF(x,y));
		}
	}
	int K = 0;
	if(nrhs >= 2)
	{
		mxClassID classMode;
		ReadScalar(K,prhs[1],classMode);
	} 

	GraphFactory<graphKey>* factory = GraphFactory<graphKey>::GetInstance();
	ParticleFactory* pfactory = ParticleFactory::getInstance();

	vector<DeformingPolygon> polygons;
	polygons.push_back(DeformingPolygon(points));
	int count = 0;
	bool bDone = false;
	vector<vector<CParticleF>> contours;
	while(!bDone && polygons.empty() == false)
	{
		DeformingPolygon poly = polygons[0];
		polygons.erase(polygons.begin());
		while(true)
		{
			int ec, el;
			count++;
			if(K == count)
			{
				bDone = true;
				break;
			}
			vector<DeformingPolygon> newpolys = fixPolygon(poly);
			if(poly.sanityCheck(ec, el) == false)
			{
				ec += 0;
			}
			polygons.insert(polygons.end(), newpolys.begin(), newpolys.end());
			if(poly.particles.size()>2)
			{
				float t1 = poly.nextEdgeEvent();
				float t2 = poly.nextSplitEvent();
				float t = Min(t1, t2);
				if(t >= std::numeric_limits<float>::infinity()) break;
				if(t1 > t2) printf("Split event at %d.\n", count);
				else printf("Edge event at %d.\n", count);

				poly.deform(t);
				vector<CParticleF> pnts;
				for(int k=0; k<poly.particles.size(); ++k)
				{
					pnts.push_back(poly.particles[k]->p);
				}
				contours.push_back(pnts);
			}
			else break;
			if(poly.sanityCheck(ec, el) == false)
			{
				ec += 0;
			}
		}
	}
	//vector<DeformingPolygon> newpolys = fixPolygon(polygons[0]);
	//polygons[0].deform(5.0);

	if(nlhs >= 1)
	{
		const int dims[] = {pfactory->particles.size(), 7};
		vector<float> F(dims[0]*dims[1]);
		for(int i=0; i<dims[0]; ++i)
		{
			MovingParticle* p = pfactory->particles[i];
			SetData2(F, i, 0, dims[0], dims[1], p->p0.m_X);
			SetData2(F, i, 1, dims[0], dims[1], p->p0.m_Y);
			SetData2(F, i, 2, dims[0], dims[1], p->p.m_X);
			SetData2(F, i, 3, dims[0], dims[1], p->p.m_Y);
			SetData2(F, i, 4, dims[0], dims[1], p->v[0]);
			SetData2(F, i, 5, dims[0], dims[1], p->v[1]);
			SetData2(F, i, 6, dims[0], dims[1], (float)p->id);
		}
		plhs[0] = StoreData(F, mxSINGLE_CLASS, 2, dims);
	}
	if(nlhs >= 2)
	{
		plhs[1] = StorePolygons(contours);
	}
	factory->Clean();
	pfactory->clean();
	mexUnlock();
}