package fr.unistra.pelican.util.vectorial.orders; import java.util.Arrays; import java.util.Comparator; import fr.unistra.pelican.util.vectorial.VectorPixel; /* TODO - size control - use longs instead of ints => up to 7 channels with fast comparing..i need more time HAL. */ /** * This class represents a vector ordering scheme based on bit interlacing.. as proposed by Channussot. * Negative values are not supported. */ public class BitMixOrdering implements VectorialOrdering,Comparator { private int doubleSize = 64; //private boolean byteFlag = false; /* public BitMixOrdering(boolean byteFlag) { doubleSize = Long.toBinaryString(Double.doubleToLongBits(Double.MAX_VALUE)).length() + 1; this.byteFlag = byteFlag; }*/ /** * Default constructor */ public BitMixOrdering() { doubleSize = Long.toBinaryString(Double.doubleToLongBits(Double.MAX_VALUE)).length() + 1; } /* public void setByteFlag(boolean byteFlag) { this.byteFlag = byteFlag; }*/ /* * (non-Javadoc) * @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#max(double[][]) */ public double[] max(double[][] p) { double[] max = p[0]; for(int i = 1; i < p.length; i++){ if(this.compare(max,p[i]) < 0) max = p[i]; } return max; } /* * (non-Javadoc) * @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#min(double[][]) */ public double[] min(double[][] p) { double[] min = p[0]; for(int i = 1; i < p.length; i++){ if(this.compare(min,p[i]) > 0) min = p[i]; } return min; } /* * (non-Javadoc) * @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#rank(double[][], int) */ public double[] rank(double[][] p,int r) { Arrays.sort(p,this); return p[r]; } /* * (non-Javadoc) * @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#order(fr.unistra.pelican.util.vectorial.VectorPixel[]) */ public VectorPixel[] order(VectorPixel[] v) { Arrays.sort(v,this); return v; } /** * Compares the given arguments according to this ordering * * @param o1 first double valued array or vector pixel * @param o2 second double valued array or vector pixel * @return 1,-1 or 0 if o1 is respectively superior, inferior or equal to o2 */ public int compare(Object o1,Object o2) { double[] p1 = null,p2 = null; try{ if(o1.getClass().getName().equals("[D")){ p1 = (double[])o1; p2 = (double[])o2; }else if(o1.getClass().getName().equals("fr.unistra.pelican.util.vectorial.VectorPixel")){ p1 = ((VectorPixel)o1).getVector(); p2 = ((VectorPixel)o2).getVector(); }else throw new ClassCastException(); }catch(ClassCastException ex){ ex.printStackTrace(); } /* // our double array is in fact an array of bytes..groovy! // so in the case of a tristumulus byte color, the bytes can be // placed in an int and get naturally compared. if(byteFlag == true){ long vector1 = 0; long vector2 = 0; //etc if(vector1 > vector2) return 1; else if(vector1 < vector2) return -1; else return 0; }*/ int n = p1.length; int totalBits = doubleSize * n; int rest,len; double[] d1 = p1; double[] d2 = p2; // check for negative values for(int j = 0; j < n; j++){ if(d1[j] < 0.0 || d2[j] < 0.0){ double min = Double.MAX_VALUE; double max = -Double.MAX_VALUE; for(int i = 0; i < n; i++){ if(d1[i] < min) min = d1[i]; if(d1[i] > max) max = d1[i]; } for(int i = 0; i < n; i++){ if(d2[i] < min) min = d2[i]; if(d2[i] > max) max = d2[i]; } // min < 0.0 double trans = Math.abs(min) + 1; if(trans > Double.MAX_VALUE - Math.abs(max)){ System.err.println("cannot process pixel values"); // throw something... FIXME }else{ d1 = new double[n]; d2 = new double[n]; for(int i = 0; i < n; i++) d1[i] = p1[i] + trans; for(int i = 0; i < n; i++) d2[i] = p2[i] + trans; } } } StringBuffer s1 = new StringBuffer(totalBits); StringBuffer s2 = new StringBuffer(totalBits); s1.setLength(totalBits); s2.setLength(totalBits); StringBuffer[] sArray1 = new StringBuffer[n]; StringBuffer[] sArray2 = new StringBuffer[n]; for(int i = 0; i < n; i++){ String s = Long.toBinaryString(Double.doubleToLongBits(d1[i])); len = s.length(); sArray1[i] = new StringBuffer(s); // pad with zeros if necessary if(len < doubleSize){ rest = doubleSize - len; for(int j = 0; j < rest; j++) sArray1[i].insert(0,'0'); } s = Long.toBinaryString(Double.doubleToLongBits(d2[i])); len = s.length(); sArray2[i] = new StringBuffer(s); // pad with zeros if necessary if(len < doubleSize){ rest = doubleSize - len; for(int j = 0; j < rest; j++) sArray2[i].insert(0,'0'); } } // combine each StringBuffer into one big buffer. for(int i = 0; i < doubleSize; i++){ for(int j = 0; j < n; j++){ s1.setCharAt(i * n + j,sArray1[j].charAt(i)); s2.setCharAt(i * n + j,sArray2[j].charAt(i)); } } // it is also possible to use BigIntegers // but the strings are already suitable for a // lexicographical comparison..and besides, it's faster. for(int i = 0; i < totalBits; i++){ char c1 = s1.charAt(i); char c2 = s2.charAt(i); if(c1 == '0' && c2 == '1') return -1; else if(c1 == '1' && c2 == '0') return 1; } return 0; } /* * (non-Javadoc) * @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#max(double[], double[]) */ public double[] max(double[] p,double[] r) { if(compare(p,r) == 1) return p; else return r; } /* * (non-Javadoc) * @see fr.unistra.pelican.util.vectorial.orders.VectorialOrdering#min(double[], double[]) */ public double[] min(double[] p,double[] r) { if(compare(p,r) == 1) return r; else return p; } }