282 lines · 10.5 KB · C#
RawDownload
//******************************************************************************************************//  InverseDistanceWeightingFunction.cs - Gbtc////  Copyright © 2016, Grid Protection Alliance.  All Rights Reserved.////  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See//  the NOTICE file distributed with this work for additional information regarding copyright ownership.//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may//  not use this file except in compliance with the License. You may obtain a copy of the License at:////      http://opensource.org/licenses/MIT////  Unless agreed to in writing, the subject software distributed under the License is distributed on an//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the//  License for the specific language governing permissions and limitations.////  Code Modification History://  ----------------------------------------------------------------------------------------------------//  08/20/2016 - Stephen C. Wills//       Generated original version of source code.////****************************************************************************************************** using System; namespace GSF.NumericalAnalysis.Interpolation{    /// <summary>    /// Function definition for the inverse distance weighting algorithm.    /// </summary>    /// <param name="x">The x-coordinate of the point at which the value is to be calculated.</param>    /// <param name="y">The y-coordinate of the point at which the value is to be calculated.</param>    /// <returns>The calculated value at the given location.</returns>    public delegate double IDWFunc(double x, double y);     /// <summary>    /// Function defintion for calculating the distance between two points.    /// </summary>    /// <param name="x1">The x-coordinate of the first point.</param>    /// <param name="y1">The y-coordinate of the first point.</param>    /// <param name="x2">The x-coordinate of the second point.</param>    /// <param name="y2">The y-coordinate of the second point.</param>    /// <returns>The distance between the two given points.</returns>    public delegate double DistanceFunc(double x1, double y1, double x2, double y2);     /// <summary>    /// Represents a function for calculating values    /// at given coordinates based on sparse data sets.    /// </summary>    /// <remarks>    /// Usage is similar to the <see cref="PiecewiseLinearFunction"/> class.    /// </remarks>    public class InverseDistanceWeightingFunction    {        #region [ Members ]         // Fields        private IDWFunc m_converter;        private DistanceFunc m_distanceFunction;        private double[] m_xCoordinates;        private double[] m_yCoordinates;        private double[] m_values;        private double m_power;         #endregion         #region [ Constructors ]         /// <summary>        /// Creates a new instance of the <see cref="InverseDistanceWeightingFunction"/> class.        /// </summary>        public InverseDistanceWeightingFunction()        {            m_distanceFunction = DefaultDistanceFunction;            m_power = 1;        }         #endregion         #region [ Properties ]         /// <summary>        /// Gets the collection of x-coordinates of points at which the values are known.        /// </summary>        public double[] XCoordinates        {            get            {                return m_xCoordinates;            }        }         /// <summary>        /// Gets the collection of y-coordinates of points at which the values are known.        /// </summary>        public double[] YCoordinates        {            get            {                return m_yCoordinates;            }        }         /// <summary>        /// Gets the collection of values of points at which the values are known.        /// </summary>        public double[] Values        {            get            {                return m_values;            }        }         /// <summary>        /// Gets the power applied to the inverse distance to control the speed of value's decay.        /// </summary>        public double Power        {            get            {                return m_power;            }        }         /// <summary>        /// Gets the function to be used to calculate the distance between two points.        /// </summary>        public DistanceFunc DistanceFunction        {            get            {                return m_distanceFunction;            }        }         #endregion         #region [ Methods ]         /// <summary>        /// Sets the collection of x-coordinates of points at which the values are known.        /// </summary>        /// <param name="xCoordinates">The x-coordinates of points at which the values are known.</param>        /// <returns>A reference to the inverse distance weighting function.</returns>        public InverseDistanceWeightingFunction SetXCoordinates(params double[] xCoordinates)        {            m_converter = null;            m_xCoordinates = xCoordinates;            return this;        }         /// <summary>        /// Sets the collection of y-coordinates of points at which the values are known.        /// </summary>        /// <param name="yCoordinates">The y-coordinates of points at which the values are known.</param>        /// <returns>A reference to the inverse distance weighting function.</returns>        public InverseDistanceWeightingFunction SetYCoordinates(params double[] yCoordinates)        {            m_converter = null;            m_yCoordinates = yCoordinates;            return this;        }         /// <summary>        /// Sets the collection of values of points at which the values are known.        /// </summary>        /// <param name="values">The values of points at which the values are known.</param>        /// <returns>A reference to the inverse distance weighting function.</returns>        public InverseDistanceWeightingFunction SetValues(params double[] values)        {            m_converter = null;            m_values = values;            return this;        }         /// <summary>        /// Sets the power applied to the inverse distance to control the speed of value's decay.        /// </summary>        /// <param name="power">The power applied to the inverse of the distance.</param>        /// <returns>A reference to the inverse distance weighting function.</returns>        /// <remarks>Larger values increase the speed of decay such that a known value affects a smaller area.</remarks>        public InverseDistanceWeightingFunction SetPower(double power)        {            m_converter = null;            m_power = power;            return this;        }         /// <summary>        /// Sets the function to be used to calculate the distance between two points.        /// </summary>        /// <param name="distanceFunction">The function used to calculate distance between two points.</param>        /// <returns>A reference to the inverse distance weighting function.</returns>        public InverseDistanceWeightingFunction SetDistanceFunction(DistanceFunc distanceFunction)        {            m_converter = null;            m_distanceFunction = distanceFunction ?? DefaultDistanceFunction;            return this;        }         private IDWFunc GetConverter()        {            DistanceFunc distanceFunction = m_distanceFunction;            double[] xCoordinates = m_xCoordinates ?? new double[0];            double[] yCoordinates = m_yCoordinates ?? new double[0];            double[] values = m_values ?? new double[0];            double power = m_power;             if (xCoordinates.Length != yCoordinates.Length)                throw new InvalidOperationException($"The number of x-coordinates must match the number of y-coordinates. ({xCoordinates.Length} != {yCoordinates.Length})");             if (xCoordinates.Length != values.Length)                throw new InvalidOperationException($"The number of coordinates must match the number of values. ({xCoordinates.Length} != {values.Length})");             if (xCoordinates.Length == 0)                return (x, y) => 0.0D;             return m_converter ?? (m_converter = (x, y) =>            {                double numerator = 0.0D;                double denominator = 0.0D;                 for (int i = 0; i < xCoordinates.Length; i++)                {                    double distance = distanceFunction(x, y, xCoordinates[i], yCoordinates[i]);                     if (distance == 0.0D)                        return values[i];                     double inverseDistance = Math.Pow(1.0D / distance, power);                    numerator += values[i] * inverseDistance;                    denominator += inverseDistance;                }                 return numerator / denominator;            });        }         #endregion         #region [ Operators ]         /// <summary>        /// Converts the <see cref="InverseDistanceWeightingFunction"/>        /// object to an <see cref="IDWFunc"/> to start converting values.        /// </summary>        /// <param name="idwFunction">The inverse distance wieghting function to be converted.</param>        /// <exception cref="InvalidOperationException">        /// <para>the number of x-coordinates does not equal the number of y-coordinates</para>        /// <para>- or -</para>        /// <para>the number of coordinates does not equal the number of values</para>        /// </exception>        public static implicit operator IDWFunc(InverseDistanceWeightingFunction idwFunction)        {            return idwFunction.GetConverter();        }         #endregion         #region [ Static ]         // Static Methods         /// <summary>        /// Calculates the distance between two points.        /// </summary>        /// <param name="x1">The x-coordinate of the first point.</param>        /// <param name="y1">The y-coordinate of the first point.</param>        /// <param name="x2">The x-coordinate of the second point.</param>        /// <param name="y2">The y-coordinate of the second point.</param>        /// <returns></returns>        public static double DefaultDistanceFunction(double x1, double y1, double x2, double y2)        {            double xDiff = x1 - x2;            double yDiff = y1 - y2;            return Math.Sqrt(xDiff * xDiff + yDiff * yDiff);        }         #endregion    }}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t