/* Math.Nhtsa.ChannelIntegration.cs $Log: Math.Nhtsa.ChannelIntegration.cs,v $ Revision 1.4 2007/10/04 04:57:45 Paul Hrissikopoulos Added new integration object. Revision 1.3 2007/08/24 23:31:08 Paul Hrissikopoulos Fixed comment typos. Revision 1.2 2007/03/28 15:58:02 Paul Hrissikopoulos Fixed error in integration calculation; fixed erroenous error check in SampleRate accessor. Revision 1.1 2007/02/05 17:17:08 Paul Hrissikopoulos Finished installing generic channel math framework + basic calculus operations. Copyright © 2007 Diversified Technical Systems, Inc. All Rights Reserved */ using System; using System.Collections.Generic; using System.Text; using DTS.Common.Utilities.DotNetProgrammingConstructs; namespace DTS.Common.Utilities.Math.Nhtsa { //////////////////////////////////////////////////////////////////////////////// /// /// Representation of NHTSA-based integration channel operation. /// public class Integration : DoubleListOperation { //////////////////////////////////////////////////////////////////////////////// /// /// Get/set the sample rate for this data to be integrated. /// public double SampleRate { get => _SampleRate.Value; set => _SampleRate.Value = value; } private Property _SampleRate = new Property( typeof(Integration).FullName + ".SampleRate", 0.0, false ); //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// /// Initialize an instance of the Integration class. /// /// /// /// The System.Collections.Generic.IList of s /// domain for this operation. /// /// public Integration(IList domain) : base(domain) { // // I'd prefer to do this statically, but I don't know of any C# way to place a constraint // on a generic type that's already been determined by some ancestor we're inheriting from, // so for now we'll have to dynamically check it on object instantiation. // if (!(domain is ICloneable)) throw new InvalidCastException("the domain type for " + typeof(Integration).FullName + " must be ICloneable"); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// /// Initialize an instance of the Iso.ChannelIntegration class. /// /// /// /// The System.Collections.Generic.IList of s /// domain for this operation. /// /// /// /// The sample rate of the channel to be integrated. /// /// public Integration(IList domain, int sampleRate) : this(domain) { try { SampleRate = sampleRate; } catch (System.Exception ex) { throw new Exception("encountered problem constructing " + GetType().FullName, ex); } } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// /// Get the System.Collections.Generic.IList of s result of /// the operation on the channel. /// public override IList Range { get { try { if (null == Domain) throw new ArgumentNullException("attempted to integrate null channel reference"); else if (0.0 >= SampleRate) throw new ArgumentOutOfRangeException("SampleRate must be greater than zero"); else if (!(Domain is ICloneable)) throw new InvalidCastException("the domain type for " + typeof(Integration).FullName + " must be ICloneable"); else { var IndexOfLastSample = Domain.Count - 1; var de = 1 / (SampleRate * 2.0); var range = ((ICloneable)Domain).Clone() as IList; range[0] = Domain[0] * de; for (var t = 1; t < IndexOfLastSample; t++) range[t] = range[t - 1] + 2 * Domain[t] * de; range[IndexOfLastSample] = range[IndexOfLastSample - 1] + Domain[IndexOfLastSample] * de; return range; } } catch (System.Exception ex) { throw new Exception("encountered problem doing " + GetType().FullName + " operation", ex); } } } //////////////////////////////////////////////////////////////////////////////// } //////////////////////////////////////////////////////////////////////////////// }