Beispiel #1
0
/////////////////////////////////////////////////////////////////////////////
// Smooth path
/////////////////////////////////////////////////////////////////////////////
void K1999::Smooth(int Step)
{
 int prev = ((Divs - Step) / Step) * Step;
 int prevprev = prev - Step;
 int next = Step;
 int nextnext = next + Step;
 
 assert(prev >= 0);
 //std::cout << Divs << ", " << Step << ", " << prev << ", " << tx.size() << std::endl;
 assert(prev < (int)tx.size());
 assert(prev < (int)ty.size());
 assert(next < (int)tx.size());
 assert(next < (int)ty.size());
 
 for (int i = 0; i <= Divs - Step; i += Step)
 {
  double ri0 = GetRInverse(prevprev, tx[prev], ty[prev], i);
  double ri1 = GetRInverse(i, tx[next], ty[next], nextnext);
  double lPrev = Mag(tx[i] - tx[prev], ty[i] - ty[prev]);
  double lNext = Mag(tx[i] - tx[next], ty[i] - ty[next]);

  double TargetRInverse = (lNext * ri0 + lPrev * ri1) / (lNext + lPrev);

  double Security = lPrev * lNext / (8 * SecurityR);
  AdjustRadius(prev, i, next, TargetRInverse, Security);
 
  prevprev = prev;
  prev = i;
  next = nextnext;
  nextnext = next + Step;
  if (nextnext > Divs - Step)
   nextnext = 0;
 }
}
Beispiel #2
0
static void Smooth(int Step)
{
	int prev = ((nSegments - Step) / Step) * Step;
	int prevprev = prev - Step;
	int next = Step;
	int nextnext = next + Step;

	for (int i = 0; i <= nSegments - Step; i += Step) {
		double ri0 = GetRInverse(prevprev, rlseg[prev].t, i);
		double ri1 = GetRInverse(i, rlseg[next].t, nextnext);
		
		double lPrev = (rlseg[i].t-rlseg[prev].t).len();
		double lNext = (rlseg[i].t-rlseg[next].t).len();
		double TargetRInverse = (lNext * ri0 + lPrev * ri1) / (lNext + lPrev);

		double Security = lPrev * lNext / (8 * SecurityR);
		AdjustRadius(prev, i, next, TargetRInverse, Security);

		prevprev = prev;
		prev = i;
		next = nextnext;
		nextnext = next + Step;
		if (nextnext > nSegments - Step)
			nextnext = 0;
	}
}
Beispiel #3
0
void K1999::CalcRaceLine()
{
	const unsigned int stepsize = 128;
	
	//abort if the track isn't long enough
	if (tx.size() < stepsize)
		return;
	
 //
 // Smoothing loop
 //
 for (int Step = stepsize; (Step /= 2) > 0;)
 {
  for (int i = Iterations * int(sqrt(float(Step))); --i >= 0;)
   Smooth(Step);
  Interpolate(Step);
 }
 
 //
 // Compute curvature along the path
 //
 for (int i = Divs; --i >= 0;)
 {
  int next = (i + 1) % Divs;
  int prev = (i - 1 + Divs) % Divs;

  double rInverse = GetRInverse(prev, tx[i], ty[i], next);
  tRInverse[i] = rInverse;
 }

#ifdef DRAWPATH
 std::ofstream ofs("k1999.path");
 DrawPath(ofs);
#endif
} 
Beispiel #4
0
static void AdjustRadius(int prev, int i, int next, double TargetRInverse, double Security = 0.0)
{
	double OldLane = rlseg[i].lane;

	// Start by aligning points for a reasonable initial lane
	rlseg[i].lane = 
		(-(rlseg[next].t.y - rlseg[prev].t.y) * (rlseg[i].l.x - rlseg[prev].t.x) +
		(  rlseg[next].t.x - rlseg[prev].t.x) * (rlseg[i].l.y - rlseg[prev].t.y)) /
		( (rlseg[next].t.y - rlseg[prev].t.y) * (rlseg[i].r.x - rlseg[i].l.x) -
		(  rlseg[next].t.x - rlseg[prev].t.x) * (rlseg[i].r.y - rlseg[i].l.y));
	if (rlseg[i].lane < -0.2)
		rlseg[i].lane = -0.2;
	else if (rlseg[i].lane > 1.2)
		rlseg[i].lane = 1.2;
	UpdateTxTy(i);

	// Newton-like resolution method
	const double dLane = 0.0001;
	vec2d d = dLane * (rlseg[i].r - rlseg[i].l);
	double dRInverse = GetRInverse(prev, rlseg[i].t + d, next);

	if (dRInverse > 0.000000001) {
		rlseg[i].lane += (dLane / dRInverse) * TargetRInverse;

		double ExtLane = (SideDistExt + Security) / trackWidth;
		double IntLane = (SideDistInt + Security) / trackWidth;
		if (ExtLane > 0.5)
			ExtLane = 0.5;
		if (IntLane > 0.5)
			IntLane = 0.5;

		if (TargetRInverse >= 0.0)
		{
			if (rlseg[i].lane < IntLane)
				rlseg[i].lane = IntLane;
			if (1 - rlseg[i].lane < ExtLane)
			{
				if (1 - OldLane < ExtLane)
					rlseg[i].lane = MIN(OldLane, rlseg[i].lane);
				else
					rlseg[i].lane = 1 - ExtLane;
			}
		}
		else
		{
			if (rlseg[i].lane < ExtLane)
			{
				if (OldLane < ExtLane)
					rlseg[i].lane = MAX(OldLane, rlseg[i].lane);
				else
					rlseg[i].lane = ExtLane;
			}
			if (1 - rlseg[i].lane < IntLane)
				rlseg[i].lane = 1 - IntLane;
		}
	}

	UpdateTxTy(i);
}
Beispiel #5
0
static void StepInterpolate(int iMin, int iMax, int Step)
{
	int next = (iMax + Step) % nSegments;
	if (next > nSegments - Step)
		next = 0;

	int prev = (((nSegments + iMin - Step) % nSegments) / Step) * Step;
	if (prev > nSegments - Step)
		prev -= Step;

	double ir0 = GetRInverse(prev, rlseg[iMin].t, iMax % nSegments);
	double ir1 = GetRInverse(iMin,  rlseg[iMax % nSegments].t, next);
	for (int k = iMax; --k > iMin;) {
		double x = double(k - iMin) / double(iMax - iMin);
		double TargetRInverse = x * ir1 + (1 - x) * ir0;
		AdjustRadius(iMin, k, iMax % nSegments, TargetRInverse);
	}
}
Beispiel #6
0
/////////////////////////////////////////////////////////////////////////////
// Interpolate between two control points
/////////////////////////////////////////////////////////////////////////////
void K1999::StepInterpolate(int iMin, int iMax, int Step)
{
 int next = (iMax + Step) % Divs;
 if (next > Divs - Step)
  next = 0;
 
 int prev = (((Divs + iMin - Step) % Divs) / Step) * Step;
 if (prev > Divs - Step)
  prev -= Step;
 
 double ir0 = GetRInverse(prev, tx[iMin], ty[iMin], iMax % Divs);
 double ir1 = GetRInverse(iMin, tx[iMax % Divs], ty[iMax % Divs], next);
 for (int k = iMax; --k > iMin;)
 {
  double x = double(k - iMin) / double(iMax - iMin);
  double TargetRInverse = x * ir1 + (1 - x) * ir0;
  AdjustRadius(iMin, k, iMax % Divs, TargetRInverse);
 }
}
Beispiel #7
0
/////////////////////////////////////////////////////////////////////////////
// Change lane value to reach a given radius
/////////////////////////////////////////////////////////////////////////////
void K1999::AdjustRadius(int prev, int i, int next, double TargetRInverse, double Security)
{
 double OldLane = tLane[i];

 double Width = Mag((txLeft[i]-txRight[i]),(tyLeft[i]-tyRight[i]));

 //
 // Start by aligning points for a reasonable initial lane
 //
 tLane[i] = (-(ty[next] - ty[prev]) * (txLeft[i] - tx[prev]) +
              (tx[next] - tx[prev]) * (tyLeft[i] - ty[prev])) /
            ( (ty[next] - ty[prev]) * (txRight[i] - txLeft[i]) -
              (tx[next] - tx[prev]) * (tyRight[i] - tyLeft[i]));
 // the original algorithm allows going outside the track 
 /*
 if (tLane[i] < -0.2)
  tLane[i] = -0.2;
 else if (tLane[i] > 1.2)
  tLane[i] = 1.2;
 */
 if (tLane[i] < 0.0)
  tLane[i] = 0.0;
 else if (tLane[i] > 1.0)
  tLane[i] = 1.0;

 UpdateTxTy(i);
 
 //
 // Newton-like resolution method
 //
 const double dLane = 0.0001;
 
 double dx = dLane * (txRight[i] - txLeft[i]);
 double dy = dLane * (tyRight[i] - tyLeft[i]);
 
 double dRInverse = GetRInverse(prev, tx[i] + dx, ty[i] + dy, next);
 
 if (dRInverse > 0.000000001)
 {
  tLane[i] += (dLane / dRInverse) * TargetRInverse;
 
  double ExtLane = (SideDistExt + Security) / Width;
  double IntLane = (SideDistInt + Security) / Width;
  if (ExtLane > 0.5)
   ExtLane = 0.5;
  if (IntLane > 0.5)
   IntLane = 0.5;
 
  if (TargetRInverse >= 0.0)
  {
   if (tLane[i] < IntLane)
    tLane[i] = IntLane;
   if (1 - tLane[i] < ExtLane)
   {
    if (1 - OldLane < ExtLane)
     tLane[i] = Min(OldLane, tLane[i]);
    else
     tLane[i] = 1 - ExtLane;
   }
  }
  else
  {
   if (tLane[i] < ExtLane)
   {
    if (OldLane < ExtLane)
     tLane[i] = Max(OldLane, tLane[i]);
    else
     tLane[i] = ExtLane;
   }
   if (1 - tLane[i] < IntLane)
    tLane[i] = 1 - IntLane;
  }
 }
 
 UpdateTxTy(i);
}