用c#裁剪矩形

Posted

技术标签:

【中文标题】用c#裁剪矩形【英文标题】:Clipping rectangle with c# 【发布时间】:2012-11-12 06:21:26 【问题描述】:

我有一些代码可以生成带有随机角度的矩形:

但我需要通过父边框切割子矩形,例如

我的代码:http://pastebin.com/b6ry8j68

谁能帮我解决算法问题?

【问题讨论】:

如何确定矩形的父子关系? 【参考方案1】:

使用SetClip 属性很容易做到。

基本上你需要添加这段代码:

           if (!pre_defined)
            
                g.SetClip(new Rectangle(x, y, 600, 300));
            

就在画线命令之前。其中 x 和 y 是父矩形的坐标。这很容易从您的功能中获得。

这是一个完整的功能:

  public void drawRectangle(double Width, double Height, int A, bool pre_defined)
    
        Graphics g = pictureBox1.CreateGraphics();
        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;

        System.Drawing.Brush brush = new System.Drawing.SolidBrush(Color.FromArgb(r.Next(0, 251), r.Next(0, 251), r.Next(0, 251)));
        Pen myPen = new Pen(brush, 2);
        myPen.Width = 2;
        int x = center.X;
        int y = center.Y;
        //top left
        P[0] = new PointF((float)Math.Round(x + (Width / 2) * Math.Cos(A) + (Height / 2) * Math.Sin(A)), (float)Math.Round(y - (Height / 2) * Math.Cos(A) + (Width / 2) * Math.Sin(A)));
        //top right
        P[1] = new PointF((float)Math.Round(x - (Width / 2) * Math.Cos(A) + (Height / 2) * Math.Sin(A)), (float)Math.Round(y - (Height / 2) * Math.Cos(A) - (Width / 2) * Math.Sin(A)));
        //bottom left
        P[2] = new PointF((float)Math.Round(x + (Width / 2) * Math.Cos(A) - (Height / 2) * Math.Sin(A)), (float)Math.Round(y + (Height / 2) * Math.Cos(A) + (Width / 2) * Math.Sin(A)));
        //bottom right
        P[3] = new PointF((float)Math.Round(x - (Width / 2) * Math.Cos(A) - (Height / 2) * Math.Sin(A)), (float)Math.Round(y + (Height / 2) * Math.Cos(A) - (Width / 2) * Math.Sin(A)));
        if (!pre_defined)
        
            g.SetClip(new Rectangle(50, 50, 600, 300));
        
        g.DrawLine(myPen, P[0], P[1]);
        g.DrawLine(myPen, P[1], P[3]);
        g.DrawLine(myPen, P[3], P[2]);
        g.DrawLine(myPen, P[2], P[0]);
    

编辑: 这不是一个完整的示例,因为这个示例只会将 Clip 设置为父宽度和高度。您需要修改函数以提供每个元素的宽度和高度。但是现在我正在查看您提供的图片,它看起来比我想象的要复杂。 您最终可能会存储所有随机值的数组,然后按大小对其进行排序,然后绘制所有元素。

【讨论】:

是的,它确实有效,但这是大学任务,我认为我必须在没有任何像 setClip 这样的助手的情况下实现实现 这么好的答案。经常遇到这个问题。【参考方案2】:

这是一个老问题,但有人可能仍需要一个简单的解决方法。

最简单的解决方案是在定义尺寸的图形表面上绘制这些矩形,这样任何超出该尺寸或其边框的绘制路径都会被自动剪裁。从已定义大小的位图创建图形对象会将任何内容限制为该大小。之后可以将位图绘制到您的屏幕图形对象上,以便直接绘制到屏幕上。

请注意,此过程也用作双缓冲技术,有助于减少直接在屏幕上绘制时的闪烁效果。

以下示例显示了如何设置大小的图形对象。

见:Information about PaintEventArgs overriding

    ///<summary>
    ///  Most common method for painting to the screen. 
    ///  Available on all control class objects by overriding 
    ///  the OnPaint method of the base class.
    ///</summary>
    protected virtual new void OnPaint(PaintEventArgs e)
    
        // We assume here that your control's screen graphics 
        // area is at least 500x400 to see the full results 
        // otherwise please resize your form or control to accommodate

        // Define your parent border size
        Size ParentBorder = new Size(400, 300);

        // Initialize a new bitmap having a size of ParentBorder and set 
        // it to the screen's pixel format. Setting the bitmap to the 
        // screens pixel format can save many milliseconds in processing 
        // due to pixel size conversions otherwise required 
        Bitmap Bmp = new Bitmap(ParentBorder.Width, ParentBorder.Height, Graphics.FromHwnd(IntPtr.Zero));

        // Next we create a graphics object tied to our bitmap for 
        // drawing our rectangles within a defined border
        Graphics BmpGfx = Graphics.FromImage(Bmp);

        //
        // Draw your rectangles here! A sample is below includes painting 
        // to the screen to illustrate this process
        //
        //
        // Rotate first rectangle 20 or transform as needed :)
        BmpGfx.RotateTransform(20);
        //
        // Sample 1: This one just shows a red rectangle near the center 
        // of the ParentBorder graphics object
        BmpGfx.DrawRectangle(new Pen(Color.Red), new Rectangle(new Point(100, -20), new Size(200, 200)));
        //
        // Reset back to normal transform
        BmpGfx.ResetTransform();
        //
        // Rotate second rectangle 60
        BmpGfx.RotateTransform(60);
        //
        // Sample 2: This one just shows a cropped blue rectangle at 
        // the borders
        BmpGfx.DrawRectangle(new Pen(Color.Blue), new Rectangle(new Point(145, -200), new Size(300, 300)));
        //
        // Reset back to normal transform for drawing a nice ParentBorder
        BmpGfx.ResetTransform();
        //
        // Border: This one just draws an Orange border around the ParaentBorder 
        // of the Bmp graphics object
        BmpGfx.DrawRectangle(new Pen(Color.Orange), new Rectangle(Point.Empty, new Size(Bmp.Width - 1, Bmp.Height - 1)));


        // Finally put your drawing to the screen. 50 points left and top so 
        // you can see the border and that nothing exceeds that ParaentBorder
        e.Graphics.DrawImage(Bmp, new Point(50,50));

        // Save your BMP to a file if you prefer or to "preserve the graphics" 
        // place the bmp in global scope (a global variable just don't forget 
        // to dispose when no longer needed)

        // Please dispose of your goods as variable objects not inline like 
        // done above to keep the GC happy of course. The below method ensures
        // resources are fully released for immediate cleanup by the GC. 
        Bmp.Dispose();
        Bmp = null;
        BmpGfx.Dispose();
        BmpGfx = null;
    

【讨论】:

以上是关于用c#裁剪矩形的主要内容,如果未能解决你的问题,请参考以下文章

Android 用Canvas画textviewbitmap矩形(裁剪)椭圆线点弧

矩形裁剪算法_pyopengl

将方形 UIImage 裁剪为圆角矩形

ArcGIS如何从矢量图剪切出一个矩形区域出来?

裁剪区域不是矩形时裁剪图像

当图片大于矩形时,计算图片裁剪的坐标矩形