Free Update that uses a ConcurrentHashMap to store 2D draw calls, Free Starter Class MIT License
package graphics;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import data.BooleanMatrix;
public class TwoColorImage {
BooleanMatrix pixels;
public int getWidth() {
return pixels.getWidth();
}
public int getHeight() {
return pixels.getHeight();
}
public TwoColorImage(int width, int height) {
pixels = new BooleanMatrix(width, height, false);
}
public TwoColorImage(BooleanMatrix pixels) {
this.pixels = pixels;
}
public BooleanMatrix getPixels() {
return pixels;
}
public void turnPixelOn(int x, int y) {
if (x<pixels.getWidth() && y<pixels.getHeight()) {
if (null!=inProgressSet) {
inProgressSet.add(new Point(x,y));
}
pixels.setElement(x, y, true);
}
}
public void turnPixelOff(int x, int y) {
if (x<pixels.getWidth() && y<pixels.getHeight()) {
pixels.setElement(x, y, false);
}
}
private class Point {
public Point(int x, int y) {
this.x=x;
this.y=y;
}
int x;
int y;
}
private static ConcurrentHashMap<String, Vector<Point>> processedCache = new ConcurrentHashMap<>();
private Vector<Point> inProgressSet;
private void startRecording() {
inProgressSet = new Vector<>();
}
private void stopRecording(String cacheName) {
processedCache.put(cacheName, inProgressSet);
inProgressSet = null;
}
private void drawFromCache(Vector<Point> cachedSet) {
inProgressSet=null;
cachedSet.stream().forEach((point)->{
turnPixelOn(point.x, point.y);
});
}
public void drawLine(int x1, int y1, int x2, int y2) {
String cacheName="drawLine("+x1+","+y1+","+x2+","+y2+")"+"["+getWidth()+","+getHeight()+"]";
Vector<Point> cachedVersion = processedCache.get(cacheName);
if (null!=cachedVersion) {
drawFromCache(cachedVersion);
return;
}
startRecording();
int yDifference = y2-y1;
int xDifference = x2-x1;
if (xDifference<0) {
// Switch points, draw left to right
int x1Temp=x1;
int x2Temp=x2;
int y1Temp=y1;
int y2Temp=y2;
x1=x2Temp;
y1=y2Temp;
x2=x1Temp;
y2=y1Temp;
xDifference = x2-x1;
}
if (x2>getWidth()-1) {
x2=getWidth()-1;
}
if (y2>getHeight()-1) {
y2=getHeight()-1;
}
double riseOverRun = (double) yDifference/xDifference;
double b = y1-(riseOverRun*x1);
turnPixelOn(x1, y1); // Draw start point
if (y1==y2) {
for (int x=x1+1; x<x2-1; x++) {
turnPixelOn(x, y1);
}
} else if (x1==x2) {
for (int y=y1+1; y<y2-1; y++) {
turnPixelOn(x1, y);
}
} else if (y1<y2){
double computedY;
double integerY;
double usedXs=x1;
double usedYs=y1;
for (int x=x1; x<x2; x++) {
computedY = (riseOverRun*x)+b;
integerY = (int) computedY;
if (x>usedXs) {
turnPixelOn((int)x, (int)integerY);
usedXs=x;
}
}
} else if (y2<y1) {
double computedY;
double integerY;
double usedXs=x1;
double usedYs=y1;
for (double x=x1; x<x2; x+=1) {
computedY = (riseOverRun*x)+b;
computedY = Math.abs(computedY);
integerY = (int) computedY;
integerY = Math.abs(integerY);
if (x>usedXs) {
turnPixelOn((int) x, (int) integerY);
usedXs=x;
}
}
}
turnPixelOn(x2, y2); // Draw end point
stopRecording(cacheName);
}
public void drawCircle(double x, double y, double radius) {
String cacheName = "drawCircle("+String.format("%.1f", x)+","
+String.format("%.1f", y)+","
+String.format("%.1f", radius)+")"
+"["+getWidth()+","+getHeight()+"]";
Vector<Point> cachedVersion = processedCache.get(cacheName);
if (null!=cachedVersion) {
drawFromCache(cachedVersion);
return;
}
startRecording();
double xPosition;
double yPosition;
double modLevel;
if (radius<200) {
modLevel=0.01;
} else if (radius<600) {
modLevel=0.005;
} else {
modLevel=0.001;
}
for (double radians=0; radians<6.28; radians+=modLevel) {
xPosition=y+(radius*Math.cos(radians));
yPosition=y+(radius*Math.sin(radians));
turnPixelOn((int) xPosition, (int) yPosition);
}
stopRecording(cacheName);
}
public void drawRectangeCoordinates(int x1, int y1, int x2, int y2) {
String cacheName="drawLine("+x1+","+y1+","+x2+","+y2+")"+"["+getWidth()+","+getHeight()+"]";
Vector<Point> cachedVersion = processedCache.get(cacheName);
if (null!=cachedVersion) {
drawFromCache(cachedVersion);
return;
}
startRecording();
for (int x=x1; x<=x2; x++) {
for (int y=y1; y<=y2; y++) {
if (x==x1 || x==x2 || y==y1 || y==y2) {
turnPixelOn(x, y);
}
}
}
stopRecording(cacheName);
}
public void drawRectangeFilledCoordinates(int x1, int y1, int x2, int y2) {
for (int x=x1; x<=x2; x++) {
for (int y=y1; y<=y2; y++) {
turnPixelOn(x, y);
}
}
}
}
HashMap Cache has potential to grow thus considering how I can optimize JVM Memory. I don’t have access to Profiling, people with Professional version of IntelliJ could look at this, currently showing 2GB on my Task Manager.