public void CalculateBends() { if (!IsCircular) { return; } Bends = new CircleList <Bend>(); Bend _bend = new Bend(); int BendId = 0; MovingAvgFloat AngleQueue = new MovingAvgFloat(5); _bez = BezierLine.Instance; int XSecCount = XSecs.Count(); Vector3 PrevMid; Vector3 ThisMid; Vector3 NextMid; BendType _bt = BendType.Unknown; BendType _prevbt = BendType.Unknown; int Incr = 1; float AngleThreshold = 1.34f; foreach (XSec X in XSecs) { PrevMid = XSecs.Prev(X).MidPt; ThisMid = X.MidPt; NextMid = XSecs.Next(X).MidPt; float Angle = VectGeom.SignedAngle(ThisMid + ThisMid - PrevMid, ThisMid, NextMid, Vector3.up); float _segDist = Vector3.Distance(ThisMid, NextMid); AngleQueue.Push(Angle); if (Mathf.Abs(AngleQueue.Avg) < AngleThreshold) { _bt = BendType.Straight; } else { _bt = AngleQueue.Avg > 0 ? BendType.Right : BendType.Left; } if (_prevbt == _bt) { _bend.Angle += Angle; } else { if (_prevbt == BendType.Left || _prevbt == BendType.Right) { //Finish off the previous bend if (Mathf.Abs(_bend.Angle) < 15) { //ignore small bends Bends.Remove(_bend); BendId--; } else { //take 2 off cos of moving avg _bend.EndXSec = XSecs[X.Idx - 2]; _bend.EndSegIdx = _bend.EndXSec.Idx; _bend.ApexXSec = XSecs[_bend.StartSegIdx + Mathf.RoundToInt(XSecs.Diff(_bend.StartXSec, _bend.EndXSec) / 2)]; _bend.ApexSegIdx = _bend.ApexXSec.Idx; if (_bend.Type == BendType.Right) { _bend.ApexPos = _bend.ApexXSec.KerbR + (_bend.ApexXSec.KerbL - _bend.ApexXSec.KerbR).normalized; _bend.MinTurninPos = _bend.StartXSec.KerbR + (_bend.StartXSec.KerbL - _bend.StartXSec.KerbR).normalized * (_bend.Concatenated ? 4 : 2); } if (_bend.Type == BendType.Left) { _bend.ApexPos = _bend.ApexXSec.KerbL + (_bend.ApexXSec.KerbR - _bend.ApexXSec.KerbL).normalized; _bend.MinTurninPos = _bend.StartXSec.KerbL + (_bend.StartXSec.KerbR - _bend.StartXSec.KerbL).normalized * (_bend.Concatenated ? 4 : 2); } //Fmax = mv^2/r float c = (_bend.EndSegIdx - _bend.StartSegIdx) * 360 / _bend.Angle; float r = Mathf.Abs(c) / Mathf.PI / 2f; //Debug.Log("Bend" + _bend.BendId + " radius = " + r); _bend.SqrtRad = Mathf.Sqrt(r); } } else { //We might be starting a new bend or carrying n the previous one if (_bt == BendType.Left || _bt == BendType.Right) { bool StartNewBend = true; if (BendId > 0 && X.Idx - Bends[BendId - 1].EndSegIdx < 15 && Bends[BendId - 1].Type == _bt) ///bugbugbug circle bug { //if the bend we've just finished is close to and the same sign as one before //We just carry on with this bend and dont create a new one StartNewBend = false; _bend.Concatenated = true; GameObject.Destroy(GameObject.Find("Turnin" + _bend.BendId)); GameObject.Destroy(GameObject.Find("Apex" + _bend.BendId)); GameObject.Destroy(GameObject.Find("BendStart" + _bend.BendId)); } if (StartNewBend) { //Create a new Bend _bend = new Bend(); _bend.Type = _bt; _bend.Sign = _bt == BendType.Right ? (Int16)1 : (Int16)(-1); _bend.StartXSec = XSecs[X.Idx - 2];//-2 cos of moving avg _bend.StartSegIdx = _bend.StartXSec.Idx; _bend.Angle = Angle; _bend.BendId = BendId; Bends.Add(_bend); BendId++; } } } //****************************************************************************************** } _prevbt = _bt; } //This is the last bend. NOt a brilliant bit but it doesn't crash if (_bt == BendType.Straight) { goto Finalise; } _bend.EndSegIdx = XSecs.Count - 1; _bend.EndXSec = XSecs[_bend.EndSegIdx]; if (_bend.EndSegIdx <= _bend.StartSegIdx && Bends.Count() > 0) { Bends.Remove(_bend); Bends.Last().EndSegIdx = XSecs.Count; } else { _bend.ApexSegIdx = Mathf.RoundToInt((_bend.EndSegIdx + _bend.StartSegIdx) / 2); _bend.ApexXSec = XSecs[_bend.ApexSegIdx]; if (_bend.Type == BendType.Right) { _bend.ApexPos = _bend.ApexXSec.KerbR + (_bend.ApexXSec.KerbL - _bend.ApexXSec.KerbR).normalized; } if (_bend.Type == BendType.Left) { _bend.ApexPos = _bend.ApexXSec.KerbL + (_bend.ApexXSec.KerbR - _bend.ApexXSec.KerbL).normalized; } } Finalise: CalculateTurninAndExitPoints(); PopulateXSecCurrBends(); }