示例#1
0
        internal static float GetEdgeLength(ITriangle triangle, TriangleEdge edge)
        {
            Vector3 point0 = triangle.GetPoint(edge, true);
            Vector3 point1 = triangle.GetPoint(edge, false);

            return((point1 - point0).magnitude);
        }
示例#2
0
        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");
        }
示例#3
0
        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;
            }