public static bool IsInsideTriangle(Coords2D _xyA, Coords2D _xyB, Coords2D _xyC, Coords2D _xy, bool _check_triangle = false) { if (_check_triangle) { if (!Coords2D.InGeneralPosition(_xyA, _xyB, _xyC)) { return(false); } } if (_xyA == null || _xyB == null || _xyC == null) { return(false); } double diff_xA = _xy.X - _xyA.X; double diff_xB = _xy.X - _xyB.X; double diff_xC = _xy.X - _xyC.X; bool inside_x = (Math.Sign(diff_xA) != Math.Sign(diff_xB)) || (Math.Sign(diff_xA) != Math.Sign(diff_xC)); double diff_yA = _xy.Y - _xyA.Y; double diff_yB = _xy.Y - _xyB.Y; double diff_yC = _xy.Y - _xyC.Y; bool inside_y = (Math.Sign(diff_yA) != Math.Sign(diff_yB)) || (Math.Sign(diff_yA) != Math.Sign(diff_yC)); return(inside_x && inside_y); }
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 Dictionary <Coords2D, double> Lists2Func2D(List <double> _xs, List <double> _ys, List <double> _zs) { if (_xs == null || _ys == null || _zs == null) { return(null); } int n = _xs.Count; if (n < 1 || n != _ys.Count || n != _zs.Count) { return(new Dictionary <Coords2D, double>()); } Dictionary <Coords2D, double> Fxy = new Dictionary <Coords2D, double>(); for (int i = 0; i < n; i++) { Coords2D xy = new Coords2D(_xs[i], _ys[i]); if (Fxy.ContainsKey(xy)) { continue; } Fxy.Add(xy, _zs[i]); } return(Fxy); }
public static bool InGeneralPosition(Coords2D _xy1, Coords2D _xy2) { if (_xy1 == null || _xy2 == null) { return(false); } double diffX = _xy1.X - _xy2.X; double diffY = _xy1.Y - _xy2.Y; return(Math.Abs(diffX) >= Calculation.MIN_DOUBLE_VAL || Math.Abs(diffY) >= Calculation.MIN_DOUBLE_VAL); }
public static bool InGeneralPosition(Coords2D _xy1, Coords2D _xy2, Coords2D _xy3) { return(Coords2D.InGeneralPosition(_xy1, _xy2) && Coords2D.InGeneralPosition(_xy2, _xy3) && Coords2D.InGeneralPosition(_xy3, _xy1)); }
public static double Interpolate2D(Coords2D _xy, List <Coords2D> _XYs, List <double> _Zs) { Dictionary <Coords2D, double> Fxy = Lists2Func2D(_XYs, _Zs); return(Interpolate2D(_xy, Fxy)); }
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]); }