public static decimal forceBetweenParticles(particle acting, particle actedUpon) { var posDiff = actedUpon.position - acting.position; decimal dist = posDiff.magnitude * scale; if (dist == 0) { dist = 0.000000001M; } return((k * acting.charge * q * actedUpon.charge * q) / (dist * dist)); }
public simulationCell(simPoint tlBoundary, simPoint brBoundary, List <simPoint> geometry, int numberOfParticles, particle prototype, vector startingVector = null) { topLeftBoundary = tlBoundary; bottomRightBoundary = brBoundary; containedGeometry = geometry; initialPrototype = prototype; initialVectorPrototype = startingVector; spawnParticles(numberOfParticles, prototype, startingVector); }
private void spawnParticles(int particles, particle proto, vector v) { var height = bottomRightBoundary.y - topLeftBoundary.y; var width = bottomRightBoundary.x - topLeftBoundary.x; if (height == 0 || width == 0) { throw new Exception("Can't define simulation zone with zero area!"); } decimal ratio = height / width; decimal inverseRatio = 1 / ratio; decimal numberToMultiply = vector.Sqrt(particles); int wide = (int)(inverseRatio * numberToMultiply); int high = (int)(ratio * numberToMultiply); if (containedParticles == null) { containedParticles = new List <particle>(); } for (int x = 0; x < wide; x++) { for (int y = 0; y < high; y++) { particle p = proto.copyWithNewID; decimal posx = topLeftBoundary.x + (width / wide) * x; decimal posy = topLeftBoundary.y + (height / high) * y; p.position = new simPoint(posx, posy); if (v != null) { p.momentum = v; } containedParticles.Add(p); } } }
//air will always flow right to left public simulation(List <simPoint> geometryPoints, int width = 700, int height = 300, int cellsHigh = 6, int cellsWide = 16, decimal baseDensity = 0.0125M, vector startingVelocity = null, particle p = null) { spawnCells = new List <simulationCell>(); int realWidth = width * 2; int realCellsWide = cellsWide + 2;//* 2; if (startingVelocity == null) { startingVelocity = new vector(-0.1M, 0); } if (p == null) { p = new particle() { momentum = startingVelocity, repellanceCoefficient = airCoefficient, position = vector.zero.asPoint } } ; if (cells == null) { cells = new List <simulationCell>(); } decimal cellWidth = (decimal)(width / cellsWide); decimal cellHeight = (decimal)(height / cellsHigh); int particlesPerCell = (int)(cellWidth * cellHeight * baseDensity); spawncount = particlesPerCell; Dictionary <Tuple <int, int>, simulationCell> cellDict = new Dictionary <Tuple <int, int>, simulationCell>(); for (int x = -1; x <= realCellsWide; x++) { for (int y = -1; y <= cellsHigh; y++) { simPoint topLeftB = new simPoint(x * cellWidth, y * cellHeight); simPoint bottomRightB = new simPoint((x + 1) * cellWidth, (y + 1) * cellHeight); //make real simulation cells simulationCell c; if (y >= 0 && y < cellsHigh) { if (x > cellsWide && x < realCellsWide) { c = new simulationCell(topLeftB, bottomRightB, new List <simPoint>(), particlesPerCell, p); spawnCells.Add(c); } else if (x >= 0) { List <simPoint> ptsRelevant = geometryPoints.FindAll((s) => { if (s.x <= bottomRightB.x && s.x >= topLeftB.x && s.y >= topLeftB.y && s.y < bottomRightB.y) { return(true); } else { return(false); } }); c = new simulationCell(topLeftB, bottomRightB, ptsRelevant, 0, p); } else { c = new simulationCell(particlesPerCell / 2, topLeftB, bottomRightB); } } else { c = new simulationCell(particlesPerCell / 2, topLeftB, bottomRightB); } cellDict[new Tuple <int, int>(x, y)] = c; cells.Add(c); } } for (int x = 0; x < realCellsWide; x++) { for (int y = 0; y < cellsHigh; y++) { cellDict[new Tuple <int, int>(x, y)].bottom = cellDict[new Tuple <int, int>(x, y + 1)]; cellDict[new Tuple <int, int>(x, y)].top = cellDict[new Tuple <int, int>(x, y - 1)]; cellDict[new Tuple <int, int>(x, y)].right = cellDict[new Tuple <int, int>(x + 1, y)]; cellDict[new Tuple <int, int>(x, y)].left = cellDict[new Tuple <int, int>(x - 1, y)]; cellDict[new Tuple <int, int>(x, y)].bottomRight = cellDict[new Tuple <int, int>(x + 1, y + 1)]; cellDict[new Tuple <int, int>(x, y)].bottomLeft = cellDict[new Tuple <int, int>(x - 1, y + 1)]; cellDict[new Tuple <int, int>(x, y)].topRight = cellDict[new Tuple <int, int>(x + 1, y - 1)]; cellDict[new Tuple <int, int>(x, y)].topLeft = cellDict[new Tuple <int, int>(x - 1, y - 1)]; } } }