public void RectangularPrism_ConstructorTest()
        {
            var height = new Distance(new Inch(), 5);
            var width = new Distance(new Inch(), 5);
            var length = new Distance(new Inch(), 5);
            RectangularPrism prism = new RectangularPrism(width, height, length);

            //make sure it was made right
            (prism.LineSegments.Count == 12).Should().BeTrue();
            (prism.Polygons.Count == 6).Should().BeTrue();
            (prism.Vertices.Count == 8).Should().BeTrue();

            Point basePoint = Point.Origin;
            Point topLeftPoint = Point.MakePointWithInches(0, 5, 0);
            Point bottomRightPoint = Point.MakePointWithInches(5, 0, 0);
            Point topRightPoint = Point.MakePointWithInches(5, 5, 0);

            Point backbasepoint = Point.MakePointWithInches(0, 0, 5);
            Point backtopleftpoint = Point.MakePointWithInches(0, 5, 5);
            Point backbottomrightpoint = Point.MakePointWithInches(5, 0, 5);
            Point backtoprightpoint = Point.MakePointWithInches(5, 5, 5);

            List<Point> expectedPoints = new List<Point>() { basePoint, topLeftPoint, bottomRightPoint, topRightPoint, backbasepoint, backtopleftpoint, backbottomrightpoint, backtoprightpoint };

            foreach (Point point in expectedPoints)
            {
                prism.Vertices.Contains(point).Should().BeTrue();
            }
        }
        public void RegularPentagon()
        {
            Distance sideLength = new Distance(5, Inches);
            Polygon pentagon = Polygon.Pentagon(sideLength);

            //Check each segment individually
            foreach(var segment in pentagon.LineSegments)
            {
                (segment.Length == sideLength).Should().BeTrue(); 
            }

            Area actualArea = pentagon.Area;
            Area expectedArea = new Area(new SquareInch(), 43);
            (actualArea == expectedArea).Should().BeTrue();

            //verify the bottom segment is flat and symmetric about zero.
            var bottomSegment =  pentagon.LineSegments.MinBy(s => s.MidPoint.Y);
            (bottomSegment.BasePoint.X == -1 * bottomSegment.EndPoint.X).Should().BeTrue();
            (bottomSegment.BasePoint.Y == bottomSegment.EndPoint.Y).Should().BeTrue();
            
            //verify the polygon is on the XY plane
            foreach(var vertex in pentagon.Vertices)
            {
                (vertex.Z == Distance.ZeroDistance).Should().BeTrue();
            }

            //verify the polygon is centered on the origin
            (pentagon.Centroid == Point.Origin).Should().BeTrue();
        }
        public void Point_MinusOperatorStandardTest()
        {
            Distance xDistance1 = new Distance(new Millimeter(), 5);
            Distance yDistance1 = new Distance(new Millimeter(), 5);
            Distance zDistance1 = new Distance(new Millimeter(), 5);

            Distance xDistance2 = new Distance(new Millimeter(), 5);
            Distance yDistance2 = new Distance(new Millimeter(), 5);
            Distance zDistance2 = new Distance(new Millimeter(), 5);

            Distance xDistance3 = new Distance(new Millimeter(), -10);
            Distance yDistance3 = new Distance(new Millimeter(), -10);
            Distance zDistance3 = new Distance(new Millimeter(), -10);

            Point p1 = new Point(xDistance1, yDistance1, zDistance1);
            Point p2 = new Point(xDistance2, yDistance2, zDistance2);
            Point p3 = new Point(xDistance3, yDistance3, zDistance3);

            Point cumulativePoint = (p1 - p2 - p3);
            cumulativePoint.X.Should().Be(new Distance(new Millimeter(), 10));
            cumulativePoint.Y.Should().Be(new Distance(new Millimeter(), 10));
            cumulativePoint.Z.Should().Be(new Distance(new Millimeter(), 10));


        }
 public void NonPolygon_Circle()
 {
     Point center = Point.Origin;
     Distance radius = new Distance(3, Inches);
     Circle c2 = new Circle(center, radius);
     c2.Center.Equals(Point.Origin).Should().BeTrue();
     c2.Radius.ValueInInches.Should().Be(3);
 }
 private static Polygon _makeRectangle(Distance length, Distance width, Point basePoint = null)
 {
     var vector1 = new Vector(Direction.Right, length);
     var vector2 = new Vector(Direction.Up, width);
     
     var rectangle = Parallelogram(vector1, vector2, basePoint);
     return rectangle;
 }
        public Ellipse(IList<Point> foci, Distance curveDefinition)
        {
            if (foci.Count != 2)
            {
                throw new ArgumentException("An ellipse must have exactly two foci.");
            }

            this._foci = foci;
            this._curveDefinition = curveDefinition;
        }
        public void FundamentalUnit_SpeedTest()
        {
            var total = Distance.ZeroDistance;
            for (int i = 0; i < 1E7; i++)
            {
                var distance = new Distance(5, Distance.Inches);
                total += distance;
            }

            Assert.Pass();
        }
        public void Point_2DConstructorTest()
        {
            Distance xDistance = new Distance(new Millimeter(), 5);
            Distance yDistance = new Distance(new Millimeter(), 10);

            Point p = new Point(xDistance, yDistance);

            p.X.Should().Be(new Distance(new Millimeter(), 5));
            p.Y.Should().Be(new Distance(new Millimeter(), 10));
            p.Z.Should().Be(new Distance(new Millimeter(), 0));
        }
        public void DistanceConversions()
        {
            Distance kilometerDistance = new Distance(new Kilometer(), 1);

            (kilometerDistance == new Distance(new Millimeter(), 1000000)).Should().BeTrue();
            (kilometerDistance == new Distance(new Centimeter(), 100000)).Should().BeTrue();
            (kilometerDistance == new Distance(new Inch(), 39370.1)).Should().BeTrue();
            (kilometerDistance == new Distance(new Foot(), 3280.84)).Should().BeTrue();
            (kilometerDistance == new Distance(new Yard(), 1093.61)).Should().BeTrue();
            (kilometerDistance == new Distance(new Mile(), 0.621371)).Should().BeTrue();
            (kilometerDistance == new Distance(new Meter(), 1000)).Should().BeTrue();
            kilometerDistance.Architectural.Should().Be("3280'10 1/16\""); //need to recheck
        }
        public void Dimension_ComparisonOperatorTest()
        {
            // arrange
            Distance biggerDistance = new Distance(new Inch(), 14.1875);
            Distance smallerDistance = new Distance("1' 2 1/16\"");
            Distance equivalentbiggerDistance = new Distance(new Millimeter(), 360.3625);

            // assert
            //(smallerDistance < biggerDistance).Should().Be(true);
            //(biggerDistance < smallerDistance).Should().Be(false);

            //(biggerDistance > smallerDistance).Should().Be(true);
            //(smallerDistance > biggerDistance).Should().Be(false);
        }
        private static Polygon _makeRectangle(Vector baseSegment, Distance height, Direction referencePlaneNormal)
        {
            if (referencePlaneNormal == null)
            {
                referencePlaneNormal = Direction.Out;
            }

            Direction heightDirection = referencePlaneNormal.CrossProduct(baseSegment.Direction);
            var heightVector = new Vector(heightDirection, height);
            
            Polygon polygon = Parallelogram(baseSegment, heightVector);

            return polygon;
        }
        private static Polyhedron _makeSolid(Distance length, Distance width, Distance height, Point basePoint = null)
        {
            if (basePoint == null)
            {
                basePoint = Point.Origin;
            }
            Distance zero = Distance.ZeroDistance;

            Vector vector1 = new Vector(new Point(zero, width, zero));
            Vector vector2 = new Vector(new Point(length, zero, zero));
            Vector vector3 = new Vector(new Point(zero, zero, height));

            var solid = MakeParallelepiped(vector1, vector2, vector3, basePoint);
            return solid;
        }
        public Circle(Point center, Distance radius, Direction normalDirection = null)    
        {
            if (normalDirection == null)
            {
                normalDirection = Direction.Out;
            }
            var vector1 = new Vector(Point.MakePointWithInches(1, 0, 0)).CrossProduct(normalDirection * new Distance(1, Inches));
            var vector2 = new Vector(Point.MakePointWithInches(0, 1, 0)).CrossProduct(normalDirection * new Distance(1, Inches));
            var vector3 = new Vector(Point.MakePointWithInches(0, 0, 1)).CrossProduct(normalDirection * new Distance(1, Inches));
            var chosen = new List<Vector>() { vector1, vector2, vector3 }.MaxBy(v => v.Magnitude);

            var basePoint = center.Translate(chosen.Direction * radius);
            var arc = new Arc(basePoint, basePoint, new Line(center, normalDirection));

            this._Edges = new List<IEdge>() { arc };
            this.NormalLine = new Line(arc.CenterPoint, arc.NormalDirection);
        }
        public void Arc_Properties_Quarter_Circle()
        {
            //make our default arc
            Point basePoint = Point.Origin;
            Point endPoint = Point.MakePointWithInches(3, 3, 4.24264); //sqr(3^2 + 3^2)
            Direction directionAtStart = new Direction(Point.MakePointWithInches(1, 1, 0));

            Arc quarterArc = new Arc(basePoint, endPoint, directionAtStart);

            //test arc length
            Distance arcLength = quarterArc.ArcLength;
            //s = r(theta)
            Distance expectedArclength = new Distance(new Inch(), 4.24264 * Math.PI / 2);
            (arcLength == expectedArclength).Should().BeTrue();

            //test arc area
            Area arcArea = quarterArc.SectorArea;
            //a = (theta)/2 * r^2
            Area expectedArea = new Area(new SquareInch(), (Math.PI / 2) / 2 * (18)); //Pi/2 = 90 degrees, 18 = r^2
            (arcArea == expectedArea).Should().BeTrue();

            //test the arcSegmentArea
            Area arcSegmentArea = quarterArc.SegmentArea;
            //a = r^2 / 2 * (theta - sin(theta))
            Area expectedSegmentLength = new Area(new SquareInch(), 18 / 2 * (Math.PI / 2 - Math.Sin(Math.PI / 2))); //Pi/2 = 90 degrees, 18 = r^2
            (arcSegmentArea == expectedSegmentLength).Should().BeTrue();

            //test the central angle
            Angle centralAngle = quarterArc.CentralAngle;
            (centralAngle == Angle.RightAngle).Should().BeTrue();

            //test the center point
            Point centerPoint = quarterArc.CenterPoint;
            (centerPoint == Point.MakePointWithInches(0, 0, 4.24264)).Should().BeTrue();//sqr(3^2 + 3^2)

            //test the radius
            Distance radius = quarterArc.RadiusOfCurvature;
            (radius == new Distance(new Inch(), 4.24264)).Should().BeTrue();//sqr(3^2 + 3^2)

            //test the straight line direction (same as direction)
            Direction straightDirection = quarterArc.StraightLineDirection;
            (straightDirection == new Direction(Angle.RightAngle / 2, Angle.RightAngle / 2)).Should().BeTrue();
        }
        public void Distance_Architectural_Constructor()
        {
            // arrange
            Distance Distance1 = new Distance("1'2 3/16\"");
            Distance Distance2 = new Distance("1'");
            Distance Distance3 = new Distance("1'2\"");
            Distance Distance4 = new Distance("2 3/16\"");
            Distance Distance5 = new Distance("1'2-3/16\"");
            Distance Distance6 = new Distance("3/16\"");
            Distance Distance7 = new Distance("121103");
            Distance Distance8 = new Distance("-1'2\"");

            // assert
            Distance1.Architectural.ShouldBeEquivalentTo("1'2 3/16\"");
            Distance2.Architectural.ShouldBeEquivalentTo("1'");
            Distance3.Architectural.ShouldBeEquivalentTo("1'2\"");
            Distance4.Architectural.ShouldBeEquivalentTo("2 3/16\"");
            Distance5.Architectural.ShouldBeEquivalentTo("1'2 3/16\"");
            Distance6.Architectural.ShouldBeEquivalentTo("3/16\"");
            Distance7.Architectural.ShouldBeEquivalentTo("12'11 3/16\"");
            Distance8.Architectural.ShouldBeEquivalentTo("-1'2\"");
        }
        public void Distance_CompareTo()
        {
            // arrange
            Distance smallDistance = new Distance(new Millimeter(), 1);
            Distance mediumDistance = new Distance(new Foot(), 1);
            Distance largeDistance = new Distance(new Kilometer(), 1);

            //Act & Assert
            smallDistance.CompareTo(mediumDistance).Should().Be(-1);
            mediumDistance.CompareTo(smallDistance).Should().Be(1);
            largeDistance.CompareTo(largeDistance).Should().Be(0);
        }
        public void Distance_EqualityTests()
        {
            // arrange
            Distance biggerDistance = new Distance(new Inch(), 14.1875);
            Distance smallerDistance = new Distance("1' 2 1/16\"");
            Distance equivalentbiggerDistance = new Distance(new Millimeter(), 360.3625);

            (equivalentbiggerDistance == biggerDistance).Should().BeTrue();
            (equivalentbiggerDistance == smallerDistance).Should().BeFalse();

            (equivalentbiggerDistance != smallerDistance).Should().BeTrue();
            (equivalentbiggerDistance != biggerDistance).Should().BeFalse();

            //check ==
            bool nonNullFirst = (biggerDistance == null);
            bool nullFirst = (null == biggerDistance);
            bool bothNull = (null == null);

            nonNullFirst.Should().BeFalse();
            nullFirst.Should().BeFalse();
            bothNull.Should().BeTrue();

            //check !=
            bool nonNullFirstNotEqual = (biggerDistance != null);
            bool nullFirstNotEqual = (null != biggerDistance);
            bool bothNullNotEqual = (null != null);

            nonNullFirstNotEqual.Should().BeTrue();
            nullFirstNotEqual.Should().BeTrue();
            bothNullNotEqual.Should().BeFalse();

            //check equals (other way should throw a nullPointerException)
            bool nullSecond = biggerDistance.Equals(null);

            nullSecond.Should().BeFalse();
        }
        public void Distance_ToString_NumberOfDecimals()
        {
            // arrange
            Distance Distance = new Distance(new Millimeter(), 14.1875);
            Distance Distance2 = new Distance(new Millimeter(), 0.0001);
            Distance Distance3 = new Distance(new Millimeter(), 1.13);
            //should come back rounded due
            // act

            // assert
            Distance.ToString(3).Should().Be("14.188 mm");
            Distance2.ToString(1).Should().Be("0 mm");
            Distance3.ToString(0).Should().Be("1 mm");
        }
 private static Polyhedron _makePrismFromRectangle(Rectangle rectangle, Distance height)
 {
     var prism = rectangle.Extrude(rectangle.NormalVector * height.ValueInInches);
     return prism;
 }
        public void Distance_ToString()
        {
            // arrange
            Distance Distance = new Distance(new Millimeter(), 14.1875);
            Distance Distance2 = new Distance(new Millimeter(), 0);
            Distance Distance3 = new Distance(new Millimeter(), 1.13);
            //should come back rounded due
            // act

            // assert
            Distance.ToString().Should().Be("14 mm");
            Distance2.ToString().Should().Be("0 mm");
            Distance3.ToString().Should().Be("1 mm");
        }
 public void Distance_SelfConversionTest()
 {
     Distance testInstance = new Distance(new Mile(), 1);
     testInstance.AsMiles().Should().Be(1);
 }
        public void LineSegment_ConstructorPointDirectionDistance_ShouldCreateLineSegmentFromOrigin_IfPointIsNull()
        {
            Point point = null;
            Direction direction = new Direction(1, 0, 0);
            Distance distance = new Distance(1, Distance.Inches);

            LineSegment lineSegment = new LineSegment(point, direction, distance);

            lineSegment.Should().Be(new LineSegment(Point.MakePointWithInches(1, 0, 0)));
        }
 public RectangularPrism(Rectangle rectangle, Distance height) : base(_makePrismFromRectangle(rectangle, height)) { }
        public void Distance_EqualsWithinPassedAcceptedDeviation()
        {
            // arrange
            Distance distance = new Distance(new Inch(), 5);
            Distance equivalentDistance = new Distance(new Inch(), 5.03125);
            Distance notequivalentDistance = new Distance(new Inch(), 5.03126);

            //    (equivalentDistance.EqualsWithinDeviationConstant(distance, distance.DeviationAsConstant)).Should().Be(true);
            //    (notequivalentDistance.EqualsWithinDeviationConstant(distance, distance.DeviationAsConstant)).Should().Be(false);
        }
 /// <summary>
 /// Creates a rectangular prism with the given Distances in the x,y,z directions
 /// </summary>
 public RectangularPrism(Distance length, Distance width, Distance height, Point basePoint = null) : base(_makeSolid(length, width, height, basePoint)) { }
        public void Distance_GetHashCode()
        {
            // arrange
            Distance Distance = new Distance(new Millimeter(), 14.1875);
            double number = 14.1875;

            // act
            int DistanceHashCode = Distance.GetHashCode();

            int hashCode = number.GetHashCode();

            // assert
            hashCode.ShouldBeEquivalentTo(DistanceHashCode);
        }
        public void LineSegment_ConstructorPointDirectionDistance_ShouldCreateLineSegmentFromPointDirectionAndDistance()
        {
            Direction direction = new Direction(1, 0, 0);
            Distance distance = new Distance(1, Distance.Inches);

            LineSegment lineSegment = new LineSegment(Point.Origin, direction, distance);

            lineSegment.Should().Be(new LineSegment(Point.MakePointWithInches(1, 0, 0)));
        }
        public void Distance_Intuitiveness()
        {
            //zero constructor
            Distance zero1 = Distance.ZeroDistance;
            Distance zero2 = Distance.ZeroDistance;
            Angle zero = Angle.ZeroAngle;

            // This doesn't compile, yay for type safety:
            // bool b1 = zero1 == zero;

            // Checking between the same type does compile:
            bool b2 = zero1 == zero2;

            //simple constructor
            Distance smallDistance = new Distance(new Millimeter(), 1);
            Distance mediumDistance = new Distance(new Foot(), 1);
            Distance largeDistance = new Distance(new Kilometer(), 1);

            //copy constructor
            Distance copy = new Distance(smallDistance);

            //comparisons
            //if (copy > zero)
            //{

            //}

            if (zero1 == Distance.ZeroDistance)
            {

            }

            if (zero1 >= Distance.ZeroDistance)
            {

            }

            //Math operations
            Distance distance4 = smallDistance + largeDistance;
            Distance doubleDistance = mediumDistance * 2;

            //absolute value
            Distance positiveDistance = (new Distance(new Inch(), -1).AbsoluteValue());

            //Static constants
            Distance oneFoot = 1.FromFeetToDistance();

            //increments
            oneFoot += oneFoot; // 2 feet
            oneFoot -= oneFoot; // 0 feet

            //we do not implement ++ and -- because that would break our "all units simultaneously" abstraction.
            // oneFoot++;
            // oneFoot--;

            //User defined equality strategies
            //EqualityStrategy<IDistanceType> userStrategy = (d1, d2) => { return true; };

            //oneFoot.EqualsWithinEqualityStrategy(positiveDistance, userStrategy);

            // ToString override
            oneFoot.ToString();

            List<Distance> distances = new List<Distance> { oneFoot, positiveDistance, distance4, zero1 };

            foreach (var distance in distances)
            {
                distance.ToString();
            }
        }
        public void LineSegment_ConstructorPointDirectionDistance_ShouldThrowException_IfDirectionIsNull()
        {
            Direction direction = null;
            Distance distance = new Distance(1, Distance.Inches);

            Action construct = () => new LineSegment(Point.Origin, direction, distance);
            construct.ShouldThrow<Exception>();
        }
        public void Distance_Math_Operators()
        {
            // arrange
            Distance inchDistance = new Distance(new Inch(), 14.1875);
            Distance architecturalDistance = new Distance("1'2 3/16\"");

            // act
            Distance subtractionDistance = inchDistance - architecturalDistance;
            Distance additionDistance = inchDistance + architecturalDistance;

            Distance tenFeet = new Distance(10, Distance.Feet);
            Distance fiveInches = new Distance(5, new Inch());

            var quotient = tenFeet/fiveInches;

            // assert
            (subtractionDistance == (Distance.ZeroDistance)).Should().BeTrue();
            (additionDistance == (new Distance(new Millimeter(), 720.725))).Should().BeTrue();
            additionDistance.Architectural.Should().Be("2'4 6/16\"");

            quotient.Should().BeApproximately(24, 0.0001);
        }