找出有限区域内字符的最大像素大小
Finding out the maximum pixel size of characters in a limited area
我正在尝试实现一项功能,以显示适合该区域的最大可能字符像素数。
示例 1:
想象一下尺寸为 100x20 像素的 LED 显示屏。需要显示的字符串是:volutpa commodo diam
手工完成所有操作后,我能够确定没有 splitting/dividing 单词的字符的最大可能像素大小为 8x8 像素。每个字符必须具有相同的像素大小。
如果字符像素大小为8x8 px,则上述字符串将成功显示在LED显示屏上。预期输出:8
示例 2:
想象一下尺寸为 100x20 像素的 LED 显示屏。需要显示的字符串是:dio volutpa diam
如果字符像素大小为9x9 px,则上述字符串将成功显示在LED显示屏上。预期输出:9
示例 3:
想象一下尺寸为 55x25 像素的 LED 显示屏。需要显示的字符串是:dio tuo diam
如果字符像素大小为8x8 px,则上述字符串将成功显示在LED显示屏上。预期输出:8
示例 4:
想象一下尺寸为 20x6 像素的 LED 显示屏。需要显示的一个字符串是:tuo volutpa
如果字符像素大小为2x2 px,则上述字符串将成功显示在LED显示屏上。预期输出:2
注意:字符串中的每个字符(包括space)必须具有相同的像素大小(例如 6x6 像素)以填充整个区域(LED 显示屏)并且字符串中的单词不能是 split/divided.
在此 example 1 中,您可以看到我正在努力实现的 "hand made" 图像。整个布局代表区域大小(100x20 像素),而黑框代表最大可能的字符像素大小(8x8 像素)。如果我使用(9x9 px 或更多)作为字符大小,文本将不适合,如果我使用(7x7 px 或更小),则会有太多空白 space.
在此 example 2 中,您可以看到我正在努力实现的 "hand made" 图像。整个布局代表区域大小(100x20 像素),而黑框代表最大可能的字符像素大小(9x9 像素)。如果我使用(10x10 像素或更多)作为字符大小,文本将不适合,如果我使用(8x8 像素或更小),则会有太多空白 space。如果该行即将结束,我们应该忽略单词末尾的 space。
预计:
第 1 行:dio_volutpa
第 2 行:直径
实际:
第 1 行:dio_volutpa_
第 2 行:直径
在此 example 3 中,您可以看到我正在努力实现的 "hand made" 图像。整个布局代表区域大小(55x25 像素),而黑框代表最大可能的字符像素大小(8x8 像素)。如果我使用(9x9 像素或更多)作为字符大小,文本将不适合,如果我使用(7x7 像素或更小),则会有太多空白 space。那里的红框告诉你下一个词没有 space,因此它需要换行或者如果下面没有行 space 则减小它的像素大小。
在 C# 中实现它的最佳方法是什么?
static void Main(string[] args)
{
String sentence = "volutpa commodo diam";
int width = 100; // 100 px
int height = 20; // 20 px
int pixelSize = height / 2; // Starting pixel size (10)
int maxLines = height / pixelSize; // Max. available lines in the area
int currentLine = 1; // Starting line
string[] words = sentence.Split(' '); // Splitting words from the sentence. words[1] = volutpa, words[2] = commodo, words[3] = diam
// Length of the words
for (int i = 0; i < words.Length; i++)
{
Console.WriteLine("Word " + i + " length: " + words[i].Length * pixelSize);
}
Console.ReadLine();
}
我现在已经做了这个,但不知道如何继续。我会很感激一些提示和想法。
这是我根据您更新后的问题得出的最终解决方案。
请阅读代码中的注释。
UPDATE
inside fixtoFitMatrix()
方法 space 将仅在 2 个单词之间被考虑。
更新 2
请阅读代码中的注释1、注释2和注释3。
namespace ConsoleApplication29
{
class Program
{
private static void Main(string[] args)
{
Check("volutpa commodo diam", 100, 20);
Check("dio volutpa diam", 100, 20);
Check("dio tuo diam", 55, 25);
Check("tuo volutpa", 20, 6);
Check("volutpa", 23, 2);
Check("diam tu diam op comodo", 10, 20);
Check("volutpas di diam e commodo", 65, 65);
Check("diamo volutpasoni onedo commodoso", 10, 40);
Console.ReadLine();
}
private static void Check(string txt,int w,int h)
{
String sentence = txt;
int width = w;
int height = h;
string[] words = sentence.Split(' ');
int maxLines;
int pixelSize = GetPixelSize(words, height, width,out maxLines);
Console.WriteLine(sentence);
// length of the words
for (int i = 0; i < words.Length; i++)
{
Console.WriteLine("Word " + i + " length: " + words[i].Length * pixelSize );
}
Console.WriteLine("pixel size will be " + pixelSize + " lines: " + maxLines );
Console.WriteLine("--------------------------------------------");
}
private static int GetPixelSize(string[] words, int height, int width,out int maxlines)
{
int lines = 1;
int basepx = GetBasePixelSize(words, height, width,1,ref lines);
// fix if not each line is fitted to width or the height of the matrix
int finalpx = fixtoFitMatrix(basepx,words,width,height,lines);
maxlines = lines;
return finalpx;
}
private static int fixtoFitMatrix(int basepx, string[] words,int width,int height,int lines)
{
List<LedLine> ldlines = new List<LedLine>();
int currentline = 0;
// set text for each line
LedLine l = new LedLine() { LineNumber = currentline, LineText = words[0]};
ldlines.Add(l);
for (int i = 1;i< words.Length;i++)
{
var currentstring = words[i];
if (ldlines[currentline].Len * basepx + basepx + currentstring.Length * basepx <= width)
{
// add to current line
ldlines[currentline].LineText = ldlines[currentline].LineText + currentstring;
}
else
{
// it is a new line
currentline++;
LedLine newl = new LedLine() { LineNumber = currentline, LineText = currentstring };
ldlines.Add(newl);
}
}
// px size is also a function of the width
// for example:
// on surface of 100X20 volutpa commodo diam will be 8px and dio volutpa diam will be 9px
// that happens because commodo diam is the length of 12 and 12*9=108 and the width is only 100 so we will need to fix
//fix will be chcked if the number of lines requeired is not the same in ldlines.count that means that we will need to "shrink" px by 1 every recursive call
if (ldlines.Count > lines)
{
return fixtoFitMatrix(basepx - 1, words, width,height, lines);
}
// comment 1: we need to check the height also
else if (lines * basepx > height)
{
return fixtoFitMatrix(basepx - 1, words, width, height, lines);
}
return basepx;
}
private static int GetBasePixelSize(string[] words, int height,int width,int linesneeded,ref int finalnumberoflines,int specialH = 0)
{
int h = (int)Math.Ceiling(((double)height / (double)linesneeded));
if (specialH > 0)
h = specialH;
var lines = linesneeded;
var accumulate = 0;
for (int i = 0;i< words.Length;i++)
{
accumulate += words[i].Length * h;
// add space if it is not the last word
if (i < words.Length - 1)
{
accumulate += h;
}
// more line needed - call recursivaly until we get the number of lines needed
if (accumulate / lines > width)
{
return GetBasePixelSize(words, height, width, linesneeded+1,ref finalnumberoflines,specialH);
}
}
finalnumberoflines = lines;
// comment 2 - special case - if there is a single word that is larger than all px (int h) we will decrease h, for example on matrix of 10*20 the word 'comodo'
// can be displayed only when h=1 because if its 2 then 2* 6 = 12
// we will strat all over again with the new size
if (words.Any(x => x.Length * h > width))
{
string specialword = words.Where(x => x.Length * h > width).FirstOrDefault();
// decrease h by the equation X = height/word.length, if the result is under 1 its not possible to do that
h = (int)Math.Floor((double)width/ (double)specialword.Length);
// comment 3 - if h = 0 exit the method and return 0 - it is not possible with the given conditions
// (for example matrix of 10X40 with the sentence 'diamo volutpasoni onedo commodoso' is not possible)
if (h == 0)
return 0;
finalnumberoflines = 1;
return GetBasePixelSize(words, height, width, 1, ref finalnumberoflines,h);
}
return h;
}
}
public class LedLine
{
public int LineNumber { get; set; }
public string LineText { get; set; }
public int Len
{
get
{
return LineText.Length;
}
}
}
}
输出:
volutpa commodo diam
Word 0 length: 56
Word 1 length:
56
Word 2 length: 32
pixel size will be 8 lines: 2
--------------------------------------------
dio volutpa diam
Word 0 length: 27
Word 1 length: 63
Word 2 length:
36
pixel size will be 9 lines: 2
--------------------------------------------
dio tuo diam
Word 0 length: 24
Word 1 length: 24
Word 2 length: 32
pixel size will be 8 lines: 3
--------------------------------------------
tuo volutpa
Word 0 length: 6
Word 1 length: 14
pixel size will be 2
lines: 2
--------------------------------------------
volutpa
Word 0 length: 14
pixel size will be 2 lines: 1
--------------------------------------------
diam tu diam op comodo
Word 0 length: 4
Word 1 length: 2
Word 2 length:
4
Word 3 length: 2
Word 4 length: 6
pixel size will be
1 lines: 3
--------------------------------------------
volutpas di diam e commodo
Word 0 length: 64
Word 1 length: 16
Word 2
length: 32
Word 3 length: 8
Word 4 length: 56
pixel
size will be 8 lines: 4
--------------------------------------------
diamo volutpasoni onedo commodoso
Word 0 length: 0
Word 1 length: 0
Word
2 length: 0
Word 3 length: 0
pixel size will be 0 lines:
7
--------------------------------------------
我正在尝试实现一项功能,以显示适合该区域的最大可能字符像素数。
示例 1: 想象一下尺寸为 100x20 像素的 LED 显示屏。需要显示的字符串是:volutpa commodo diam
手工完成所有操作后,我能够确定没有 splitting/dividing 单词的字符的最大可能像素大小为 8x8 像素。每个字符必须具有相同的像素大小。
如果字符像素大小为8x8 px,则上述字符串将成功显示在LED显示屏上。预期输出:8
示例 2: 想象一下尺寸为 100x20 像素的 LED 显示屏。需要显示的字符串是:dio volutpa diam
如果字符像素大小为9x9 px,则上述字符串将成功显示在LED显示屏上。预期输出:9
示例 3: 想象一下尺寸为 55x25 像素的 LED 显示屏。需要显示的字符串是:dio tuo diam
如果字符像素大小为8x8 px,则上述字符串将成功显示在LED显示屏上。预期输出:8
示例 4: 想象一下尺寸为 20x6 像素的 LED 显示屏。需要显示的一个字符串是:tuo volutpa
如果字符像素大小为2x2 px,则上述字符串将成功显示在LED显示屏上。预期输出:2
注意:字符串中的每个字符(包括space)必须具有相同的像素大小(例如 6x6 像素)以填充整个区域(LED 显示屏)并且字符串中的单词不能是 split/divided.
在此 example 1 中,您可以看到我正在努力实现的 "hand made" 图像。整个布局代表区域大小(100x20 像素),而黑框代表最大可能的字符像素大小(8x8 像素)。如果我使用(9x9 px 或更多)作为字符大小,文本将不适合,如果我使用(7x7 px 或更小),则会有太多空白 space.
在此 example 2 中,您可以看到我正在努力实现的 "hand made" 图像。整个布局代表区域大小(100x20 像素),而黑框代表最大可能的字符像素大小(9x9 像素)。如果我使用(10x10 像素或更多)作为字符大小,文本将不适合,如果我使用(8x8 像素或更小),则会有太多空白 space。如果该行即将结束,我们应该忽略单词末尾的 space。
预计:
第 1 行:dio_volutpa
第 2 行:直径
实际:
第 1 行:dio_volutpa_
第 2 行:直径
在此 example 3 中,您可以看到我正在努力实现的 "hand made" 图像。整个布局代表区域大小(55x25 像素),而黑框代表最大可能的字符像素大小(8x8 像素)。如果我使用(9x9 像素或更多)作为字符大小,文本将不适合,如果我使用(7x7 像素或更小),则会有太多空白 space。那里的红框告诉你下一个词没有 space,因此它需要换行或者如果下面没有行 space 则减小它的像素大小。
在 C# 中实现它的最佳方法是什么?
static void Main(string[] args)
{
String sentence = "volutpa commodo diam";
int width = 100; // 100 px
int height = 20; // 20 px
int pixelSize = height / 2; // Starting pixel size (10)
int maxLines = height / pixelSize; // Max. available lines in the area
int currentLine = 1; // Starting line
string[] words = sentence.Split(' '); // Splitting words from the sentence. words[1] = volutpa, words[2] = commodo, words[3] = diam
// Length of the words
for (int i = 0; i < words.Length; i++)
{
Console.WriteLine("Word " + i + " length: " + words[i].Length * pixelSize);
}
Console.ReadLine();
}
我现在已经做了这个,但不知道如何继续。我会很感激一些提示和想法。
这是我根据您更新后的问题得出的最终解决方案。
请阅读代码中的注释。
UPDATE
inside fixtoFitMatrix()
方法 space 将仅在 2 个单词之间被考虑。
更新 2
请阅读代码中的注释1、注释2和注释3。
namespace ConsoleApplication29
{
class Program
{
private static void Main(string[] args)
{
Check("volutpa commodo diam", 100, 20);
Check("dio volutpa diam", 100, 20);
Check("dio tuo diam", 55, 25);
Check("tuo volutpa", 20, 6);
Check("volutpa", 23, 2);
Check("diam tu diam op comodo", 10, 20);
Check("volutpas di diam e commodo", 65, 65);
Check("diamo volutpasoni onedo commodoso", 10, 40);
Console.ReadLine();
}
private static void Check(string txt,int w,int h)
{
String sentence = txt;
int width = w;
int height = h;
string[] words = sentence.Split(' ');
int maxLines;
int pixelSize = GetPixelSize(words, height, width,out maxLines);
Console.WriteLine(sentence);
// length of the words
for (int i = 0; i < words.Length; i++)
{
Console.WriteLine("Word " + i + " length: " + words[i].Length * pixelSize );
}
Console.WriteLine("pixel size will be " + pixelSize + " lines: " + maxLines );
Console.WriteLine("--------------------------------------------");
}
private static int GetPixelSize(string[] words, int height, int width,out int maxlines)
{
int lines = 1;
int basepx = GetBasePixelSize(words, height, width,1,ref lines);
// fix if not each line is fitted to width or the height of the matrix
int finalpx = fixtoFitMatrix(basepx,words,width,height,lines);
maxlines = lines;
return finalpx;
}
private static int fixtoFitMatrix(int basepx, string[] words,int width,int height,int lines)
{
List<LedLine> ldlines = new List<LedLine>();
int currentline = 0;
// set text for each line
LedLine l = new LedLine() { LineNumber = currentline, LineText = words[0]};
ldlines.Add(l);
for (int i = 1;i< words.Length;i++)
{
var currentstring = words[i];
if (ldlines[currentline].Len * basepx + basepx + currentstring.Length * basepx <= width)
{
// add to current line
ldlines[currentline].LineText = ldlines[currentline].LineText + currentstring;
}
else
{
// it is a new line
currentline++;
LedLine newl = new LedLine() { LineNumber = currentline, LineText = currentstring };
ldlines.Add(newl);
}
}
// px size is also a function of the width
// for example:
// on surface of 100X20 volutpa commodo diam will be 8px and dio volutpa diam will be 9px
// that happens because commodo diam is the length of 12 and 12*9=108 and the width is only 100 so we will need to fix
//fix will be chcked if the number of lines requeired is not the same in ldlines.count that means that we will need to "shrink" px by 1 every recursive call
if (ldlines.Count > lines)
{
return fixtoFitMatrix(basepx - 1, words, width,height, lines);
}
// comment 1: we need to check the height also
else if (lines * basepx > height)
{
return fixtoFitMatrix(basepx - 1, words, width, height, lines);
}
return basepx;
}
private static int GetBasePixelSize(string[] words, int height,int width,int linesneeded,ref int finalnumberoflines,int specialH = 0)
{
int h = (int)Math.Ceiling(((double)height / (double)linesneeded));
if (specialH > 0)
h = specialH;
var lines = linesneeded;
var accumulate = 0;
for (int i = 0;i< words.Length;i++)
{
accumulate += words[i].Length * h;
// add space if it is not the last word
if (i < words.Length - 1)
{
accumulate += h;
}
// more line needed - call recursivaly until we get the number of lines needed
if (accumulate / lines > width)
{
return GetBasePixelSize(words, height, width, linesneeded+1,ref finalnumberoflines,specialH);
}
}
finalnumberoflines = lines;
// comment 2 - special case - if there is a single word that is larger than all px (int h) we will decrease h, for example on matrix of 10*20 the word 'comodo'
// can be displayed only when h=1 because if its 2 then 2* 6 = 12
// we will strat all over again with the new size
if (words.Any(x => x.Length * h > width))
{
string specialword = words.Where(x => x.Length * h > width).FirstOrDefault();
// decrease h by the equation X = height/word.length, if the result is under 1 its not possible to do that
h = (int)Math.Floor((double)width/ (double)specialword.Length);
// comment 3 - if h = 0 exit the method and return 0 - it is not possible with the given conditions
// (for example matrix of 10X40 with the sentence 'diamo volutpasoni onedo commodoso' is not possible)
if (h == 0)
return 0;
finalnumberoflines = 1;
return GetBasePixelSize(words, height, width, 1, ref finalnumberoflines,h);
}
return h;
}
}
public class LedLine
{
public int LineNumber { get; set; }
public string LineText { get; set; }
public int Len
{
get
{
return LineText.Length;
}
}
}
}
输出:
volutpa commodo diam
Word 0 length: 56
Word 1 length: 56
Word 2 length: 32
pixel size will be 8 lines: 2
--------------------------------------------
dio volutpa diam
Word 0 length: 27
Word 1 length: 63
Word 2 length: 36
pixel size will be 9 lines: 2
--------------------------------------------
dio tuo diam
Word 0 length: 24
Word 1 length: 24
Word 2 length: 32
pixel size will be 8 lines: 3
--------------------------------------------
tuo volutpa
Word 0 length: 6
Word 1 length: 14
pixel size will be 2 lines: 2
--------------------------------------------
volutpa
Word 0 length: 14
pixel size will be 2 lines: 1
--------------------------------------------
diam tu diam op comodo
Word 0 length: 4
Word 1 length: 2
Word 2 length: 4
Word 3 length: 2
Word 4 length: 6
pixel size will be 1 lines: 3
--------------------------------------------
volutpas di diam e commodo
Word 0 length: 64
Word 1 length: 16
Word 2 length: 32
Word 3 length: 8
Word 4 length: 56
pixel size will be 8 lines: 4
--------------------------------------------
diamo volutpasoni onedo commodoso
Word 0 length: 0
Word 1 length: 0
Word 2 length: 0
Word 3 length: 0
pixel size will be 0 lines: 7
--------------------------------------------