我如何模拟像窗户喷漆一样的喷雾?我认为它随机创造点,你的意见是什么?
答案 0 :(得分:5)
是的,我会说它会在选择点的某个半径范围内对随机像素进行着色。在一个像素和另一个像素的着色之间也可能存在时间延迟,因为今天的机器足够快,能够在放开鼠标按钮之前为每个可能的像素着色(只要半径很小)。 / p>
另外,我认为Paint使用的算法可以选择要绘制的像素,即使它已经被绘制过,因为有时你最终会得到一个带有几个未上漆像素的画圆。
答案 1 :(得分:3)
喷漆的图案是半随机的。如果你拿出一罐Krylon并慢慢地在墙上喷一条线,你最终会得到一条宽阔的实线,它会在边缘渐变成背景。在一个地方喷洒十秒钟,然后在中心得到一个颜色完全饱和的大点,背景为径向渐变。
所以 - 你的模拟变量包括:
答案 2 :(得分:2)
您已收到许多答案,指示您正确的方向开始处理喷涂效果的用户体验。根据您对我的评论的回应,您还需要一种算法来生成半径内的随机点。
有很多方法可以做到这一点,最明显的可能是使用polar coordinates选择随机点,然后将极坐标转换为笛卡尔坐标(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));
}
}
}
答案 3 :(得分:0)
您可以通过采样极坐标的某些数字(与所需的强度和扩展相关)来创建各种强度的喷雾模式。为此,通过以下方法确定每个样本的随机极坐标(ρ,θ):
ρ从N(0,1)采样:使用Normal (Gaussian) distribution表示距离喷雾模式的精确中心的距离。我不记得.NET库中是否有正常的variate生成器。如果没有,您可以create one from a U(0, 1) generator。
从U(0,π)采样的θ:从Uniform Continuous Distribution采样角度分量。在不损失性能或一般性的情况下,您可以在U( n π, m π)上采样 n &lt; m ,但U(0,π)可能会满足您的需求。
每个样本的笛卡尔坐标由(T x + S x ρcosθ,T y + S 给出y ρsinθ)其中(T x ,T y )是您想要创建的喷雾模式的中心; S x 和S y 分别是您想要在x和y方向上的扩展因子。
答案 4 :(得分:0)
尝试使用计时器
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;
}
}
请修改间隔和半径。
答案 5 :(得分:-1)
我认为很难在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!");
}
}
正如杰西所说,我认为你应该找到一种扩散随机像素的算法。