Beispiel #1
0
        public static Dictionary <string, object[]> KinematicEnvelope(
            string[] curveTypes,
            double[] curveRadiuses,
            double[] superElevations,
            string[] curveSides,
            SleeperType sleeperType,
            string SpecificationName,
            string vehicleType,
            string VechileDataFilePath  = "",
            string SpecificationPath    = "",
            bool VerticalTrackTolerance = false)
        {
            int    no      = curveTypes.Count();
            string assPath = Assembly.GetExecutingAssembly().Location;

            if (VechileDataFilePath == "")
            {
                VechileDataFilePath = Path.GetDirectoryName(assPath) + "\\VehicleData.json";
            }

            if (SpecificationPath == "")
            {
                SpecificationPath = Path.GetDirectoryName(assPath) + "\\RailcorpSpecs.json";
            }

            RailSpec specification = LoadSpecs(SpecificationPath);

            if (specification == null)
            {
                return(null);
            }

            TrackSpecs trackSpec = specification.TrackSpecs.Where(x => x.Type == SpecificationName).FirstOrDefault();

            #region get vehicle data from spec and by selection
            List <VehicleData> vehicleDatas = LoadVehicleData(VechileDataFilePath);

            VehicleData vehicleData = null;
            if (vehicleDatas.Select(x => x.VehicleType).ToList().Contains(vehicleType))
            {
                vehicleData = vehicleDatas.Where(x => x.VehicleType == vehicleType).FirstOrDefault();
            }

            //terminate if no vechicle data is load
            if (vehicleData == null)
            {
                return(null);
            }
            #endregion

            Dictionary <string, object[]> output = new Dictionary <string, object[]>();

            object[] staticKE        = new object[no];
            object[] KE1             = new object[no];
            object[] KE2             = new object[no];
            object[] KE3             = new object[no];
            object[] KE4             = new object[no];
            object[] structuralGauge = new object[no];
            object[] warnings        = new object[no];

            for (int i = 0; i < no; i++)
            {
                CurveType cvType   = (CurveType)Enum.Parse(typeof(CurveType), curveTypes[i]);
                CurveSide cvSide   = (CurveSide)Enum.Parse(typeof(CurveSide), curveSides[i]);
                double    cvRadius = curveRadiuses[i];
                double    e        = superElevations[i];

                //calculate each
                Dictionary <string, object> data = KEcalculation.KinematicEnvelopeCal(
                    vehicleData,
                    sleeperType,
                    trackSpec,
                    VerticalTrackTolerance,
                    cvType,
                    cvRadius,
                    e,
                    cvSide);

                if (data != null)
                {
                    staticKE[i]        = data["Static"];
                    KE1[i]             = data["KE1"];
                    KE2[i]             = data["KE2"];
                    KE3[i]             = data["KE3"];
                    KE4[i]             = data["KE4"];
                    structuralGauge[i] = data["Structural Gauge"];
                    warnings[i]        = data["Warnings"];
                }
                else
                {
                    staticKE[i]        = null;
                    KE1[i]             = null;
                    KE2[i]             = null;
                    KE3[i]             = null;
                    KE4[i]             = null;
                    structuralGauge[i] = null;
                    warnings[i]        = null;
                }
            }

            output.Add("KE0 (Static)", staticKE);
            output.Add("KE1 (Body Roll, Positive TT)", KE1);
            output.Add("KE2 (Bounce Positive TT)", KE2);
            output.Add("KE3 (Body Roll Negative TT)", KE3);
            output.Add("KE4 (Bounce, Negative TT)", KE4);
            output.Add("Structural Gauge", structuralGauge);
            output.Add("Warnings", warnings);

            return(output);
        }
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object can be used to retrieve data from input parameters and
        /// to store data in output parameters.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            #region //initiate variables
            List <string> curveTypes      = new List <string>();
            List <double> curveRadiuses   = new List <double>();
            List <double> superElevations = new List <double>();
            List <string> curveSides      = new List <string>();
            SleeperType   sleeperType;
            string        sleeperTypeName        = string.Empty;
            string        SpecificationName      = string.Empty;
            string        vehicleType            = string.Empty;
            string        VechileDataFilePath    = string.Empty;
            string        SpecificationPath      = string.Empty;
            bool          VerticalTrackTolerance = false;
            double        pointTolerance         = 0.001;
            #endregion

            #region get data from input
            DA.GetDataList(0, curveTypes);
            DA.GetDataList(1, curveRadiuses);
            DA.GetDataList(2, superElevations);
            DA.GetDataList(3, curveSides);
            DA.GetData(4, ref sleeperTypeName);
            DA.GetData(5, ref SpecificationName);
            DA.GetData(6, ref vehicleType);
            DA.GetData(7, ref VechileDataFilePath);
            DA.GetData(8, ref SpecificationPath);
            DA.GetData(9, ref VerticalTrackTolerance);
            DA.GetData(10, ref pointTolerance);

            //if no data provided, do not do anything
            if (curveTypes.Count == 0 || curveRadiuses.Count == 0 || superElevations.Count == 0 || curveSides.Count == 0 || string.IsNullOrEmpty(sleeperTypeName) || string.IsNullOrEmpty(SpecificationName) ||
                string.IsNullOrEmpty(vehicleType) || string.IsNullOrEmpty(VechileDataFilePath))
            {
                return;
            }

            //if the sleeper type is not avlid, do not do anything
            try
            {
                sleeperType = (SleeperType)Enum.Parse(typeof(SleeperType), sleeperTypeName.ToUpper());
            }
            catch { return; }

            int    no      = curveTypes.Count;
            string assPath = Assembly.GetExecutingAssembly().Location;

            //use default file, if not given
            if (string.IsNullOrEmpty(VechileDataFilePath))
            {
                VechileDataFilePath = Path.GetDirectoryName(assPath) + "\\VehicleData.json";
            }

            //use default file, if not given
            if (string.IsNullOrEmpty(SpecificationPath))
            {
                SpecificationPath = Path.GetDirectoryName(assPath) + "\\RailcorpSpecs.json";
            }

            //if the file is not found
            if (!File.Exists(VechileDataFilePath))
            {
                return;
            }
            if (!File.Exists(SpecificationPath))
            {
                return;
            }

            RailSpec specification = LoadSpecs(SpecificationPath);
            if (specification == null)
            {
                return;
            }

            TrackSpecs trackSpec = specification.TrackSpecs.Where(x => x.Type == SpecificationName).FirstOrDefault();

            if (trackSpec == null)
            {
                return;
            }
            #endregion

            #region get vehicle data from spec and by selection
            List <VehicleData> vehicleDatas = LoadVehicleData(VechileDataFilePath);

            VehicleData vehicleData = null;
            if (vehicleDatas.Select(x => x.VehicleType).ToList().Contains(vehicleType))
            {
                vehicleData = vehicleDatas.Where(x => x.VehicleType == vehicleType).FirstOrDefault();
            }

            //terminate if no vechicle data is load
            if (vehicleData == null)
            {
                return;
            }
            #endregion

            List <Polyline> staticKE_pl        = new List <Polyline>();
            List <Polyline> KE1_pl             = new List <Polyline>();
            List <Polyline> KE2_pl             = new List <Polyline>();
            List <Polyline> KE3_pl             = new List <Polyline>();
            List <Polyline> KE4_pl             = new List <Polyline>();
            List <Polyline> structuralGauge_pl = new List <Polyline>();
            List <string>   warnings           = new List <string>();

            for (int i = 0; i < no; i++)
            {
                CurveType cvType = CurveType.CURVE;
                CurveSide cvSide = CurveSide.NONE;
                try
                {
                    cvType = (CurveType)Enum.Parse(typeof(CurveType), curveTypes[i].ToUpper());
                }
                catch
                {
                    warnings.Add("Curve Type string is not valid. It must be 'Curve' or 'Tagent'");
                    continue;
                }

                try
                {
                    cvSide = (CurveSide)Enum.Parse(typeof(CurveSide), curveSides[i].ToUpper());
                }
                catch
                {
                    warnings.Add("Curve Type Side is not valid. It must be 'Left' or 'Right'");
                    continue;
                }

                double cvRadius = curveRadiuses[i];
                double e        = superElevations[i];

                //calculate each
                Dictionary <string, object> data = KEcalculation.KinematicEnvelopeCal(
                    vehicleData,
                    sleeperType,
                    trackSpec,
                    VerticalTrackTolerance,
                    cvType,
                    cvRadius,
                    e,
                    cvSide);

                if (data != null)
                {
                    double[][] _KE0     = (double[][])data["Static"];           //data unit is mm
                    double[][] _ke1     = (double[][])data["KE1"];              //data unit is mm
                    double[][] _ke2     = (double[][])data["KE2"];              //data unit is mm
                    double[][] _ke3     = (double[][])data["KE3"];              //data unit is mm
                    double[][] _ke4     = (double[][])data["KE4"];              //data unit is mm
                    double[][] _ke5     = (double[][])data["Structural Gauge"]; //data unit is mm
                    string[]   _warning = (string[])data["Warnings"];

                    List <Point3d> staticKE        = new List <Point3d>();
                    List <Point3d> KE1             = new List <Point3d>();
                    List <Point3d> KE2             = new List <Point3d>();
                    List <Point3d> KE3             = new List <Point3d>();
                    List <Point3d> KE4             = new List <Point3d>();
                    List <Point3d> structuralGauge = new List <Point3d>();
                    List <Point3d> pts             = new List <Point3d>();

                    for (int n = 0; n < _KE0[0].Count(); n++)
                    {
                        Point3d pt = new Point3d(_KE0[0][n] / 1000, _KE0[1][n] / 1000, 0);
                        staticKE.Add(pt);
                    }
                    pts = Point3d.CullDuplicates(staticKE, pointTolerance).ToList();
                    pts.Add(new Point3d(_KE0[0][0] / 1000, _KE0[1][0] / 1000, 0));
                    Polyline pl = new Polyline(pts);
                    staticKE_pl.Add(pl);

                    for (int n = 0; n < _ke1[0].Count(); n++)
                    {
                        Point3d pt = new Point3d(_ke1[0][n] / 1000, _ke1[1][n] / 1000, 0);
                        KE1.Add(pt);
                    }
                    pts = Point3d.CullDuplicates(KE1, pointTolerance).ToList();
                    pts.Add(new Point3d(_ke1[0][0] / 1000, _ke1[1][0] / 1000, 0));
                    pl = new Polyline(pts);
                    KE1_pl.Add(pl);

                    for (int n = 0; n < _ke2[0].Count(); n++)
                    {
                        Point3d pt = new Point3d(_ke2[0][n] / 1000, _ke2[1][n] / 1000, 0);
                        KE2.Add(pt);
                    }
                    pts = Point3d.CullDuplicates(KE2, pointTolerance).ToList();
                    pts.Add(new Point3d(_ke2[0][0] / 1000, _ke2[1][0] / 1000, 0));
                    pl = new Polyline(pts);
                    KE2_pl.Add(pl);

                    for (int n = 0; n < _ke3[0].Count(); n++)
                    {
                        Point3d pt = new Point3d(_ke3[0][n] / 1000, _ke3[1][n] / 1000, 0);
                        KE3.Add(pt);
                    }
                    pts = Point3d.CullDuplicates(KE3, pointTolerance).ToList();
                    pts.Add(new Point3d(_ke3[0][0] / 1000, _ke3[1][0] / 1000, 0));//add the first point
                    pl = new Polyline(pts);
                    KE3_pl.Add(pl);

                    for (int n = 0; n < _ke4[0].Count(); n++)
                    {
                        Point3d pt = new Point3d(_ke4[0][n] / 1000, _ke4[1][n] / 1000, 0);
                        KE4.Add(pt);
                    }
                    pts = Point3d.CullDuplicates(KE4, pointTolerance).ToList();
                    pts.Add(new Point3d(_ke4[0][0] / 1000, _ke4[1][0] / 1000, 0));//add the first point
                    pl = new Polyline(pts);
                    KE4_pl.Add(pl);

                    for (int n = 0; n < _ke5[0].Count(); n++)
                    {
                        Point3d pt = new Point3d(_ke5[0][n] / 1000, _ke5[1][n] / 1000, 0);
                        structuralGauge.Add(pt);
                    }
                    pts = Point3d.CullDuplicates(structuralGauge, pointTolerance).ToList();
                    pts.Add(new Point3d(_ke5[0][0] / 1000, _ke5[1][0] / 1000, 0));//add the first point
                    pl = new Polyline(pts);
                    structuralGauge_pl.Add(pl);

                    warnings.AddRange(_warning.ToList());
                }
                else
                {
                    staticKE_pl[i]        = null;
                    KE1_pl[i]             = null;
                    KE2_pl[i]             = null;
                    KE3_pl[i]             = null;
                    KE4_pl[i]             = null;
                    structuralGauge_pl[i] = null;
                    warnings[i]           = null;
                }
            }

            DA.SetDataList(0, staticKE_pl);
            DA.SetDataList(1, KE1_pl);
            DA.SetDataList(2, KE2_pl);
            DA.SetDataList(3, KE3_pl);
            DA.SetDataList(4, KE4_pl);
            DA.SetDataList(5, structuralGauge_pl);
            DA.SetDataList(6, warnings);
        }
        /// <summary>
        /// Refresh the data in the main report
        /// the calculation is based on excel calculation sheet KE_Calculator_v2.3.xlsm (7/03/2013)
        /// </summary>
        public static Dictionary <string, object> KinematicEnvelopeCal(
            VehicleData vehicleData,
            SleeperType sleeperType,
            TrackSpecs trackSpec,
            bool VerticalTrackTolerance,
            CurveType curveType,
            double curveRadius,
            double e,
            CurveSide curveSide)
        {
            #region properties
            _Superelevation = e;
            _WarningMegs    = new List <string>();
            #endregion

            #region load specification => track constants

            if (trackSpec == null)
            {
                return(null);
            }

            //get the properties from spec
            _LateralToleranceTang  = trackSpec.LateralTangentTolerance;
            _LateralToleranceCurve = trackSpec.LateralCurveTolerance;
            _RailWearLateral       = trackSpec.RailWearLateral;
            _SuperTolerance        = trackSpec.SuperTolerance;

            /////?========================????????? Calculations => G6, G7
            if (VerticalTrackTolerance == true)
            {
                _VerticalTolerancePos = trackSpec.VerticalTrackTolerancePositive;
                _VerticalToleranceNeg = trackSpec.VerticalTrackToleranceNegative;
            }
            else
            {
                _VerticalTolerancePos = 0;
                _VerticalToleranceNeg = 0;
            }

            //load vehicle data for parameters
            GetVehicleData(vehicleData);

            //provide warning if superelecation > 20 in tangent
            //Calculation G10
            if (curveType == CurveType.TANGENT && _Superelevation > _MaxSuperOnTangentAllowed)
            {
                _WarningMegs.Add("Superelevation is greater than 20.");
                //_LataralRailTolerance = trackSpec.LateralTangentTolerance;
            }
            else
            {
                _WarningMegs.Add("");
                //_LataralRailTolerance = trackSpec.LateralCurveTolerance;
            }

            _RailCentres = _TrackGauge + 70;
            _SuperElevationRunningEdge = _Superelevation * _TrackGauge / _RailCentres;

            if (curveSide == CurveSide.NONE)
            {
                _RotAngToSuper = 0;
                //_AngleToSuperDeg = 0;
            }
            else if (curveSide == CurveSide.LEFT)
            {
                _RotAngToSuper = Math.Asin(_SuperElevationRunningEdge / _TrackGauge);
            }
            else
            {
                _RotAngToSuper = -Math.Asin(_SuperElevationRunningEdge / _TrackGauge);
            }

            _SuperToleranceRunningEdge = Math.Round(_SuperTolerance * (_TrackGauge / _RailCentres), 4);
            _RotAngleToSuperTolRad     = Math.Round(Math.Asin((_SuperTolerance * _TrackGauge / _RailCentres) / _TrackGauge), 8);
            //_RotationToSuperDeg = Math.Round(DataConvert.RadToDeg( _RotAngleToSuperTolRad), 8);

            if (curveSide == CurveSide.LEFT)
            {
                _xValueLowRail = -_TrackGauge / 2;
            }
            else if (curveSide == CurveSide.RIGHT)
            {
                _xValueLowRail = _TrackGauge / 2;
            }
            #endregion

            double x1 = _SuperElevationRunningEdge * Math.Tan(_RotAngToSuper / 2); //x' //Calculation => F22
            double y1 = x1 * _SuperElevationRunningEdge / _TrackGauge;             //y' //Calculation => G22
            _noOfPoint = _HorizontalData.Count;                                    //number of profile points

            #region define variables
            double alphaRad;
            double alphaDeg;

            List <double> deltaX = new List <double>();
            List <double> deltaY = new List <double>();
            //List<double> _xFirst = new List<double>();
            //List<double> _yFirst = new List<double>();
            List <double> _deltaX1 = new List <double>();
            List <double> _deltaY1 = new List <double>();
            List <double> _tetaRad = new List <double>();
            List <double> _tetaDeg = new List <double>();

            List <double> xFirstList = new List <double>();
            List <double> yFirstList = new List <double>();
            List <double> x2List     = new List <double>();
            List <double> y2List     = new List <double>();
            List <double> x3List     = new List <double>();
            List <double> y3List     = new List <double>();
            //List<double> x3NegList = new List<double>();
            //List<double> y3NegList = new List<double>();
            List <double> x4List = new List <double>();
            List <double> y4List = new List <double>();
            //List<double> x4NegList = new List<double>();
            //List<double> y4NegList = new List<double>();
            List <double> centreThrowList             = new List <double>();
            List <double> endThrowList                = new List <double>();
            List <double> x5List                      = new List <double>();
            List <double> y5List                      = new List <double>();
            List <double> x5NegList                   = new List <double>();
            List <double> y5NegList                   = new List <double>();
            List <double> xpList                      = new List <double>();
            List <double> ypList                      = new List <double>();
            List <double> xpNegList                   = new List <double>();
            List <double> ypNegList                   = new List <double>();
            List <double> RList                       = new List <double>();
            List <double> RNegList                    = new List <double>();
            List <double> bodyRollTetaRadList         = new List <double>();
            List <double> bodyRollTetaDegList         = new List <double>();
            List <double> bodyRollTetaRadNegList      = new List <double>();
            List <double> bodyRollTetaDegNegList      = new List <double>();
            List <double> bodyRollTetaFirstRadList    = new List <double>();
            List <double> bodyRollTetaFirstDegList    = new List <double>();
            List <double> bodyRollTetaFirstRadNegList = new List <double>();
            List <double> bodyRollTetaFirstDegNegList = new List <double>();
            List <double> bodyRollx                   = new List <double>();
            List <double> bodyRolly                   = new List <double>();
            List <double> bodyRollNegx                = new List <double>();
            List <double> bodyRollNegy                = new List <double>();
            List <double> bounceTetaRadList           = new List <double>();
            List <double> bounceTetaDegList           = new List <double>();
            //List<double> bounceTetaRadNegList = new List<double>();
            //List<double> bounceTetaDegNegList = new List<double>();
            List <double> bounceListx = new List <double>();
            List <double> bounceListy = new List <double>();
            //List<double> bounceListNegx = new List<double>();
            //List<double> bounceListNegy = new List<double>();

            #region Static Envelop
            List <double> staticKEx = new List <double>();
            List <double> staticKEy = new List <double>();
            double[][]    staticKE  = new double[2][];
            #endregion

            #region KE1 Body Roll Positive TT
            List <double> KE1_x = new List <double>();
            List <double> KE1_y = new List <double>();
            double[][]    KE1   = new double[2][];
            #endregion

            #region KE2 (Bounce Positive TT)
            List <double> KE2_x = new List <double>();
            List <double> KE2_y = new List <double>();
            double[][]    KE2   = new double[2][];
            #endregion

            #region KE3 Body Roll Negative TT
            List <double> KE3_x = new List <double>();
            List <double> KE3_y = new List <double>();
            double[][]    KE3   = new double[2][];
            #endregion

            #region KE4 (Bounce Negative TT)
            List <double> KE4_x = new List <double>();
            List <double> KE4_y = new List <double>();
            double[][]    KE4   = new double[2][];
            #endregion

            #region structural gauge
            List <double> structuralGaugeX = new List <double>();
            List <double> structuralGaugeY = new List <double>();
            double[][]    structuralGauge  = new double[2][];
            #endregion

            double centreThrow = 0;
            double endThrow    = 0;
            #endregion

            for (int i = 0; i < _noOfPoint; i++)
            {
                #region Superelevation
                //H22
                double dx = ((_TrackGauge / 2 - _HorizontalData[i]) / _TrackGauge) * x1 + _VerticalData[i] * Math.Sin(_RotAngToSuper);
                //I22
                double dy = 0;

                if (_Superelevation != 0)
                {
                    dy = (_TrackGauge / 2 - _HorizontalData[i]) * Math.Sin(_RotAngToSuper) - y1 * (_VerticalData[i] / _SuperElevationRunningEdge);
                }

                deltaX.Add(dx);
                deltaY.Add(dy);

                //J22
                double x_1 = _xValueLowRail + (_HorizontalData[i] - _xValueLowRail) * Math.Cos(_RotAngToSuper) - (_VerticalData[i] - _yValueLowRail) * Math.Sin(_RotAngToSuper);
                //K22
                double y_1 = _yValueLowRail + (_HorizontalData[i] - _xValueLowRail) * Math.Sin(_RotAngToSuper) + (_VerticalData[i] - _yValueLowRail) * Math.Cos(_RotAngToSuper);

                staticKEx.Add(x_1);
                staticKEy.Add(y_1);

                //N22
                if (i < _noOfPoint / 2)
                {
                    alphaRad = _RotAngToSuper + _RotAngleToSuperTolRad;
                }
                else
                {
                    alphaRad = _RotAngToSuper - _RotAngleToSuperTolRad;
                }
                //O22
                alphaDeg = DataConvert.RadToDeg(alphaRad);

                double xFirst = 0; //P22 (x')
                double yFirst = 0; //Q22 (y')
                //P22
                if (i < _noOfPoint / 2)
                {
                    xFirst = (_SuperTolerance * _TrackGauge / 1505) * Math.Tan(_RotAngleToSuperTolRad / 2);
                }
                else
                {
                    xFirst = (_SuperTolerance * _TrackGauge / 1505) * Math.Tan(-_RotAngleToSuperTolRad / 2);
                }
                //Q22
                yFirst = xFirst * (_SuperTolerance * _TrackGauge / 1505) / _TrackGauge;

                xFirstList.Add(xFirst);
                yFirstList.Add(yFirst);

                double deltaX1 = 0; //R22
                double deltaY1 = 0; //S22
                if (i < _noOfPoint / 2)
                {
                    deltaX1 = ((_TrackGauge / 2 - x_1) / _TrackGauge) * -xFirst + y_1 * Math.Sin(_RotAngleToSuperTolRad);
                    deltaY1 = (_TrackGauge / 2 - x_1) * Math.Sin(0) + yFirst * y_1 / ((_SuperTolerance * _TrackGauge / 1505));
                }
                else
                {
                    deltaX1 = ((_TrackGauge / 2 - x_1) / _TrackGauge) * -xFirst + y_1 * Math.Sin(-_RotAngleToSuperTolRad);
                    deltaY1 = (_TrackGauge / 2 - x_1) * Math.Sin(0) - yFirst * y_1 / ((_SuperTolerance * _TrackGauge / 1505));
                }

                _deltaX1.Add(deltaX1);
                _deltaY1.Add(deltaY1);
                //A value is always null in the Excel spreadsheet

                #endregion

                #region Super Tolerance Case Generation
                double x2; //T22
                double y2; //U22

                if (_Superelevation == 0)
                {
                    x2 = GetSuperToleranceCase(_HorizontalData[i], _VerticalData[i], i)[0];
                    y2 = GetSuperToleranceCase(_HorizontalData[i], _VerticalData[i], i)[1];
                }
                else
                {
                    if (i < _noOfPoint / 2)
                    {
                        x2 = _xValueLowRail + (x_1 - _xValueLowRail) * Math.Cos(_RotAngleToSuperTolRad) - (y_1 - _yValueLowRail) * Math.Sin(_RotAngleToSuperTolRad);
                        y2 = _yValueLowRail + (x_1 - _xValueLowRail) * Math.Sin(_RotAngleToSuperTolRad) + (y_1 - _yValueLowRail) * Math.Cos(_RotAngleToSuperTolRad);
                    }
                    else
                    {
                        x2 = _xValueLowRail + (x_1 - _xValueLowRail) * Math.Cos(-_RotAngleToSuperTolRad) - (y_1 - _yValueLowRail) * Math.Sin(-_RotAngleToSuperTolRad);
                        y2 = _yValueLowRail + (x_1 - _xValueLowRail) * Math.Sin(-_RotAngleToSuperTolRad) + (y_1 - _yValueLowRail) * Math.Cos(-_RotAngleToSuperTolRad);
                    }
                }
                x2List.Add(x2);
                y2List.Add(y2);
                #endregion

                //factor
                int factor = 1;
                if (i >= _noOfPoint / 2)
                {
                    factor = -1;
                }

                #region Lateral Track Tolerance - Positive Vertical Track Tolerance
                double x3;//V22
                if (_Superelevation == 0 || curveRadius > _MaxRadius)
                {
                    x3 = x2 - _LateralToleranceTang * factor;
                }
                else
                {
                    x3 = x2 - _LateralToleranceCurve * factor;
                }
                double y3 = y2 + _VerticalTolerancePos;//W22

                x3List.Add(x3);
                y3List.Add(y3);
                #endregion

                #region Negative Vertical Track Tolerance
                //W55
                double y3Neg = y2 - _VerticalToleranceNeg;
                #endregion

                #region Vehicle Tolerance (Lateral Track + Bogie Wear)
                double tetaRad = -alphaRad;                     //X22
                double tetaDeg = DataConvert.RadToDeg(tetaRad); //Y22

                _tetaRad.Add(tetaRad);
                _tetaDeg.Add(tetaDeg);

                //Z22
                double x4 = x3 - (_RollingStockLateralTolerance + _RailWearLateral) * Math.Cos(tetaRad) * factor;
                //Y22
                double y4 = y3 + (_RollingStockLateralTolerance + _RailWearLateral) * Math.Sin(tetaRad) * factor;

                x4List.Add(x4);
                y4List.Add(y4);
                #endregion

                #region Negative Vehicle Tolerance (Lateral Track + Bogie Wear)
                //Z55
                double x4Neg = x3 - (_RollingStockLateralTolerance + _RailWearLateral) * Math.Cos(tetaRad) * factor;
                //Y55
                double y4Neg = y3Neg + (_RollingStockLateralTolerance + _RailWearLateral) * Math.Sin(tetaRad) * factor;
                #endregion

                #region Centre / End Throw
                if (curveRadius != 0)
                {
                    centreThrow = Math.Pow(_BogieCentres, 2) / (8 * curveRadius * 1000);                                        //ESC-215 (12.2.1)
                    endThrow    = Math.Pow(_VehicleLength, 2) / ((8 * curveRadius * 1000) + (4 * _VehicleWidth)) - centreThrow; //ESC-215 (12.2.1)
                }
                else
                {
                    centreThrow = 0;
                    endThrow    = 0;
                }

                centreThrowList.Add(centreThrow);
                endThrowList.Add(endThrow);

                double x5    = 0; //AD22
                double y5    = 0; //AE22
                double x5Neg = 0; //AD55
                double y5Neg = 0; //AE55

                ////// ====================================> this part is in doubt, should question the
                if (curveSide == CurveSide.RIGHT)
                {
                    if (i < _noOfPoint / 2)
                    {
                        x5    = x4 - endThrow * Math.Cos(tetaRad) * factor;
                        y5    = y4 + endThrow * Math.Sin(tetaRad) * factor;
                        x5Neg = x4Neg - endThrow * Math.Cos(tetaRad) * factor;
                        y5Neg = y4Neg + endThrow * Math.Sin(tetaRad) * factor;
                    }
                    else
                    {
                        x5    = x4 - centreThrow * Math.Cos(tetaRad) * factor;
                        y5    = y4 + centreThrow * Math.Sin(tetaRad) * factor;
                        x5Neg = x4Neg - centreThrow * Math.Cos(tetaRad) * factor;
                        y5Neg = y4Neg + centreThrow * Math.Sin(tetaRad) * factor;
                    }
                }
                else
                {
                    if (i < _noOfPoint / 2)
                    {
                        x5    = x4 - centreThrow * Math.Cos(tetaRad) * factor;
                        y5    = y4 + centreThrow * Math.Sin(tetaRad) * factor;
                        x5Neg = x4Neg - centreThrow * Math.Cos(tetaRad) * factor;
                        y5Neg = y4Neg + centreThrow * Math.Sin(tetaRad) * factor;
                    }
                    else
                    {
                        x5    = x4 - endThrow * Math.Cos(tetaRad) * factor;
                        y5    = y4 + endThrow * Math.Sin(tetaRad) * factor;
                        x5Neg = x4Neg - endThrow * Math.Cos(tetaRad) * factor;
                        y5Neg = y4Neg + endThrow * Math.Sin(tetaRad) * factor;
                    }
                }

                x5List.Add(x5);
                y5List.Add(y5);
                x5NegList.Add(x5Neg);
                y5NegList.Add(y5Neg);
                #endregion
            }

            for (int i = 0; i < _noOfPoint; i++)
            {
                #region Maximum Vehicle Body Roll
                double xp    = 0; //AF22
                double yp    = 0; //AG22
                double x     = 0; //AM22
                double y     = 0; //AN22
                double x6    = 0; //AO22
                double y6    = 0; //AN22
                double x7    = 0; //AQ22
                double y7    = 0; //AR22
                double xpNeg = 0; //AF55
                double ypNeg = 0; //AG55
                double xNeg  = 0; //AM55
                double yNeg  = 0; //AN55
                double x6Neg = 0; //AO55
                double y6Neg = 0; //AN55
                double x7Neg = 0; //AQ55
                double y7Neg = 0; //AR55

                if (i < _noOfPoint / 2)
                {
                    xp    = x5List[i] - x5List[0];
                    yp    = y5List[i] - y5List[0];
                    xpNeg = x5NegList[i] - x5List[0];
                    ypNeg = y5NegList[i] - y5List[0];
                }
                else
                {
                    xp    = x5List[i] - x5List[_HorizontalData.Count - 1];
                    yp    = y5List[i] - y5List[_HorizontalData.Count - 1];
                    xpNeg = x5NegList[i] - x5List[_HorizontalData.Count - 1];
                    ypNeg = y5NegList[i] - y5List[_HorizontalData.Count - 1];
                }

                xpList.Add(xp);
                ypList.Add(yp);
                xpNegList.Add(xpNeg);
                ypNegList.Add(ypNeg);

                //AH23
                double R = Math.Sqrt(Math.Pow(xp, 2) + Math.Pow(yp, 2));
                //AH56
                double RNeg = Math.Sqrt(Math.Pow(xpNeg, 2) + Math.Pow(ypNeg, 2));
                RList.Add(R);
                RNegList.Add(RNeg);

                //AI23
                double tetaRad = Math.Asin(yp / R);
                //AI56
                double tetaNegRad = Math.Asin(ypNeg / RNeg);
                //AU23
                double tetaDeg = DataConvert.RadToDeg(tetaRad);
                //AU56
                double tetaNegDeg = DataConvert.RadToDeg(tetaNegRad);

                bodyRollTetaDegList.Add(tetaDeg);
                bodyRollTetaRadList.Add(tetaRad);
                bodyRollTetaDegNegList.Add(tetaNegDeg);
                bodyRollTetaRadNegList.Add(tetaNegRad);

                //AK23
                double tetaFirstDeg = tetaDeg - _MaxBodyRollDeg;
                //AK56
                double tetaFirstNegDeg = tetaNegDeg - _MaxBodyRollDeg;
                //AL23
                double tetaFirstRad = DataConvert.DegToRad(tetaFirstDeg);
                //AL56
                double tetaFirstNegRad = DataConvert.DegToRad(tetaFirstNegDeg);

                bodyRollTetaFirstDegList.Add(tetaFirstDeg);
                bodyRollTetaFirstRadList.Add(tetaFirstRad);
                bodyRollTetaFirstDegNegList.Add(tetaFirstNegDeg);
                bodyRollTetaFirstRadNegList.Add(tetaFirstNegRad);

                if (xp < 0)
                {
                    x = -R *Math.Cos(tetaFirstRad);
                }
                else
                {
                    x = R * Math.Cos(tetaFirstRad);
                }
                y = R * Math.Sin(tetaFirstRad);

                if (xpNeg < 0)
                {
                    xNeg = -RNeg *Math.Cos(tetaFirstNegRad);
                }
                else
                {
                    xNeg = RNeg * Math.Cos(tetaFirstNegRad);
                }
                yNeg = RNeg * Math.Sin(tetaFirstNegRad);

                bodyRollx.Add(x);
                bodyRolly.Add(y);
                bodyRollNegx.Add(xNeg);
                bodyRollNegy.Add(yNeg);

                if (i < _noOfPoint / 2)
                {
                    x6    = x5List[0] + (x5List[i] - x5List[0]) * Math.Cos(_MaxBodyRollRad) - (y5List[i] - y5List[0]) * Math.Sin(_MaxBodyRollRad);
                    y6    = y5List[0] + (x5List[i] - x5List[0]) * Math.Sin(_MaxBodyRollRad) + (y5List[i] - y5List[0]) * Math.Cos(_MaxBodyRollRad);
                    x6Neg = x5NegList[0] + (x5NegList[i] - x5NegList[0]) * Math.Cos(_MaxBodyRollRad) - (y5NegList[i] - y5NegList[0]) * Math.Sin(_MaxBodyRollRad);
                    y6Neg = y5NegList[0] + (x5NegList[i] - x5NegList[0]) * Math.Sin(_MaxBodyRollRad) + (y5NegList[i] - y5NegList[0]) * Math.Cos(_MaxBodyRollRad);
                }
                else
                {
                    x6    = x5List[x5List.Count - 1] + (x5List[i] - x5List[x5List.Count - 1]) * Math.Cos(-_MaxBodyRollRad) - (y5List[i] - y5List[y5List.Count - 1]) * Math.Sin(-_MaxBodyRollRad);
                    y6    = y5List[y5List.Count - 1] + (x5List[i] - x5List[x5List.Count - 1]) * Math.Sin(-_MaxBodyRollRad) + (y5List[i] - y5List[y5List.Count - 1]) * Math.Cos(-_MaxBodyRollRad);
                    x6Neg = x5NegList[x5NegList.Count - 1] + (x5NegList[i] - x5NegList[x5NegList.Count - 1]) * Math.Cos(-_MaxBodyRollRad) - (y5NegList[i] - y5NegList[y5NegList.Count - 1]) * Math.Sin(-_MaxBodyRollRad);
                    y6Neg = y5NegList[y5NegList.Count - 1] + (x5NegList[i] - x5NegList[x5NegList.Count - 1]) * Math.Sin(-_MaxBodyRollRad) + (y5NegList[i] - y5NegList[y5NegList.Count - 1]) * Math.Cos(-_MaxBodyRollRad);
                }

                KE1_x.Add(x6);
                KE1_y.Add(y6);

                KE3_x.Add(x6Neg);
                KE3_y.Add(y6Neg);
                #endregion

                #region Bounce
                double tetaBounceRad = 0; //AS23
                double tetaBounceDeg = 0; //AT23
                double xFirstBounce  = 0; //AU23
                double yFirstBounce  = 0; //AV23

                if (i < _noOfPoint / 2)
                {
                    tetaBounceRad = _tetaRad[i] - _MaxBodyRollRad;
                    tetaBounceDeg = DataConvert.RadToDeg(tetaBounceRad);
                    xFirstBounce  = _Bounce * Math.Sin(tetaBounceRad);
                    yFirstBounce  = _Bounce * Math.Cos(tetaBounceRad);
                }
                else
                {
                    tetaBounceDeg = 90 - _tetaDeg[i] - _MaxBodyRollDeg;
                    tetaBounceRad = DataConvert.DegToRad(tetaBounceDeg);
                    xFirstBounce  = _Bounce * Math.Cos(tetaBounceRad);
                    yFirstBounce  = _Bounce * Math.Sin(tetaBounceRad);
                }

                bounceTetaRadList.Add(tetaBounceRad);
                bounceTetaDegList.Add(tetaBounceDeg);
                bounceListx.Add(xFirstBounce);
                bounceListy.Add(yFirstBounce);

                x7    = x6 + xFirstBounce;    //AW23
                y7    = y6 + yFirstBounce;    //AX23
                x7Neg = x6Neg + xFirstBounce; //AW56
                y7Neg = y6Neg + yFirstBounce; //AX56

                KE2_x.Add(x7);
                KE2_y.Add(y7);

                KE4_x.Add(x7Neg);
                KE4_y.Add(y7Neg);
                #endregion
            }

            #region Calculate Structural Gauge
            //y coordinate
            structuralGaugeY.Add(0);
            structuralGaugeY.Add(3800);
            structuralGaugeY.Add(4670 + _Superelevation * 1.2);
            structuralGaugeY.Add(4670 + _Superelevation * 1.2);
            structuralGaugeY.Add(3800);
            structuralGaugeY.Add(0);

            // x coordinate
            if (_Superelevation == 0)
            {
                structuralGaugeX.Add(-(2060 + endThrow));
                structuralGaugeX.Add(-(2060 + endThrow));
                structuralGaugeX.Add(-(1525 + endThrow));
                structuralGaugeX.Add(1525 + endThrow);
                structuralGaugeX.Add(2060 + endThrow);
                structuralGaugeX.Add(2060 + endThrow);
            }
            else
            {
                if (curveSide == CurveSide.LEFT)
                {
                    structuralGaugeX.Add(-(2060 + endThrow + _Superelevation * 3800 / _TrackGauge));
                    structuralGaugeX.Add(-(2060 + endThrow + _Superelevation * 3800 / _TrackGauge));
                    structuralGaugeX.Add(-(1525 + endThrow + _Superelevation * (double)structuralGaugeY[2] / _TrackGauge));
                    structuralGaugeX.Add((1525 + endThrow - _Superelevation * (double)structuralGaugeY[3] / _TrackGauge));
                    structuralGaugeX.Add(2060 + endThrow - _Superelevation * 3800 / _TrackGauge);
                    structuralGaugeX.Add(2060 + endThrow - _Superelevation * 3800 / _TrackGauge);
                }
                else if (curveSide == CurveSide.RIGHT)
                {
                    structuralGaugeX.Add(-(2060 + endThrow - _Superelevation * 3800 / _TrackGauge));
                    structuralGaugeX.Add(-(2060 + endThrow - _Superelevation * 3800 / _TrackGauge));
                    structuralGaugeX.Add(-(1525 + endThrow - _Superelevation * (double)structuralGaugeY[2] / _TrackGauge));
                    structuralGaugeX.Add((1525 + endThrow + _Superelevation * (double)structuralGaugeY[3] / _TrackGauge));
                    structuralGaugeX.Add(2060 + endThrow + _Superelevation * 3800 / _TrackGauge);
                    structuralGaugeX.Add(2060 + endThrow + _Superelevation * 3800 / _TrackGauge);
                }
            }
            #endregion

            #region Output //remove the first and last item in the output list
            //Static KE
            List <double> container = new List <double>();
            container = staticKEx;
            container.RemoveAt(_noOfPoint - 1);
            container.RemoveAt(0);
            staticKE[0] = container.ToArray();

            container = new List <double>();
            container = staticKEy;
            container.RemoveAt(_noOfPoint - 1);
            container.RemoveAt(0);
            staticKE[1] = container.ToArray();

            //KE1
            container = new List <double>();
            container = KE1_x;
            container.RemoveAt(_noOfPoint - 1);
            container.RemoveAt(0);
            KE1[0] = container.ToArray();

            container = new List <double>();
            container = KE1_y;
            container.RemoveAt(_noOfPoint - 1);
            container.RemoveAt(0);
            KE1[1] = container.ToArray();

            //KE2
            container = new List <double>();
            container = KE2_x;
            container.RemoveAt(_noOfPoint - 1);
            container.RemoveAt(0);
            KE2[0] = container.ToArray();

            container = new List <double>();
            container = KE2_y;
            container.RemoveAt(_noOfPoint - 1);
            container.RemoveAt(0);
            KE2[1] = container.ToArray();

            //KE3
            container = new List <double>();
            container = KE3_x;
            container.RemoveAt(_noOfPoint - 1);
            container.RemoveAt(0);
            KE3[0] = container.ToArray();

            container = new List <double>();
            container = KE3_y;
            container.RemoveAt(_noOfPoint - 1);
            container.RemoveAt(0);
            KE3[1] = container.ToArray();

            //KE4
            container = new List <double>();
            container = KE4_x;
            container.RemoveAt(_noOfPoint - 1);
            container.RemoveAt(0);
            KE4[0] = container.ToArray();

            container = new List <double>();
            container = KE4_y;
            container.RemoveAt(_noOfPoint - 1);
            container.RemoveAt(0);
            KE4[1] = container.ToArray();

            //Structural Gauge
            structuralGauge[0] = structuralGaugeX.ToArray();
            structuralGauge[1] = structuralGaugeY.ToArray();

            //warning message
            //string[][] warnings = new string[1][];
            //warnings[0] = _WarningMegs.ToArray();
            #endregion

            #region output as dictionary
            Dictionary <string, object> keyValuePairs = new Dictionary <string, object>();
            keyValuePairs.Add("Static", staticKE);
            keyValuePairs.Add("KE1", KE1);
            keyValuePairs.Add("KE2", KE2);
            keyValuePairs.Add("KE3", KE3);
            keyValuePairs.Add("KE4", KE4);
            keyValuePairs.Add("Structural Gauge", structuralGauge);
            keyValuePairs.Add("Warnings", _WarningMegs.ToArray());
            #endregion

            return(keyValuePairs);
        }