/// <summary> /// Gets whether a given point is inside a triangle /// </summary> /// <param name="p">Point</param> /// <param name="triangle">Triangle defined by 3 points</param> /// <returns>True if the point is inside given triangle</returns> public static bool IsPointInTriangle(Point3D p, Tuple <Point3D, Point3D, Point3D> triangle) { // taken from http://www.blackpawn.com/texts/pointinpoly/default.html // Compute vectors Point3D a = triangle.Item1; Point3D b = triangle.Item2; Point3D c = triangle.Item3; Point3D v0 = c - a; Point3D v1 = b - a; Point3D v2 = p - a; // Compute dot products float dot00 = v0.DotProduct(v0); float dot01 = v0.DotProduct(v1); float dot02 = v0.DotProduct(v2); float dot11 = v1.DotProduct(v1); float dot12 = v1.DotProduct(v2); // Compute barycentric coordinates double invDenom = 1F / (dot00 * dot11 - dot01 * dot01); double u = (dot11 * dot02 - dot01 * dot12) * invDenom; double v = (dot00 * dot12 - dot01 * dot02) * invDenom; // Check if point is in triangle return((u >= 0) && (v >= 0) && (u + v <= 1)); }
/// <summary> /// Gets the line fragment intersection with a triangle (if any). /// </summary> /// <param name="triangle">Triangle defined by 3 points</param> /// <param name="line">Line fragment defined by 2 points</param> /// <returns>First item = 0 --> no intersetion; first item = 1 --> one /// intersection in the second item; first item = 2 --> line is on the /// plane</returns> public static Tuple <int, Point3D> GetTriangleIntersection(Tuple <Point3D, Point3D, Point3D> triangle, Vector3D line) { #if DIAG _IntersectCounter++; #endif Point3D vU1U2 = line.Point2 - line.Point1; Point3D vU1P1 = triangle.Item2 - line.Point1; Point3D norm = GetPlanesNormal(triangle); float lenNormU1U2 = norm.DotProduct(vU1U2); float lenNormU1P1 = norm.DotProduct(vU1P1); // normala dotProduct usecka => kdyz je to 0, jsou kolme, normala je kolma na plochu, tedy usecka a plocha jsou paralelni if (lenNormU1U2.EqEps(0)) { if (lenNormU1P1.EqEps(0)) { // usecka lezi v rovine definovane trojuhelnikem.... detekuj si prunik usecky strojuhelnikem sam :-) return(Tuple.Create <int, Point3D>(2, null)); } else { // usecka je paralelni s rovinou, takze nic se nikdy neprotne return(Tuple.Create <int, Point3D>(0, null)); } } // 0 zacatek, 1 konec usecky... uzavreny interval [0;1] == na usecce :-) float position = lenNormU1P1 / lenNormU1U2; if (0 <= position && position <= 1) { // ha!, usecka protina rovinu definovanou trojuhelnikem.... ted jen zjistit jestli ten bod je v tom trojuhelniku // měla by platit rovnost pro všechny 4 body roviny: // NBx = ZjistiNormaluPlochuDefinovanouTremiBodyVole(plocha) // NBx.Item1.DotProduct( [ plocha.Item1 ...až plocha.Item3 a bodPruniku] ) == NBx.Item3 // jestli ne, mám něco blbě, což by nebylo nic zvláštního :) Point3D intersection = line.Point1 + vU1U2 * position; if (IsPointInTriangle(intersection, triangle)) { return(Tuple.Create(1, intersection)); } return(Tuple.Create <int, Point3D>(0, null)); } // usecka NEprotina plochu, ale kdybys ji prodlouzil (kdyby to byla primka), tak by rovinu protnula v bode (usecka.Item1 + vU1U2 * pozice) return(Tuple.Create <int, Point3D>(0, null)); }