Added working particle physics simulation.
This commit is contained in:
parent
e4ea40079c
commit
3807e0bae3
71
pom.xml
71
pom.xml
|
@ -8,6 +8,10 @@
|
|||
<artifactId>threadripper</artifactId>
|
||||
<version>0.0.1</version>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
@ -15,19 +19,56 @@
|
|||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<release>14</release>
|
||||
<release>12</release>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-maven-plugin</artifactId>
|
||||
<version>0.0.4</version>
|
||||
<configuration>
|
||||
<release>3.8.1</release>
|
||||
<launcher>launcher</launcher>
|
||||
<mainClass>nl.andrewlalis.threadripper.ThreadRipperApplication</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- https://mvnrepository.com/artifact/org.openjfx/javafx -->
|
||||
<!-- https://mvnrepository.com/artifact/org.openjfx/javafx-controls -->
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx</artifactId>
|
||||
<artifactId>javafx-controls</artifactId>
|
||||
<version>15</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.openjfx/javafx-graphics -->
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-graphics</artifactId>
|
||||
<version>15</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.openjfx/javafx-base -->
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-base</artifactId>
|
||||
<version>15</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.openjfx/javafx-media -->
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-media</artifactId>
|
||||
<version>15</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.openjfx/javafx-fxml -->
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-fxml</artifactId>
|
||||
<version>15</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
|
||||
|
@ -45,5 +86,27 @@
|
|||
<version>1.10.19</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.30</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-jdk14 -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-jdk14</artifactId>
|
||||
<version>1.7.30</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.12</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -1,10 +1,92 @@
|
|||
package nl.andrewlalis.threadripper;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.canvas.Canvas;
|
||||
import javafx.scene.canvas.GraphicsContext;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.stage.Stage;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import nl.andrewlalis.threadripper.engine.ParticleChamber;
|
||||
import nl.andrewlalis.threadripper.engine.Vec2;
|
||||
import nl.andrewlalis.threadripper.particle.Particle;
|
||||
import nl.andrewlalis.threadripper.particle.ParticleFactory;
|
||||
|
||||
/**
|
||||
* Main application starting point.
|
||||
*/
|
||||
public class ThreadRipperApplication {
|
||||
@Slf4j
|
||||
public class ThreadRipperApplication extends Application {
|
||||
|
||||
private final Canvas canvas;
|
||||
private final ParticleChamber chamber;
|
||||
|
||||
public ThreadRipperApplication() {
|
||||
this.canvas = new Canvas(1000, 1000);
|
||||
this.chamber = new ParticleChamber(canvas);
|
||||
ParticleFactory factory = new ParticleFactory(
|
||||
10000.0,
|
||||
10000000.0,
|
||||
0,
|
||||
0,
|
||||
new Vec2(350, 250),
|
||||
new Vec2(450, 400),
|
||||
new Vec2(10, -2),
|
||||
new Vec2(25, 2)
|
||||
);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
this.chamber.addParticle(factory.build());
|
||||
}
|
||||
|
||||
// this.chamber.addParticle(new Particle(new Vec2(400, 298), new Vec2(19, 0), 100000.0, 0.0));
|
||||
// this.chamber.addParticle(new Particle(new Vec2(400, 300), new Vec2(20, 0), 10000000000.0, 0.0));
|
||||
this.chamber.addParticle(new Particle(new Vec2(400, 500), new Vec2(0, 0), 1000000000000000.0, 0.0));
|
||||
|
||||
// ParticleFactory factory1 = new ParticleFactory(
|
||||
// 1000000000.0,
|
||||
// 10000000000000.0,
|
||||
// 0,
|
||||
// 0,
|
||||
// new Vec2(700, 700),
|
||||
// new Vec2(900, 900),
|
||||
// new Vec2(0, 0),
|
||||
// new Vec2(0, 0)
|
||||
// );
|
||||
// for (int i = 0; i < 500; i++) {
|
||||
// this.chamber.addParticle(factory1.build());
|
||||
// }
|
||||
|
||||
Thread particleChamberThread = new Thread(chamber);
|
||||
particleChamberThread.setName("ParticleChamber");
|
||||
particleChamberThread.start();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello world.");
|
||||
log.info("Starting ThreadRipper application.");
|
||||
Application.launch(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Stage stage) throws Exception {
|
||||
stage.setTitle("ThreadRipper");
|
||||
|
||||
GraphicsContext gc = this.canvas.getGraphicsContext2D();
|
||||
|
||||
gc.setFill(Color.GREEN);
|
||||
gc.fillOval(10, 60, 30, 30);
|
||||
|
||||
Group root = new Group();
|
||||
root.getChildren().add(this.canvas);
|
||||
Scene scene = new Scene(root);
|
||||
stage.setScene(scene);
|
||||
stage.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() throws Exception {
|
||||
this.chamber.setRunning(false);
|
||||
super.stop();
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package nl.andrewlalis.threadripper.engine;
|
||||
|
||||
public class Constants {
|
||||
/**
|
||||
* Newton's Gravitational Constant
|
||||
* https://en.wikipedia.org/wiki/Gravitational_constant
|
||||
*/
|
||||
public static final double G = 0.00000000006674;
|
||||
|
||||
/**
|
||||
* Coulomb's Constant
|
||||
* https://en.wikipedia.org/wiki/Coulomb%27s_law
|
||||
*/
|
||||
public static final double Ke = 8990000000.0;
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
package nl.andrewlalis.threadripper.engine;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.canvas.Canvas;
|
||||
import javafx.scene.canvas.GraphicsContext;
|
||||
import javafx.scene.paint.Color;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import nl.andrewlalis.threadripper.particle.Particle;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
@Slf4j
|
||||
public class ParticleChamber implements Runnable {
|
||||
private static final int DEFAULT_THREAD_POOL = 100;
|
||||
private static final double DEFAULT_UPDATE_FPS = 60;
|
||||
|
||||
private final Set<Particle> particles;
|
||||
private int threadCount;
|
||||
private ExecutorService executorService;
|
||||
private CompletionService<ParticleUpdate> particleUpdateService;
|
||||
|
||||
private boolean running;
|
||||
private double updateFps;
|
||||
|
||||
private final Canvas canvas;
|
||||
|
||||
public ParticleChamber(Canvas canvas) {
|
||||
this.particles = new HashSet<>();
|
||||
|
||||
this.threadCount = DEFAULT_THREAD_POOL;
|
||||
this.executorService = Executors.newFixedThreadPool(this.threadCount);
|
||||
this.particleUpdateService = new ExecutorCompletionService<>(this.executorService);
|
||||
|
||||
this.updateFps = DEFAULT_UPDATE_FPS;
|
||||
|
||||
this.canvas = canvas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds one or more particles to the chamber.
|
||||
* @param particles The particles to add.
|
||||
*/
|
||||
public void addParticle(Particle... particles) {
|
||||
this.particles.addAll(Arrays.asList(particles));
|
||||
}
|
||||
|
||||
public synchronized void setRunning(boolean running) {
|
||||
this.running = running;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
this.running = true;
|
||||
long previousTimeMilliseconds = System.currentTimeMillis();
|
||||
long millisecondsSinceLastUpdate = 0L;
|
||||
|
||||
log.info("Starting particle chamber.");
|
||||
while (this.running) {
|
||||
final long currentTimeMilliseconds = System.currentTimeMillis();
|
||||
final long elapsedMilliseconds = currentTimeMilliseconds - previousTimeMilliseconds;
|
||||
|
||||
millisecondsSinceLastUpdate += elapsedMilliseconds;
|
||||
|
||||
final double millisecondsPerFrame = 1000.0 / this.updateFps;
|
||||
|
||||
if (millisecondsSinceLastUpdate > millisecondsPerFrame) {
|
||||
final double secondsSinceLastUpdate = millisecondsSinceLastUpdate / 1000.0;
|
||||
millisecondsSinceLastUpdate = 0L;
|
||||
//log.info("Updating particles after {} seconds elapsed.", secondsSinceLastUpdate);
|
||||
this.updateParticles(secondsSinceLastUpdate);
|
||||
this.drawParticles();
|
||||
}
|
||||
|
||||
previousTimeMilliseconds = currentTimeMilliseconds;
|
||||
}
|
||||
log.info("Particle chamber stopped.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all the particles in the simulation.
|
||||
* @param deltaTime The amount of seconds that have passed since the last update.
|
||||
*/
|
||||
private void updateParticles(double deltaTime) {
|
||||
// First submit a new callable task for each particle.
|
||||
for (Particle particle : this.particles) {
|
||||
this.particleUpdateService.submit(new ParticleUpdater(particle, this.particles));
|
||||
}
|
||||
|
||||
int updatesReceived = 0;
|
||||
boolean errorEncountered = false;
|
||||
final List<ParticleUpdate> updates = new ArrayList<>(this.particles.size());
|
||||
|
||||
// Iterate until we've received the results of each particle updater's calculations.
|
||||
while (updatesReceived < this.particles.size() && !errorEncountered) {
|
||||
try {
|
||||
Future<ParticleUpdate> updateFuture = this.particleUpdateService.take();
|
||||
updates.add(updateFuture.get());
|
||||
updatesReceived++;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
errorEncountered = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Implement the updates for each particle.
|
||||
for (ParticleUpdate update : updates) {
|
||||
update.getFocusParticle().updateVelocity(update.getAcceleration(), deltaTime);
|
||||
update.getFocusParticle().updatePosition(deltaTime);
|
||||
//log.info("Particle updated: {}", update.getFocusParticle().toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws all particles on the canvas.
|
||||
*/
|
||||
private void drawParticles() {
|
||||
Platform.runLater(() -> {
|
||||
GraphicsContext gc = this.canvas.getGraphicsContext2D();
|
||||
gc.setFill(Color.WHITE);
|
||||
gc.clearRect(0, 0, this.canvas.getWidth(), this.canvas.getHeight());
|
||||
gc.setFill(Color.BLACK);
|
||||
gc.setStroke(Color.BLUE);
|
||||
for (Particle particle : this.particles) {
|
||||
Vec2 pos = particle.getPosition();
|
||||
gc.fillOval(pos.getX() - 3, pos.getY() - 3, 6, 6);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package nl.andrewlalis.threadripper.engine;
|
||||
|
||||
import lombok.Getter;
|
||||
import nl.andrewlalis.threadripper.particle.Particle;
|
||||
|
||||
/**
|
||||
* Describes an update to a particle's motion.
|
||||
*/
|
||||
@Getter
|
||||
public class ParticleUpdate {
|
||||
/**
|
||||
* The particle to be updated.
|
||||
*/
|
||||
private final Particle focusParticle;
|
||||
|
||||
/**
|
||||
* The acceleration that the particle experiences, in meters per second
|
||||
* squared.
|
||||
*/
|
||||
private final Vec2 acceleration;
|
||||
|
||||
public ParticleUpdate(Particle focusParticle, Vec2 acceleration) {
|
||||
this.focusParticle = focusParticle;
|
||||
this.acceleration = acceleration;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package nl.andrewlalis.threadripper.engine;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import nl.andrewlalis.threadripper.particle.Particle;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* Callable which is dedicated to finding the net force which is applied to a
|
||||
* particular particle of interest, with respect to all other particles.
|
||||
*/
|
||||
@Slf4j
|
||||
public class ParticleUpdater implements Callable<ParticleUpdate> {
|
||||
private final Particle focusParticle;
|
||||
private final Set<Particle> particles;
|
||||
|
||||
public ParticleUpdater(Particle focusParticle, Set<Particle> particles) {
|
||||
this.focusParticle = focusParticle;
|
||||
this.particles = particles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParticleUpdate call() throws Exception {
|
||||
double accelerationX = 0L;
|
||||
double accelerationY = 0L;
|
||||
for (Particle particle : this.particles) {
|
||||
if (!particle.equals(this.focusParticle)) {
|
||||
Vec2 partialAcceleration = this.computeAcceleration(particle);
|
||||
accelerationX += partialAcceleration.getX();
|
||||
accelerationY += partialAcceleration.getY();
|
||||
}
|
||||
}
|
||||
return new ParticleUpdate(this.focusParticle, new Vec2(accelerationX, accelerationY));
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the acceleration which another particle imparts on this updater's
|
||||
* focus particle.
|
||||
* @param other The other particle which is acting upon the focus particle.
|
||||
* @return The acceleration, in m/s^2, which the focus particle experiences
|
||||
* from this particle.
|
||||
*/
|
||||
private Vec2 computeAcceleration(Particle other) {
|
||||
final double radius = this.focusParticle.getPosition().distance(other.getPosition());
|
||||
final double dY = other.getPosition().getY() - this.focusParticle.getPosition().getY();
|
||||
final double dX = other.getPosition().getX() - this.focusParticle.getPosition().getX();
|
||||
|
||||
final double angle = Math.atan2(dY, dX);
|
||||
|
||||
final double gravityNewtons = Constants.G * (this.focusParticle.getMass() * other.getMass()) / Math.pow(radius, 2);
|
||||
final double gravityAcceleration = gravityNewtons / this.focusParticle.getMass();
|
||||
final Vec2 gravityAccelerationVector = Vec2.fromPolar(gravityAcceleration, angle);
|
||||
// log.info(
|
||||
// "Force of gravity between particles {} and {} is {} Newtons.\nCauses {} m/s^2 acceleration on particle {}.",
|
||||
// this.focusParticle.getId(),
|
||||
// other.getId(),
|
||||
// gravityNewtons,
|
||||
// gravityAcceleration,
|
||||
// this.focusParticle.getId()
|
||||
// );
|
||||
|
||||
final double emNewtons = Constants.Ke * (this.focusParticle.getCharge() * other.getCharge()) / Math.pow(radius, 2);
|
||||
final double emAcceleration = emNewtons / this.focusParticle.getMass();
|
||||
final Vec2 emAccelerationVector = Vec2.fromPolar(emAcceleration, angle);
|
||||
|
||||
final Vec2 totalAcceleration = gravityAccelerationVector.add(emAccelerationVector);
|
||||
return totalAcceleration;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package nl.andrewlalis.threadripper.engine;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Simple vector for two double values, X and Y.
|
||||
*/
|
||||
@Getter
|
||||
public class Vec2 {
|
||||
private final double x;
|
||||
private final double y;
|
||||
|
||||
public Vec2(double x, double y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public static Vec2 fromPolar(double radius, double theta) {
|
||||
return new Vec2(
|
||||
radius * Math.cos(theta),
|
||||
radius * Math.sin(theta)
|
||||
);
|
||||
}
|
||||
|
||||
public Vec2 add(Vec2 other) {
|
||||
return new Vec2(this.getX() + other.getX(), this.getY() + other.getY());
|
||||
}
|
||||
|
||||
public Vec2 multiply(double factor) {
|
||||
return new Vec2(this.getX() * factor, this.getY() * factor);
|
||||
}
|
||||
|
||||
public double distance(Vec2 other) {
|
||||
final double deltaX = this.getX() - other.getX();
|
||||
final double deltaY = this.getY() - other.getY();
|
||||
return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (obj instanceof Vec2) {
|
||||
Vec2 other = (Vec2) obj;
|
||||
return other.getX() == this.getX() && other.getY() == this.getY();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[%f, %f]", this.getX(), this.getY());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package nl.andrewlalis.threadripper.particle;
|
||||
|
||||
import lombok.Getter;
|
||||
import nl.andrewlalis.threadripper.engine.Vec2;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Represents a single particle that exists in a simulation.
|
||||
*/
|
||||
@Getter
|
||||
public class Particle {
|
||||
private static long NEXT_PARTICLE_ID = 1L;
|
||||
|
||||
/**
|
||||
* Unique id for this particle.
|
||||
*/
|
||||
private long id;
|
||||
|
||||
/**
|
||||
* The particle's position, in meters.
|
||||
*/
|
||||
private Vec2 position;
|
||||
|
||||
/**
|
||||
* The particle's velocity, in meters.
|
||||
*/
|
||||
private Vec2 velocity;
|
||||
|
||||
/**
|
||||
* The particle's mass, in kilograms.
|
||||
*/
|
||||
private double mass;
|
||||
|
||||
/**
|
||||
* The particle's charge, in coulombs.
|
||||
*/
|
||||
private double charge;
|
||||
|
||||
public Particle(Vec2 position) {
|
||||
this(position, new Vec2(0, 0), 1, 0);
|
||||
}
|
||||
|
||||
public Particle(Vec2 position, Vec2 velocity, double mass, double charge) {
|
||||
this.position = position;
|
||||
this.velocity = velocity;
|
||||
this.mass = mass;
|
||||
this.charge = charge;
|
||||
|
||||
this.id = NEXT_PARTICLE_ID;
|
||||
NEXT_PARTICLE_ID++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates this particle's velocity, according to a delta velocity value,
|
||||
* @param acceleration Acceleration due to net force, in meters per second,
|
||||
* squared.
|
||||
* @param deltaTime The amount of time elapsed, in seconds.
|
||||
*/
|
||||
public void updateVelocity(Vec2 acceleration, double deltaTime) {
|
||||
this.velocity = this.velocity.add(acceleration.multiply(deltaTime));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates this particle's position, according to its current velocity.
|
||||
* @param deltaTime The amount of time that has elapsed, in seconds.
|
||||
*/
|
||||
public void updatePosition(double deltaTime) {
|
||||
this.position = this.position.add(this.getVelocity().multiply(deltaTime));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (obj instanceof Particle) {
|
||||
Particle other = (Particle) obj;
|
||||
return other.getId() == this.getId();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"{id: %d, mass: %f, charge: %f, position: %s, velocity: %s}",
|
||||
this.getId(),
|
||||
this.getMass(),
|
||||
this.getCharge(),
|
||||
this.getPosition(),
|
||||
this.getVelocity()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package nl.andrewlalis.threadripper.particle;
|
||||
|
||||
import nl.andrewlalis.threadripper.engine.Vec2;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class ParticleFactory {
|
||||
private final double minMass;
|
||||
private final double maxMass;
|
||||
private final double minCharge;
|
||||
private final double maxCharge;
|
||||
private final Vec2 minPosition;
|
||||
private final Vec2 maxPosition;
|
||||
private final Vec2 minVelocity;
|
||||
private final Vec2 maxVelocity;
|
||||
|
||||
public ParticleFactory(
|
||||
double minMass,
|
||||
double maxMass,
|
||||
double minCharge,
|
||||
double maxCharge,
|
||||
Vec2 minPosition,
|
||||
Vec2 maxPosition,
|
||||
Vec2 minVelocity,
|
||||
Vec2 maxVelocity
|
||||
) {
|
||||
this.minMass = minMass;
|
||||
this.maxMass = maxMass;
|
||||
this.minCharge = minCharge;
|
||||
this.maxCharge = maxCharge;
|
||||
this.minPosition = minPosition;
|
||||
this.maxPosition = maxPosition;
|
||||
this.minVelocity = minVelocity;
|
||||
this.maxVelocity = maxVelocity;
|
||||
}
|
||||
|
||||
public Particle build() {
|
||||
ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||
final Vec2 position = new Vec2(
|
||||
random.nextDouble(this.minPosition.getX(), this.maxPosition.getX()),
|
||||
random.nextDouble(this.minPosition.getY(), this.maxPosition.getY())
|
||||
);
|
||||
final Vec2 velocity = new Vec2(
|
||||
random.nextDouble(this.minVelocity.getX(), this.maxVelocity.getX()),
|
||||
random.nextDouble(this.minVelocity.getY(), this.maxVelocity.getY())
|
||||
);
|
||||
final double mass = random.nextDouble(this.minMass, this.maxMass);
|
||||
// final double charge = random.nextDouble(this.minCharge, this.maxCharge);
|
||||
|
||||
final double charge = 0;
|
||||
return new Particle(
|
||||
position,
|
||||
velocity,
|
||||
mass,
|
||||
charge
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue