Моделируйте брызги

Как я могу моделировать брызги как краска окон? я думаю это случайные точки формирования данных, каково Ваше мнение?

6
задан andand 6 July 2010 в 15:41
поделиться

6 ответов

Да, я бы сказал, что он раскрашивает случайные пиксели в пределах определенного радиуса от точки выбора. Также, вероятно, существует временная задержка между окрашиванием одного пикселя и другого, потому что сегодня машины достаточно быстрые, чтобы иметь возможность раскрасить каждый возможный пиксель (пока радиус небольшой), прежде чем вы сможете отпустить кнопку мыши.

Кроме того, я думаю, что алгоритм, который использует Paint, может выбрать пиксель для рисования, даже если он уже был нарисован, поскольку иногда вы можете получить нарисованный круг с несколькими неокрашенными пикселями внутри.

5
ответ дан 10 December 2019 в 02:43
поделиться

Узор для аэрозольной краски будет полуслучайным. Если вы достанете баллончик Krylon и медленно проведете линию на стене, то в итоге получите широкую сплошную линию, переходящую в фон с градиентом по краям. Если распылять краску в одном месте в течение десяти секунд, вы получите большую точку в центре, в которой цвет полностью насыщен, с радиальным градиентом к фону.

Итак, ваши переменные для моделирования включают:

  • Время удержания "распылителя" (кнопка мыши)
  • Движение "баллончика" (мышь)
  • Скорость "баллончика" (быстрые движения делают светлую, ненасыщенную линию. Медленные движения делают толстую, насыщенную линию с градиентом)
  • Форма распыления: распыление концентрированное, как у аэрографа, или большое, как у баллончика?
  • "Расстояние": Как далеко "распылитель" находится от "холста"?
3
ответ дан 10 December 2019 в 02:43
поделиться

Думаю, трудно найти пример на C#. Ниже я привожу способ, с которого можно начать свой путь в этом направлении. Здесь я использую текстурную кисть.

private void Button1_Click(System.Object sender, System.EventArgs e)
{
    try
    {
        Bitmap image1 = (Bitmap)Image.FromFile(@"C:\temp\mybrush.bmp", true);

        TextureBrush t = new TextureBrush(image1);
        t.WrapMode = System.Drawing.Drawing2D.WrapMode.Tile;
        Graphics formGraphics = this.CreateGraphics();
        formGraphics.FillEllipse(t, new RectangleF(90.0F, 110.0F, 100, 100));
        formGraphics.Dispose();

    }
    catch (System.IO.FileNotFoundException)
    {
        MessageBox.Show("Image file not found!");
    }

}

как сказал Джесси, я думаю, вам нужно найти алгоритм для разбрасывания случайных пикселей.

-1
ответ дан 10 December 2019 в 02:43
поделиться

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

Есть несколько способов сделать это, и, вероятно, наиболее очевидным будет использование полярных координат для выбора случайной точки и последующего преобразования полярных координат в декартовы координаты (x, y). для рендеринга пикселя. Вот простой пример такого подхода. Для простоты я только что нарисовал простой эллипс 1x1 для каждой точки.

private Random _rnd = new Random();
private void Form1_MouseDown(object sender, MouseEventArgs e)
{      
  int radius = 15;

  using (Graphics g = this.CreateGraphics())
  {
    for (int i = 0; i < 100; ++i)
    {
      // Select random Polar coordinate
      // where theta is a random angle between 0..2*PI
      // and r is a random value between 0..radius
      double theta = _rnd.NextDouble() * (Math.PI * 2);
      double r = _rnd.NextDouble() * radius;

      // Transform the polar coordinate to cartesian (x,y)
      // and translate the center to the current mouse position
      double x = e.X + Math.Cos(theta) * r;
      double y = e.Y + Math.Sin(theta) * r;

      g.DrawEllipse(Pens.Black, new Rectangle((int)x - 1, (int)y - 1, 1, 1));
    }
  }
}

Кроме того, вы можете случайным образом выбрать координаты x, y из прямоугольника, который соответствует кругу распыления, и с помощью уравнения круга r ^ 2 = x ^ 2 + y ^ 2 проверить точку, чтобы определить, находится ли она внутри круга, если при этом вы случайным образом выбираете другую точку и снова проверяете, пока не получите точку, лежащую внутри круга. Вот краткий пример этого подхода

private Random _rnd = new Random();
private void Form1_MouseDown(object sender, MouseEventArgs e)
{      
  int radius = 15;
  int radius2 = radius * 2;

  using (Graphics g = this.CreateGraphics())
  {
    double x;
    double y;

    for (int i = 0; i < 100; ++i)
    {          
      do 
      {
        // Randomy select x,y so that 
        // x falls between -radius..radius
        // y falls between -radius..radius
        x = (_rnd.NextDouble() * radius2) - radius;
        y = (_rnd.NextDouble() * radius2) - radius;

        // If x^2 + y^2 > r2 the point is outside the circle
        // and a new point needs to be selected
      } while ((x*x + y*y) > (radius * radius));

      // Translate the point so that the center is at the mouse
      // position
      x += e.X;
      y += e.Y;

      g.DrawEllipse(Pens.Black, new Rectangle((int)x - 1, (int)y - 1, 1, 1));
    }
  }
}
2
ответ дан 10 December 2019 в 02:43
поделиться

Попробуйте использовать таймер

public partial class Form1 : Form
{
    int Radious = 5;
    Random _rnd = new Random();
    Timer T = new Timer();
    int InterVal = 1000;
    MouseEventArgs MEA = null;
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        T.Tick += (O, E) =>
        {
            StartSpray();
        };
        this.MouseDown += (O, E) =>
        {
            MEA = E;
            T.Interval = InterVal;
            T.Start();

         };
        this.MouseUp += (O, E) =>
        {
            T.Stop();
        };
    }
    private void StartSpray()
    {
        Point P = DrawPoint(Radious, MEA.X, MEA.Y);
        // Draw the point on any graphics area you can add the color or anything else
    }
    private Point DrawPoint(int Radious, int StatX, int StartY)
    {
        double theta = _rnd.NextDouble() * (Math.PI * 2);
        double r = _rnd.NextDouble() * Radious;
        Point P = new Point { X = StatX + Convert.ToInt32(Math.Cos(theta) * r), Y = StartY + Convert.ToInt32(Math.Sin(theta) * r) };
        return P;
    }      
}

, пожалуйста, измените Интервал и радиус.

0
ответ дан 10 December 2019 в 02:43
поделиться

Вы можете создать рисунок распыления различной интенсивности, выбрав некоторое количество (связанное с желаемой интенсивностью и разбросом) полярных координат. Для этого определите случайную полярную координату (ρ, θ) для каждой выборки следующим образом:

ρ выборка из N (0, 1): Используйте нормальное (гауссово) распределение для расстояние от точного центра вашей формы распыления. Я не помню, есть ли в библиотеке .NET нормальный генератор переменных. Если нет, вы можете создать его из генератора U (0, 1) .

θ, взятый из U (0, π): Пример угловой составляющей из Uniform Continuous Distribution . Без потери производительности или общности, вместо этого можно было бы выполнить выборку на U ( n π, m π) для n < m , но U (0, π), вероятно, подойдет для того, что вам нужно.

Декартовы координаты каждой выборки выражаются как (T x + S x ρ cos θ, T y + S y ] ρ sin θ) где (T x , T y ) - центр рисунка распыления, который вы хотите создать; S x и S y - это коэффициенты распространения, которые вы хотите иметь в направлениях x и y соответственно.

0
ответ дан 10 December 2019 в 02:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: