From 123aeb323ba700119f23ddbeee62eb6c50464209 Mon Sep 17 00:00:00 2001
From: Markus Quaritsch <markus.quaritsch@tugraz.at>
Date: Thu, 25 Feb 2016 13:08:11 +0100
Subject: [PATCH] refactoring crosswind correction classes:

- separate reader and crosswind airdrag losses
- renaming files
- adapting tests
---
 .../DeclarationDataAdapter.cs                 |  16 +-
 .../EngineeringDataAdapter.cs                 |  20 +-
 .../Data/CrossWindCorrectionCurve.cs          | 171 -----------------
 .../Data/CrossWindCorrectionCurveReader.cs    | 179 ++++++++++++++++++
 .../Data/CrosswindCorrectionCdxALookup.cs     |  57 ++++++
 .../Data/CrosswindCorrectionVAirBeta.cs       |  73 +++++++
 .../Data/ICrossWindCorrection.cs              |   2 +
 .../Data/VAirBetaCrosswindCorrection.cs       | 116 ------------
 VectoCore/VectoCore.csproj                    |   5 +-
 VectoCoreTest/Integration/CoachPowerTrain.cs  |   4 +-
 .../SimulationRuns/FullPowertrain.cs          |   2 +-
 .../SimulationRuns/MinimalPowertrain.cs       |   4 +-
 .../Integration/Truck40tPowerTrain.cs         |   2 +-
 .../Models/Declaration/DeclarationDataTest.cs |   4 +-
 .../Simulation/MeasuredSpeedModeTest.cs       |   3 +-
 .../Models/SimulationComponent/DriverTest.cs  |   2 +-
 .../Models/SimulationComponent/VehicleTest.cs |  31 +--
 17 files changed, 367 insertions(+), 324 deletions(-)
 delete mode 100644 VectoCore/Models/SimulationComponent/Data/CrossWindCorrectionCurve.cs
 create mode 100644 VectoCore/Models/SimulationComponent/Data/CrossWindCorrectionCurveReader.cs
 create mode 100644 VectoCore/Models/SimulationComponent/Data/CrosswindCorrectionCdxALookup.cs
 create mode 100644 VectoCore/Models/SimulationComponent/Data/CrosswindCorrectionVAirBeta.cs
 delete mode 100644 VectoCore/Models/SimulationComponent/Data/VAirBetaCrosswindCorrection.cs

diff --git a/VectoCore/InputData/Reader/DataObjectAdaper/DeclarationDataAdapter.cs b/VectoCore/InputData/Reader/DataObjectAdaper/DeclarationDataAdapter.cs
index 9d694fb158..f18d2a24d7 100644
--- a/VectoCore/InputData/Reader/DataObjectAdaper/DeclarationDataAdapter.cs
+++ b/VectoCore/InputData/Reader/DataObjectAdaper/DeclarationDataAdapter.cs
@@ -87,7 +87,9 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdaper
 				? data.AirDragAreaRigidTruck
 				: data.AirDragArea;
 
-			retVal.CrossWindCorrectionCurve = GetDeclarationAirResistanceCurve(retVal.VehicleCategory, aerodynamicDragAera);
+			retVal.CrossWindCorrectionCurve =
+				new CrosswindCorrectionCdxALookup(GetDeclarationAirResistanceCurve(retVal.VehicleCategory, aerodynamicDragAera),
+					CrossWindCorrectionMode.DeclarationModeCorrection);
 			var axles = data.Axles;
 			if (axles.Count < mission.AxleWeightDistribution.Length) {
 				throw new VectoException("Vehicle does not contain sufficient axles. {0} axles defined, {1} axles required",
@@ -253,12 +255,12 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdaper
 		}
 
 
-		public static CrossWindCorrectionCurve GetDeclarationAirResistanceCurve(VehicleCategory vehicleCategory,
-			SquareMeter aerodynamicDragAera)
+		public static List<CrossWindCorrectionCurveReader.CrossWindCorrectionEntry> GetDeclarationAirResistanceCurve(
+			VehicleCategory vehicleCategory, SquareMeter aerodynamicDragAera)
 		{
 			var values = DeclarationData.AirDrag.Lookup(vehicleCategory);
-			var points = new List<CrossWindCorrectionCurve.CrossWindCorrectionEntry> {
-				new CrossWindCorrectionCurve.CrossWindCorrectionEntry {
+			var points = new List<CrossWindCorrectionCurveReader.CrossWindCorrectionEntry> {
+				new CrossWindCorrectionCurveReader.CrossWindCorrectionEntry {
 					Velocity = 0.SI<MeterPerSecond>(),
 					EffectiveCrossSectionArea = 0.SI<SquareMeter>()
 				}
@@ -281,14 +283,14 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdaper
 //					cdASum += degreeShare * cdA * (vAir * vAir / (vVeh * vVeh)).Cast<Scalar>();
 					cdASum += degreeShare * cdA * ((vAirX * vAirX + vAirY * vAirY) / (vVeh * vVeh)).Cast<Scalar>();
 				}
-				points.Add(new CrossWindCorrectionCurve.CrossWindCorrectionEntry {
+				points.Add(new CrossWindCorrectionCurveReader.CrossWindCorrectionEntry {
 					Velocity = vVeh,
 					EffectiveCrossSectionArea = cdASum
 				});
 			}
 
 			points[0].EffectiveCrossSectionArea = points[1].EffectiveCrossSectionArea;
-			return new CrossWindCorrectionCurve(points, CrossWindCorrectionMode.DeclarationModeCorrection);
+			return points;
 		}
 
 		protected static SquareMeter ComputeDeltaCd(double beta, AirDrag.AirDragEntry values)
diff --git a/VectoCore/InputData/Reader/DataObjectAdaper/EngineeringDataAdapter.cs b/VectoCore/InputData/Reader/DataObjectAdaper/EngineeringDataAdapter.cs
index 808ab0cda8..3f033f1550 100644
--- a/VectoCore/InputData/Reader/DataObjectAdaper/EngineeringDataAdapter.cs
+++ b/VectoCore/InputData/Reader/DataObjectAdaper/EngineeringDataAdapter.cs
@@ -47,21 +47,23 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdaper
 			retVal.DynamicTyreRadius = data.DynamicTyreRadius;
 			switch (data.CrossWindCorrectionMode) {
 				case CrossWindCorrectionMode.NoCorrection:
-					retVal.CrossWindCorrectionCurve = CrossWindCorrectionCurve.GetNoCorrectionCurve(data.AirDragArea);
+					retVal.CrossWindCorrectionCurve =
+						new CrosswindCorrectionCdxALookup(CrossWindCorrectionCurveReader.GetNoCorrectionCurve(data.AirDragArea),
+							CrossWindCorrectionMode.NoCorrection);
 					break;
 				case CrossWindCorrectionMode.SpeedDependentCorrectionFactor:
-					retVal.CrossWindCorrectionCurve =
-						CrossWindCorrectionCurve.ReadSpeedDependentCorrectionCurve(data.CrosswindCorrectionMap,
-							data.AirDragArea);
+					retVal.CrossWindCorrectionCurve = new CrosswindCorrectionCdxALookup(
+						CrossWindCorrectionCurveReader.ReadSpeedDependentCorrectionCurve(data.CrosswindCorrectionMap,
+							data.AirDragArea), CrossWindCorrectionMode.SpeedDependentCorrectionFactor);
 					break;
 				case CrossWindCorrectionMode.VAirBetaLookupTable:
-					var delcEntries = DeclarationDataAdapter.GetDeclarationAirResistanceCurve(retVal.VehicleCategory,
-						data.AirDragArea);
-					retVal.CrossWindCorrectionCurve = new VAirBetaCrosswindCorrection(data.AirDragArea, data.CrosswindCorrectionMap);
+					retVal.CrossWindCorrectionCurve = new CrosswindCorrectionVAirBeta(data.AirDragArea,
+						CrossWindCorrectionCurveReader.ReadCdxABetaTable(data.CrosswindCorrectionMap));
 					break;
 				case CrossWindCorrectionMode.DeclarationModeCorrection:
-					retVal.CrossWindCorrectionCurve = DeclarationDataAdapter.GetDeclarationAirResistanceCurve(retVal.VehicleCategory,
-						data.AirDragArea);
+					retVal.CrossWindCorrectionCurve =
+						new CrosswindCorrectionCdxALookup(DeclarationDataAdapter.GetDeclarationAirResistanceCurve(retVal.VehicleCategory,
+							data.AirDragArea), CrossWindCorrectionMode.DeclarationModeCorrection);
 					break;
 				default:
 					throw new ArgumentOutOfRangeException();
diff --git a/VectoCore/Models/SimulationComponent/Data/CrossWindCorrectionCurve.cs b/VectoCore/Models/SimulationComponent/Data/CrossWindCorrectionCurve.cs
deleted file mode 100644
index 2f8751a005..0000000000
--- a/VectoCore/Models/SimulationComponent/Data/CrossWindCorrectionCurve.cs
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
-* Copyright 2015, 2016 Graz University of Technology,
-* Institute of Internal Combustion Engines and Thermodynamics,
-* Institute of Technical Informatics
-*
-* Licensed under the EUPL (the "Licence");
-* You may not use this work except in compliance with the Licence.
-* You may obtain a copy of the Licence at:
-*
-* http://ec.europa.eu/idabc/eupl
-*
-* Unless required by applicable law or agreed to in writing, software 
-* distributed under the Licence is distributed on an "AS IS" basis,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the Licence for the specific language governing permissions and 
-* limitations under the Licence.
-*/
-
-using System.Collections.Generic;
-using System.Data;
-using System.IO;
-using System.Linq;
-using TUGraz.VectoCore.Exceptions;
-using TUGraz.VectoCore.Models.Simulation.DataBus;
-using TUGraz.VectoCore.Utils;
-
-namespace TUGraz.VectoCore.Models.SimulationComponent.Data
-{
-	public class CrossWindCorrectionCurve : LoggingObject, ICrossWindCorrection
-	{
-		protected List<CrossWindCorrectionEntry> Entries;
-
-		public CrossWindCorrectionMode CorrectionMode { get; internal set; }
-
-		public CrossWindCorrectionCurve(List<CrossWindCorrectionEntry> entries, CrossWindCorrectionMode correctionMode)
-		{
-			CorrectionMode = correctionMode;
-			Entries = entries;
-		}
-
-
-		public static CrossWindCorrectionCurve ReadSpeedDependentCorrectionCurve(DataTable data,
-			SquareMeter aerodynamicDragArea)
-		{
-			return ParseSpeedDependent(data, aerodynamicDragArea);
-		}
-
-		public static CrossWindCorrectionCurve ReadSpeedDependentCorrectionCurveFromStream(Stream inputData,
-			SquareMeter aerodynamicDragArea)
-		{
-			var data = VectoCSVFile.ReadStream(inputData);
-			return ParseSpeedDependent(data, aerodynamicDragArea);
-		}
-
-		public static CrossWindCorrectionCurve ReadSpeedDependentCorrectionFromFile(string fileName,
-			SquareMeter aerodynamicDragArea)
-		{
-			var data = VectoCSVFile.Read(fileName);
-			return ParseSpeedDependent(data, aerodynamicDragArea);
-		}
-
-		protected static CrossWindCorrectionCurve ParseSpeedDependent(DataTable data,
-			SquareMeter aerodynamicDragArea)
-		{
-			if (data.Columns.Count != 2) {
-				throw new VectoException("Crosswind correction file must consist of 2 columns.");
-			}
-			if (data.Rows.Count < 2) {
-				throw new VectoException("Crosswind correction file must consist of at least two entries");
-			}
-
-			if (HeaderIsValid(data.Columns)) {
-				return new CrossWindCorrectionCurve(ReadSpeedDependentFromColumnNames(data, aerodynamicDragArea),
-					CrossWindCorrectionMode.SpeedDependentCorrectionFactor);
-			}
-			Logger<CrossWindCorrectionCurve>()
-				.Warn(
-					"Crosswind correction file: Header line is not valid. Expected: '{0}, {1}', Got: '{2}'. Falling back to column index.",
-					Fields.Velocity, Fields.Cd, ", ".Join(data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse()));
-			return new CrossWindCorrectionCurve(ReadSpeedDependentFromColumnIndizes(data, aerodynamicDragArea),
-				CrossWindCorrectionMode.SpeedDependentCorrectionFactor);
-		}
-
-		protected static List<CrossWindCorrectionEntry> ReadSpeedDependentFromColumnIndizes(DataTable data,
-			SquareMeter aerodynamicDragArea)
-		{
-			return (from DataRow row in data.Rows
-				select new CrossWindCorrectionEntry {
-					Velocity = row.ParseDouble(0).KMPHtoMeterPerSecond(),
-					EffectiveCrossSectionArea = row.ParseDouble(1) * aerodynamicDragArea
-				}).ToList();
-		}
-
-		protected static List<CrossWindCorrectionEntry> ReadSpeedDependentFromColumnNames(DataTable data,
-			SquareMeter aerodynamicDragArea)
-		{
-			return (from DataRow row in data.Rows
-				select new CrossWindCorrectionEntry {
-					Velocity = row.ParseDouble(Fields.Velocity).KMPHtoMeterPerSecond(),
-					EffectiveCrossSectionArea = row.ParseDouble(Fields.Cd) * aerodynamicDragArea
-				}).ToList();
-		}
-
-		private static bool HeaderIsValid(DataColumnCollection columns)
-		{
-			return columns.Contains(Fields.Velocity) && columns.Contains(Fields.Cd);
-		}
-
-		public static CrossWindCorrectionCurve GetNoCorrectionCurve(SquareMeter aerodynamicDragArea)
-		{
-			return new CrossWindCorrectionCurve(new[] {
-				new CrossWindCorrectionEntry {
-					Velocity = 0.KMPHtoMeterPerSecond(),
-					EffectiveCrossSectionArea = aerodynamicDragArea
-				},
-				new CrossWindCorrectionEntry {
-					Velocity = 100.KMPHtoMeterPerSecond(),
-					EffectiveCrossSectionArea = aerodynamicDragArea
-				}
-			}.ToList(), CrossWindCorrectionMode.NoCorrection);
-		}
-
-		public void SetDataBus(IDataBus dataBus) {}
-
-		public Watt AverageAirDragPowerLoss(MeterPerSecond v1, MeterPerSecond v2, Second dt)
-		{
-			var vAverage = (v1 + v2) / 2;
-			var CdA = EffectiveAirDragArea(vAverage);
-			Watt averageAirDragPower;
-			if (v1.IsEqual(v2)) {
-				averageAirDragPower = (Physics.AirDensity / 2.0 * CdA * vAverage * vAverage * vAverage).Cast<Watt>();
-			} else {
-				// compute the average force within the current simulation interval
-				// P(t) = k * CdA * v(t)^3  , v(t) = v0 + a * t  // a != 0, P_avg = 1/T * Integral P(t) dt
-				// => P_avg = (CdA * rho/2)/(4*a * dt) * (v2^4 - v1^4)
-				var acceleration = (v2 - v1) / dt;
-				averageAirDragPower =
-					(Physics.AirDensity / 2.0 * CdA * (v2 * v2 * v2 * v2 - v1 * v1 * v1 * v1) / (4 * acceleration * dt))
-						.Cast<Watt>();
-			}
-			return averageAirDragPower;
-		}
-
-		protected internal SquareMeter EffectiveAirDragArea(MeterPerSecond x)
-		{
-			var p = Entries.GetSection(c => c.Velocity < x);
-
-			if (x < p.Item1.Velocity || p.Item2.Velocity < x) {
-				//Log.Error(_data.CrossWindCorrectionMode == CrossWindCorrectionMode.VAirBetaLookupTable
-				//    ? string.Format("CdExtrapol β = {0}", x)
-				//    : string.Format("CdExtrapol v = {0}", x));
-				Log.Error("CdExtrapol v = {0}", x);
-			}
-
-			return VectoMath.Interpolate(p.Item1.Velocity, p.Item2.Velocity,
-				p.Item1.EffectiveCrossSectionArea, p.Item2.EffectiveCrossSectionArea, x);
-		}
-
-		public class Fields
-		{
-			public static readonly string Velocity = "v";
-			public static readonly string Cd = "Cd";
-		}
-
-		public class CrossWindCorrectionEntry
-		{
-			public SquareMeter EffectiveCrossSectionArea;
-			public MeterPerSecond Velocity;
-		}
-	}
-}
\ No newline at end of file
diff --git a/VectoCore/Models/SimulationComponent/Data/CrossWindCorrectionCurveReader.cs b/VectoCore/Models/SimulationComponent/Data/CrossWindCorrectionCurveReader.cs
new file mode 100644
index 0000000000..6d43d02d46
--- /dev/null
+++ b/VectoCore/Models/SimulationComponent/Data/CrossWindCorrectionCurveReader.cs
@@ -0,0 +1,179 @@
+/*
+* Copyright 2015, 2016 Graz University of Technology,
+* Institute of Internal Combustion Engines and Thermodynamics,
+* Institute of Technical Informatics
+*
+* Licensed under the EUPL (the "Licence");
+* You may not use this work except in compliance with the Licence.
+* You may obtain a copy of the Licence at:
+*
+* http://ec.europa.eu/idabc/eupl
+*
+* Unless required by applicable law or agreed to in writing, software 
+* distributed under the Licence is distributed on an "AS IS" basis,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the Licence for the specific language governing permissions and 
+* limitations under the Licence.
+*/
+
+using System.Collections.Generic;
+using System.Data;
+using System.IO;
+using System.Linq;
+using TUGraz.VectoCore.Exceptions;
+using TUGraz.VectoCore.Utils;
+
+namespace TUGraz.VectoCore.Models.SimulationComponent.Data
+{
+	public class CrossWindCorrectionCurveReader : LoggingObject
+	{
+		public static List<CrossWindCorrectionEntry> GetNoCorrectionCurve(SquareMeter aerodynamicDragArea)
+		{
+			return new[] {
+				new CrossWindCorrectionEntry {
+					Velocity = 0.KMPHtoMeterPerSecond(),
+					EffectiveCrossSectionArea = aerodynamicDragArea
+				},
+				new CrossWindCorrectionEntry {
+					Velocity = 100.KMPHtoMeterPerSecond(),
+					EffectiveCrossSectionArea = aerodynamicDragArea
+				}
+			}.ToList();
+		}
+
+		public static List<CrossWindCorrectionEntry> ReadSpeedDependentCorrectionFromFile(string fileName,
+			SquareMeter aerodynamicDragArea)
+		{
+			var data = VectoCSVFile.Read(fileName);
+			return ParseSpeedDependent(data, aerodynamicDragArea);
+		}
+
+		public static List<CrossWindCorrectionEntry> ReadSpeedDependentCorrectionCurveFromStream(Stream inputData,
+			SquareMeter aerodynamicDragArea)
+		{
+			var data = VectoCSVFile.ReadStream(inputData);
+			return ParseSpeedDependent(data, aerodynamicDragArea);
+		}
+
+		public static List<CrossWindCorrectionEntry> ReadSpeedDependentCorrectionCurve(DataTable data,
+			SquareMeter aerodynamicDragArea)
+		{
+			return ParseSpeedDependent(data, aerodynamicDragArea);
+		}
+
+		public static List<AirDragBetaEntry> ReadCdxABetaTable(DataTable betaTable)
+		{
+			if (betaTable.Columns.Count != 2) {
+				throw new VectoException("VAir/Beta Crosswind Correction must consist of 2 columns");
+			}
+			if (betaTable.Rows.Count < 2) {
+				throw new VectoException("VAir/Beta Crosswind Correction must consist of at least 2 rows");
+			}
+			if (HeaderIsValid(betaTable.Columns)) {
+				return ParseCdxABetaFromColumnNames(betaTable);
+			}
+			Logger<CrossWindCorrectionCurveReader>().Warn("VAir/Beta Crosswind Correction header Line is not valid");
+			return ParseCdxABetaFromColumnIndices(betaTable);
+		}
+
+
+		protected static List<CrossWindCorrectionEntry> ParseSpeedDependent(DataTable data,
+			SquareMeter aerodynamicDragArea)
+		{
+			if (data.Columns.Count != 2) {
+				throw new VectoException("Crosswind correction file must consist of 2 columns.");
+			}
+			if (data.Rows.Count < 2) {
+				throw new VectoException("Crosswind correction file must consist of at least two entries");
+			}
+
+			if (SpeedDependentHeaderIsValid(data.Columns)) {
+				return ParseSpeedDependentFromColumnNames(data, aerodynamicDragArea);
+			}
+			Logger<CrossWindCorrectionCurveReader>()
+				.Warn(
+					"Crosswind correction file: Header line is not valid. Expected: '{0}, {1}', Got: '{2}'. Falling back to column index.",
+					FieldsSpeedDependent.Velocity, FieldsSpeedDependent.Cd,
+					", ".Join(data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse()));
+			return ParseSpeedDependentFromColumnIndizes(data, aerodynamicDragArea);
+		}
+
+		protected static List<CrossWindCorrectionCurveReader.CrossWindCorrectionEntry> ParseSpeedDependentFromColumnIndizes(
+			DataTable data,
+			SquareMeter aerodynamicDragArea)
+		{
+			return (from DataRow row in data.Rows
+				select new CrossWindCorrectionEntry {
+					Velocity = row.ParseDouble(0).KMPHtoMeterPerSecond(),
+					EffectiveCrossSectionArea = row.ParseDouble(1) * aerodynamicDragArea
+				}).ToList();
+		}
+
+		protected static List<CrossWindCorrectionCurveReader.CrossWindCorrectionEntry> ParseSpeedDependentFromColumnNames(
+			DataTable data,
+			SquareMeter aerodynamicDragArea)
+		{
+			return (from DataRow row in data.Rows
+				select new CrossWindCorrectionEntry {
+					Velocity = row.ParseDouble(FieldsSpeedDependent.Velocity).KMPHtoMeterPerSecond(),
+					EffectiveCrossSectionArea = row.ParseDouble(FieldsSpeedDependent.Cd) * aerodynamicDragArea
+				}).ToList();
+		}
+
+		private static bool SpeedDependentHeaderIsValid(DataColumnCollection columns)
+		{
+			return columns.Contains(FieldsSpeedDependent.Velocity) && columns.Contains(FieldsSpeedDependent.Cd);
+		}
+
+		private static List<AirDragBetaEntry> ParseCdxABetaFromColumnIndices(DataTable betaTable)
+		{
+			return (from DataRow row in betaTable.Rows
+				select
+					new AirDragBetaEntry() {
+						Beta = row.ParseDouble(0),
+						DeltaCdA = row.ParseDouble(1).SI<SquareMeter>()
+					}).ToList();
+		}
+
+		private static List<AirDragBetaEntry> ParseCdxABetaFromColumnNames(DataTable betaTable)
+		{
+			return (from DataRow row in betaTable.Rows
+				select
+					new AirDragBetaEntry() {
+						Beta = row.ParseDouble(FieldsCdxABeta.Beta),
+						DeltaCdA = row.ParseDouble(FieldsCdxABeta.DeltaCdxA).SI<SquareMeter>()
+					}).ToList();
+		}
+
+		private static bool HeaderIsValid(DataColumnCollection columns)
+		{
+			return columns.Contains(FieldsCdxABeta.Beta) && columns.Contains(FieldsCdxABeta.DeltaCdxA);
+		}
+
+		private static class FieldsCdxABeta
+		{
+			public const string Beta = "Beta";
+
+			public const string DeltaCdxA = "Delta CdA";
+		}
+
+
+		public class AirDragBetaEntry
+		{
+			public double Beta;
+			public SquareMeter DeltaCdA;
+		}
+
+		public class FieldsSpeedDependent
+		{
+			public static readonly string Velocity = "v";
+			public static readonly string Cd = "Cd";
+		}
+
+		public class CrossWindCorrectionEntry
+		{
+			public SquareMeter EffectiveCrossSectionArea;
+			public MeterPerSecond Velocity;
+		}
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/Models/SimulationComponent/Data/CrosswindCorrectionCdxALookup.cs b/VectoCore/Models/SimulationComponent/Data/CrosswindCorrectionCdxALookup.cs
new file mode 100644
index 0000000000..a2b95cf497
--- /dev/null
+++ b/VectoCore/Models/SimulationComponent/Data/CrosswindCorrectionCdxALookup.cs
@@ -0,0 +1,57 @@
+using System.Collections.Generic;
+using TUGraz.VectoCore.Models.Simulation.DataBus;
+using TUGraz.VectoCore.Utils;
+
+
+namespace TUGraz.VectoCore.Models.SimulationComponent.Data
+{
+	public class CrosswindCorrectionCdxALookup : LoggingObject, ICrossWindCorrection
+	{
+		protected List<CrossWindCorrectionCurveReader.CrossWindCorrectionEntry> Entries;
+
+		public CrosswindCorrectionCdxALookup(List<CrossWindCorrectionCurveReader.CrossWindCorrectionEntry> entries,
+			CrossWindCorrectionMode correctionMode)
+		{
+			CorrectionMode = correctionMode;
+			Entries = entries;
+		}
+
+		public CrossWindCorrectionMode CorrectionMode { get; internal set; }
+
+		public void SetDataBus(IDataBus dataBus) {}
+
+		public Watt AverageAirDragPowerLoss(MeterPerSecond v1, MeterPerSecond v2, Second dt)
+		{
+			var vAverage = (v1 + v2) / 2;
+			var CdA = EffectiveAirDragArea(vAverage);
+			Watt averageAirDragPower;
+			if (v1.IsEqual(v2)) {
+				averageAirDragPower = (Physics.AirDensity / 2.0 * CdA * vAverage * vAverage * vAverage).Cast<Watt>();
+			} else {
+				// compute the average force within the current simulation interval
+				// P(t) = k * CdA * v(t)^3  , v(t) = v0 + a * t  // a != 0, P_avg = 1/T * Integral P(t) dt
+				// => P_avg = (CdA * rho/2)/(4*a * dt) * (v2^4 - v1^4)
+				var acceleration = (v2 - v1) / dt;
+				averageAirDragPower =
+					(Physics.AirDensity / 2.0 * CdA * (v2 * v2 * v2 * v2 - v1 * v1 * v1 * v1) / (4 * acceleration * dt))
+						.Cast<Watt>();
+			}
+			return averageAirDragPower;
+		}
+
+		protected internal SquareMeter EffectiveAirDragArea(MeterPerSecond x)
+		{
+			var p = Entries.GetSection(c => c.Velocity < x);
+
+			if (x < p.Item1.Velocity || p.Item2.Velocity < x) {
+				//Log.Error(_data.CrossWindCorrectionMode == CrossWindCorrectionMode.VAirBetaLookupTable
+				//    ? string.Format("CdExtrapol β = {0}", x)
+				//    : string.Format("CdExtrapol v = {0}", x));
+				Log.Error("CdExtrapol v = {0}", x);
+			}
+
+			return VectoMath.Interpolate(p.Item1.Velocity, p.Item2.Velocity,
+				p.Item1.EffectiveCrossSectionArea, p.Item2.EffectiveCrossSectionArea, x);
+		}
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/Models/SimulationComponent/Data/CrosswindCorrectionVAirBeta.cs b/VectoCore/Models/SimulationComponent/Data/CrosswindCorrectionVAirBeta.cs
new file mode 100644
index 0000000000..5d768d6e0a
--- /dev/null
+++ b/VectoCore/Models/SimulationComponent/Data/CrosswindCorrectionVAirBeta.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using TUGraz.VectoCore.Exceptions;
+using TUGraz.VectoCore.Models.Simulation.DataBus;
+using TUGraz.VectoCore.Utils;
+
+namespace TUGraz.VectoCore.Models.SimulationComponent.Data
+{
+	internal class CrosswindCorrectionVAirBeta : LoggingObject, ICrossWindCorrection
+	{
+		protected SquareMeter AirDragArea { get; set; }
+
+		protected List<CrossWindCorrectionCurveReader.AirDragBetaEntry> AirDragEntries;
+		protected IDataBus DataBus;
+
+		public CrosswindCorrectionVAirBeta(SquareMeter airDragArea,
+			List<CrossWindCorrectionCurveReader.AirDragBetaEntry> entries)
+		{
+			AirDragArea = airDragArea;
+			AirDragEntries = entries;
+		}
+
+		public void SetDataBus(IDataBus dataBus)
+		{
+			DataBus = dataBus;
+		}
+
+		public CrossWindCorrectionMode CorrectionMode
+		{
+			get { return CrossWindCorrectionMode.VAirBetaLookupTable; }
+		}
+
+		public Watt AverageAirDragPowerLoss(MeterPerSecond v1, MeterPerSecond v2, Second dt)
+		{
+			if (DataBus == null) {
+				throw new VectoException("Databus is not set - can't access vAir, beta!");
+			}
+			var vAir = DataBus.CycleData.LeftSample.AirSpeedRelativeToVehicle;
+			var beta = DataBus.CycleData.LeftSample.WindYawAngle;
+
+			// F_air(t) = k * CdA_korr * v_air^2   // assumption: v_air = const for the current interval
+			// P(t) = F_air(t) * v(t) , v(t) = v1 + a * t
+			// P_avg = 1/T * Integral P(t) dt
+			// P_avg = k * CdA_korr * v_air^2 * (v1 + v2) / 2
+			var airDragForce = (AirDragArea + DeltaCdxA(Math.Abs(beta))) * Physics.AirDensity / 2.0 * vAir * vAir;
+			var vAverage = (v1 + v2) / 2;
+
+			return (airDragForce * vAverage).Cast<Watt>();
+		}
+
+		protected SquareMeter DeltaCdxA(double beta)
+		{
+			var idx = FindIndex(beta);
+			return VectoMath.Interpolate(AirDragEntries[idx - 1].Beta, AirDragEntries[idx].Beta, AirDragEntries[idx - 1].DeltaCdA,
+				AirDragEntries[idx].DeltaCdA, beta);
+		}
+
+		protected int FindIndex(double beta)
+		{
+			if (beta < AirDragEntries.First().Beta) {
+				throw new VectoSimulationException("Beta / CdxA Lookup table does not cover beta={0}", beta);
+			}
+			if (beta > AirDragEntries.Last().Beta) {
+				throw new VectoSimulationException("Beta / CdxA Lookup table does not cover beta={0}", beta);
+			}
+			int index;
+			AirDragEntries.GetSection(x => x.Beta < beta, out index);
+			return index + 1;
+		}
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/Models/SimulationComponent/Data/ICrossWindCorrection.cs b/VectoCore/Models/SimulationComponent/Data/ICrossWindCorrection.cs
index 1417240503..e312f9e7ae 100644
--- a/VectoCore/Models/SimulationComponent/Data/ICrossWindCorrection.cs
+++ b/VectoCore/Models/SimulationComponent/Data/ICrossWindCorrection.cs
@@ -10,6 +10,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
 
 		void SetDataBus(IDataBus dataBus);
 
+		CrossWindCorrectionMode CorrectionMode { get; }
+
 		Watt AverageAirDragPowerLoss(MeterPerSecond v1, MeterPerSecond v2, Second dt);
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/Models/SimulationComponent/Data/VAirBetaCrosswindCorrection.cs b/VectoCore/Models/SimulationComponent/Data/VAirBetaCrosswindCorrection.cs
deleted file mode 100644
index adac8e653e..0000000000
--- a/VectoCore/Models/SimulationComponent/Data/VAirBetaCrosswindCorrection.cs
+++ /dev/null
@@ -1,116 +0,0 @@
-using System.Collections.Generic;
-using System.Data;
-using System.Linq;
-using TUGraz.VectoCore.Exceptions;
-using TUGraz.VectoCore.Models.Simulation.DataBus;
-using TUGraz.VectoCore.Utils;
-
-namespace TUGraz.VectoCore.Models.SimulationComponent.Data
-{
-	internal class VAirBetaCrosswindCorrection : LoggingObject, ICrossWindCorrection
-	{
-		protected SquareMeter AirDragArea { get; set; }
-
-		protected List<AirDragBetaEntry> AirDragEntries;
-		protected IDataBus DataBus;
-
-		public VAirBetaCrosswindCorrection(SquareMeter airDragArea, DataTable betaTable)
-		{
-			AirDragArea = airDragArea;
-			if (betaTable.Columns.Count != 2) {
-				throw new VectoException("VAir/Beta Crosswind Correction must consist of 2 columns");
-			}
-			if (betaTable.Rows.Count < 2) {
-				throw new VectoException("VAir/Beta Crosswind Correction must consist of at least 2 rows");
-			}
-			if (HeaderIsValid(betaTable.Columns)) {
-				AirDragEntries = CreateFromColumnNames(betaTable);
-			} else {
-				Log.Warn("VAir/Beta Crosswind Correction header Line is not valid");
-				AirDragEntries = CreateFromColumnIndices(betaTable);
-			}
-		}
-
-		private static List<AirDragBetaEntry> CreateFromColumnIndices(DataTable betaTable)
-		{
-			return (from DataRow row in betaTable.Rows
-				select
-					new AirDragBetaEntry() {
-						Beta = row.ParseDouble(0),
-						DeltaCdA = row.ParseDouble(1).SI<SquareMeter>()
-					}).ToList();
-		}
-
-		private static List<AirDragBetaEntry> CreateFromColumnNames(DataTable betaTable)
-		{
-			return (from DataRow row in betaTable.Rows
-				select
-					new AirDragBetaEntry() {
-						Beta = row.ParseDouble(Fields.Beta),
-						DeltaCdA = row.ParseDouble(Fields.DeltaCdxA).SI<SquareMeter>()
-					}).ToList();
-		}
-
-		private static bool HeaderIsValid(DataColumnCollection columns)
-		{
-			return columns.Contains(Fields.Beta) && columns.Contains(Fields.DeltaCdxA);
-		}
-
-
-		public void SetDataBus(IDataBus dataBus)
-		{
-			DataBus = dataBus;
-		}
-
-		public Watt AverageAirDragPowerLoss(MeterPerSecond v1, MeterPerSecond v2, Second dt)
-		{
-			if (DataBus == null) {
-				throw new VectoException("Databus is not set - can't access vAir, beta!");
-			}
-			var vAir = DataBus.CycleData.LeftSample.AirSpeedRelativeToVehicle;
-			var beta = DataBus.CycleData.LeftSample.WindYawAngle;
-
-			// F_air(t) = k * CdA_korr * v_air^2   // assumption: v_air = const for the current interval
-			// P(t) = F_air(t) * v(t) , v(t) = v1 + a * t
-			// P_avg = 1/T * Integral P(t) dt
-			// P_avg = k * CdA_korr * v_air^2 * (v1 + v2) / 2
-			var airDragForce = (AirDragArea + DeltaCdA(beta)) * Physics.AirDensity / 2.0 * vAir * vAir;
-			var vAverage = (v1 + v2) / 2;
-
-			return (airDragForce * vAverage).Cast<Watt>();
-		}
-
-		protected SquareMeter DeltaCdA(double beta)
-		{
-			var idx = FindIndex(beta);
-			return VectoMath.Interpolate(AirDragEntries[idx - 1].Beta, AirDragEntries[idx].Beta, AirDragEntries[idx - 1].DeltaCdA,
-				AirDragEntries[idx].DeltaCdA, beta);
-		}
-
-		protected int FindIndex(double beta)
-		{
-			if (beta < AirDragEntries.First().Beta) {
-				throw new VectoSimulationException("Beta / CdxA Lookup table does not cover beta={0}", beta);
-			}
-			if (beta > AirDragEntries.Last().Beta) {
-				throw new VectoSimulationException("Beta / CdxA Lookup table does not cover beta={0}", beta);
-			}
-			int index;
-			AirDragEntries.GetSection(x => x.Beta < beta, out index);
-			return index + 1;
-		}
-
-		protected class AirDragBetaEntry
-		{
-			public double Beta;
-			public SquareMeter DeltaCdA;
-		}
-
-		private static class Fields
-		{
-			public const string Beta = "Beta";
-
-			public const string DeltaCdxA = "Delta CdA";
-		}
-	}
-}
\ No newline at end of file
diff --git a/VectoCore/VectoCore.csproj b/VectoCore/VectoCore.csproj
index 6077cd9b67..fce6d8eb75 100644
--- a/VectoCore/VectoCore.csproj
+++ b/VectoCore/VectoCore.csproj
@@ -147,7 +147,8 @@
     <Compile Include="Models\Declaration\VehicleClass.cs" />
     <Compile Include="Models\Declaration\Wheels.cs" />
     <Compile Include="Models\Declaration\WHTCCorrection.cs" />
-    <Compile Include="Models\SimulationComponent\Data\CrossWindCorrectionCurve.cs" />
+    <Compile Include="Models\SimulationComponent\Data\CrosswindCorrectionCdxALookup.cs" />
+    <Compile Include="Models\SimulationComponent\Data\CrossWindCorrectionCurveReader.cs" />
     <Compile Include="Models\SimulationComponent\Data\AuxiliaryData.cs" />
     <Compile Include="Models\SimulationComponent\Data\AuxSupplyPowerReader.cs" />
     <Compile Include="Models\SimulationComponent\Data\AxleGearData.cs" />
@@ -163,7 +164,7 @@
     <Compile Include="Models\LoggingObject.cs" />
     <Compile Include="Models\SimulationComponent\Data\GearboxType.cs" />
     <Compile Include="Models\SimulationComponent\Data\ICrossWindCorrection.cs" />
-    <Compile Include="Models\SimulationComponent\Data\VAirBetaCrosswindCorrection.cs" />
+    <Compile Include="Models\SimulationComponent\Data\CrosswindCorrectionVAirBeta.cs" />
     <Compile Include="Models\SimulationComponent\IAuxiliary.cs" />
     <Compile Include="Models\SimulationComponent\IBrakes.cs" />
     <Compile Include="Models\SimulationComponent\ICombustionEngineIdleController.cs" />
diff --git a/VectoCoreTest/Integration/CoachPowerTrain.cs b/VectoCoreTest/Integration/CoachPowerTrain.cs
index bb74ea31fe..6c4fe406e9 100644
--- a/VectoCoreTest/Integration/CoachPowerTrain.cs
+++ b/VectoCoreTest/Integration/CoachPowerTrain.cs
@@ -160,7 +160,9 @@ namespace TUGraz.VectoCore.Tests.Integration
 				AxleConfiguration = AxleConfiguration.AxleConfig_6x2,
 				//AerodynamicDragAera = 3.2634.SI<SquareMeter>(),
 				//CrossWindCorrectionMode = CrossWindCorrectionMode.NoCorrection,
-				CrossWindCorrectionCurve = CrossWindCorrectionCurve.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()),
+				CrossWindCorrectionCurve =
+					new CrosswindCorrectionCdxALookup(CrossWindCorrectionCurveReader.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()),
+						CrossWindCorrectionMode.NoCorrection),
 				CurbWeight = 15700.SI<Kilogram>(),
 				CurbWeigthExtra = 0.SI<Kilogram>(),
 				Loading = loading,
diff --git a/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs b/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs
index 946f28d8a5..a3370a74c1 100644
--- a/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs
+++ b/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs
@@ -372,7 +372,7 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns
 			};
 			return new VehicleData {
 				AxleConfiguration = AxleConfiguration.AxleConfig_6x2,
-				CrossWindCorrectionCurve = CrossWindCorrectionCurve.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()),
+				CrossWindCorrectionCurve = new CrosswindCorrectionCdxALookup(CrossWindCorrectionCurveReader.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()),CrossWindCorrectionMode.NoCorrection),
 				CurbWeight = 15700.SI<Kilogram>(),
 				CurbWeigthExtra = 0.SI<Kilogram>(),
 				Loading = loading,
diff --git a/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs b/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs
index 114824c837..81b954ece7 100644
--- a/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs
+++ b/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs
@@ -267,7 +267,9 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns
 			};
 			return new VehicleData {
 				AxleConfiguration = AxleConfiguration.AxleConfig_6x2,
-				CrossWindCorrectionCurve = CrossWindCorrectionCurve.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()),
+				CrossWindCorrectionCurve =
+					new CrosswindCorrectionCdxALookup(CrossWindCorrectionCurveReader.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()),
+						CrossWindCorrectionMode.NoCorrection),
 				CurbWeight = 15700.SI<Kilogram>(),
 				CurbWeigthExtra = 0.SI<Kilogram>(),
 				Loading = loading,
diff --git a/VectoCoreTest/Integration/Truck40tPowerTrain.cs b/VectoCoreTest/Integration/Truck40tPowerTrain.cs
index 28b9a3207f..d5512bf3a7 100644
--- a/VectoCoreTest/Integration/Truck40tPowerTrain.cs
+++ b/VectoCoreTest/Integration/Truck40tPowerTrain.cs
@@ -184,7 +184,7 @@ namespace TUGraz.VectoCore.Tests.Integration
 				AxleConfiguration = AxleConfiguration.AxleConfig_4x2,
 				//AerodynamicDragAera = 6.2985.SI<SquareMeter>(),
 				//CrossWindCorrectionMode = CrossWindCorrectionMode.NoCorrection,
-				CrossWindCorrectionCurve = CrossWindCorrectionCurve.GetNoCorrectionCurve(6.2985.SI<SquareMeter>()),
+				CrossWindCorrectionCurve = new CrosswindCorrectionCdxALookup(CrossWindCorrectionCurveReader.GetNoCorrectionCurve(6.2985.SI<SquareMeter>()),CrossWindCorrectionMode.NoCorrection),
 				CurbWeight = 7100.SI<Kilogram>(),
 				CurbWeigthExtra = massExtra,
 				Loading = loading,
diff --git a/VectoCoreTest/Models/Declaration/DeclarationDataTest.cs b/VectoCoreTest/Models/Declaration/DeclarationDataTest.cs
index 5c368bba3e..e85c555577 100644
--- a/VectoCoreTest/Models/Declaration/DeclarationDataTest.cs
+++ b/VectoCoreTest/Models/Declaration/DeclarationDataTest.cs
@@ -152,9 +152,9 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration
 		[TestMethod]
 		public void CrossWindCorrectionTest()
 		{
-			var crossWindCorrectionCurve =
+			var crossWindCorrectionCurve = new CrosswindCorrectionCdxALookup(
 				DeclarationDataAdapter.GetDeclarationAirResistanceCurve(VehicleCategory.Tractor,
-					6.46.SI<SquareMeter>());
+					6.46.SI<SquareMeter>()), CrossWindCorrectionMode.DeclarationModeCorrection);
 
 			var tmp = crossWindCorrectionCurve.EffectiveAirDragArea(0.KMPHtoMeterPerSecond());
 			Assert.AreEqual(8.12204, tmp.Value(), Tolerance);
diff --git a/VectoCoreTest/Models/Simulation/MeasuredSpeedModeTest.cs b/VectoCoreTest/Models/Simulation/MeasuredSpeedModeTest.cs
index c5657d9d8c..0f92d32960 100644
--- a/VectoCoreTest/Models/Simulation/MeasuredSpeedModeTest.cs
+++ b/VectoCoreTest/Models/Simulation/MeasuredSpeedModeTest.cs
@@ -382,7 +382,8 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation
 			var tbl = VectoCSVFile.Read(@"TestData/MeasuredSpeed/VairBeta.vcdb");
 
 			var dataBus = new MockVairVechicleContainer();
-			var vairbeta = new VAirBetaCrosswindCorrection(5.SI<SquareMeter>(), tbl);
+			var vairbeta = new CrosswindCorrectionVAirBeta(5.SI<SquareMeter>(),
+				CrossWindCorrectionCurveReader.ReadCdxABetaTable(tbl));
 			vairbeta.SetDataBus(dataBus);
 
 			var cycleEntry = new DrivingCycleData.DrivingCycleEntry() {
diff --git a/VectoCoreTest/Models/SimulationComponent/DriverTest.cs b/VectoCoreTest/Models/SimulationComponent/DriverTest.cs
index 5b072da8bc..439c2360a5 100644
--- a/VectoCoreTest/Models/SimulationComponent/DriverTest.cs
+++ b/VectoCoreTest/Models/SimulationComponent/DriverTest.cs
@@ -376,7 +376,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 			};
 			return new VehicleData {
 				AxleConfiguration = AxleConfiguration.AxleConfig_4x2,
-				CrossWindCorrectionCurve = CrossWindCorrectionCurve.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()),
+				CrossWindCorrectionCurve = new CrosswindCorrectionCdxALookup(CrossWindCorrectionCurveReader.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()), CrossWindCorrectionMode.NoCorrection),
 				CurbWeight = 15700.SI<Kilogram>(),
 				CurbWeigthExtra = 0.SI<Kilogram>(),
 				Loading = loading,
diff --git a/VectoCoreTest/Models/SimulationComponent/VehicleTest.cs b/VectoCoreTest/Models/SimulationComponent/VehicleTest.cs
index 5a05b1c888..65b28cdfdc 100644
--- a/VectoCoreTest/Models/SimulationComponent/VehicleTest.cs
+++ b/VectoCoreTest/Models/SimulationComponent/VehicleTest.cs
@@ -74,9 +74,9 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 
 			var vehicleData = MockSimulationDataFactory.CreateVehicleDataFromFile(VehicleDataFileTruck);
 			//vehicleData.AerodynamicDragAera = 6.46.SI<SquareMeter>();
-			vehicleData.CrossWindCorrectionCurve =
+			vehicleData.CrossWindCorrectionCurve = new CrosswindCorrectionCdxALookup(
 				DeclarationDataAdapter.GetDeclarationAirResistanceCurve(VehicleCategory.Tractor,
-					6.46.SI<SquareMeter>());
+					6.46.SI<SquareMeter>()), CrossWindCorrectionMode.DeclarationModeCorrection);
 			var vehicle = new Vehicle(container, vehicleData);
 
 			var mockPort = new MockFvOutPort();
@@ -117,9 +117,9 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 			var container = new VehicleContainer();
 
 			var vehicleData = MockSimulationDataFactory.CreateVehicleDataFromFile(VehicleDataFileTruck);
-			vehicleData.CrossWindCorrectionCurve =
+			vehicleData.CrossWindCorrectionCurve = new CrosswindCorrectionCdxALookup(
 				DeclarationDataAdapter.GetDeclarationAirResistanceCurve(VehicleCategory.Tractor,
-					6.2985.SI<SquareMeter>());
+					6.2985.SI<SquareMeter>()), CrossWindCorrectionMode.DeclarationModeCorrection);
 
 			var vehicle = new Vehicle(container, vehicleData);
 
@@ -179,20 +179,29 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 			correctionData.Seek(0, SeekOrigin.Begin);
 
 			var crossSectionArea = 5.19.SI<SquareMeter>();
-			var cwcc = CrossWindCorrectionCurve.ReadSpeedDependentCorrectionCurveFromStream(correctionData, crossSectionArea);
+			var cwcc =
+				new CrosswindCorrectionCdxALookup(
+					CrossWindCorrectionCurveReader.ReadSpeedDependentCorrectionCurveFromStream(correctionData,
+						crossSectionArea), CrossWindCorrectionMode.SpeedDependentCorrectionFactor);
 
-			Assert.AreEqual(crossSectionArea.Value() * 1.173, cwcc.EffectiveAirDragArea(0.KMPHtoMeterPerSecond()).Value(),
+			Assert.AreEqual(crossSectionArea.Value() * 1.173,
+				cwcc.EffectiveAirDragArea(0.KMPHtoMeterPerSecond()).Value(),
 				Tolerance);
-			Assert.AreEqual(crossSectionArea.Value() * 1.173, cwcc.EffectiveAirDragArea(40.KMPHtoMeterPerSecond()).Value(),
+			Assert.AreEqual(crossSectionArea.Value() * 1.173,
+				cwcc.EffectiveAirDragArea(40.KMPHtoMeterPerSecond()).Value(),
 				Tolerance);
-			Assert.AreEqual(crossSectionArea.Value() * 1.173, cwcc.EffectiveAirDragArea(60.KMPHtoMeterPerSecond()).Value(),
+			Assert.AreEqual(crossSectionArea.Value() * 1.173,
+				cwcc.EffectiveAirDragArea(60.KMPHtoMeterPerSecond()).Value(),
 				Tolerance);
-			Assert.AreEqual(crossSectionArea.Value() * 1.109, cwcc.EffectiveAirDragArea(80.KMPHtoMeterPerSecond()).Value(),
+			Assert.AreEqual(crossSectionArea.Value() * 1.109,
+				cwcc.EffectiveAirDragArea(80.KMPHtoMeterPerSecond()).Value(),
 				Tolerance);
-			Assert.AreEqual(crossSectionArea.Value() * 1.075, cwcc.EffectiveAirDragArea(100.KMPHtoMeterPerSecond()).Value(),
+			Assert.AreEqual(crossSectionArea.Value() * 1.075,
+				cwcc.EffectiveAirDragArea(100.KMPHtoMeterPerSecond()).Value(),
 				Tolerance);
 
-			Assert.AreEqual(crossSectionArea.Value() * 1.163, cwcc.EffectiveAirDragArea(62.5.KMPHtoMeterPerSecond()).Value(),
+			Assert.AreEqual(crossSectionArea.Value() * 1.163,
+				cwcc.EffectiveAirDragArea(62.5.KMPHtoMeterPerSecond()).Value(),
 				Tolerance);
 		}
 	}
-- 
GitLab