【问题标题】:Drawing text on reversed Y Axis在反向 Y 轴上绘制文本
【发布时间】:2014-09-28 05:48:00
【问题描述】:

我正在编写一个可视化应用程序:它从 XML 加载建筑几何图形并将其绘制在屏幕上。 建筑物由矩形房间组成,其中很多 - 所以我想在上面画上他们的名字。

我使用this 教程在我的表单中翻转 Y 轴,因为构建存储在笛卡尔坐标中的数据。并将它们全部转换为经典的 Windows“y 成长”系统,而绘图看起来很奇怪。
我还需要缩放并将我的“场景”翻译到左下角。
而且,我最后的痛苦,我需要再次翻转我的文字 - 因为它也会翻转!

正如tutorial 所说,我需要:

  1. 翻转 Y 轴、缩放并将场景移动到所需位置
  2. 在笛卡尔坐标系中绘制建筑几何体(只是矩形)
  3. 返回“Y 向下增长”系统,再次缩放和移动
  4. 在这个“经典”系统中绘制文本

但文字坐标无效!
它们从正确的位置向下移动 :(

所以这是我的问题 - 如何正确计算 Windows 窗体对象中的新文本坐标

void VisualizerForm_Paint(object sender, PaintEventArgs e)
{
    // Setup graphics output settings
    var g = e.Graphics;
    g.Clear(Color.White);
    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
    g.PageUnit = GraphicsUnit.Pixel;
    
    // Move coordinate system center to the bottom left corner,
    // scale it to user-defined scale value and flip Y axis (mul it scale to -1)
    g.ScaleTransform(m_scale, -m_scale, MatrixOrder.Append);
    g.TranslateTransform(50, Height - 50, MatrixOrder.Append);
    
    // ... Draw some complex building geometry ...
    
    // Draw building room
    var customPen = new Pen(Color.Black, 1.0f / g.DpiX);
    var rect = new RectangleF(box.X1, box.Y1, (box.X2 - box.X1), (box.Y2 - box.Y1));
    g.DrawRectangle(customPen, box.X1, box.Y1, (box.X2 - box.X1), (box.Y2 - box.Y1));

    GraphicsState gs = g.Save();
    
    // First reset transform matrix
    g.ResetTransform();
    // Then again scale and move scene, but now with classic down-incresed Y axis
    g.ScaleTransform(m_scale, m_scale, MatrixOrder.Append);
    g.TranslateTransform(50, Height - 50, MatrixOrder.Append);
    
    // All Y coords now must be inverted :/ *sigh*
    box.Y1 *= -1.0f;
    box.Y2 *= -1.0f;
    rect = new RectangleF(box.X1, box.Y1, Math.Abs(box.X2 - box.X1), Math.Abs(box.Y2 - box.Y1));

    // FIXME: This text is drawing in incorrect place
    var fnt = new Font("Arial", 40f / g.DpiX, FontStyle.Bold, GraphicsUnit.Pixel);
    g.DrawString("ID: " + box.Id, fnt, Brushes.Black, rect, stringFormat);

    g.Restore(gs);
}

【问题讨论】:

    标签: c# .net winforms drawing gdi+


    【解决方案1】:

    试试这个:

    void DrawDigonalString(Graphics G, string S, Font F, Brush B, PointF P, int Angle)
    {
        SizeF MySize = G.MeasureString(S, F);
        G.TranslateTransform(P.X + MySize.Width / 2, P.Y + MySize.Height / 2);
        G.RotateTransform(Angle);
        G.DrawString(S, F, B, new PointF(-MySize.Width / 2, -MySize.Height / 2));
        G.RotateTransform(-Angle);
        G.TranslateTransform(-P.X - MySize.Width / 2, -P.Y- MySize.Height / 2);
    }
    

    【讨论】:

    • 通过调整翻译(g.TranslateTransform(50, Height - 100, MatrixOrder.Append) 你的功能很好,谢谢。我这样称呼它:DrawDigonalString(g, "ID: " + box.Id, fnt, Brushes.Black, new PointF(box.X1, -box.Y1), 0)。P.S. 你能简单解释一下它是如何工作的吗?
    • 我只发现了一个问题:文本和矩形的缩放方式不同。 IE。带有小比例值的文本从它的父矩形中“跳出”
    【解决方案2】:

    我终于明白了!
    下面的类在 Y 反转场景中绘制带有指定文本的矩形。
    文本自动缩放以适合实际矩形大小。享受:)

    class RectangleWithText
    {
        RectangleF m_extent = new RectangleF();
        string m_text = "";
    
        Font m_textFont = null;
        RectangleF m_textRect = new RectangleF();
    
        public RectangleWithText( RectangleF extent, string text )
        {
            m_extent = extent;
            m_text = text;
        }
    
        public void Draw( Graphics g )
        {
            var dashedGrayPen = new Pen( Color.Gray, 1.0f / g.DpiX ) { DashStyle = DashStyle.Dash };
            var brownPen = new Pen( Color.Brown, 1.0f / g.DpiX );
    
            // Draw rectangle itself
            g.DrawRectangle( brownPen, m_extent.X, m_extent.Y, m_extent.Width, m_extent.Height );
    
            // Draw text on it
            var extentCenter = new PointF( ( m_extent.Left + m_extent.Right ) / 2, ( m_extent.Bottom + m_extent.Top ) / 2 );
            DrawText( g, m_text, extentCenter, m_extent );
    
            }
        }
    
        private void DrawText( Graphics g, string text, PointF ptStart, RectangleF extent )
        {
            var gs = g.Save();
    
            // Inverse Y axis again - now it grow down;
            // if we don't do this, text will be drawn inverted
            g.ScaleTransform( 1.0f, -1.0f, MatrixOrder.Prepend );
    
            if ( m_textFont == null )
            {
                // Find the maximum appropriate text size to fix the extent
                float fontSize = 100.0f;
                Font fnt;
                SizeF textSize;
                do
                {
                    fnt = new Font( "Arial", fontSize / g.DpiX, FontStyle.Bold, GraphicsUnit.Pixel );
                    textSize = g.MeasureString( text, fnt );
                    m_textRect = new RectangleF( new PointF( ptStart.X - textSize.Width / 2.0f, -ptStart.Y - textSize.Height / 2.0f ), textSize );
    
                    var textRectInv = new RectangleF( m_textRect.X, -m_textRect.Y, m_textRect.Width, m_textRect.Height );
                    if ( extent.Contains( textRectInv ) )
                        break;
    
                    fontSize -= 1.0f;
                    if ( fontSize <= 0 )
                    {
                        fontSize = 1.0f;
                        break;
                    }
                } while ( true );
    
                m_textFont = fnt;
            }
    
            // Create a StringFormat object with the each line of text, and the block of text centered on the page
            var stringFormat = new StringFormat()
            {
                Alignment = StringAlignment.Center,
                LineAlignment = StringAlignment.Center
            };
            g.DrawString( text, m_textFont, Brushes.Black, m_textRect, stringFormat );
    
            g.Restore( gs );
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-02-08
      • 1970-01-01
      • 2016-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多