From 664ae529aa819787a124273c532f30fa0584e699 Mon Sep 17 00:00:00 2001 From: RenatZubakin Date: Tue, 5 Dec 2023 00:10:53 +0500 Subject: [PATCH 1/9] create hometask solution and add simple tests --- cs/TagsCloudVisualization/App.config | 6 ++ cs/TagsCloudVisualization/Program.cs | 16 ++++ .../Properties/AssemblyInfo.cs | 36 +++++++++ .../TagsCloudVisualization.cs | 41 ++++++++++ .../TagsCloudVisualization.csproj | 81 +++++++++++++++++++ .../TagsCloudVisualizationTests.cs | 50 ++++++++++++ cs/TagsCloudVisualization/packages.config | 6 ++ cs/tdd.sln | 17 +++- 8 files changed, 249 insertions(+), 4 deletions(-) create mode 100644 cs/TagsCloudVisualization/App.config create mode 100644 cs/TagsCloudVisualization/Program.cs create mode 100644 cs/TagsCloudVisualization/Properties/AssemblyInfo.cs create mode 100644 cs/TagsCloudVisualization/TagsCloudVisualization.cs create mode 100644 cs/TagsCloudVisualization/TagsCloudVisualization.csproj create mode 100644 cs/TagsCloudVisualization/TagsCloudVisualizationTests.cs create mode 100644 cs/TagsCloudVisualization/packages.config diff --git a/cs/TagsCloudVisualization/App.config b/cs/TagsCloudVisualization/App.config new file mode 100644 index 000000000..193aecc67 --- /dev/null +++ b/cs/TagsCloudVisualization/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/cs/TagsCloudVisualization/Program.cs b/cs/TagsCloudVisualization/Program.cs new file mode 100644 index 000000000..ff2d5dd5f --- /dev/null +++ b/cs/TagsCloudVisualization/Program.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TagsCloudVisualization +{ + public class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/cs/TagsCloudVisualization/Properties/AssemblyInfo.cs b/cs/TagsCloudVisualization/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..b80282fac --- /dev/null +++ b/cs/TagsCloudVisualization/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("TagsCloudVisualization")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TagsCloudVisualization")] +[assembly: AssemblyCopyright("Copyright © 2023")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("80edaa6b-8db4-4a7e-8d3d-7032262731b6")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/cs/TagsCloudVisualization/TagsCloudVisualization.cs b/cs/TagsCloudVisualization/TagsCloudVisualization.cs new file mode 100644 index 000000000..1900708fd --- /dev/null +++ b/cs/TagsCloudVisualization/TagsCloudVisualization.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Drawing; + +namespace TagsCloudVisualization +{ + public class TagsCloudVisualization + { + public Point Center; + public List WordPositions; + public double Radius; + public double Angle; + + public TagsCloudVisualization(Point center) + { + Center = center; + Radius = 0; + Angle = 0; + } + + public Rectangle PutNextRectangle(Size rectangleSize) + { + throw new ArgumentException(); + } + + } + + /*public class WordPosition + { + public Point Position; + public double Width; + public double Height; + + public WordPosition(Point position, double width, double height) + { + Position = position; + Width = width; + Height = height; + } + }*/ +} \ No newline at end of file diff --git a/cs/TagsCloudVisualization/TagsCloudVisualization.csproj b/cs/TagsCloudVisualization/TagsCloudVisualization.csproj new file mode 100644 index 000000000..689c58e46 --- /dev/null +++ b/cs/TagsCloudVisualization/TagsCloudVisualization.csproj @@ -0,0 +1,81 @@ + + + + + + + + Debug + AnyCPU + {80EDAA6B-8DB4-4A7E-8D3D-7032262731B6} + Exe + TagsCloudVisualization + TagsCloudVisualization + v4.8 + 512 + true + true + + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Microsoft.CodeCoverage.16.7.1\lib\net45\Microsoft.VisualStudio.CodeCoverage.Shim.dll + + + ..\packages\NUnit.3.12.0\lib\net45\nunit.framework.dll + + + + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + \ No newline at end of file diff --git a/cs/TagsCloudVisualization/TagsCloudVisualizationTests.cs b/cs/TagsCloudVisualization/TagsCloudVisualizationTests.cs new file mode 100644 index 000000000..a1841ae04 --- /dev/null +++ b/cs/TagsCloudVisualization/TagsCloudVisualizationTests.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using NUnit.Framework; + +namespace TagsCloudVisualization +{ + [TestFixture] + public class TagsCloudVisualizationTests + { + + private TagsCloudVisualization tagsCloud; + + [SetUp] + public void SetUp() + { + tagsCloud = new TagsCloudVisualization(new Point(1, 2)); + } + + [Test] + public void TagsCloudVisualization_Initialize_Params() + { + Assert.AreEqual(0,tagsCloud.Radius); + Assert.AreEqual(0,tagsCloud.Angle); + Assert.AreEqual(null,tagsCloud.WordPositions); + Assert.AreEqual(new Point(1,2), tagsCloud.Center); + } + + [TestCase(-1,2, TestName = "When_Width_Is_Negative")] + [TestCase(1, -2, TestName = "When_Height_Is_Negative")] + [TestCase(0,1, TestName = "When_Width_Is_Zero")] + [TestCase(1, 0, TestName = "When_Height_Is_Zero")] + public void PutNextRectangle_Throws_ArgumentException(int width,int height) + { + var size = new Size(width, height); + Assert.Throws(() => tagsCloud.PutNextRectangle(size)); + } + + [Test] + public void TagsCloudVisualization_First_ElementPosition_Should_Be_Equal_To_Center() + { + tagsCloud.PutNextRectangle(new Size(4, 5)); + Assert.AreEqual(tagsCloud.Center, tagsCloud.WordPositions[0].Location); + } + + } +} diff --git a/cs/TagsCloudVisualization/packages.config b/cs/TagsCloudVisualization/packages.config new file mode 100644 index 000000000..a2bd3e845 --- /dev/null +++ b/cs/TagsCloudVisualization/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/cs/tdd.sln b/cs/tdd.sln index c8f523d63..7b807df43 100644 --- a/cs/tdd.sln +++ b/cs/tdd.sln @@ -1,11 +1,13 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33829.357 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BowlingGame", "BowlingGame\BowlingGame.csproj", "{AD0F018A-732E-4074-8527-AB2EEC8D0BF3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BowlingGame", "BowlingGame\BowlingGame.csproj", "{AD0F018A-732E-4074-8527-AB2EEC8D0BF3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples", "Samples\Samples.csproj", "{B5108E20-2ACF-4ED9-84FE-2A718050FC94}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Samples", "Samples\Samples.csproj", "{B5108E20-2ACF-4ED9-84FE-2A718050FC94}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TagsCloudVisualization", "TagsCloudVisualization\TagsCloudVisualization.csproj", "{80EDAA6B-8DB4-4A7E-8D3D-7032262731B6}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,8 +23,15 @@ Global {B5108E20-2ACF-4ED9-84FE-2A718050FC94}.Debug|Any CPU.Build.0 = Debug|Any CPU {B5108E20-2ACF-4ED9-84FE-2A718050FC94}.Release|Any CPU.ActiveCfg = Release|Any CPU {B5108E20-2ACF-4ED9-84FE-2A718050FC94}.Release|Any CPU.Build.0 = Release|Any CPU + {80EDAA6B-8DB4-4A7E-8D3D-7032262731B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80EDAA6B-8DB4-4A7E-8D3D-7032262731B6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80EDAA6B-8DB4-4A7E-8D3D-7032262731B6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80EDAA6B-8DB4-4A7E-8D3D-7032262731B6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2D0D81D1-AF13-4EDD-B964-95EA74589BD3} + EndGlobalSection EndGlobal From 351efe7e83528e4674acfaed45ce163de8753065 Mon Sep 17 00:00:00 2001 From: RenatZubakin Date: Tue, 5 Dec 2023 19:22:51 +0500 Subject: [PATCH 2/9] Add tests and realization --- .../CircularCloudLayouter | 81 +++++++++++ .../CircularCloudLayouter.cs | 131 ++++++++++++++++++ .../CircularCloudLayouterTests.cs | 99 +++++++++++++ cs/TagsCloudVisualization/Program.cs | 5 +- .../Properties/AssemblyInfo.cs | 4 +- .../TagsCloudVisualization.cs | 41 ------ .../TagsCloudVisualization.csproj | 5 +- .../TagsCloudVisualizationTests.cs | 50 ------- cs/TagsCloudVisualization/output.png | Bin 0 -> 388458 bytes 9 files changed, 319 insertions(+), 97 deletions(-) create mode 100644 cs/TagsCloudVisualization/CircularCloudLayouter create mode 100644 cs/TagsCloudVisualization/CircularCloudLayouter.cs create mode 100644 cs/TagsCloudVisualization/CircularCloudLayouterTests.cs delete mode 100644 cs/TagsCloudVisualization/TagsCloudVisualization.cs delete mode 100644 cs/TagsCloudVisualization/TagsCloudVisualizationTests.cs create mode 100644 cs/TagsCloudVisualization/output.png diff --git a/cs/TagsCloudVisualization/CircularCloudLayouter b/cs/TagsCloudVisualization/CircularCloudLayouter new file mode 100644 index 000000000..136ad191d --- /dev/null +++ b/cs/TagsCloudVisualization/CircularCloudLayouter @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using static NUnit.Framework.Constraints.Tolerance; + +namespace TagsCloudVisualization +{ + public class TagsCloudVisualization + { + public Point Center; + public List WordPositions; + public double Radius; + public double Angle; + + public TagsCloudVisualization(Point center) + { + Center = center; + Radius = 0; + Angle = 0; + WordPositions = new List(); + } + + public Rectangle PutNextRectangle(Size rectangleSize) + { + while (true) + { + if (rectangleSize.Width < 1 || rectangleSize.Height < 1) + throw new ArgumentException(); + + var x = Radius * Math.Cos(Angle) + Center.X; + var y = Radius * Math.Sin(Angle)+ Center.Y; + + var currRectangle = new Rectangle(new Point((int)x, (int)y), rectangleSize); + + if (!CheckIntersection(currRectangle)) + { + WordPositions.Add(currRectangle); + return currRectangle; + } + + Angle += 0.1; + + if (Angle >= Math.PI * 2) + { + Angle = 0; + Radius += 0.5; + } + } + } + + + public bool CheckIntersection(Rectangle currRectangle) + { + return WordPositions.Any(rec => + { + var isRecIntersect = Rectangle.Intersect(rec,currRectangle); + return !isRecIntersect.IsEmpty; + }); + } + + public void Drawing() + { + int w = 10000; + int h = 10000; + Bitmap bitmap = new Bitmap(w, h); + Graphics graphics = Graphics.FromImage(bitmap); + Brush brush = new SolidBrush(Color.Blue); + + // Рисование прямоугольников + foreach (var word in WordPositions) + { + var x = word.X + 5000; + var y = word.Y + 5000; + graphics.FillRectangle(brush, x,y,word.Width,word.Height); + } + + bitmap.Save("C:\\Users\\hellw\\Desktop\\output.png", System.Drawing.Imaging.ImageFormat.Png); + } + } +} \ No newline at end of file diff --git a/cs/TagsCloudVisualization/CircularCloudLayouter.cs b/cs/TagsCloudVisualization/CircularCloudLayouter.cs new file mode 100644 index 000000000..10b54dd83 --- /dev/null +++ b/cs/TagsCloudVisualization/CircularCloudLayouter.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using static NUnit.Framework.Constraints.Tolerance; + +namespace TagsCloudVisualization +{ + public class CircularCloudLayouter + { + public Point Center; + public List WordPositions; + public double Radius; + public double Angle; + + public CircularCloudLayouter(Point center) + { + Center = center; + Radius = 0; + Angle = 0; + WordPositions = new List(); + } + + public Rectangle PutNextRectangle(Size rectangleSize) + { + while (true) + { + if (rectangleSize.Width < 1 || rectangleSize.Height < 1) + throw new ArgumentException(); + + var x = Radius * Math.Cos(Angle) + Center.X; + var y = Radius * Math.Sin(Angle) + Center.Y; + + var currRectangle = new Rectangle(new Point((int)x, (int)y), rectangleSize); + + if (!CheckIntersection(currRectangle)) + { + currRectangle = RectangleCompression(currRectangle); + WordPositions.Add(currRectangle); + return currRectangle; + } + + Angle += 0.1; + + if (Angle >= Math.PI * 2) + { + Angle = 0; + Radius += 0.1; + } + } + } + + public bool CheckIntersection(Rectangle currRectangle) + { + return WordPositions.Any(rec => + { + var x = Math.Max(currRectangle.X, rec.X); + var num1 = Math.Min(currRectangle.X + currRectangle.Width, rec.X + rec.Width); + var y = Math.Max(currRectangle.Y, rec.Y); + var num2 = Math.Min(currRectangle.Y + currRectangle.Height, rec.Y + rec.Height); + var res = num1 > x && num2 > y ? new Rectangle(x, y, num1 - x, num2 - y) : Rectangle.Empty; + return !res.IsEmpty; + }); + } + + public Rectangle RectangleCompression(Rectangle rectangle) + { + var changes = 1; + while (changes > 0) + { + CompressionsAxis(ref rectangle, ref changes, Center.X, + (Point point) => point.X, + (Point point, int step) => new Point(point.X + step, point.Y)); + CompressionsAxis(ref rectangle, ref changes, Center.Y, + (Point point) => point.Y, + (Point point, int step) => new Point(point.X, point.Y + step)); + } + + return rectangle; + } + + public void CompressionsAxis(ref Rectangle rectangle, ref int changes, int targetCoord, + Func currCoord, + Func changePoint) + { + var step = (currCoord(rectangle.Location) < targetCoord) ? 1 : -1; + changes = 0; + while (currCoord(rectangle.Location) != targetCoord) + { + var newRectangle = + new Rectangle(changePoint(new Point(rectangle.X, rectangle.Y), step), rectangle.Size); + if (!CheckIntersection(newRectangle)) + { + rectangle = newRectangle; + changes += 1; + continue; + } + + break; + } + } + + public void Drawing(string name) + { + if (string.IsNullOrEmpty(name)) + throw new ArgumentException(); + + int w = 500; + int h = 500; + + Bitmap bitmap = new Bitmap(w, h); + Graphics graphics = Graphics.FromImage(bitmap); + Random random = new Random(); + + foreach (var word in WordPositions) + { + Color randomColor = Color.FromArgb(random.Next(256), random.Next(256), random.Next(256)); + Brush brush = new SolidBrush(randomColor); + var x = word.X + w/2; + var y = word.Y + h/2; + graphics.FillRectangle(brush, x, y, word.Width, word.Height); + } + + string projectDirectory = Directory.GetParent(Environment.CurrentDirectory).Parent.FullName; + string filePath = Path.Combine(projectDirectory, "images",name); + Console.WriteLine(filePath); + bitmap.Save(filePath, System.Drawing.Imaging.ImageFormat.Png); + } + } +} \ No newline at end of file diff --git a/cs/TagsCloudVisualization/CircularCloudLayouterTests.cs b/cs/TagsCloudVisualization/CircularCloudLayouterTests.cs new file mode 100644 index 000000000..8e7c30a79 --- /dev/null +++ b/cs/TagsCloudVisualization/CircularCloudLayouterTests.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using NUnit.Framework; + +namespace TagsCloudVisualization +{ + [TestFixture] + public class CircularCloudLayouterTests + { + [Test] + public void CircularCloudLayouter_Initialize_Params() + { + var center = new Point(1, 2); + var tagsCloud = new CircularCloudLayouter(center); + + Assert.AreEqual(0, tagsCloud.Radius); + Assert.AreEqual(0, tagsCloud.Angle); + Assert.AreEqual(0, tagsCloud.WordPositions.Count); + Assert.AreEqual(center, tagsCloud.Center); + } + + [TestCaseSource(nameof(PutNextRectangleIncorrectArguments))] + public void PutNextRectangle_With_Incorrect_Arguments(Size rectangleSize, CircularCloudLayouter tagsCloud) + { + Assert.Throws(() => tagsCloud.PutNextRectangle(rectangleSize)); + } + + [Test] + public void PutNextRectangleFirstRectanglePositionEqualCenter() + { + var tagsCloud = new CircularCloudLayouter(new Point(4, 2)); + tagsCloud.PutNextRectangle(new Size(3, 1)); + Assert.AreEqual(tagsCloud.Center, tagsCloud.WordPositions[0].Location); + } + + [TestCaseSource(nameof(CheckIntersectionCaseData))] + public bool CheckIntersectionTest(Size size1, Rectangle rectangle) + { + var tagsCloud = new CircularCloudLayouter(new Point(0, 0)); + tagsCloud.PutNextRectangle(size1); + return tagsCloud.CheckIntersection(rectangle); + } + + [TestCaseSource(nameof(RectangleCompressionCaseData))] + public Point RectangleCompression(CircularCloudLayouter cloud, Rectangle rectangle) + { + return cloud.RectangleCompression(rectangle).Location; + } + + private static IEnumerable PutNextRectangleIncorrectArguments() + { + var tagsCloud = new CircularCloudLayouter(new Point()); + + yield return new TestCaseData(new Size(-1, 1), tagsCloud) + .SetName("PutNextReactangle_Throws_ArgumentException_When_Width_Is_Negative"); + + yield return new TestCaseData(new Size(1, -1), tagsCloud) + .SetName("PutNextReactangle_Throws_ArgumentException_When_Height_Is_Negative"); + + yield return new TestCaseData(new Size(0, 1), tagsCloud) + .SetName("PutNextReactangle_Throws_ArgumentException_When_Width_Is_Zero"); + + yield return new TestCaseData(new Size(1, 0), tagsCloud) + .SetName("PutNextReactangle_Throws_ArgumentException_When_Height_Is_Zero"); + } + + private static IEnumerable CheckIntersectionCaseData() + { + yield return new TestCaseData(new Size(4, 2), new Rectangle(new Point(1, 1), new Size(2, 2))) + .SetName( + "CheckIntersection_Return_True_When_Rectangle_Intersection_With_Any_Rectangle_In_CircularCloudLayouter") + .Returns(true); + yield return new TestCaseData(new Size(1, 1), new Rectangle(new Point(1, 0), new Size(1, 1))) + .SetName( + "CheckIntersection_Return_False_When_Rectangle_Have_Common_Side_With_Another_Rectangle") + .Returns(false); + yield return new TestCaseData(new Size(4, 2), new Rectangle(new Point(4, 4), new Size(2, 2))) + .SetName( + "CheckIntersection_Return_True_When_Rectangle_Intersection_With_Any_Rectangle_In_CircularCloudLayouter") + .Returns(false); + } + + private static IEnumerable RectangleCompressionCaseData() + { + var cloudEmpty = new CircularCloudLayouter(new Point()); + var cloudWithElements = new CircularCloudLayouter(new Point()); + cloudWithElements.PutNextRectangle(new Size(1, 1)); + var rectangle = new Rectangle(new Point(5, 5), new Size(1, 1)); + + yield return new TestCaseData(cloudEmpty, rectangle) + .SetName("RectangleCompression_When_Cloud_Is_Empty_Set_Rectangle_Position_On_Center") + .Returns(cloudEmpty.Center); + yield return new TestCaseData(cloudWithElements, rectangle) + .SetName("RectangleCompression_When_Cloud_Has_Rectangles_Set_Rectangle_Position_Closer_To_Center") + .Returns(new Point(0, 1)); + } + } +} \ No newline at end of file diff --git a/cs/TagsCloudVisualization/Program.cs b/cs/TagsCloudVisualization/Program.cs index ff2d5dd5f..902c8412c 100644 --- a/cs/TagsCloudVisualization/Program.cs +++ b/cs/TagsCloudVisualization/Program.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -8,9 +9,9 @@ namespace TagsCloudVisualization { public class Program { - static void Main(string[] args) + static void Main() { - Console.WriteLine("Hello World!"); + Console.ReadKey(); } } } diff --git a/cs/TagsCloudVisualization/Properties/AssemblyInfo.cs b/cs/TagsCloudVisualization/Properties/AssemblyInfo.cs index b80282fac..ed73102d4 100644 --- a/cs/TagsCloudVisualization/Properties/AssemblyInfo.cs +++ b/cs/TagsCloudVisualization/Properties/AssemblyInfo.cs @@ -5,11 +5,11 @@ // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("TagsCloudVisualization")] +[assembly: AssemblyTitle("CircularCloudLayouter")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("TagsCloudVisualization")] +[assembly: AssemblyProduct("CircularCloudLayouter")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/cs/TagsCloudVisualization/TagsCloudVisualization.cs b/cs/TagsCloudVisualization/TagsCloudVisualization.cs deleted file mode 100644 index 1900708fd..000000000 --- a/cs/TagsCloudVisualization/TagsCloudVisualization.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; - -namespace TagsCloudVisualization -{ - public class TagsCloudVisualization - { - public Point Center; - public List WordPositions; - public double Radius; - public double Angle; - - public TagsCloudVisualization(Point center) - { - Center = center; - Radius = 0; - Angle = 0; - } - - public Rectangle PutNextRectangle(Size rectangleSize) - { - throw new ArgumentException(); - } - - } - - /*public class WordPosition - { - public Point Position; - public double Width; - public double Height; - - public WordPosition(Point position, double width, double height) - { - Position = position; - Width = width; - Height = height; - } - }*/ -} \ No newline at end of file diff --git a/cs/TagsCloudVisualization/TagsCloudVisualization.csproj b/cs/TagsCloudVisualization/TagsCloudVisualization.csproj index 689c58e46..a3cefb594 100644 --- a/cs/TagsCloudVisualization/TagsCloudVisualization.csproj +++ b/cs/TagsCloudVisualization/TagsCloudVisualization.csproj @@ -56,15 +56,16 @@ + - - + + diff --git a/cs/TagsCloudVisualization/TagsCloudVisualizationTests.cs b/cs/TagsCloudVisualization/TagsCloudVisualizationTests.cs deleted file mode 100644 index a1841ae04..000000000 --- a/cs/TagsCloudVisualization/TagsCloudVisualizationTests.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using NUnit.Framework; - -namespace TagsCloudVisualization -{ - [TestFixture] - public class TagsCloudVisualizationTests - { - - private TagsCloudVisualization tagsCloud; - - [SetUp] - public void SetUp() - { - tagsCloud = new TagsCloudVisualization(new Point(1, 2)); - } - - [Test] - public void TagsCloudVisualization_Initialize_Params() - { - Assert.AreEqual(0,tagsCloud.Radius); - Assert.AreEqual(0,tagsCloud.Angle); - Assert.AreEqual(null,tagsCloud.WordPositions); - Assert.AreEqual(new Point(1,2), tagsCloud.Center); - } - - [TestCase(-1,2, TestName = "When_Width_Is_Negative")] - [TestCase(1, -2, TestName = "When_Height_Is_Negative")] - [TestCase(0,1, TestName = "When_Width_Is_Zero")] - [TestCase(1, 0, TestName = "When_Height_Is_Zero")] - public void PutNextRectangle_Throws_ArgumentException(int width,int height) - { - var size = new Size(width, height); - Assert.Throws(() => tagsCloud.PutNextRectangle(size)); - } - - [Test] - public void TagsCloudVisualization_First_ElementPosition_Should_Be_Equal_To_Center() - { - tagsCloud.PutNextRectangle(new Size(4, 5)); - Assert.AreEqual(tagsCloud.Center, tagsCloud.WordPositions[0].Location); - } - - } -} diff --git a/cs/TagsCloudVisualization/output.png b/cs/TagsCloudVisualization/output.png new file mode 100644 index 0000000000000000000000000000000000000000..e0bf548bcc84ce099ebb850512c814f0a15799bc GIT binary patch literal 388458 zcmeI)Pl%Ld90%}cb|*2zT{{SsL0v=$ItmeHzRUP$4lW|IMj&k?Y7kh$5`>qQB(g*4 zrJFaAwj$dOf=0+jP+n39LJif2}Y5LPy~HFk!uZdLEId|CIK@5lG7>;9=t?c6#RPF;BRkM5%WR<=D0 z;k%tK3ea!oejB0zuu z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t8YQSbgW(rU!2`obQ}|vXy!_>L);e z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXj+JXW63J4G&K!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfWSZr2nHCaacYJD0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5(52nO&YAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0s|%>7+}B# zsvQCZ2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FpSV9jS-zHN7yoCc{C1009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF%*>tL6hddd*~nVSYX}KQeuNqzK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk{Q^P)`aP@&5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7dX>H>lRQlFsu2@oJafB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+z!Cw$082nD2@oJafB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+K;i;|0TLge z@(B zaA@uJeIaz_n~kg$S7ixQBP1Y!At{jn0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&Y5fBnkM9W?R1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oN9;zkpzX_-CX- z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyP)I;9Kp`%h2@oJafB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+K=cBF0iqv~0tpZxK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfIu+;!2rd)>?S~f009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RpiL z2nL9KLh2(xfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C81=`PjcHpTa?QrDQ ztN-o`?`=6ZyLqS{Tm%RZAV7cs0RjXF5FkK+009C72vi_&ZSw79xgI-xI)RO=Z*0ib zOxWyjd!B6jQ%(rv*iM(aL_Vqvcj=X*R z<(!>g{Ia?uXUBfc*Us#&_&4V3#4Z8^2oNApwZPA34!sycXTI6UT2ZNPz?h5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV8pyfM9?^Ts9LRK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB=E`1q1`cKO+?q zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly@aPD9_4IF7L+H#m8(Hho=~|~{3J3`( zQ`gx92oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkLH0s$cb6`*@00RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UC{aK#K#91HCP07y0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0#yhI2B<>aGYJqNK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfIxWyf&t32bus}01PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oR`5Krlch>>f&h z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjX{6A%ng8m)r~5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7dXH3EVGs&V&J0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1kw<=_`~JfA>0~oHnLV46|0g!zkrZ{eh(`G1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNBUynv8^ Date: Tue, 5 Dec 2023 19:24:33 +0500 Subject: [PATCH 3/9] cleanup code --- cs/TagsCloudVisualization/CircularCloudLayouterTests.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cs/TagsCloudVisualization/CircularCloudLayouterTests.cs b/cs/TagsCloudVisualization/CircularCloudLayouterTests.cs index 8e7c30a79..132203e64 100644 --- a/cs/TagsCloudVisualization/CircularCloudLayouterTests.cs +++ b/cs/TagsCloudVisualization/CircularCloudLayouterTests.cs @@ -71,10 +71,12 @@ private static IEnumerable CheckIntersectionCaseData() .SetName( "CheckIntersection_Return_True_When_Rectangle_Intersection_With_Any_Rectangle_In_CircularCloudLayouter") .Returns(true); + yield return new TestCaseData(new Size(1, 1), new Rectangle(new Point(1, 0), new Size(1, 1))) .SetName( "CheckIntersection_Return_False_When_Rectangle_Have_Common_Side_With_Another_Rectangle") .Returns(false); + yield return new TestCaseData(new Size(4, 2), new Rectangle(new Point(4, 4), new Size(2, 2))) .SetName( "CheckIntersection_Return_True_When_Rectangle_Intersection_With_Any_Rectangle_In_CircularCloudLayouter") @@ -91,6 +93,7 @@ private static IEnumerable RectangleCompressionCaseData() yield return new TestCaseData(cloudEmpty, rectangle) .SetName("RectangleCompression_When_Cloud_Is_Empty_Set_Rectangle_Position_On_Center") .Returns(cloudEmpty.Center); + yield return new TestCaseData(cloudWithElements, rectangle) .SetName("RectangleCompression_When_Cloud_Has_Rectangles_Set_Rectangle_Position_Closer_To_Center") .Returns(new Point(0, 1)); From f6bf236f5b151c153d8b952f33efdb2fdbf0a669 Mon Sep 17 00:00:00 2001 From: RenatZubakin Date: Sun, 10 Dec 2023 06:05:11 +0500 Subject: [PATCH 4/9] refactoring --- .../CircularCloudLayouter.cs | 123 ++++++------------ .../CloudLayouterDrawer.cs | 63 +++++++++ cs/TagsCloudVisualization/IDistribution.cs | 10 ++ cs/TagsCloudVisualization/Program.cs | 20 ++- cs/TagsCloudVisualization/Readme.md | 3 + .../SpiralDistribution.cs | 39 ++++++ .../TagsCloudVisualization.csproj | 11 +- .../CircularCloudLayouterTests.cs | 64 ++++++--- cs/TagsCloudVisualization/images/example1.png | Bin 0 -> 3566 bytes cs/TagsCloudVisualization/images/example2.png | Bin 0 -> 2604 bytes cs/TagsCloudVisualization/images/example3.png | Bin 0 -> 1923 bytes cs/TagsCloudVisualization/output.png | Bin 388458 -> 0 bytes 12 files changed, 228 insertions(+), 105 deletions(-) create mode 100644 cs/TagsCloudVisualization/CloudLayouterDrawer.cs create mode 100644 cs/TagsCloudVisualization/IDistribution.cs create mode 100644 cs/TagsCloudVisualization/Readme.md create mode 100644 cs/TagsCloudVisualization/SpiralDistribution.cs rename cs/TagsCloudVisualization/{ => TagsCloudVisualizationTests}/CircularCloudLayouterTests.cs (60%) create mode 100644 cs/TagsCloudVisualization/images/example1.png create mode 100644 cs/TagsCloudVisualization/images/example2.png create mode 100644 cs/TagsCloudVisualization/images/example3.png delete mode 100644 cs/TagsCloudVisualization/output.png diff --git a/cs/TagsCloudVisualization/CircularCloudLayouter.cs b/cs/TagsCloudVisualization/CircularCloudLayouter.cs index 10b54dd83..5a87a7b6b 100644 --- a/cs/TagsCloudVisualization/CircularCloudLayouter.cs +++ b/cs/TagsCloudVisualization/CircularCloudLayouter.cs @@ -1,131 +1,90 @@ using System; using System.Collections.Generic; using System.Drawing; -using System.IO; using System.Linq; -using static NUnit.Framework.Constraints.Tolerance; namespace TagsCloudVisualization { public class CircularCloudLayouter { - public Point Center; - public List WordPositions; - public double Radius; - public double Angle; - - public CircularCloudLayouter(Point center) + public CircularCloudLayouter(Point center, IDistribution distribution) { + if (center != distribution.Center) + throw new ArgumentException(); + Center = center; - Radius = 0; - Angle = 0; + Distribution = distribution; WordPositions = new List(); } - public Rectangle PutNextRectangle(Size rectangleSize) - { - while (true) - { - if (rectangleSize.Width < 1 || rectangleSize.Height < 1) - throw new ArgumentException(); - - var x = Radius * Math.Cos(Angle) + Center.X; - var y = Radius * Math.Sin(Angle) + Center.Y; + public Point Center { get;private set; } + public List WordPositions { get; private set; } + public IDistribution Distribution { get; private set; } - var currRectangle = new Rectangle(new Point((int)x, (int)y), rectangleSize); - if (!CheckIntersection(currRectangle)) - { - currRectangle = RectangleCompression(currRectangle); - WordPositions.Add(currRectangle); - return currRectangle; - } + public Rectangle PutNextRectangle(Size rectangleSize) + { + if (rectangleSize.Width < 1 || rectangleSize.Height < 1) + throw new ArgumentException(); - Angle += 0.1; + var rectanglePosition = Distribution.GetNextPoint(); + var currRectangle = new Rectangle(rectanglePosition, rectangleSize); - if (Angle >= Math.PI * 2) - { - Angle = 0; - Radius += 0.1; - } + while (CheckIntersection(currRectangle)) + { + rectanglePosition = Distribution.GetNextPoint(); + currRectangle.Location = rectanglePosition; } + + currRectangle = ComperessRectangle(currRectangle); + WordPositions.Add(currRectangle); + return currRectangle; } + public bool CheckIntersection(Rectangle currRectangle) { - return WordPositions.Any(rec => - { - var x = Math.Max(currRectangle.X, rec.X); - var num1 = Math.Min(currRectangle.X + currRectangle.Width, rec.X + rec.Width); - var y = Math.Max(currRectangle.Y, rec.Y); - var num2 = Math.Min(currRectangle.Y + currRectangle.Height, rec.Y + rec.Height); - var res = num1 > x && num2 > y ? new Rectangle(x, y, num1 - x, num2 - y) : Rectangle.Empty; - return !res.IsEmpty; - }); + return WordPositions.Any(rec => currRectangle.IntersectsWith(rec)); } - public Rectangle RectangleCompression(Rectangle rectangle) + + public Rectangle ComperessRectangle(Rectangle rectangle) { var changes = 1; while (changes > 0) { - CompressionsAxis(ref rectangle, ref changes, Center.X, - (Point point) => point.X, - (Point point, int step) => new Point(point.X + step, point.Y)); - CompressionsAxis(ref rectangle, ref changes, Center.Y, - (Point point) => point.Y, - (Point point, int step) => new Point(point.X, point.Y + step)); + rectangle = CompressByAxis(rectangle, true, out changes); + rectangle = CompressByAxis(rectangle, false, out changes); } return rectangle; } - public void CompressionsAxis(ref Rectangle rectangle, ref int changes, int targetCoord, - Func currCoord, - Func changePoint) + + public Rectangle CompressByAxis(Rectangle rectangle, bool isByX, out int changes) { - var step = (currCoord(rectangle.Location) < targetCoord) ? 1 : -1; changes = 0; - while (currCoord(rectangle.Location) != targetCoord) + var stepX = rectangle.X < Center.X ? 1 : -1; + var stepY = rectangle.Y < Center.Y ? 1 : -1; + + while ((isByX && rectangle.X != Center.X) || + (!isByX && rectangle.Y != Center.Y)) { - var newRectangle = - new Rectangle(changePoint(new Point(rectangle.X, rectangle.Y), step), rectangle.Size); + var newRectangle = isByX + ? new Rectangle(new Point(rectangle.X + stepX, rectangle.Y), rectangle.Size) + : new Rectangle(new Point(rectangle.X, rectangle.Y + stepY), rectangle.Size); + if (!CheckIntersection(newRectangle)) { rectangle = newRectangle; - changes += 1; + changes++; continue; } break; } - } - - public void Drawing(string name) - { - if (string.IsNullOrEmpty(name)) - throw new ArgumentException(); - - int w = 500; - int h = 500; - - Bitmap bitmap = new Bitmap(w, h); - Graphics graphics = Graphics.FromImage(bitmap); - Random random = new Random(); - - foreach (var word in WordPositions) - { - Color randomColor = Color.FromArgb(random.Next(256), random.Next(256), random.Next(256)); - Brush brush = new SolidBrush(randomColor); - var x = word.X + w/2; - var y = word.Y + h/2; - graphics.FillRectangle(brush, x, y, word.Width, word.Height); - } - string projectDirectory = Directory.GetParent(Environment.CurrentDirectory).Parent.FullName; - string filePath = Path.Combine(projectDirectory, "images",name); - Console.WriteLine(filePath); - bitmap.Save(filePath, System.Drawing.Imaging.ImageFormat.Png); + return rectangle; } } } \ No newline at end of file diff --git a/cs/TagsCloudVisualization/CloudLayouterDrawer.cs b/cs/TagsCloudVisualization/CloudLayouterDrawer.cs new file mode 100644 index 000000000..0b7e1a5ed --- /dev/null +++ b/cs/TagsCloudVisualization/CloudLayouterDrawer.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; + +namespace TagsCloudVisualization +{ + public static class CloudLayouterDrawer + { + private static readonly Random Random = new Random(); + + + public static void DrawCloudLayout(CircularCloudLayouter layouter, string filename) + { + int imageWidth, imageHeight; + SetImageSize(layouter.WordPositions, out imageWidth, out imageHeight); + var wordImagePositions = layouter.WordPositions.Select(rec => + new Rectangle(rec.X + imageWidth / 2, rec.Y + imageHeight / 2, rec.Width, rec.Height)); + + + using (var bitmap = new Bitmap(imageWidth, imageHeight)) + { + foreach (var rectangle in wordImagePositions) + DrawRectangle(bitmap, rectangle); + SaveImageAsPng(bitmap, filename); + } + } + + + private static void DrawRectangle(Bitmap bitmap, Rectangle rectangle) + { + var randomColor = Color.FromArgb(Random.Next(256), Random.Next(256), Random.Next(256)); + Brush brush = new SolidBrush(randomColor); + + using (var graphics = Graphics.FromImage(bitmap)) + { + graphics.FillRectangle(brush, rectangle); + } + } + + + private static void SaveImageAsPng(Bitmap bitmap, string filename) + { + var projectDirectory = Directory.GetParent(Environment.CurrentDirectory).Parent.FullName; + var filePath = Path.Combine(projectDirectory, "images", filename); + bitmap.Save(filePath, ImageFormat.Png); + } + + + private static void SetImageSize(IEnumerable rectangles, out int imageWidth, out int imageHeight) + { + var maxX = rectangles.Select(rec => rec.X + rec.Width / 2).Max(); + var minX = rectangles.Select(rec => rec.X - rec.Width / 2).Min(); + var maxY = rectangles.Select(rec => rec.Y + rec.Height / 2).Max(); + var minY = rectangles.Select(rec => rec.Y - rec.Height / 2).Min(); + + imageWidth = maxX - minX + 10; + imageHeight = maxY - minY + 10; + } + } +} \ No newline at end of file diff --git a/cs/TagsCloudVisualization/IDistribution.cs b/cs/TagsCloudVisualization/IDistribution.cs new file mode 100644 index 000000000..0d372f0cf --- /dev/null +++ b/cs/TagsCloudVisualization/IDistribution.cs @@ -0,0 +1,10 @@ +using System.Drawing; + +namespace TagsCloudVisualization +{ + public interface IDistribution + { + Point Center { get; } + Point GetNextPoint(); + } +} diff --git a/cs/TagsCloudVisualization/Program.cs b/cs/TagsCloudVisualization/Program.cs index 902c8412c..3b4631f79 100644 --- a/cs/TagsCloudVisualization/Program.cs +++ b/cs/TagsCloudVisualization/Program.cs @@ -1,17 +1,23 @@ using System; -using System.Collections.Generic; using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace TagsCloudVisualization { public class Program { - static void Main() + private static void Main() { - Console.ReadKey(); + var p = new Point(0, 0); + var a = new CircularCloudLayouter(p,new SpiralDistribution(p)); + var random = new Random(); + + for (int i = 0; i < 350; i++) + { + + a.PutNextRectangle(new Size(5,5)); + } + CloudLayouterDrawer.DrawCloudLayout(a,"example3.png"); + } } -} +} \ No newline at end of file diff --git a/cs/TagsCloudVisualization/Readme.md b/cs/TagsCloudVisualization/Readme.md new file mode 100644 index 000000000..09fde1fa5 --- /dev/null +++ b/cs/TagsCloudVisualization/Readme.md @@ -0,0 +1,3 @@ +![" 1"](./images/test.png) +![" 2"](./images/example1.png) +![" 3"](./images/example2.png) diff --git a/cs/TagsCloudVisualization/SpiralDistribution.cs b/cs/TagsCloudVisualization/SpiralDistribution.cs new file mode 100644 index 000000000..6abe07d64 --- /dev/null +++ b/cs/TagsCloudVisualization/SpiralDistribution.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TagsCloudVisualization +{ + public class SpiralDistribution : IDistribution + { + public Point Center { get; private set; } + public double Radius { get; private set; } + public double Angle { get; private set; } + + + public SpiralDistribution(Point center) + { + Center = center; + Radius = 0; + Angle = 0; + } + public Point GetNextPoint() + { + var x = Radius * Math.Cos(Angle) + Center.X; + var y = Radius * Math.Sin(Angle) + Center.Y; + + Angle += 0.1; + + if (Angle >= Math.PI * 2) + { + Angle = 0; + Radius += 0.1; + } + + return new Point((int)x, (int)y); + } + } +} diff --git a/cs/TagsCloudVisualization/TagsCloudVisualization.csproj b/cs/TagsCloudVisualization/TagsCloudVisualization.csproj index a3cefb594..0a943a551 100644 --- a/cs/TagsCloudVisualization/TagsCloudVisualization.csproj +++ b/cs/TagsCloudVisualization/TagsCloudVisualization.csproj @@ -57,15 +57,24 @@ + + - + + + + + + + + diff --git a/cs/TagsCloudVisualization/CircularCloudLayouterTests.cs b/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CircularCloudLayouterTests.cs similarity index 60% rename from cs/TagsCloudVisualization/CircularCloudLayouterTests.cs rename to cs/TagsCloudVisualization/TagsCloudVisualizationTests/CircularCloudLayouterTests.cs index 132203e64..3ed7f5d41 100644 --- a/cs/TagsCloudVisualization/CircularCloudLayouterTests.cs +++ b/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CircularCloudLayouterTests.cs @@ -2,55 +2,85 @@ using System.Collections.Generic; using System.Drawing; using NUnit.Framework; +using NUnit.Framework.Interfaces; namespace TagsCloudVisualization { [TestFixture] public class CircularCloudLayouterTests { + private Point center; + private CircularCloudLayouter tagsCloud; + private SpiralDistribution distribution; + + [SetUp] + public void SetUp() + { + center = new Point(); + distribution = new SpiralDistribution(center); + tagsCloud = new CircularCloudLayouter(center,distribution); + } + + [TearDown] + public void TearDown() + { + if (TestContext.CurrentContext.Result.Outcome.Status == TestStatus.Failed) + { + var fileName = TestContext.CurrentContext.Test.FullName; + CloudLayouterDrawer.DrawCloudLayout(tagsCloud,fileName); + Console.WriteLine($"Tag cloud visualization saved to file /images/{fileName}"); + } + } + [Test] public void CircularCloudLayouter_Initialize_Params() { - var center = new Point(1, 2); - var tagsCloud = new CircularCloudLayouter(center); - - Assert.AreEqual(0, tagsCloud.Radius); - Assert.AreEqual(0, tagsCloud.Angle); Assert.AreEqual(0, tagsCloud.WordPositions.Count); Assert.AreEqual(center, tagsCloud.Center); + Assert.AreEqual(distribution, tagsCloud.Distribution); + } + + [Test] + public void CircularCloudLayouter_Initialize_Throws_ArgumentException_When_Distribution_Have_Different_Center() + { + var center = new Point(1, 5); + var centerDistribution = new Point(2, 4); + var distribution = new SpiralDistribution(centerDistribution); + Assert.Throws(() => new CircularCloudLayouter(center, distribution)); } [TestCaseSource(nameof(PutNextRectangleIncorrectArguments))] - public void PutNextRectangle_With_Incorrect_Arguments(Size rectangleSize, CircularCloudLayouter tagsCloud) + public void PutNextRectangle_ThrowsArgumentException_WhenIncorrectArguments(Size rectangleSize, CircularCloudLayouter tagsCloud) { Assert.Throws(() => tagsCloud.PutNextRectangle(rectangleSize)); } [Test] - public void PutNextRectangleFirstRectanglePositionEqualCenter() + public void PutNextRectangle_Should_Place_First_On_Center() { - var tagsCloud = new CircularCloudLayouter(new Point(4, 2)); tagsCloud.PutNextRectangle(new Size(3, 1)); Assert.AreEqual(tagsCloud.Center, tagsCloud.WordPositions[0].Location); } [TestCaseSource(nameof(CheckIntersectionCaseData))] - public bool CheckIntersectionTest(Size size1, Rectangle rectangle) + public bool CheckIntersectionTest(Size rectangleSize, Rectangle rectangle) { - var tagsCloud = new CircularCloudLayouter(new Point(0, 0)); - tagsCloud.PutNextRectangle(size1); + tagsCloud.PutNextRectangle(rectangleSize); return tagsCloud.CheckIntersection(rectangle); } [TestCaseSource(nameof(RectangleCompressionCaseData))] public Point RectangleCompression(CircularCloudLayouter cloud, Rectangle rectangle) { - return cloud.RectangleCompression(rectangle).Location; + return cloud.ComperessRectangle(rectangle).Location; } + private static IEnumerable PutNextRectangleIncorrectArguments() { - var tagsCloud = new CircularCloudLayouter(new Point()); + var center = new Point(); + var distribution = new SpiralDistribution(center); + var tagsCloud = new CircularCloudLayouter(center,distribution); yield return new TestCaseData(new Size(-1, 1), tagsCloud) .SetName("PutNextReactangle_Throws_ArgumentException_When_Width_Is_Negative"); @@ -85,8 +115,11 @@ private static IEnumerable CheckIntersectionCaseData() private static IEnumerable RectangleCompressionCaseData() { - var cloudEmpty = new CircularCloudLayouter(new Point()); - var cloudWithElements = new CircularCloudLayouter(new Point()); + var center = new Point(); + var distributionEmpty = new SpiralDistribution(center); + var cloudEmpty = new CircularCloudLayouter(center,distributionEmpty); + var distributionWithElements = new SpiralDistribution(center); + var cloudWithElements = new CircularCloudLayouter(center, distributionWithElements); cloudWithElements.PutNextRectangle(new Size(1, 1)); var rectangle = new Rectangle(new Point(5, 5), new Size(1, 1)); @@ -98,5 +131,6 @@ private static IEnumerable RectangleCompressionCaseData() .SetName("RectangleCompression_When_Cloud_Has_Rectangles_Set_Rectangle_Position_Closer_To_Center") .Returns(new Point(0, 1)); } + } } \ No newline at end of file diff --git a/cs/TagsCloudVisualization/images/example1.png b/cs/TagsCloudVisualization/images/example1.png new file mode 100644 index 0000000000000000000000000000000000000000..90bf8ceb7be8e2780aff3c7ccc5431924a9e8328 GIT binary patch literal 3566 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 literal 0 HcmV?d00001 diff --git a/cs/TagsCloudVisualization/images/example3.png b/cs/TagsCloudVisualization/images/example3.png new file mode 100644 index 0000000000000000000000000000000000000000..17738e42d0f1e44d6f9c9e413f19c3945b8161c1 GIT binary patch literal 1923 zcmZ9Nc{CgN7RM7wERl%iS!&PNX&;THOlwI{%P1yBnY>10#8!KQCf3IKOg)^^mfF)= zW||VEq=FP}ZLf+_)G|^AwI!&r^TK;`PUrn`f8TTex#!-`?|bgeaCNqWL*=0W008b_ zZ-eFQ&65xopTfy zS6DR>01%RMutEPo_F5eb^8B!+)DP~oUPw-k8_X0-ZVFRc1~~? zn!Vm7vbhuXnz=nhRDsipSdMY&VR|?bjmq%4pQLwoY%zIwT{3+W%yr*J$KPG4a>B@W zt3Rfm3Q@MyjZi`xxzr4)DVR>5I6u#zOd6ODc9gC(1MF473ijNd+)WD zkK~Y*CK66O71qut*(~>lq%Al!qBr$ePE> z&h90G_-Q%jhPO(0q*(Iav}R6gh;p3obFd@cGR2!xBR*^@3Y}W9GT%N9Jt=uI^~HET zJ}eQthYDV0a29{O;pD;|{rdLk2S!DMSuP1pK=t0kW1oMCi=| zYb#0!OkLLn8oPJpp5i#^U4yuT`@Kt5eIUnleTHy) z5glCfs24aOL195hCKhIphW7w|$5lD-j=%9O*i!ZJl!x}@=s6B>+ z&g+IV`+X$Ui%YiJ&Cx)t)CSV$9h6tN2J2e(pg#O{_A59WmUQkJ+vP&rAH^-{(ikri zgyn(gkUP{Kpd^UgDz$*Mvw~DVzrf`mOnNi7d<9d^dO{B^JP0pt!JJ;a7j0ubQ~vY} zYPI_vs^udcbf+3vc7IR*YdS2wfhKKSlVPMm0$D9zdL=pH&2rg|6(iy2q_m_jCZ3!K zfuuey^!iN2%yW0d6Bi14rI%1WZ6V-1XPjJjPmf$t(Ox&m5%)VlIl;Fe|IdEeWboP` zlzm3zSZ+;l(}|rLF}ghSW>k&f!jWgj5!L5Z#-TCCGE7CDgd(;C@_=>5mB}&gE({l= zDZdriAMXkGjRxh}Hgr6F60dqJTTxcIME=v3eES3^u9HC0=VmiZat{00=xqi(r^N#3 z*Zd_p^17kvPAYtE1)kEt1n;!6m4jE^ya#sv#R$rjf_=maT`{|wqx3;E?hm$DX$>m9 z^GR)cZwL$h*WcZpZ5q(<7~FexQ;j|~31dGMzKy&rJ;41%Am3zN{o2%og3Nv!K<&c! zWiHSn+ze!y+aeHu&gW&Kt)3?YY_+zlL}1689E=;u4}*&hPwaSVc`T-pT@vN>^9Nw9 zBhR@2>U`1vrHI;vYTPP#H)GU$AnDK`c+6|@>Q&I-i>>g!pI|9kYv4Y!I~;79ShT!; zQuS>-<3PiXTuYIt7WvlyD7+dcQ^=QyM z*hHBY<|VHSWija9;5c5K;lcU^Ujz1Y$zSR9gt^Kv)reK1se%M-&pN0q?3STpB4Ri< z>g`|m=C%*pt>FWg0%+2GizE(1nWMLKhyC%l4-+jBhcR^O2)b>i;imRkiYai2Uj{uY zm9>|i98=PDI^>^AbCzk79%=ieZc-4l6xz`;aO0mwq%`HjsrDfUAr-{aq>eA*`JCTi z*eYI>AY4t^5Qhp`~1+rSI1V h!xuF^i&A@(2$D^$+0J~FN#h?*fP<~GO$~;S^dBS@Z7~1< literal 0 HcmV?d00001 diff --git a/cs/TagsCloudVisualization/output.png b/cs/TagsCloudVisualization/output.png deleted file mode 100644 index e0bf548bcc84ce099ebb850512c814f0a15799bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 388458 zcmeI)Pl%Ld90%}cb|*2zT{{SsL0v=$ItmeHzRUP$4lW|IMj&k?Y7kh$5`>qQB(g*4 zrJFaAwj$dOf=0+jP+n39LJif2}Y5LPy~HFk!uZdLEId|CIK@5lG7>;9=t?c6#RPF;BRkM5%WR<=D0 z;k%tK3ea!oejB0zuu z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t8YQSbgW(rU!2`obQ}|vXy!_>L);e z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXj+JXW63J4G&K!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfWSZr2nHCaacYJD0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5(52nO&YAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0s|%>7+}B# zsvQCZ2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FpSV9jS-zHN7yoCc{C1009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF%*>tL6hddd*~nVSYX}KQeuNqzK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk{Q^P)`aP@&5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7dX>H>lRQlFsu2@oJafB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+z!Cw$082nD2@oJafB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+K;i;|0TLge z@(B zaA@uJeIaz_n~kg$S7ixQBP1Y!At{jn0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&Y5fBnkM9W?R1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oN9;zkpzX_-CX- z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyP)I;9Kp`%h2@oJafB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+K=cBF0iqv~0tpZxK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfIu+;!2rd)>?S~f009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RpiL z2nL9KLh2(xfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C81=`PjcHpTa?QrDQ ztN-o`?`=6ZyLqS{Tm%RZAV7cs0RjXF5FkK+009C72vi_&ZSw79xgI-xI)RO=Z*0ib zOxWyjd!B6jQ%(rv*iM(aL_Vqvcj=X*R z<(!>g{Ia?uXUBfc*Us#&_&4V3#4Z8^2oNApwZPA34!sycXTI6UT2ZNPz?h5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV8pyfM9?^Ts9LRK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB=E`1q1`cKO+?q zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly@aPD9_4IF7L+H#m8(Hho=~|~{3J3`( zQ`gx92oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkLH0s$cb6`*@00RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UC{aK#K#91HCP07y0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0#yhI2B<>aGYJqNK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfIxWyf&t32bus}01PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oR`5Krlch>>f&h z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjX{6A%ng8m)r~5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7dXH3EVGs&V&J0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1kw<=_`~JfA>0~oHnLV46|0g!zkrZ{eh(`G1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNBUynv8^ Date: Sun, 10 Dec 2023 06:06:28 +0500 Subject: [PATCH 5/9] refactoring1 --- cs/TagsCloudVisualization/Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cs/TagsCloudVisualization/Readme.md b/cs/TagsCloudVisualization/Readme.md index 09fde1fa5..4de85600c 100644 --- a/cs/TagsCloudVisualization/Readme.md +++ b/cs/TagsCloudVisualization/Readme.md @@ -1,3 +1,3 @@ -![" 1"](./images/test.png) +![" 1"](./images/example3.png) ![" 2"](./images/example1.png) ![" 3"](./images/example2.png) From dad14b2f4b780ed14701f8edbfee4b2b27431d45 Mon Sep 17 00:00:00 2001 From: RenatZubakin Date: Sun, 10 Dec 2023 13:49:31 +0500 Subject: [PATCH 6/9] add SpiralDistribution tests --- .../CircularCloudLayouter.cs | 2 +- .../TagsCloudVisualization.csproj | 1 + .../CircularCloudLayouterTests.cs | 14 ++--- .../SpiralDistributionTests.cs | 57 +++++++++++++++++++ 4 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 cs/TagsCloudVisualization/TagsCloudVisualizationTests/SpiralDistributionTests.cs diff --git a/cs/TagsCloudVisualization/CircularCloudLayouter.cs b/cs/TagsCloudVisualization/CircularCloudLayouter.cs index 5a87a7b6b..b9bafa019 100644 --- a/cs/TagsCloudVisualization/CircularCloudLayouter.cs +++ b/cs/TagsCloudVisualization/CircularCloudLayouter.cs @@ -17,7 +17,7 @@ public CircularCloudLayouter(Point center, IDistribution distribution) WordPositions = new List(); } - public Point Center { get;private set; } + public Point Center { get; private set; } public List WordPositions { get; private set; } public IDistribution Distribution { get; private set; } diff --git a/cs/TagsCloudVisualization/TagsCloudVisualization.csproj b/cs/TagsCloudVisualization/TagsCloudVisualization.csproj index 0a943a551..e27d1789e 100644 --- a/cs/TagsCloudVisualization/TagsCloudVisualization.csproj +++ b/cs/TagsCloudVisualization/TagsCloudVisualization.csproj @@ -63,6 +63,7 @@ + diff --git a/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CircularCloudLayouterTests.cs b/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CircularCloudLayouterTests.cs index 3ed7f5d41..98d503643 100644 --- a/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CircularCloudLayouterTests.cs +++ b/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CircularCloudLayouterTests.cs @@ -18,7 +18,7 @@ public void SetUp() { center = new Point(); distribution = new SpiralDistribution(center); - tagsCloud = new CircularCloudLayouter(center,distribution); + tagsCloud = new CircularCloudLayouter(center, distribution); } [TearDown] @@ -27,8 +27,8 @@ public void TearDown() if (TestContext.CurrentContext.Result.Outcome.Status == TestStatus.Failed) { var fileName = TestContext.CurrentContext.Test.FullName; - CloudLayouterDrawer.DrawCloudLayout(tagsCloud,fileName); - Console.WriteLine($"Tag cloud visualization saved to file /images/{fileName}"); + CloudLayouterDrawer.DrawCloudLayout(tagsCloud, fileName); + Console.WriteLine($"Tag cloud visualization saved to file /images/{fileName}.png"); } } @@ -50,7 +50,8 @@ public void CircularCloudLayouter_Initialize_Throws_ArgumentException_When_Distr } [TestCaseSource(nameof(PutNextRectangleIncorrectArguments))] - public void PutNextRectangle_ThrowsArgumentException_WhenIncorrectArguments(Size rectangleSize, CircularCloudLayouter tagsCloud) + public void PutNextRectangle_ThrowsArgumentException_WhenIncorrectArguments(Size rectangleSize, + CircularCloudLayouter tagsCloud) { Assert.Throws(() => tagsCloud.PutNextRectangle(rectangleSize)); } @@ -80,7 +81,7 @@ private static IEnumerable PutNextRectangleIncorrectArguments() { var center = new Point(); var distribution = new SpiralDistribution(center); - var tagsCloud = new CircularCloudLayouter(center,distribution); + var tagsCloud = new CircularCloudLayouter(center, distribution); yield return new TestCaseData(new Size(-1, 1), tagsCloud) .SetName("PutNextReactangle_Throws_ArgumentException_When_Width_Is_Negative"); @@ -117,7 +118,7 @@ private static IEnumerable RectangleCompressionCaseData() { var center = new Point(); var distributionEmpty = new SpiralDistribution(center); - var cloudEmpty = new CircularCloudLayouter(center,distributionEmpty); + var cloudEmpty = new CircularCloudLayouter(center, distributionEmpty); var distributionWithElements = new SpiralDistribution(center); var cloudWithElements = new CircularCloudLayouter(center, distributionWithElements); cloudWithElements.PutNextRectangle(new Size(1, 1)); @@ -131,6 +132,5 @@ private static IEnumerable RectangleCompressionCaseData() .SetName("RectangleCompression_When_Cloud_Has_Rectangles_Set_Rectangle_Position_Closer_To_Center") .Returns(new Point(0, 1)); } - } } \ No newline at end of file diff --git a/cs/TagsCloudVisualization/TagsCloudVisualizationTests/SpiralDistributionTests.cs b/cs/TagsCloudVisualization/TagsCloudVisualizationTests/SpiralDistributionTests.cs new file mode 100644 index 000000000..5277a553a --- /dev/null +++ b/cs/TagsCloudVisualization/TagsCloudVisualizationTests/SpiralDistributionTests.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using NUnit.Framework; + +namespace TagsCloudVisualization.TagsCloudVisualizationTests +{ + [TestFixture] + public class SpiralDistributionTests + { + private Point center; + private SpiralDistribution spiralDistribution; + + [SetUp] + public void SetUp() + { + center = new Point(); + spiralDistribution = new SpiralDistribution(center); + } + + + [Test] + public void SprialDistribution_Initialize_Params() + { + Assert.AreEqual(center, spiralDistribution.Center); + Assert.AreEqual(0, spiralDistribution.Angle); + Assert.AreEqual(0, spiralDistribution.Radius); + } + + [Test] + public void SpiralDistribution_First_Call_GetNextPoint_Should_Return_Center() + { + Assert.AreEqual(center, spiralDistribution.GetNextPoint()); + } + + [Test] + public void SpiralDistribution_Should_Increase_Angle_After_Call_GetNextPoint() + { + spiralDistribution.GetNextPoint(); + Assert.AreEqual(0.1, spiralDistribution.Angle); + } + + [Test] + public void SpiralDistribution_Should_Increase_Radius_And_Reset_Angle_When_Angle_More_Than_2Pi() + { + for (int i = 0; i < 63; i++) + { + spiralDistribution.GetNextPoint(); + } + Assert.AreEqual(0,spiralDistribution.Angle); + Assert.AreEqual(0.1,spiralDistribution.Radius); + } + } +} \ No newline at end of file From b28d5fca92e5c64ec19100ef45a6156c7d902f3c Mon Sep 17 00:00:00 2001 From: RenatZubakin Date: Sun, 10 Dec 2023 16:02:16 +0500 Subject: [PATCH 7/9] add tests and refactoring --- .../CircularCloudLayouter.cs | 3 +- .../CloudLayouterDrawer.cs | 69 ++++++++++-------- cs/TagsCloudVisualization/Program.cs | 12 +-- .../TagsCloudVisualization.csproj | 1 + .../CircularCloudLayouterTests.cs | 12 +-- .../CloudLayouterDrawerTests.cs | 51 +++++++++++++ cs/TagsCloudVisualization/images/example3.png | Bin 1923 -> 1926 bytes 7 files changed, 99 insertions(+), 49 deletions(-) create mode 100644 cs/TagsCloudVisualization/TagsCloudVisualizationTests/CloudLayouterDrawerTests.cs diff --git a/cs/TagsCloudVisualization/CircularCloudLayouter.cs b/cs/TagsCloudVisualization/CircularCloudLayouter.cs index b9bafa019..ee81a8c62 100644 --- a/cs/TagsCloudVisualization/CircularCloudLayouter.cs +++ b/cs/TagsCloudVisualization/CircularCloudLayouter.cs @@ -61,7 +61,7 @@ public Rectangle ComperessRectangle(Rectangle rectangle) } - public Rectangle CompressByAxis(Rectangle rectangle, bool isByX, out int changes) + private Rectangle CompressByAxis(Rectangle rectangle, bool isByX, out int changes) { changes = 0; var stepX = rectangle.X < Center.X ? 1 : -1; @@ -86,5 +86,6 @@ public Rectangle CompressByAxis(Rectangle rectangle, bool isByX, out int changes return rectangle; } + } } \ No newline at end of file diff --git a/cs/TagsCloudVisualization/CloudLayouterDrawer.cs b/cs/TagsCloudVisualization/CloudLayouterDrawer.cs index 0b7e1a5ed..b2391ef9a 100644 --- a/cs/TagsCloudVisualization/CloudLayouterDrawer.cs +++ b/cs/TagsCloudVisualization/CloudLayouterDrawer.cs @@ -7,57 +7,62 @@ namespace TagsCloudVisualization { - public static class CloudLayouterDrawer + public class CloudLayouterDrawer { - private static readonly Random Random = new Random(); + private Random random; + public int margin; + public int imageWidth; + public int imageHeight; + public CloudLayouterDrawer(int margin) + { + this.margin= margin; + random = new Random(); + } - public static void DrawCloudLayout(CircularCloudLayouter layouter, string filename) + public void DrawCloud(string filename, IEnumerable rectangles) { - int imageWidth, imageHeight; - SetImageSize(layouter.WordPositions, out imageWidth, out imageHeight); - var wordImagePositions = layouter.WordPositions.Select(rec => - new Rectangle(rec.X + imageWidth / 2, rec.Y + imageHeight / 2, rec.Width, rec.Height)); + if (!rectangles.Any()) + throw new ArgumentException(); + SetImageSize(rectangles); + var newRectanglesPositions = GetNewRectanglesPositions(rectangles); using (var bitmap = new Bitmap(imageWidth, imageHeight)) { - foreach (var rectangle in wordImagePositions) - DrawRectangle(bitmap, rectangle); - SaveImageAsPng(bitmap, filename); - } - } + using (var graphics = Graphics.FromImage(bitmap)) + { + foreach (var rectangle in newRectanglesPositions) + { + var color = Color.FromArgb(random.Next(256), random.Next(256), random.Next(256)); + var brush = new SolidBrush(color); + graphics.FillRectangle(brush, rectangle); + } - private static void DrawRectangle(Bitmap bitmap, Rectangle rectangle) - { - var randomColor = Color.FromArgb(Random.Next(256), Random.Next(256), Random.Next(256)); - Brush brush = new SolidBrush(randomColor); - - using (var graphics = Graphics.FromImage(bitmap)) - { - graphics.FillRectangle(brush, rectangle); + var projectDirectory = Directory.GetParent(Environment.CurrentDirectory).Parent.FullName; + var filePath = Path.Combine(projectDirectory, "images", filename); + bitmap.Save(filePath, ImageFormat.Png); + } } } - - private static void SaveImageAsPng(Bitmap bitmap, string filename) - { - var projectDirectory = Directory.GetParent(Environment.CurrentDirectory).Parent.FullName; - var filePath = Path.Combine(projectDirectory, "images", filename); - bitmap.Save(filePath, ImageFormat.Png); - } - - - private static void SetImageSize(IEnumerable rectangles, out int imageWidth, out int imageHeight) + private void SetImageSize(IEnumerable rectangles) { var maxX = rectangles.Select(rec => rec.X + rec.Width / 2).Max(); var minX = rectangles.Select(rec => rec.X - rec.Width / 2).Min(); var maxY = rectangles.Select(rec => rec.Y + rec.Height / 2).Max(); var minY = rectangles.Select(rec => rec.Y - rec.Height / 2).Min(); - imageWidth = maxX - minX + 10; - imageHeight = maxY - minY + 10; + imageWidth = maxX - minX + margin; + imageHeight = maxY - minY + margin; } + + private IEnumerable GetNewRectanglesPositions(IEnumerable rectangles) + { + return rectangles.Select(rec => + new Rectangle(rec.X + imageWidth / 2, rec.Y + imageHeight / 2, rec.Width, rec.Height)); + } + } } \ No newline at end of file diff --git a/cs/TagsCloudVisualization/Program.cs b/cs/TagsCloudVisualization/Program.cs index 3b4631f79..2cea0f135 100644 --- a/cs/TagsCloudVisualization/Program.cs +++ b/cs/TagsCloudVisualization/Program.cs @@ -7,17 +7,7 @@ public class Program { private static void Main() { - var p = new Point(0, 0); - var a = new CircularCloudLayouter(p,new SpiralDistribution(p)); - var random = new Random(); - - for (int i = 0; i < 350; i++) - { - - a.PutNextRectangle(new Size(5,5)); - } - CloudLayouterDrawer.DrawCloudLayout(a,"example3.png"); - + } } } \ No newline at end of file diff --git a/cs/TagsCloudVisualization/TagsCloudVisualization.csproj b/cs/TagsCloudVisualization/TagsCloudVisualization.csproj index e27d1789e..6a72393b3 100644 --- a/cs/TagsCloudVisualization/TagsCloudVisualization.csproj +++ b/cs/TagsCloudVisualization/TagsCloudVisualization.csproj @@ -63,6 +63,7 @@ + diff --git a/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CircularCloudLayouterTests.cs b/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CircularCloudLayouterTests.cs index 98d503643..90320669c 100644 --- a/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CircularCloudLayouterTests.cs +++ b/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CircularCloudLayouterTests.cs @@ -12,6 +12,7 @@ public class CircularCloudLayouterTests private Point center; private CircularCloudLayouter tagsCloud; private SpiralDistribution distribution; + private CloudLayouterDrawer drawer; [SetUp] public void SetUp() @@ -19,19 +20,20 @@ public void SetUp() center = new Point(); distribution = new SpiralDistribution(center); tagsCloud = new CircularCloudLayouter(center, distribution); + drawer = new CloudLayouterDrawer(10); } - [TearDown] + [TearDown] public void TearDown() { if (TestContext.CurrentContext.Result.Outcome.Status == TestStatus.Failed) { - var fileName = TestContext.CurrentContext.Test.FullName; - CloudLayouterDrawer.DrawCloudLayout(tagsCloud, fileName); - Console.WriteLine($"Tag cloud visualization saved to file /images/{fileName}.png"); + var fileName =$"{TestContext.CurrentContext.Test.FullName}.png"; + drawer.DrawCloud(fileName, tagsCloud.WordPositions); + Console.WriteLine($"Tag cloud visualization saved to file /images/{fileName}"); } } - + [Test] public void CircularCloudLayouter_Initialize_Params() { diff --git a/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CloudLayouterDrawerTests.cs b/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CloudLayouterDrawerTests.cs new file mode 100644 index 000000000..1f7ec5c0d --- /dev/null +++ b/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CloudLayouterDrawerTests.cs @@ -0,0 +1,51 @@ +using System; +using System.Drawing; +using System.IO; +using NUnit.Framework; + +namespace TagsCloudVisualization.TagsCloudVisualizationTests +{ + [TestFixture] + public class CloudLayouterDrawerTests + { + private CloudLayouterDrawer drawer; + private string fileName; + private string TestFilePath; + + + [SetUp] + public void SetUp() + { + drawer = new CloudLayouterDrawer(10); + fileName = "testcreation.png"; + var projectDirectory = Directory.GetParent(Environment.CurrentDirectory).Parent.FullName; + TestFilePath = Path.Combine(projectDirectory, "images", fileName); + if (File.Exists(TestFilePath)) + { + File.Delete(TestFilePath); + } + } + + [TearDown] + public void TearDown() + { + if (File.Exists(TestFilePath)) + { + File.Delete(TestFilePath); + } + } + [Test] + public void CloudLayouterDrawer_Initialize_Params() + { + Assert.AreEqual(10,drawer.margin); + } + + [Test] + public void CloudLayouterDrawer_IsCreate_Imgae() + { + var rectanglesCollection = new Rectangle[] { new Rectangle(0, 0, 5, 10) }; + drawer.DrawCloud(fileName,rectanglesCollection); + Assert.IsTrue(File.Exists(TestFilePath), $"File at path '{TestFilePath}' should have been created."); + } + } +} diff --git a/cs/TagsCloudVisualization/images/example3.png b/cs/TagsCloudVisualization/images/example3.png index 17738e42d0f1e44d6f9c9e413f19c3945b8161c1..3d9938962362907c8fefa50abb71f0a221bc70a4 100644 GIT binary patch delta 1861 zcmZXVc|03-AIB?5q*8HLrJ^=8v>oCoSsf9EI#*?(w22}nu2MIRYvHM**&L0dVQT6q z@}!CfC5~<@b)+b9#I4j7=I9*BuIaq zUS$y-azf>Q*|4~%2_2J<#9F)-%pzP3F@N3G_ z&wu739_Dr7-^WSINVp2gNI85%Nt}^jg}Iol#fG%9_q#Q1JLBVVmJBaz#($yHDlW6h~js$Fq0RtSmpzP15<{ zMEpK1dxe;>7>fP?+nVvDVU97hCsmNCF)2}(n-xz=odlPyUz6a)bixWC>&#bh?F;B| zIb^hXd=xE18?2_J;u)Qnltqzb82V2uLCw2YYvF52jftF>;*ESwz~vaIsnh1yh?QO8 zh>2~`@<9i^-ov0^zu_DWl9Ehr*H5wCgA8WA?6a~w@){dZE;;hz*SOrWb*!y;SHmPd zK~I{5&fZIDng@s$KUJEEhx-{%ib`b!kU?Lt#FyTktqa=_uCI2-Gb`Nt2buvqEp?G` z!}|EB(aA8$8>ZJ!Y-1!Dg5-jgDugR)*jFwZCG)fJ7{-#BOzD3H=wb-sxkNsB)2`HE z?hcrpfx+AMDeDJ(3D`SZoj~fbu)cuv(DG~E(l*mej*D93Pn^tna>@5e%?cHc zwH`fo=vch$mi-1GfAe+Fiv{(ADy~=omJXuL--$D@CZO*xN=00qv!G_{fq=0qP-8;{ zv4633=>vn(yilZQv&Je=7d>Y4=e#P%5Kt352aq|5*fpdug);!63|}M|sNCaDXCG32 zpa}}!MvE7$oO;8v#`Dv>aD*l}>TDLXl;Jw^I2*L4ct3vW!7n)8bSvii1DC0BY20enFMlVt!Wr^|uR;n8hE1K57!y5we3Z~WB8 z*5!tt`b4gpu6R@vTrYqPb}#m5V}A(?*0bnXTksv>I(|VdWyj}LY@eifGQK2Zel>{q ztT;57kD+t21j^$rrgHms#e;v8SMQQFsc&2or?<(-=cnS9KZ6BDeGtcTdXux+!+0)T zogP>QY`v$|A9@f*3TpWzV&l7yne59)+Yash&HgA?_U4VooJ+3Bvfh{+C9z=V9rEkn zGCB%l^b&gSURiAFG#MF^FZ|n^b`q z&czLi&MWxf%_{r<;(tY>7~#$$jS?*55RWzc?U9M8PRqE`eFLf!0oV=lH1Up7#FFlc z4Eig89~7##kBp_`95R7m>q-M~PjRKt*#ngR*kh!sDX+wUoDL z^W5}@?~~X(`U26gIhLhT;NA^Jl>9zNu7ua$M8WH&abI z=hnQc$lMeoO(YIj(m=+m?3$Mxd`{$BCW`>m$Nz2I+Abis;P0%lL=qJvaz&;JCA@{fA%TU2L!H-wHrrX~cvOLKJ4A#}|9+Jn*|FBo5dA6=G~hZM-#7hEsVxagZ_Kup9{; z6!Jg0QOAWk0?*qtti4s{qq4;T&PzE?KOL<9aiJ3tq1|_G^X)c;q%JEv;R?{UXchXN z*j_}4RX`+?)=fOuZqjSi$saE6nC7g8I@s@z+5NR9p858s@>aj*?0n2qHov6I5O1+L zfBK9QJ1FKLOy8LzY8~uxfw;ZP)mc|dqXz=|UK%-|7A4#?ZbLFSMwAk$z_#aV$nie> zx})>wB^`~{IQ*K$(0LozHRC3-#*re$*mU6UKa%r_@q;#fwui9`kT|&JE#oQOlN1TH z##6VugSZ+kMYLzLC%1!5Q&l>u-%1MXNwYcYWAzq!6z1#@patU~pC=wrKTPd4z)DmW z@uLq1=qf-023E(ivR!s literal 1923 zcmZ9Nc{CgN7RM7wERl%iS!&PNX&;THOlwI{%P1yBnY>10#8!KQCf3IKOg)^^mfF)= zW||VEq=FP}ZLf+_)G|^AwI!&r^TK;`PUrn`f8TTex#!-`?|bgeaCNqWL*=0W008b_ zZ-eFQ&65xopTfy zS6DR>01%RMutEPo_F5eb^8B!+)DP~oUPw-k8_X0-ZVFRc1~~? zn!Vm7vbhuXnz=nhRDsipSdMY&VR|?bjmq%4pQLwoY%zIwT{3+W%yr*J$KPG4a>B@W zt3Rfm3Q@MyjZi`xxzr4)DVR>5I6u#zOd6ODc9gC(1MF473ijNd+)WD zkK~Y*CK66O71qut*(~>lq%Al!qBr$ePE> z&h90G_-Q%jhPO(0q*(Iav}R6gh;p3obFd@cGR2!xBR*^@3Y}W9GT%N9Jt=uI^~HET zJ}eQthYDV0a29{O;pD;|{rdLk2S!DMSuP1pK=t0kW1oMCi=| zYb#0!OkLLn8oPJpp5i#^U4yuT`@Kt5eIUnleTHy) z5glCfs24aOL195hCKhIphW7w|$5lD-j=%9O*i!ZJl!x}@=s6B>+ z&g+IV`+X$Ui%YiJ&Cx)t)CSV$9h6tN2J2e(pg#O{_A59WmUQkJ+vP&rAH^-{(ikri zgyn(gkUP{Kpd^UgDz$*Mvw~DVzrf`mOnNi7d<9d^dO{B^JP0pt!JJ;a7j0ubQ~vY} zYPI_vs^udcbf+3vc7IR*YdS2wfhKKSlVPMm0$D9zdL=pH&2rg|6(iy2q_m_jCZ3!K zfuuey^!iN2%yW0d6Bi14rI%1WZ6V-1XPjJjPmf$t(Ox&m5%)VlIl;Fe|IdEeWboP` zlzm3zSZ+;l(}|rLF}ghSW>k&f!jWgj5!L5Z#-TCCGE7CDgd(;C@_=>5mB}&gE({l= zDZdriAMXkGjRxh}Hgr6F60dqJTTxcIME=v3eES3^u9HC0=VmiZat{00=xqi(r^N#3 z*Zd_p^17kvPAYtE1)kEt1n;!6m4jE^ya#sv#R$rjf_=maT`{|wqx3;E?hm$DX$>m9 z^GR)cZwL$h*WcZpZ5q(<7~FexQ;j|~31dGMzKy&rJ;41%Am3zN{o2%og3Nv!K<&c! zWiHSn+ze!y+aeHu&gW&Kt)3?YY_+zlL}1689E=;u4}*&hPwaSVc`T-pT@vN>^9Nw9 zBhR@2>U`1vrHI;vYTPP#H)GU$AnDK`c+6|@>Q&I-i>>g!pI|9kYv4Y!I~;79ShT!; zQuS>-<3PiXTuYIt7WvlyD7+dcQ^=QyM z*hHBY<|VHSWija9;5c5K;lcU^Ujz1Y$zSR9gt^Kv)reK1se%M-&pN0q?3STpB4Ri< z>g`|m=C%*pt>FWg0%+2GizE(1nWMLKhyC%l4-+jBhcR^O2)b>i;imRkiYai2Uj{uY zm9>|i98=PDI^>^AbCzk79%=ieZc-4l6xz`;aO0mwq%`HjsrDfUAr-{aq>eA*`JCTi z*eYI>AY4t^5Qhp`~1+rSI1V h!xuF^i&A@(2$D^$+0J~FN#h?*fP<~GO$~;S^dBS@Z7~1< From 91a3c63a23a2e003c1c8139f33db1949e45f9e7a Mon Sep 17 00:00:00 2001 From: RenatZubakin Date: Sun, 10 Dec 2023 16:04:24 +0500 Subject: [PATCH 8/9] cleanup code --- cs/TagsCloudVisualization/CircularCloudLayouter.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cs/TagsCloudVisualization/CircularCloudLayouter.cs b/cs/TagsCloudVisualization/CircularCloudLayouter.cs index ee81a8c62..dfb898a35 100644 --- a/cs/TagsCloudVisualization/CircularCloudLayouter.cs +++ b/cs/TagsCloudVisualization/CircularCloudLayouter.cs @@ -17,9 +17,9 @@ public CircularCloudLayouter(Point center, IDistribution distribution) WordPositions = new List(); } - public Point Center { get; private set; } - public List WordPositions { get; private set; } - public IDistribution Distribution { get; private set; } + public Point Center { get; } + public List WordPositions { get; } + public IDistribution Distribution { get; } public Rectangle PutNextRectangle(Size rectangleSize) @@ -86,6 +86,5 @@ private Rectangle CompressByAxis(Rectangle rectangle, bool isByX, out int change return rectangle; } - } } \ No newline at end of file From b599e22238ee57d9930c4ea1acb8695aef99412e Mon Sep 17 00:00:00 2001 From: RenatZubakin Date: Mon, 11 Dec 2023 23:41:24 +0500 Subject: [PATCH 9/9] add more tests methods and refactoring --- .../CircularCloudLayouter | 81 ---------------- .../CircularCloudLayouter.cs | 6 +- .../CloudLayouterDrawer.cs | 40 ++++---- cs/TagsCloudVisualization/IDistribution.cs | 1 + .../SpiralDistribution.cs | 31 ++++--- .../TagsCloudVisualization.csproj | 3 + .../CircularCloudLayouterTests.cs | 92 +++++++++---------- .../CloudLayouterDrawerTests.cs | 53 ++++++----- .../SpiralDistributionTests.cs | 57 +++++++----- cs/TagsCloudVisualization/packages.config | 1 + 10 files changed, 156 insertions(+), 209 deletions(-) delete mode 100644 cs/TagsCloudVisualization/CircularCloudLayouter diff --git a/cs/TagsCloudVisualization/CircularCloudLayouter b/cs/TagsCloudVisualization/CircularCloudLayouter deleted file mode 100644 index 136ad191d..000000000 --- a/cs/TagsCloudVisualization/CircularCloudLayouter +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using static NUnit.Framework.Constraints.Tolerance; - -namespace TagsCloudVisualization -{ - public class TagsCloudVisualization - { - public Point Center; - public List WordPositions; - public double Radius; - public double Angle; - - public TagsCloudVisualization(Point center) - { - Center = center; - Radius = 0; - Angle = 0; - WordPositions = new List(); - } - - public Rectangle PutNextRectangle(Size rectangleSize) - { - while (true) - { - if (rectangleSize.Width < 1 || rectangleSize.Height < 1) - throw new ArgumentException(); - - var x = Radius * Math.Cos(Angle) + Center.X; - var y = Radius * Math.Sin(Angle)+ Center.Y; - - var currRectangle = new Rectangle(new Point((int)x, (int)y), rectangleSize); - - if (!CheckIntersection(currRectangle)) - { - WordPositions.Add(currRectangle); - return currRectangle; - } - - Angle += 0.1; - - if (Angle >= Math.PI * 2) - { - Angle = 0; - Radius += 0.5; - } - } - } - - - public bool CheckIntersection(Rectangle currRectangle) - { - return WordPositions.Any(rec => - { - var isRecIntersect = Rectangle.Intersect(rec,currRectangle); - return !isRecIntersect.IsEmpty; - }); - } - - public void Drawing() - { - int w = 10000; - int h = 10000; - Bitmap bitmap = new Bitmap(w, h); - Graphics graphics = Graphics.FromImage(bitmap); - Brush brush = new SolidBrush(Color.Blue); - - // Рисование прямоугольников - foreach (var word in WordPositions) - { - var x = word.X + 5000; - var y = word.Y + 5000; - graphics.FillRectangle(brush, x,y,word.Width,word.Height); - } - - bitmap.Save("C:\\Users\\hellw\\Desktop\\output.png", System.Drawing.Imaging.ImageFormat.Png); - } - } -} \ No newline at end of file diff --git a/cs/TagsCloudVisualization/CircularCloudLayouter.cs b/cs/TagsCloudVisualization/CircularCloudLayouter.cs index dfb898a35..b65ea78b4 100644 --- a/cs/TagsCloudVisualization/CircularCloudLayouter.cs +++ b/cs/TagsCloudVisualization/CircularCloudLayouter.cs @@ -19,7 +19,7 @@ public CircularCloudLayouter(Point center, IDistribution distribution) public Point Center { get; } public List WordPositions { get; } - public IDistribution Distribution { get; } + public IDistribution Distribution { get; private set; } public Rectangle PutNextRectangle(Size rectangleSize) @@ -42,13 +42,13 @@ public Rectangle PutNextRectangle(Size rectangleSize) } - public bool CheckIntersection(Rectangle currRectangle) + private bool CheckIntersection(Rectangle currRectangle) { return WordPositions.Any(rec => currRectangle.IntersectsWith(rec)); } - public Rectangle ComperessRectangle(Rectangle rectangle) + private Rectangle ComperessRectangle(Rectangle rectangle) { var changes = 1; while (changes > 0) diff --git a/cs/TagsCloudVisualization/CloudLayouterDrawer.cs b/cs/TagsCloudVisualization/CloudLayouterDrawer.cs index b2391ef9a..164727634 100644 --- a/cs/TagsCloudVisualization/CloudLayouterDrawer.cs +++ b/cs/TagsCloudVisualization/CloudLayouterDrawer.cs @@ -9,60 +9,64 @@ namespace TagsCloudVisualization { public class CloudLayouterDrawer { - private Random random; - public int margin; - public int imageWidth; - public int imageHeight; + private readonly Random random; + public int Margin { get; private set; } + public CloudLayouterDrawer(int margin) { - this.margin= margin; + this.Margin = margin; random = new Random(); } public void DrawCloud(string filename, IEnumerable rectangles) { - if (!rectangles.Any()) + + if (!rectangles.Any() || string.IsNullOrEmpty(filename)) throw new ArgumentException(); - SetImageSize(rectangles); - var newRectanglesPositions = GetNewRectanglesPositions(rectangles); + int imageWidth,imageHeight; + SetImageSize(rectangles, out imageWidth, out imageHeight); + + var newRectanglesPositions = GetNewRectanglesPositions(rectangles,imageWidth,imageHeight); using (var bitmap = new Bitmap(imageWidth, imageHeight)) { using (var graphics = Graphics.FromImage(bitmap)) { - foreach (var rectangle in newRectanglesPositions) { var color = Color.FromArgb(random.Next(256), random.Next(256), random.Next(256)); var brush = new SolidBrush(color); graphics.FillRectangle(brush, rectangle); } - - var projectDirectory = Directory.GetParent(Environment.CurrentDirectory).Parent.FullName; - var filePath = Path.Combine(projectDirectory, "images", filename); - bitmap.Save(filePath, ImageFormat.Png); + SaveImageToFile(bitmap,filename); } } } - private void SetImageSize(IEnumerable rectangles) + + private void SaveImageToFile(Bitmap bitmap,string filename) + { + var projectDirectory = Directory.GetParent(Environment.CurrentDirectory).Parent.FullName; + var filePath = Path.Combine(projectDirectory, "images", filename); + bitmap.Save(filePath, ImageFormat.Png); + } + private void SetImageSize(IEnumerable rectangles,out int imageWidth,out int imageHeight) { var maxX = rectangles.Select(rec => rec.X + rec.Width / 2).Max(); var minX = rectangles.Select(rec => rec.X - rec.Width / 2).Min(); var maxY = rectangles.Select(rec => rec.Y + rec.Height / 2).Max(); var minY = rectangles.Select(rec => rec.Y - rec.Height / 2).Min(); - imageWidth = maxX - minX + margin; - imageHeight = maxY - minY + margin; + imageWidth = maxX - minX + Margin; + imageHeight = maxY - minY + Margin; } - private IEnumerable GetNewRectanglesPositions(IEnumerable rectangles) + private IEnumerable GetNewRectanglesPositions(IEnumerable rectangles,int imageWidth, int imageHeight) { return rectangles.Select(rec => new Rectangle(rec.X + imageWidth / 2, rec.Y + imageHeight / 2, rec.Width, rec.Height)); } - } } \ No newline at end of file diff --git a/cs/TagsCloudVisualization/IDistribution.cs b/cs/TagsCloudVisualization/IDistribution.cs index 0d372f0cf..27d82813a 100644 --- a/cs/TagsCloudVisualization/IDistribution.cs +++ b/cs/TagsCloudVisualization/IDistribution.cs @@ -6,5 +6,6 @@ public interface IDistribution { Point Center { get; } Point GetNextPoint(); + } } diff --git a/cs/TagsCloudVisualization/SpiralDistribution.cs b/cs/TagsCloudVisualization/SpiralDistribution.cs index 6abe07d64..96c269e20 100644 --- a/cs/TagsCloudVisualization/SpiralDistribution.cs +++ b/cs/TagsCloudVisualization/SpiralDistribution.cs @@ -1,39 +1,40 @@ using System; -using System.Collections.Generic; using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace TagsCloudVisualization { public class SpiralDistribution : IDistribution { - public Point Center { get; private set; } - public double Radius { get; private set; } - public double Angle { get; private set; } - - - public SpiralDistribution(Point center) + public SpiralDistribution(Point center = new Point(), double angleStep = 0.1, double radiusStep = 0.1) { + if (radiusStep <= 0 || angleStep == 0) throw new ArgumentException(); Center = center; Radius = 0; Angle = 0; + AngleStep = angleStep - 2 * Math.PI * (int)(angleStep / 2 * Math.PI); + RadiusStep = radiusStep; } + + public double Angle { get; private set; } + public double AngleStep { get; } + public double RadiusStep { get; } + public Point Center { get; } + public double Radius { get; private set; } + public Point GetNextPoint() { var x = Radius * Math.Cos(Angle) + Center.X; var y = Radius * Math.Sin(Angle) + Center.Y; - - Angle += 0.1; + + Angle += AngleStep; if (Angle >= Math.PI * 2) { - Angle = 0; - Radius += 0.1; + Angle -= 2 * Math.PI; + Radius += RadiusStep; } return new Point((int)x, (int)y); } } -} +} \ No newline at end of file diff --git a/cs/TagsCloudVisualization/TagsCloudVisualization.csproj b/cs/TagsCloudVisualization/TagsCloudVisualization.csproj index 6a72393b3..9071bff31 100644 --- a/cs/TagsCloudVisualization/TagsCloudVisualization.csproj +++ b/cs/TagsCloudVisualization/TagsCloudVisualization.csproj @@ -38,6 +38,9 @@ 4 + + ..\packages\FluentAssertions.5.10.3\lib\net47\FluentAssertions.dll + ..\packages\Microsoft.CodeCoverage.16.7.1\lib\net45\Microsoft.VisualStudio.CodeCoverage.Shim.dll diff --git a/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CircularCloudLayouterTests.cs b/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CircularCloudLayouterTests.cs index 90320669c..68d3b85b0 100644 --- a/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CircularCloudLayouterTests.cs +++ b/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CircularCloudLayouterTests.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Drawing; +using System.Linq; +using FluentAssertions; using NUnit.Framework; using NUnit.Framework.Interfaces; @@ -9,11 +11,6 @@ namespace TagsCloudVisualization [TestFixture] public class CircularCloudLayouterTests { - private Point center; - private CircularCloudLayouter tagsCloud; - private SpiralDistribution distribution; - private CloudLayouterDrawer drawer; - [SetUp] public void SetUp() { @@ -23,23 +20,28 @@ public void SetUp() drawer = new CloudLayouterDrawer(10); } - [TearDown] + [TearDown] public void TearDown() { if (TestContext.CurrentContext.Result.Outcome.Status == TestStatus.Failed) { - var fileName =$"{TestContext.CurrentContext.Test.FullName}.png"; + var fileName = $"{TestContext.CurrentContext.Test.FullName}.png"; drawer.DrawCloud(fileName, tagsCloud.WordPositions); Console.WriteLine($"Tag cloud visualization saved to file /images/{fileName}"); } } - + + private Point center; + private CircularCloudLayouter tagsCloud; + private SpiralDistribution distribution; + private CloudLayouterDrawer drawer; + [Test] public void CircularCloudLayouter_Initialize_Params() { - Assert.AreEqual(0, tagsCloud.WordPositions.Count); - Assert.AreEqual(center, tagsCloud.Center); - Assert.AreEqual(distribution, tagsCloud.Distribution); + tagsCloud.WordPositions.Count.Should().Be(0); + tagsCloud.Center.Should().Be(center); + tagsCloud.Distribution.Should().Be(distribution); } [Test] @@ -62,20 +64,28 @@ public void PutNextRectangle_ThrowsArgumentException_WhenIncorrectArguments(Size public void PutNextRectangle_Should_Place_First_On_Center() { tagsCloud.PutNextRectangle(new Size(3, 1)); - Assert.AreEqual(tagsCloud.Center, tagsCloud.WordPositions[0].Location); + tagsCloud.WordPositions[0].Location.Should().Be(tagsCloud.Center); } - [TestCaseSource(nameof(CheckIntersectionCaseData))] - public bool CheckIntersectionTest(Size rectangleSize, Rectangle rectangle) + [Test] + public void CircularCloudLayouter_Should_Has_No_Intersections_When_1000_Rectangles() { - tagsCloud.PutNextRectangle(rectangleSize); - return tagsCloud.CheckIntersection(rectangle); + getRandomTagsCloud().WordPositions.Any(tag1 => + tagsCloud.WordPositions.Any(tag2 => tag1.IntersectsWith(tag2) && tag1 != tag2)) + .Should().BeFalse(); } - [TestCaseSource(nameof(RectangleCompressionCaseData))] - public Point RectangleCompression(CircularCloudLayouter cloud, Rectangle rectangle) + + [Test] + public void CircularCloudLayouter_Should_Be_Close_To_Circle() { - return cloud.ComperessRectangle(rectangle).Location; + var randomTagsCloud = getRandomTagsCloud(); + randomTagsCloud.WordPositions.All(tag => + { + var distanceToCenter = + Math.Sqrt(Math.Pow(tag.X - tagsCloud.Center.X, 2) + Math.Pow(tag.Y - tagsCloud.Center.Y, 2)); + return distanceToCenter <= GetCircilarCloudLayouterRadius(randomTagsCloud); + }).Should().BeTrue(); } @@ -98,41 +108,23 @@ private static IEnumerable PutNextRectangleIncorrectArguments() .SetName("PutNextReactangle_Throws_ArgumentException_When_Height_Is_Zero"); } - private static IEnumerable CheckIntersectionCaseData() + + private CircularCloudLayouter getRandomTagsCloud() { - yield return new TestCaseData(new Size(4, 2), new Rectangle(new Point(1, 1), new Size(2, 2))) - .SetName( - "CheckIntersection_Return_True_When_Rectangle_Intersection_With_Any_Rectangle_In_CircularCloudLayouter") - .Returns(true); - - yield return new TestCaseData(new Size(1, 1), new Rectangle(new Point(1, 0), new Size(1, 1))) - .SetName( - "CheckIntersection_Return_False_When_Rectangle_Have_Common_Side_With_Another_Rectangle") - .Returns(false); - - yield return new TestCaseData(new Size(4, 2), new Rectangle(new Point(4, 4), new Size(2, 2))) - .SetName( - "CheckIntersection_Return_True_When_Rectangle_Intersection_With_Any_Rectangle_In_CircularCloudLayouter") - .Returns(false); + var randomTagCloud = new CircularCloudLayouter(center, distribution); + var random = new Random(); + for (var i = 0; i < 1000; i++) + { + var size = new Size(random.Next(1, 100), random.Next(1, 100)); + randomTagCloud.PutNextRectangle(size); + } + + return randomTagCloud; } - private static IEnumerable RectangleCompressionCaseData() + public static double GetCircilarCloudLayouterRadius(CircularCloudLayouter layouter) { - var center = new Point(); - var distributionEmpty = new SpiralDistribution(center); - var cloudEmpty = new CircularCloudLayouter(center, distributionEmpty); - var distributionWithElements = new SpiralDistribution(center); - var cloudWithElements = new CircularCloudLayouter(center, distributionWithElements); - cloudWithElements.PutNextRectangle(new Size(1, 1)); - var rectangle = new Rectangle(new Point(5, 5), new Size(1, 1)); - - yield return new TestCaseData(cloudEmpty, rectangle) - .SetName("RectangleCompression_When_Cloud_Is_Empty_Set_Rectangle_Position_On_Center") - .Returns(cloudEmpty.Center); - - yield return new TestCaseData(cloudWithElements, rectangle) - .SetName("RectangleCompression_When_Cloud_Has_Rectangles_Set_Rectangle_Position_Closer_To_Center") - .Returns(new Point(0, 1)); + return layouter.WordPositions.Max(tag => Math.Sqrt(Math.Pow(tag.X, 2) + Math.Pow(tag.Y, 2))); } } } \ No newline at end of file diff --git a/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CloudLayouterDrawerTests.cs b/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CloudLayouterDrawerTests.cs index 1f7ec5c0d..efe29bca9 100644 --- a/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CloudLayouterDrawerTests.cs +++ b/cs/TagsCloudVisualization/TagsCloudVisualizationTests/CloudLayouterDrawerTests.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.Drawing; using System.IO; +using FluentAssertions; using NUnit.Framework; namespace TagsCloudVisualization.TagsCloudVisualizationTests @@ -8,44 +10,53 @@ namespace TagsCloudVisualization.TagsCloudVisualizationTests [TestFixture] public class CloudLayouterDrawerTests { - private CloudLayouterDrawer drawer; - private string fileName; - private string TestFilePath; - - [SetUp] public void SetUp() { drawer = new CloudLayouterDrawer(10); - fileName = "testcreation.png"; var projectDirectory = Directory.GetParent(Environment.CurrentDirectory).Parent.FullName; - TestFilePath = Path.Combine(projectDirectory, "images", fileName); - if (File.Exists(TestFilePath)) - { - File.Delete(TestFilePath); - } + testFilePath = Path.Combine(projectDirectory, "images", fileName); + if (File.Exists(testFilePath)) File.Delete(testFilePath); } [TearDown] public void TearDown() { - if (File.Exists(TestFilePath)) - { - File.Delete(TestFilePath); - } + if (File.Exists(testFilePath)) File.Delete(testFilePath); } + + private CloudLayouterDrawer drawer; + private const string fileName = "testcreation.png"; + private string testFilePath; + [Test] public void CloudLayouterDrawer_Initialize_Params() { - Assert.AreEqual(10,drawer.margin); + drawer.Margin.Should().Be(10); + } + + [Test] + public void CloudLayouterDrawer_Initialize_Throws_ArgumentException_When_Rectangles_length_Is_Zero() + { + var rectangles = new List(); + Assert.Throws(()=>drawer.DrawCloud("output.png",rectangles)); + } + + [TestCase("",TestName = "When_Filename_Is_Empty")] + [TestCase(null, TestName = "When_Filename_Is_Null")] + + public void CloudLayouterDrawer_Initialize_Throws_ArgumentException(string filename) + { + var rectangles = new List(){new Rectangle(1,1,1,1)}; + Assert.Throws(() => drawer.DrawCloud(filename, rectangles)); } [Test] - public void CloudLayouterDrawer_IsCreate_Imgae() + public void CloudLayouterDrawer_IsCreate_Image() { - var rectanglesCollection = new Rectangle[] { new Rectangle(0, 0, 5, 10) }; - drawer.DrawCloud(fileName,rectanglesCollection); - Assert.IsTrue(File.Exists(TestFilePath), $"File at path '{TestFilePath}' should have been created."); + var rectanglesCollection = new[] { new Rectangle(0, 0, 5, 10) }; + drawer.DrawCloud(fileName, rectanglesCollection); + File.Exists(testFilePath).Should().BeTrue(); } } -} +} \ No newline at end of file diff --git a/cs/TagsCloudVisualization/TagsCloudVisualizationTests/SpiralDistributionTests.cs b/cs/TagsCloudVisualization/TagsCloudVisualizationTests/SpiralDistributionTests.cs index 5277a553a..fcc5ecb78 100644 --- a/cs/TagsCloudVisualization/TagsCloudVisualizationTests/SpiralDistributionTests.cs +++ b/cs/TagsCloudVisualization/TagsCloudVisualizationTests/SpiralDistributionTests.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using FluentAssertions; using NUnit.Framework; namespace TagsCloudVisualization.TagsCloudVisualizationTests @@ -11,47 +8,65 @@ namespace TagsCloudVisualization.TagsCloudVisualizationTests [TestFixture] public class SpiralDistributionTests { - private Point center; - private SpiralDistribution spiralDistribution; - [SetUp] public void SetUp() { center = new Point(); - spiralDistribution = new SpiralDistribution(center); + spiralDistribution = new SpiralDistribution(); } + private Point center; + private SpiralDistribution spiralDistribution; + + + [Test] + public void SprialDistribution_Initialize__Default_Params() + { + spiralDistribution.Center.Should().Be(center); + spiralDistribution.Angle.Should().Be(0); + spiralDistribution.Radius.Should().Be(0); + spiralDistribution.AngleStep.Should().Be(0.1); + spiralDistribution.RadiusStep.Should().Be(0.1); + } [Test] - public void SprialDistribution_Initialize_Params() + public void SprialDistribution_Initialize__Custom_Params() + { + var customCenter = new Point(1, 1); + var customSpiralDistribution = new SpiralDistribution(customCenter,0.6, 0.7); + + customSpiralDistribution.Center.Should().Be(customCenter); + customSpiralDistribution.AngleStep.Should().Be(0.6); + customSpiralDistribution.RadiusStep.Should().Be(0.7); + } + + [TestCase(0,1, TestName = "When_AngleStep_Is_Zero")] + [TestCase(0.6, -1, TestName = "When_Radius_Is_Negative")] + [TestCase(0.6, 0, TestName = "When_Radius_Is_Zero")] + public void SpiralDistribution_Initialize_Throw_ArgumentException(double angleStep,double radiusStep) { - Assert.AreEqual(center, spiralDistribution.Center); - Assert.AreEqual(0, spiralDistribution.Angle); - Assert.AreEqual(0, spiralDistribution.Radius); + Assert.Throws(()=> new SpiralDistribution(center, angleStep, radiusStep)); } [Test] public void SpiralDistribution_First_Call_GetNextPoint_Should_Return_Center() { - Assert.AreEqual(center, spiralDistribution.GetNextPoint()); + spiralDistribution.GetNextPoint().Should().Be(center); } [Test] public void SpiralDistribution_Should_Increase_Angle_After_Call_GetNextPoint() { spiralDistribution.GetNextPoint(); - Assert.AreEqual(0.1, spiralDistribution.Angle); + spiralDistribution.Angle.Should().Be(spiralDistribution.AngleStep); } [Test] - public void SpiralDistribution_Should_Increase_Radius_And_Reset_Angle_When_Angle_More_Than_2Pi() + public void SpiralDistribution_Should_Increase_Radius_When_Angle_More_Than_2Pi() { - for (int i = 0; i < 63; i++) - { - spiralDistribution.GetNextPoint(); - } - Assert.AreEqual(0,spiralDistribution.Angle); - Assert.AreEqual(0.1,spiralDistribution.Radius); + var expectedAngle = spiralDistribution.Angle * 64 - 2 * Math.PI; + for (var i = 0; i < 63; i++) spiralDistribution.GetNextPoint(); + spiralDistribution.Radius.Should().Be(spiralDistribution.Radius); } } } \ No newline at end of file diff --git a/cs/TagsCloudVisualization/packages.config b/cs/TagsCloudVisualization/packages.config index a2bd3e845..1f1658b24 100644 --- a/cs/TagsCloudVisualization/packages.config +++ b/cs/TagsCloudVisualization/packages.config @@ -1,5 +1,6 @@  +