Wolfgang
Wolfgang

Reputation: 254

Clipping rectangle with c#

I have some code whiсh generate rectangles wшth random angle:

enter image description here

But i need cut children rectangle by parent border, e.g

enter image description here

My code: http://pastebin.com/b6ry8j68

Can anyone help me with algo?

Upvotes: 5

Views: 7585

Answers (2)

RAS
RAS

Reputation: 3385

It's pretty easy to do with SetClip Property.

Basically you need to add this code:

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

right before drawline commands. where x and y are coordinates of your parent rectangular. which is easy to get from your function.

this is complete function that works:

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

EDIT:
this is not a complete example, since this one will only set Clip to parent width and height. You need to modify your function to provide width and height of each element. But now I'm looking at the picture you provided and it looks more complicated than I thought.
You will probably end up storing array of all random values and that ordering it by size and then drawing all of the elements.

Upvotes: 5

Jamie
Jamie

Reputation: 25

This is an old question yet someone may still need a simple workaround.

The simplest solution is draw these rectangles on a graphics surface of a defined size such that any drawing paths that extends beyond that size or its border is automatically clipped. Creating graphics object from a bitmap of a defined size constrains anything to that size. After which the bitmap can be drawn to your screen graphics object for painting directly to screen.

Note that this process is also used as double buffering technique which helps to reduce flicker effects when painting directly to the screen.

The following example shows how to setup the sized graphics object.

See: 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;
    }

Upvotes: 0

Related Questions