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

Савенко Дмитрий #258

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions cs/TagsCloudVisualization/CircularCloudLayouter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using TagsCloudVisualization;

public class CircularCloudLayouter

Choose a reason for hiding this comment

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

Кажется, что в этом классе смешались две ответственности - он и располагает прямоугольники, и умеет с файловой системой работать. Давай оставим один лейаутер и отдельную зависимость, которая будет уметь сохранять файл

{
private readonly RectangleLayouter rectangleLayouter;

public CircularCloudLayouter(Point center)
{
rectangleLayouter = new RectangleLayouter(center);
}

public Rectangle PutNextRectangle(Size rectangleSize)
{
return rectangleLayouter.PutNextRectangle(rectangleSize);
}

public List<Rectangle> GetRectangles()
{
return rectangleLayouter.GetRectangles();
}
}
45 changes: 45 additions & 0 deletions cs/TagsCloudVisualization/CloudImageRenderer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System.Drawing;
using System.Drawing.Imaging;

namespace TagsCloudVisualization;

public class CloudImageRenderer
{
private readonly Size imageSize;

public CloudImageRenderer(Size imageSize)
{
this.imageSize = imageSize;
}

public void SaveToFile(string filename, IEnumerable<Rectangle> rectangles)
{
using var bitmap = new Bitmap(imageSize.Width, imageSize.Height);
using var graphics = Graphics.FromImage(bitmap);
graphics.Clear(Color.Black);

var random = new Random();
foreach (var rectangle in rectangles)
{
var color = Color.FromArgb(
random.Next(128, 255),
random.Next(128, 255),
random.Next(128, 255)
);

using var brush = new SolidBrush(Color.FromArgb(180, color));
using var pen = new Pen(color, 2f);

var rect = new Rectangle(
rectangle.X + imageSize.Width / 2,
rectangle.Y + imageSize.Height / 2,
rectangle.Width,
rectangle.Height);

graphics.FillRectangle(brush, rect);
graphics.DrawRectangle(pen, rect);
}

bitmap.Save(filename, ImageFormat.Png);
}
}
23 changes: 23 additions & 0 deletions cs/TagsCloudVisualization/Extensions/PointExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.Drawing;

namespace TagsCloudVisualization.Extensions;

public static class PointExtensions
{
public static double DistanceFromCenter(this Point point, Point center)
{
var dx = point.X - center.X;
var dy = point.Y - center.Y;
return Math.Sqrt(dx * dx + dy * dy);
}

public static Point GetDirectionToCenter(this Point center, Rectangle rectangle)
{
var rectangleCenter = rectangle.GetCenter();

var directionX = center.X - rectangleCenter.X;
var directionY = center.Y - rectangleCenter.Y;

return new Point(directionX, directionY);
}
}
22 changes: 22 additions & 0 deletions cs/TagsCloudVisualization/Extensions/RectangleExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Drawing;

namespace TagsCloudVisualization.Extensions;

public static class RectangleExtensions
{
public static double DistanceToCenter(this Rectangle rectangle, Point center)
{
var rectangleCenter = rectangle.GetCenter();

var dx = rectangleCenter.X - center.X;
var dy = rectangleCenter.Y - center.Y;
return Math.Sqrt(dx * dx + dy * dy);
}

public static Point GetCenter(this Rectangle rectangle)
{
return new Point(
rectangle.Left + rectangle.Width / 2,
rectangle.Top + rectangle.Height / 2);
}
}
64 changes: 64 additions & 0 deletions cs/TagsCloudVisualization/Grid.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System.Drawing;

namespace TagsCloudVisualization;

public class Grid
{
private readonly int cellSize;
private readonly Dictionary<Point, List<Rectangle>> cells = new();

public Grid(int cellSize = 50)
{
this.cellSize = cellSize;
}
public void AddRectangle(Rectangle rectangle)
{
var cellsToUpdate = GetCellsCoveredByRectangle(rectangle);

foreach (var cell in cellsToUpdate)
{
if (!cells.ContainsKey(cell))
{
cells[cell] = new List<Rectangle>();
}

cells[cell].Add(rectangle);
}
}

public bool IsIntersecting(Rectangle rectangle)
{
var cellsToCheck = GetCellsCoveredByRectangle(rectangle);

foreach (var cell in cellsToCheck)
{
if (!cells.TryGetValue(cell, out var rectanglesInCell))
{
continue;
}

if (rectanglesInCell.Any(r => r.IntersectsWith(rectangle)))
{
return true;
}
}

return false;
}

private IEnumerable<Point> GetCellsCoveredByRectangle(Rectangle rectangle)
{
var startX = rectangle.Left / cellSize;
var endX = rectangle.Right / cellSize;
var startY = rectangle.Top / cellSize;
var endY = rectangle.Bottom / cellSize;

for (var x = startX; x <= endX; x++)
{
for (var y = startY; y <= endY; y++)
{
yield return new Point(x, y);
}
}
}
}
32 changes: 32 additions & 0 deletions cs/TagsCloudVisualization/LayoutGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Drawing;

namespace TagsCloudVisualization;

public class LayoutGenerator
{
private readonly Point center;
private readonly Size imageSize;
private readonly CloudImageRenderer renderer;

public LayoutGenerator(Point center, Size imageSize)
{
this.center = center;
this.imageSize = imageSize;
renderer = new CloudImageRenderer(this.imageSize);
}

public void GenerateLayout(string outputFileName, int rectangleCount, Func<Random, Size> sizeGenerator)
{
var layouter = new CircularCloudLayouter(center);
var random = new Random();

for (var i = 0; i < rectangleCount; i++)
{
var size = sizeGenerator(random);
layouter.PutNextRectangle(size);
}

var rectangles = layouter.GetRectangles();
renderer.SaveToFile(outputFileName, rectangles);
}
}
9 changes: 9 additions & 0 deletions cs/TagsCloudVisualization/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Drawing;
using TagsCloudVisualization;


var generator = new LayoutGenerator(new Point(0, 0), new Size(800, 600));

generator.GenerateLayout("layout1.png", 100, random => new Size(random.Next(20, 100), random.Next(10, 50)));
generator.GenerateLayout("layout2.png", 150, random => new Size(50, 20));
generator.GenerateLayout("layout3.png", 200, random => new Size(random.Next(10, 30), random.Next(10, 30)));
16 changes: 16 additions & 0 deletions cs/TagsCloudVisualization/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Circular Cloud Layouter


### Раскладка 1

![Layout 1](layout1.png)


### Раскладка 2

![Layout 2](layout2.png)


### Раскладка 3

![Layout 3](layout3.png)
31 changes: 31 additions & 0 deletions cs/TagsCloudVisualization/RectangleLayouter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Drawing;

namespace TagsCloudVisualization;

public class RectangleLayouter(Point center)
{
private readonly SpiralGenerator spiralGenerator = new(center);
private readonly List<Rectangle> rectangles = new();
private readonly Grid grid = new();
public Rectangle PutNextRectangle(Size rectangleSize)
{
if (rectangleSize.Width <= 0 || rectangleSize.Height <= 0)
throw new ArgumentException("Размеры прямоугольника должны быть положительными.");

Rectangle newRectangle;
do
{
var point = spiralGenerator.GetNextPoint();
var location = new Point(
point.X - rectangleSize.Width / 2,
point.Y - rectangleSize.Height / 2);
newRectangle = new Rectangle(location, rectangleSize);
} while (grid.IsIntersecting(newRectangle));

grid.AddRectangle(newRectangle);
rectangles.Add(newRectangle);
return newRectangle;
}

public List<Rectangle> GetRectangles() => rectangles;
}
41 changes: 41 additions & 0 deletions cs/TagsCloudVisualization/SpiralGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.Drawing;

namespace TagsCloudVisualization;

public class SpiralGenerator
{
private readonly Point center;
private double phi;
private readonly double spiralStep;
private readonly double deltaPhi;
private Point? lastGeneratedPoint;

public SpiralGenerator(Point center, double spiralStep = 1, double deltaPhiDegrees = (Math.PI / 180))
{
if (spiralStep <= 0)
throw new ArgumentException("Шаг спирали должен быть больше 0");

this.center = center;
phi = 0;
this.spiralStep = spiralStep;
deltaPhi = deltaPhiDegrees;
}

public Point GetNextPoint()
{
Point newPoint;

do
{
var radius = spiralStep * phi;
var x = (int)Math.Round(radius * Math.Cos(phi)) + center.X;
var y = (int)Math.Round(radius * Math.Sin(phi)) + center.Y;
phi += deltaPhi;

newPoint = new Point(x, y);
} while (newPoint == lastGeneratedPoint);

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

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="System.Drawing.Common" Version="9.0.0-rc.2.24474.1" />
</ItemGroup>

</Project>
Binary file added cs/TagsCloudVisualization/layout1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added cs/TagsCloudVisualization/layout2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added cs/TagsCloudVisualization/layout3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading