diff --git a/.idea/.idea.Shapes/.idea/contentModel.xml b/.idea/.idea.Shapes/.idea/contentModel.xml index b826856..c48181e 100644 --- a/.idea/.idea.Shapes/.idea/contentModel.xml +++ b/.idea/.idea.Shapes/.idea/contentModel.xml @@ -1,13 +1,17 @@ + + + - + + @@ -15,9 +19,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.Shapes/riderModule.iml b/.idea/.idea.Shapes/riderModule.iml index 1a4e0d9..a703f0e 100644 --- a/.idea/.idea.Shapes/riderModule.iml +++ b/.idea/.idea.Shapes/riderModule.iml @@ -1,6 +1,9 @@ + + + diff --git a/Shapes.sln b/Shapes.sln index 5352aa8..8b4d161 100644 --- a/Shapes.sln +++ b/Shapes.sln @@ -2,6 +2,10 @@ Microsoft Visual Studio Solution File, Format Version 12.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shapes", "Shapes\Shapes.csproj", "{3DEEB67E-89F4-403E-8210-EEBD5A01C64D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Temp", "Temp\Temp.csproj", "{781AE2D9-ADBF-4AA4-9D9D-78AFBF04A6F5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{E7BB8603-7B34-4C9E-9C1F-916527FD68A5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -12,5 +16,13 @@ Global {3DEEB67E-89F4-403E-8210-EEBD5A01C64D}.Debug|Any CPU.Build.0 = Debug|Any CPU {3DEEB67E-89F4-403E-8210-EEBD5A01C64D}.Release|Any CPU.ActiveCfg = Release|Any CPU {3DEEB67E-89F4-403E-8210-EEBD5A01C64D}.Release|Any CPU.Build.0 = Release|Any CPU + {781AE2D9-ADBF-4AA4-9D9D-78AFBF04A6F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {781AE2D9-ADBF-4AA4-9D9D-78AFBF04A6F5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {781AE2D9-ADBF-4AA4-9D9D-78AFBF04A6F5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {781AE2D9-ADBF-4AA4-9D9D-78AFBF04A6F5}.Release|Any CPU.Build.0 = Release|Any CPU + {E7BB8603-7B34-4C9E-9C1F-916527FD68A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E7BB8603-7B34-4C9E-9C1F-916527FD68A5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E7BB8603-7B34-4C9E-9C1F-916527FD68A5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E7BB8603-7B34-4C9E-9C1F-916527FD68A5}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/Shapes/Circle.cs b/Shapes/Circle.cs new file mode 100644 index 0000000..ffa6c0d --- /dev/null +++ b/Shapes/Circle.cs @@ -0,0 +1,89 @@ +using System; +using System.Drawing; + +namespace Shapes +{ + public class Circle : Shape + { + public Point Center { get; private set; } + public double Radius { get; private set; } + + public override Color Fill { get; set; } + public override Color Color { get; set; } + public override double Height { get; } + public override double Width { get; } + + /** + * Constructor with x-y Location for center + * + * @param x The x-location of the center of the circle -- must be a valid double + * @param y The y-location of the center of the circle + * @param radius The radius of the circle -- must be greater or equal to zero. + * @throws ShapeException The exception thrown if the x, y, or z are not valid + */ + public Circle(double x, double y, double radius) + { + Validator.ValidatePositiveDouble(radius, "Invalid radius"); + Center = new Point(x, y); + Radius = radius; + Color = Color.Black; + Fill = Color.White; + Height = radius * 2; + Width = radius * 2; + } + + /** + * Constructor with a Point for center + * + * @param center The x-location of the center of the circle -- must be a valid point + * @param radius The radius of the circle -- must be greater or equal to zero. + * @throws ShapeException The exception thrown if the x, y, or z are not valid + */ + public Circle(Point center, double radius) { + + Validator.ValidatePositiveDouble(radius, "Invalid radius"); + if (center == null) + throw new ShapeException("Invalid center point"); + Center = center; + Radius = radius; + Color = Color.Black; + Fill = Color.White; + Height = radius * 2; + Width = radius * 2; + } + + /** + * Move the circle + * @param deltaX a delta change for the x-location of center of the circle + * @param deltaY a delta change for the y-location of center of the circle + * @throws ShapeException Exception thrown if either the delta x or y are not valid doubles + */ + public void Move(double deltaX, double deltaY) + { + Center.Move(deltaX, deltaY); + } + + /** + * Scale the circle + * + * @param scaleFactor a non-negative double that represents the percentage to scale the circle. + * 0>= and <1 to shrink. + * >1 to grow. + * @throws ShapeException Exception thrown if the scale factor is not valid + */ + public override void Scale(double scaleFactor) + { + Validator.ValidatePositiveDouble(scaleFactor, "Invalid scale factor"); + Radius *= scaleFactor; + } + + /** + * @return The area of the circle. + */ + public override double ComputeArea() + { + return Math.PI * Math.Pow(Radius, 2); + } + + } +} \ No newline at end of file diff --git a/Shapes/Class1.cs b/Shapes/Class1.cs deleted file mode 100644 index 1658be6..0000000 --- a/Shapes/Class1.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; - -namespace Shapes -{ - public class Class1 - { - } -} \ No newline at end of file diff --git a/Shapes/Line.cs b/Shapes/Line.cs new file mode 100644 index 0000000..3ccd7d8 --- /dev/null +++ b/Shapes/Line.cs @@ -0,0 +1,72 @@ +using System; +using System.Drawing; + +namespace Shapes +{ + public class Line + { + public Point Point1 { get; private set; } + public Point Point2 { get; private set; } + public Color Color { get; set; } + + /** + * Constructor based on x-y Locations + * @param x1 The x-location of first point -- must be a valid double. + * @param y1 The y-location of first point -- must be a valid double. + * @param x2 The x-location of second point -- must be a valid double. + * @param y2 The y-location of second point -- must be a valid double. + * @throws ShapeException Exception throw if any parameter is invalid + */ + public Line(double x1, double y1, double x2, double y2) + { + Color = Color.Black; + Point1 = new Point(x1, y1); + Point2 = new Point(x2, y2); + } + + /** + * + * @param point1 The first point -- must not be null + * @param point2 The second point -- must not b e null + * @throws ShapeException Exception throw if any parameter is invalid + */ + public Line(Point point1, Point point2) + { + if (point1==null || point2==null) + throw new ShapeException("Invalid point"); + Color = Color.Black; + Point1 = point1; + Point2 = point2; + } + + /** + * Move a line + * + * @param deltaX The delta x-location by which the line should be moved -- must be a valid double + * @param deltaY The delta y-location by which the line should be moved -- must be a valid double + * @throws ShapeException Exception throw if any parameter is invalid + */ + public void Move(double deltaX, double deltaY) + { + Point1.Move(deltaX, deltaY); + Point2.Move(deltaX, deltaY); + } + + /** + * @return The length of the line + */ + public double ComputeLength() + { + return Math.Sqrt(Math.Pow(Math.Abs(Point2.X - Point1.X), 2) + + Math.Pow(Math.Abs(Point2.Y - Point1.Y), 2)); + } + + /** + * @return The slope of the line + */ + public double ComputeSlope() + { + return (Point2.Y - Point1.Y) / (Point2.X - Point1.X); + } + } +} \ No newline at end of file diff --git a/Shapes/Point.cs b/Shapes/Point.cs new file mode 100644 index 0000000..99d2b21 --- /dev/null +++ b/Shapes/Point.cs @@ -0,0 +1,66 @@ +using System.Drawing; + +namespace Shapes +{ + public class Point + { + public double X { get; internal set; } + public double Y { get; internal set; } + public Color Color { get; set; } + + public Point(double x, double y) + { + Validator.ValidateDouble(x, "Invalid x-location point"); + Validator.ValidateDouble(y, "Invalid y-location point"); + X = x; + Y = y; + Color = Color.Black; + } + + /** + * Move the point in the x direction + * + * @param deltaX The delta amount to move the point -- must be a valid double + * @throws ShapeException Exception thrown if the parameter is invalid + */ + public void MoveX(double deltaX) { + Validator.ValidateDouble(deltaX, "Invalid delta-x value"); + X += deltaX; + } + + /** + * Move the point in the y direction + * + * @param deltaY The delta amount to move the point -- must be a valid double + * @throws ShapeException Exception thrown if the parameter is invalid + */ + public void MoveY(double deltaY) + { + Validator.ValidateDouble(deltaY, "Invalid delta-y value"); + Y += deltaY; + } + + /** + * Move the point + * + * @param deltaX The delta amount to move the point in the x direction -- must be a valid double + * @param deltaY The delta amount to move the point in the y direction -- must be a valid double + * @throws ShapeException Exception throw if any parameter is invalid + */ + public void Move(double deltaX, double deltaY) + { + MoveX(deltaX); + MoveY(deltaY); + } + + /** + * Copy the point + * @return A new point with same x and y locations + * @throws ShapeException Should never thrown because the current x and y are valid + */ + public Point Copy() + { + return new Point(X, Y); + } + } +} \ No newline at end of file diff --git a/Shapes/Rectangle.cs b/Shapes/Rectangle.cs new file mode 100644 index 0000000..2551f75 --- /dev/null +++ b/Shapes/Rectangle.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.Drawing; + +namespace Shapes +{ + public class Rectangle : Shape + { + public override Color Fill { get; set; } + public override Color Color { get; set; } + public List Points { get; } + public Point CenterPoint { get; } + public sealed override double Width { get; } + public sealed override double Height { get; } + + + public Rectangle(Point point1, Point point2, Point point3, Point point4) + { + Points = new List(); + Points.Add(point1); + Points.Add(point2); + Points.Add(point3); + Points.Add(point4); + Height = new Line(point1, point4).ComputeLength(); + Width = new Line(point1, point2).ComputeLength(); + CenterPoint = new Point(point1.X + (Width/2), point1.Y + (Height/2)); + Validator.ValidateRectangle(point1, point2, point3, point4, $"Attempted to create an invalid shape {this.GetType()}"); + } + + public Rectangle(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) + { + Points = new List(); + var point1 = new Point(x1, y1); + var point2 = new Point(x2, y2); + var point3 = new Point(x3, y3); + var point4 = new Point(x4, y4); + Points.Add(point1); + Points.Add(point2); + Points.Add(point3); + Points.Add(point4); + Height = new Line(point1, point2).ComputeLength(); + Width = new Line(point1, point4).ComputeLength(); + CenterPoint = new Point((point1.X + Width)/2, (point1.Y + Height)/2); + Validator.ValidateRectangle(point1, point2, point3, point4, $"Attempted to create an invalid shape {this.GetType()}"); + } + + public Rectangle(Point point, Size size) + { + Points = new List(); + var point1 = point; + var point2 = new Point(point.X + size.Width, point.Y); + var point3 = new Point(point.X + size.Width, point.Y + size.Height); + var point4 = new Point(point.X, point.Y + size.Height); + Points.Add(point1); + Points.Add(point2); + Points.Add(point3); + Points.Add(point4); + Height = new Line(point1, point2).ComputeLength(); + Width = new Line(point1, point4).ComputeLength(); + CenterPoint = new Point((point1.X + Width)/2, (point1.Y + Height)/2); + Validator.ValidateRectangle(point1, point2, point3, point4, $"Attempted to create an invalid shape {this.GetType()}"); + } + + public override double ComputeArea() + { + return Height * Width; + } + + public override void Scale(double scaleFactor) + { + throw new System.NotImplementedException(); + } + + public double CalculateWidth() + { + return new Line(Points[0], Points[3]).ComputeLength(); + + } + + public double CalculateHeight() + { + return new Line(Points[0], Points[1]).ComputeLength(); + } + + public void Rotate(double degrees) + { + double radians = degrees * (Math.PI / 180); + double cosTheta = Math.Cos(radians); + double sinTheta = Math.Sin(radians); + foreach (var point in Points) + { + var oldPoint = point; + + + var tempX = oldPoint.X - CenterPoint.X; + var tempY = oldPoint.Y - CenterPoint.X; + + var rotatedX = tempX*cosTheta - tempY*sinTheta; + var rotatedY = tempX*sinTheta + tempY*cosTheta; + + point.X = rotatedX + CenterPoint.X; + point.Y = rotatedY + CenterPoint.Y; + + } + } + + + } +} \ No newline at end of file diff --git a/Shapes/Shape.cs b/Shapes/Shape.cs new file mode 100644 index 0000000..aa5de68 --- /dev/null +++ b/Shapes/Shape.cs @@ -0,0 +1,20 @@ +using System.ComponentModel; +using System.Diagnostics.Tracing; +using System.Drawing; +using System.Reflection.Metadata.Ecma335; + +namespace Shapes +{ + public abstract class Shape + { + public abstract Color Fill { get; set; } + public abstract Color Color { get; set; } + public abstract double Width { get; } + public abstract double Height { get; } + public abstract double ComputeArea(); + + public abstract void Scale(double scaleFactor); + + + } +} \ No newline at end of file diff --git a/Shapes/ShapeException.cs b/Shapes/ShapeException.cs new file mode 100644 index 0000000..2f3459e --- /dev/null +++ b/Shapes/ShapeException.cs @@ -0,0 +1,11 @@ +namespace Shapes +{ + + public class ShapeException : System.Exception + { + public ShapeException(string message) : base(message) + { + } + } + +} \ No newline at end of file diff --git a/Shapes/Triangle.cs b/Shapes/Triangle.cs new file mode 100644 index 0000000..db3c71e --- /dev/null +++ b/Shapes/Triangle.cs @@ -0,0 +1,10 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.Drawing; + +namespace Shapes +{ + public class Triangle + { + } +} \ No newline at end of file diff --git a/Shapes/Validator.cs b/Shapes/Validator.cs new file mode 100644 index 0000000..0716060 --- /dev/null +++ b/Shapes/Validator.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Globalization; + +namespace Shapes +{ + public class Validator + { + + public static void ValidateDouble(double value, string errorMessage) + { + if (double.IsInfinity(value) || double.IsNaN(value)) + throw new ShapeException(errorMessage); + } + + public static void ValidatePositiveDouble(double value, String errorMessage) + { + ValidateDouble(value, errorMessage); + if (value < 0) + throw new ShapeException(errorMessage); + } + + public static void ValidateRectangle(Point point1, Point point2, Point point3, Point point4, String errorMessage) + { + var TOLERANCE = Double.Epsilon + Double.Epsilon; + var plumLine1 = new Line(point1, point3); + var plumLine2 = new Line(point2, point4); + var heightLine1 = new Line(point1, point4); + var heightLine2 = new Line( point2, point3); + var lengthLine1 = new Line(point1, point2); + var lengthLine2 = new Line(point4, point3); + if (Math.Abs(plumLine1.ComputeLength() - plumLine2.ComputeLength()) > TOLERANCE + || Math.Abs(heightLine1.ComputeLength() - heightLine2.ComputeLength()) > TOLERANCE + || Math.Abs(lengthLine1.ComputeLength() - lengthLine2.ComputeLength()) > TOLERANCE ) + { + throw new ShapeException(errorMessage); + } + + } + + + + } +} \ No newline at end of file diff --git a/Temp/Program.cs b/Temp/Program.cs new file mode 100644 index 0000000..70cf78e --- /dev/null +++ b/Temp/Program.cs @@ -0,0 +1,29 @@ +using System; +using System.Drawing; +using Shapes; +using Point = Shapes.Point; +using Rectangle = Shapes.Rectangle; + +namespace Temp +{ + class Program + { + static void Main(string[] args) + { + var circle = new Circle(new Point(20, 20), 4); + Console.WriteLine("Hello World!"); + var line = new Line(3, 4, 4, 5); + var tmp = line.ComputeLength(); + var point = new Point(3, 3); + point.Color = Color.Aqua; + var rectangle = new Rectangle(new Point(3,3), new Point(6,3), new Point(6,6), new Point(3,6)); + //var rectangle2 = new Rectangle(new Point(3,0), new Point(3,0), new Point(3,2), new Point(0,3)); + Console.WriteLine($"({rectangle.Points[0].X}, {rectangle.Points[0].Y}), ({rectangle.Points[1].X}, {rectangle.Points[1].Y}), ({rectangle.Points[2].X}, {rectangle.Points[2].Y}), ({rectangle.Points[3].X}, {rectangle.Points[3].Y}) Height:{rectangle.CalculateHeight()} Width:{rectangle.CalculateWidth()} Center: {rectangle.CenterPoint.X}, {rectangle.CenterPoint.Y}"); + rectangle.Rotate(180); + Console.WriteLine($"({rectangle.Points[0].X}, {rectangle.Points[0].Y}), ({rectangle.Points[1].X}, {rectangle.Points[1].Y}), ({rectangle.Points[2].X}, {rectangle.Points[2].Y}), ({rectangle.Points[3].X}, {rectangle.Points[3].Y}) Height:{rectangle.CalculateHeight()} Width:{rectangle.CalculateWidth()} Center: {rectangle.CenterPoint.X}, {rectangle.CenterPoint.Y}"); + rectangle.Rotate(90); + Console.WriteLine($"({rectangle.Points[0].X}, {rectangle.Points[0].Y}), ({rectangle.Points[1].X}, {rectangle.Points[1].Y}), ({rectangle.Points[2].X}, {rectangle.Points[2].Y}), ({rectangle.Points[3].X}, {rectangle.Points[3].Y}) Height:{rectangle.CalculateHeight()} Width:{rectangle.CalculateWidth()} Center: {rectangle.CenterPoint.X}, {rectangle.CenterPoint.Y}"); + + } + } +} \ No newline at end of file diff --git a/Temp/Temp.csproj b/Temp/Temp.csproj new file mode 100644 index 0000000..1d148c8 --- /dev/null +++ b/Temp/Temp.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp2.2 + + + + + + + diff --git a/TestProject1/TestProject1.csproj b/TestProject1/TestProject1.csproj new file mode 100644 index 0000000..89b9b0d --- /dev/null +++ b/TestProject1/TestProject1.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp2.2 + + false + + + + + + + + + diff --git a/TestProject1/UnitTest1.cs b/TestProject1/UnitTest1.cs new file mode 100644 index 0000000..dfbb241 --- /dev/null +++ b/TestProject1/UnitTest1.cs @@ -0,0 +1,18 @@ +using NUnit.Framework; +using Shapes; +namespace Tests +{ + public class Tests + { + [SetUp] + public void Setup() + { + } + + [Test] + public void Test1() + { + Assert.Pass(); + } + } +} \ No newline at end of file diff --git a/UnitTests/UnitTest1.cs b/UnitTests/UnitTest1.cs new file mode 100644 index 0000000..794c408 --- /dev/null +++ b/UnitTests/UnitTest1.cs @@ -0,0 +1,18 @@ +using NUnit.Framework; + +namespace Tests +{ + public class Tests + { + [SetUp] + public void Setup() + { + } + + [Test] + public void Test1() + { + Assert.Pass(); + } + } +} \ No newline at end of file diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj new file mode 100644 index 0000000..5005a03 --- /dev/null +++ b/UnitTests/UnitTests.csproj @@ -0,0 +1,19 @@ + + + + netcoreapp2.2 + + false + + + + + + + + + + + + +