本版本只是把js+HTML那个版本的算法移植到Silverlight上 连变量名称都没改......
不但没优化 反而退步了 单击start就可以了 ~
原帖:http://news.cnblogs.com/n/85268/
园子里的同志用原生js写的http://www.cnblogs.com/hongru/archive/2010/12/21/1912820.html
代码链接:https://files.cnblogs.com/sandcu/fluent.rar
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Threading;
using System.Windows.Threading;
namespace fluent
{
public partial class MainPage : UserControl
{
LiquidTest lt;
DispatcherTimer dispatcher = new DispatcherTimer();
public MainPage()
{
InitializeComponent();
lt = new LiquidTest(100, 100, 50, 50);
lt.init();
// CompositionTarget.Rendering+=RenderFrame;
dispatcher.Tick += new EventHandler(changePage_Tick);
dispatcher.Interval = new TimeSpan(0, 0, 0, 0, 10);
canvas = LayoutRoot;
}
private void changePage_Tick(object sender, EventArgs e)
{
Path path = canvas.Children[1] as Path;
path.ClearValue(Path.DataProperty);
foreach (Particle p in lt.particles)
{
// var p = this.particles[pi];
line(4.0 * p.x, 4.0 * p.y,
4.0 * (p.x - p.u), 4.0 * (p.y - p.v));
}
lt.simulate();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
dispatcher.Start();
running = true;
step = 1;
}
Canvas canvas;
//var context;
bool running = false;
int width = 0;
int height = 0;
//var liquidTest;
int step = 1;
class Material
{
public double m;
public double rd;
public double k;
public double v;
public double d;
public double g;
public Material(double m, double rd, double k, double v, double d, double g)
{
this.m = m;
this.rd = rd;
this.k = k;
this.v = v;
this.d = d;
this.g = g;
}
}
class Node
{
public double m = 0;
public double d = 0;
public double gx = 0;
public double gy = 0;
public double u = 0;
public double v = 0;
public double ax = 0;
public double ay = 0;
public bool active = false;
public void clear()
{
this.m = this.d = this.gx = this.gy = this.u = this.v = this.ax = this.ay = 0.0;
active = false;
}
}
class Particle
{
public Material mat;
public double x = 0, y = 0;
public double u = 0, v = 0;
public Particle(Material mat, double x, double y, double u, double v)
{
this.mat = mat;
this.x = x;
this.y = y;
this.u = u;
this.v = v;
}
public double dudx = 0;
public double dudy = 0;
public double dvdx = 0;
public double dvdy = 0;
public int cx = 0;
public int cy = 0;
public double[] px = new double[] { 0, 0, 0 };
public double[] py = new double[] { 0, 0, 0 };
public double[] gx = new double[] { 0, 0, 0 };
public double[] gy = new double[] { 0, 0, 0 };
}
class LiquidTest
{
int gsizeX;
int gsizeY;
int particlesX; int particlesY;
public LiquidTest(int gsizeX, int gsizeY, int particlesX, int particlesY)
{
this.gsizeX = gsizeX;
this.gsizeY = gsizeY;
this.particlesX = particlesX;
this.particlesY = particlesY;
}
public List<Particle> particles = new List<Particle>();
List<List<Node>> grid = new List<List<Node>>();
List<Node> active = new List<Node>(); //Nodes
Material water = new Material(1.0, 1.0, 1.0, 1.0, 1.0, 1.0);
//this.pressed = false;
// this.pressedprev = false;
double mx = 0;
double my = 0;
double mxprev = 0;
double myprev = 0;
public void init()
{
int i = 0, j = 0;
for (i = 0; i < this.gsizeX; i++)
{
List<Node> nodes = new List<Node>();
for (j = 0; j < this.gsizeY; j++)
{
nodes.Add(new Node());
}
grid.Add(nodes);
}
Particle p;
for (i = 0; i < particlesX; i++)
for (j = 0; j < particlesY; j++)
{
p = new Particle(water, i + 4, j + 4, 0.0, 0.0);
this.particles.Add(p);
}
}
public void simulate()
{
bool drag = false;
double mdx = 0.0, mdy = 0.0;
// if (this.pressed && this.pressedprev)
// {
// drag = true;
// mdx = 0.25 * (this.mx - this.mxprev);
// mdy = 0.25 * (this.my - this.myprev);
// }
// this.pressedprev = this.pressed;
this.mxprev = this.mx;
this.myprev = this.my;
foreach (Node n in this.active)
{
n.clear();
} this.active.Clear();
double x, y, phi;
double fx = 0.0, fy = 0.0;
foreach (Particle p in this.particles)
{
// var p = this.particles[pi];
p.cx = (int)(p.x - 0.5);
p.cy = (int)(p.y - 0.5);
x = p.cx - p.x;
p.px[0] = (0.5 * x * x + 1.5 * x + 1.125);
p.gx[0] = (x + 1.5);
x += 1.0;
p.px[1] = (-x * x + 0.75);
p.gx[1] = (-2.0 * x);
x += 1.0;
p.px[2] = (0.5 * x * x - 1.5 * x + 1.125);
p.gx[2] = (x - 1.5);
y = p.cy - p.y;
p.py[0] = (0.5 * y * y + 1.5 * y + 1.125);
p.gy[0] = (y + 1.5);
y += 1.0;
p.py[1] = (-y * y + 0.75);
p.gy[1] = (-2.0 * y);
y += 1.0;
p.py[2] = (0.5 * y * y - 1.5 * y + 1.125);
p.gy[2] = (y - 1.5);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Node n = this.grid[p.cx + i][p.cy + j];
if (!n.active)
{
this.active.Add(n);
n.active = true;
}
phi = p.px[i] * p.py[j];
n.m += phi * p.mat.m;
n.d += phi;
n.gx += p.gx[i] * p.py[j];
n.gy += p.px[i] * p.gy[j];
}
}
}
double density, pressure, weight;
Node n01, n02;
Node n11, n12;
int cx, cy;
int cxi, cyi;
double pdx, pdy;
double C20, C02, C30, C03;
double csum1, csum2;
double C21, C31, C12, C13, C11;
double u, u2, u3;
double v, v2, v3;
foreach (Particle p in this.particles)
{
cx = (int)(p.x);
cy = (int)(p.y);
cxi = cx + 1;
cyi = cy + 1;
n01 = this.grid[cx][cy];
n02 = this.grid[cx][cyi];
n11 = this.grid[cxi][cy];
n12 = this.grid[cxi][cyi];
pdx = n11.d - n01.d;
pdy = n02.d - n01.d;
C20 = 3.0 * pdx - n11.gx - 2.0 * n01.gx;
C02 = 3.0 * pdy - n02.gy - 2.0 * n01.gy;
C30 = -2.0 * pdx + n11.gx + n01.gx;
C03 = -2.0 * pdy + n02.gy + n01.gy;
csum1 = n01.d + n01.gy + C02 + C03;
csum2 = n01.d + n01.gx + C20 + C30;
C21 = 3.0 * n12.d - 2.0 * n02.gx - n12.gx - 3.0 * csum1 - C20;
C31 = -2.0 * n12.d + n02.gx + n12.gx + 2.0 * csum1 - C30;
C12 = 3.0 * n12.d - 2.0 * n11.gy - n12.gy - 3.0 * csum2 - C02;
C13 = -2.0 * n12.d + n11.gy + n12.gy + 2.0 * csum2 - C03;
C11 = n02.gx - C13 - C12 - n01.gx;
u = p.x - cx;
u2 = u * u;
u3 = u * u2;
v = p.y - cy;
v2 = v * v;
v3 = v * v2;
density = n01.d + n01.gx * u + n01.gy * v + C20 * u2 + C02 * v2 + C30 * u3 + C03 * v3 + C21 * u2 * v + C31 * u3 * v + C12 * u * v2 + C13 * u * v3 + C11 * u * v;
pressure = density - 1.0;
if (pressure > 2.0)
pressure = 2.0;
fx = 0.0;
fy = 0.0;
if (p.x < 4.0)
fx += p.mat.m * (4.0 - p.x);
else if (p.x > this.gsizeX - 5)
fx += p.mat.m * (this.gsizeX - 5 - p.x);
if (p.y < 4.0)
fy += p.mat.m * (4.0 - p.y);
else if (p.y > this.gsizeY - 5)
fy += p.mat.m * (this.gsizeY - 5 - p.y);
if (drag)
{
var vx = Math.Abs(p.x - 0.25 * this.mx);
var vy = Math.Abs(p.y - 0.25 * this.my);
if ((vx < 10.0) && (vy < 10.0))
{
weight = p.mat.m * (1.0 - vx * 0.10) * (1.0 - vy * 0.10);
fx += weight * (mdx - p.u);
fy += weight * (mdy - p.v);
}
}
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Node n = this.grid[(p.cx + i)][(p.cy + j)];
phi = p.px[i] * p.py[j];
n.ax += -((p.gx[i] * p.py[j]) * pressure) + fx * phi;
n.ay += -((p.px[i] * p.gy[j]) * pressure) + fy * phi;
}
}
}
foreach (Node n in this.active)
{
// var n = this.active[ni];
if (n.m > 0.0)
{
n.ax /= n.m;
n.ay /= n.m;
n.ay += 0.03;
}
}
double mu, mv;
foreach (Particle p in this.particles)
{
// var p = this.particles[pi];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Node n = this.grid[(p.cx + i)][(p.cy + j)];
phi = p.px[i] * p.py[j];
p.u += phi * n.ax;
p.v += phi * n.ay;
}
}
mu = p.mat.m * p.u;
mv = p.mat.m * p.v;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Node n = this.grid[(p.cx + i)][(p.cy + j)];
phi = p.px[i] * p.py[j];
n.u += phi * mu;
n.v += phi * mv;
}
}
}
foreach (Node n in this.active)
{
// var n = this.active[ni];
if (n.m > 0.0)
{
n.u /= n.m;
n.v /= n.m;
}
}
double gu, gv;
Random rm = new Random();
foreach (Particle p in this.particles)
{
//var p = this.particles[pi];
gu = 0.0;
gv = 0.0;
for (var i = 0; i < 3; i++)
{
for (var j = 0; j < 3; j++)
{
var n = this.grid[(p.cx + i)][(p.cy + j)];
phi = p.px[i] * p.py[j];
gu += phi * n.u;
gv += phi * n.v;
}
}
p.x += gu;
p.y += gv;
p.u += 1.0 * (gu - p.u);
p.v += 1.0 * (gv - p.v);
if (p.x < 1.0)
{
p.x = (1.0 + rm.Next(0, 1) * 0.01);
p.u = 0.0;
}
else if (p.x > this.gsizeX - 2)
{
p.x = (this.gsizeX - 2 - rm.Next(0, 1) * 0.01);
p.u = 0.0;
}
if (p.y < 1.0)
{
p.y = (1.0 + rm.Next(0, 1) * 0.01);
p.v = 0.0;
}
else if (p.y > this.gsizeY - 2)
{
p.y = (this.gsizeY - 2 - rm.Next(0, 1) * 0.01);
p.v = 0.0;
}
}
}
}
private void line(double x1, double y1, double x2, double y2)
{
Path path = canvas.Children[1] as Path;
GeometryGroup aPathGeometry;// = new PathGeometry();
if (path.Data == null)
{
aPathGeometry = new GeometryGroup();
path.Data = aPathGeometry;
path.Stroke = new SolidColorBrush(Colors.Black);
path.StrokeThickness = 2;
}
else
{
aPathGeometry = path.Data as GeometryGroup;
}
LineGeometry Line = new LineGeometry();
Line.StartPoint = new Point(x1, y1);
Line.EndPoint = new Point(x2, y2);
aPathGeometry.Children.Add(Line);
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Threading;
using System.Windows.Threading;
namespace fluent
{
public partial class MainPage : UserControl
{
LiquidTest lt;
DispatcherTimer dispatcher = new DispatcherTimer();
public MainPage()
{
InitializeComponent();
lt = new LiquidTest(100, 100, 50, 50);
lt.init();
// CompositionTarget.Rendering+=RenderFrame;
dispatcher.Tick += new EventHandler(changePage_Tick);
dispatcher.Interval = new TimeSpan(0, 0, 0, 0, 10);
canvas = LayoutRoot;
}
private void changePage_Tick(object sender, EventArgs e)
{
Path path = canvas.Children[1] as Path;
path.ClearValue(Path.DataProperty);
foreach (Particle p in lt.particles)
{
// var p = this.particles[pi];
line(4.0 * p.x, 4.0 * p.y,
4.0 * (p.x - p.u), 4.0 * (p.y - p.v));
}
lt.simulate();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
dispatcher.Start();
running = true;
step = 1;
}
Canvas canvas;
//var context;
bool running = false;
int width = 0;
int height = 0;
//var liquidTest;
int step = 1;
class Material
{
public double m;
public double rd;
public double k;
public double v;
public double d;
public double g;
public Material(double m, double rd, double k, double v, double d, double g)
{
this.m = m;
this.rd = rd;
this.k = k;
this.v = v;
this.d = d;
this.g = g;
}
}
class Node
{
public double m = 0;
public double d = 0;
public double gx = 0;
public double gy = 0;
public double u = 0;
public double v = 0;
public double ax = 0;
public double ay = 0;
public bool active = false;
public void clear()
{
this.m = this.d = this.gx = this.gy = this.u = this.v = this.ax = this.ay = 0.0;
active = false;
}
}
class Particle
{
public Material mat;
public double x = 0, y = 0;
public double u = 0, v = 0;
public Particle(Material mat, double x, double y, double u, double v)
{
this.mat = mat;
this.x = x;
this.y = y;
this.u = u;
this.v = v;
}
public double dudx = 0;
public double dudy = 0;
public double dvdx = 0;
public double dvdy = 0;
public int cx = 0;
public int cy = 0;
public double[] px = new double[] { 0, 0, 0 };
public double[] py = new double[] { 0, 0, 0 };
public double[] gx = new double[] { 0, 0, 0 };
public double[] gy = new double[] { 0, 0, 0 };
}
class LiquidTest
{
int gsizeX;
int gsizeY;
int particlesX; int particlesY;
public LiquidTest(int gsizeX, int gsizeY, int particlesX, int particlesY)
{
this.gsizeX = gsizeX;
this.gsizeY = gsizeY;
this.particlesX = particlesX;
this.particlesY = particlesY;
}
public List<Particle> particles = new List<Particle>();
List<List<Node>> grid = new List<List<Node>>();
List<Node> active = new List<Node>(); //Nodes
Material water = new Material(1.0, 1.0, 1.0, 1.0, 1.0, 1.0);
//this.pressed = false;
// this.pressedprev = false;
double mx = 0;
double my = 0;
double mxprev = 0;
double myprev = 0;
public void init()
{
int i = 0, j = 0;
for (i = 0; i < this.gsizeX; i++)
{
List<Node> nodes = new List<Node>();
for (j = 0; j < this.gsizeY; j++)
{
nodes.Add(new Node());
}
grid.Add(nodes);
}
Particle p;
for (i = 0; i < particlesX; i++)
for (j = 0; j < particlesY; j++)
{
p = new Particle(water, i + 4, j + 4, 0.0, 0.0);
this.particles.Add(p);
}
}
public void simulate()
{
bool drag = false;
double mdx = 0.0, mdy = 0.0;
// if (this.pressed && this.pressedprev)
// {
// drag = true;
// mdx = 0.25 * (this.mx - this.mxprev);
// mdy = 0.25 * (this.my - this.myprev);
// }
// this.pressedprev = this.pressed;
this.mxprev = this.mx;
this.myprev = this.my;
foreach (Node n in this.active)
{
n.clear();
} this.active.Clear();
double x, y, phi;
double fx = 0.0, fy = 0.0;
foreach (Particle p in this.particles)
{
// var p = this.particles[pi];
p.cx = (int)(p.x - 0.5);
p.cy = (int)(p.y - 0.5);
x = p.cx - p.x;
p.px[0] = (0.5 * x * x + 1.5 * x + 1.125);
p.gx[0] = (x + 1.5);
x += 1.0;
p.px[1] = (-x * x + 0.75);
p.gx[1] = (-2.0 * x);
x += 1.0;
p.px[2] = (0.5 * x * x - 1.5 * x + 1.125);
p.gx[2] = (x - 1.5);
y = p.cy - p.y;
p.py[0] = (0.5 * y * y + 1.5 * y + 1.125);
p.gy[0] = (y + 1.5);
y += 1.0;
p.py[1] = (-y * y + 0.75);
p.gy[1] = (-2.0 * y);
y += 1.0;
p.py[2] = (0.5 * y * y - 1.5 * y + 1.125);
p.gy[2] = (y - 1.5);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Node n = this.grid[p.cx + i][p.cy + j];
if (!n.active)
{
this.active.Add(n);
n.active = true;
}
phi = p.px[i] * p.py[j];
n.m += phi * p.mat.m;
n.d += phi;
n.gx += p.gx[i] * p.py[j];
n.gy += p.px[i] * p.gy[j];
}
}
}
double density, pressure, weight;
Node n01, n02;
Node n11, n12;
int cx, cy;
int cxi, cyi;
double pdx, pdy;
double C20, C02, C30, C03;
double csum1, csum2;
double C21, C31, C12, C13, C11;
double u, u2, u3;
double v, v2, v3;
foreach (Particle p in this.particles)
{
cx = (int)(p.x);
cy = (int)(p.y);
cxi = cx + 1;
cyi = cy + 1;
n01 = this.grid[cx][cy];
n02 = this.grid[cx][cyi];
n11 = this.grid[cxi][cy];
n12 = this.grid[cxi][cyi];
pdx = n11.d - n01.d;
pdy = n02.d - n01.d;
C20 = 3.0 * pdx - n11.gx - 2.0 * n01.gx;
C02 = 3.0 * pdy - n02.gy - 2.0 * n01.gy;
C30 = -2.0 * pdx + n11.gx + n01.gx;
C03 = -2.0 * pdy + n02.gy + n01.gy;
csum1 = n01.d + n01.gy + C02 + C03;
csum2 = n01.d + n01.gx + C20 + C30;
C21 = 3.0 * n12.d - 2.0 * n02.gx - n12.gx - 3.0 * csum1 - C20;
C31 = -2.0 * n12.d + n02.gx + n12.gx + 2.0 * csum1 - C30;
C12 = 3.0 * n12.d - 2.0 * n11.gy - n12.gy - 3.0 * csum2 - C02;
C13 = -2.0 * n12.d + n11.gy + n12.gy + 2.0 * csum2 - C03;
C11 = n02.gx - C13 - C12 - n01.gx;
u = p.x - cx;
u2 = u * u;
u3 = u * u2;
v = p.y - cy;
v2 = v * v;
v3 = v * v2;
density = n01.d + n01.gx * u + n01.gy * v + C20 * u2 + C02 * v2 + C30 * u3 + C03 * v3 + C21 * u2 * v + C31 * u3 * v + C12 * u * v2 + C13 * u * v3 + C11 * u * v;
pressure = density - 1.0;
if (pressure > 2.0)
pressure = 2.0;
fx = 0.0;
fy = 0.0;
if (p.x < 4.0)
fx += p.mat.m * (4.0 - p.x);
else if (p.x > this.gsizeX - 5)
fx += p.mat.m * (this.gsizeX - 5 - p.x);
if (p.y < 4.0)
fy += p.mat.m * (4.0 - p.y);
else if (p.y > this.gsizeY - 5)
fy += p.mat.m * (this.gsizeY - 5 - p.y);
if (drag)
{
var vx = Math.Abs(p.x - 0.25 * this.mx);
var vy = Math.Abs(p.y - 0.25 * this.my);
if ((vx < 10.0) && (vy < 10.0))
{
weight = p.mat.m * (1.0 - vx * 0.10) * (1.0 - vy * 0.10);
fx += weight * (mdx - p.u);
fy += weight * (mdy - p.v);
}
}
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Node n = this.grid[(p.cx + i)][(p.cy + j)];
phi = p.px[i] * p.py[j];
n.ax += -((p.gx[i] * p.py[j]) * pressure) + fx * phi;
n.ay += -((p.px[i] * p.gy[j]) * pressure) + fy * phi;
}
}
}
foreach (Node n in this.active)
{
// var n = this.active[ni];
if (n.m > 0.0)
{
n.ax /= n.m;
n.ay /= n.m;
n.ay += 0.03;
}
}
double mu, mv;
foreach (Particle p in this.particles)
{
// var p = this.particles[pi];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Node n = this.grid[(p.cx + i)][(p.cy + j)];
phi = p.px[i] * p.py[j];
p.u += phi * n.ax;
p.v += phi * n.ay;
}
}
mu = p.mat.m * p.u;
mv = p.mat.m * p.v;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Node n = this.grid[(p.cx + i)][(p.cy + j)];
phi = p.px[i] * p.py[j];
n.u += phi * mu;
n.v += phi * mv;
}
}
}
foreach (Node n in this.active)
{
// var n = this.active[ni];
if (n.m > 0.0)
{
n.u /= n.m;
n.v /= n.m;
}
}
double gu, gv;
Random rm = new Random();
foreach (Particle p in this.particles)
{
//var p = this.particles[pi];
gu = 0.0;
gv = 0.0;
for (var i = 0; i < 3; i++)
{
for (var j = 0; j < 3; j++)
{
var n = this.grid[(p.cx + i)][(p.cy + j)];
phi = p.px[i] * p.py[j];
gu += phi * n.u;
gv += phi * n.v;
}
}
p.x += gu;
p.y += gv;
p.u += 1.0 * (gu - p.u);
p.v += 1.0 * (gv - p.v);
if (p.x < 1.0)
{
p.x = (1.0 + rm.Next(0, 1) * 0.01);
p.u = 0.0;
}
else if (p.x > this.gsizeX - 2)
{
p.x = (this.gsizeX - 2 - rm.Next(0, 1) * 0.01);
p.u = 0.0;
}
if (p.y < 1.0)
{
p.y = (1.0 + rm.Next(0, 1) * 0.01);
p.v = 0.0;
}
else if (p.y > this.gsizeY - 2)
{
p.y = (this.gsizeY - 2 - rm.Next(0, 1) * 0.01);
p.v = 0.0;
}
}
}
}
private void line(double x1, double y1, double x2, double y2)
{
Path path = canvas.Children[1] as Path;
GeometryGroup aPathGeometry;// = new PathGeometry();
if (path.Data == null)
{
aPathGeometry = new GeometryGroup();
path.Data = aPathGeometry;
path.Stroke = new SolidColorBrush(Colors.Black);
path.StrokeThickness = 2;
}
else
{
aPathGeometry = path.Data as GeometryGroup;
}
LineGeometry Line = new LineGeometry();
Line.StartPoint = new Point(x1, y1);
Line.EndPoint = new Point(x2, y2);
aPathGeometry.Children.Add(Line);
}
}
}