/*
* Created on 13 mai 2005
*
* Tobot log tracer - write the trajectory of a robot into an image file.
*
*/
package contribs.robotlogtracer;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
/**
* This class will take a structure proposing the trace to create a png file (or a jpg) will be created.
* In the basic, i will use a pixel matrix, ie an array of array. This matrix defines a density of passages
* of the robots on each cases of the matrix. The more it went on a place, the darker the trace will be.
*
* How it works :
*
* The trace is represented by some kind of pixel Matrix. It is an integer matrix (ie int[][]).
* The value of the integers at the position [i][j] represent how much the robot went on the
* position [i][j] in the environment. So the more it went, the darker the trace will be ( because
* the value will be greater )
*
* In supplement, it is possible to plot points on specific locations with specific
* colors. For example i do put a red point on my starting position adding the position
* with the setBeginTrace(x,y) function
* For the collisions, i can add a second matrix to plot the collisions with green points.
*
* It is also now possible to trace manualy a point with the function : tracePoint(..)
*
*
* TODO : Tracing the walls should be hand-written
*
* @author Cedric Hartland
*
*/
public class LogTracer extends JFrame {
private static final long serialVersionUID = 1L;
private String _path = "log/trace-"+(System.currentTimeMillis()/1000);
private String _type = "png";
private final String [] _stringType = ImageIO.getWriterFormatNames();
private int _startingX;
private int _startingZ;
/**
* Default constructor.
*
*/
public LogTracer () { }
/**
* Second constructor, take the path and the name of the (PNG) file to create.
* @param __pathFile the formated \"path/filename.png\" to create
*/
public LogTracer (String __pathFile)
{
_path=__pathFile;
}
/**
* Thrid constructor, takes a path and a file type (image type). The pah may be empty if the default is to be used.
* @param __pathFile
* @param __type
*/
public LogTracer (String __pathFile, String __type)
{
if (__pathFile!="") _path=__pathFile;
boolean found=false;
int i=0;
while (i<_stringType.length && !found)
{
if (_stringType[i]==_type)
{
_type=__type;
found=true;
}
i++;
}
if (!found)
{
_type="png";
System.err.println("Warning : the given type of file is unsupported, please ensure the format is correct");
System.err.println("Warning : the file type for the traces will be png instead");
}
}
/**
* decide the type from the path name, else, keep the default one.
*
*/
private void setType(){
try
{
// if the last four are to be the file type, then, we can change the file type
// else we do nothing but just test for the last char to be a dot, else we add
char dot = _path.charAt(_path.length()-4);
if (dot=='.')
{
String type = _path.substring(_path.length()-3,_path.length());
boolean found=false;
int i=0;
while (i<_stringType.length && !found)
{
if (_stringType[i].compareTo(type)==0)
{
_type=type;
found=true;
}
i++;
}
_path=_path.substring(0,_path.length()-4);
if (!found)
{
_type="png";
System.err.println("Warning : the given type of file is unsupported, please ensure the format is correct");
System.err.println("Warning : the file type for the traces will be png instead");
System.err.flush();
}
}
}
catch(Exception e)
{
//do nothing
}
}
/**
* trace a point on the graphic
* @param bi
* @param colour
* @param width
* @param height
*/
private void tracePoint(BufferedImage bi, int colour, int width, int height)
{
// define the range of the coords
int beginX;
int endX;
int beginZ;
int endZ;
if (this._startingX<10) beginX=0;
else beginX=this._startingX-10;
if (this._startingX>height-10) endX=height;
else endX=this._startingX+10;
if (this._startingZ<10) beginZ=0;
else beginZ=this._startingZ-10;
if (this._startingZ>width-10) endZ=width;
else endZ=this._startingZ+10;
for(int i=beginX; i<endX; i++) bi.setRGB(i,this._startingZ,colour);
for(int i=beginZ; i<endZ; i++) bi.setRGB(this._startingX,i,colour);
}
/**
* trace a point on the graphic
* @param bi
* @param colour
* @param width
* @param height
* @param x
* @param z
*/
public void tracePoint(BufferedImage bi, int colour, int width, int height, int x, int z)
{
// define the range of the coords
int beginX;
int endX;
int beginZ;
int endZ;
if (x<10) beginX=0;
else beginX=x-10;
if (x>height-10) endX=height;
else endX=x+10;
if (z<10) beginZ=0;
else beginZ=z-10;
if (z>width-10) endZ=width;
else endZ=z+10;
for(int i=beginX; i<endX; i++) bi.setRGB(i,z,colour);
for(int i=beginZ; i<endZ; i++) bi.setRGB(x,i,colour);
}
public void setBeginTrace(int __x, int __z)
{
this._startingX=__x;
this._startingZ=__z;
}
/**
* This function commits the trace of the pixel matrix to a precise filename and path. The default output generated will be a png.
* @param traceMatrix the trace matrix that will be used to generate a file.
* @param __path the path and the name of the file to generate
*/
public void commitTrace(int [] [] traceMatrix, String __path)
{
_path = __path;
commitTrace(traceMatrix);
}
/**
* This function commits the trace of the pixel matrix to a precise filename and path. The default output generated will be a png.
* @param traceMatrix the trace matrix that will be used to generate a file.
* @param __path the path and the name of the file to generate
*/
public void commitTrace(int [] [] traceMatrix, String __path, boolean [][] collisionMatrix)
{
_path = __path;
commitTrace(traceMatrix,collisionMatrix);
}
/**
* Get the traceMatrix and write the image corresponding to a file. The height/width length of the matrix will be the same as the height/width of the image.
* The trace matrix represents the arena and the number of times the robots
* have been on a quadrant of it. The more it went, the darker the trace
* will be.
* @param traceMatrix the trace matrix generated by the robot
*/
public void commitTrace(int [][] traceMatrix)
{
setType();
//define the height/width of the image
int height=traceMatrix.length;
int width=traceMatrix[0].length;
// integrity checks
for(int i=0;i<traceMatrix.length;i++)
{
if (traceMatrix[i].length!=width)
{
System.err.println("The pixel matrix is not well formed, it should be X*Y but some of its columns are not the right size");
return;
}
}
//define the BufferedImage
BufferedImage bufferedImage = new BufferedImage(height,width,BufferedImage.TYPE_INT_RGB);
//the trace define an intensity of passage to a pixel point, the more it is visited, the darker it will be.
int value,col;
int alpha = 255;
int red = 255;
int green = 255;
int blue = 255;
// we fill the BufferedImage
for(int i=0; i<height;i++)
{
for(int j=0;j<width;j++)
{
// to be visible, we define grey traits on white board
value= Math.min(255,10*(traceMatrix[i][j]));
col = (alpha << 24) | ((red-value) << 16) | ((green-value) << 8 ) | (blue-value);
bufferedImage.setRGB(i,j,col);
}
}
// set the starting point
if (this._startingX!=0 || this._startingZ!=0)
{
col = (alpha << 24) | ((red) << 16) | ((green-255) << 8 ) | (blue-255);
this.tracePoint(bufferedImage,col,width,height);
}
// finaly we write the BufferedImage to a file
try {
File f = new File(_path+"."+_type);
ImageIO.write( bufferedImage , _type , f );
}
catch(Exception e){
System.out.println("Error append during the creation of the image");
System.out.println("The process will now try to write it in the root of the classpath");
try {
System.err.println("Warning : the file could not be created, another try with the default settings will be computed on the root path");
_path = "trace-"+(System.currentTimeMillis()/1000)+"."+this._type;
File f = new File(_path);
ImageIO.write( bufferedImage , _type , f );
}
catch(Exception e2){ e.printStackTrace(); }
}
}
/**
* * Get the traceMatrix and write the image corresponding to a file. The height/width length of the matrix will be the same as the height/width of the image.
* The trace matrix represents the arena and the number of times the robots
* have been on a quadrant of it. The more it went, the darker the trace
* will be.
* @param traceMatrix the trace matrix generated by the robot
* @param collisionMatrix define the points where the robot did hit the wall
*/
public void commitTrace(int [][] traceMatrix, boolean [][] collisionMatrix)
{
setType();
//define the height/width of the image
int height=traceMatrix.length;
int width=traceMatrix[0].length;
// integrity checks
for(int i=0;i<traceMatrix.length;i++)
{
if (traceMatrix[i].length!=width)
{
System.err.println("The pixel matrix is not well formed, it should be X*Y but some of its columns are not the right size");
return;
}
}
for(int i=0;i<collisionMatrix.length;i++)
{
if (collisionMatrix[i].length!=width)
{
System.err.println("The pixel matrix is not well formed, it should be X*Y but some of its columns are not the right size");
return;
}
}
//define the BufferedImage
BufferedImage bufferedImage = new BufferedImage(height,width,BufferedImage.TYPE_INT_RGB);
//the trace define an intensity of passage to a pixel point, the more it is visited, the darker it will be.
int value,col;
int alpha = 255;
int red = 255;
int green = 255;
int blue = 255;
// we fill the BufferedImage
for(int i=0; i<height;i++)
{
for(int j=0;j<width;j++)
{
// to be visible, we define grey traits on white board
value= Math.min(255,10*(traceMatrix[i][j]));
col = (alpha << 24) | ((red-value) << 16) | ((green-value) << 8 ) | (blue-value);
bufferedImage.setRGB(i,j,col);
}
}
// put points on the colision positions
for(int i=0; i<height;i++)
{
for(int j=0;j<width;j++)
{
if (collisionMatrix[i][j])
{
col = (alpha << 24) | ((red-255) << 16) | ((green) << 8 ) | (blue-255);
this.tracePoint(bufferedImage,col,width,height,i,j);
}
}
}
// set the starting point
if (this._startingX!=0 || this._startingZ!=0)
{
col = (alpha << 24) | ((red) << 16) | ((green-255) << 8 ) | (blue-255);
this.tracePoint(bufferedImage,col,width,height);
}
// finaly we write the BufferedImage to a file
try {
File f = new File(_path+"."+_type);
ImageIO.write( bufferedImage , _type , f );
}
catch(Exception e){
System.out.println("Error append during the creation of the image");
System.out.println("The process will now try to write it in the root of the classpath");
try {
System.err.println("Warning : the file could not be created, another try with the default settings will be computed on the root path");
_path = "trace-"+(System.currentTimeMillis()/1000)+"."+this._type;
File f = new File(_path);
ImageIO.write( bufferedImage , _type , f );
}
catch(Exception e2){ e.printStackTrace(); }
}
}
/**
* TEST: used to test the class.
* @param args the arguments ...
*/
public static void main(String[] args)
{
int [][] trace = new int [256][256];
int k=0;
for(int i=0;i<trace.length;i++)
{
for(int j=0;j<trace[i].length;j++)
{
if (i==100 & j<100) trace[i][j]=(k++)/10;
if (j==100 & i>100 & i<180) trace[i][j]=(k++)/10;
if (i==180 & j>100) trace[i][j]=(k++)/10;
//trace[i][j]=rand.nextInt((k++/1000)+1);
}
}
LogTracer tr = new LogTracer("trace.png");
tr.commitTrace(trace);
//tr.setType();
}
}