using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Media.Media3D; namespace Microsoft.Research.DynamicDataDisplay.Common.Auxiliary { public static class TriangleMath { public static bool TriangleContains(Point a, Point b, Point c, Point m) { double a0 = a.X - c.X; double a1 = b.X - c.X; double a2 = a.Y - c.Y; double a3 = b.Y - c.Y; if (AreClose(a0 * a3, a1 * a2)) { // determinant is too close to zero => apexes are on one line Vector ab = a - b; Vector ac = a - c; Vector bc = b - c; Vector ax = a - m; Vector bx = b - m; bool res = AreClose(ab.X * ax.Y, ab.Y * ax.X) && !AreClose(ab.LengthSquared, 0) || AreClose(ac.X * ax.Y, ac.Y * ax.X) && !AreClose(ac.LengthSquared, 0) || AreClose(bc.X * bx.Y, bc.Y * bx.X) && !AreClose(bc.LengthSquared, 0); return res; } else { double b1 = m.X - c.X; double b2 = m.Y - c.Y; // alpha, beta and gamma - are baricentric coordinates of v // in triangle with apexes a, b and c double beta = (b2 / a2 * a0 - b1) / (a3 / a2 * a0 - a1); double alpha = (b1 - a1 * beta) / a0; double gamma = 1 - beta - alpha; return alpha >= 0 && beta >= 0 && gamma >= 0; } } private const double eps = 0.00001; private static bool AreClose(double x, double y) { return Math.Abs(x - y) < eps; } public static Vector3D GetBaricentricCoordinates(Point a, Point b, Point c, Point m) { double Sac = GetSquare(a, c, m); double Sbc = GetSquare(b, c, m); double Sab = GetSquare(a, b, m); double sum = (Sab + Sac + Sbc) / 3; return new Vector3D(Sbc / sum, Sac / sum, Sab / sum); } public static double GetSquare(Point a, Point b, Point c) { double ab = (a - b).Length; double ac = (a - c).Length; double bc = (b - c).Length; double p = 0.5 * (ab + ac + bc); // half of perimeter return Math.Sqrt(p * (p - ab) * (p - ac) * (p - bc)); } } }