void CreatePASP(List <PlanningTarget> SpeedTargets)
        {
            List <Rectangle> paspRectangles = new List <Rectangle>();

            if (SpeedTargets.Count == 0)
            {
                goto Exit;
            }
            PlanningTarget prev_pasp       = SpeedTargets[0];
            bool           oth1            = false;
            bool           oth2            = false;
            float          widthFactor     = 1;
            float          allowedSpeedMpS = prev_pasp.TargetSpeedMpS;

            for (int i = 1; i < SpeedTargets.Count; i++)
            {
                PlanningTarget cur  = SpeedTargets[i];
                PlanningTarget prev = SpeedTargets[i - 1];
                if (cur.DistanceToTrainM < 0)
                {
                    continue;
                }
                if (cur.DistanceToTrainM > MaxViewingDistanceM)
                {
                    paspRectangles.Add(new Rectangle(14, 0, (int)(93 * widthFactor), GetPlanningHeight(prev_pasp.DistanceToTrainM) - 15));
                    break;
                }
                if (prev_pasp.TargetSpeedMpS > cur.TargetSpeedMpS && (!oth2 || cur.TargetSpeedMpS == 0))
                {
                    oth1 = true;
                    paspRectangles.Add(new Rectangle(14, GetPlanningHeight(cur.DistanceToTrainM) - 15, (int)(93 * widthFactor), GetPlanningHeight(prev_pasp.DistanceToTrainM) - GetPlanningHeight(cur.DistanceToTrainM)));
                    float v = cur.TargetSpeedMpS / allowedSpeedMpS;
                    if (v > 0.74)
                    {
                        widthFactor = 3.0f / 4;
                    }
                    else if (v > 0.49)
                    {
                        widthFactor = 1.0f / 2;
                    }
                    else
                    {
                        widthFactor = 1.0f / 4;
                    }
                    if (cur.TargetSpeedMpS == 0)
                    {
                        break;
                    }
                    prev_pasp = cur;
                }
                if (oth1 && prev.TargetSpeedMpS < cur.TargetSpeedMpS)
                {
                    oth2 = true;
                }
            }
Exit:
            PASPRectangles = paspRectangles;
        }
        void CreateTargetSpeeds(List <PlanningTarget> speedTargets)
        {
            var speedTargetText     = new List <TextPrimitive>(speedTargets.Count);
            var speedTargetTextures = new List <LocatedTexture>(speedTargets.Count);
            int ld = 0;

            for (int i = 1; i < speedTargets.Count; i++)
            {
                bool overlap = false;
                for (int j = 1; j < speedTargets.Count; j++)
                {
                    if (i != j && CheckTargetOverlap(speedTargets[i], speedTargets[j]))
                    {
                        overlap = true;
                        break;
                    }
                }
                if (overlap)
                {
                    continue;
                }
                PlanningTarget cur  = speedTargets[i];
                PlanningTarget prev = speedTargets[ld];
                if (cur.DistanceToTrainM < 0)
                {
                    continue;
                }
                ld = i;
                bool im = cur.Equals(IndicationMarkerTarget);
                if (cur.DistanceToTrainM > MaxViewingDistanceM)
                {
                    break;
                }
                int    a    = GetPlanningHeight(cur.DistanceToTrainM) - 15;
                string text = ((int)MpS.ToKpH(cur.TargetSpeedMpS)).ToString();
                if (im || prev.TargetSpeedMpS > cur.TargetSpeedMpS || cur.TargetSpeedMpS == 0)
                {
                    speedTargetText.Add(new TextPrimitive(new Point(25, a - 2), im ? ColorYellow : ColorGrey, text, FontTargetSpeed));
                    speedTargetTextures.Add(new LocatedTexture(im ? YellowSpeedReductionTexture : SpeedReductionTexture, 4, a + 7 - 10));
                }
                else
                {
                    speedTargetText.Add(new TextPrimitive(new Point(25, a - 2 - (int)FontHeightTargetSpeed), ColorGrey, text, FontTargetSpeed));
                    speedTargetTextures.Add(new LocatedTexture(SpeedIncreaseTexture, 4, a - 7 - 10));
                }
                if (cur.TargetSpeedMpS == 0)
                {
                    break;
                }
            }
            SpeedTargetText     = speedTargetText;
            SpeedTargetTextures = speedTargetTextures;
        }
        bool CheckTargetOverlap(PlanningTarget cur, PlanningTarget chk)
        {
            int a = GetPlanningHeight(cur.DistanceToTrainM);
            int b = GetPlanningHeight(chk.DistanceToTrainM);

            if (Math.Abs(a - b) > 18)
            {
                return(false);
            }
            if (IndicationMarkerTarget.HasValue)
            {
                if (IndicationMarkerTarget.Value.Equals(chk))
                {
                    return(true);
                }
                if (IndicationMarkerTarget.Value.Equals(cur))
                {
                    return(false);
                }
            }
            return(cur.TargetSpeedMpS > chk.TargetSpeedMpS);
        }