int main(int argc, char *argv[]) 
{

  Pooma::initialize(argc, argv);
  Pooma::Tester tester(argc, argv);

  Interval<1> n1(1,5);
  Interval<1> n2(4,8);
  Interval<1> n3(10,20);
  Interval<2> a(n1,n2);
  Interval<3> b(n1,n2,n3);

  Range<1> r1(1,5);
  Range<1> r2(4,8,2);
  Range<1> r3(5,9,2);
  Range<1> r4(10,20,5);
  Range<2> ra(r1,r2);
  Range<2> rb(r1,r3);
  Range<3> rc(r1,r2,r3);

  tester.out() << "1: touches(" << a[0] << "," << a[1] << ") ? ";
  tester.out() << touches(a[0], a[1]) << std::endl;
  tester.check( touches(a[0], a[1]) );
  tester.out() << "0: touches(" << a[0] << "," << b[2] << ") ? ";
  tester.out() << touches(a[0], b[2]) << std::endl;
  tester.check( touches(a[0], b[2])==0);
  tester.out() << "1: touches(" << a[0] << "," << ra[0] << ") ? ";
  tester.out() << touches(a[0], ra[0]) << std::endl;
  tester.check(touches(a[0], ra[0]));
  tester.out() << "1: touches(" << ra[0] << "," << ra[1] << ") ? ";
  tester.out() << touches(ra[0], ra[1]) << std::endl;
  tester.check( touches(ra[0], ra[1]));
  tester.out() << "0: touches(" << r2 << "," << r3 << ") ? ";
  tester.out() << touches(r2, r3) << std::endl;
  tester.check( touches(r2, r3)==0);
  tester.out() << "0: touches(" << ra << "," << rb << ") ? ";
  tester.out() << touches(ra, rb) << std::endl;
  tester.check(  touches(ra, rb) ==0);
  tester.out() << "1: touches(" << rc << "," << rc << ") ? ";
  tester.out() << touches(rc, rc) << std::endl;
  tester.check( touches(rc, rc) );
  tester.out() << "------------------------------------" << std::endl;

  tester.check(" touches ", true);

  Interval<1> c1(1,10);
  Interval<1> c2(3,8);
  Interval<1> c3(5,15);
  Interval<2> ca(c1, c1);
  Interval<2> cb(c1, c2);
  Range<1>    cr1(2,20,2);
  Range<1>    cr2(4,16,4);
  Range<1>    cr3(3,15,2);
  Range<1>    cr4(5,15,5);

  tester.out() << "1: contains(" << c1 << "," << c2 << ") ? ";
  tester.out() << contains(c1,c2) << std::endl;
  tester.check(contains(c1,c2));
  tester.out() << "0: contains(" << c2 << "," << c1 << ") ? ";
  tester.out() << contains(c2,c1) << std::endl;
  tester.check(contains(c2,c1)==0);
  tester.out() << "0: contains(" << c1 << "," << c3 << ") ? ";
  tester.out() << contains(c1,c3) << std::endl;
  tester.check(contains(c1,c3)==0);
  tester.out() << "1: contains(" << ca << "," << cb << ") ? ";
  tester.out() << contains(ca,cb) << std::endl;
  tester.check(contains(ca,cb));
  tester.out() << "0: contains(" << cb << "," << ca << ") ? ";
  tester.out() << contains(cb,ca) << std::endl;
  tester.check(contains(cb,ca)==0);
  tester.out() << "1: contains(" << cr1 << "," << cr2 << ") ? ";
  tester.out() << contains(cr1,cr2) << std::endl;
  tester.check( contains(cr1,cr2));
  tester.out() << "0: contains(" << cr1 << "," << cr3 << ") ? ";
  tester.out() << contains(cr1,cr3) << std::endl;
  tester.check(contains(cr1,cr3)==0);
  tester.out() << "1: contains(" << c3 << "," << cr4 << ") ? ";
  tester.out() << contains(c3,cr4) << std::endl;
  tester.check(contains(c3,cr4));
  tester.out() << "0: contains(" << cr4 << "," << c3 << ") ? ";
  tester.out() << contains(cr4,c3) << std::endl;
  tester.check(contains(cr4,c3)==0);
  tester.out() << "------------------------------------" << std::endl;

  Interval<2> s1, s2;
  Range<2>    sr1, sr2;

  split(cb, s1, s2);
  tester.out() << "split(" << cb << ") = " << s1 << " and " << s2 << std::endl;
  tester.check(s1==Interval<2>(Interval<1>(1,5),Interval<1>(3,5)));
  tester.check(s2==Interval<2>(Interval<1>(6,10),Interval<1>(6,8)));

 

  split(rb, sr1, sr2);
  tester.out() << "split(" << rb << ") = " << sr1 << " and " << sr2 << std::endl;
  tester.check(sr1==Range<2>(Range<1>(1,2),Range<1>(5,5,2)));
  tester.check(sr2==Range<2>(Range<1>(3,5),Range<1>(7,9,2)));

  tester.out() << "------------------------------------" << std::endl;

  tester.out() << "intersect(" << cb << "," << ca << ") = ";
  tester.out() << intersect(cb,ca) << std::endl;
  tester.check(intersect(cb,ca)==Interval<2>(Interval<1>(1,10),
					     Interval<1>(3,8)));

  tester.out() << "intersect(" << rb << "," << ra << ") = ";
  tester.out() << intersect(rb,ra) << std::endl;


  Range<1> i1(1,16,3);
  Range<1> i2(17,3,-2);
  tester.out() << "intersect(" << i1 << "," << i2 << ") = ";
  tester.out() << intersect(i1,i2) << std::endl;
  tester.check( intersect(i1,i2) == Range<1>(7,14,6));

  tester.out() << "intersect(" << i2 << "," << i1 << ") = ";
  tester.out() << intersect(i2,i1) << std::endl;
  tester.check( intersect(i2,i1) == Range<1>(13,7,-6));

  tester.out() << "------------------------------------" << std::endl;

  Interval<1> eq1(1,5);
  Range<1> eq2 = -2 * eq1 + 3;
  Range<1> eq3(-8,8,4);
  Range<1> eq4 = 3 * eq1;
  Range<1> eq5 = 2 * eq1;
  Range<1> eq6 = 6 * eq1 + 1;

  tester.out() << "For " << eq1 << " --> " << eq4 << ", then " << eq3 << " --> ";
  tester.out() << equivSubset(eq1,eq4,eq3) << std::endl;

  tester.out() << "For " << eq4 << " --> " << eq6 << ", then " << eq3 << " --> ";
  tester.out() << equivSubset(eq4,eq6,eq3) << std::endl;

  tester.out() << "For " << eq1 << " --> " << eq2 << ", then " << eq3 << " --> ";
  tester.out() << equivSubset(eq1,eq2,eq3) << std::endl;

  tester.out() << "------------------------------------" << std::endl;

  NewDomain3<Interval<1>, Interval<1>, int>::SliceType_t  ba;
  //  tester.out() << "Created initial slice domain ba = " << ba << std::endl;
  ba = NewDomain3<Interval<1>, Interval<1>, int>::combineSlice(ba,eq1,eq1,7);
  tester.out() << "After taking slice, ba = " << ba << std::endl;

  int retval = tester.results("Domain Calc");
  Pooma::finalize();
  return retval;


}
Beispiel #2
0
 typename enable_if<is_interval_map<Type>, bool>::type
 is_joinable(typename Type::iterator it_, typename Type::iterator next_, Type* = 0)
 {
     return touches(it_->first, next_->first)
         && it_->second == next_->second    ;
 }
Touch peakToTouch(Touch p)
{
	return Touch{.x = mapRange(3.5f, 59.5f, 1.f, 29.f, p.x), .y = sensorToKeyY(p.y), .z = p.z};
}

// quick touch finder based on peaks of curvature.
// this works well, but a different approach based on blob sizes / shapes could do a much better
// job with contiguous keys.
TouchArray TouchTracker::findTouches(const SensorFrame& in)
{
	constexpr int kMaxPeaks = kMaxTouches*2;
	constexpr int w = SensorGeometry::width;
	constexpr int h = SensorGeometry::height;
	const float* pIn = in.data();
	int i, j;
	
	std::array<Touch, kMaxPeaks> peaks;
	TouchArray touches{};
	std::array<std::bitset<w>, h> map;
	
	// get peaks
	float f11, f12, f13;
	float f21, f22, f23;
	float f31, f32, f33;
	
	j = 0;
	{
		auto& row = map[j];
		const float* pRow2 = pIn + (j)*w;
		const float* pRow3 = pIn + (j + 1)*w;
		for(i = 1; i < w - 1; ++i)
		{
			f21 = pRow2[i - 1]; f22 = pRow2[i]; f23 = pRow2[i + 1];
			f31 = pRow3[i - 1]; f32 = pRow3[i]; f33 = pRow3[1 + 1];
			row[i] = (f22 > f21) && (f22 > mFilterThreshold) && (f22 > f23)
			&& (f22 > f31) && (f22 > f32) && (f22 > f33);
		}
	}
	
	for (j = 1; j < h - 1; ++j)
	{
		auto& row = map[j];
		const float* pRow1 = pIn + (j - 1)*w;
		const float* pRow2 = pIn + (j)*w;
		const float* pRow3 = pIn + (j + 1)*w;
		for(i = 1; i < w - 1; ++i)
		{
			f11 = pRow1[i - 1]; f12 = pRow1[i]; f13 = pRow1[i + 1];
			f21 = pRow2[i - 1]; f22 = pRow2[i]; f23 = pRow2[i + 1];
			f31 = pRow3[i - 1]; f32 = pRow3[i]; f33 = pRow3[1 + 1];
			row[i] = (f22 > f11) && (f22 > f12) && (f22 > f13)
			&& (f22 > f21) && (f22 > mFilterThreshold) && (f22 > f23)
			&& (f22 > f31) && (f22 > f32) && (f22 > f33);
		}
	}
	
	j = h - 1;
	{
		auto& row = map[j];
		const float* pRow1 = pIn + (j - 1)*w;
		const float* pRow2 = pIn + (j)*w;
		for(i = 1; i < w - 1; ++i)
		{
			f11 = pRow1[i - 1]; f12 = pRow1[i]; f13 = pRow1[i + 1];
			f21 = pRow2[i - 1]; f22 = pRow2[i]; f23 = pRow2[i + 1];
			row[i] = (f22 > f11) && (f22 > f12) && (f22 > f13)
			&& (f22 > f21) && (f22 > mFilterThreshold) && (f22 > f23);
		}
	}
	
	// gather all peaks.
	int nPeaks = 0;
	for (int j=0; j<h; j++)
	{
		auto& mapRow = map[j];
		for (int i=0; i < w; i++)
		{
			// if peak
			if (mapRow[i])
			{
				float z = in[j*w + i];
				peaks[nPeaks++] = Touch{.x = static_cast<float>(i), .y = static_cast<float>(j), .z = z};
				if (nPeaks >= kMaxPeaks) break;
			}
		}
	}
	
	if(nPeaks > 1)
	{
		std::sort(peaks.begin(), peaks.begin() + nPeaks, [](Touch a, Touch b){ return a.z > b.z; } );
	}
	
	// correct and clip
	int nTouches = std::min(nPeaks, (int)kMaxTouches);
	for(int i=0; i<nTouches; ++i)
	{
		Touch p = peaks[i];
		if(p.z < mFilterThreshold) break;
		
		Touch px = correctPeakX(p, in);
		Touch pxy = correctPeakY(px, in);
		touches[i] = peakToTouch(pxy);
	}
	
	return touches;
}

// match incoming touches in x with previous frame of touches in x1.
// for each possible touch slot, output the touch x closest in location to the previous frame.
// if the incoming touch is a continuation of the previous one, set its age (w) to 1, otherwise to 0.
// if there is no incoming touch to match with a previous one at index i, and no new touch needs index i, the position at index i will be maintained.

// TODO first touch below filter threshold(?) is on one index, then active touch switches index?! investigate.

TouchArray TouchTracker::matchTouches(const TouchArray& x, const TouchArray& x1)
{
	const float kMaxConnectDist = 2.f;
	
	TouchArray newTouches{};
	
	std::array<int, kMaxTouches> forwardMatchIdx;
	forwardMatchIdx.fill(-1);
	
	std::array<int, kMaxTouches> reverseMatchIdx;
	reverseMatchIdx.fill(-1);
	
	// for each previous touch, find minimum distance to a current touch.
	for(int i=0; i<mMaxTouchesPerFrame; ++i)
	{
		float minDist = MAXFLOAT;
		Touch prev = x1[i];
		
		for(int j=0; j < mMaxTouchesPerFrame; ++j)
		{
			Touch curr = x[j];
			if((curr.z > mFilterThreshold) && (prev.z > mFilterThreshold))
			{
				float distToCurrentTouch = cityBlockDistanceXYZ(prev, curr, 20.f);
				if(distToCurrentTouch < minDist)
				{
					forwardMatchIdx[i] = j;
					minDist = distToCurrentTouch;
				}
			}
		}
	}
	
	// for each current touch, find minimum distance to a previous touch
	for(int i=0; i<mMaxTouchesPerFrame; ++i)
	{
		float minDist = MAXFLOAT;
		Touch curr = x[i];
		for(int j=0; j < mMaxTouchesPerFrame; ++j)
		{
			Touch prev = x1[j];
			if((curr.z > mFilterThreshold) && (prev.z > mFilterThreshold))
			{
				float distToPreviousTouch = cityBlockDistanceXYZ(prev, curr, 20.f);
				if(distToPreviousTouch < minDist)
				{
					reverseMatchIdx[i] = j;
					minDist = distToPreviousTouch;
				}
			}
		}
	}
	
	// get mutual matches
	std::array<int, kMaxTouches> mutualMatches;
	mutualMatches.fill(0);
	for(int i=0; i<mMaxTouchesPerFrame; ++i)
	{
		int prevIdx = reverseMatchIdx[i];
		if(prevIdx >= 0)
		{
			if(forwardMatchIdx[prevIdx] == i)
			{
				mutualMatches[i] = true;
			}
		}
	}
	
	std::array<bool, kMaxTouches> currWrittenToNew;
	currWrittenToNew.fill(false);
	
	// first, continue mutually matched  touches
	for(int i=0; i<mMaxTouchesPerFrame; ++i)
	{
		if(mutualMatches[i])
		{
			int j = reverseMatchIdx[i];
			Touch curr = x[i];
			Touch prev = x1[j];
			{
				// touch is continued, mark as connected and write to new touches
				curr.age = (cityBlockDistanceXYZ(prev, curr, 0.f) < kMaxConnectDist);
				newTouches[j] = curr;
				currWrittenToNew[i] = true;
			}
		}
	}
	
	// now take care of any remaining nonzero current touches
	for(int i=0; i<mMaxTouchesPerFrame; ++i)
	{
		Touch curr = x[i];
		if((!currWrittenToNew[i]) && (curr.z > mFilterThreshold))
		{
			int freeIdx = -1;
			float minDist = MAXFLOAT;
			
			// first, try to match same touch index (important for decay!)
			Touch prev = x1[i];
			if(prev.z <= mFilterThreshold)
			{
				freeIdx = i;
			}
			
			// then try closest free touch
			if(freeIdx < 0)
			{
				for(int j=0; j<mMaxTouchesPerFrame; ++j)
				{
					Touch prev = x1[j];
					if(prev.z <= mFilterThreshold)
					{
						float d = cityBlockDistanceXYZ(curr, prev, 0.f);
						if(d < minDist)
						{
							minDist = d;
							freeIdx = j;
						}
					}
				}
			}
			
			// if a free index was found, write the current touch
			if(freeIdx >= 0)
			{
				Touch free = x1[freeIdx];
				curr.age = (cityBlockDistanceXYZ(free, curr, 0.f) < kMaxConnectDist);
				newTouches[freeIdx] = curr;
			}
		}
	}
	
	// fill in any free touches with previous touches at those indices. This will allow old touches to re-link if not reused.
	for(int i=0; i < mMaxTouchesPerFrame; ++i)
	{
		Touch t = newTouches[i];
		if(t.z <= mFilterThreshold)
		{
			newTouches[i].x = (x1[i].x);
			newTouches[i].y = (x1[i].y);
		}
	}
	
	return newTouches;
}

// input: vec4<x, y, z, k> where k is 1 if the touch is connected to the previous touch at the same index.
//
TouchArray TouchTracker::filterTouchesXYAdaptive(const TouchArray& in, const TouchArray& inz1)
{
	// these filter settings have a big and sort of delicate impact on play feel, so they are not user settable
	const float kFixedXYFreqMax = 20.f;
	const float kFixedXYFreqMin = 1.f;
	
	TouchArray out{};
	
	for(int i=0; i<mMaxTouchesPerFrame; ++i)
	{
		float x = in[i].x;
		float y = in[i].y;
		float z = in[i].z;
		int age = in[i].age;
		
		float x1 = inz1[i].x;
		float y1 = inz1[i].y;
		
		// filter, or not, based on w from matchTouches
		float newX, newY;
		if(age > 0)
		{
			// get xy coeffs, adaptive based on z
			float freq = mapAndClipRange(0., 0.02, kFixedXYFreqMin, kFixedXYFreqMax, z);
			float omegaXY = freq*kTwoPi/mSampleRate;
			float kXY = expf(-omegaXY);
			float a0XY = 1.f - kXY;
			float b1XY = kXY;
			
			// onepole filters
			newX = (x*a0XY) + (x1*b1XY);
			newY = (y*a0XY) + (y1*b1XY);
		}
		else
		{
			newX = x;
			newY = y;
		}
		
		out[i] = Touch{.x = newX, .y = newY, .z = z, .age = age};
	}
	
	return out;
}

TouchArray TouchTracker::filterTouchesZ(const TouchArray& in, const TouchArray& inz1, float upFreq, float downFreq)
{
	const float omegaUp = upFreq*kTwoPi/mSampleRate;
	const float kUp = expf(-omegaUp);
	const float a0Up = 1.f - kUp;
	const float b1Up = kUp;
	const float omegaDown = downFreq*kTwoPi/mSampleRate;
	const float kDown = expf(-omegaDown);
	const float a0Down = 1.f - kDown;
	const float b1Down = kDown;
	
	TouchArray out{};
	
	for(int i=0; i<mMaxTouchesPerFrame; ++i)
	{
		float x = in[i].x;
		float y = in[i].y;
		float z = in[i].z;
		
		float z1 = inz1[i].z;
		int age1 = inz1[i].age;
		
		float newZ;
		
		// filter z variable
		float dz = z - z1;
		if(dz > 0.f)
		{
			newZ = (z*a0Up) + (z1*b1Up);
		}
		else
		{
			newZ = (z*a0Down) + (z1*b1Down);
		}
		
		// gate with hysteresis
		bool gate1 = (age1 > 0);
		bool newGate = gate1;
		if(newZ > mOnThreshold)
		{
			newGate = true;
		}
		else if (newZ < mOffThreshold)
		{
			newGate = false;
		}
		
		// increment age
		int newAge = newGate ? (age1 + 1) : 0;
		
		// set state
		int newState = newGate ? (gate1 ? kTouchStateContinue : kTouchStateOn) : (gate1 ? kTouchStateOff : kTouchStateInactive);
		
		out[i] = Touch{.x=x, .y=y, .z=newZ, .dz=dz, .age=newAge, .state=newState};
	}
	
	return out;
}

// if a touch has decayed below the filter threshold after z filtering, move it off the scene so it won't match to other nearby touches.
TouchArray TouchTracker::exileUnusedTouches(const TouchArray& preFiltered, const TouchArray& postFiltered)
{
	TouchArray out(preFiltered);
	for(int i = 0; i < mMaxTouchesPerFrame; ++i)
	{
		Touch a = preFiltered[i];
		Touch b = postFiltered[i];
		
		if(b.x > 0.f)
		{
			if(b.z <= mFilterThreshold)
			{
				a.x = (-1.f);
				a.y = (-10.f);
				a.z = (0.f);
			}
		}
		
		out[i] = a;
	}
	return out;
}

// rotate order of touches, changing order every time there is a new touch in a frame.
// side effect: writes to mRotateShuffleOrder
TouchArray TouchTracker::rotateTouches(const TouchArray& in)
{
	TouchArray touches(in);
	if(mMaxTouchesPerFrame > 1)
	{
		bool doRotate = false;
		for(int i = 0; i < mMaxTouchesPerFrame; ++i)
		{
			if(in[i].age == 1)
			{
				// we have a new touch at index i.
				doRotate = true;
				break;
			}
		}
		
		if(doRotate)
		{
			// rotate the indices of all free or new touches in the shuffle order
			int nFree = 0;
			std::array<int, kMaxTouches> freeIndexes;
			
			for(int i=0; i<mMaxTouchesPerFrame; ++i)
			{
				if((in[i].z < mFilterThreshold) || (in[i].age == 1))
				{
					freeIndexes[nFree++] = i;
				}
			}
			
			if(nFree > 1)
			{
				int first = mRotateShuffleOrder[freeIndexes[0]];
				for(int i=0; i < nFree - 1; ++i)
				{
					mRotateShuffleOrder[freeIndexes[i]] = mRotateShuffleOrder[freeIndexes[i + 1]];
				}
				mRotateShuffleOrder[freeIndexes[nFree - 1]] = first;
			}
		}
		
		// shuffle
		for(int i = 0; i < mMaxTouchesPerFrame; ++i)
		{
			touches[mRotateShuffleOrder[i]] = in[i];
		}
	}
	return touches;
}
Beispiel #4
0
 typename enable_if<is_interval_set<Type>, bool>::type
 is_joinable(typename Type::iterator it_, typename Type::iterator next_, Type* = 0)
 {
     return touches(*it_, *next_);
 }
void SparseTileLayoutData<Dim>::calcGCFillList()
{
  if(!this->initialized() || !this->hasInternalGuards_m)
    return;
  
  this->gcFillList_m.clear();
  gcBorderFillList_m.clear();

  typedef Node<Domain_t,AllocatedDomain_t> NNode_t;
  typedef std::vector<NNode_t>             TouchList_t;
  TouchList_t tlist;

  // first we do the internal overlap regions
  typename List_t::iterator start = this->all_m.begin();
  typename List_t::iterator end = this->all_m.end();

  for ( ; start!=end; ++start)
    {
      touches((*start)->allocated(),
	      std::back_inserter(tlist),
	      TouchesConstructNodeObj());

      // now pack the tlist into the GCFillInfo object
      // The if test is to remove the self-touch entry
      typename TouchList_t::iterator GCLstart = tlist.begin();
      typename TouchList_t::iterator GCLend = tlist.end();
      
      for( ; GCLstart != GCLend ;++GCLstart)
	{
	  if(GCLstart->globalID() == (*start)->globalID()) 
	    {
	      tlist.erase(GCLstart);
	      break;
	    }
	}

      GCLstart = tlist.begin();
      GCLend = tlist.end();
      for ( ; GCLstart!=GCLend ; ++GCLstart )
	{
	  //  removed the external guard layer area. 
	  this->gcFillList_m.push_back(GCFillInfo_t((*GCLstart).domain(),
						    (*GCLstart).globalID(),
						    (*start)->globalID()));
	}
      tlist.clear();
    }

  // Next, generate the list of all the internalGuardLayer
  // regions, and 'subtract' the above list from it to produce
  // a list of internal guard layers that will be filled externally.
 
  std::vector<GCBorderFillInfo> bfv;

  start = this->all_m.begin();
  for ( ; start!=this->all_m.end(); ++start)
    {
      for(int d=0;d<Dim;++d)
	{
	  Domain_t gcdom( (*start)->allocated());
	  
	  int max = (*start)->allocated()[d].last();
	  int min = max - this->internalGuards_m.upper(d) + 1;
	  gcdom[d] = Interval<1>(min, max);
	  gcdom = intersect(this->innerdomain_m,gcdom);
	  if (gcdom.size()>0) 
	    {
	      bfv.push_back(GCBorderFillInfo(gcdom, (*start)->globalID() ));
	    }
	  // now do the other side of this dimension. 
	  gcdom = (*start)->allocated();
	  min = (*start)->allocated()[d].first();
	  max = min + this->internalGuards_m.lower(d) -1;
 	  gcdom[d] = Interval<1>(min, max);
	  gcdom = intersect(this->innerdomain_m,gcdom);
	  
	  if (gcdom.size() > 0)
	  {
	    bfv.push_back(GCBorderFillInfo(gcdom,(*start)->globalID())); 
	  }
	} 
    }

  // remove overlap of GCFillInfo on GCBorderFillInfo
  std::vector<Domain_t> temp2,temp3,temp4;

  std::vector<GCBorderFillInfo> temp;

  BorderFillIterator_t bst = bfv.begin();
  BorderFillIterator_t ben = bfv.end();

  for ( ; bst != ben ; ++bst)
    {
      FillIterator_t gst = this->beginFillList();
      FillIterator_t gen = this->endFillList(); 
      temp2.clear();
      temp2.push_back(bst->domain());
      
      for ( ; gst!=gen ; ++gst )
	{
	  typename std::vector<Domain_t>::iterator ts = temp2.begin();
	  for ( ; ts != temp2.end() ; ++ts )
	    {
	      temp3 = DomainRemoveOverlap(*ts,gst->domain_m);
	      temp4.insert(temp4.end(),temp3.begin(),temp3.end());
	    }
	  temp2 = temp4;
	  temp4.clear();
	}
      
      typename std::vector<Domain_t>::iterator ts = temp2.begin();
      for( ; ts != temp2.end(); ++ts)
	temp.push_back(GCBorderFillInfo(*ts, bst->patchID() ));
    }
  
  //gcBorderFillList_m.clear();
  gcBorderFillList_m = temp;
}
Beispiel #6
0
int NPC_can_walk( NPC* _pNPC, bomb* _pBomb, NPC** _NPCs, int _NPCCount, map* _pMap, int _dir )
{
    // NPC's collide with the map, with other NPCs(not yet) and with the bomb
    switch ( _dir )
    {
        case UP:
        {
            // change NPC direction even if he can't walk
            _pNPC->direction = UP;

            // check if upwards square is a destructible or undestructible block which means NPC can't walk there
            int upwards_square_is_blocked = ( _pMap->map_data[_pNPC->i - 1][_pNPC->j].block_type == DESTRUCTIBLE_BLOCK ||
                _pMap->map_data[_pNPC->i - 1][_pNPC->j].block_type == INDESTRUCTIBLE_BLOCK ) ? 1 : 0;

            int upwards_square_has_bomb = ( (_pNPC->i - 1) == _pBomb->i ) && ( _pNPC->j == _pBomb->j ) ? 1 : 0;

            // if upwards block is des/indes then check if NPC is colliding with or touching upwards block if he isn't, he can walk up
            if ( upwards_square_is_blocked )
            {
                rect NPC    = { _pNPC->left, _pNPC->top, _pNPC->right, _pNPC->bottom };

                rect block  = { _pMap->map_data[_pNPC->i - 1][_pNPC->j].left,
                                _pMap->map_data[_pNPC->i - 1][_pNPC->j].top,
                                _pMap->map_data[_pNPC->i - 1][_pNPC->j].right,
                                _pMap->map_data[_pNPC->i - 1][_pNPC->j].bottom };

                if ( collides( NPC, block ) || touches( NPC, block ) )
                    return 0;
                else
                    return 1;
            }
            else if ( upwards_square_has_bomb && _pBomb->active )
            {
                rect NPC  = { _pNPC->left, _pNPC->top, _pNPC->right, _pNPC->bottom };

                rect bomb = { _pBomb->left, _pBomb->top, _pBomb->right, _pBomb->bottom };

                if ( collides( NPC, bomb ) || touches( NPC, bomb ) )
                    return 0;
                else
                    return 1;

            }
            else
            {
                // left allign NPC if he already isn't
                _pNPC->left = _pMap->map_data[_pNPC->i][_pNPC->j].left;
                return 1;
            }

            break;
        }

        case RIGHT:
        {
            // change NPC direction even if he can't walk
            _pNPC->direction = RIGHT;

            // check if rightmost square is a destructible or undestructible block which means NPC can't walk there
            int rightmost_square_is_blocked = ( _pMap->map_data[_pNPC->i][_pNPC->j + 1].block_type == DESTRUCTIBLE_BLOCK ||
                _pMap->map_data[_pNPC->i][_pNPC->j + 1].block_type == INDESTRUCTIBLE_BLOCK ) ? 1 : 0;

            int rightmost_square_has_bomb = ( _pNPC->i == _pBomb->i ) && ( (_pNPC->j + 1) == _pBomb->j ) ? 1 : 0;

            if ( rightmost_square_is_blocked )
            {
                rect NPC = { _pNPC->left, _pNPC->top, _pNPC->right, _pNPC->bottom };

                rect block  = { _pMap->map_data[_pNPC->i][_pNPC->j + 1].left,
                                _pMap->map_data[_pNPC->i][_pNPC->j + 1].top,
                                _pMap->map_data[_pNPC->i][_pNPC->j + 1].right,
                                _pMap->map_data[_pNPC->i][_pNPC->j + 1].bottom };

                if ( collides( NPC, block ) || touches( NPC, block ) )
                    return 0;
                else
                    return 1;
            }
            else if ( rightmost_square_has_bomb && _pBomb->active )
            {
                rect NPC  = { _pNPC->left, _pNPC->top, _pNPC->right, _pNPC->bottom };

                rect bomb = { _pBomb->left, _pBomb->top, _pBomb->right, _pBomb->bottom };

                if ( collides( NPC, bomb ) || touches( NPC, bomb ) )
                    return 0;
                else
                    return 1;

            }
            else
            {
                // top allign NPC if he already isn't
                _pNPC->top = _pMap->map_data[_pNPC->i][_pNPC->j].top;
                return 1;
            }

            break;
        }

        case DOWN:
        {
            // change NPC direction even if he can't walk
            _pNPC->direction = DOWN;

            // check if downwards square is a destructible or undestructible block which means NPC can't walk there
            int downwards_square_is_blocked = ( _pMap->map_data[_pNPC->i + 1][_pNPC->j].block_type == DESTRUCTIBLE_BLOCK ||
                _pMap->map_data[_pNPC->i + 1][_pNPC->j].block_type == INDESTRUCTIBLE_BLOCK ) ? 1 : 0;

            int downwards_square_has_bomb = ( (_pNPC->i + 1) == _pBomb->i ) && ( _pNPC->j == _pBomb->j ) ? 1 : 0;


            if ( downwards_square_is_blocked )
            {
                rect NPC = { _pNPC->left, _pNPC->top, _pNPC->right, _pNPC->bottom };

                rect block  = { _pMap->map_data[_pNPC->i + 1][_pNPC->j].left,
                                _pMap->map_data[_pNPC->i + 1][_pNPC->j].top,
                                _pMap->map_data[_pNPC->i + 1][_pNPC->j].right,
                                _pMap->map_data[_pNPC->i + 1][_pNPC->j].bottom };

                if ( collides( NPC, block ) || touches( NPC, block ) )
                    return 0;
                else
                    return 1;
            }
            else if ( downwards_square_has_bomb && _pBomb->active )
            {
                rect NPC  = { _pNPC->left, _pNPC->top, _pNPC->right, _pNPC->bottom };

                rect bomb = { _pBomb->left, _pBomb->top, _pBomb->right, _pBomb->bottom };

                if ( collides( NPC, bomb ) || touches( NPC, bomb ) )
                    return 0;
                else
                    return 1;

            }
            else
            {
                // left allign NPC if he already isn't
                _pNPC->left = _pMap->map_data[_pNPC->i][_pNPC->j].left;
                return 1;
            }

            break;
        }

        case LEFT:
        {
            // change NPC direction even if he can't walk
            _pNPC->direction = LEFT;

            // check if leftmost square is a destructible or undestructible block which means NPC can't walk there
            int leftmost_square_is_blocked = ( _pMap->map_data[_pNPC->i][_pNPC->j - 1].block_type == DESTRUCTIBLE_BLOCK ||
                _pMap->map_data[_pNPC->i][_pNPC->j - 1].block_type == INDESTRUCTIBLE_BLOCK ) ? 1 : 0;

            int leftmost_square_has_bomb = ( _pNPC->i == _pBomb->i ) && ( (_pNPC->j - 1) == _pBomb->j ) ? 1 : 0;

            if ( leftmost_square_is_blocked )
            {
                rect NPC = { _pNPC->left, _pNPC->top, _pNPC->right, _pNPC->bottom };

                rect block  = { _pMap->map_data[_pNPC->i][_pNPC->j - 1].left,
                                _pMap->map_data[_pNPC->i][_pNPC->j - 1].top,
                                _pMap->map_data[_pNPC->i][_pNPC->j - 1].right,
                                _pMap->map_data[_pNPC->i][_pNPC->j - 1].bottom };

                if ( collides( NPC, block ) || touches( NPC, block ) )
                    return 0;
                else
                    return 1;
            }
            else if ( leftmost_square_has_bomb && _pBomb->active )
            {
                rect NPC  = { _pNPC->left, _pNPC->top, _pNPC->right, _pNPC->bottom };

                rect bomb = { _pBomb->left, _pBomb->top, _pBomb->right, _pBomb->bottom };

                if ( collides( NPC, bomb ) || touches( NPC, bomb ) )
                    return 0;
                else
                    return 1;

            }
            else
            {
                // top allign NPC if he already isn't
                _pNPC->top = _pMap->map_data[_pNPC->i][_pNPC->j].top;
                return 1;
            }

            break;
        }
    }
}
int UniformGridLayoutData<Dim>::touchesAllocLocal(const OtherDomain &d, OutIter o, 
					          const ConstructTag &ctag) const 
{
  // If there are no internal guard cells, then this calculation is the
  // same as the normal touches calculation.
    
  if (!this->hasInternalGuards_m) return touches(d,o,ctag);
    
  int i, count = 0;

  // Make sure we have a valid touching domain.

  PAssert(this->initialized());
  PAssert(contains(this->domain_m, d));

  // Find the starting and ending grid positions, and store as an
  // Interval.

  Interval<Dim> box = Pooma::NoInit();
  for (i = 0; i < Dim; ++i) 
    {
      int a, b;
        
      // This part is unchanged from touches. What we're going to do
      // here is simply extend the range in each direction by one block
      // and then let the intersection calculation below sort out if
      // there is actually an intersection. Otherwise we'd have to do
      // comparisons on all blocks up here and then still do the
      // intersection on the remaining blocks below. On average, this
      // should be slightly faster I think.
        
      if (!this->hasExternalGuards_m)
	{
	  a = (d[i].min() - this->firsti_m[i]) / blocksizes_m[i];
	  b = (d[i].max() - this->firsti_m[i]) / blocksizes_m[i];
	}
      else
	{
	  // If we're in the lower guards, this will fall
	  // through to give zero.
            
	  a = b = 0;
	  int pos = d[i].min();
	  int last = this->innerdomain_m[i].last();
	  int del = pos - this->firsti_m[i];
            
	  if (del >= 0)
	    if (pos <= last)
	      a = del / blocksizes_m[i];
	    else
	      a = allDomain_m[i].last();
            
	  pos = d[i].max();
	  del = pos - this->firsti_m[i];
            
	  if (del >= 0)
	    if (pos <= last)
	      b = del / blocksizes_m[i];
	    else
	      b = allDomain_m[i].last();
	}
          
      // Now we check that we're not at the ends of the domain for the
      // brick of blocks, and extend the region accordingly.
        
      if (a > 0) --a;
      if (b < allDomain_m[i].last()) ++b;
        
      box[i] = Interval<1>(a, b);
    }

  // Figure the type of the domain resulting from the intersection.

  typedef typename 
    IntersectReturnType<Domain_t,OtherDomain>::Type_t OutDomain_t;
  OutDomain_t outDomain = Pooma::NoInit();

  // Generate the type of the node pushed on the output iterator.

  typedef Node<OutDomain_t,Domain_t> OutNode_t;

  // Iterate through the Interval grid positions.

  typename Interval<Dim>::const_iterator boxiter = box.begin();
    
  while (boxiter != box.end()) 
    {
      // Calculate the linear position of the current node.
        
      int indx = (*boxiter)[0].first();
      for (i = 1; i < Dim; ++i)
	indx += blockstride_m[i] * (*boxiter)[i].first();

      // Get that node, intersect the *allocated* domain with the 
      // requested one, and write the result out to the output iterator.
        
      PAssert(indx >= 0 && indx < this->local_m.size());
        
      outDomain = intersect(d, this->local_m[indx]->allocated());

      // We can no longer assert that outDomain is not empty since
      // we extended the search box without checking. Thus we now 
      // have an if tests around the output.
        
      if (!outDomain.empty())
	{
	  *o = touchesConstruct(outDomain,
				this->local_m[indx]->allocated(),
				this->local_m[indx]->affinity(),
				this->local_m[indx]->context(),
				this->local_m[indx]->globalID(),
				this->local_m[indx]->localID(),
				ctag);
	}

      // Increment output iterator, count, and grid iterator.

      ++o;
      ++count;
      ++boxiter;
    }

  // Return the number of non-empty domains we found.
      
  return count;
}
int player_can_walk( player* _pPlayer, map* _pMap, int _dir )
{
    switch ( _dir )
    {
        case UP:
        {
            // change player direction even if he can't walk
            _pPlayer->direction = UP;

            // check if upwards square is a destructible or undestructible block which means player can't walk there
            int upwards_square_is_blocked = ( _pMap->map_data[_pPlayer->i - 1][_pPlayer->j].block_type == DESTRUCTIBLE_BLOCK ||
                _pMap->map_data[_pPlayer->i - 1][_pPlayer->j].block_type == INDESTRUCTIBLE_BLOCK ) ? 1 : 0;

            // if upwards block is des/indes then check if player is colliding with or touching upwards block if he isn't, he can walk up
            if ( upwards_square_is_blocked )
            {
                rect player = { _pPlayer->left, _pPlayer->top, _pPlayer->right, _pPlayer->bottom };

                rect block  = { _pMap->map_data[_pPlayer->i - 1][_pPlayer->j].left,
                                _pMap->map_data[_pPlayer->i - 1][_pPlayer->j].top,
                                _pMap->map_data[_pPlayer->i - 1][_pPlayer->j].right,
                                _pMap->map_data[_pPlayer->i - 1][_pPlayer->j].bottom };

                if ( collides( player, block ) || touches( player, block ) )
                    return 0;
                else
                    return 1;
            }
            else
            {
                // left allign player if he already isn't
                _pPlayer->left = _pMap->map_data[_pPlayer->i][_pPlayer->j].left;
                return 1;
            }

            break;
        }

        case RIGHT:
        {
            // change player direction even if he can't walk
            _pPlayer->direction = RIGHT;

            // check if rightmost square is a destructible or undestructible block which means player can't walk there
            int rightmost_square_is_blocked = ( _pMap->map_data[_pPlayer->i][_pPlayer->j + 1].block_type == DESTRUCTIBLE_BLOCK ||
                _pMap->map_data[_pPlayer->i][_pPlayer->j + 1].block_type == INDESTRUCTIBLE_BLOCK ) ? 1 : 0;

            if ( rightmost_square_is_blocked )
            {
                rect player = { _pPlayer->left, _pPlayer->top, _pPlayer->right, _pPlayer->bottom };

                rect block  = { _pMap->map_data[_pPlayer->i][_pPlayer->j + 1].left,
                                _pMap->map_data[_pPlayer->i][_pPlayer->j + 1].top,
                                _pMap->map_data[_pPlayer->i][_pPlayer->j + 1].right,
                                _pMap->map_data[_pPlayer->i][_pPlayer->j + 1].bottom };

                if ( collides( player, block ) || touches( player, block ) )
                    return 0;
                else
                    return 1;
            }
            else
            {
                // top allign player if he already isn't
                _pPlayer->top = _pMap->map_data[_pPlayer->i][_pPlayer->j].top;
                return 1;
            }

            break;
        }

        case DOWN:
        {
            // change player direction even if he can't walk
            _pPlayer->direction = DOWN;

            // check if downwards square is a destructible or undestructible block which means player can't walk there
            int downwards_square_is_blocked = ( _pMap->map_data[_pPlayer->i + 1][_pPlayer->j].block_type == DESTRUCTIBLE_BLOCK ||
                _pMap->map_data[_pPlayer->i + 1][_pPlayer->j].block_type == INDESTRUCTIBLE_BLOCK ) ? 1 : 0;


            if ( downwards_square_is_blocked )
            {
                rect player = { _pPlayer->left, _pPlayer->top, _pPlayer->right, _pPlayer->bottom };

                rect block  = { _pMap->map_data[_pPlayer->i + 1][_pPlayer->j].left,
                                _pMap->map_data[_pPlayer->i + 1][_pPlayer->j].top,
                                _pMap->map_data[_pPlayer->i + 1][_pPlayer->j].right,
                                _pMap->map_data[_pPlayer->i + 1][_pPlayer->j].bottom };

                if ( collides( player, block ) || touches( player, block ) )
                    return 0;
                else
                    return 1;
            }
            else
            {
                // left allign player if he already isn't
                _pPlayer->left = _pMap->map_data[_pPlayer->i][_pPlayer->j].left;
                return 1;
            }

            break;
        }

        case LEFT:
        {
            // change player direction even if he can't walk
            _pPlayer->direction = LEFT;

            // check if leftmost square is a destructible or undestructible block which means player can't walk there
            int leftmost_square_is_blocked = ( _pMap->map_data[_pPlayer->i][_pPlayer->j - 1].block_type == DESTRUCTIBLE_BLOCK ||
                _pMap->map_data[_pPlayer->i][_pPlayer->j - 1].block_type == INDESTRUCTIBLE_BLOCK ) ? 1 : 0;

            if ( leftmost_square_is_blocked )
            {
                rect player = { _pPlayer->left, _pPlayer->top, _pPlayer->right, _pPlayer->bottom };

                rect block  = { _pMap->map_data[_pPlayer->i][_pPlayer->j - 1].left,
                                _pMap->map_data[_pPlayer->i][_pPlayer->j - 1].top,
                                _pMap->map_data[_pPlayer->i][_pPlayer->j - 1].right,
                                _pMap->map_data[_pPlayer->i][_pPlayer->j - 1].bottom };

                if ( collides( player, block ) || touches( player, block ) )
                    return 0;
                else
                    return 1;
            }
            else
            {
                // top allign player if he already isn't
                _pPlayer->top = _pMap->map_data[_pPlayer->i][_pPlayer->j].top;
                return 1;
            }

            break;
        }
    }
}