Code development platform for open source projects from the European Union institutions

Skip to content
Snippets Groups Projects
Commit 0302a94c authored by Michael KRISPER's avatar Michael KRISPER
Browse files

corrected Localization Errors in CSV read/write, minor changes in DelauneyMap

parent cca2e7be
No related branches found
No related tags found
No related merge requests found
......@@ -65,18 +65,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
public class DataBody
{
public class DataFullLoadCurve
{
[JsonProperty(Required = Required.Always)]
public string Gears;
[JsonProperty(Required = Required.Always)]
public string Path;
}
[JsonProperty(Required = Required.Always)]
public IList<DataFullLoadCurve> FullLoadCurves;
[JsonProperty("SavedInDeclMode")]
public bool SavedInDeclarationMode;
......@@ -92,6 +80,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
[JsonProperty(Required = Required.Always)]
public double Inertia;
public class DataFullLoadCurve
{
[JsonProperty(Required = Required.Always)]
public string Path;
[JsonProperty(Required = Required.Always)]
public string Gears;
}
[JsonProperty(Required = Required.Always)]
public IList<DataFullLoadCurve> FullLoadCurves;
[JsonProperty(Required = Required.Always)]
public string FuelMap;
......@@ -190,16 +190,21 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
return combustionEngineData;
}
public string WriteToJson()
public string ToJson()
{
_data.Header.Date = DateTime.Now;
_data.Header.FileVersion = 2;
_data.Header.AppVersion = "3.0.0"; // todo: get current app version!
_data.Header.CreatedBy = ""; // todo: get current user
_data.Body.SavedInDeclarationMode = false; //todo: get declaration mode setting
return JsonConvert.SerializeObject(_data);
return JsonConvert.SerializeObject(_data, Formatting.Indented);
}
public void WriteToFile(string fileName)
{
//todo handle file exceptions
File.WriteAllText(fileName, ToJson());
}
public FullLoadCurve GetFullLoadCurve(uint gear)
{
......
......@@ -14,7 +14,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
/// Columns:
/// * engine speed [1/min]
/// * engine torque [Nm]
/// * Fuel Consumption [g/h]
/// * Fuel Consumption [g/h]
/// </summary>
public class FuelConsumptionMap
{
......@@ -33,18 +33,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
}
private IList<FuelConsumptionEntry> _entries = new List<FuelConsumptionEntry>();
private DelauneyMap _fuelMap = new DelauneyMap();
private FuelConsumptionMap()
{
}
private FuelConsumptionMap() { }
public static FuelConsumptionMap ReadFromFile(string fileName)
{
var fuelConsumptionMap = new FuelConsumptionMap();
var data = VectoCSVReader.Read(fileName);
var data = VectoCSVFile.Read(fileName);
try
{
......@@ -58,8 +54,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
Torque = row.GetDouble(Fields.Torque),
FuelConsumption = row.GetDouble(Fields.FuelConsumption)
};
if (entry.FuelConsumption < 0)
throw new ArgumentOutOfRangeException("FuelConsumption < 0" + data.Rows.IndexOf(row));
fuelConsumptionMap._entries.Add(entry);
fuelConsumptionMap._fuelMap.AddPoint(entry.EngineSpeed, entry.Torque, entry.FuelConsumption);
}
......@@ -75,7 +73,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
}
fuelConsumptionMap._fuelMap.Triangulate();
return fuelConsumptionMap;
}
......
......@@ -39,7 +39,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
public static FullLoadCurve ReadFromFile(string fileName)
{
var fullLoadCurve = new FullLoadCurve();
var data = VectoCSVReader.Read(fileName);
var data = VectoCSVFile.Read(fileName);
fullLoadCurve.entries = new List<FullLoadCurveEntry>();
//todo: catch exceptions if value format is wrong.
......
......@@ -56,7 +56,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
public static List<EngineOnlyDrivingCycle> ReadFromFile(string fileName)
{
var data = VectoCSVReader.Read(fileName);
var data = VectoCSVFile.Read(fileName);
var cycles = new List<EngineOnlyDrivingCycle>();
......
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics.Eventing.Reader;
using System.Reflection;
using TUGraz.VectoCore.Utils;
namespace TUGraz.VectoCore.Models.SimulationComponent.Data
{
......@@ -15,29 +14,45 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
Columns.Add(value.GetName(), value.GetDataType());
}
public ModalResults ReadFromFile(string fileName)
public static ModalResults ReadFromFile(string fileName)
{
var modalResults = new ModalResults();
var data = VectoCSVReader.Read(fileName);
var data = VectoCSVFile.Read(fileName);
foreach (DataRow row in data.Rows)
{
var new_row = modalResults.NewRow();
var newRow = modalResults.NewRow();
foreach (DataColumn col in row.Table.Columns)
{
new_row.SetField(col, row.Field<object>(col));
// In cols FC-AUXc and FC-WHTCc can be a "-"
if ((col.ColumnName == ModalResultField.FCAUXc.GetName() ||
col.ColumnName == ModalResultField.FCWHTCc.GetName()) && row.Field<string>(col) == "-")
continue;
// In col FC can sometimes be a "ERROR"
if (col.ColumnName == ModalResultField.FC.GetName() && row.Field<string>(col) == "ERROR")
continue;
newRow.SetField(col.ColumnName, row.GetDouble(col.ColumnName));
}
modalResults.Rows.Add(new_row);
modalResults.Rows.Add(newRow);
}
modalResults.Load(data.CreateDataReader());
return modalResults;
}
public void WriteToFile(string fileName)
{
VectoCSVFile.Write(fileName, this);
}
}
/// <summary>
/// Enum with field definitions of the Modal Results File (.vmod).
/// </summary>
public enum ModalResultField
{
{
[ModalResultField(typeof(double))] time, // [s] Time step.
[ModalResultField(typeof(double))] n, // [1/min] Engine speed.
[ModalResultField(typeof(double))] Tq_eng, // [Nm] Engine torque.
......@@ -71,7 +86,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
[ModalResultField(typeof(double))] Pgrad, // [kW] Power demand due to road gradient.
[ModalResultField(typeof(double))] Pwheel, // [kW] Total power demand at wheel = sum of rolling, air, acceleration and road gradient resistance.
[ModalResultField(typeof(double))] Pbrake, // [kW] Brake power. Drag power is included in Pe.
//[ModalResultField(typeof(double))] Paux_xxx, // [kW] Power demand of Auxiliary with ID xxx. See also Aux Dialog and Driving Cycle.
//[ModalResultField(typeof(double))] Paux_xxx, // [kW] Power demand of Auxiliary with ID xxx. See also Aux Dialog and Driving Cycle.
[ModalResultField(typeof(double))] TCν, // [-] Torque converter speed ratio
[ModalResultField(typeof(double), "TCµ")] TCmu, // [-] Torque converter torque ratio
[ModalResultField(typeof(double))] TC_M_Out, // [Nm] Torque converter output torque
......@@ -79,19 +94,19 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
}
[AttributeUsage(AttributeTargets.Field)]
class ModalResultFieldAttribute : Attribute
{
internal ModalResultFieldAttribute(Type fieldType, string name=null)
{
FieldType = fieldType;
Name = name;
}
public Type FieldType { get; private set; }
public string Name { get; private set; }
}
[AttributeUsage(AttributeTargets.Field)]
class ModalResultFieldAttribute : Attribute
{
internal ModalResultFieldAttribute(Type fieldType, string name = null)
{
FieldType = fieldType;
Name = name;
}
public Type FieldType { get; private set; }
public string Name { get; private set; }
}
public static class ModalResultFieldExtensions
public static class ModalResultFieldExtensionMethods
{
public static Type GetDataType(this ModalResultField field)
{
......@@ -103,14 +118,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
return GetAttr(field).Name ?? field.ToString();
}
private static ModalResultFieldAttribute GetAttr(ModalResultField field)
{
return (ModalResultFieldAttribute)Attribute.GetCustomAttribute(ForValue(field), typeof (ModalResultFieldAttribute));
}
private static ModalResultFieldAttribute GetAttr(ModalResultField field)
{
return (ModalResultFieldAttribute)Attribute.GetCustomAttribute(ForValue(field), typeof(ModalResultFieldAttribute));
}
private static MemberInfo ForValue(ModalResultField field)
{
return typeof (ModalResultField).GetField(Enum.GetName(typeof (ModalResultField), field));
}
private static MemberInfo ForValue(ModalResultField field)
{
return typeof(ModalResultField).GetField(Enum.GetName(typeof(ModalResultField), field));
}
}
}
using System;
using System.Data;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using TUGraz.VectoCore.Exceptions;
namespace TUGraz.VectoCore.Models.SimulationComponent.Data
{
public static class VectoCSVReader
/// <summary>
/// Class for Reading and Writing VECTO CSV Files.
/// </summary>
/// <remarks>
/// The following format applies to all CSV (Comma-separated values) Input Files used in VECTO:
/// List Separator: Comma ","
/// Decimal-Mark: Dot "."
/// Comments: "#" at the beginning of the comment line. Number and position of comment lines is not limited.
/// Header: One header line (not a comment line) at the beginning of the file.
/// All Combinations between max-format and min-format possible. Only "id"-field is used.
/// max: <id> (name) [unit], <id> (name) [unit], ...
/// min: id,id,...
/// </remarks>
public static class VectoCSVFile
{
private const char Separator = ',';
private const char Comment = '#';
......@@ -18,16 +33,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
/// <param name="fileName"></param>
/// <exception cref="FileIOException"></exception>
/// <returns>A DataTable which represents the CSV File.</returns>
/// <remarks>
/// The following format applies to all CSV (Comma-separated values) Input Files used in VECTO:
/// List Separator: Comma ","
/// Decimal-Mark: Dot "."
/// Comments: "#" at the beginning of the comment line. Number and position of comment lines is not limited.
/// Header: One header line (not a comment line) at the beginning of the file.
/// All Combinations between max-format and min-format possible. Only "id"-field is used.
/// max: <id> (name) [unit], <id> (name) [unit], ...
/// min: id,id,...
/// </remarks>
public static DataTable Read(string fileName)
{
try
......@@ -76,5 +82,20 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
throw new VectoException(string.Format("File {0}: {1}", fileName, e.Message));
}
}
public static void Write(string fileName, DataTable table)
{
StringBuilder sb = new StringBuilder();
var header = table.Columns.Cast<DataColumn>().Select(col => col.ColumnName);
sb.AppendLine(string.Join(", ", header));
foreach (DataRow row in table.Rows)
{
sb.AppendLine(string.Join(", ", row.ItemArray.Select(item => (item is IFormattable) ? ((IFormattable)item).ToString("", CultureInfo.InvariantCulture) : item)));
}
File.WriteAllText(fileName, sb.ToString());
}
}
}
\ No newline at end of file
using System;
using System.Data;
using System.Globalization;
using TUGraz.VectoCore.Exceptions;
namespace TUGraz.VectoCore.Utils
......@@ -17,7 +18,7 @@ namespace TUGraz.VectoCore.Utils
//todo ArgumentNullException?
try
{
return double.Parse(row.Field<string>(columnName));
return double.Parse(row.Field<string>(columnName), CultureInfo.InvariantCulture);
}
catch (IndexOutOfRangeException e)
{
......
......@@ -17,18 +17,17 @@ namespace TUGraz.VectoCore.Utils
public void Triangulate()
{
const int SuperTriangleScalingFactor = 10;
const int superTriangleScalingFactor = 10;
if (_points.Count < 3)
throw new ArgumentException(string.Format("Triangulations needs at least 3 Points. Got {0} Points.", _points.Count));
// The "supertriangle" encompasses all triangulation points.
// This triangle initializes the algorithm and will be removed later.
var max = _points.Select(point => Math.Max(Math.Abs(point.X), Math.Abs(point.Y))).Max();
max *= SuperTriangleScalingFactor;
var superTriangle = new Triangle(new Point(max, 0), new Point(0, max), new Point(-max, -max));
var max = _points.Max(point => Math.Max(Math.Abs(point.X), Math.Abs(point.Y))) * superTriangleScalingFactor;
var superTriangle = new Triangle(new Point(max, 0, 0), new Point(0, max, 0), new Point(-max, -max, 0));
_triangles.Add(superTriangle);
var triangles = new List<Triangle> { superTriangle };
foreach (var point in _points)
{
......@@ -36,38 +35,32 @@ namespace TUGraz.VectoCore.Utils
// If the actual vertex lies inside the circumcircle, then the three edges of the
// triangle are added to the edge buffer and the triangle is removed from list.
var containerTriangles = _triangles.Where(triangle => triangle.ContainsInCircumcircle(point)).ToList();
foreach (var triangle in containerTriangles)
foreach (var containerTriangle in triangles.Where(triangle => triangle.ContainsInCircumcircle(point)).ToList())
{
edges.Add(new Edge(triangle.P1, triangle.P2));
edges.Add(new Edge(triangle.P2, triangle.P3));
edges.Add(new Edge(triangle.P3, triangle.P1));
_triangles.Remove(triangle);
edges.Add(new Edge(containerTriangle.P1, containerTriangle.P2));
edges.Add(new Edge(containerTriangle.P2, containerTriangle.P3));
edges.Add(new Edge(containerTriangle.P3, containerTriangle.P1));
triangles.Remove(containerTriangle);
}
// Remove duplicate edges. This leaves the convex hull of the edges.
// The edges in this convex hull are oriented counterclockwise!
edges = edges.GroupBy(edge => edge)
.Where(group => group.Count() == 1)
.SelectMany(group => group)
.ToList();
var convexHullEdges = edges.GroupBy(edge => edge).Where(group => group.Count() == 1).SelectMany(group => group);
// Generate new counterclockwise oriented triangles filling the "hole" in
// the existing triangulation. These triangles all share the actual vertex.
var counterTriangles = edges.Select(edge => new Triangle(edge.P1, edge.P2, point));
_triangles.AddRange(counterTriangles);
var counterTriangles = convexHullEdges.Select(edge => new Triangle(edge.P1, edge.P2, point));
triangles.AddRange(counterTriangles);
}
// We don't want the supertriangle in the triangulation, so
// remove all triangles sharing a vertex with the supertriangle.
_triangles = _triangles.Where(triangle => !triangle.SharesVertexWith(superTriangle)).ToList();
// Remove all triangles sharing a vertex with the supertriangle.
_triangles = triangles.Where(triangle => !triangle.SharesVertexWith(superTriangle)).ToList();
}
public double Interpolate(double x, double y)
{
var tr = _triangles.FirstOrDefault(triangle => triangle.IsInside(x, y, exact: true)) ??
_triangles.FirstOrDefault(triangle => triangle.IsInside(x, y, exact: false));
var tr = _triangles.Find(triangle => triangle.IsInside(x, y, exact: true)) ??
_triangles.Find(triangle => triangle.IsInside(x, y, exact: false));
if (tr == null)
throw new VectoException("Interpolation failed.");
......@@ -88,19 +81,12 @@ namespace TUGraz.VectoCore.Utils
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Point)obj);
return obj.GetType() == GetType() && Equals((Point)obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = X.GetHashCode();
hashCode = (hashCode * 397) ^ Y.GetHashCode();
hashCode = (hashCode * 397) ^ Z.GetHashCode();
return hashCode;
}
return unchecked((((X.GetHashCode() * 397) ^ Y.GetHashCode()) * 397) ^ Z.GetHashCode());
}
public override string ToString()
......@@ -112,7 +98,7 @@ namespace TUGraz.VectoCore.Utils
public double Y { get; set; }
public double Z { get; set; }
public Point(double x, double y, double z = 0)
public Point(double x, double y, double z)
{
X = x;
Y = y;
......@@ -180,7 +166,7 @@ namespace TUGraz.VectoCore.Utils
public bool IsInside(double x, double y, bool exact = true)
{
var p = new Point(x, y);
var p = new Point(x, y, 0);
var v0 = P3 - P1;
var v1 = P2 - P1;
......@@ -254,8 +240,7 @@ namespace TUGraz.VectoCore.Utils
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((Edge)obj);
return obj.GetType() == GetType() && Equals((Edge)obj);
}
public override int GetHashCode()
......
......@@ -73,7 +73,7 @@
<Compile Include="Models\SimulationComponent\Data\CombustionEngineData.cs" />
<Compile Include="Models\SimulationComponent\Data\Engine\FuelConsumptionMap.cs" />
<Compile Include="Models\SimulationComponent\Data\Engine\FullLoadCurve.cs" />
<Compile Include="Models\SimulationComponent\Data\VectoCSVReader.cs" />
<Compile Include="Models\SimulationComponent\Data\VectoCSVFile.cs" />
<Compile Include="Models\SimulationComponent\ICombustionEngine.cs" />
<Compile Include="Models\Connector\Ports\IInPort.cs" />
<Compile Include="Models\SimulationComponent\IGearbox.cs" />
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment