0

我需要画一个桶并用两种不同的液体颜色(黄色和红色)填充它。

到目前为止,我已经获得了硬编码版本,但我需要能够指定填充桶的百分比,例如 50% 黄色然后 10% 红色。

我从来没有在 C# 中做过图形,所以对此的任何和所有帮助表示赞赏。我还需要一种更清洁的方式来处理桶的底部,因为它在下面的示例中在黄色的顶部画了一条黑线。 当前代码输出

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;
    }
4

3 回答 3

1

我已经设法解决了这个问题,我在这里发布代码,看看是否有人仍然可以改进它,然后我接受这个作为答案。

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);
    }
于 2012-03-01T15:22:12.667 回答
1

“液体”是两个椭圆,中间有空间填充,因此您需要计算的只是高度和左右位置,具体取决于液体量并从下到上绘制(即黄色然后红色)

// Upper Elipse and top Points for the filled center
y = HeightOfBottom + (FullHeight * (StartAmountFloat + AmountFloat))
x1 = Middle - (DiffenceOfDiameter * (StartAmountFloat + AmountFloat))
x2 = Middle + (DiffenceOfDiameter * (StartAmountFloat + AmountFloat))

// Lower Elipse and bottom Points for the filled center
y = HeightOfBottom + (FullHeight * StartAmountFloat)
x1 = Middle - (DiffenceOfDiameter * StartAmountFloat)
x2 = Middle + (DiffenceOfDiameter * StartAmountFloat)

底部也应该是椭圆的下半部分。

于 2012-02-29T17:02:19.437 回答
1

好的,没有任何代码给你,但我可以给你一个大致的工作流程来实现这一点。基本上你想把你的物体画回前面,所以我会按这个顺序画

  1. 将桶的底部画成椭圆
  2. 将液体的底部绘制为相同大小但高一个像素的椭圆
  3. 现在在上面的每个 Y 像素处绘制椭圆,直到达到所需的百分比,其中像素的最终数量由(桶底)+((桶顶)-(桶底)*(百分比 / 100))。您将需要在某些点加宽椭圆。这将创建一个别名效果,但别担心,我们接下来将在它上面绘制
  4. 最后画出桶的侧面和顶部。如果您选择合适的线条粗细,您可以厚颜无耻地隐藏您闯入荣耀之路的事实:)

最后一件事,我建议进行大量的试验和错误。你做的越多,它就会变得越容易!祝你好运

于 2012-02-29T17:04:26.783 回答