public void Plane_ContainsLineOnOrigin()
        {
            Plane testPlane = new Plane(Point.Origin, Point.MakePointWithInches(1, 3, 0), Point.MakePointWithInches(-3, -1, 0));
            Line testLine = new Line(Point.Origin, Point.MakePointWithInches(1, 1, 0));

            bool result = testPlane.Contains(testLine);

            result.Should().BeTrue();
        }
        public void Plane_ContainsLine()
        {
            Plane testPlane = new Plane(Point.Origin, Point.MakePointWithInches(1, 3, 0), Point.MakePointWithInches(4, -2, 0));
            Line testLine = new Line(Point.MakePointWithInches(2, 0, 0), Point.MakePointWithInches(0, -1, 0));
            Line testFalseLine = new Line(Point.MakePointWithInches(1, 2, -2), Point.MakePointWithInches(2, 4, 3));

            bool result = testPlane.Contains(testLine);
            bool result2 = testPlane.Contains(testFalseLine);

            result.Should().BeTrue();
            result2.Should().BeFalse();
        }
        public void Plane_ContainsPoint()
        {
            Plane testPlane = new Plane(Point.MakePointWithInches(0,1,0), Point.MakePointWithInches(2,1,-3), Point.MakePointWithInches(-4,1,-1));
            Point testPoint1 = Point.MakePointWithInches(0, 1, 5);
            Point testPoint2 = Point.MakePointWithInches(2, 2, 2);

            bool result1 = testPlane.Contains(testPoint1);
            bool result2 = testPlane.Contains(testPoint2);

            result1.Should().BeTrue();
            result2.Should().BeFalse();
        }
 public static List<Point> ProjectAllOntoPlane(this IEnumerable<Point> pointList, Plane plane)
 {
     var results = new List<Point>();
     foreach (var point in pointList)
     {
         var pointInPlane = point.ProjectOntoPlane(plane);
         if (pointInPlane != null && !results.Contains(pointInPlane))
         {
             results.Add(pointInPlane);
         }
     }
     return results;
 }
        public void Plane_ContainsPolygon()
        {
            Plane testPlane = new Plane(Point.MakePointWithInches(1, 0, 0), Point.MakePointWithInches(1, -3, 4), Point.MakePointWithInches(1, 2, 2));
            Polygon testRegion = new Polygon(new List<Point>
                {
                    Point.MakePointWithInches(1,1,1),
                    Point.MakePointWithInches(1,2,1),
                    Point.MakePointWithInches(1,2,2),
                    Point.MakePointWithInches(1,1,2)
                });

            bool result = testPlane.Contains(testRegion);

            result.Should().BeTrue();
        }
        /// <summary>
        /// Finds all the polygons in this list that touch the plane passed in. If the includeContained flag is false, it will not return any 
        /// polygons contained by the the plane
        /// </summary>
        /// <param name="polygonList">The list of polygons to to see if they touch the planes</param>
        /// <param name="toSeeIfTouches">The plane to see if the polygons touch</param>
        /// <param name="includeContained">If true it will include any polygons in the list that are contained in the plane, false it will not</param>
        /// <returns>Returns the polygons that are touching this plane</returns>
        public static List<Polygon> FindPolygonsTouchingPlane(this List<Polygon> polygonList, Plane toSeeIfTouches, bool includeContained = false)
        {
            List<Polygon> touchingPolygons = new List<Polygon>();
            foreach (Polygon polygon in polygonList)
            {
                //see if they intersect
                if (toSeeIfTouches.Intersects(polygon))
                {
                    touchingPolygons.Add(polygon);
                }
                //they will not intersect if the are coplanar so we check here if we want to include contained ones
                else if (includeContained && toSeeIfTouches.Contains(polygon))
                {
                    touchingPolygons.Add(polygon);
                }
            }

            return touchingPolygons;
        }
        public void Plane_RotateTest()
        {
            Point testBasePoint = Point.MakePointWithInches(1, 1, -1);            
            Vector testNormalVector = new Vector(Point.MakePointWithInches(0, 2, 3), Point.MakePointWithInches(-3, -2, 0));

            Plane testPlane = new Plane(testNormalVector.Direction, testBasePoint);

            Line rotationAxis = new Line(new Direction(Point.MakePointWithInches(1, 1, 1)), Point.MakePointWithInches(1, -1, -1));
            Angle rotationAngle = new Angle(new Degree(), 212);

            Plane actualResult = testPlane.Rotate(new Rotation(rotationAxis, rotationAngle));

            Point expectedPoint = Point.MakePointWithInches(2.8439301238119032, -1.4640641282085687, -0.37986599560333495);
            Vector expectedVector = new Vector(Point.MakePointWithInches(5.23819525861547, 1.681697053112619, -1.91989231172809), Point.MakePointWithInches(1.3162301967095191, -1.0862708827830958, -5.2299593139264218));
            Plane expectedResult = new Plane(expectedVector.Direction, expectedPoint);

            bool test = expectedPoint == actualResult.BasePoint;
            bool test2 = expectedVector == actualResult.NormalVector;

            (actualResult == expectedResult).Should().BeTrue();
        }
        public static List<Polygon> MakeCoplanarLineSegmentsIntoPolygons(this List<LineSegment> passedLineSegments)
        {
            List<Plane> planesList = new List<Plane>();

            foreach (var segment1 in passedLineSegments)
            {
                foreach (var segment2 in passedLineSegments)
                {
                    if ((segment1.BasePoint == segment2.BasePoint && segment1.EndPoint != segment2.EndPoint) ||
                        (segment1.BasePoint != segment2.BasePoint && segment1.EndPoint == segment2.EndPoint))     
                    {
                        Plane possiblePlane = new Plane(segment1, segment2);
                        if (!planesList.Contains(possiblePlane))
                        {
                            planesList.Add(possiblePlane);
                        }
                    }
                }
            }

            List<Polygon> returnList = new List<Polygon>();

            foreach (var plane in planesList)
            {
                List<LineSegment> newRegionBoundaries = new List<LineSegment>();
                foreach (var segment in passedLineSegments)
                {
                    if (plane.Contains(segment) && !newRegionBoundaries.Contains(segment))
                    {
                        newRegionBoundaries.Add(segment);
                    }
                }
                returnList.Add(new Polygon(newRegionBoundaries));
            }

            return returnList;
        }
        public void Polyhedron_SliceThroughOppositeEdges()
        {
            Point bottomPoint1 = Point.Origin;
            Point bottomPoint2 = Point.MakePointWithInches(0, 12, 0);
            Point bottomPoint3 = Point.MakePointWithInches(4, 12, 0);
            Point bottomPoint4 = Point.MakePointWithInches(4, 0, 0);

            Point topPoint1 = Point.MakePointWithInches(0, 0, 2);
            Point topPoint2 = Point.MakePointWithInches(0, 12, 2);
            Point topPoint3 = Point.MakePointWithInches(4, 12, 2);
            Point topPoint4 = Point.MakePointWithInches(4, 0, 2);

            List<Polygon> faces = new List<Polygon>();
            faces.Add(new Polygon(new List<Point> { bottomPoint1, bottomPoint2, bottomPoint3, bottomPoint4 }));
            faces.Add(new Polygon(new List<Point> { topPoint1, topPoint2, topPoint3, topPoint4}));
            faces.Add(new Polygon(new List<Point> { bottomPoint1, topPoint1, topPoint2, bottomPoint2}));
            faces.Add(new Polygon(new List<Point> { bottomPoint2, topPoint2, topPoint3, bottomPoint3 }));
            faces.Add(new Polygon(new List<Point> { bottomPoint3, topPoint3, topPoint4, bottomPoint4 }));
            faces.Add(new Polygon(new List<Point> { bottomPoint4, topPoint4, topPoint1, bottomPoint1 }));
            Polyhedron testPolyhedron = new Polyhedron(faces);

            Plane slicingPlane = new Plane(bottomPoint1, bottomPoint4, topPoint2);
            
            List<Polyhedron> results = testPolyhedron.Slice(slicingPlane);


            List<Polygon> polygons1 = new List<Polygon>();
            polygons1.Add(new Polygon(new List<Point> { bottomPoint1, bottomPoint2, bottomPoint3, bottomPoint4 }));
            polygons1.Add(new Polygon(new List<Point> { bottomPoint2, bottomPoint3, topPoint3, topPoint2 }));
            polygons1.Add(new Polygon(new List<Point> { bottomPoint4, bottomPoint1, topPoint2, topPoint3 }));
            polygons1.Add(new Polygon(new List<Point> { bottomPoint1, bottomPoint2, topPoint2 }));
            polygons1.Add(new Polygon(new List<Point> { bottomPoint3, bottomPoint4, topPoint3 }));
            Polyhedron expected1 = new Polyhedron(polygons1);

            List<Polygon> polygons2 = new List<Polygon>();
            polygons2.Add(new Polygon(new List<Point> { topPoint1, topPoint2, topPoint3, topPoint4 }));
            polygons2.Add(new Polygon(new List<Point> { topPoint4, topPoint1, bottomPoint1, bottomPoint4 }));
            polygons2.Add(new Polygon(new List<Point> { bottomPoint4, bottomPoint1, topPoint2, topPoint3 }));
            polygons2.Add(new Polygon(new List<Point> { topPoint1, topPoint2, bottomPoint1 }));
            polygons2.Add(new Polygon(new List<Point> { topPoint3, topPoint4, bottomPoint4 }));
            Polyhedron expected2 = new Polyhedron(polygons2);
            
            //now test to see if we got what we expect
            results.Count.Should().Be(2);
            results.Contains(expected1).Should().BeTrue();
            results.Contains(expected2).Should().BeTrue();
        }
        public void Polygon_SliceAnotherCaseThatDidntWorkBefore()
        {
            List<LineSegment> bounds = new List<LineSegment>();
            bounds.Add(new LineSegment(Point.Origin, Point.MakePointWithInches(0, 0, 1.5)));
            bounds.Add(new LineSegment(Point.MakePointWithInches(0, 0, 1.5), Point.MakePointWithInches(240, 0, 1.5)));
            bounds.Add(new LineSegment(Point.MakePointWithInches(240, 0, 1.5), Point.MakePointWithInches(240, 0, 0)));
            bounds.Add(new LineSegment(Point.MakePointWithInches(240, 0, 0), Point.Origin));
            Polygon testPolygon = new Polygon(bounds);

            Plane slicingPlane = new Plane(new Direction(new Angle(new Radian(), 5.6548667765)), Point.MakePointWithInches(122.8315595, 169.313137732, 0));

            List<Polygon> results = testPolygon.Slice(slicingPlane);

            //create the expected planes to compare to
            List<LineSegment> expected1Bounds = new List<LineSegment>();
            expected1Bounds.Add(new LineSegment(Point.Origin, Point.MakePointWithInches(240, 0, 0)));
            expected1Bounds.Add(new LineSegment(Point.MakePointWithInches(240, 0, 0), Point.MakePointWithInches(240, 0, 1.5)));
            expected1Bounds.Add(new LineSegment(Point.MakePointWithInches(240, 0, 1.5), Point.MakePointWithInches(0, 0, 1.5)));
            expected1Bounds.Add(new LineSegment(Point.MakePointWithInches(0, 0, 1.5), Point.Origin));
            Polygon expected1 = new Polygon(expected1Bounds);

            //should only return the original plane
            results.Count.Should().Be(1);
            (results[0] == testPolygon).Should().BeTrue();
        }
        /// <summary>
        /// determines if the points in the list, all lie on the same side of the dividing plane.
        /// Points on the plane are disregarded
        /// </summary>
        /// <param name="plane"></param>
        /// <returns></returns>
        public static bool AllPointsAreOnTheSameSideOf(this List<Point> pointList, Plane plane)
        {
            int index = 0;
            //find a reference point
            for (int i = 0; i < pointList.Count; i++)
		    {
			    if (!plane.Contains(pointList[i]))
                {
                    index = i;
                    break;
                }
		    }
            Point referencePoint = pointList[index];   
            
            //Now check the remaining points
            for (int i = index + 1; i < pointList.Count; i++)
            {
                if (!plane.Contains(pointList[i]) && !plane.PointIsOnSameSideAs(pointList[i], referencePoint))
                {
                    return false;
                }
            }
            return true;
        }
 public static List<LineSegment> ProjectAllOntoPlane(this IList<LineSegment> segmentList, Plane plane)
 {
     var results = new List<LineSegment>();
     foreach(var segment in segmentList)
     {
         var newSegment = segment.ProjectOntoPlane(plane);
         if (newSegment != null && !results.Contains(newSegment))
         {
             results.Add(newSegment);
         }
     }
     return results;
 }
        public void Polygon_SliceACaseThatDidntWorkBefore()
        {
            List<LineSegment> bounds = new List<LineSegment>();
            bounds.Add(new LineSegment(Point.Origin, Point.MakePointWithInches(0, 3.5, 0)));
            bounds.Add(new LineSegment(Point.MakePointWithInches(0, 3.5, 0), Point.MakePointWithInches(240, 3.5, 0)));
            bounds.Add(new LineSegment(Point.MakePointWithInches(240, 3.5, 0), Point.MakePointWithInches(240, 0, 0)));
            bounds.Add(new LineSegment(Point.MakePointWithInches(240, 0, 0), Point.Origin));
            Polygon testPolygon = new Polygon(bounds);

            Plane slicingPlane = new Plane(new Direction(new Angle(new Radian(), 5.6548667765)), Point.MakePointWithInches(122.8315595, 169.313137732, 0));

            List<Polygon> results = testPolygon.Slice(slicingPlane);

            //create the expected planes to compare to
            List<LineSegment> expected1Bounds = new List<LineSegment>();
            expected1Bounds.Add(new LineSegment(Point.Origin, Point.MakePointWithInches(0, 0.25, 0)));
            expected1Bounds.Add(new LineSegment(Point.MakePointWithInches(0, 0.25, 0), Point.MakePointWithInches(2.36126321602, 3.5, 0)));
            expected1Bounds.Add(new LineSegment(Point.MakePointWithInches(2.36126321602, 3.5, 0), Point.MakePointWithInches(240, 3.5, 0)));
            expected1Bounds.Add(new LineSegment(Point.MakePointWithInches(240, 3.5, 0), Point.MakePointWithInches(240, 0, 0)));
            expected1Bounds.Add(new LineSegment(Point.MakePointWithInches(240, 0, 0), Point.Origin));
            Polygon expected1 = new Polygon(expected1Bounds);

            List<LineSegment> expected2Bounds = new List<LineSegment>();
            expected2Bounds.Add(new LineSegment(Point.MakePointWithInches(0, 0.25, 0), Point.MakePointWithInches(0, 3.5, 0)));
            expected2Bounds.Add(new LineSegment(Point.MakePointWithInches(0, 3.5, 0), Point.MakePointWithInches(2.36126321602, 3.5, 0)));
            expected2Bounds.Add(new LineSegment(Point.MakePointWithInches(2.36126321602, 3.5, 0), Point.MakePointWithInches(0, 0.25, 0)));
            Polygon expected2 = new Polygon(expected2Bounds);


            results.Contains(expected1).Should().BeTrue();
            results.Contains(expected2).Should().BeTrue();

            //now make sure it handles no intersection well
            Line notIntersecting = new Line(Point.Origin, Point.MakePointWithInches(1, 1, 0.9));
            List<Polygon> results2 = testPolygon.Slice(notIntersecting);

            //should only return the original plane
            results2.Count.Should().Be(1);
            (results2[0] == testPolygon).Should().BeTrue();
        }
        public void Plane_IntersectLine()
        {
            Plane testPlane1 = new Plane(new Direction(2, -1, 1), Point.MakePointWithInches(2, -1, 1));
            Plane testPlane2 = new Plane(new Direction(1, 2, -1), Point.MakePointWithInches(2, -1, 1));

            Line perpendicular1 = new Line(Point.MakePointWithInches(2, -1, 1));
            Line perpendicular2 = new Line(Point.MakePointWithInches(3, 1, -3), Point.MakePointWithInches(4, 3, -4)); //1, 2, -1

            Point intersection11 = testPlane1.IntersectWithLine(perpendicular1);
            Point intersection12 = testPlane1.IntersectWithLine(perpendicular2);
            Point intersection21 = testPlane2.IntersectWithLine(perpendicular1);
            Point intersection22 = testPlane2.IntersectWithLine(perpendicular2);

            intersection11.Should().Be(Point.MakePointWithInches(2, -1, 1));
            intersection21.Should().Be(Point.MakePointWithInches(2, -1, 1));
            intersection12.Should().Be(Point.MakePointWithInches(-1, -7, 1));
            intersection22.Should().Be(Point.MakePointWithInches(1.5, -2, -1.5));
        }
        public void Plane_ParallelLineTest()
        {
            Line plane1Line1 = new Line(Point.MakePointWithInches(1, 1, 0));
            Line plane1Line2 = new Line(Point.MakePointWithInches(2, 0, -1), Point.MakePointWithInches(3, 1, -1));
            Plane testPlane1 = new Plane(plane1Line1, plane1Line2);

            Line plane2Line1 = new Line(Point.MakePointWithInches(-3, 2, -2));
            Line plane2Line2 = new Line(Point.MakePointWithInches(1, -2, -1), Point.MakePointWithInches(-2, 0, -3));
            Plane testPlane2 = new Plane(plane2Line1, plane2Line2);

            Line parallel1 = new Line(Point.MakePointWithInches(1, -2, 1), Point.MakePointWithInches(2, -1, 1));
            Line parallel2 = new Line(Point.MakePointWithInches(-6, 4, -4));

            testPlane1.IsParallelTo(parallel1).Should().BeTrue();
            testPlane1.IsParallelTo(parallel2).Should().BeFalse();

            testPlane2.IsParallelTo(parallel1).Should().BeFalse();
            testPlane2.IsParallelTo(parallel2).Should().BeTrue();
        }
        public void Polyhedron_SliceAtVertex()
        {
            Point basePoint = Point.Origin;
            Point topLeftPoint = Point.MakePointWithInches(0, 12, 0);
            Point bottomRightPoint = Point.MakePointWithInches(4, 0, 0);
            Point topRightPoint = Point.MakePointWithInches(4, 12, 0);

            Point backbasepoint = Point.MakePointWithInches(0, 0, 2);
            Point backtopleftpoint = Point.MakePointWithInches(0, 12, 2);
            Point backbottomrightpoint = Point.MakePointWithInches(4, 0, 2);
            Point backtoprightpoint = Point.MakePointWithInches(4, 12, 2);

            List<Polygon> planes = new List<Polygon>();
            planes.Add(new Polygon(new List<Point> { basePoint, topLeftPoint, topRightPoint, bottomRightPoint }));
            planes.Add(new Polygon(new List<Point> { backbasepoint, backtopleftpoint, backtoprightpoint, backbottomrightpoint }));
            planes.Add(new Polygon(new List<Point> { topLeftPoint, topRightPoint, backtoprightpoint, backtopleftpoint }));
            planes.Add(new Polygon(new List<Point> { basePoint, bottomRightPoint, backbottomrightpoint, backbasepoint }));
            planes.Add(new Polygon(new List<Point> { basePoint, topLeftPoint, backtopleftpoint, backbasepoint }));
            planes.Add(new Polygon(new List<Point> { bottomRightPoint, topRightPoint, backtoprightpoint, backbottomrightpoint }));
            Polyhedron testPolyhedron = new Polyhedron(planes);

            Plane slicingPlane = new Plane(Point.MakePointWithInches(4, 12, 0), Point.MakePointWithInches(0, 8, 0), Point.MakePointWithInches(4, 12, 2));

            List<Polyhedron> results = testPolyhedron.Slice(slicingPlane);

            //make our results
            Point slicedPoint = Point.MakePointWithInches(0, 8, 0);
            Point slicedPointBack = Point.MakePointWithInches(0, 8, 2);

            List<Polygon> ExpectedPlanes1 = new List<Polygon>();
            ExpectedPlanes1.Add(new Polygon(new List<Point> { basePoint, slicedPoint, topRightPoint, bottomRightPoint }));
            ExpectedPlanes1.Add(new Polygon(new List<Point> { backbasepoint, slicedPointBack, backtoprightpoint, backbottomrightpoint }));
            ExpectedPlanes1.Add(new Polygon(new List<Point> { slicedPoint, topRightPoint, backtoprightpoint, slicedPointBack }));
            ExpectedPlanes1.Add(new Polygon(new List<Point> { basePoint, bottomRightPoint, backbottomrightpoint, backbasepoint }));
            ExpectedPlanes1.Add(new Polygon(new List<Point> { basePoint, slicedPoint, slicedPointBack, backbasepoint }));
            ExpectedPlanes1.Add(new Polygon(new List<Point> { bottomRightPoint, topRightPoint, backtoprightpoint, backbottomrightpoint }));
            Polyhedron ExpectedPolyhedron1 = new Polyhedron(ExpectedPlanes1);

            List<Polygon> ExpectedPlanes2 = new List<Polygon>();
            ExpectedPlanes2.Add(new Polygon(new List<Point> { topLeftPoint, topRightPoint, slicedPoint }));
            ExpectedPlanes2.Add(new Polygon(new List<Point> { backtopleftpoint, backtoprightpoint, slicedPointBack }));
            ExpectedPlanes2.Add(new Polygon(new List<Point> { topLeftPoint, topRightPoint, backtoprightpoint, backtopleftpoint }));
            ExpectedPlanes2.Add(new Polygon(new List<Point> { backtopleftpoint, slicedPointBack, slicedPoint, topLeftPoint }));
            ExpectedPlanes2.Add(new Polygon(new List<Point> { slicedPoint, slicedPointBack, backtoprightpoint, topRightPoint }));
            Polyhedron ExpectedPolyhedron2 = new Polyhedron(ExpectedPlanes2);

            //now test to see if we got what we expect
            results.Count.Should().Be(2);
            results.Contains(ExpectedPolyhedron1).Should().BeTrue();
            results.Contains(ExpectedPolyhedron2).Should().BeTrue();
        }
        public void LineSegment_DoesIntersectNotTouchingPlane_ShouldReturnFalse_IfBothEndPointsAreOnPlane()
        {
            LineSegment lineSegment = new LineSegment(Point.MakePointWithInches(1, 0, 0));
            Plane plane = new Plane(Direction.Right);

            lineSegment.DoesIntersectNotTouching(plane).Should().BeFalse();
        }
        public void Plane_IntersectLine_PrecisionCheck()
        {
            Point point1 = Point.MakePointWithInches(-2.5, 73, 3.5);
            Point point2 = Point.MakePointWithInches(1, 1, 2);
            Point point3 = Point.MakePointWithInches(0, 0, 2);
            
            Plane testPlane = new Plane(Direction.Out, point3);
            Line line = new Line(point1, point2);

            Point actualIntersection = testPlane.IntersectWithLine(line);
            Point expectedIntersection = point2;

            (actualIntersection == expectedIntersection).Should().BeTrue();
        }
        public void Plane_IntersectionWithPlane()
        {
            Plane testPlane1 = new Plane(new Direction(Point.MakePointWithInches(2, -1, 1)), Point.MakePointWithInches(2, 1, 2));
            Plane testPlane2 = new Plane(new Direction(Point.MakePointWithInches(1, 1, -1)), Point.MakePointWithInches(1, 3, 3));

            Line test12Intersect = testPlane1.IntersectWithPlane(testPlane2);
            Line test21Intersect = testPlane2.IntersectWithPlane(testPlane1);

            Line expectedLine = new Line(new Direction(Point.MakePointWithInches(0, 3, 3)), Point.MakePointWithInches(2, -1, 0));

            Assert.IsTrue(test12Intersect.Equals(test21Intersect));
            Assert.IsTrue(test21Intersect.Equals(expectedLine));
        }
        public void Plane_IntersectionWithPlane_IdenticalPlane()
        {
            Plane testPlane = new Plane(new Direction(2, -1, 1), Point.MakePointWithInches(2, 1, 2));

            Line found = (testPlane.IntersectWithPlane(testPlane));
            Line expected = new Line(new Direction(-1, 0, 2), Point.MakePointWithInches(2, 1, 2));

            testPlane.Contains(found).Should().BeTrue();
            (found == expected).Should().BeTrue();
        }
        public void Plane_IntersectLineOnPlane()
        {
            Plane testPlane = new Plane(Direction.Out);
            Line lineOnPlane = new Line(Point.MakePointWithInches(2, 1, 0));

            testPlane.IntersectWithLine(lineOnPlane).Should().Be(Point.Origin);
        }
        public void Plane_Intersect_Line_Segment()
        {
            Plane testPlane = new Plane(new Direction(2, -1, 1), Point.MakePointWithInches(2, -1, 1));

            var linesegment=new LineSegment(Point.MakePointWithInches(2, -1, 1));
            testPlane.Intersects(linesegment).Should().BeTrue();
            
        }
        public void LineSegment_ProjectOntoPlane_ShouldReturnNull_IfVectorLengthIsZero()
        {
            LineSegment lineSegment = new LineSegment(Point.MakePointWithInches(1, 0, 0));
            Plane plane = new Plane(Direction.Right);

            lineSegment.ProjectOntoPlane(plane).Should().BeNull();
        }
        public void LineSegment_DoesIntersectNotTouchingPlane_ShouldReturnTrue_IfEndPointsAreOnOppositeSidesOfThePlane()
        {
            LineSegment lineSegment = new LineSegment(Point.MakePointWithInches(1, 1, 1), Point.MakePointWithInches(-1, -1, -1));
            Plane plane = new Plane(Direction.Right);

            lineSegment.DoesIntersectNotTouching(plane).Should().BeTrue();
        }
        public void LineSegment_ProjectOntoPlane_ShouldReturnVectorProjection_IfVectorLengthIsNotZero()
        {
            LineSegment lineSegment = new LineSegment(Point.MakePointWithInches(1, 1, 1));
            Plane plane = new Plane(Direction.Right);

            Vector vector = new Vector(lineSegment.BasePoint, lineSegment.EndPoint);

            lineSegment.ProjectOntoPlane(plane).Should().Be(new LineSegment(vector.ProjectOntoPlane(plane)));
        }
        public void Plane_PerpendicularLineTest()
        {
            Plane testPlane1 = new Plane(new Direction(Point.MakePointWithInches(2, -1, 1)), Point.MakePointWithInches(2, 1, 2));
            Plane testPlane2 = new Plane(new Direction(Point.MakePointWithInches(1, 1, -1)), Point.MakePointWithInches(1, 3, 3));

            Line perpindicular1 = new Line(Point.MakePointWithInches(2, -1, 1));
            Line perpindicular2 = new Line(Point.MakePointWithInches(3, 1, -3), Point.MakePointWithInches(4, 2, -4));

            testPlane1.IsPerpendicularTo(perpindicular1).Should().BeTrue();
            testPlane1.IsPerpendicularTo(perpindicular2).Should().BeFalse();

            testPlane2.IsPerpendicularTo(perpindicular1).Should().BeFalse();
            testPlane2.IsPerpendicularTo(perpindicular2).Should().BeTrue();
        }
        public void LineSegment_DoesIntersectNotTouchingPlane_ShouldReturnFalse_IfEndPointsAreOnTheSameSideOfThePlane()
        {
            LineSegment lineSegment = new LineSegment(Point.MakePointWithInches(1, 1, 1), Point.MakePointWithInches(2, 2, 2));
            Plane plane = new Plane(Direction.Right);

            lineSegment.DoesIntersectNotTouching(plane).Should().BeFalse();
        }
        public void Plane_PointOnSameSideAs()
        {
            Point testPoint = Point.MakePointWithInches(1, 3, -1);
            Point testPoint2 = Point.MakePointWithInches(-1, -2, 5);
            Point testPoint3 = Point.MakePointWithInches(0, 1, 0);
            Point referencePoint = Point.MakePointWithInches(1, 2, 1);
            Point referencePoint2 = Point.MakePointWithInches(0, 2, 1);
            Vector testNormalVector = new Vector(Point.MakePointWithInches(1, 0, 0));

            Plane testPlane = new Plane(testNormalVector);

            testPlane.PointIsOnSameSideAs(testPoint, referencePoint).Should().BeTrue(); //test one on the same side
            testPlane.PointIsOnSameSideAs(testPoint2, referencePoint).Should().BeFalse(); //test one on the opposite side
            testPlane.PointIsOnSameSideAs(testPoint3, referencePoint).Should().BeFalse(); //test one on the plane
            testPlane.PointIsOnSameSideAs(testPoint, referencePoint2).Should().BeFalse(); //test a reference point on the plane


            Point testPointOffOrigin = Point.MakePointWithInches(5, 4, 0);
            Point testPointOffOrigin2 = Point.MakePointWithInches(5, -2, 0);
            Point referencePointOffOrigin = Point.MakePointWithInches(1, 2, 3);
            Point planeBase = Point.MakePointWithInches(1, -4, 2);
            Vector testNormalVectorOffOrigin = new Vector(Point.MakePointWithInches(-1, 2, 1));

            Plane testPlaneOffOrigin = new Plane(testNormalVectorOffOrigin.Direction, planeBase);

            testPlaneOffOrigin.PointIsOnSameSideAs(testPointOffOrigin, referencePointOffOrigin).Should().BeTrue();
            testPlaneOffOrigin.PointIsOnSameSideAs(testPointOffOrigin2, referencePointOffOrigin).Should().BeFalse();
            testPlaneOffOrigin.PointIsOnSameSideAs(planeBase, referencePointOffOrigin).Should().BeFalse();

        }
        public void Vector_ProjectOntoPlane()
        {
            Vector testSegment = new Vector(Point.MakePointWithInches(2, 5, 3));
            Plane projectOnto = new Plane(Line.XAxis, Line.YAxis);

            Vector result = testSegment.ProjectOntoPlane(projectOnto);

            Vector expected = new Vector(Point.MakePointWithInches(2, 5));

            result.Should().Be(expected);
        }
        public void Plane_IntersectionWithPlane_ZeroCases()
        {
            //try all the zero cases
            Point testPoint = Point.Origin;
            Point testPointX = Point.MakePointWithInches(10, 0, 0);
            Point testPointY = Point.MakePointWithInches(0, 10, 0);
            Point testPointZ = Point.MakePointWithInches(0, 0, 10);

            Plane testPlaneXY = new Plane(testPoint, testPointX, testPointY);
            Plane testPlaneXZ = new Plane(testPoint, testPointX, testPointZ);
            Plane testPlaneYZ = new Plane(testPoint, testPointY, testPointZ);

            Line testXYXZIntersect = testPlaneXZ.IntersectWithPlane(testPlaneXY);
            Line testXZXYIntersect = testPlaneXY.IntersectWithPlane(testPlaneXZ);
            testXYXZIntersect.Should().Be(Line.XAxis);
            testXZXYIntersect.Should().Be(Line.XAxis);

            Line testXYYZIntersect = testPlaneXY.IntersectWithPlane(testPlaneYZ);
            Line testYZXYIntersect = testPlaneYZ.IntersectWithPlane(testPlaneXY);
            testXYYZIntersect.Should().Be(Line.YAxis);
            testYZXYIntersect.Should().Be(Line.YAxis);

            Line testXZYZIntersect = testPlaneXZ.IntersectWithPlane(testPlaneYZ);
            Line testYZXZIntersect = testPlaneYZ.IntersectWithPlane(testPlaneXZ);
            testXZYZIntersect.Should().Be(Line.ZAxis);
            testYZXZIntersect.Should().Be(Line.ZAxis);

            Line testXYXY = testPlaneXY.IntersectWithPlane(testPlaneXY);
            testXYXY.Should().Be(Line.YAxis);
        }