Search code examples
c#winformsgraphicsdrawingdrawing2d

Draw a Bucket with multiple liquids


I need to draw a bucket and fill it with two different liquid colours (yellow and red).

I have got so far in a hard coded version but I need to be able to specify the % of the bucket filled, so for instance 50% yellow then 10% red.

I have never done graphics in C# so any and all help on this is appreciated. I also need a cleaner way of doing the bottom of the bucket as it draws a black line ontop of the yellow in the below example. Current output of code

private Bitmap drawBucket2()
    {
        Bitmap img = new Bitmap(200, 200);


        using (Graphics g = Graphics.FromImage(img))
        {
            try
            {
                Pen penBlack = new Pen(Color.Black, 1);                    
                Pen penYellow = new Pen(Color.Yellow, 1);
                Brush brushYellow = new SolidBrush(Color.Yellow);
                Brush brushRed = new SolidBrush(Color.Red);
                Point[] pts = new Point[4];
                pts[0] = new Point(11, 115);
                pts[1] = new Point(170, 115);
                pts[2] = new Point(162, 180);
                pts[3] = new Point(21, 180); 

                g.FillEllipse(brushYellow, 11, 90, 160, 50);
                g.FillPolygon(brushYellow, pts);

                pts = new Point[3];
                pts[0] = new Point(21, 180);
                pts[1] = new Point(91, 195);
                pts[2] = new Point(162, 180);
                g.FillClosedCurve(brushYellow, pts);

                /*outline */
                g.DrawEllipse(penBlack, 2, 10, 180, 50);
                g.DrawLine(penBlack, 1, 35, 21, 180);
                g.DrawLine(penBlack, 182, 35, 162, 180);
                pts = new Point[3];
                pts[0] = new Point(21, 180);
                pts[1] = new Point(91, 195);
                pts[2] = new Point(162, 180);
                g.DrawClosedCurve(penBlack, pts);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }
        return img;
    }

Solution

  • I have manged to solve this one, I am posting the code here to see if anyone can still improve it before I accept this as the answer.

    private int[] getPoints(int perc)
        {
            int[] pts;// = new int[4];
            double x_offset_left = (35 - 21);
            x_offset_left = x_offset_left / 100;
            double height = 135;
            double width = 178;
            double x1, x2, y1, y2;
    
            int margin_top = 66;//68
            int margin_left = 21;
    
            y1 = ((height / 100) * perc) + margin_top;
            y2 = y1;
    
            x1 = margin_left + (x_offset_left * perc);
            x2 = width - (x_offset_left * perc);
    
            pts = new int[4] { Convert.ToInt32(x1), Convert.ToInt32(y1), Convert.ToInt32(x2), Convert.ToInt32(y2) };
            return pts;
        }
        private Bitmap drawBucket2(int yellowval, int redval, int overval)
        {
            Bitmap img = new Bitmap(200, 221);
            using (Graphics g = Graphics.FromImage(img))
            {
                Brush bRed = new SolidBrush(Color.FromArgb(50, Color.DarkRed));
                Brush bYellow = new SolidBrush(Color.FromArgb(75, Color.Gold));
                Brush bBlue = new SolidBrush(Color.FromArgb(50, Color.Blue));
    
                GraphicsPath gp = new GraphicsPath();
                Region r;
                Point[] points_yellow;
                Point[] points_red;
    
                int percentage = 0;
                int[] pts;
                int[] pts_full = getPoints(100);
                int[] pts_min = getPoints(1);
    
                #region "Yellow Region"
                // bottom curve
                percentage = yellowval;
                pts = getPoints(100 - percentage);
    
                points_yellow = new Point[3];
                points_yellow[0] = new Point(pts_full[0], pts_full[3]);
                points_yellow[1] = new Point(((pts_full[2] - pts_full[0]) / 2 + pts_full[0]), (pts_full[1] + 15));
                points_yellow[2] = new Point(pts_full[2], pts_full[3]);
                gp.AddCurve(points_yellow, 0.7f);
                //Console.WriteLine("curve : (" + points_yellow[0].X + ", " + points_yellow[0].Y + "), " + " (" + points_yellow[1].X + ", " + points_yellow[1].Y + "), " + " (" + points_yellow[2].X + ", " + points_yellow[2].Y + ")");
    
                //polygon
                points_yellow = new Point[4];
                points_yellow[0] = new Point(pts[0], pts[1]);
                points_yellow[1] = new Point(pts[2], pts[1]);
                points_yellow[2] = new Point(pts_full[2], pts_full[1]);
                points_yellow[3] = new Point(pts_full[0], pts_full[1]);
                gp.AddPolygon(points_yellow);
                //Console.WriteLine("Poly : (" + points_yellow[0].X + ", " + points_yellow[0].Y + "), " + " (" + points_yellow[1].X + ", " + points_yellow[1].Y + "), " + " (" + points_yellow[2].X + ", " + points_yellow[2].Y + "), " + " (" + points_yellow[3].X + ", " + points_yellow[3].Y + ")");
    
                // top curve
                points_yellow = new Point[3];
                points_yellow[0] = new Point(pts[0], pts[1]);
                points_yellow[1] = new Point(((pts[2] - pts[0]) / 2 + pts[0]), (pts[1] + 15));
                points_yellow[2] = new Point(pts[2], pts[1]);
                gp.AddCurve(points_yellow, 0.7f);
                //Console.WriteLine("curve : (" + points_yellow[0].X + ", " + points_yellow[0].Y + "), " + " (" + points_yellow[1].X + ", " + points_yellow[1].Y + "), " + " (" + points_yellow[2].X + ", " + points_yellow[2].Y + ")");
    
                r = new Region(gp);
                g.FillRegion(bYellow, r);
                #endregion     
    
                #region "Red Region"
                gp = new GraphicsPath();
                percentage = yellowval + redval;
    
                // Bottom Curve
                gp.AddCurve(points_yellow, 0.7f);
                //Console.WriteLine("curve : (" + points_yellow[0].X + ", " + points_yellow[0].Y + "), " + " (" + points_yellow[1].X + ", " + points_yellow[1].Y + "), " + " (" + points_yellow[2].X + ", " + points_yellow[2].Y + ")");
    
                // polygon
                int[] pts_yel = new int[3]{pts[0], pts[1], pts[2]};
                pts = getPoints(100 - percentage);
                points_red = new Point[4];
                points_red[0] = new Point(pts[0], pts[1]);
                points_red[1] = new Point(pts[2], pts[1]);
                points_red[2] = new Point(pts_yel[2], pts_yel[1]);
                points_red[3] = new Point(pts_yel[0], pts_yel[1]);
                gp.AddPolygon(points_red);
    
                // Top Curve
                points_red = new Point[3];
                points_red[0] = new Point(pts[0], pts[1]);
                points_red[1] = new Point(((pts[2] - pts[0]) / 2 + pts[0]), (pts[1] + 12));
                points_red[2] = new Point(pts[2], pts[1]);
                gp.AddCurve(points_red, 0.7f);
    
                r = new Region(gp);
                g.FillRegion(bRed, r);
                #endregion
    
                #region "Overflow"
                if (overval > 0)
                {
                    gp = new GraphicsPath();
                    gp.AddEllipse(16, 10, 165, 32);
                    r = new Region(gp);
                    g.FillRegion(bBlue, r);
                }
                #endregion
                r.Dispose();
                gp.Dispose();
                bRed.Dispose();
                bYellow.Dispose();
                bBlue.Dispose();            
            }
            return img;
        }
    
        private void fillBucket(int Yellowperc, int Redperc, int Overperc)
        {
            pictureBox1.Image = null;
            pictureBox1.Image = drawBucket2(Yellowperc, Redperc, Overperc);
        }