I have found Haralick's algorithm already implemented. It is used to get some feature with the help of Gray-Level Co-occurence matrices.
Now i have problems getting it to work. There are no exceptions. The code is fine. I'm not sure where to begin. Can someone help me with the first steps?How to i get a texture feature?
Below you can find the complete Haralick source code:
package de.lmu.dbs.jfeaturelib.features;
import Jama.Matrix;
import de.lmu.dbs.jfeaturelib.Progress;
import de.lmu.ifi.dbs.utilities.Arrays2;
import ij.plugin.filter.PlugInFilter;
import ij.process.ByteProcessor;
import ij.process.ImageProcessor;
import java.util.Arrays;
import java.util.EnumSet;
/**
* Haralick texture features
*
* http://makseq.com/materials/lib/Articles-Books/Filters/Texture/Co-occurence/haralick73.pdf
* <pre>
* #article{haralick1973textural,
* title={Textural features for image classification},
* author={Haralick, R.M. and Shanmugam, K. and Dinstein, I.},
* journal={Systems, Man and Cybernetics, IEEE Transactions on},
* volume={3},
* number={6},
* pages={610--621},
* year={1973},
* publisher={IEEE}
* }
* </pre>
*
* #author graf
*/
public class Haralick extends AbstractFeatureDescriptor {
/**
* The number of gray values for the textures
*/
private final int NUM_GRAY_VALUES = 32;
/**
* p_(x+y) statistics
*/
private double[] p_x_plus_y = new double[2 * NUM_GRAY_VALUES - 1];
/**
* p_(x-y) statistics
*/
private double[] p_x_minus_y = new double[NUM_GRAY_VALUES];
/**
* row mean value
*/
private double mu_x = 0;
/**
* column mean value
*/
private double mu_y = 0;
/**
* row variance
*/
private double var_x = 0;
/**
* column variance
*/
private double var_y = 0;
/**
* HXY1 statistics
*/
private double hx = 0;
/**
* HXY2 statistics
*/
private double hy = 0;
/**
* HXY1 statistics
*/
private double hxy1 = 0;
/**
* HXY2 statistics
*/
private double hxy2 = 0;
/**
* p_x statistics
*/
private double[] p_x = new double[NUM_GRAY_VALUES];
/**
* p_y statistics
*/
private double[] p_y = new double[NUM_GRAY_VALUES];
// -
private int haralickDist;
double[] features = null;
/**
* Constructs a haralick detector with default parameters.
*/
public Haralick() {
this.haralickDist = 1;
}
/**
* Constructs a haralick detector.
*
* #param haralickDist Integer for haralick distribution
*/
public Haralick(int haralickDist) {
this.haralickDist = haralickDist;
}
/**
* Defines the capability of the algorithm.
*
* #see PlugInFilter
* #see #supports()
*/
#Override
public EnumSet<Supports> supports() {
EnumSet set = EnumSet.of(
Supports.NoChanges,
Supports.DOES_8C,
Supports.DOES_8G,
Supports.DOES_RGB);
return set;
}
/**
* Starts the haralick detection.
*
* #param ip ImageProcessor of the source image
*/
#Override
public void run(ImageProcessor ip) {
if (!ByteProcessor.class.isAssignableFrom(ip.getClass())) {
ip = ip.convertToByte(true);
}
firePropertyChange(Progress.START);
process((ByteProcessor) ip);
addData(features);
firePropertyChange(Progress.END);
}
/**
* Returns information about the getFeature
*/
#Override
public String getDescription() {
StringBuilder sb = new StringBuilder();
sb.append("Haralick features: ");
sb.append("Angular 2nd moment, ");
sb.append("Contrast, ");
sb.append("Correlation, ");
sb.append("variance, ");
sb.append("Inverse Difference Moment, ");
sb.append("Sum Average, ");
sb.append("Sum Variance, ");
sb.append("Sum Entropy, ");
sb.append("Entropy, ");
sb.append("Difference Variance, ");
sb.append("Difference Entropy, ");
sb.append("Information Measures of Correlation, ");
sb.append("Information Measures of Correlation, ");
sb.append("Maximum Correlation COefficient");
return sb.toString();
}
private void process(ByteProcessor image) {
features = new double[14];
firePropertyChange(new Progress(1, "creating coocurrence matrix"));
Coocurrence coocurrence = new Coocurrence(image, NUM_GRAY_VALUES, this.haralickDist);
double[][] cooccurrenceMatrix = coocurrence.getCooccurrenceMatrix();
double meanGrayValue = coocurrence.getMeanGrayValue();
firePropertyChange(new Progress(25, "normalizing"));
normalize(cooccurrenceMatrix, coocurrence.getCooccurenceSums());
firePropertyChange(new Progress(50, "computing statistics"));
calculateStatistics(cooccurrenceMatrix);
firePropertyChange(new Progress(75, "computing features"));
double[][] p = cooccurrenceMatrix;
double[][] Q = new double[NUM_GRAY_VALUES][NUM_GRAY_VALUES];
for (int i = 0; i < NUM_GRAY_VALUES; i++) {
double sum_j_p_x_minus_y = 0;
for (int j = 0; j < NUM_GRAY_VALUES; j++) {
double p_ij = p[i][j];
sum_j_p_x_minus_y += j * p_x_minus_y[j];
features[0] += p_ij * p_ij;
features[2] += i * j * p_ij - mu_x * mu_y;
features[3] += (i - meanGrayValue) * (i - meanGrayValue) * p_ij;
features[4] += p_ij / (1 + (i - j) * (i - j));
features[8] += p_ij * log(p_ij);
// feature 13
if (p_ij != 0 && p_x[i] != 0) { // would result in 0
for (int k = 0; k < NUM_GRAY_VALUES; k++) {
if (p_y[k] != 0 && p[j][k] != 0) { // would result in NaN
Q[i][j] += (p_ij * p[j][k]) / (p_x[i] * p_y[k]);
}
}
}
}
features[1] += i * i * p_x_minus_y[i];
features[9] += (i - sum_j_p_x_minus_y) * (i - sum_j_p_x_minus_y) * p_x_minus_y[i];
features[10] += p_x_minus_y[i] * log(p_x_minus_y[i]);
}
// feature 13: Max Correlation Coefficient
double[] realEigenvaluesOfQ = new Matrix(Q).eig().getRealEigenvalues();
Arrays2.abs(realEigenvaluesOfQ);
Arrays.sort(realEigenvaluesOfQ);
features[13] = Math.sqrt(realEigenvaluesOfQ[realEigenvaluesOfQ.length - 2]);
features[2] /= Math.sqrt(var_x * var_y);
features[8] *= -1;
features[10] *= -1;
double maxhxhy = Math.max(hx, hy);
if (Math.signum(maxhxhy) == 0) {
features[11] = 0;
} else {
features[11] = (features[8] - hxy1) / maxhxhy;
}
features[12] = Math.sqrt(1 - Math.exp(-2 * (hxy2 - features[8])));
for (int i = 0; i < 2 * NUM_GRAY_VALUES - 1; i++) {
features[5] += i * p_x_plus_y[i];
features[7] += p_x_plus_y[i] * log(p_x_plus_y[i]);
double sum_j_p_x_plus_y = 0;
for (int j = 0; j < 2 * NUM_GRAY_VALUES - 1; j++) {
sum_j_p_x_plus_y += j * p_x_plus_y[j];
}
features[6] += (i - sum_j_p_x_plus_y) * (i - sum_j_p_x_plus_y) * p_x_plus_y[i];
}
features[7] *= -1;
}
/**
* Calculates the statistical properties.
*/
private void calculateStatistics(double[][] cooccurrenceMatrix) {
// p_x, p_y, p_x+y, p_x-y
for (int i = 0; i < NUM_GRAY_VALUES; i++) {
for (int j = 0; j < NUM_GRAY_VALUES; j++) {
double p_ij = cooccurrenceMatrix[i][j];
p_x[i] += p_ij;
p_y[j] += p_ij;
p_x_plus_y[i + j] += p_ij;
p_x_minus_y[Math.abs(i - j)] += p_ij;
}
}
// mean and variance values
double[] meanVar;
meanVar = meanVar(p_x);
mu_x = meanVar[0];
var_x = meanVar[1];
meanVar = meanVar(p_y);
mu_y = meanVar[0];
var_y = meanVar[1];
for (int i = 0; i < NUM_GRAY_VALUES; i++) {
// hx and hy
hx += p_x[i] * log(p_x[i]);
hy += p_y[i] * log(p_y[i]);
// hxy1 and hxy2
for (int j = 0; j < NUM_GRAY_VALUES; j++) {
double p_ij = cooccurrenceMatrix[i][j];
hxy1 += p_ij * log(p_x[i] * p_y[j]);
hxy2 += p_x[i] * p_y[j] * log(p_x[i] * p_y[j]);
}
}
hx *= -1;
hy *= -1;
hxy1 *= -1;
hxy2 *= -1;
}
/**
* Compute mean and variance of the given array
*
* #param a inut values
* #return array{mean, variance}
*/
private double[] meanVar(double[] a) {
// VAR(X) = E(X^2) - E(X)^2
double ex = 0, ex2 = 0; // E(X), E(X^2)
for (int i = 0; i < NUM_GRAY_VALUES; i++) {
ex += a[i];
ex2 += a[i] * a[i];
}
ex /= a.length;
ex2 /= a.length;
double var = ex2 - ex * ex;
return new double[]{ex, var};
}
/**
* Returns the logarithm of the specified value.
*
* #param value the value for which the logarithm should be returned
* #return the logarithm of the specified value
*/
private double log(double value) {
double log = Math.log(value);
if (log == Double.NEGATIVE_INFINITY) {
log = 0;
}
return log;
}
private void normalize(double[][] A, double sum) {
for (int i = 0; i < A.length; i++) {
Arrays2.div(A[i], sum);
}
}
//<editor-fold defaultstate="collapsed" desc="getter/Setter">
/**
* Getter for haralick distributions
*
* #return haralick distributions
*/
public int getHaralickDist() {
return haralickDist;
}
/**
* Setter for haralick distributions
*
* #param haralickDist int for haralick distributions
*/
public void setHaralickDist(int haralickDist) {
this.haralickDist = haralickDist;
}
//</editor-fold>
}
//<editor-fold defaultstate="collapsed" desc="Coocurrence Matrix">
/**
* http://makseq.com/materials/lib/Articles-Books/Filters/Texture/Co-occurence/haralick73.pdf
*/
class Coocurrence {
/**
* The number of gray values for the textures
*/
private final int NUM_GRAY_VALUES;
/**
* The number of gray levels in an image
*/
private final int GRAY_RANGES = 256;
/**
* The scale for the gray values for conversion rgb to gray values.
*/
private final double GRAY_SCALE;
/**
* gray histogram of the image.
*/
private final double[] grayHistogram;
/**
* quantized gray values of each pixel of the image.
*/
private final byte[] grayValue;
/**
* mean gray value
*/
private double meanGrayValue = 0;
/**
* The cooccurrence matrix
*/
private final double[][] cooccurrenceMatrices;
/**
* The value for one increment in the gray/color histograms.
*/
private final int HARALICK_DIST;
private final ByteProcessor image;
public Coocurrence(ByteProcessor b, int numGrayValues, int haralickDist) {
this.NUM_GRAY_VALUES = numGrayValues;
this.image = b;
this.GRAY_SCALE = (double) GRAY_RANGES / (double) NUM_GRAY_VALUES;
this.cooccurrenceMatrices = new double[NUM_GRAY_VALUES][NUM_GRAY_VALUES];
this.grayValue = new byte[image.getPixelCount()];
this.grayHistogram = new double[GRAY_RANGES];
this.HARALICK_DIST = haralickDist;
calculate();
}
public double getMeanGrayValue() {
return this.meanGrayValue;
}
public double[][] getCooccurrenceMatrix() {
return this.cooccurrenceMatrices;
}
public double getCooccurenceSums() {
return image.getPixelCount() * 8;
}
private void calculate() {
calculateGreyValues();
final int imageWidth = image.getWidth();
final int imageHeight = image.getHeight();
final int d = HARALICK_DIST;
int i, j, pos;
// image is not empty per default
for (int y = 0; y < imageHeight; y++) {
for (int x = 0; x < imageWidth; x++) {
pos = imageWidth * y + x;
// horizontal neighbor: 0 degrees
i = x - d;
// j = y;
if (!(i < 0)) {
increment(grayValue[pos], grayValue[pos - d]);
}
// vertical neighbor: 90 degree
// i = x;
j = y - d;
if (!(j < 0)) {
increment(grayValue[pos], grayValue[pos - d * imageWidth]);
}
// 45 degree diagonal neigbor
i = x + d;
j = y - d;
if (i < imageWidth && !(j < 0)) {
increment(grayValue[pos], grayValue[pos + d - d * imageWidth]);
}
// 135 vertical neighbor
i = x - d;
j = y - d;
if (!(i < 0) && !(j < 0)) {
increment(grayValue[pos], grayValue[pos - d - d * imageWidth]);
}
}
}
meanGrayValue = Arrays2.sum(grayValue);
}
private void calculateGreyValues() {
int size = image.getPixelCount();
int gray;
for (int pos = 0; pos < size; pos++) {
gray = image.get(pos);
grayValue[pos] = (byte) (gray / GRAY_SCALE); // quantized for texture analysis
grayHistogram[gray]++;
}
Arrays2.div(grayHistogram, size);
}
/**
* Incremets the coocurrence matrix at the specified positions (g1,g2) and
* (g2,g1).
*
* #param g1 the gray value of the first pixel
* #param g2 the gray value of the second pixel
*/
private void increment(int g1, int g2) {
cooccurrenceMatrices[g1][g2]++;
cooccurrenceMatrices[g2][g1]++;
}
}
//</editor-fold>
Here you have the source.
Thanks in advance=)
Related
I created a applet using threads. When i run it and change the size of the window I see a few copies of "Applet started" string. I wonder why is that and how to fix that?
When exactly does this strin starts?
here is my code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Random;
import javax.swing.JApplet;
public class app extends javax.swing.JApplet {
/**
*
*/
Random generator = new Random();
public int n = 15;
public int m = 15;
public int k = 200;
public int size = 25;
public kwadrat[][] watki;
public double p = 0.98;
public boolean sth = true ;
/**
* Function initializes threads by given data
* #exception NumberFormatException when there is no data from html code
*
*/
public void init(){
try{n = Integer.parseInt(getParameter("n"));}
catch( NumberFormatException e){
System.out.println("Nieprawidłowy parametr: n");
}
catch( NullPointerException e){}
try{m = Integer.parseInt(getParameter("m"));}
catch( NumberFormatException e){
System.out.println("Nieprawidłowy parametr: m");
}
catch( NullPointerException e){}
try{k = Integer.parseInt(getParameter("k"));}
catch( NumberFormatException e){
System.out.println("Nieprawidłowy parametr: k");
}
catch( NullPointerException e){}
try{ p = Double.parseDouble(getParameter("p"));}
catch( NumberFormatException e){
System.out.println("Nieprawidłowy parametr: k");
}
catch( NullPointerException e){}
watki = new kwadrat[n][m];
for (int i = 0 ; i < n ; ++i)
for (int j = 0 ; j < m ; ++j){
watki[i][j] = new kwadrat(10+i*size,
10+j*size,
i,
j,
size,
(int)(k*(generator.nextDouble()+0.5)),
new java.awt.Color(generator.nextInt(255),
generator.nextInt(255),
generator.nextInt(255)
)
);
}
}
/**
* start method start the threads
*/
public void start(){
for (int i = 0 ; i < n ; ++i)
for (int j = 0 ; j < m ; ++j){
Thread t;
t = new Thread( new MovingRunnable(watki[i][j]));
t.start();
}
}
/**
* Paint method is responsible for drawing the rectangles(threads)
*/
public void paint(Graphics g){
//super.paint(g);
//g.fillRect(0, 0, 1000, 1000);
repaint();
for (int i = 0 ; i < n ; ++i)
for (int j = 0 ; j < m ; ++j){
g.setColor(watki[i][j].kwadratColor);
g.fillRect(watki[i][j].x, watki[i][j].y, size, size);
}
}
/**
*
* #author Seba
* Class MovingRunnable implements Runnable includes rectangles as threads
* #param b it is object of kwadrat class
* #param run() main method of the class. Changes color of rectangles
* #exception InterruptedException when something is wrong with sleeping thread
*/
private class MovingRunnable implements Runnable{
private final kwadrat b;
private MovingRunnable(kwadrat b){this.b=b;}
public void run(){
for(;;){
if(generator.nextDouble()<p){
int c1 = 0,c2 = 0,c3 = 0;
if(b.nrx>0){
c1 += watki[b.nrx-1][b.nry].kwadratColor.getRed();
c2 += watki[b.nrx-1][b.nry].kwadratColor.getGreen();
c3 += watki[b.nrx-1][b.nry].kwadratColor.getBlue();
}
if(b.nrx<n-1) {
c1 += watki[b.nrx+1][b.nry].kwadratColor.getRed();
c2 += watki[b.nrx+1][b.nry].kwadratColor.getGreen();
c3 += watki[b.nrx+1][b.nry].kwadratColor.getBlue();
}
if(b.nry>0) {
c1 += watki[b.nrx][b.nry-1].kwadratColor.getRed();
c2 += watki[b.nrx][b.nry-1].kwadratColor.getGreen();
c3 += watki[b.nrx][b.nry-1].kwadratColor.getBlue();
}
if(b.nry<m-1) {
c1 += watki[b.nrx][b.nry+1].kwadratColor.getRed();
c2 += watki[b.nrx][b.nry+1].kwadratColor.getGreen();
c3 += watki[b.nrx][b.nry+1].kwadratColor.getBlue();
}
b.changeColor(new java.awt.Color(c1/4,c2/4,c3/4));
}
else
//b.changeColor(Color.GRAY);
b.changeColor(generator);
repaint();
try {
Thread.sleep(b.wait);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
/**
*
* #author Seba
* #param x position in x
* #param y position in y
* #param nrx x position in watki[][] array
* #param nry y position in watki[][] array
* #param wait time of sleeping thread
* #param size size of side
* #param kwadratColor - color of the ractangle
* #param kwadrat(int,int,int,int,int,int,Color) main constructor
* #param changeColor(Random) changing color by generating Random
* #param changeColor(Color) changing color to given color
*/
class kwadrat{
public int x;
public int y;
public int nrx;
public int nry;
public int wait;
public int size;
Color kwadratColor;
public kwadrat( int x, int y, int nrx, int nry, int size , int wait, Color kwadratColor){
this.x = x;
this.y = y;
this.nrx = nrx;
this.nry = nry;
this.size = size;
this.kwadratColor = kwadratColor;
this.wait = wait;
}
public void changeColor(Random gen){
kwadratColor = new java.awt.Color(gen.nextInt(255),
gen.nextInt(255),
gen.nextInt(255)
);
}
public void changeColor(Color x){
kwadratColor = x;
}
}
For an assignment I'm supposed to test different types of recommenders, which I have to implement first. I've been looking around for a good library to do that (I had thought about Weka at first) and stumbled upon Mahout.
I must therefore put forward that: a) I'm completely new to Mahout b) I do not have a strong background in recommenders nor their algorithms (otherwise I wouldn't be doing this class...) and c) sorry but I'm far from being the best developper in the world ==> I'd appreciate if you could use layman terms (as far as possible...) :)
I've been following some tutorials (e.g. this, as well as part2) and got some preliminary results on item-based and user-based recommenders.
However, I'm not very happy with the item-based prediction. So far, I've only found similarity functions that do not take into consideration the users' rating-biases. I was wondering if there is something like adjusted cosine similarity. Any hints?
Here is a sample of the AdjustedCosineSimilarity I created. You must remember that this will be slower than PearsonCorrelationSimilarity because of the sqrt computations, but will produce better results. At least for my dataset results were much better. But you should make a trade off, quality/performance, and depending of your needs you should use the implementation you want.
/**
* Custom implementation of {#link AdjustedCosineSimilarity}
*
* #author dmilchevski
*
*/
public class AdjustedCosineSimilarity extends AbstractSimilarity {
/**
* Creates new {#link AdjustedCosineSimilarity}
*
* #param dataModel
* #throws TasteException
*/
public AdjustedCosineSimilarity(DataModel dataModel)
throws TasteException {
this(dataModel, Weighting.UNWEIGHTED);
}
/**
* Creates new {#link AdjustedCosineSimilarity}
*
* #param dataModel
* #param weighting
* #throws TasteException
*/
public AdjustedCosineSimilarity(DataModel dataModel, Weighting weighting)
throws TasteException {
super(dataModel, weighting, true);
Preconditions.checkArgument(dataModel.hasPreferenceValues(),
"DataModel doesn't have preference values");
}
/**
* Compute the result
*/
#Override
double computeResult(int n, double sumXY, double sumX2, double sumY2, double sumXYdiff2) {
if (n == 0) {
return Double.NaN;
}
// Note that sum of X and sum of Y don't appear here since they are
// assumed to be 0;
// the data is assumed to be centered.
double denominator = Math.sqrt(sumX2) * Math.sqrt(sumY2);
if (denominator == 0.0) {
// One or both parties has -all- the same ratings;
// can't really say much similarity under this measure
return Double.NaN;
}
return sumXY / denominator;
}
/**
* Gets the average preference
* #param prefs
* #return
*/
private double averagePreference(PreferenceArray prefs){
double sum = 0.0;
int n = prefs.length();
for(int i=0; i<n; i++){
sum+=prefs.getValue(i);
}
if(n>0){
return sum/n;
}
return 0.0d;
}
/**
* Compute the item similarity between two items
*/
#Override
public double itemSimilarity(long itemID1, long itemID2) throws TasteException {
DataModel dataModel = getDataModel();
PreferenceArray xPrefs = dataModel.getPreferencesForItem(itemID1);
PreferenceArray yPrefs = dataModel.getPreferencesForItem(itemID2);
int xLength = xPrefs.length();
int yLength = yPrefs.length();
if (xLength == 0 || yLength == 0) {
return Double.NaN;
}
long xIndex = xPrefs.getUserID(0);
long yIndex = yPrefs.getUserID(0);
int xPrefIndex = 0;
int yPrefIndex = 0;
double sumX = 0.0;
double sumX2 = 0.0;
double sumY = 0.0;
double sumY2 = 0.0;
double sumXY = 0.0;
double sumXYdiff2 = 0.0;
int count = 0;
// No, pref inferrers and transforms don't appy here. I think.
while (true) {
int compare = xIndex < yIndex ? -1 : xIndex > yIndex ? 1 : 0;
if (compare == 0) {
// Both users expressed a preference for the item
double x = xPrefs.getValue(xPrefIndex);
double y = yPrefs.getValue(yPrefIndex);
long xUserId = xPrefs.getUserID(xPrefIndex);
long yUserId = yPrefs.getUserID(yPrefIndex);
double xMean = averagePreference(dataModel.getPreferencesFromUser(xUserId));
double yMean = averagePreference(dataModel.getPreferencesFromUser(yUserId));
sumXY += (x - xMean) * (y - yMean);
sumX += x;
sumX2 += (x - xMean) * (x - xMean);
sumY += y;
sumY2 += (y - yMean) * (y - yMean);
double diff = x - y;
sumXYdiff2 += diff * diff;
count++;
}
if (compare <= 0) {
if (++xPrefIndex == xLength) {
break;
}
xIndex = xPrefs.getUserID(xPrefIndex);
}
if (compare >= 0) {
if (++yPrefIndex == yLength) {
break;
}
yIndex = yPrefs.getUserID(yPrefIndex);
}
}
double result;
// See comments above on these computations
double n = (double) count;
double meanX = sumX / n;
double meanY = sumY / n;
// double centeredSumXY = sumXY - meanY * sumX - meanX * sumY + n *
// meanX * meanY;
double centeredSumXY = sumXY - meanY * sumX;
// double centeredSumX2 = sumX2 - 2.0 * meanX * sumX + n * meanX *
// meanX;
double centeredSumX2 = sumX2 - meanX * sumX;
// double centeredSumY2 = sumY2 - 2.0 * meanY * sumY + n * meanY *
// meanY;
double centeredSumY2 = sumY2 - meanY * sumY;
// result = computeResult(count, centeredSumXY, centeredSumX2,
// centeredSumY2, sumXYdiff2);
result = computeResult(count, sumXY, sumX2, sumY2, sumXYdiff2);
if (!Double.isNaN(result)) {
result = normalizeWeightResult(result, count,
dataModel.getNumUsers());
}
return result;
}
}
My task is to create an OpenGL Java program which will load a dataset, and then display an orthogonal slice of said data on the X, Y and Z axis. I'm new to OpenGL and I've been having trouble with plotting the data. The class to load the dataset has been provided for me:
public class VolumetricDataSet {
private final int[] dimensions;
private int maxValue;
private int minValue;
private final int[][][] volumeData;
/**
* Construct a new dataset from a File.
*
* #param in
* the file to read the data from.
* #param xSize
* the maximal x dimension to use.
* #param ySize
* the maximal y dimension to use.
* #param zSize
* the maximal z dimension to use.
* #throws IOException
* if the underlying reader encounters an error.
* #throws FileNotFoundException
* if the file cannot be found.
*/
public VolumetricDataSet(final File in, final int xSize, final int ySize,
final int zSize) throws IOException, FileNotFoundException {
this(new FileInputStream(in), xSize, ySize, zSize);
}
/**
* Construct a new dataset.
*
* #param in
* the stream to read the data from.
* #param xSize
* the maximal x dimension to use.
* #param ySize
* the maximal y dimension to use.
* #param zSize
* the maximal z dimension to use.
* #throws IOException
* if the underlying reader encounters an error.
*/
public VolumetricDataSet(final InputStream in, final int xSize,
final int ySize, final int zSize) throws IOException {
int value = 0, xCur = 0, yCur = 0, zCur = 0;
volumeData = new int[xSize][ySize][zSize];
while ((value = in.read()) != -1) {
volumeData[xCur][yCur][zCur] = value;
if (value > maxValue)
maxValue = value;
if (value < minValue)
minValue = value;
if (++xCur == xSize) {
xCur = 0;
if (++yCur == ySize) {
yCur = 0;
zCur++;
}
}
}
dimensions = new int[] { xSize, ySize, zSize };
}
/**
* Retrieve the length of the x y z dimensions of the data set. 3 element array
*
* #return the dimensions.
*/
public int[] getDimensions()
{
return dimensions;
}
/**
* #return the maximal value
*/
public int getMaxValue()
{
return maxValue;
}
/**
* #return the minimal value.
*/
public int getMinValue()
{
return minValue;
}
/**
* #return the entire data set as a 3-D array. x is the 1st dimension, y the
* 2nd and z the 3rd.
*/
public int[][][] getVolumeData()
{
return volumeData;
}
}
My code to display the data:
VolumetricDataSet ds = new VolumetricDataSet(new File("C:\\Users\\Me\\Desktop\\Work\\Comp Graphics\\marschnerlobb.raw.gz"), 41, 41, 41);
int[][][] volumeData = ds.getVolumeData();
int[] dimensions = ds.getDimensions();
for(int i = 0; i < dimensions[0]; i++)
{
for(int j = 0; j < dimensions[1]; j++)
{
if(volumeData[i][j][0] < 1)
{
gl.glColor3f(0.0f,0.0f,0.0f);
gl.glPointSize(10);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2i(i, j);
}
else if(volumeData[i][j][0] < 40)
{
gl.glColor3f(0.0f,0.0f,0.1f);
gl.glPointSize(10);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2i(i, j);
}
else if(volumeData[i][j][0] < 80)
{
gl.glColor3f(0.0f,0.0f,0.2f);
gl.glPointSize(10);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2i(i, j);
}
else if(volumeData[i][j][0] < 120)
{
gl.glColor3f(0.0f,0.0f,0.3f);
gl.glPointSize(10);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2i(i, j);
}
else if(volumeData[i][j][0] < 160)
{
gl.glColor3f(0.0f,0.0f,0.4f);
gl.glPointSize(10);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2i(i, j);
}
else if(volumeData[i][j][0] < 200)
{
gl.glColor3f(0.0f,0.0f,0.5f);
gl.glPointSize(10);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2i(i, j);
}
else if(volumeData[i][j][0] < 240)
{
gl.glColor3f(0.0f,0.0f,0.6f);
gl.glPointSize(10);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2i(i, j);
}
else if(volumeData[i][j][0] < 280)
{
gl.glColor3f(0.0f,0.0f,0.7f);
gl.glPointSize(10);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2i(i, j);
}
}
}
marschnerlobb.raw.gz is the dataset that I am currently using to test my program which can be found at http://www.volvis.org/
When I run the program at first I thought it was correct as it looked like it may be a a slice from the dataset I used (which resembles a square). But when I tried it with a different dataset (a skull) the result being displayed was still a square image.
What I'm trying to do is come up with a way to generate n random points on a graph (displaying it isn't necessary). A point is randomly selected and connected to the point closest to it (or the next closest if it's already connected to the best option) in a way so that no two lines intersect. This repeats until no more connections are possible. The vertices are meant to represent regions on a map, and connections represent adjacency. The following code I have thus far is as follows, taken from http://javaingrab.blogspot.com/2012/12/m-way-graph-coloring-with-backtracking.html:
public class MWayGrColor{
/*G is graph's adjacency matrix and x is solution vector */
private int G[][],x[],n,m,soln;
public void mColoring(int k){ //backtracking function
for(int i=1;i<=n;i++){
next_color(k); //coloring kth vertex
if(x[k]==0)
return; //if unsuccessful then backtrack
if(k==n) //if all colored then show
write();
else
mColoring(k+1); /* successful but still left to color */
}
}
private void next_color(int k){
do{
int i=1;
x[k]=(x[k]+1)%(m+1);
if(x[k]==0)
return;
for(i=1;i<=n;i++)
if(G[i][k]!=0 && x[k]==x[i]) /* checking adjacency and not same color */
break;
if(i==n+1) return; //new color found
}while(true);
}
private void write(){
System.out.print("\nColoring(V C) # "+(++soln)+"-->");
for(int i=1;i<=n;i++)
System.out.print("\t("+i+" "+x[i]+")"); //solution vector
}
public void input(){
java.util.Scanner sc=new java.util.Scanner(System.in);
System.out.print("Enter no. of vertices : ");
n=sc.nextInt();
G=new int[n+1][n+1];
x=new int[n+1];
System.out.print("Enter no. of colors : ");
m=sc.nextInt();
System.out.println("Enter adjacency matrix-->");
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
G[i][j]=sc.nextInt();
}
public static void main (String[] args) {
MWayGrColor obj=new MWayGrColor();
obj.input();
obj.mColoring(1);
if(obj.soln==0)
System.out.println("\nNeed more than "+obj.m+" colors");
else
System.out.print("\nTOTAL SOLN : "+obj.soln);
}
}
As noted, the map doesn't need to be visually represented, as the current method of display is adequate. I'm aware of the Point2D.Double class and the Line2D class, and I was originally going to just start generating points and use the lines to create the adjacency matrix already shown in the code, but the methods for connecting points and avoiding repetition are extremely confusing to me in how they should be implemented. How can I accomplish this generation of an adjacency matrix?
It's still not clear what the actual question is. It sounds like "this is so complicated, I don't get it done". However, unless there are strict requirements about the approach and its running time etc., one can pragmatically write down what has to be done:
do
{
V v0 = randomVertex();
V v1 = findClosestUnconnected(v0);
if (line(v0,v1).intersectsNoOtherLine())
{
insert(line(v0,v1));
}
} while (insertedNewLine);
Of course, this implies some searching. For large graphs there may be some sophisticated data structures to accelerate this. Particularly the search for the nearest (unconnected) neighbor may be accelerated with the classical structures like KD-trees etc. But this seems to be unrelated to the original question.
The handing of the adjacency matrix can be made a bit more convenient with a wrapper that offers methods that allow a more "natural" description:
class Graph
{
private final boolean matrix[][];
void addEdge(V v0, V v1)
{
matrix[v0.index][v1.index] = true;
matrix[v1.index][v0.index] = true;
}
boolean hasEdge(V v0, V v1)
{
return matrix[v0.index][v1.index];
}
}
But in this case, this is only a minor, syntactical simplification.
An example, only as a VERY q&d sketch:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class NonIntersectingAdjacencies
{
public static void main(String[] args)
{
Random random = new Random(0);
int numVertices = 25;
List<AdjacencyVertex> vertices =
createRandomVertices(numVertices, random);
final AdjacencyGraph adjacencyGraph =
new AdjacencyGraph(vertices);
boolean createdNewLine = true;
while (createdNewLine)
{
createdNewLine = false;
List<Integer> indices =
createShuffledList(numVertices, random);
for (int i=0; i<numVertices; i++)
{
int randomIndex = indices.get(i);
AdjacencyVertex randomVertex = vertices.get(randomIndex);
AdjacencyVertex closest =
findClosestUnconnected(randomVertex, adjacencyGraph);
if (closest != null)
{
if (!intersectsOtherLine(
randomVertex, closest, adjacencyGraph))
{
adjacencyGraph.addEdge(randomVertex, closest);
createdNewLine = true;
}
}
}
}
AdjacencyGraphPanel.show(adjacencyGraph);
}
private static List<AdjacencyVertex> createRandomVertices(
int numVertices, Random random)
{
List<AdjacencyVertex> vertices = new ArrayList<AdjacencyVertex>();
for (int i=0; i<numVertices; i++)
{
AdjacencyVertex v = new AdjacencyVertex();
v.index = i;
v.x = random.nextDouble();
v.y = random.nextDouble();
vertices.add(v);
}
return vertices;
}
private static List<Integer> createShuffledList(
int maxValue, Random random)
{
List<Integer> list = new ArrayList<Integer>();
for (int i=0; i<maxValue; i++)
{
list.add(i);
}
Collections.shuffle(list, random);
return list;
}
private static boolean intersectsOtherLine(
AdjacencyVertex v0, AdjacencyVertex v1,
AdjacencyGraph adjacencyGraph)
{
Line2D newLine = new Line2D.Double(
v0.x, v0.y, v1.x, v1.y);
List<AdjacencyVertex> vertices = adjacencyGraph.getVertices();
for (int i=0; i<vertices.size(); i++)
{
for (int j=0; j<vertices.size(); j++)
{
if (i == j)
{
continue;
}
AdjacencyVertex oldV0 = vertices.get(i);
AdjacencyVertex oldV1 = vertices.get(j);
if (adjacencyGraph.hasEdge(oldV0, oldV1))
{
Line2D oldLine = new Line2D.Double(
oldV0.x, oldV0.y, oldV1.x, oldV1.y);
if (Intersection.intersect(oldLine, newLine))
{
return true;
}
}
}
}
return false;
}
private static AdjacencyVertex findClosestUnconnected(
AdjacencyVertex v,
AdjacencyGraph adjacencyGraph)
{
double minDistanceSquared = Double.MAX_VALUE;
AdjacencyVertex closest = null;
List<AdjacencyVertex> vertices = adjacencyGraph.getVertices();
for (int i=0; i<vertices.size(); i++)
{
AdjacencyVertex other = vertices.get(i);
if (other.index == v.index)
{
continue;
}
if (adjacencyGraph.hasEdge(v, other))
{
continue;
}
double dx = other.x - v.x;
double dy = other.y - v.y;
double distanceSquared = Math.hypot(dx, dy);
if (distanceSquared < minDistanceSquared)
{
minDistanceSquared = distanceSquared;
closest = other;
}
}
return closest;
}
}
class AdjacencyVertex
{
double x;
double y;
int index;
}
class AdjacencyGraph
{
private final boolean matrix[][];
private final List<AdjacencyVertex> vertices;
AdjacencyGraph(List<AdjacencyVertex> vertices)
{
this.vertices = vertices;
this.matrix = new boolean[vertices.size()][vertices.size()];
}
List<AdjacencyVertex> getVertices()
{
return vertices;
}
void addEdge(AdjacencyVertex v0, AdjacencyVertex v1)
{
matrix[v0.index][v1.index] = true;
matrix[v1.index][v0.index] = true;
}
boolean hasEdge(AdjacencyVertex v0, AdjacencyVertex v1)
{
return matrix[v0.index][v1.index];
}
}
//============================================================================
// Only helper stuff below this line...
class AdjacencyGraphPanel extends JPanel
{
public static void show(final AdjacencyGraph adjacencyGraph)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI(adjacencyGraph);
}
});
}
private static void createAndShowGUI(AdjacencyGraph adjacencyGraph)
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new AdjacencyGraphPanel(adjacencyGraph));
f.setSize(600,600);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private final AdjacencyGraph adjacencyGraph;
public AdjacencyGraphPanel(AdjacencyGraph adjacencyGraph)
{
this.adjacencyGraph = adjacencyGraph;
}
#Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
int offsetX = 30;
int offsetY = 30;
int w = getWidth() - offsetX - offsetX;
int h = getHeight() - offsetY - offsetY;
g.setColor(Color.BLACK);
List<AdjacencyVertex> vertices = adjacencyGraph.getVertices();
for (int i=0; i<vertices.size(); i++)
{
for (int j=0; j<vertices.size(); j++)
{
if (i == j)
{
continue;
}
AdjacencyVertex v0 = vertices.get(i);
AdjacencyVertex v1 = vertices.get(j);
if (adjacencyGraph.hasEdge(v0, v1))
{
Line2D newLine = new Line2D.Double(
offsetX + v0.x*w,
offsetY + v0.y*h,
offsetX + v1.x*w,
offsetY + v1.y*h);
g.draw(newLine);
}
}
}
g.setColor(Color.BLUE);
for (int i=0; i<vertices.size(); i++)
{
AdjacencyVertex v = vertices.get(i);
int ix = (int)(offsetX + v.x * w);
int iy = (int)(offsetY + v.y * h);
g.fill(new Ellipse2D.Double(
ix - 5, iy - 5, 10, 10));
g.drawString(String.valueOf(i), ix, iy+16);
}
}
}
class Intersection
{
static boolean intersect(Line2D line0, Line2D line1)
{
Point2D location = new Point2D.Double();
Point2D intersection =
Intersection.computeIntersectionSegmentSegment(
line0, line1, location);
if (intersection == null)
{
return false;
}
return !isAtLineAnd(location);
}
private static boolean isAtLineAnd(Point2D location)
{
double EPSILON = 0.05;
if (Math.abs(location.getX()) < EPSILON)
{
return true;
}
if (Math.abs(location.getX()-1) < EPSILON)
{
return true;
}
if (Math.abs(location.getY()) < EPSILON)
{
return true;
}
if (Math.abs(location.getY()-1) < EPSILON)
{
return true;
}
return false;
}
/**
* Epsilon for floating point computations
*/
private static final double epsilon = 1e-6f;
/**
* Computes the intersection of the specified line segments and returns
* the intersection point, or <code>null</code> if the line segments do
* not intersect.
*
* #param line0 The first line segment
* #param line1 The second line segment
* #param location Optional location that stores the
* relative location of the intersection point on
* the given line segments
* #return The intersection point, or <code>null</code> if
* there is no intersection.
*/
public static Point2D computeIntersectionSegmentSegment(
Line2D line0, Line2D line1, Point2D location)
{
return computeIntersectionSegmentSegment(
line0.getX1(), line0.getY1(), line0.getX2(), line0.getY2(),
line1.getX1(), line1.getY1(), line1.getX2(), line1.getY2(),
location);
}
/**
* Computes the intersection of the specified line segments and returns
* the intersection point, or <code>null</code> if the line segments do
* not intersect.
*
* #param s0x0 x-coordinate of point 0 of line segment 0
* #param s0y0 y-coordinate of point 0 of line segment 0
* #param s0x1 x-coordinate of point 1 of line segment 0
* #param s0y1 y-coordinate of point 1 of line segment 0
* #param s1x0 x-coordinate of point 0 of line segment 1
* #param s1y0 y-coordinate of point 0 of line segment 1
* #param s1x1 x-coordinate of point 1 of line segment 1
* #param s1y1 y-coordinate of point 1 of line segment 1
* #param location Optional location that stores the
* relative location of the intersection point on
* the given line segments
* #return The intersection point, or <code>null</code> if
* there is no intersection.
*/
public static Point2D computeIntersectionSegmentSegment(
double s0x0, double s0y0,
double s0x1, double s0y1,
double s1x0, double s1y0,
double s1x1, double s1y1,
Point2D location)
{
if (location == null)
{
location = new Point2D.Double();
}
Point2D result = computeIntersectionLineLine(
s0x0, s0y0, s0x1, s0y1, s1x0, s1y0, s1x1, s1y1, location);
if (location.getX() >= 0 && location.getX() <= 1.0 &&
location.getY() >= 0 && location.getY() <= 1.0)
{
return result;
}
return null;
}
/**
* Computes the intersection of the specified lines and returns the
* intersection point, or <code>null</code> if the lines do not
* intersect.
*
* Ported from
* http://www.geometrictools.com/LibMathematics/Intersection/
* Wm5IntrSegment2Segment2.cpp
*
* #param s0x0 x-coordinate of point 0 of line segment 0
* #param s0y0 y-coordinate of point 0 of line segment 0
* #param s0x1 x-coordinate of point 1 of line segment 0
* #param s0y1 y-coordinate of point 1 of line segment 0
* #param s1x0 x-coordinate of point 0 of line segment 1
* #param s1y0 y-coordinate of point 0 of line segment 1
* #param s1x1 x-coordinate of point 1 of line segment 1
* #param s1y1 y-coordinate of point 1 of line segment 1
* #param location Optional location that stores the
* relative location of the intersection point on
* the given line segments
* #return The intersection point, or <code>null</code> if
* there is no intersection.
*/
public static Point2D computeIntersectionLineLine(
double s0x0, double s0y0,
double s0x1, double s0y1,
double s1x0, double s1y0,
double s1x1, double s1y1,
Point2D location)
{
double dx0 = s0x1 - s0x0;
double dy0 = s0y1 - s0y0;
double dx1 = s1x1 - s1x0;
double dy1 = s1y1 - s1y0;
double len0 = Math.sqrt(dx0*dx0+dy0*dy0);
double len1 = Math.sqrt(dx1*dx1+dy1*dy1);
double dir0x = dx0 / len0;
double dir0y = dy0 / len0;
double dir1x = dx1 / len1;
double dir1y = dy1 / len1;
double c0x = s0x0 + dx0 * 0.5;
double c0y = s0y0 + dy0 * 0.5;
double c1x = s1x0 + dx1 * 0.5;
double c1y = s1y0 + dy1 * 0.5;
double cdx = c1x - c0x;
double cdy = c1y - c0y;
double dot = dotPerp(dir0x, dir0y, dir1x, dir1y);
if (Math.abs(dot) > epsilon)
{
double dot0 = dotPerp(cdx, cdy, dir0x, dir0y);
double dot1 = dotPerp(cdx, cdy, dir1x, dir1y);
double invDot = 1.0/dot;
double s0 = dot1*invDot;
double s1 = dot0*invDot;
if (location != null)
{
double n0 = (s0 / len0) + 0.5;
double n1 = (s1 / len1) + 0.5;
location.setLocation(n0, n1);
}
double x = c0x + s0 * dir0x;
double y = c0y + s0 * dir0y;
return new Point2D.Double(x,y);
}
return null;
}
/**
* Returns the perpendicular dot product, i.e. the length
* of the vector (x0,y0,0)x(x1,y1,0).
*
* #param x0 Coordinate x0
* #param y0 Coordinate y0
* #param x1 Coordinate x1
* #param y1 Coordinate y1
* #return The length of the cross product vector
*/
private static double dotPerp(double x0, double y0, double x1, double y1)
{
return x0*y1 - y0*x1;
}
}
I am newbie to the java....working on a piece of applet code...............as I am still going through the OOPs concepts and java understanding and need to develop below mentioned functionality.
The piece of code I have works like this :
First it reads all parameters from HTML tags and stores in global variables. Then it sends query to CGI to read graph data. Then it converts data for plotting and draws graph. There is a option for user to select 1-24 hours. Based on the selection graph will be plotted by plotting only selected data. Every 30 sec it sends query to CGI for collecting data.
The code uses following library and uses java 1.5 environment and i cannot change it due to embeded requirements :
I need to enchance it by implementing zoom in zoom out feature with x-y axis granuality changing with zoom in .
My worry is how to do that?I know its Frustrating question ...but i am here to get suggestion from the java experts so that I can quickly learn and implement this stuff.
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.applet.*;
import java.net.*;
import java.io.*;
import java.util.*;
import java.text.*;
/******************************************************************************
*
* Class - Graph
*
* This is the entry point.
* This class extends Applet class and implements Runnable.
*
*****************************************************************************/
public class GraphPerf extends Applet implements Runnable,ItemListener,MouseMotionListener
{
//Global variables
int MAX_DATA_X ;
int SIZE_X= 480;
int SIZE_Y= 250;
int SIZE_Y1= 240;
int MIN_ERROR = -1;
int MAX_LOG10_ERROR_COUNT = 1001;
int MAX_ERROR_COUNT = 101;
int SIZE_Y_EXTENDED_BOTTOM = 20;
int MAX_DISP_PARMS = 16;
int MAX_NUM_INTERVELL_PER_DAY = 96;
int MAX_DISP_PARMS_STD = 7;
int refreshTime;
String serverAddress,hostAddr;
Color plotColor1,plotColor8;
float graphData[][];
float graph_data_rf_east,graph_data_rf_west;
int xOffset = 50;
int yOffset = 40;
int Y1_MAX_VALUE = 100;
int Y2_MAX_VALUE = 3;
float RANGE2;
Thread graphThread;
Image Buffer;
Graphics plot;
Choice timeChoice, modeChoice, seloptChoice;
int duration=1, viewMode=1, line_type = 0,viewOpt = 1;
Label valueLabel1, valueLabel2,valueLabel3,valueLabel4,valueLabel5;
boolean GraphBottomExtendFlag=true;
/******************************************************************************
*
* method - init
*
* This is the method called first after applet loaded in to browser.
* This function reads configurable parameters from HTML tag and updates
* global variables.
*****************************************************************************/
public void init()
{
MAX_DATA_X = 672;//Integer.parseInt(getParameter("max_data_x"));
//refreshTime = 30;//Integer.parseInt(getParameter("refresh_sec"));
/*URL url = getDocumentBase();
String host = url.getHost();
try
{
InetAddress addr = InetAddress.getByName(host);
hostAddr=addr.getHostAddress();
}catch (UnknownHostException ex) {
ex.printStackTrace();
}
*/
//serverAddress = new String ( getParameter("access_str")+ hostAddr + getParameter("data_server"));
graphData = new float[MAX_DISP_PARMS][MAX_DATA_X+1];
/*initialize the array with -1 not with 0(0 also valid for graph data) */
int i =0,j = 0;
for( j=0; j<MAX_DISP_PARMS; j++)
{
for( i=0; i<MAX_DATA_X+1; i++)
{
graphData[j][i] = -1;
}
}
graph_data_rf_east = -1;
graph_data_rf_west = -1;
plotColor1 = Color.orange;
plotColor2 = Color.black;
plotColor8 = Color.red;
plotColor9 = Color.green;
setBackground(Color.white);
setLayout(null);
timeChoice = new Choice();
timeChoice.add("1");
timeChoice.add("2");
timeChoice.add("3");
timeChoice.add("4");
timeChoice.add("5");
timeChoice.add("6");
timeChoice.add("7");
add(timeChoice);
timeChoice.setBounds(190,340,40,23);
timeChoice.addItemListener(this);
Label timeLabel1 = new Label("View graph for last");
Label timeLabel2 = new Label("day(s)");
add(timeLabel1);
timeLabel1.setBounds(xOffset+30,340,160,23);
add(timeLabel2);
timeLabel2.setBounds(240,340,50,23);
valueLabel1 = new Label();
add(valueLabel1);
valueLabel1.setBounds(300,340,50,23);
valueLabel2 = new Label();
add(valueLabel2);
valueLabel2.setBounds(370,340,70,23);
valueLabel3 = new Label();
add(valueLabel3);
valueLabel3.setBounds(440,340,70,23);
valueLabel4 = new Label();
add(valueLabel4);
valueLabel4.setBounds(500,340,70,23);
valueLabel5 = new Label();
add(valueLabel5);
valueLabel5.setBounds(370,370,80,25);
modeChoice = new Choice();
modeChoice.add("East");
modeChoice.add("West");
/* Display this only for Protected and East-West Mode */
if(2/*Integer.parseInt(getParameter("mode"))*/ == 2)
{
add(modeChoice);
}
else
{
viewOpt = 1;
}
modeChoice.setBounds(xOffset+SIZE_X-55, 0, 60, 25);
modeChoice.addItemListener(this);
addMouseMotionListener(this);
}
public void start()
{
graphThread = new Thread(this);
graphThread.start();
}
public void stop()
{
graphThread = null;
}
/******************************************************************************
*
* This method will be called after starting the thread. This is a
* infinite loop which will call query method for every 30 sec to read data
* from CGI. Then it plots graph by calling plotGraph method
* the thread.
*****************************************************************************/
public void run()
{
/*while (false)
{
try
{//getData(serverAddress);
int sizeY = SIZE_Y;
if(GraphBottomExtendFlag)
{
sizeY += SIZE_Y_EXTENDED_BOTTOM;
}
repaint(xOffset+1,yOffset+1,SIZE_X-1,sizeY-1);
//graphThread.sleep(refreshTime*1000);
}catch (Exception e) { System.out.println(e); }
}*/
}
/******************************************************************************
*
* method - paint
*
* This method displays the graph plotted by plotGraph method
* in the screen. Then it draws axis for the graph
*
*****************************************************************************/
public void paint(Graphics g1)
{
int sizeY = SIZE_Y;
/*If Graph Bottom is to be Etended
*soo that zero is displayed properly
*/
if(GraphBottomExtendFlag)
{
sizeY += SIZE_Y_EXTENDED_BOTTOM;
}
if( duration <= 5 )
{
Buffer = createImage(SIZE_X, sizeY);
plot = Buffer.getGraphics();
plotGraph(plot);
g1.drawImage (Buffer,xOffset,yOffset,this);
}
else
{
Buffer = createImage(MAX_DATA_X*duration/7,sizeY);
plot = Buffer.getGraphics();
plotGraph(plot);
g1.drawImage (Buffer,xOffset,yOffset,SIZE_X,sizeY,this);
}
g1.setColor(Color.black);
g1.drawRect(70,150,270,80);
/*Dram Graph boarder */
g1.drawRect(xOffset,yOffset,SIZE_X,sizeY);
g1.drawRect(xOffset-1,yOffset-1,SIZE_X+2,sizeY+2);
/*Plot X axis*/
int max_x_marks = 8;
int temp = 1,cnt_graph = 0;
int float_temp,float_temp2;
/*max 8 plots on x axis*/
for(int x=max_x_marks; x>0; x--)
{
float_temp = (int)((MAX_NUM_INTERVELL_PER_DAY*duration)/max_x_marks)*((max_x_marks+1)-x);
float_temp2 = SIZE_X-(60*cnt_graph);
g1.drawString(String.valueOf(float_temp),(float_temp2-20) ,SIZE_Y+yOffset+35);
cnt_graph++;
}
/*Plot Y1 AXIS*/
temp = Y1_MAX_VALUE;
for(int x = 0; x <= SIZE_Y; x+= 25)
{
g1.drawString(String.valueOf(temp), 25, x + yOffset+10);
temp -= (Y1_MAX_VALUE - 0)/10;
}
temp = 1000;
/*Plot Y2 AXIS*/
int index_log = 1;
for(int x = 0; x <= SIZE_Y1; x+= 80)
{
if(x== 240)
index_log--;
if(temp>=1)
{
g1.drawString(String.valueOf(temp), 550, x+yOffset+8-index_log);
g1.drawLine(530,x+yOffset+5-index_log, 540, x+yOffset+5-index_log);
}
temp = temp/10;
}
Font thisFont = new Font("Times New Roman", Font.BOLD, 14);
g1.setFont(thisFont);
g1.drawString("Y2", 550, 160);
g1.drawString("Y1",5, 160);
}
/******************************************************************************
*
* method - plotGraph
*
* Depending on the mode, "East", "West" or "Combined", it plots
* single or two graphs in the same applet.
*
* Inputs :
* g - Graphics object
*****************************************************************************/
public void plotGraph(Graphics g)
{
g.setColor(new Color(255,255,220));
/*If Error-Sec-Count Graph
*Then extend the lower portion
*soo that zero is displayed properly
*/
if(GraphBottomExtendFlag)
{
g.fillRect(0,0,MAX_DATA_X,SIZE_Y + SIZE_Y_EXTENDED_BOTTOM);
}
else
{
g.fillRect(0,0,MAX_DATA_X,SIZE_Y);
}
switch(viewMode)
{
case 1 :
plot1(g);
plot_timeelapsed_east(g);
break;
case 2 :
plot8(g);
plot_timeelapsed_west(g);
break;
}
}
/******************************************************************************
*
* method - plot1
*
* This method uses graphData[0][] global variable and plots series of lines
* in the applet
*
* Inputs :
* g - Graphics object
*****************************************************************************/
void plot1(Graphics g)
{
int end = MAX_DATA_X;
int localPlotBuffer[];
localPlotBuffer = new int[2];
g.setColor(plotColor1);
if(duration > 5)
{
for(int x=(duration*MAX_NUM_INTERVELL_PER_DAY); x > 0 ; x--)
{
/*if data is valid data then plot else ignore*/
if((graphData[0][end]>MIN_ERROR)&&(graphData[0][end-1]<MAX_LOG10_ERROR_COUNT)&&(graphData[0][end-1]>MIN_ERROR)&&(graphData[0][end]<MAX_LOG10_ERROR_COUNT))
{
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[0][end] == 0)
{
localPlotBuffer[0] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[0][end]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[0][end])/(float)Y2_MAX_VALUE));
}
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[0][end-1] == 0)
{
localPlotBuffer[1] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[0][end-1]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[1] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[0][end-1])/(float)Y2_MAX_VALUE));
}
g.drawLine(x-1,(localPlotBuffer[0]+5), x-2,(localPlotBuffer[1]+5));
g.drawLine(x,(localPlotBuffer[0]+5), x-1,(localPlotBuffer[1]+5));
}
end--;
}
}
else
{
float temp = SIZE_X;
for(int x=(duration*MAX_NUM_INTERVELL_PER_DAY) ; x > 0 ; x--)
{
float LocalTemp1 = temp;
float LocalTemp2 = (int)(temp-(double)5/(double)duration);
/*Normalise the pixcel positions */
/*Normalise the pixcel positions */
if(duration == 1)
{
if(LocalTemp1>(SIZE_X-3))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-3))
LocalTemp2 = SIZE_X;
}
/*Normalise the pixcel positions */
else if(duration == 2)
{
if(LocalTemp1>(SIZE_X-2))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-2))
LocalTemp2 = SIZE_X;
}
/*Normalise the pixcel positions */
else if(duration == 3)
{
if(LocalTemp1>(SIZE_X-1))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-1))
LocalTemp2 = SIZE_X;
}
/*if data is valid data then plot else ignore*/
if((graphData[0][end]>MIN_ERROR)&&(graphData[0][end-1]<MAX_LOG10_ERROR_COUNT)&&(graphData[0][end-1]>MIN_ERROR)&&(graphData[0][end]<MAX_LOG10_ERROR_COUNT))
{
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[0][end] == 0)
{
localPlotBuffer[0] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[0][end]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[0][end])/(float)Y2_MAX_VALUE));
}
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[0][end-1] == 0)
{
localPlotBuffer[1] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[0][end-1]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[1] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[0][end-1])/(float)Y2_MAX_VALUE));
}
g.drawLine((int)LocalTemp1,(localPlotBuffer[0]+5), (int)LocalTemp2,(localPlotBuffer[1]+5));
}
temp-=(double)5/(double)duration;
end--;
}
}
}
/******************************************************************************
*
* method - plot8
*
* This method uses graphData[7][] global variable and plots series of lines
* in the applet
*
* Inputs :
* g - Graphics object
*****************************************************************************/
void plot8(Graphics g)
{
int end = MAX_DATA_X;
int localPlotBuffer[];
localPlotBuffer = new int[2];
g.setColor(plotColor1);
if(duration > 5)
{
for(int x=(duration*MAX_NUM_INTERVELL_PER_DAY); x > 0 ;x-- )
{
/*if data is valid data then plot else ignore*/
if((graphData[8][end]>MIN_ERROR)&&(graphData[8][end-1]<MAX_LOG10_ERROR_COUNT)&&(graphData[8][end-1]>MIN_ERROR)&&(graphData[8][end]<MAX_LOG10_ERROR_COUNT))
{
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[8][end] == 0)
{
localPlotBuffer[0] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[8][end]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[8][end])/(float)Y2_MAX_VALUE));
}
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[8][end-1]== 0)
{
localPlotBuffer[1] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[8][end-1]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[1] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[8][end-1])/(float)Y2_MAX_VALUE));
}
g.drawLine(x-1,(localPlotBuffer[0]+5), x-2,(localPlotBuffer[1]+5));
g.drawLine(x,(localPlotBuffer[0]+5), x-1,(localPlotBuffer[1]+5));
}
end--;
}
}
else
{
float temp = SIZE_X;
for(int x=(duration*MAX_NUM_INTERVELL_PER_DAY) ; x > 0 ; x--)
{
float LocalTemp1 = temp;
float LocalTemp2 = (int)(temp-(double)5/(double)duration);
/*Normalise the pixcel positions */
if(duration == 1)
{
if(LocalTemp1>(SIZE_X-3))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-3))
LocalTemp2 = SIZE_X;
}
/*Normalise the pixcel positions */
else if(duration == 2)
{
if(LocalTemp1>(SIZE_X-2))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-2))
LocalTemp2 = SIZE_X;
}
/*Normalise the pixcel positions */
else if(duration == 3)
{
if(LocalTemp1>(SIZE_X-1))
LocalTemp1 = SIZE_X;
if(LocalTemp2>(SIZE_X-1))
LocalTemp2 = SIZE_X;
}
/*if data is valid data then plot else ignore*/
if((graphData[8][end]>MIN_ERROR)&&(graphData[8][end-1]<MAX_LOG10_ERROR_COUNT)&&(graphData[8][end-1]>MIN_ERROR)&&(graphData[8][end]<MAX_LOG10_ERROR_COUNT))
{
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[8][end] == 0)
{
localPlotBuffer[0] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[8][end]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[8][end])/(float)Y2_MAX_VALUE));
}
/*if data present is 0, log10(0) is not define so then plot this graph in normal scale */
if(graphData[8][end-1]== 0)
{
localPlotBuffer[1] = (int)((float)(SIZE_Y )*(float)(1 - (float)graphData[8][end-1]/(float)Y1_MAX_VALUE)) ;
}
else
{
localPlotBuffer[1] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graphData[8][end-1])/(float)Y2_MAX_VALUE));
}
g.drawLine((int)LocalTemp1,(localPlotBuffer[0]+5), (int)LocalTemp2,(localPlotBuffer[1]+5));
}
temp-=(double)5/(double)duration;
end--;
}
}
}
/******************************************************************************
*
* method - plot_timeelapsed_east
*
* This method uses graph_data_rf_east global variable and plots series of lines
* in the applet
*****************************************************************************/
void plot_timeelapsed_east(Graphics g)
{
int end = MAX_DATA_X;
int localPlotBuffer[];
int x= 0;
localPlotBuffer = new int[2];
x= (duration*MAX_NUM_INTERVELL_PER_DAY);
g.setColor(plotColor9);
/*if data is valid data then plot else ignore*/
if((graph_data_rf_east>0)&&(graph_data_rf_east<MAX_LOG10_ERROR_COUNT))
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graph_data_rf_east)/(float)Y2_MAX_VALUE));
if(duration>5)
g.drawLine(x-1,SIZE_Y+5, x-2,(localPlotBuffer[0]+5));
else
g.drawLine(SIZE_X,SIZE_Y+5, 474+duration,(localPlotBuffer[0]+5));
}
}/*End for plot_timeelapsed_east() */
/******************************************************************************
*
* method - plot_timeelapsed_west
*
* This method uses graph_data_rf_east global variable and plots series of lines
* in the applet
*****************************************************************************/
void plot_timeelapsed_west(Graphics g)
{
int end = MAX_DATA_X;
int localPlotBuffer[];
int x= 0;
localPlotBuffer = new int[2];
x= (duration*MAX_NUM_INTERVELL_PER_DAY);
g.setColor(plotColor9);
/*if data is valid data then plot else ignore*/
if((graph_data_rf_east>MIN_ERROR)&&(graph_data_rf_east<MAX_LOG10_ERROR_COUNT))
{
localPlotBuffer[0] = (int)((float)(SIZE_Y1 )*(float)(1 - (float)Math.log10(graph_data_rf_west)/(float)Y2_MAX_VALUE));
if(duration>5)
g.drawLine(x-1,SIZE_Y+5, x-2,(localPlotBuffer[0]+5));
else
g.drawLine(SIZE_X,SIZE_Y+5, 474+duration,(localPlotBuffer[0]+5));
}
}
/******************************************************************************
*
* method - getData
*
* This method sends query to CGI to collect data. Then it converts the
* data for applet area then updates global variable.
*
* Inputs :
* serverAddress - server CGI path
*****************************************************************************/
public void getData(String serverAddress)
{
URL addr;
BufferedReader in;
String inputLine;
int count = 0;
int i=0,j = 0;
try
{
addr = new URL(serverAddress);
URLConnection connection = addr.openConnection();
in = new BufferedReader(new InputStreamReader(addr.openStream()));
/*Read data for first link */
for( j=0; j<MAX_DISP_PARMS_STD; j++)
{
for( i=0; i<MAX_DATA_X+1; i++)
{
inputLine = in.readLine();
graphData[j][i] = Integer.parseInt(inputLine);
}
}
for( i=0; i<MAX_DATA_X; i++)
{
inputLine = in.readLine();
graphData[7][i] = Integer.parseInt(inputLine);
if(graphData[7][i] == 1)
graphData[7][i] = 10;
}
inputLine = in.readLine();
graph_data_rf_east = Integer.parseInt(inputLine);
/*Reading data for second link */
if(Integer.parseInt(getParameter("mode")) == 2)
{
for( j=8; j<15; j++)
{
for( i=0; i<MAX_DATA_X+1; i++)
{
inputLine = in.readLine();
graphData[j][i] = Integer.parseInt(inputLine);
}
}
for( i=0; i<MAX_DATA_X; i++)
{
inputLine = in.readLine();
graphData[15][i] = Integer.parseInt(inputLine);
if(graphData[15][i] == 1)
graphData[15][i] = 10;
}
inputLine = in.readLine();
graph_data_rf_west = Integer.parseInt(inputLine);
}
in.close();
}catch (Exception e) { System.out.println("Server Data Read Error:"+e); }
}
/******************************************************************************
*
* method - itemStateChanged
*
* This method will be called whenever event occured on this choice.
* it read the current status and changes scale accordingly.
* *****************************************************************************/
public void itemStateChanged(ItemEvent evt)
{
if( evt.getSource() == timeChoice )
duration = Integer.parseInt(timeChoice.getSelectedItem());
else
viewMode = modeChoice.getSelectedIndex()+1;
repaint();
}
/******************************************************************************
*
* method - mouseMoved
*
* This method will be called whenever mouse cursor is moved over the
* applet. Depending on the cursor position, it will display Actual
* X and Y values of the graph.
*****************************************************************************/
public void mouseMoved(MouseEvent evt)
{
int x = evt.getX()-xOffset;
int y = evt.getY()-yOffset-5;
int a = evt.getX();
int b = evt.getY();
int duration = Integer.parseInt(timeChoice.getSelectedItem());
if( (x>=0) && (x<=SIZE_X) && (y>=0) && (y<=SIZE_Y) )
{
valueLabel1.setText("X ");
valueLabel2.setText("Y1 ");
valueLabel3.setText("Y2 ");
try
{
int x_max_value = ((SIZE_X*duration)/5);
int x1 = (int)((float)((float)((float)(SIZE_X*duration))/5) * ((float)((float)(SIZE_X - x))/((float)SIZE_X)));
/*For Durations less than 16 scale starts with 1*/
int y1 = (int)((float)Y1_MAX_VALUE * (((float)SIZE_Y - (float)y)/((float)SIZE_Y)));
int y2 = (int) Math.pow(10,((float)(3 * ((float)(1 - (float)y/((float)SIZE_Y1))))));
valueLabel1.setText("X="+x1);
valueLabel2.setText("X pix="+a);
valueLabel3.setText("Y="+y1);
valueLabel4.setText("Y pix="+b);
valueLabel5.setText("Y2="+y2);
}
catch(Exception e) {System.out.println("Mouse Moved Error" + e);}
}
else
{
valueLabel1.setText(" ");
valueLabel2.setText(" ");
valueLabel3.setText(" ");
}
}
public void mouseDragged(MouseEvent evt) { }
}
There are many ways to do this. Here are two:
You can simply scale the values: Multiply every coordinate with the zoom factor.
Use Java2D and AffineTransform:
AffineTransform transformer = new AffineTransform();
transformer.scale(zoom, zoom);
Graphics2D g2d = (Graphics2D)g;
g2d.setTransform(transformer);
// draw to g2d.
[EDIT] If you want to do everything yourself, see this page for a refresh of basic linear algebra: 2D Transformations
Don't mind the 3D example at the top; the rest of the page is about 2D.
I used JCC kit for my target platform and it's less than 100kb library. You need to understand the library and after that you can play without worrying about size. :)
Good library to use in embedded systems whether size is always the issue. it has inbuilt function o transform coordinates into screen coordinates and vice-verse.