【问题标题】:Creating another Graphics with different coordinates?创建另一个具有不同坐标的图形?
【发布时间】:2020-07-16 11:13:17
【问题描述】:

是否可以使用不同的坐标系从现有的Graphics 创建另一个Graphics?例如,假设黑色矩形是我在OnPaint() 中得到的Graphics 对象的ClipRectangle。如果我只想在蓝色矩形内绘制,我将不得不不断计算偏移量。也就是说,要在蓝色矩形中的逻辑点 (0,0) 处绘制,我必须添加 x 和 y 偏移量。这使得绘图代码变得复杂。

有没有办法使用上面的Graphics 创建某种虚拟Graphics,但使用不同的坐标系?类似下面的东西

//not actual code
var virtualG = Graphics.FromExistingGraphics(e.Graphics, 200/*x1*/, 200/*y1*/, 1000/*x2*/, 600/*y2*/);

//Doing the same thing as e.Graphics.DrawLine(pen, 200, 200, 400, 400) 
virtualG.DrawLine(pen, 0, 0, 200, 200); 

//Draws nothing, NOT the same as e.Graphics.DrawLine(pen, 1100, 200, 1200, 400)
//, because its outside of the virtualG's bounds.
virtualG.DrawLine(pen, 900, 0, 1000, 200); 

我想过用位图创建一个新的Graphics,在那里绘制,然后将位图从OnPaint复制到Graphics的指定位置,但这可能会很慢。

【问题讨论】:

  • Graphics.ScaleTransformMatrix.Scale(以及所有相关的转换)、Rectangle.Inflate(更多...)
  • 输出到Graphics 是输出的结束。但是您可以在此之前添加更多层,在不同的单元中操作,添加相机逻辑(在 2d 中也很有用),坐标转换,所需的抽象。因此,您可以拥有 2 个具有不同坐标系的平面,它们以某种方式定位在您的 2d/3d 世界中,并通过相机显示在屏幕上。
  • 您还可以检查Graphics.TransformPoints 方法(工作,嗯,非常快)。所有转换(使用 Matrix 或提供的辅助方法)都可以应用于 Graphics 对象和 GraphicsPath 对象。结合起来,这些允许构建许多不同的工具。不提及可应用于钢笔和画笔的变换(请参阅有关此的 GraphicsPath,使用钢笔进行变换)
  • 请注意:Graphics 对象不包含任何图形;它是一个工具,可让您绘制到相关位图上,包括控件的表面。系统需要在您无法控制的时候绘制所有控件的表面;因此,您要添加到这些表面的所有内容都必须从系统将调用的一个事件创建,即Paint 事件。只有 非持久性 图形操作(例如显示动态橡皮筋矩形)可以使用从 control.CreateGraphics() 获得的 Graphics 对象。无需绘图即可测量...
  • 另外:您不能缓存 Graphics 对象,但您可以存储和恢复当前设置,包括缩放和平移..

标签: c# winforms gdi+


【解决方案1】:

如果您不想进行任何缩放,而只是想将原点移动到 (200, 200),请按照前面的建议使用 TranslateTransform。如果您想剪裁该矩形之外的任何图形,请使用SetClip

这是一个示例,显示了在平移和剪切之前和之后绘制的同一组线。黑线在之前,而蓝线在之后(第二条蓝线被剪掉,因此不可见)。红色矩形显示剪辑区域:

代码:

public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();
    }

    public class Line
    {
        public Point ptA;
        public Point ptB;
        public void Draw(Graphics G, Color color)
        {
            using (Pen P = new Pen(color))
            {
                G.DrawLine(P, ptA, ptB);
            }
        }
    }

    private List<Line> Lines = new List<Line>();

    private void Form1_Load(object sender, EventArgs e)
    {
        Lines.Add(new Line() { ptA = new Point(0,0), ptB = new Point(200, 200)});
        Lines.Add(new Line() { ptA = new Point(900, 0), ptB = new Point(1000, 200) });
    }        

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        Graphics G = e.Graphics;
        G.Clear(Color.DarkGray);

        foreach(Line line in Lines)
        {
            line.Draw(G, Color.Black);
        }

        Rectangle rc = new Rectangle(new Point(200, 200), new Size(800, 400));
        G.DrawRectangle(Pens.Red, rc);
        G.SetClip(rc);

        G.TranslateTransform(rc.Left, rc.Top); // origin is now at (200, 200)

        foreach (Line line in Lines)
        {
            line.Draw(G, Color.Blue);
        }
    }

}

【讨论】:

    猜你喜欢
    • 2017-06-08
    • 1970-01-01
    • 1970-01-01
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    • 2021-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多