diff --git a/TagCloudVisualizationTests/CircularCloudLayouterTests.cs b/TagCloudVisualizationTests/CircularCloudLayouterTests.cs new file mode 100644 index 000000000..2e36ecf2f --- /dev/null +++ b/TagCloudVisualizationTests/CircularCloudLayouterTests.cs @@ -0,0 +1,145 @@ +using NUnit.Framework.Interfaces; +using FluentAssertions; +using System.Drawing; +using TagsCloudVisualization.CloudLayouter; +using TagsCloudVisualization.Visualizers; +using NUnit.Framework; + +namespace TagsCloudVisualization.Tests.CircularCloudLayouterTests; + +[TestFixture, NonParallelizable] +public class CircularCloudLayouterTests +{ + private CircularCloudLayouter cloudLayouter; + private const int imageWidth = 1500; + private const int imageHeight = 1500; + + [SetUp] + public void Init() + { + var center = new Point(imageWidth / 2, imageHeight / 2); + cloudLayouter = new CircularCloudLayouter(center); + cloudLayouter.GenerateCloud(100); + } + + [TearDown] + public void TearDown() + { + if (TestContext.CurrentContext.Result.Outcome.Status != TestStatus.Failed) + return; + var directory = "FailedVisualisations"; + var path = Path.Combine(directory, $"{TestContext.CurrentContext.Test.Name}_visualisation.png"); + var visuliser = new ImageCreator(); + visuliser.CreateBitmap(cloudLayouter.GeneratedRectangles, new(imageWidth, imageHeight), path); + Console.WriteLine($"Tag cloud visualization saved to file {path}"); + } + + [TestCase(0, 1, TestName = "WhenWidthIsZero")] + [TestCase(1, 0, TestName = "WhenHeightIsZero")] + [TestCase(-1, 1, TestName = "WhenWidthIsNegative")] + [TestCase(1, -1, TestName = "WhenHeightIsNegative")] + public void PutNextRectangle_ShouldThrowArgumentException(int width, int height) + { + var size = new Size(width, height); + + var action = () => cloudLayouter.PutNextRectangle(size); + + action.Should().Throw(); + } + + [Test] + public void PutNextRectangle_FirstRectangle_ShouldBeInCenter() + { + cloudLayouter = new CircularCloudLayouter(cloudLayouter.Center); + var rectangleSize = new Size(10, 10); + var expectedRectangle = new Rectangle( + cloudLayouter.Center.X - rectangleSize.Width / 2, + cloudLayouter.Center.Y - rectangleSize.Height / 2, + rectangleSize.Width, + rectangleSize.Height + ); + + var actualRectangle = cloudLayouter.PutNextRectangle(rectangleSize); + + actualRectangle.Should().BeEquivalentTo(expectedRectangle); + } + + [Test, Parallelizable(ParallelScope.Self)] + [Repeat(10)] + public void PutNextRectangle_Rectangles_ShouldNotHaveIntersects() => + AreRectanglesHaveIntersects(cloudLayouter.GeneratedRectangles).Should().BeFalse(); + + [Test] + [Repeat(10)] + public void PutNextRectangle_CloudCenterMust_ShouldBeInLayoterCenter() + { + var maxRectangleSize = 10; + var expectedDiscrepancy = maxRectangleSize; + var minRectangleSize = 1; + var center = cloudLayouter.Center; + + cloudLayouter.GenerateCloud(100, minRectangleSize, maxRectangleSize); + + var actualCenter = GetCenterOfAllRectangles(cloudLayouter.GeneratedRectangles); + actualCenter.X.Should().BeInRange(center.X - expectedDiscrepancy, center.X + expectedDiscrepancy); + actualCenter.Y.Should().BeInRange(center.Y - expectedDiscrepancy, center.Y + expectedDiscrepancy); + } + + [Test] + [Repeat(10)] + public void PutNextRectangle_RectanglesDensity_ShouldBeMax() + { + var expectedDensity = 0.45; + var center = cloudLayouter.Center; + var rectangles = cloudLayouter.GeneratedRectangles; + + var rectanglesArea = rectangles.Sum(rect => rect.Width * rect.Height); + + var radius = GetMaxDistanceBetweenRectangleAndCenter(rectangles); + var circleArea = Math.PI * radius * radius; + var density = rectanglesArea / circleArea; + density.Should().BeGreaterThanOrEqualTo(expectedDensity); + } + + private Point GetCenterOfAllRectangles(List rectangles) + { + var top = rectangles.Max(r => r.Top); + var right = rectangles.Max(r => r.Right); + var bottom = rectangles.Min(r => r.Bottom); + var left = rectangles.Min(r => r.Left); + var x = left + (right - left) / 2; + var y = bottom + (top - bottom) / 2; + return new(x, y); + } + + private double GetMaxDistanceBetweenRectangleAndCenter(List rectangles) + { + var center = GetCenterOfAllRectangles(rectangles); + double maxDistance = -1; + foreach (var rectangle in rectangles) + { + var corners = new Point[4] + { + new(rectangle.Top, rectangle.Left), + new(rectangle.Bottom, rectangle.Left), + new(rectangle.Top, rectangle.Right), + new(rectangle.Bottom, rectangle.Right) + }; + var distance = corners.Max(p => GetDistanceBetweenPoints(p, center)); + maxDistance = Math.Max(maxDistance, distance); + } + return maxDistance; + } + + private static bool AreRectanglesHaveIntersects(List rectangles) + { + for (var i = 0; i < rectangles.Count; i++) + for (var j = i + 1; j < rectangles.Count; j++) + if (rectangles[i].IntersectsWith(rectangles[j])) + return true; + return false; + } + + private static double GetDistanceBetweenPoints(Point point1, Point point2) + => Math.Sqrt(Math.Pow(point1.X - point2.X, 2) + Math.Pow(point1.Y - point2.Y, 2)); +} \ No newline at end of file diff --git a/TagCloudVisualizationTests/SpiralPointsGeneratorTests.cs b/TagCloudVisualizationTests/SpiralPointsGeneratorTests.cs new file mode 100644 index 000000000..bb9ef0565 --- /dev/null +++ b/TagCloudVisualizationTests/SpiralPointsGeneratorTests.cs @@ -0,0 +1,43 @@ +using FluentAssertions; +using System.Drawing; +using TagsCloudVisualization.PointsGenerators; +using NUnit.Framework; + +namespace TagsCloudVisualization.Tests.SpiralPointsGeneratorTests; + +[TestFixture, Parallelizable(ParallelScope.All)] +public class SpiralPointsGeneratorTests +{ + [TestCase(0, 1, TestName = "WhenStepIsZero")] + [TestCase(1, 0, TestName = "WhenAngleOffsetIsZero")] + public void Constructor_ShouldThrowArgumentException(double step, double angleOffset) + { + var act = () => new SpiralPointsGenerator(new Point(0, 0), step, angleOffset); + + act.Should().Throw(); + } + + [TestCaseSource(nameof(GeneratePointsTestCases))] + public void GetNextPointPosition_ShouldReturnCorrectPoint(double step, double angleOffset, int pointNumber, Point expectedPoint) + { + var pointsGenerator = new SpiralPointsGenerator(new Point(0, 0), step, angleOffset); + + var actualPoint = pointsGenerator.GetNextPointPosition(); + for (var i = 0; i < pointNumber - 1; i++) + actualPoint = pointsGenerator.GetNextPointPosition(); + + actualPoint.Should().Be(expectedPoint); + } + + public static TestCaseData[] GeneratePointsTestCases = + { + new TestCaseData(0.1, 0.1, 1, new Point(0, 0)), + new TestCaseData(1, 1, 1, new Point(0, 0)), + new TestCaseData(1, 1, 3, new Point(0, 1)), + new TestCaseData(1, 1, 5, new Point(-2, -3)), + new TestCaseData(3, 1, 3, new Point(-2, 5)), + new TestCaseData(3, 1, 5, new Point(-7, -9)), + new TestCaseData(5, 1, 3, new Point(-4, 9)), + new TestCaseData(5, 1, 5, new Point(-13, -15)), + }; +} \ No newline at end of file diff --git a/TagCloudVisualizationTests/TagCloudVisualizationTests.csproj b/TagCloudVisualizationTests/TagCloudVisualizationTests.csproj new file mode 100644 index 000000000..5cbc76ea4 --- /dev/null +++ b/TagCloudVisualizationTests/TagCloudVisualizationTests.csproj @@ -0,0 +1,34 @@ + + + + net8.0 + enable + enable + + false + true + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + diff --git a/TagCloudVisualizationTests/TagCloudVisualizationTests.sln b/TagCloudVisualizationTests/TagCloudVisualizationTests.sln new file mode 100644 index 000000000..98b7dbf5a --- /dev/null +++ b/TagCloudVisualizationTests/TagCloudVisualizationTests.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.11.35327.3 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TagsCloudVisualization", "..\TagsCloudVisualization\TagsCloudVisualization.csproj", "{F131A5F9-48B5-465B-B9CB-CD459DE76A8E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TagCloudVisualizationTests", "TagCloudVisualizationTests.csproj", "{312FED20-0051-4DD3-B787-4601BE046411}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F131A5F9-48B5-465B-B9CB-CD459DE76A8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F131A5F9-48B5-465B-B9CB-CD459DE76A8E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F131A5F9-48B5-465B-B9CB-CD459DE76A8E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F131A5F9-48B5-465B-B9CB-CD459DE76A8E}.Release|Any CPU.Build.0 = Release|Any CPU + {312FED20-0051-4DD3-B787-4601BE046411}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {312FED20-0051-4DD3-B787-4601BE046411}.Debug|Any CPU.Build.0 = Debug|Any CPU + {312FED20-0051-4DD3-B787-4601BE046411}.Release|Any CPU.ActiveCfg = Release|Any CPU + {312FED20-0051-4DD3-B787-4601BE046411}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {24AAD118-F9C5-4FA5-B5F6-2A75C584C1D1} + EndGlobalSection +EndGlobal diff --git a/TagsCloudVisualization/CloudLayouter/CircularCloudLayouter.cs b/TagsCloudVisualization/CloudLayouter/CircularCloudLayouter.cs new file mode 100644 index 000000000..1f0988616 --- /dev/null +++ b/TagsCloudVisualization/CloudLayouter/CircularCloudLayouter.cs @@ -0,0 +1,50 @@ +using System.Drawing; +using TagsCloudVisualization.CloudLayouter.PointsGenerators; +using TagsCloudVisualization.PointsGenerators; + +namespace TagsCloudVisualization.CloudLayouter; + +public class CircularCloudLayouter : ICircularCloudLayouter +{ + public Point Center { get; } + public List GeneratedRectangles { get; } + private readonly IPointsGenerator spiral; + + public CircularCloudLayouter(Point center) + { + Center = center; + GeneratedRectangles = new List(); + spiral = new SpiralPointsGenerator(center); + } + + public CircularCloudLayouter(Point center, int step, int angleOffset) : this(center) + { + spiral = new SpiralPointsGenerator(center, step, angleOffset); + } + + public Rectangle PutNextRectangle(Size rectangleSize) + { + if (rectangleSize.Width <= 0 || rectangleSize.Height <= 0) + throw new ArgumentException($"{nameof(rectangleSize)} height and width must be greater than zero"); + Rectangle rectangle; + do + { + rectangle = GetNextRectangle(rectangleSize); + } while (GeneratedRectangles.Any(rectangle.IntersectsWith)); + GeneratedRectangles.Add(rectangle); + return rectangle; + } + + private Rectangle GetNextRectangle(Size rectangleSize) + { + var rectanglePosition = spiral.GetNextPointPosition(); + return CreateRectangle(rectanglePosition, rectangleSize); + } + + private static Rectangle CreateRectangle(Point center, Size rectangleSize) + { + var x = center.X - rectangleSize.Width / 2; + var y = center.Y - rectangleSize.Height / 2; + return new Rectangle(x, y, rectangleSize.Width, rectangleSize.Height); + } +} \ No newline at end of file diff --git a/TagsCloudVisualization/CloudLayouter/ICircularCloudLayouter.cs b/TagsCloudVisualization/CloudLayouter/ICircularCloudLayouter.cs new file mode 100644 index 000000000..6289e0961 --- /dev/null +++ b/TagsCloudVisualization/CloudLayouter/ICircularCloudLayouter.cs @@ -0,0 +1,8 @@ +using System.Drawing; + +namespace TagsCloudVisualization.CloudLayouter; + +public interface ICircularCloudLayouter +{ + Rectangle PutNextRectangle(Size rectangleSize); +} \ No newline at end of file diff --git a/TagsCloudVisualization/CloudLayouter/ICircularCloudLayouterExtensions.cs b/TagsCloudVisualization/CloudLayouter/ICircularCloudLayouterExtensions.cs new file mode 100644 index 000000000..1deb2567e --- /dev/null +++ b/TagsCloudVisualization/CloudLayouter/ICircularCloudLayouterExtensions.cs @@ -0,0 +1,21 @@ +using System.Drawing; + +namespace TagsCloudVisualization.CloudLayouter; + +public static class ICircularCloudLayouterExtensions +{ + public static void GenerateCloud( + this ICircularCloudLayouter cloudLayouter, + int rectanglesNumber = 1000, + int minRectangleSize = 10, + int maxRectangleSize = 50) + { + var random = new Random(); + new Rectangle[rectanglesNumber] + .Select(x => new Size( + random.Next(minRectangleSize, maxRectangleSize), + random.Next(minRectangleSize, maxRectangleSize))) + .Select(size => cloudLayouter.PutNextRectangle(size)) + .ToArray(); + } +} \ No newline at end of file diff --git a/TagsCloudVisualization/CloudLayouter/PointsGenerators/IPointsGenerator.cs b/TagsCloudVisualization/CloudLayouter/PointsGenerators/IPointsGenerator.cs new file mode 100644 index 000000000..75dcdb9dd --- /dev/null +++ b/TagsCloudVisualization/CloudLayouter/PointsGenerators/IPointsGenerator.cs @@ -0,0 +1,8 @@ +using System.Drawing; + +namespace TagsCloudVisualization.CloudLayouter.PointsGenerators; + +public interface IPointsGenerator +{ + Point GetNextPointPosition(); +} diff --git a/TagsCloudVisualization/CloudLayouter/PointsGenerators/SpiralPointsGenerator.cs b/TagsCloudVisualization/CloudLayouter/PointsGenerators/SpiralPointsGenerator.cs new file mode 100644 index 000000000..66615aa12 --- /dev/null +++ b/TagsCloudVisualization/CloudLayouter/PointsGenerators/SpiralPointsGenerator.cs @@ -0,0 +1,29 @@ +using System.Drawing; + +namespace TagsCloudVisualization.CloudLayouter.PointsGenerators; + +public class SpiralPointsGenerator : IPointsGenerator +{ + private readonly double step; + private readonly double angleOffset; + private readonly Point center; + private double currentAngle = 0; + + public SpiralPointsGenerator(Point center, double step = 0.1, double angleOffset = 0.1) + { + if (step == 0 || angleOffset == 0) + throw new ArgumentException($"Step and angleOffset must not be zero"); + this.center = center; + this.step = step; + this.angleOffset = angleOffset; + } + + public Point GetNextPointPosition() + { + var radius = step * currentAngle; + var x = (int)(center.X + radius * Math.Cos(currentAngle)); + var y = (int)(center.Y + radius * Math.Sin(currentAngle)); + currentAngle += angleOffset; + return new(x, y); + } +} \ No newline at end of file diff --git a/TagsCloudVisualization/ConsoleClient.cs b/TagsCloudVisualization/ConsoleClient.cs new file mode 100644 index 000000000..894750ded --- /dev/null +++ b/TagsCloudVisualization/ConsoleClient.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TagsCloudVisualization +{ + internal class ConsoleClient + { + } +} diff --git a/TagsCloudVisualization/FileReaders/Filters/BoringWordsFilter.cs b/TagsCloudVisualization/FileReaders/Filters/BoringWordsFilter.cs new file mode 100644 index 000000000..ba86b8e0a --- /dev/null +++ b/TagsCloudVisualization/FileReaders/Filters/BoringWordsFilter.cs @@ -0,0 +1,10 @@ + +namespace TagsCloudVisualization.FileReaders.Filters; + +public class BoringWordsFilter : IFilter +{ + public List FilterText(List text) + { + throw new NotImplementedException(); + } +} diff --git a/TagsCloudVisualization/FileReaders/Filters/IFilter.cs b/TagsCloudVisualization/FileReaders/Filters/IFilter.cs new file mode 100644 index 000000000..6631a4f6b --- /dev/null +++ b/TagsCloudVisualization/FileReaders/Filters/IFilter.cs @@ -0,0 +1,6 @@ +namespace TagsCloudVisualization.FileReaders.Filters; + +public interface IFilter +{ + public List FilterText(List text); +} diff --git a/TagsCloudVisualization/FileReaders/Filters/LowercaseFilter.cs b/TagsCloudVisualization/FileReaders/Filters/LowercaseFilter.cs new file mode 100644 index 000000000..af3b9f38e --- /dev/null +++ b/TagsCloudVisualization/FileReaders/Filters/LowercaseFilter.cs @@ -0,0 +1,10 @@ + +namespace TagsCloudVisualization.FileReaders.Filters; + +public class LowercaseFilter : IFilter +{ + public List FilterText(List text) + { + throw new NotImplementedException(); + } +} diff --git a/TagsCloudVisualization/FileReaders/IFileReader.cs b/TagsCloudVisualization/FileReaders/IFileReader.cs new file mode 100644 index 000000000..28b7ff38d --- /dev/null +++ b/TagsCloudVisualization/FileReaders/IFileReader.cs @@ -0,0 +1,6 @@ +namespace TagsCloudVisualization.FileReaders; + +public interface IFileReader +{ + public List ReadLines(string path); +} diff --git a/TagsCloudVisualization/FileReaders/TxtFileReader.cs b/TagsCloudVisualization/FileReaders/TxtFileReader.cs new file mode 100644 index 000000000..c4d6a8858 --- /dev/null +++ b/TagsCloudVisualization/FileReaders/TxtFileReader.cs @@ -0,0 +1,10 @@ + +namespace TagsCloudVisualization.FileReaders; + +public class TxtFileReader : IFileReader +{ + public List ReadLines(string path) + { + throw new NotImplementedException(); + } +} diff --git a/TagsCloudVisualization/Program.cs b/TagsCloudVisualization/Program.cs new file mode 100644 index 000000000..a09764387 --- /dev/null +++ b/TagsCloudVisualization/Program.cs @@ -0,0 +1,22 @@ +using System.Drawing; +using TagsCloudVisualization.Visualizers; +using TagsCloudVisualization.CloudLayouter; + +namespace TagsCloudVisualization; + +public static class Program +{ + private const int imageWidth = 1500; + private const int imageHeight = 1500; + + public static void Main() + { + var imageSize = new Size(imageWidth, imageHeight); + var center = new Point(imageSize.Width / 2, imageSize.Height / 2); + var layouter = new CircularCloudLayouter(center); + layouter.GenerateCloud(); + var rectangles = layouter.GeneratedRectangles; + var visualizer = new ImageCreator(); + visualizer.CreateBitmap(rectangles, imageSize); + } +} \ No newline at end of file diff --git a/TagsCloudVisualization/Settings/ConsoleClientSettings.cs b/TagsCloudVisualization/Settings/ConsoleClientSettings.cs new file mode 100644 index 000000000..09edc3cb6 --- /dev/null +++ b/TagsCloudVisualization/Settings/ConsoleClientSettings.cs @@ -0,0 +1,5 @@ +namespace TagsCloudVisualization.Settings; + +public class ConsoleClientSettings +{ +} diff --git a/TagsCloudVisualization/Settings/ImageColoringSettings.cs b/TagsCloudVisualization/Settings/ImageColoringSettings.cs new file mode 100644 index 000000000..4228d0e68 --- /dev/null +++ b/TagsCloudVisualization/Settings/ImageColoringSettings.cs @@ -0,0 +1,6 @@ +using System.Drawing; +using TagsCloudVisualization.Visualizers.ImageColoring; + +namespace TagsCloudVisualization.Settings; + +public record ImageSettings(Size Size, IImageColoring Coloring); diff --git a/TagsCloudVisualization/Settings/TextReaderSettings.cs b/TagsCloudVisualization/Settings/TextReaderSettings.cs new file mode 100644 index 000000000..49787a170 --- /dev/null +++ b/TagsCloudVisualization/Settings/TextReaderSettings.cs @@ -0,0 +1,4 @@ +namespace TagsCloudVisualization.Settings; +public class TextReaderSettings +{ +} diff --git a/TagsCloudVisualization/TagsCloudVisualization.csproj b/TagsCloudVisualization/TagsCloudVisualization.csproj new file mode 100644 index 000000000..56ddd599d --- /dev/null +++ b/TagsCloudVisualization/TagsCloudVisualization.csproj @@ -0,0 +1,20 @@ + + + + Exe + net8.0 + enable + enable + + TagsCloudVisualization.Program + + + + + + + + + + + diff --git a/TagsCloudVisualization/Visualizers/ImageColoring/IImageColoring.cs b/TagsCloudVisualization/Visualizers/ImageColoring/IImageColoring.cs new file mode 100644 index 000000000..7a7654473 --- /dev/null +++ b/TagsCloudVisualization/Visualizers/ImageColoring/IImageColoring.cs @@ -0,0 +1,8 @@ +using System.Drawing; + +namespace TagsCloudVisualization.Visualizers.ImageColoring; + +public interface IImageColoring +{ + public Color GetNextColor(); +} diff --git a/TagsCloudVisualization/Visualizers/ImageCreator.cs b/TagsCloudVisualization/Visualizers/ImageCreator.cs new file mode 100644 index 000000000..308e9ce9f --- /dev/null +++ b/TagsCloudVisualization/Visualizers/ImageCreator.cs @@ -0,0 +1,42 @@ +using System.Drawing; +using System.Drawing.Imaging; + +namespace TagsCloudVisualization.Visualizers; + +public class ImageCreator +{ + private const string imagesDirectory = "images"; + + public void CreateBitmap( + IEnumerable rectangles, + Size bitmapSize, + string path = null + ) + { + var bitmap = new Bitmap(bitmapSize.Width, bitmapSize.Height); + using (var graphics = Graphics.FromImage(bitmap)) + { + graphics.Clear(Color.White); + foreach (var rectangle in rectangles) + { + var pen = new Pen(GetRandomColor()); + graphics.DrawRectangle(pen, rectangle); + } + var currentPath = path == null ? GetPathToImages(rectangles.Count()) : path; + Directory.CreateDirectory(Path.GetDirectoryName(currentPath)); + bitmap.Save((string)currentPath, ImageFormat.Jpeg); + } + } + + private static Color GetRandomColor() + { + var random = new Random(); + return Color.FromArgb(random.Next(0, 255), random.Next(0, 255), random.Next(0, 255)); + } + + private static string GetPathToImages(int rectanglesNumber) + { + var filename = $"{rectanglesNumber}_TagCloud.jpg"; + return Path.Combine(imagesDirectory, filename); + } +} \ No newline at end of file diff --git a/TagsCloudVisualization/Visualizers/ImageSaver.cs b/TagsCloudVisualization/Visualizers/ImageSaver.cs new file mode 100644 index 000000000..5affc3a12 --- /dev/null +++ b/TagsCloudVisualization/Visualizers/ImageSaver.cs @@ -0,0 +1,11 @@ +using System.Drawing; + +namespace TagsCloudVisualization.Visualizers; + +public class ImageSaver +{ + public void SaveImage(Bitmap bitmapm, string format, string path) + { + throw new NotImplementedException(); + } +} diff --git a/di.sln b/di.sln index b27b7c05d..161c514b8 100644 --- a/di.sln +++ b/di.sln @@ -1,6 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FractalPainter", "FractalPainter\FractalPainter.csproj", "{4D70883B-6F8B-4166-802F-8EDC9BE93199}" +# Visual Studio Version 17 +VisualStudioVersion = 17.11.35327.3 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TagsCloudVisualization", "TagsCloudVisualization\TagsCloudVisualization.csproj", "{3D0B2588-CF21-43DB-BEF0-44CE83B090B7}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -8,9 +11,12 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4D70883B-6F8B-4166-802F-8EDC9BE93199}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4D70883B-6F8B-4166-802F-8EDC9BE93199}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4D70883B-6F8B-4166-802F-8EDC9BE93199}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4D70883B-6F8B-4166-802F-8EDC9BE93199}.Release|Any CPU.Build.0 = Release|Any CPU + {3D0B2588-CF21-43DB-BEF0-44CE83B090B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3D0B2588-CF21-43DB-BEF0-44CE83B090B7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3D0B2588-CF21-43DB-BEF0-44CE83B090B7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3D0B2588-CF21-43DB-BEF0-44CE83B090B7}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection EndGlobal