Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Брайденбихер Виктор Николаевич #238

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,5 @@ FakesAssemblies/

*Solved.cs

.idea/
.idea/
/cs/tdd.sln.DotSettings
51 changes: 51 additions & 0 deletions cs/TagsCloudVisualization/CloudClasses/CircularCloudLayouter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using System.Drawing;
using System.Runtime.CompilerServices;
using TagsCloudVisualization.CloudClasses.Interfaces;

namespace TagsCloudVisualization.CloudClasses
{
public class CircularCloudLayouter : ICloudLayouter
{
private readonly List<Rectangle> rectangles = new List<Rectangle>();

public readonly ISpiralRayMover RayMover;

public List<Rectangle> Rectangles => rectangles;

public CircularCloudLayouter(ISpiralRayMover rayMover)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можно сделать интерфейс IRayMover и наследовать от него будущие RayMover'ы, как SpiralRayMover. И сюда передавать IRayMover, чтобы в случае изменения логики распределения прямоугольников просто подменить реализацию RayMover'a

{
if (rayMover.Center.X <= 0 || rayMover.Center.Y <= 0)
throw new ArgumentException("IRayMover center Point should have positive X and Y");

if (rayMover.RadiusStep <= 0 || rayMover.AngleStep <= 0)
throw new ArgumentException("radiusStep and angleStep should be positive");

RayMover = rayMover;
}

public Rectangle PutNextRectangle(Size rectangleSize)
{
if (rectangleSize.Width <= 0 || rectangleSize.Height <= 0)
throw new ArgumentException("The height and width of the Rectangle must be greater than 0");

var rectangle = Rectangle.Empty;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

можно убрать и создавать внутри цикла


foreach (var point in RayMover.MoveRay())
{
var location = new Point(point.X - rectangleSize.Width / 2,
point.Y - rectangleSize.Height / 2);

rectangle = new Rectangle(location, rectangleSize);

// Проверяем, пересекается ли новый прямоугольник с уже существующими
if (!rectangles.Any(r => r.IntersectsWith(rectangle)))
{
rectangles.Add(rectangle);
return rectangle;
}
}

throw new InvalidOperationException("No suitable location found for the rectangle.");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Drawing;

namespace TagsCloudVisualization.CloudClasses.Interfaces
{
public interface ICloudLayouter
{
public Rectangle PutNextRectangle(Size rectangleSize);

public List<Rectangle> Rectangles { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Drawing;

namespace TagsCloudVisualization.CloudClasses.Interfaces
{
// Интерфейс для класса, который перемещает луч по спирали, генерируя последовательность точек.
public interface ISpiralRayMover
{
IEnumerable<Point> MoveRay();

public Point Center { get; }

public double RadiusStep { get; }

public double AngleStep { get; }
}
}
35 changes: 35 additions & 0 deletions cs/TagsCloudVisualization/CloudClasses/Ray.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Drawing;

namespace TagsCloudVisualization.CloudClasses
{
public class Ray
{
public double Radius { get; private set; }

//В радианах
public double Angle { get; private set; }

public readonly Point StartPoint;

public Ray(Point startPoint, int radius, int angle)
{
StartPoint = startPoint;

Radius = radius;

Angle = angle;
}

public void Update(double deltaRadius, double deltaAngle)
{
Radius += deltaRadius;
Angle += deltaAngle;
}

public Point EndPoint => new Point
{
X = StartPoint.X + (int)(Radius * Math.Cos(Angle)),
Y = StartPoint.Y + (int)(Radius * Math.Sin(Angle))
};
}
}
44 changes: 44 additions & 0 deletions cs/TagsCloudVisualization/CloudClasses/SpiralRayMover.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System.Drawing;
using TagsCloudVisualization.CloudClasses.Interfaces;

namespace TagsCloudVisualization.CloudClasses
{
public class SpiralRayMover : ISpiralRayMover
{
private readonly Ray spiralRay;

private readonly double radiusStep;

//В радианах
private readonly double angleStep;

private const double OneRound = Math.PI * 2;

public SpiralRayMover(Point center, double radiusStep = 1, double angleStep = 5,
int startRadius = 0, int startAngle = 0)
{
spiralRay = new Ray(center, startRadius, startAngle);
this.radiusStep = radiusStep;

//Преобразование из градусов в радианы
this.angleStep = angleStep * Math.PI / 180;
}

public Point Center => spiralRay.StartPoint;

public double RadiusStep => radiusStep;

public double AngleStep => angleStep;

public IEnumerable<Point> MoveRay()
{
while (true)
{
yield return spiralRay.EndPoint;

//Радиус увеличивается на 1 только после полного прохождения круга
spiralRay.Update(radiusStep / OneRound * angleStep, angleStep);
}
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
54 changes: 54 additions & 0 deletions cs/TagsCloudVisualization/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System.Drawing;
using TagsCloudVisualization.CloudClasses;
using TagsCloudVisualization.CloudClasses.Interfaces;

namespace TagsCloudVisualization.Visualisation
{
internal class Program
{
private static void Main(string[] args)
{
using var tagCloudGenerator = new TagCloudImageGenerator(new Visualiser(Color.Black, 1));

var center = new Point(500, 500);
var bitmapSize = new Size(1000, 1000);

var firstSizes = GenerateRectangleSizes(40, 60, 80, 60, 80);
var secondSizes = GenerateRectangleSizes(100, 10, 40, 20, 30);
var thirdSizes = GenerateRectangleSizes(30, 80, 130, 80, 130);

var firstLayouter = SetupCloudLayout(center, firstSizes);
var secondLayouter = SetupCloudLayout(center, secondSizes);
var thirdLayouter = SetupCloudLayout(center, thirdSizes);

using var bitmap1 = tagCloudGenerator.CreateNewBitmap(bitmapSize, firstLayouter.Rectangles);
using var bitmap2 = tagCloudGenerator.CreateNewBitmap(bitmapSize, secondLayouter.Rectangles);
using var bitmap3 = tagCloudGenerator.CreateNewBitmap(bitmapSize, thirdLayouter.Rectangles);

BitmapSaver.SaveToCorrect(bitmap1, "bitmap_1.png");
BitmapSaver.SaveToCorrect(bitmap2, "bitmap_2.png");
BitmapSaver.SaveToCorrect(bitmap3, "bitmap_3.png");
}

private static IEnumerable<Size> GenerateRectangleSizes(int count, int minWidth, int maxWidth, int minHeight, int maxHeight)
{
var sizeBuilder = SizeBuilder.Configure()
.SetCount(count)
.SetWidth(minWidth, maxWidth)
.SetHeight(minHeight, maxHeight)
.Generate();

return sizeBuilder;
}

private static CircularCloudLayouter SetupCloudLayout(Point center, IEnumerable<Size> sizes)
{
var layouter = new CircularCloudLayouter(new SpiralRayMover(center));

sizes.ToList()
.ForEach(size => layouter.PutNextRectangle(size));

return layouter;
}
}
}
32 changes: 32 additions & 0 deletions cs/TagsCloudVisualization/TagsCloudVisualization.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<StartupObject>TagsCloudVisualization.Visualisation.Program</StartupObject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="FluentAssertions" Version="6.12.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="NUnit" Version="3.14.0" />
<PackageReference Include="NUnit.Analyzers" Version="3.9.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.10" />
</ItemGroup>

<ItemGroup>
<Using Include="NUnit.Framework" />
</ItemGroup>

<ItemGroup>
<Folder Include="CorrectImages\" />
<Folder Include="FailImages\" />
</ItemGroup>

</Project>
Loading