Code development platform for open source projects from the European Union institutions :large_blue_circle: EU Login authentication by SMS will be completely phased out by mid-2025. To see alternatives please check here

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

VectoMath Interpolate Extensions; AggressiveInlining of Methods added; DebuggerStepThrough added

parent cab06e01
No related branches found
No related tags found
No related merge requests found
......@@ -30,6 +30,7 @@
*/
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using TUGraz.VectoCommon.Utils;
......@@ -66,16 +67,19 @@ namespace TUGraz.VectoCommon.Models
}
}
[DebuggerStepThrough]
public static string ShortName(this GearboxType type)
{
return type.ToString();
}
[DebuggerStepThrough]
public static bool AutomaticTransmission(this GearboxType type)
{
return type == GearboxType.ATPowerSplit || type == GearboxType.ATSerial;
}
[DebuggerStepThrough]
public static bool ManualTransmission(this GearboxType type)
{
return type == GearboxType.MT || type == GearboxType.AMT;
......
......@@ -34,6 +34,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
namespace TUGraz.VectoCommon.Utils
{
......@@ -59,19 +60,22 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="other">The other.</param>
/// <param name="tolerance">The tolerance.</param>
/// <returns></returns>
[DebuggerHidden]
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsEqual(this double self, double other, double tolerance = Tolerance)
{
return Math.Abs(self - other) < tolerance;
}
[DebuggerHidden]
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsRelativeEqual(this SI expected, SI actual, double toleranceFactor = ToleranceFactor)
{
return IsRelativeEqual(expected.Value(), actual.Value(), toleranceFactor: toleranceFactor);
}
[DebuggerHidden]
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsRelativeEqual(this double expected, double actual,
double toleranceFactor = DoubleExtensionMethods.ToleranceFactor)
{
......@@ -90,7 +94,8 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="other">The other.</param>
/// <param name="tolerance">The tolerance.</param>
/// <returns></returns>
[DebuggerHidden]
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsSmaller(this double self, double other, double tolerance = Tolerance)
{
return self < other - tolerance;
......@@ -103,6 +108,8 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="other">The other.</param>
/// <param name="tolerance">The tolerance.</param>
/// <returns></returns>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsSmallerOrEqual(this double self, double other, double tolerance = Tolerance)
{
return self <= other + tolerance;
......@@ -115,6 +122,8 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="other">The other.</param>
/// <param name="tolerance">The tolerance.</param>
/// <returns></returns>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsGreater(this double self, double other, double tolerance = Tolerance)
{
return self > other + tolerance;
......@@ -127,6 +136,8 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="other">The other.</param>
/// <param name="tolerance">The tolerance.</param>
/// <returns></returns>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsGreaterOrEqual(this double self, double other, double tolerance = Tolerance)
{
return self >= other - tolerance;
......@@ -137,17 +148,39 @@ namespace TUGraz.VectoCommon.Utils
/// </summary>
/// <param name="self">The self.</param>
/// <param name="tolerance">The tolerance.</param>
/// <returns></returns>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsPositive(this double self, double tolerance = Tolerance)
{
return self >= -tolerance;
}
/// <summary>
/// Checks if a value is between min and max (min &lt;= value &lt;= max)
/// </summary>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsBetween(this double self, double min, double max)
{
return min <= self && self <= max;
}
/// <summary>
/// Checks if a value is between min and max (min &lt;= value &lt;= max)
/// </summary>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsBetween(this double self, SI min, SI max)
{
return min <= self && self <= max;
}
/// <summary>
/// Converts the double-value from RPM (rounds per minute) to the SI Unit PerSecond.
/// </summary>
/// <param name="self"></param>
/// <returns></returns>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PerSecond RPMtoRad(this double self)
{
return SI<PerSecond>(self * 2 * Math.PI / 60.0);
......@@ -156,8 +189,8 @@ namespace TUGraz.VectoCommon.Utils
/// <summary>
/// Converts the double-value from RPM (rounds per minute) to the SI Unit PerSecond.
/// </summary>
/// <param name="self"></param>
/// <returns></returns>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PerSecond RPMtoRad(this float self)
{
return SI<PerSecond>(self * 2 * Math.PI / 60.0);
......@@ -166,25 +199,29 @@ namespace TUGraz.VectoCommon.Utils
/// <summary>
/// Converts the value from rounds per minute to the SI Unit PerSecond
/// </summary>
/// <param name="self"></param>
/// <returns></returns>
[DebuggerHidden]
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PerSecond RPMtoRad(this int self)
{
return SI<PerSecond>(self * 2.0 * Math.PI / 60.0);
}
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static MeterPerSecond KMPHtoMeterPerSecond(this double self)
{
return SI<MeterPerSecond>(self / 3.6);
}
[DebuggerHidden]
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static MeterPerSecond KMPHtoMeterPerSecond(this int self)
{
return SI<MeterPerSecond>(self / 3.6);
}
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double ToDegree(this double self)
{
return self * 180.0 / Math.PI;
......@@ -193,6 +230,8 @@ namespace TUGraz.VectoCommon.Utils
/// <summary>
/// Creates an SI object for the number (unit-less: [-]).
/// </summary>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static SI SI(this double value)
{
return new SI(value);
......@@ -201,17 +240,22 @@ namespace TUGraz.VectoCommon.Utils
/// <summary>
/// Creates an templated SI object for the number.
/// </summary>
[DebuggerHidden]
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SI<T>(this double value) where T : SIBase<T>
{
return SIBase<T>.Create(value);
}
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IEnumerable<T> SI<T>(this IEnumerable<double> self) where T : SIBase<T>
{
return self.Select(x => x.SI<T>());
}
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToGUIFormat(this double self)
{
return self.ToString(CultureInfo.InvariantCulture);
......@@ -220,7 +264,8 @@ namespace TUGraz.VectoCommon.Utils
public static class FloatExtensionMethods
{
[DebuggerHidden]
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SI<T>(this float value) where T : SIBase<T>
{
return SIBase<T>.Create(value);
......@@ -229,6 +274,8 @@ namespace TUGraz.VectoCommon.Utils
public static class IntegerExtensionMethods
{
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToGUIFormat(this int self)
{
return self.ToString();
......
......@@ -225,6 +225,11 @@ namespace TUGraz.VectoCommon.Utils
}
}
public static IEnumerable<Tuple<TSource, TSource>> Pairwise<TSource>(this IEnumerable<TSource> source)
{
return Pairwise(source, Tuple.Create);
}
/// <summary>
/// Repeats the element and returns an Enumerable.
/// </summary>
......
......@@ -826,6 +826,7 @@ namespace TUGraz.VectoCommon.Utils
/// Creates the specified special SI object.
/// </summary>
/// <param name="val">The value of the SI object.</param>
[DebuggerStepThrough]
public static T Create(double val)
{
if (val == 0) {
......@@ -1907,16 +1908,16 @@ namespace TUGraz.VectoCommon.Utils
if (Denominator.Any()) {
if (Numerator.Any()) {
return string.Concat(
Numerator.GroupBy(x => x)
.Select(x => x.Count() == 1 ? x.Key.ToString() : string.Format("{0}^{1}", x.Key, x.Count())))
Numerator.GroupBy(x => x)
.Select(x => x.Count() == 1 ? x.Key.ToString() : string.Format("{0}^{1}", x.Key, x.Count())))
+ "/"
+ string.Concat(
Denominator.GroupBy(x => x)
.Select(x => x.Count() == 1 ? x.Key.ToString() : string.Format("{0}^{1}", x.Key, x.Count())));
}
return "1/" + string.Concat(
Denominator.GroupBy(x => x)
.Select(x => x.Count() == 1 ? x.Key.ToString() : string.Format("{0}^{1}", x.Key, x.Count())));
Denominator.GroupBy(x => x)
.Select(x => x.Count() == 1 ? x.Key.ToString() : string.Format("{0}^{1}", x.Key, x.Count())));
}
if (Numerator.Any()) {
......@@ -2092,6 +2093,7 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="si">The si.</param>
/// <param name="tolerance">The tolerance.</param>
/// <returns></returns>
[DebuggerStepThrough]
public bool IsGreater(SI si, double tolerance)
{
if (!HasEqualUnit(si)) {
......@@ -2107,6 +2109,7 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="si">The si.</param>
/// <param name="tolerance">The tolerance.</param>
/// <returns></returns>
[DebuggerStepThrough]
public bool IsGreaterOrEqual(SI si, SI tolerance = null)
{
if (!HasEqualUnit(si)) {
......@@ -2125,6 +2128,7 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="val">The value.</param>
/// <param name="tolerance">The tolerance.</param>
/// <returns></returns>
[DebuggerStepThrough]
public bool IsSmaller(double val, double tolerance = DoubleExtensionMethods.Tolerance)
{
return Val.IsSmaller(val, tolerance);
......@@ -2136,6 +2140,7 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="val">The value.</param>
/// <param name="tolerance">The tolerance.</param>
/// <returns></returns>
[DebuggerStepThrough]
public bool IsSmallerOrEqual(double val, double tolerance = DoubleExtensionMethods.Tolerance)
{
return Val.IsSmallerOrEqual(val, tolerance);
......@@ -2147,6 +2152,7 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="val">The value.</param>
/// <param name="tolerance">The tolerance.</param>
/// <returns></returns>
[DebuggerStepThrough]
public bool IsGreater(double val, double tolerance = DoubleExtensionMethods.Tolerance)
{
return Val.IsGreater(val, tolerance);
......@@ -2158,6 +2164,7 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="val">The value.</param>
/// <param name="tolerance">The tolerance.</param>
/// <returns></returns>
[DebuggerStepThrough]
public bool IsGreaterOrEqual(double val, double tolerance = DoubleExtensionMethods.Tolerance)
{
return Val.IsGreaterOrEqual(val, tolerance);
......
......@@ -55,23 +55,68 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="y2">Second Value on the Y-Axis.</param>
/// <param name="xint">Value on the X-Axis, for which the Y-Value should be interpolated.</param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TResult Interpolate<T, TResult>(T x1, T x2, TResult y1, TResult y2, T xint) where T : SI
where TResult : SIBase<TResult>
{
return Interpolate(x1.Value(), x2.Value(), y1.Value(), y2.Value(), xint.Value()).SI<TResult>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TResult Interpolate<TInput, T, TResult>(this Tuple<TInput, TInput> self, Func<TInput, T> x,
Func<TInput, TResult> y, T xInterpolate)
where T : SIBase<T>
where TResult : SIBase<TResult>
{
return Interpolate(x(self.Item1).Value(), x(self.Item2).Value(), y(self.Item1).Value(), y(self.Item2).Value(),
xInterpolate.Value()).SI<TResult>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TResult Interpolate<TInput, TResult>(this Tuple<TInput, TInput> self, Func<TInput, double> x,
Func<TInput, TResult> y, double xInterpolate)
where TResult : SIBase<TResult>
{
return
Interpolate(x(self.Item1), x(self.Item2), y(self.Item1).Value(), y(self.Item2).Value(), xInterpolate).SI<TResult>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TResult Interpolate<TInput, TResult>(this IEnumerable<TInput> self, Func<TInput, double> x,
Func<TInput, TResult> y, double xInterpolate)
where TResult : SIBase<TResult>
{
return self.GetSection(elem => x(elem) < xInterpolate).Interpolate(x, y, xInterpolate);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Interpolate<TInput>(this IEnumerable<TInput> self, Func<TInput, double> x,
Func<TInput, double> y, double xInterpolate)
{
return self.GetSection(elem => x(elem) < xInterpolate).Interpolate(x, y, xInterpolate);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Interpolate<TInput>(this Tuple<TInput, TInput> self, Func<TInput, double> x,
Func<TInput, double> y, double xInterpolate)
{
return Interpolate(x(self.Item1), x(self.Item2), y(self.Item1), y(self.Item2), xInterpolate);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Interpolate<T>(T x1, T x2, double y1, double y2, T xint) where T : SI
{
return Interpolate(x1.Value(), x2.Value(), y1, y2, xint.Value());
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TResult Interpolate<TResult>(double x1, double x2, TResult y1, TResult y2, double xint)
where TResult : SIBase<TResult>
{
return Interpolate(x1, x2, y1.Value(), y2.Value(), xint).SI<TResult>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Interpolate(Point p1, Point p2, double x)
{
return Interpolate(p1.X, p2.X, p1.Y, p2.Y, x);
......@@ -80,6 +125,7 @@ namespace TUGraz.VectoCommon.Utils
/// <summary>
/// Linearly interpolates a value between two points.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Interpolate(double x1, double x2, double y1, double y2, double xint)
{
return (xint - x1) * (y2 - y1) / (x2 - x1) + y1;
......@@ -88,6 +134,8 @@ namespace TUGraz.VectoCommon.Utils
/// <summary>
/// Returns the absolute value.
/// </summary>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static SI Abs(SI si)
{
return si.Abs();
......@@ -96,6 +144,8 @@ namespace TUGraz.VectoCommon.Utils
/// <summary>
/// Returns the minimum of two values.
/// </summary>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Min<T>(T c1, T c2) where T : IComparable
{
return c1.CompareTo(c2) <= 0 ? c1 : c2;
......@@ -104,59 +154,67 @@ namespace TUGraz.VectoCommon.Utils
/// <summary>
/// Returns the maximum of two values.
/// </summary>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Max<T>(T c1, T c2) where T : IComparable
{
return c1.CompareTo(c2) >= 0 ? c1 : c2;
}
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Max<T>(T c1, T c2, T c3) where T : IComparable
{
return Max(Max(c1, c2), c3);
}
public static T Limit<T>(this T value, T lowerBound, T upperBound) where T : IComparable
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T LimitTo<T>(this T value, T lowerBound, T upperBound) where T : IComparable
{
if (lowerBound.CompareTo(upperBound) > 0) {
throw new VectoException(
"VectoMath.Limit: lowerBound must not be greater than upperBound. lowerBound: {0}, upperBound: {1}", lowerBound,
"VectoMath.LimitTo: lowerBound must not be greater than upperBound. lowerBound: {0}, upperBound: {1}", lowerBound,
upperBound);
}
if (value.CompareTo(upperBound) > 0) {
return upperBound;
}
if (value.CompareTo(lowerBound) < 0) {
return lowerBound;
}
return value;
}
/// <summary>
/// converts the given inclination in percent (0-1+) into Radians
/// converts the given inclination in percent (0-1+) into Radians
/// </summary>
/// <param name="inclinationPercent"></param>
/// <returns></returns>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Radian InclinationToAngle(double inclinationPercent)
{
return Math.Atan(inclinationPercent).SI<Radian>();
}
public static List<double> QuadraticEquationSolver(double a, double b, double c)
public static double[] QuadraticEquationSolver(double a, double b, double c)
{
var retVal = new List<double>();
var d = b * b - 4 * a * c;
// no real solution
if (d < 0) {
return retVal;
} else if (d > 0) {
// two solutions possible
retVal.Add((-b + Math.Sqrt(d)) / (2 * a));
retVal.Add((-b - Math.Sqrt(d)) / (2 * a));
} else {
// only one solution possible
retVal.Add(-b / (2 * a));
return new double[0];
}
return retVal;
if (d > 0) {
// two solutions
return new[] { (-b + Math.Sqrt(d)) / (2 * a), (-b - Math.Sqrt(d)) / (2 * a) };
}
// one real solution
return new[] { -b / (2 * a) };
}
public static Point Intersect(Edge line1, Edge line2)
......@@ -221,10 +279,10 @@ namespace TUGraz.VectoCommon.Utils
// we need to accelerate / decelerate. solve quadratic equation...
// ds = acceleration / 2 * dt^2 + currentSpeed * dt => solve for dt
var solutions = VectoMath.QuadraticEquationSolver(acceleration.Value() / 2.0, currentSpeed.Value(),
var solutions = QuadraticEquationSolver(acceleration.Value() / 2.0, currentSpeed.Value(),
-ds.Value());
if (solutions.Count == 0) {
if (solutions.Length == 0) {
// no real-valued solutions: acceleration is so negative that vehicle stops already before the required distance can be reached.
// adapt ds to the halting-point.
// t = v / a
......@@ -256,12 +314,14 @@ namespace TUGraz.VectoCommon.Utils
return retVal;
}
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Ceiling<T>(T si) where T : SIBase<T>
{
return Math.Ceiling(si.Value()).SI<T>();
}
public static List<double> CubicEquationSolver(double a, double b, double c, double d)
public static double[] CubicEquationSolver(double a, double b, double c, double d)
{
var solutions = new List<double>();
if (a.IsEqual(0, 1e-12)) {
......@@ -280,7 +340,7 @@ namespace TUGraz.VectoCommon.Utils
solutions.Add(p * Math.Cos((phi + 2 * i * Math.PI) / 3.0) - w);
}
} else {
// only one real solution
// one real solution
discriminant = Math.Sqrt(discriminant);
solutions.Add(Cbrt(q + discriminant) + Cbrt(q - discriminant) - w);
}
......@@ -293,7 +353,7 @@ namespace TUGraz.VectoCommon.Utils
}
}
solutions.Sort();
return solutions;
return solutions.ToArray();
}
private static double Cbrt(double x)
......@@ -336,27 +396,11 @@ namespace TUGraz.VectoCommon.Utils
return new Point(p1.X * scalar, p1.Y * scalar, p1.Z * scalar);
}
/// <summary>
///
/// </summary>
/// <param name="scalar"></param>
/// <param name="p1"></param>
/// <returns></returns>
public static Point operator *(double scalar, Point p1)
{
return p1 * scalar;
}
/// <summary>
/// Calculates cross product between two 3d-vectors.
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public Point Cross(Point other)
{
return new Point(Y * other.Z - Z * other.Y, Z * other.X - X * other.Z, X * other.Y - Y * other.X);
}
/// <summary>
/// Returns perpendicular vector for xy-components of this point. P = (-Y, X)
/// </summary>
......@@ -422,14 +466,6 @@ namespace TUGraz.VectoCommon.Utils
public readonly double Z;
public readonly double W;
public Plane(double x, double y, double z, double w)
{
X = x;
Y = y;
Z = z;
W = w;
}
public Plane(Triangle tr)
{
var abX = tr.P2.X - tr.P1.X;
......@@ -466,13 +502,8 @@ namespace TUGraz.VectoCommon.Utils
}
/// <summary>
/// Barycentric Technique: http://www.blackpawn.com/texts/pointinpoly/default.html
/// Check if Point is inside of Triangle. Barycentric Technique: http://www.blackpawn.com/texts/pointinpoly/default.html
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="exact"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsInside(double x, double y, bool exact)
{
var smallerY = y - DoubleExtensionMethods.Tolerance;
......@@ -530,17 +561,6 @@ namespace TUGraz.VectoCommon.Utils
var result = p0Square * det12 + p1Square * det20 + p2Square * det01;
return result > 0;
//double[,] m = { { P1.X - p.X, P1.Y - p.Y, (P1.X * P1.X - p.X*p.X) + (P1.Y * P1.Y - p.Y*p.Y) },
// { P2.X - p.X, P2.Y - p.Y, (P2.X * P2.X - p.X*p.X) + (P2.Y * P2.Y - p.Y*p.Y) },
// { P3.X - p.X, P3.Y - p.Y, (P3.X * P3.X - p.X*p.X) + (P3.Y * P3.Y - p.Y*p.Y) } };
//var det = m[0, 0] * m[1, 1] * m[2, 2]
// + m[0, 1] * m[1, 2] * m[2, 0]
// + m[0, 2] * m[1, 0] * m[2, 1]
// - m[0, 0] * m[1, 2] * m[2, 1]
// - m[0, 1] * m[1, 0] * m[2, 2]
// - m[0, 2] * m[1, 1] * m[2, 0];
//return det > 0;
}
public bool Contains(Point p)
......@@ -553,7 +573,7 @@ namespace TUGraz.VectoCommon.Utils
return Contains(t.P1) || Contains(t.P2) || Contains(t.P3);
}
public Edge[] GetEdges()
public IEnumerable<Edge> GetEdges()
{
return new[] { new Edge(P1, P2), new Edge(P2, P3), new Edge(P3, P1) };
}
......
......@@ -71,16 +71,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
return Formulas.TorqueToPower(DragLoadStationaryTorque(angularVelocity), angularVelocity);
}
public CombustionEngineData EngineData { get; internal set; }
public Second PT1(PerSecond angularVelocity)
{
return PT1Data.Lookup(angularVelocity);
}
/// <summary>
/// Get the engine's preferred speed from the given full-load curve (i.e. Speed at 51% torque/speed-integral between idling and N95h.)
/// </summary>
......@@ -105,7 +102,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
get { return _n95hSpeed ?? (_n95hSpeed = FindEngineSpeedForPower(0.95 * MaxPower).Last()); }
}
public PerSecond LoSpeed
{
get { return _engineSpeedLo ?? (_engineSpeedLo = FindEngineSpeedForPower(0.55 * MaxPower).First()); }
......@@ -116,7 +112,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
get { return _engineSpeedHi ?? (_engineSpeedHi = FindEngineSpeedForPower(0.7 * MaxPower).Last()); }
}
public NewtonMeter MaxLoadTorque
{
get { return FullLoadEntries.Max(x => x.TorqueFullLoad); }
......@@ -127,7 +122,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
get { return FullLoadEntries.Min(x => x.TorqueDrag); }
}
private void ComputePreferredSpeed()
{
var maxArea = ComputeArea(EngineData.IdleSpeed, N95hSpeed);
......@@ -161,10 +155,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
// area = (M(n1) + M(n2))/2 * (n2 - n1) => solve for n2
var retVal = VectoMath.QuadraticEquationSolver(k.Value() / 2.0, d.Value(),
(-k * p1.EngineSpeed * p1.EngineSpeed / 2 - p1.EngineSpeed * d - area).Value());
if (retVal.Count == 0) {
if (retVal.Length == 0) {
Log.Info("No real solution found for requested area: P: {0}, p1: {1}, p2: {2}", area, p1, p2);
}
return retVal.First(x => x >= p1.EngineSpeed && x <= p2.EngineSpeed).SI<PerSecond>();
return retVal.First(x => x.IsBetween(p1.EngineSpeed, p2.EngineSpeed)).SI<PerSecond>();
}
private List<PerSecond> FindEngineSpeedForPower(Watt power)
......
......@@ -97,32 +97,33 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
torqueOut.Value();
var sol = VectoMath.QuadraticEquationSolver(a, b, c);
var selected = sol.Where(x => x > min
&& angularSpeedOut.Value() / x >= muEdge.P1.X && angularSpeedOut.Value() / x < muEdge.P2.X
&& angularSpeedOut.Value() / x >= mpEdge.P1.X && angularSpeedOut.Value() / x < mpEdge.P2.X);
solutions.AddRange(selected);
foreach (var x in sol) {
var ratio = angularSpeedOut.Value() / x;
if (x > min && muEdge.P1.X <= ratio && ratio < muEdge.P2.X)
solutions.Add(x);
}
}
if (solutions.Count == 0) {
throw new VectoException("No solution for input torque/input speed found! n_out: {0}, tq_out: {1}", angularSpeedOut,
torqueOut);
}
var retVal = new List<TorqueConverterOperatingPoint>();
var retVal = new List<TorqueConverterOperatingPoint>(solutions.Count);
foreach (var sol in solutions) {
var s = sol.SI<PerSecond>();
var tmp = new TorqueConverterOperatingPoint {
OutTorque = torqueOut,
OutAngularVelocity = angularSpeedOut,
InAngularVelocity = sol.SI<PerSecond>()
InAngularVelocity = s,
SpeedRatio = angularSpeedOut / s,
TorqueRatio = MuLookup(angularSpeedOut / s)
};
tmp.SpeedRatio = angularSpeedOut / tmp.InAngularVelocity;
tmp.TorqueRatio = MuLookup(angularSpeedOut / tmp.InAngularVelocity);
tmp.InTorque = torqueOut / tmp.TorqueRatio;
retVal.Add(tmp);
}
return retVal;
}
/// <summary>
/// find an operating point for the torque converter
///
......@@ -139,30 +140,29 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
OutAngularVelocity = outAngularVelocity,
SpeedRatio = outAngularVelocity.Value() / inAngularVelocity.Value(),
};
foreach (var segment in TorqueConverterEntries.Pairwise(Tuple.Create)) {
if (!(retVal.SpeedRatio >= segment.Item1.SpeedRatio) || !(retVal.SpeedRatio < segment.Item2.SpeedRatio)) {
continue;
foreach (var segment in TorqueConverterEntries.Pairwise()) {
if (retVal.SpeedRatio.IsBetween(segment.Item1.SpeedRatio, segment.Item2.SpeedRatio)) {
var mpTorque = segment.Interpolate(x => x.SpeedRatio, y => y.Torque, retVal.SpeedRatio);
retVal.TorqueRatio = segment.Interpolate(x => x.SpeedRatio, y => y.TorqueRatio, retVal.SpeedRatio);
retVal.InTorque = mpTorque * (inAngularVelocity * inAngularVelocity / ReferenceSpeed / ReferenceSpeed).Value();
retVal.OutTorque = retVal.InTorque * retVal.TorqueRatio;
return retVal;
}
var mpTorque = VectoMath.Interpolate(segment.Item1.SpeedRatio, segment.Item2.SpeedRatio, segment.Item1.Torque,
segment.Item2.Torque, retVal.SpeedRatio);
retVal.TorqueRatio = VectoMath.Interpolate(segment.Item1.SpeedRatio, segment.Item2.SpeedRatio,
segment.Item1.TorqueRatio, segment.Item2.TorqueRatio, retVal.SpeedRatio);
retVal.InTorque = mpTorque * (inAngularVelocity * inAngularVelocity / ReferenceSpeed / ReferenceSpeed).Value();
retVal.OutTorque = retVal.InTorque * retVal.TorqueRatio;
return retVal;
}
// No solution found. Throw Errror
var nu = outAngularVelocity / inAngularVelocity;
var nuMax = TorqueConverterEntries.Last().SpeedRatio;
if (nu.IsGreater(nuMax)) {
throw new VectoException(
"Torque Converter: Range of torque converter data is not sufficient. Needed nu: {0}, Got nu_max: {1}", nu,
nuMax);
} else {
throw new VectoException(
"Torque Converter: No solution for output speed/input speed found! n_out: {0}, n_in: {1}, nu: {2}, nu_max: {3}",
outAngularVelocity, inAngularVelocity, nu, nuMax);
"Torque Converter: Range of torque converter data is not sufficient. Needed nu: {0}, Got nu_max: {1}", nu, nuMax);
}
throw new VectoException(
"Torque Converter: No solution for output speed/input speed found! n_out: {0}, n_in: {1}, nu: {2}, nu_max: {3}",
outAngularVelocity, inAngularVelocity, nu, nuMax);
}
/// <summary>
......@@ -238,22 +238,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
private double MuLookup(double speedRatio)
{
int index;
TorqueConverterEntries.GetSection(x => x.SpeedRatio < speedRatio, out index);
var retVal = VectoMath.Interpolate(TorqueConverterEntries[index].SpeedRatio,
TorqueConverterEntries[index + 1].SpeedRatio, TorqueConverterEntries[index].TorqueRatio,
TorqueConverterEntries[index + 1].TorqueRatio, speedRatio);
return retVal;
return TorqueConverterEntries.Interpolate(x => x.SpeedRatio, y => y.TorqueRatio, speedRatio);
}
private NewtonMeter ReferenceTorqueLookup(double speedRatio)
{
int index;
TorqueConverterEntries.GetSection(x => x.SpeedRatio < speedRatio, out index);
var retVal = VectoMath.Interpolate(TorqueConverterEntries[index].SpeedRatio,
TorqueConverterEntries[index + 1].SpeedRatio, TorqueConverterEntries[index].Torque,
TorqueConverterEntries[index + 1].Torque, speedRatio);
return retVal;
return TorqueConverterEntries.Interpolate(x => x.SpeedRatio, y => y.Torque, speedRatio);
}
// ReSharper disable once UnusedMember.Global -- used by validation
......
......@@ -248,7 +248,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
maxTorque = VectoMath.Min(maxTorque, gearboxFullLoad);
}
CurrentState.EngineTorque = totalTorqueDemand.Limit(minTorque, maxTorque);
CurrentState.EngineTorque = totalTorqueDemand.LimitTo(minTorque, maxTorque);
CurrentState.EnginePower = CurrentState.EngineTorque * avgEngineSpeed;
if (totalTorqueDemand.IsGreater(0) &&
......
......@@ -58,7 +58,6 @@ namespace TUGraz.VectoCore.Tests.Utils
Assert.AreEqual(positive, VectoMath.Abs(negative));
Assert.AreEqual(positive, VectoMath.Abs(positive));
var smallerWatt = 0.SI<Watt>();
var biggerWatt = 5.SI<Watt>();
var negativeWatt = -10.SI<Watt>();
......@@ -68,12 +67,10 @@ namespace TUGraz.VectoCore.Tests.Utils
Assert.AreEqual(biggerWatt, VectoMath.Max(smallerWatt, biggerWatt));
Assert.AreEqual(positiveWatt, VectoMath.Abs(negativeWatt));
Assert.AreEqual(positiveWatt, VectoMath.Abs(positiveWatt));
}
[TestCase(0, -1, 0, 1, -1, 0, 1, 0, 0, 0),
TestCase(0, 0, 10, 0, 0, 5, 10, 5, double.NaN, double.NaN),
TestCase(0, 0, 0, 10, 5, 0, 10, 5, double.NaN, double.NaN),
......@@ -101,10 +98,10 @@ namespace TUGraz.VectoCore.Tests.Utils
{
var results = VectoMath.CubicEquationSolver(a, b, c, d);
Assert.AreEqual(expected.Length, results.Count);
Assert.AreEqual(expected.Length, results.Length);
var sorted = expected.ToList();
sorted.Sort();
results.Sort();
Array.Sort(results);
var comparison = sorted.Zip(results, (exp, result) => exp - result);
foreach (var cmp in comparison) {
......
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