This is exercise 3.2.23. from the book Computer Science An Interdisciplinary Approach by Sedgewick & Wayne:
Write a program that creates an array of charged particles from values given on standard input (each charged particle is specified by its x-coordinate, y-coordinate, and charge value) and produces a visualization of the electric potential in the unit square. To do so, sample points in the unit square. For each sampled point, compute the electric potential at that point (by summing the electric potentials due to each charged particle) and plot the corresponding point in a shade of gray proportional to the electric potential.
The following is the data-type implementation for charged particles from the book which I modified (beautified and added more appropriate names):
public class Charge {
private final double pointXCoordinate;
private final double pointYCoordinate;
private final double charge;
public Charge(double pointXCoordinate, double pointYCoordinate, double charge) {
this.pointXCoordinate = pointXCoordinate;
this.pointYCoordinate = pointYCoordinate;
this.charge = charge;
}
public double calculatePotentialAt(double otherPointXCoordinate, double otherPointYCoordinate) {
double electrostaticConstant = 8.99e09;
double distanceInXCoordinate = otherPointXCoordinate - pointXCoordinate;
double distanceInYCoordinate = otherPointYCoordinate - pointYCoordinate;
return electrostaticConstant * charge / Math.sqrt(distanceInXCoordinate * distanceInXCoordinate + distanceInYCoordinate * distanceInYCoordinate);
}
public String toString() {
return charge + " at (" + pointXCoordinate + "," + pointYCoordinate + ")";
}
}
Here is my program (but to increase the variety I created random particles instead of reading from input data):
import java.awt.Color;
public class Potential {
public static void main(String[] args) {
int width = Integer.parseInt(args[0]);
int height = Integer.parseInt(args[1]);
int numberOfCharges = Integer.parseInt(args[2]);
double chargeSignDistribution = Double.parseDouble(args[3]);
double chargeSizeDistribution = Double.parseDouble(args[4]);
Charge[] charges = new Charge[numberOfCharges];
for (int i = 0; i < numberOfCharges; i++) {
double pointXCoordinate = Math.random();
double pointYCoordinate = Math.random();
double charge = 0;
if (Math.random() < chargeSignDistribution) charge = -chargeSizeDistribution + Math.random() * chargeSizeDistribution;
else charge = Math.random() * chargeSizeDistribution;
charges[i] = new Charge(pointXCoordinate, pointYCoordinate, charge);
}
double[][] potentials = new double[width][height];
for (int j = 0; j < width; j++) {
for (int i = 0; i < height; i++) {
for (int k = 0; k < numberOfCharges; k++) {
potentials[j][i] += charges[k].calculatePotentialAt(1.0 * j / width, 1.0 * i / height);
}
/*
Obtained '180' by experimentation.
Scaled down by the amount of electrostatic constant (9e09).
*/
potentials[j][i] = 180 + potentials[j][i] / 9e09;
}
}
int[][] rescaledPotentials = new int[width][height];
for (int j = 0; j < width; j++) {
for (int i = 0; i < height; i++) {
if (potentials[j][i] < 0) rescaledPotentials[j][i] = 0;
else if (potentials[j][i] > 255) rescaledPotentials[j][i] = 255;
else rescaledPotentials[j][i] = (int) potentials[j][i];
}
}
Color[][] colors = new Color[width][height];
for (int j = 0; j < width; j++) {
for (int i = 0; i < height; i++) {
int c = rescaledPotentials[j][i];
colors[j][i] = new Color(c, c, c);
}
}
Picture picture = new Picture(width, height);
for (int j = 0; j < width; j++) {
for (int i = 0; i < height; i++) {
picture.set(j, i, colors[j][i]);
}
}
picture.show();
}
}
Picture is a simple API written by the authors of the book. I checked my program and it works. Here are two instances of it:
Input: 3840 2160 200 0.5 10
Output:
Input: 3840 2160 5000 0.5 5
Output:
Is there any way that I can improve my program?
Thanks for your attention.