2017-05-29 68 views
0

我想把一个标签(字符串)放在用户创建的多边形的中心。我检查了Graphics类的可用方法,但我只找到了带字符串,字体和矩形的DrawString方法。问题是我正在使用一个多边形。并且没有DrawPolygon重载,它将一个字符串作为参数。Polygon上的中心文本

// 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

你想在哪里绘制你的字符串?多边形内部或外部?...居中或沿着边缘?给我们一些关于如何计算点和/或绘制多边形的代码,然后解释或模拟如何绘制字符串。移动和旋转图形表面非常简单,以便您的字符串与多边形对齐;我们只需要更多的细节。 –

+0

嗨,我编辑了我的原始文章,以显示我迄今为止所做的工作。我想要将字符串绘制在多边形的中心内部。 – Gene

+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 
|  |_____________ 
|      | 
|      | 
|______________________| 

有关如何将其移入内部的任何想法?

0

这里是你如何能做到的,但要注意与真正棘手的形状不会有一个空间,包含文本,或者即使有可能比较难找..

你已经知道如何确定文本适合的大小。

我们接下来需要的是一个测试,看看我们的边界矩形是否包含在多边形中。

这里是一个,这使得使用GraphicsPathsRegions ..:

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个方向或忽略了一些应该是简单的适应..:

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呈红色。 enter image description here

这是创建测试台代码:

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)); 

当然,你可能要向下搜索只在第一个,然后向上,再向左,再向右,然后或从不对角等。