gpt4 book ai didi

c# - 预定义行上的文本

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:22:07 25 4
gpt4 key购买 nike

我有一条虚线 (PointF[])、一些 stringGraphics 对象。现在我想在我的线上绘制这个字符串。

这是一个例子:

enter image description here

是否有任何算法以最简单的方式做到这一点?

[编辑]好的,我已经尝试了@endofzero 的代码并稍微修改了它。这是整个解决方案(包括角度和距离计算):

private static void DrawBrokenString(Graphics g, IList<PointF> line, string text, Font font)
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.TextRenderingHint = TextRenderingHint.AntiAlias;
Pen pen = new Pen(Brushes.Black);

for (int index = 0; index < line.Count - 1; index++)
{
float distance = GetDistance(line[index], line[index + 1]);

if (text.Length > 0)
{
for (int cIndex = text.Length; cIndex >= 0; cIndex--)
{
SizeF textSize = g.MeasureString(text.Substring(0, cIndex).Trim(), font);
if (textSize.Width <= distance)
{
float rotation = GetAngle(line[index], line[index + 1]);

g.TranslateTransform(line[index].X, line[index].Y);
g.RotateTransform(rotation);

if (index != line.Count - 2)
{
g.DrawString(text.Substring(0, cIndex).Trim(), font, new SolidBrush(Color.Black),
new PointF(0, -textSize.Height));
}
else
{
g.DrawString(text.Trim(), font, new SolidBrush(Color.Black),
new PointF(0, -textSize.Height));
}

g.RotateTransform(-rotation);
g.TranslateTransform(-line[index].X, -line[index].Y);

text = text.Remove(0, cIndex);
break;
}
}
}
else
{
break;
}

g.DrawLine(pen, line[index].X, line[index].Y, line[index + 1].X, line[index + 1].Y);
}
}

private static float GetDistance(PointF p1, PointF p2)
{
return (float) Math.Sqrt(Math.Pow(p2.X - p1.X, 2) + Math.Pow(p2.Y - p1.Y, 2));
}

private static float GetAngle(PointF p1, PointF p2)
{
float c = (float) Math.Sqrt(Math.Pow(p2.X - p1.X, 2) + Math.Pow(p2.Y - p1.Y, 2));

if (c == 0)
return 0;

if (p1.X > p2.X)
return (float) (Math.Asin((p1.Y - p2.Y)/c)*180/Math.PI - 180);

return (float) (Math.Asin((p2.Y - p1.Y)/c)*180/Math.PI);
}

现在我只需要一件事就可以解决我的问题。我不希望字符串相互重叠。有任何想法吗?啊啊,当我们不能在路径上绘制字符串时(因为中断太多,它应该绘制在线上方(中间顶部)。

这是不需要的重叠示例:

enter image description here

最佳答案

这是一个简单的示例,说明如何在虚线后绘制文本。

    private static void DrawBrokenLine(PointF[] line, string text, Graphics g, Font font)
{
for (int index = 0; index < line.Length - 1; index++)
{
float distance = distanceBetween(line[index], line[index + 1]);

if (text.Length > 0)
{
for (int cIndex = text.Length; cIndex >= 0; cIndex--)
{
SizeF textSize = g.MeasureString(text.Substring(0, cIndex).Trim(), font);
if (textSize.Width <= distance)
{
float rotation = angleBetween(line[index], line[index + 1]);

g.TranslateTransform(line[index].X, line[index].Y);
g.RotateTransform(rotation);

g.DrawString(text.Substring(0, cIndex).Trim(), font, new SolidBrush(Color.Black),
new PointF(0, -textSize.Height));

g.RotateTransform(-rotation);
g.TranslateTransform(-line[index].X, -line[index].Y);

text = text.Remove(0, cIndex);
break;
}
}
}
else
break;
}
}

如果您希望它只在单词之间的空格处断开,则必须更改它在测量时缩短字符串的方式。

编辑

为了修复角上的文本重叠,我为其添加了一个计算:

    private static void DrawBrokenLine(PointF[] line, string text, Graphics g, Font font)
{
float lastOverlap = 0;

for (int index = 0; index < line.Length - 1; index++)
{
float distance = distanceBetween(line[index], line[index + 1]);

float angleOfLines = 180;
if (index < line.Length - 2)
{
angleOfLines = angleBetweenLines(line[index], line[index + 1], line[index + 2]);
}

if (text.Length > 0)
{
SizeF textSize = g.MeasureString(text, font);
float overlap = 0;
if (angleOfLines < 180)
{
if (angleOfLines <= 90)
{
overlap = (textSize.Height / 1.5f) / (
Convert.ToSingle(Math.Tan((angleOfLines / 2) * Math.PI / 180))
);
}
else
{
overlap = Convert.ToSingle(
Math.Sin(angleOfLines * Math.PI / 180) * (textSize.Height / 1.5f));
}
}

for (int cIndex = text.Length; cIndex >= 0; cIndex--)
{
textSize = g.MeasureString(text.Substring(0, cIndex).Trim(), font);

if (textSize.Width <= distance - overlap - lastOverlap) //notice the subtraction of overlap
{
float rotation = angleBetween(line[index], line[index + 1]);

g.TranslateTransform(line[index].X, line[index].Y);
g.RotateTransform(rotation);

g.DrawString(text.Substring(0, cIndex).Trim(), font, new SolidBrush(Color.Black),
new PointF(lastOverlap, -textSize.Height));

g.RotateTransform(-rotation);
g.TranslateTransform(-line[index].X, -line[index].Y);

text = text.Remove(0, cIndex);
break;
}
}

lastOverlap = overlap;
}
else
break;
}
}

private static float angleBetweenLines(PointF A, PointF B, PointF C)
{
float angle1 = 360 - angleBetween(A, B);
float angle2 = 360 - angleBetween(B, C);

if (angle1 < 0)
angle1 += 360;
if (angle2 < 0)
angle2 += 360;

float delta = 180 + angle1 - angle2;

if (delta < 0)
delta += 360;
if (delta > 360)
delta -= 360;

return delta;
}

enter image description here

我的示例有一个警告:如果您注意到,我将文本高度除以一个特殊数字。 MeasureString 没有返回准确的文本高度,我遇到了麻烦,所以我尝试手动更正这个问题。

关于在线上方绘制一个字符串(因为太多的中断),这取决于你想如何检测这种情况(什么构成太多,文本应该放在哪里,它应该是一个角度吗?)。也许如果您可以提供您所想到的这种情况的示例图像,这将有助于澄清。

关于c# - 预定义行上的文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13179492/

25 4 0
文章推荐: java - 有使用 Terracotta 开源的经验吗?
文章推荐: java - 在生产系统上详分割析 Tomcat 堆
文章推荐: java - 使用 Google Collections 创建弱多图
文章推荐: java - 在 XStream 中有更好的方法来编码/解码 JSON 和 Java 中的 List