/// <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); }
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); }