/// <summary>
        /// Interpolate source values to target
        /// </summary>
        public void Interpolate(double[] sourceValues, double[] targetValues)
        {
            // Loop over all target elements/nodes
            for (int i = 0; i < _interpData.Length; i++)
            {
                InterPData interPData = _interpData[i];

                double value  = 0;
                double weight = 0;

                int[]    indices = interPData.Indices;
                double[] weights = interPData.Weights;

                // For angular-type data, find reference value
                double refValue = 0;
                if (_circularType != CircularValueTypes.Normal)
                {
                    for (int j = 0; j < indices.Length; j++)
                    {
                        double sourceValue = sourceValues[indices[j]];
                        if (sourceValue != _deleteValue)
                        {
                            // First one found is good, break out.
                            refValue = sourceValue;
                            break;
                        }
                    }
                }

                // Loop over all source elements connected to target
                for (int j = 0; j < indices.Length; j++)
                {
                    double sourceValue = sourceValues[indices[j]];

                    if (sourceValue != _deleteValue)
                    {
                        // For angular type values, correct to match reference value
                        CircularValueHandler.ToReference(_circularType, ref sourceValue, refValue);

                        value  += sourceValue * weights[j];
                        weight += weights[j];
                    }
                }

                if (weight == 0) // all element values were delete values
                {
                    targetValues[i] = _deleteValue;
                }
                else
                {
                    value /= weight;

                    // For angular type values, correct to match angular span.
                    CircularValueHandler.ToCircular(_circularType, ref value);

                    targetValues[i] = value;
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Interpolate values from source (element values) to target points.
        /// </summary>
        public void InterpolateToTarget(double[] sourceElementValues, double[] target)
        {
            // Firstly, interpolate to node values
            _nodeInterpolator.Interpolate(sourceElementValues, _nodeValues);

            for (int i = 0; i < _targets.Count; i++)
            {
                InterPData interPData = _targets[i];
                if (interPData.Element1Index < 0)
                {
                    // target not included in source
                    target[i] = _deleteValue;
                    continue;
                }

                // Do interpolation inside (element-element-node) triangle,
                // disregarding any delete values.
                double sourceElementValue = sourceElementValues[interPData.Element1Index];
                if (sourceElementValue != _deleteValue)
                {
                    double value  = sourceElementValue * interPData.Element1Weight;
                    double weight = interPData.Element1Weight;

                    {
                        double otherElmentValue = sourceElementValues[interPData.Element2Index];
                        if (otherElmentValue != _deleteValue)
                        {
                            CircularValueHandler.ToReference(_circularType, ref otherElmentValue, sourceElementValue);
                            value  += otherElmentValue * interPData.Element2Weight;
                            weight += interPData.Element2Weight;
                        }
                    }

                    {
                        double nodeValue = _nodeValues[interPData.NodeIndex];
                        if (nodeValue != _deleteValue)
                        {
                            CircularValueHandler.ToReference(_circularType, ref nodeValue, sourceElementValue);
                            value  += nodeValue * interPData.NodeWeight;
                            weight += interPData.NodeWeight;
                        }
                    }

                    value /= weight;
                    CircularValueHandler.ToCircular(_circularType, ref value);
                    target[i] = value;
                }
                else
                {
                    target[i] = _deleteValue;
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Add a target, by specifying its (x,y) coordinate.
        /// </summary>
        public void AddTarget(double x, double y)
        {
            if (_targets == null)
            {
                _targets = new List <InterPData>();
            }
            if (_searcher == null)
            {
                _searcher = new MeshSearcher(_mesh);
                _searcher.SetupElementSearch();
            }

            InterPData interpData = new InterPData();

            // Setting "out-of-bounds" index
            interpData.Element1Index = -1;

            // Find element that includes the (x,y) coordinate
            MeshElement element = _searcher.FindElement(x, y);

            // Check if element has been found, i.e. includes the (x,y) point
            if (element != null)
            {
                bool found = false;
                interpData.Element1Index = element.Index;

                // Check which face the point belongs to, and which "side" of the face
                bool isQuad   = element.IsQuadrilateral();
                int  numFaces = isQuad ? 4 : 3;
                for (int j = 0; j < numFaces; j++)
                {
                    MeshFace elementFace = element.Faces[j];
                    // From the element (x,y), looking towards the face,
                    // figure out wich node is right and which is left.
                    MeshNode rightNode, leftNode;
                    if (elementFace.LeftElement == element)
                    {
                        rightNode = elementFace.FromNode;
                        leftNode  = elementFace.ToNode;
                    }
                    else
                    {
                        rightNode = elementFace.ToNode;
                        leftNode  = elementFace.FromNode;
                    }

                    // Find also the element on the other side of the face
                    double      otherElementX, otherElementY;
                    MeshElement otherElement = elementFace.OtherElement(element);
                    if (otherElement != null)
                    {
                        otherElementX            = otherElement.XCenter;
                        otherElementY            = otherElement.YCenter;
                        interpData.Element2Index = otherElement.Index;
                    }
                    else
                    {
                        // No other element - boundary face, use center of face.
                        otherElementX = 0.5 * (rightNode.X + leftNode.X);
                        otherElementY = 0.5 * (rightNode.Y + leftNode.Y);
                        // Use "itself" as element-2
                        interpData.Element2Index = element.Index;
                    }


                    // Check if point is on the right side of the line between element and other-element
                    if (MeshExtensions.IsPointInsideLines(x, y, element.XCenter, element.YCenter, rightNode.X, rightNode.Y, otherElementX, otherElementY))
                    {
                        (double w1, double w2, double w3) = MeshExtensions.InterpolationWeights(x, y, element.XCenter, element.YCenter, rightNode.X, rightNode.Y, otherElementX, otherElementY);
                        interpData.NodeIndex      = rightNode.Index;
                        interpData.Element1Weight = w1;
                        interpData.NodeWeight     = w2;
                        interpData.Element2Weight = w3;
                        found = true;
                        break;
                    }
                    // Check if point is on the left side of the line between element and other-element
                    if (MeshExtensions.IsPointInsideLines(x, y, element.XCenter, element.YCenter, otherElementX, otherElementY, leftNode.X, leftNode.Y))
                    {
                        (double w1, double w2, double w3) = MeshExtensions.InterpolationWeights(x, y, element.XCenter, element.YCenter, otherElementX, otherElementY, leftNode.X, leftNode.Y);
                        interpData.NodeIndex      = leftNode.Index;
                        interpData.Element1Weight = w1;
                        interpData.Element2Weight = w2;
                        interpData.NodeWeight     = w3;
                        found = true;
                        break;
                    }
                }

                if (!found) // Should never happen, but just in case
                {
                    interpData.Element1Weight = 1;
                    interpData.Element2Weight = 0;
                    interpData.NodeWeight     = 0;
                    interpData.Element2Index  = element.Index;
                    interpData.NodeIndex      = element.Nodes[0].Index;
                }
            }
            _targets.Add(interpData);
        }