-
Notifications
You must be signed in to change notification settings - Fork 0
/
WordCloud.cs
156 lines (141 loc) · 4.91 KB
/
WordCloud.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
namespace MeCab
{
public class WordCloud
{
private readonly int maxWordSize = 750; // 最大文字サイズ 500
private readonly int minWordSize = 8;
readonly Bitmap img = null;
readonly Bitmap demo = null;
readonly Graphics g;
readonly Graphics demoG;
Random rnd = new Random();
string font = "MS UI Gothic";
readonly int width;
readonly int height;
bool[,] png = null;
public WordCloud(int _width, int _height)
{
width = _width;
height = _height;
img = new Bitmap(_width, _height);
demo = new Bitmap(_width, _height);
g = Graphics.FromImage(img);
demoG = Graphics.FromImage(demo);
png = new bool[_height, _width];
}
public void SetFont(string _font)
{
font = _font;
}
private void DrawWord(AggregateData aggregate, int _maxCount) // 文字を描画する
{
double ratio = (double)aggregate.Count / (double)_maxCount;
int size = MeasurementWordSize(ratio);
bool b = true;
int count = 0;
while(b)
{
int x = rnd.Next(0, width - 20);
int y = rnd.Next(0, height - 20);
// demoG.DrawString(aggregate.Word, new Font(font, size), Brushes.Blue, x, y);
demoG.DrawString(aggregate.Word, new Font(font, size), FontColor(), x, y);
if (CheckMeasureSize(aggregate.Word, new Font(font, size), x, y))
{
// g.DrawString(aggregate.Word, new Font(font, size), Brushes.Blue, x, y);
g.DrawString(aggregate.Word, new Font(font, size), FontColor(), x, y);
SetMeasureSize(aggregate.Word, new Font(font, size), x, y);
b = false;
}
count++;
if(count >= 100) // 複数回描画できなかったら強制的に次の文字に移行
{
b = false;
}
}
}
private Brush FontColor()
{
int n = rnd.Next(3);
return n switch
{
0 => Brushes.Aqua,
1 => Brushes.SpringGreen,
2 => Brushes.Magenta,
_ => Brushes.Blue,
};
}
private int MeasurementWordSize(double _ratio) // フォントサイズの最小値を決める
{
int size = (int)Math.Round(maxWordSize * _ratio);
if(size < minWordSize)
{
size = minWordSize;
}
else if(size > (maxWordSize*0.065))
{
size = ((int)(maxWordSize * 0.065));
}
return size;
}
private bool CheckMeasureSize(string str, Font fontData, int x, int y) // 描画文字と位置を計測し、範囲内かほかの文字と重なっていないか確認する。
{
bool b = true;
var size2 = demoG.MeasureString(str, fontData);
if(height <= size2.Height+y )
{
return false;
}
else if(width <= size2.Width+x)
{
return false;
}
for (int i = y; i < size2.Height+y; i++)
{
for (int w = x; w < size2.Width+x; w++)
{
if (png[i, w])
{
b = false;
break;
}
}
}
return b;
}
private void SetMeasureSize(string str, Font fontData, int x, int y) // 描画位置を配列に格納する
{
var size2 = g.MeasureString(str, fontData);
for (int i = y+0; i < size2.Height+y-0; i++) // +2 -2
{
for (int w = x+4 ; w < size2.Width+x-4; w++) // +5 -5
{
png[i, w] = true;
}
}
Console.WriteLine("配置str:" + str );
}
public void MakeImg(List<AggregateData> _list, string outputPath) // 画像を出力する
{
g.FillRectangle(Brushes.White, g.VisibleClipBounds);
int maxCount = 0;
foreach(AggregateData data in _list)
{
maxCount += data.Count;
}
foreach (AggregateData data in _list)
{
DrawWord(data, maxCount);
}
string path = outputPath + "\\data.png";
img.Save(path);
}
private void ReleaseResources()
{
g.Dispose();
}
}
}