public static void GetBarycentricCoords(Coords2D _xyA, Coords2D _xyB, Coords2D _xyC, Coords2D _xy, out double a, out double b, out double c) { a = double.NaN; b = double.NaN; c = double.NaN; if (!Coords2D.IsInsideTriangle(_xyA, _xyB, _xyC, _xy, true)) { return; } // solving the eq system: // _xy.X = a * _xyA.X + b * _xyB.X + (1 - a - b) * _xyC.X // _xy.Y = a * _xyA.Y + b * _xyB.Y + (1 - a - b) * _xyC.Y double denominator = (_xyB.Y - _xyC.Y) * (_xyA.X - _xyC.X) + (_xyC.X - _xyB.X) * (_xyA.Y - _xyC.Y); if (Math.Abs(denominator) < Calculation.MIN_DOUBLE_VAL) { return; } a = ((_xyB.Y - _xyC.Y) * (_xy.X - _xyC.X) + (_xyC.X - _xyB.X) * (_xy.Y - _xyC.Y)) / denominator; b = ((_xy.Y - _xyC.Y) * (_xyA.X - _xyC.X) + (_xyC.X - _xy.X) * (_xyA.Y - _xyC.Y)) / denominator; c = 1 - a - b; }
private static double Interpolate2D(Coords2D _xy, Dictionary <Coords2D, double> _Fxy) { if (_Fxy == null || _Fxy.Count < 3) { return(double.NaN); } // find closest xy values SortedList <double, Coords2D> distances = new SortedList <double, Coords2D>(); foreach (Coords2D xy_current in _Fxy.Keys) { double dist = Math.Abs(_xy.X - xy_current.X) + Math.Abs(_xy.Y - xy_current.Y); distances.Add(dist, xy_current); } // construct the smallest well-defined triangle containing _xy Coords2D xyA = distances.ElementAt(0).Value; Coords2D xyB = distances.ElementAt(1).Value; int i = 1; if (!Coords2D.InGeneralPosition(xyA, xyB)) { for (; i < distances.Count; i++) { xyB = distances.ElementAt(i).Value; if (Coords2D.InGeneralPosition(xyA, xyB)) { break; } } } if (!Coords2D.InGeneralPosition(xyA, xyB)) { return(double.NaN); } Coords2D xyC = null; for (int j = 1; j < distances.Count && j != i; j++) { xyC = distances.ElementAt(j).Value; if (Coords2D.InGeneralPosition(xyA, xyB, xyC) && Coords2D.IsInsideTriangle(xyA, xyB, xyC, _xy, false)) { break; } } if (!Coords2D.InGeneralPosition(xyA, xyB, xyC) || !Coords2D.IsInsideTriangle(xyA, xyB, xyC, _xy, false)) { return(double.NaN); } // perform actual interpolation double a, b, c; Coords2D.GetBarycentricCoords(xyA, xyB, xyC, _xy, out a, out b, out c); if (double.IsNaN(a) || double.IsNaN(b) || double.IsNaN(c)) { return(double.NaN); } return(a * _Fxy[xyA] + b * _Fxy[xyB] + c * _Fxy[xyC]); }