internal static float GetEdgeLength(ITriangle triangle, TriangleEdge edge) { Vector3 point0 = triangle.GetPoint(edge, true); Vector3 point1 = triangle.GetPoint(edge, false); return((point1 - point0).magnitude); }
internal static Vector3 GetUncommonPoint(ITriangle triangle, TriangleEdge edge0, TriangleEdge edge1) { Vector3[] points0 = new Vector3[] { triangle.GetPoint(edge0, true), triangle.GetPoint(edge0, false) }; Vector3[] points1 = new Vector3[] { triangle.GetPoint(edge1, true), triangle.GetPoint(edge1, false) }; // Find exact for (int cntr0 = 0; cntr0 < points0.Length; cntr0++) { for (int cntr1 = 0; cntr1 < points1.Length; cntr1++) { if (points0[cntr0] == points1[cntr1]) { return(points0[cntr0 == 0 ? 1 : 0]); // return the one that isn't common } } } // Find close - execution should never get here, just being safe for (int cntr0 = 0; cntr0 < points0.Length; cntr0++) { for (int cntr1 = 0; cntr1 < points1.Length; cntr1++) { if (points0[cntr0].IsNearValue(points1[cntr1])) { return(points0[cntr0 == 0 ? 1 : 0]); // return the one that isn't common } } } throw new ApplicationException("Didn't find a common point"); }
internal static Vector3 GetEdgeMidpoint(ITriangle triangle, TriangleEdge edge) { Vector3 point0 = triangle.GetPoint(edge, true); Vector3 point1 = triangle.GetPoint(edge, false); Vector3 halfLength = (point1 - point0) * .5f; return(point0 + halfLength); }
private static Tuple<Point3D, Point3D> GetIntersection_Plane_Triangle(ITriangle plane, ITriangle triangle) { // Get the line of intersection of the two planes Point3D pointOnLine; Vector3D lineDirection; if (!Math3D.GetIntersection_Plane_Plane(out pointOnLine, out lineDirection, plane, triangle)) { return null; } List<Point3D> retval = new List<Point3D>(); // Cap to the triangle foreach (TriangleEdge edge in Triangle.Edges) { Point3D[] resultsLine, resultsLineSegment; if (!Math3D.GetClosestPoints_Line_LineSegment(out resultsLine, out resultsLineSegment, pointOnLine, lineDirection, triangle.GetPoint(edge, true), triangle.GetPoint(edge, false))) { continue; } if (resultsLine.Length != resultsLineSegment.Length) { throw new ApplicationException("The line vs line segments have a different number of matches"); } // This method is dealing with lines that are in the same plane, so if the result point for the plane/plane line is different // than the triangle edge, then throw out this match bool allMatched = true; for (int cntr = 0; cntr < resultsLine.Length; cntr++) { if (!Math3D.IsNearValue(resultsLine[cntr], resultsLineSegment[cntr])) { allMatched = false; break; } } if (!allMatched) { continue; } retval.AddRange(resultsLineSegment); if (retval.Count >= 2) { // No need to keep looking, there will only be up to two points of intersection break; } } // Exit Function if (retval.Count == 0) { return null; } else if (retval.Count == 1) { // Only touched one vertex return Tuple.Create(retval[0], retval[0]); } else if (retval.Count == 2) { // Standard result return Tuple.Create(retval[0], retval[1]); } else { throw new ApplicationException("Found more than two intersection points"); } }
/// <summary> /// This draws a line from pointOnTriangle toward guidePoint, and stops at the edge of the triangle (returning that point on the edge). /// Returns null if the point passed in is already sitting on the desired edge, or if pointOnTriangle+guidePoint is orthogonal to the triangle /// </summary> internal static Tuple<TriangleEdge, Point3D> GetPointOnTriangleEdge(ITriangle triangle, Point3D pointOnTriangle, Point3D guidePoint) { // Make the guide line parallel to the triangle Vector3D guideDirection = (guidePoint - pointOnTriangle).GetProjectedVector(triangle); if (Math3D.IsInvalid(guideDirection)) { // Guide guideDirection is perpendicular to the triangle return null; } guideDirection.Normalize(); Point3D guidePoint2 = pointOnTriangle + guideDirection; Point3D? resultEdge, resultGuide; foreach (TriangleEdge edge in Triangle.Edges) { // Since the test points are coplanar, this will return a value that is also coplanar if (!Math3D.GetClosestPoints_Line_Line(out resultEdge, out resultGuide, triangle.GetPoint(edge, true), triangle.GetPoint(edge, false), pointOnTriangle, guidePoint2)) { continue; } // Make sure it's not outside the triangle if (!Math3D.IsNearTriangle(triangle, resultEdge.Value, false)) { continue; } // See if pointOnTriangle is already sitting on this edge Vector3D towardResult = resultEdge.Value - pointOnTriangle; if (Math3D.IsNearZero(towardResult)) { continue; } towardResult.Normalize(); // Make sure it's along the guide direction if (!Math1D.IsNearValue(Vector3D.DotProduct(towardResult, guideDirection), 1d)) { continue; } // Exit Function return Tuple.Create(edge, resultEdge.Value); } // The only way this should happen is if pointOnTriangle is sitting on the triangle's edge, and that's the edge that // the guide line is pointing toward (so it's basically saying, there is no point closer to the edge than pointOnTriangle) return null; }
private static Point3D[] TwoInside(ITriangleIndexed[] hull, ITriangle triangle, int insidePointIndex1, int insidePointIndex2) { if (insidePointIndex1 > insidePointIndex2) { // Reverse them to simplify the switch statements return TwoInside(hull, triangle, insidePointIndex2, insidePointIndex1); } #region Examine Indices TriangleEdge edgeLeft, edgeRight; Point3D insidePointLeft, insidePointRight, insidePointMiddle, outsideCenterPoint; switch (insidePointIndex1) { case 0: switch (insidePointIndex2) { case 1: #region 0, 1 edgeLeft = TriangleEdge.Edge_20; edgeRight = TriangleEdge.Edge_12; insidePointLeft = triangle.Point0; insidePointRight = triangle.Point1; insidePointMiddle = triangle.GetEdgeMidpoint(TriangleEdge.Edge_01); outsideCenterPoint = triangle.Point2; #endregion break; case 2: #region 0, 2 edgeLeft = TriangleEdge.Edge_01; edgeRight = TriangleEdge.Edge_12; insidePointLeft = triangle.Point0; insidePointRight = triangle.Point2; insidePointMiddle = triangle.GetEdgeMidpoint(TriangleEdge.Edge_20); outsideCenterPoint = triangle.Point1; #endregion break; default: throw new ApplicationException("Unexpected point: " + insidePointIndex2.ToString()); } break; case 1: #region 1, 2 if (insidePointIndex2 != 2) { throw new ApplicationException("Unexpected point: " + insidePointIndex2.ToString()); } edgeLeft = TriangleEdge.Edge_01; edgeRight = TriangleEdge.Edge_20; insidePointLeft = triangle.Point1; insidePointRight = triangle.Point2; insidePointMiddle = triangle.GetEdgeMidpoint(TriangleEdge.Edge_12); outsideCenterPoint = triangle.Point0; #endregion break; default: throw new ApplicationException("Unexpected point: " + insidePointIndex2.ToString()); } // Make sure that outsideCenterPoint is outside the hull outsideCenterPoint = EnsureOutsidePointIsBeyondHull(hull[0].AllPoints, insidePointMiddle, outsideCenterPoint); #endregion // Get edge/hull intersections var intersectLeft = GetIntersectPoints(hull, triangle.GetPoint(edgeLeft, true), triangle.GetPoint(edgeLeft, false)); if (intersectLeft.Length == 0) { return null; // triangle is only touching the hull, not really intersecting } var intersectRight = GetIntersectPoints(hull, triangle.GetPoint(edgeRight, true), triangle.GetPoint(edgeRight, false)); if (intersectRight.Length == 0) { return null; } // Now that the two intersect points are found, find connecting lines Point3D[] hullEdge = GetConnectingLines(hull, intersectLeft[0], intersectRight[0], outsideCenterPoint); // Clip poly List<Point3D> hullPoly = new List<Point3D>(); hullPoly.Add(insidePointLeft); hullPoly.AddRange(hullEdge); hullPoly.Add(insidePointRight); Point3D[] retVal = Math2D.GetIntersection_Polygon_Triangle(hullPoly.ToArray(), triangle); // Exit Function return retVal; }
private static Point3D[] OneInside(ITriangleIndexed[] hull, ITriangle triangle, int insidePointIndex) { #region Examine Index TriangleEdge edge1, edge2, edgeOutside; // Edges that are intersecting the hull Point3D insidePoint, outsideCenterPoint; switch (insidePointIndex) { case 0: edge1 = TriangleEdge.Edge_01; edge2 = TriangleEdge.Edge_20; edgeOutside = TriangleEdge.Edge_12; insidePoint = triangle.Point0; outsideCenterPoint = triangle.GetEdgeMidpoint(edgeOutside); break; case 1: edge1 = TriangleEdge.Edge_01; edge2 = TriangleEdge.Edge_12; edgeOutside = TriangleEdge.Edge_20; insidePoint = triangle.Point1; outsideCenterPoint = triangle.GetEdgeMidpoint(edgeOutside); break; case 2: edge1 = TriangleEdge.Edge_12; edge2 = TriangleEdge.Edge_20; edgeOutside = TriangleEdge.Edge_01; insidePoint = triangle.Point2; outsideCenterPoint = triangle.GetEdgeMidpoint(edgeOutside); break; default: throw new ApplicationException("Unexpected point: " + insidePointIndex.ToString()); } // Make sure that outsideCenterPoint is outside the hull outsideCenterPoint = EnsureOutsidePointIsBeyondHull(hull[0].AllPoints, insidePoint, outsideCenterPoint); #endregion // Get edge/hull intersections var intersect1 = GetIntersectPoints(hull, triangle.GetPoint(edge1, true), triangle.GetPoint(edge1, false)); if (intersect1.Length == 0) { return null; // triangle is only touching the hull, not really intersecting } else if (intersect1.Length > 1) { throw new ApplicationException("Should never get more than one intersect point: " + intersect1.Length.ToString()); } var intersect2 = GetIntersectPoints(hull, triangle.GetPoint(edge2, true), triangle.GetPoint(edge2, false)); if (intersect2.Length == 0) { return null; } else if (intersect2.Length > 1) { throw new ApplicationException("Should never get more than one intersect point: " + intersect2.Length.ToString()); } // Now that the two intersect points are found, find connecting lines Point3D[] hullEdge = GetConnectingLines(hull, intersect1[0], intersect2[0], outsideCenterPoint); // Clip poly List<Point3D> hullPoly = new List<Point3D>(); hullPoly.Add(insidePoint); hullPoly.AddRange(hullEdge); Point3D[] retVal = Math2D.GetIntersection_Polygon_Triangle(hullPoly.ToArray(), triangle); // Exit Function return retVal; }