2012-02-29 3 views
0

Мне нужно нарисовать ведро и наполнить его двумя разными жидкостями (желтый и красный).Нарисуйте ковш с несколькими жидкостями

У меня есть до сих пор в жесткой кодированной версии, но мне нужно указать% заполненного ковша, например, на 50% желтый, а затем на 10% красный.

Я никогда не делал графики на C#, поэтому любая помощь по этому поводу ценится. Мне также нужен более чистый способ сделать нижнюю часть ковша, поскольку он рисует черную линию поверх желтого в приведенном ниже примере. 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; 
    } 
+0

Это домашнее задание? – om471987

+0

Блок 'catch' совершенно бессмыслен. Если выбрано исключение, вы уже * видите сообщение об этом. Нет причин, чтобы поймать его и показать свой собственный ящик сообщений. Кроме того, вы никогда не должны ловить и проглатывать исключения, о которых вы ничего не можете сделать. –

+0

Следующая проблема заключается в том, что вы не удаляете объекты GDI +, которые вы создаете (ручка, кисть и т. Д.), Когда вы закончите с ними до завершения метода. ** Вы абсолютно должны называть 'Dispose' на любом объекте, который реализует' IDisposable' **, иначе у вас будет утечка памяти. (Да, финализатор бла-бла, вам все равно. Вам нужно привыкнуть к удалению этих объектов.) Лучший способ сделать это - обернуть их создание в блок «using». Кроме того, вы можете просто вызвать свой метод 'Dispose' вручную в конце вашей функции. –

ответ

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

В «жидкости» два elipses с пространством между ними заполнены, поэтому все, что вам нужно вычислить это высоты и левые и правые позиции в зависимости от количества жидкости и рисовать снизу вверх (т.е. желтый, затем красный)

// 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) 

Нижняя часть должна быть нижней половиной элипса.

+0

Спасибо, Стефан, я совершенно не знаком с GD на C#, как бы это реализовать? – Neo

1

Хорошо, у вас нет кода для вас, но я могу дать вам приблизительный рабочий процесс, чтобы достичь этого. В основном вы хотите сделать свои объекты обратно на фронт, так что я бы рисовать в таком порядке

  1. Нарисовать дно ковша в виде эллипса
  2. Нарисуйте нижнюю часть жидкости, как ellpise того же размера , но на один пиксель выше
  3. Теперь нарисуйте эллипсы на каждом Y-пикселе выше, пока не будет достигнут желаемый%, где конечное число пикселей вычисляется (нижней частью ведра) + ((верхняя часть ковша) - (нижняя часть ковша) * (в процентах/100)). Вам нужно будет расширить эллипс в определенных точках. Это создаст эффект aliased, но не волнуйтесь, мы собираемся нарисовать его дальше.
  4. Наконец, нарисуйте стороны ведра и верха. Если вы выберете подходящую толщину линии, вы можете скрыть скрытый факт, что вы взломали свой путь к славе :)

Последнее, что я предложил бы для проведения проб и ошибок. тем больше вы это сделаете, тем легче это станет! Удачи

+0

Большое спасибо за хедз-ап, это странно, поскольку вы всегда нарисовываете сверху вниз в реальной жизни, я запомню, чтобы переупорядочить заказ. – Neo

Смежные вопросы