package hirondelle.starfield.physics;
import hirondelle.starfield.projection.Coords;
import hirondelle.starfield.projection.Projection;
import hirondelle.starfield.projection.Projector;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
final class StarfieldImage {
StarfieldImage(Projector aProjector, File aOutputFile, int aImageSize, int aMagnification){
fImageSize = aImageSize;
fMagnification = aMagnification;
fCenter = new Coords(aImageSize/2, aImageSize/2);
if (aProjector.isHalfSky()){
fScale = mapScaleHalfSky(aImageSize, fMagnification);
}
else {
fScale = mapScaleFullSky(aImageSize);
}
fProjection = aProjector.getProjection();
fOutputFile = aOutputFile;
initializeImage(aProjector);
}
void add(BoostedStar aBoostedStar, double aPhi ){
if (fCtx == null){
throw new IllegalStateException("Image file has already been generated. Cannot add another star.");
}
Coords coords = fProjection.project(aBoostedStar.ThetaPrime, aPhi, fScale, fCenter);
fCtx.setColor(Star.temperatureToColor(aBoostedStar.Temperature));
if (aBoostedStar.Magnitude > 4.5){
point(aBoostedStar, coords);
}
else {
square(aBoostedStar, coords);
}
fCtx.setColor(FOREGROUND_COLOR);
}
void generateFile() {
try {
ImageIO.write(fBufferedImage, fileExtension(), fOutputFile);
}
catch (IOException ex) {
ex.printStackTrace();
}
dispose();
}
void dispose(){
if (fCtx == null){
fCtx.dispose();
fCtx = null; }
}
private int fImageSize;
private int fMagnification = 1; private final Coords fCenter;
private Projection fProjection;
private File fOutputFile;
private double fScale = 0.0;
private BufferedImage fBufferedImage;
private Graphics2D fCtx;
private static double mapScaleFullSky(int aImageSize){
return 0.125D * aImageSize;
}
private static double mapScaleHalfSky(int aImageSize, int aMagnification){
return 0.5D * aImageSize * aMagnification;
}
private static final Color BACKGROUND_COLOR = new Color(50,50,50);
private static final Color FOREGROUND_COLOR = Color.yellow;
private void initializeImage(Projector aProjector){
fBufferedImage = new BufferedImage(fImageSize, fImageSize, BufferedImage.TYPE_INT_RGB);
fCtx = fBufferedImage.createGraphics();
if (aProjector.isHalfSky()){
fCtx.setColor(BACKGROUND_COLOR);
fCtx.fillRect(0, 0, fImageSize, fImageSize);
fCtx.setColor(Color.black);
fCtx.fillOval(fImageSize/2-fImageSize/2, 0, fImageSize, fImageSize);
Shape circle = new Ellipse2D.Double(fImageSize/2-fImageSize/2, 0,fImageSize, fImageSize);
fCtx.setClip(circle);
fCtx.setColor(FOREGROUND_COLOR);
}
}
private String fileExtension(){
int lastDot = fOutputFile.getName().lastIndexOf(".");
return fOutputFile.getName().substring(lastDot+1);
}
private void point(BoostedStar aBoostedStar, Coords coords){
fCtx.drawLine((int)coords.X, (int)coords.Y, (int)coords.X, (int)coords.Y);
}
private void square(BoostedStar aBoostedStar, Coords coords){
double size = magToSquareSize(aBoostedStar.Magnitude);
int x = (int)(coords.X - size); int y = (int)(coords.Y - size);
fCtx.fillRect(x, y, (int)size, (int)size);
}
private void spot(BoostedStar aBoostedStar, Coords coords){
int x = (int)(coords.X);
int y = (int)(coords.Y);
fCtx.fillOval(x, y, 20,20);
}
private void spot1(BoostedStar aBoostedStar, Coords coords){
double size = magToSpotSize(aBoostedStar.Magnitude);
int x = (int)(coords.X - size);
int y = (int)(coords.Y - size);
fCtx.fillOval(x, y, (int)size*2, (int) size*2);
}
private double magToSquareSize(double mag){
double result=0;
double MAG_0_SIZE=3;
double MAG_5_SIZE=1;
double BASE_RANGE=MAG_0_SIZE-MAG_5_SIZE;
result=MAG_0_SIZE - mag * (BASE_RANGE/5.0D);
return result;
}
private double magToSpotSize(double aMagnitude){
double result=0;
double MAG_0_SIZE = 0.75;
double MAG_5_SIZE = 0.1;
double BASE_RANGE = MAG_0_SIZE - MAG_5_SIZE;
result = MAG_0_SIZE - aMagnitude * (BASE_RANGE/5.0D);
return result;
}
}