我正在尝试将标签(字符串)放在用户创建的多边形的中心。我检查了Graphics类上的可用方法,但我只找到了DrawString方法,该方法接受字符串,Font和Rectangle。问题是我正在使用多边形。并且没有DrawPolygon重载,它将字符串作为参数。
// Get the highest and lowest of both axis to
// determine the width and height of the polygon
int _lowestX = _slot.Min(o => o.X);
int _highestX = _slot.Max(o => o.X);
int _lowestY = _slot.Min(o => o.Y);
int _highestY = _slot.Max(o => o.Y);
// Draw the polygon
e.Graphics.FillPolygon(Brushes.White, _slot.ToArray()); // _slot is a list of points
e.Graphics.DrawPolygon(Pens.Blue, _slot.ToArray());
Font _font = new Font(FontFamily.GenericSansSerif, _highestX - _lowestX, FontStyle.Regular);
SizeF _textSize = e.Graphics.MeasureString("Slot 1", _font);
// My attempt at drawing the text using the DrawString method
// by trying to mock a rectangle using the height and width of the polygon
e.Graphics.DrawString("Slot 1", _font, new SolidBrush(Color.Black), (_highestX - _lowestX - _textSize.Width) / 2, 0);
有关该怎么做的任何建议?
提前致谢。
答案 0 :(得分:1)
我试图找到多边形的所有X和Y的平均值。然后在平均值上减去字符串减去文本的宽度或高度除以2。到目前为止,它现在正在中间显示文本。
这是我更新的代码
int _avgX = _slot.Sum(o => o.X) / _slot.Count;
int _avgY = _slot.Sum(o => o.Y) / _slot.Count;
e.Graphics.FillPolygon(Brushes.White, _slot.ToArray());
e.Graphics.DrawPolygon(Pens.Blue, _slot.ToArray());
Font _font = new Font(FontFamily.GenericSansSerif, 8, FontStyle.Regular);
SizeF _textSize = e.Graphics.MeasureString("Slot 1", _font);
e.Graphics.DrawString("Slot 1", _font, new SolidBrush(Color.Black), _avgX - (_textSize.Width / 2), _avgY - (_textSize.Height / 2));
这仅适用于凸多边形。在凹多边形(例如L形)上,文本将像这样在多边形外部绘制。
__________
| |
| |
| |
| | Slot 1
| |_____________
| |
| |
|______________________|
有关如何将其移入内部的任何想法?
答案 1 :(得分:0)
以下是如何做到这一点,但请注意,如果形状非常棘手,则不会有空间来包含文本,或者即使有可能很难找到它。
您已经知道如何确定文本适合的大小。
我们接下来需要的是测试我们的边界矩形是否包含在多边形中。
这是一个使用GraphicsPaths
和Regions
..:
static bool PathContainsRect(GraphicsPath gp, RectangleF rect, Graphics g)
{
Region rPath0 = new Region(gp);
Region rPath1 = new Region(gp);
Region rRect = new Region(rect);
rPath1.Union(rRect);
rPath1.Exclude(rPath0);
return rPath1.IsEmpty(g);
}
您需要输入要用于绘图的Graphics
对象。
接下来,您需要一些算法来查找要测试的点。最佳选择取决于您的多边形。
这是一个简单的:它从中心开始,并在4个方向上逐步移动:左上角,上下,右下角,下角。如果你想添加其他4个方向或省略一些,那么它应该很容易适应..:
static Point NearestCenterLocation(GraphicsPath gp, Size sz, Graphics g, int step)
{
RectangleF rB = gp.GetBounds();
Point center = new Point((int)(rB.Left + rB.Width / 2f - sz.Width / 2),
(int)(rB.Top + rB.Height /2f - sz.Height/ 2));
Point ncTL = center; Point ncBR = center;
Point ncT = center; Point ncB = center;
RectangleF nTLRect = new RectangleF(center, sz);
RectangleF nBRRect = new RectangleF(center, sz);
RectangleF nTRect = new RectangleF(center, sz);
RectangleF nBRect = new RectangleF(center, sz);
Point hit = Point.Empty;
do
{
ncTL.Offset(-step, -step);
ncBR.Offset(step, step);
ncT.Offset(-step, 0);
ncB.Offset(step, 0);
nTLRect = new RectangleF(ncTL, sz);
nBRRect = new RectangleF(ncBR, sz);
nTRect = new RectangleF(ncT, sz);
nBRect = new RectangleF(ncB, sz);
hit = (PathContainsRect(gp, nTLRect, g) && ncTL.X > 0) ? ncTL : hit;
hit = (PathContainsRect(gp, nBRRect, g) ) ? ncBR : hit;
hit = (PathContainsRect(gp, nTRect, g)) ? ncT : hit;
hit = (PathContainsRect(gp, nBRect, g) ) ? ncB : hit;
g.DrawRectangle(Pens.Green, Rectangle.Round(nTLRect)); // test only
g.DrawRectangle(Pens.Blue, Rectangle.Round(nBRRect)); // test only
g.DrawRectangle(Pens.Cyan, Rectangle.Round(nTRect)); // test only
g.DrawRectangle(Pens.Khaki, Rectangle.Round(nBRect)); // test only
} while (hit == Point.Empty);
g.DrawRectangle(Pens.Tomato, new Rectangle(center, sz)); // test only
return hit;
}
它包含绘图调用,以显示它如何在四个方向上搜索,直到找到第一个匹配。中心和结果Rectangles
为红色。
这是创建测试台的代码:
Size sz = new Size(70, 35);
GraphicsPath gp1 = new GraphicsPath();
gp1.FillMode = FillMode.Winding;
gp1.AddRectangle(new Rectangle(0, 0, 350, 120));
gp1.AddRectangle(new Rectangle(0, 0, 120, 300));
gp1.AddRectangle(new Rectangle(250, 0, 100, 300));
Point px = NearestCenterLocation(gp1, sz, g , 10);
using (SolidBrush brush = new SolidBrush(Color.FromArgb(66, Color.Gold)))
g.FillPath(brush, gp1);
g.DrawRectangle(Pens.Tomato, new Rectangle(px, sz));
当然,您可能只想先搜索,然后再向上搜索,然后向左搜索,然后向右搜索,或者从不对角搜索等。