/// <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; } } }
/// <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; } } }
/// <summary> /// Returns interpolated value based on 3 node values /// <para> /// In case values are one of the circular types in <see cref="CircularValueTypes"/>, /// then the values must first be re-referenced, <see cref="CircularValueHandler"/>. /// </para> /// </summary> /// <param name="T1">Node value 1</param> /// <param name="T2">Node value 2</param> /// <param name="T3">Node value 3</param> /// <param name="w1">Weights for node value 1</param> /// <param name="w2">Weights for node value 2</param> /// <param name="w3">Weights for node value 3</param> /// <returns>Interpolated value</returns> public double GetValue( double w1, double w2, double w3, double T1, double T2, double T3 ) { if (CircularType != CircularValueTypes.Normal) { double circReference = DelVal; // Try find circReference value - the first non-delete value if (CircularValueHandler.AsReference(T1, ref circReference, DelVal) || CircularValueHandler.AsReference(T2, ref circReference, DelVal) || CircularValueHandler.AsReference(T3, ref circReference, DelVal)) { CircularValueHandler.ToReference(CircularType, ref T1, circReference, DelVal); CircularValueHandler.ToReference(CircularType, ref T2, circReference, DelVal); CircularValueHandler.ToReference(CircularType, ref T3, circReference, DelVal); } } double value = 0; double weight = 0; int delValMask = 0; // Delete value mask values for each node const int dvm1 = 0x1; const int dvm2 = 0x2; const int dvm3 = 0x4; if (T1 != DelVal) { value += w1 * T1; weight += w1; } // T1 is delete value - If we are close to this node, return delVal else if (w1 > 0.5) { return(DelVal); } else { delValMask |= dvm1; } if (T2 != DelVal) { value += w2 * T2; weight += w2; } // T2 is delete value - If we are close to this node, return delVal else if (w2 > 0.5) { return(DelVal); } else { delValMask |= dvm2; } if (T3 != DelVal) { value += w3 * T3; weight += w3; } // T3 is delete value - If we are close to this node, return delVal else if (w3 > 0.5) { return(DelVal); } else { delValMask |= dvm3; } // Check if only one non-delete value is present switch (delValMask) { //case 0: // All had values // return value; case dvm1: // Only one delete value, and we are outside the case dvm2: // "delete value area". case dvm3: // Weight them accordingly value = value / weight; break; case dvm1 + dvm2: // Only T3 is non-delete // If we are close to T3, use that, otherwise delVal value = (w3 > 0.5) ? T3 : DelVal; break; case dvm2 + dvm3: // Only T1 is non-delete // If we are close to T1, use that, otherwise delVal value = (w1 > 0.5) ? T1 : DelVal; break; case dvm3 + dvm1: // Only T2 is non-delete // If we are close to T2, use that, otherwise delVal value = (w2 > 0.5) ? T2 : DelVal; break; } CircularValueHandler.ToCircular(CircularType, ref value); return(value); }
/// <summary> /// Returns interpolated value based on 4 node values /// <para> /// In case values are one of the circular types in <see cref="CircularValueTypes"/>, /// then the values must first be re-referenced, <see cref="CircularValueHandler"/>. /// </para> /// </summary> /// <param name="dx">Bilinear dx interpolation weights</param> /// <param name="dy">Bilinear dy interpolation weights</param> /// <param name="T00">Node value 1</param> /// <param name="T10">Node value 2</param> /// <param name="T11">Node value 3</param> /// <param name="T01">Node value 4</param> /// <returns>Interpolated value</returns> // Matching CMzQuadrangle::GetValue public double GetValue( double dx, double dy, double T00, double T10, double T11, double T01 ) { if (CircularType != CircularValueTypes.Normal) { double circReference = DelVal; // Try find circReference value - the first non-delete value if (CircularValueHandler.AsReference(T00, ref circReference, DelVal) || CircularValueHandler.AsReference(T01, ref circReference, DelVal) || CircularValueHandler.AsReference(T11, ref circReference, DelVal) || CircularValueHandler.AsReference(T10, ref circReference, DelVal)) { CircularValueHandler.ToReference(CircularType, ref T00, circReference, DelVal); CircularValueHandler.ToReference(CircularType, ref T01, circReference, DelVal); CircularValueHandler.ToReference(CircularType, ref T11, circReference, DelVal); CircularValueHandler.ToReference(CircularType, ref T10, circReference, DelVal); } } int deleteValueMask = DeleteValueMask(T00, T10, T11, T01); const double m_xc = 0.5; const double m_yc = 0.5; double z; switch (deleteValueMask) { case 0: // Default if ((T00 == T10) && (T00 == T01) && (T00 == T11)) { z = T00; } else { z = (1 - dx) * (1 - dy) * T00 + dx * (1 - dy) * T10 + (1 - dx) * dy * T01 + dx * dy * T11; } break; case 1: // Delete value: T00 if ((dx < m_xc) && (dy < m_yc)) { z = DelVal; } else { z = (dx * (1 - dy) * T10 + (1 - dx) * dy * T01 + dx * dy * T11) / (dx + dy - dx * dy); } break; case 2: // Delete value: T10 if ((dx >= m_xc) && (dy < m_yc)) { z = DelVal; } else { z = ((1 - dx) * (1 - dy) * T00 + (1 - dx) * dy * T01 + dx * dy * T11) / (1 - dx + dx * dy); } break; case 3: // Delete value: T00+T10 if (dy < m_yc) { z = DelVal; } else { z = ((1 - dx) * T01 + dx * T11); } break; case 4: // Delete value: T01 if ((dx < m_xc) && (dy >= m_yc)) { z = DelVal; } else { z = ((1 - dx) * (1 - dy) * T00 + dx * (1 - dy) * T10 + dx * dy * T11) / (1 - dy + dx * dy); } break; case 5: // Delete value: T00+T01 if (dx < m_xc) { z = DelVal; } else { z = (1 - dy) * T10 + dy * T11; } break; case 6: // Delete value: T10+T01 if (((dx < m_xc) && (dy >= m_yc)) || ((dx >= m_xc) && (dy < m_yc))) { z = DelVal; } else { z = ((1 - dx) * (1 - dy) * T00 + dx * dy * T11) / (1 - dx - dy + 2 * dx * dy); } break; case 7: // Delete value: T00+T10+T01 if ((dx >= m_xc) && (dy >= m_yc)) { z = T11; } else { z = DelVal; } break; case 8: // Delete value: T11 if ((dx >= m_xc) && (dy >= m_yc)) { z = DelVal; } else { z = ((1 - dx) * (1 - dy) * T00 + dx * (1 - dy) * T10 + (1 - dx) * dy * T01) / (1 - dx * dy); } break; case 9: // Delete value: T00+T11 if (((dx < m_xc) && (dy < m_yc)) || ((dx >= m_xc) && (dy >= m_yc))) { z = DelVal; } else { z = (dx * (1 - dy) * T10 + (1 - dx) * dy * T01) / (dx + dy - 2 * dx * dy); } break; case 10: // Delete value: T10+T11 if (dx >= m_xc) { z = DelVal; } else { z = (1 - dy) * T00 + dy * T01; } break; case 11: // Delete value: T00+T10+T11 if ((dx < m_xc) && (dy >= m_yc)) { z = T01; } else { z = DelVal; } break; case 12: // Delete value: T01+T11 if (dy >= m_yc) { z = DelVal; } else { z = (1 - dx) * T00 + dx * T10; } break; case 13: // Delete value: T00+T01+T11 if ((dx >= m_xc) && (dy < m_yc)) { z = T10; } else { z = DelVal; } break; case 14: // Delete value: T10+T01+T11 if ((dx < m_xc) && (dy < m_yc)) { z = T00; } else { z = DelVal; } break; case 15: // Delete value: T00+T10+T01+T11 z = DelVal; break; //------------------------- // Smooth delete value chop variants // Calculation of z is identical, though the chopping is different case 16: // 0: Default if ((T00 == T10) && (T00 == T01) && (T00 == T11)) { z = T00; } else { z = (1 - dx) * (1 - dy) * T00 + dx * (1 - dy) * T10 + (1 - dx) * dy * T01 + dx * dy * T11; } break; case 17: // 1: Delete value: T00 if (dx + dy < 0.5) { z = DelVal; } else { z = (dx * (1 - dy) * T10 + (1 - dx) * dy * T01 + dx * dy * T11) / (dx + dy - dx * dy); } break; case 18: // 2: Delete value: T10 if (dx - dy >= 0.5) { z = DelVal; } else { z = ((1 - dx) * (1 - dy) * T00 + (1 - dx) * dy * T01 + dx * dy * T11) / (1 - dx + dx * dy); } break; case 19: // 3: Delete value: T00+T10 if (dy < 0.5) { z = DelVal; } else { z = ((1 - dx) * T01 + dx * T11); } break; case 20: // 4: Delete value: T01 if (dx - dy < -0.5) { z = DelVal; } else { z = ((1 - dx) * (1 - dy) * T00 + dx * (1 - dy) * T10 + dx * dy * T11) / (1 - dy + dx * dy); } break; case 21: // 5: Delete value: T00+T01 if (dx < 0.5) { z = DelVal; } else { z = (1 - dy) * T10 + dy * T11; } break; case 22: // 6: Delete value: T10+T01 if ((dx + dy >= 0.5) && (dx + dy < 1.5)) { z = DelVal; } else { z = ((1 - dx) * (1 - dy) * T00 + dx * dy * T11) / (1 - dx - dy + 2 * dx * dy); } break; case 23: // 7: Delete value: T00+T10+T01 if (dx + dy < 1.5) { z = DelVal; } else { z = T11; } break; case 24: // 8: Delete value: T11 if (dx + dy >= 1.5) { z = DelVal; } else { z = ((1 - dx) * (1 - dy) * T00 + dx * (1 - dy) * T10 + (1 - dx) * dy * T01) / (1 - dx * dy); } break; case 25: // 9: Delete value: T00+T11 if ((dx - dy >= -0.5) && (dx - dy < 0.5)) { z = DelVal; } else { z = (dx * (1 - dy) * T10 + (1 - dx) * dy * T01) / (dx + dy - 2 * dx * dy); } break; case 26: // 10: Delete value: T10+T11 if (dx >= 0.5) { z = DelVal; } else { z = (1 - dy) * T00 + dy * T01; } break; case 27: // 11: Delete value: T00+T10+T11 if (dx - dy > -0.5) { z = DelVal; } else { z = T01; } break; case 28: // 12: Delete value: T01+T11 if (dy >= 0.5) { z = DelVal; } else { z = (1 - dx) * T00 + dx * T10; } break; case 29: // 13: Delete value: T00+T01+T11 if (dx - dy < 0.5) { z = DelVal; } else { z = T10; } break; case 30: // 14: Delete value: T10+T01+T11 if (dx + dy > 0.5) { z = DelVal; } else { z = T00; } break; case 31: // 15: Delete value: T00+T10+T01+T11 z = DelVal; break; default: z = DelVal; break; } CircularValueHandler.ToCircular(CircularType, ref z); return(z); }