模拟喷雾

发布于 2024-09-03 02:34:06 字数 42 浏览 3 评论 0原文

我怎样才能模拟像窗户油漆一样的喷涂?我认为它会随机创建点,您有何看法?

How can i simulate a spray like windows paint ? i think it create points random , what is your opinion?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

戏蝶舞 2024-09-10 02:34:07

是的,我想说它对选择点一定半径内的随机像素进行着色。一个像素与另一个像素的着色之间也可能存在时间延迟,因为当今的机器速度足够快,能够在您放开鼠标按钮之前为每个可能的像素(只要半径很小)着色。

另外,我认为 Paint 使用的算法可以选择一个像素进行绘制,即使它已经被绘制过,因为有时您可能会得到一个绘制的圆圈,里面有一些未绘制的像素。

Yes, I would say it colors random pixels within a certain radius of the selection point. There's also probably a time delay between the coloring of one pixel and the other, because machines today are fast enough to be able to color every possible pixel (As long as the radius is small) before you could let go of the mouse button.

Also, I think the algorithm that Paint uses can select a pixel to paint even if it already has been painted, since sometimes you can end up with a painted circle with a few unpainted pixels inside.

雨落星ぅ辰 2024-09-10 02:34:07

喷漆的图案是半随机的。如果你拿出一罐 Krylon 并在墙上慢慢喷出一条线,你最终会得到一条宽实线,该线逐渐淡出到背景中,边缘周围有渐变。在一个点上喷涂十秒钟,您会在中心看到一个大点,其中颜色完全饱和,并具有向背景的径向渐变。

因此,用于模拟的变量包括:

  • 握住“喷雾器”的时间(鼠标按钮)
  • “罐头”的运动(鼠标)
  • “罐头”的速度(快速移动会形成一条较轻、不饱和的线。慢速移动会形成一条较粗、饱和的线)渐变线)
  • 扩散模式:喷雾是像喷枪一样聚焦,还是像喷雾罐一样大?
  • “距离”:“喷雾器”距离“画布”有多远?

The pattern for spray paint would be semi-random. If you get out a can of Krylon and slowly spray a line on a wall, you end up with a wide solid line that fades out to the background with a gradient around the edges. Spray in one spot for ten seconds, and you get a big dot in the center in which the color is fully saturated, with a radial gradient to the background.

So- your variables for simulation include:

  • Time holding the "sprayer" (mouse button)
  • Motion of the "can" (mouse)
  • Speed of the "can" (fast moves make a light, unsaturated line. Slow moves make a thick, saturated line with a gradient)
  • spread pattern: is the spray focused like an airbrush, or big like a spray can?
  • "Distance": How far away is the "sprayer" from the "canvas"?
岁月静好 2024-09-10 02:34:07

您收到了许多答案,为您指明了开始处理喷雾效果的用户体验的正确方向。根据您对我的评论的回复,您还需要一种算法来生成半径内的随机点。

有很多方法可以做到这一点,最明显的可能是使用极坐标 选择随机点,然后将极坐标转换为笛卡尔 (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));
    }
  }
}

You have received a number of answers pointing you in the right direction to start handling the user experience of the spray effect. Based on your reponse to my comment you also need an algorithm for generating the random points within the radius.

There are a number of ways to do this, and probably the most obvious would be to use polar coordinates to select the random point and then transform the polar coordinate to a cartesian (x,y) coordinate to render the pixel. Here is a simple example of this approach. To keep things simple, I have just drawn a simple 1x1 ellipse for each point.

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

Alternatively, you can randomly select x,y coordinates from the rectangle that fits the spray circle and using the circle equation r^2 = x^2 + y^2 test the point to determine if it lies inside the circle, if it does you randomly select another point and test again until you have a point that lies within the circle. Here is a quick sample of this approach

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));
    }
  }
}
快乐很简单 2024-09-10 02:34:07

您可以通过对极坐标的一些数量(与所需的强度和扩散相关)进行采样来创建各种强度的喷雾图案。为此,请通过以下方式确定每个样本的随机极坐标 (ρ, θ):

从 N(0, 1) 采样的 ρ: 使用 距喷雾图案精确中心的距离的正态(高斯)分布。我不记得 .NET 库中是否有普通的变量生成器。如果没有,您可以从 U(0, 1) 生成器创建一个

从 U(0, π) 采样的 θ:均匀连续分布。在不损失性能或通用性的情况下,您可以在 U(nπ, mπ) 上进行采样,使 n n m,但 U(0, π) 可能可以满足您的需要。

每个样本的笛卡尔坐标由 (Tx + Sxρ cos θ, Ty + Syρ sin θ) 其中 (Tx, Ty) 是您要创建的喷雾图案的中心; Sx 和 Sy 分别是您希望在 x 和 y 方向上拥有的扩展因子。

You can create a spray pattern of various intensities by sampling some number (related to the desired intensity and spread) of polar coordinates. To do this, determine a random polar coordiate (ρ, θ) for each sample by:

ρ sampled from N(0, 1): Use a Normal (Gaussian) distribution for the distance from the exact center of your spray pattern. I don't recall if there's a normal variate generator in the .NET library. If there isn't, you can create one from a U(0, 1) generator.

θ sampled from U(0, π): Sample the angular component from the Uniform Continuous Distribution. Without loss of performance or generality, you could instead sample on U(nπ, mπ) for n < m, but U(0, π) will probably be fine for what you need.

The Cartesian coordinates of each sample are give by (Tx + Sxρ cos θ, Ty + Syρ sin θ) where (Tx, Ty) is the center of the spray pattern you want to create; Sx and Sy are the spread factors you want to have in the x and y directions respectively.

罪#恶を代价 2024-09-10 02:34:07

尝试使用计时器

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

请修改间隔和半径。

Try using the timer

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

please modify the Interval and the radius.

拥抱影子 2024-09-10 02:34:07

我认为很难找到 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!");
    }

}

正如杰西所说,我认为你应该找到一种算法来传播随机像素。

I think it's hard to find a sample on C#. Below I present a way to start your journey on this. Here I am using a texture brush.

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!");
    }

}

as Jesse said, I think you should find an algorithm to spread random pixels.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文