Simulate spray

How can I simulate an aerosol like paint for windows? I think it creates dots randomly, what is your opinion?

+6
math c # image-editing
source share
6 answers

Yes, I would say that it colors random pixels within a certain radius of the selection point. There is probably also a time delay between painting one pixel and another, because cars are fast enough today to be able to color every possible pixel (as long as the radius is small) before you can release the mouse button.

In addition, I think that the algorithm that Paint uses can select a pixel for drawing, even if it has already been drawn, as sometimes you can get a painted circle with a few unpainted pixels inside.

+5
source share

A sample for spray paint will be semi-random. If you select a can from Krylon and slowly wipe the line on the wall, you will get a wide solid line that disappears against the background with a gradient along the edges. Spray in one place for ten seconds, and you get a big dot in the center where the color is fully saturated, with a radial gradient in the background.

So, your modeling variables include:

  • Spray holding time (mouse button)
  • Movement "can" (mouse)
  • Can speed (fast movements make a light, desaturated line. Slow movements make a thick saturated line a gradient)
  • Propagation of the pattern: spraying focused like an airbrush, or big like a spray?
  • "Distance": how far is the "spray" from the "canvas"?
+3
source share

You have received a series of answers indicating the right direction to begin processing the spray effect. Based on your answer to my comment, you also need an algorithm for generating random points in a radius.

There are several ways to do this, and probably the most obvious would be to use polar coordinates to select a random point, and then convert 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 just drew 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 = eX + Math.Cos(theta) * r; double y = eY + Math.Sin(theta) * r; g.DrawEllipse(Pens.Black, new Rectangle((int)x - 1, (int)y - 1, 1, 1)); } } } 

Alternatively, you can arbitrarily select the x, y coordinates from the rectangle that corresponds to the spray circle, and using the equation of the circle r ^ 2 = x ^ 2 + y ^ 2 check the point to determine whether it lies inside the circle if you arbitrarily choose another point and check again until you get a point lying inside the circle. Here is a brief example 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 += eX; y += eY; g.DrawEllipse(Pens.Black, new Rectangle((int)x - 1, (int)y - 1, 1, 1)); } } } 
+2
source share

You can create a spray pattern of various intensities by taking a test number (associated with the desired intensity and spread) of the polar coordinates. To do this, determine the random polar coordinates (& rho ;, & theta;) for each sample using:

& Rho; selected from N (0, 1): Use the normal (Gaussian) distribution for the distance from the exact center of your spray pattern. I don’t remember if there is a regular variable generator in the .NET library. If this does not happen, you can create one of the generator U (0, 1) .

& theta; selected from U (0, Ο€): A sample angular component from Uniform Continuous Distribution . Without loss of performance or generality, you could instead choose U ( n & pi ;, m & pi;) for n m , but U (0, & pi;) will probably be fine for what you need.

The Cartesian coordinates of each sample are given by (T x + S x ? R? Cos? Theta ;, T y + S y ? Rho; sin? Theta;) where (T x , T y ) is the center of the spray pattern you want to create ; S x and S y are the propagation coefficients that you want to have in the x and y directions, respectively.

0
source share

Try using a 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; } } 

change the spacing and radius.

0
source share

It's hard for me to find a sample in C #. Below I present you a way to begin your journey. Here I use a brush texture.

 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 a random pixel propagation algorithm.

-one
source share

All Articles