package fr.unistra.pelican.util; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import fr.unistra.pelican.util.data.Data; import fr.unistra.pelican.util.data.DataArrayData; import fr.unistra.pelican.util.data.DoubleArrayData; /** * An interest point for using by interest points descriptors. * * @author Régis Witz */ public class Keypoint implements Cloneable { //////////// // FIELDS // //////////// /** Coordinates of the detected interest point */ public double x, y; // public double[] descriptor; public Data data; ////////////////// // CONSTRUCTORS // ////////////////// public Keypoint( double x, double y ) { this.x = x; this.y = y; } public Keypoint( double x, double y, Data data ) { this( x,y ); this.data = data; } // public Keypoint( double x, double y, double value ) { // // this( x,y ); // this.descriptor = new double[1]; // this.descriptor[0] = value; // } // // public Keypoint( double x, double y, double[] descriptor ) { // // this( x,y ); // this.descriptor = new double[ descriptor.length ]; // for ( int i = 0 ; i < this.descriptor.length ; i++ ) this.descriptor[i] = descriptor[i]; // } public Keypoint( Keypoint arg ) { this.x = arg.x; this.y = arg.y; // if ( arg.descriptor != null ) { // // this.descriptor = new double[ arg.descriptor.length ]; // for ( int i = 0 ; i < this.descriptor.length ; i++ ) descriptor[i] = arg.descriptor[i]; // } if ( arg.data != null ) this.data = arg.data.clone(); } ///////////// // METHODS // ///////////// public Keypoint clone() { return new Keypoint( this ); } public boolean equals( Keypoint key ) { if ( this.x != key.x ) return false; if ( this.y != key.y ) return false; // if ( this.descriptor == null ) // if ( key.descriptor == null ) return true; // else return false; // else // if ( key.descriptor != null ) { // // if ( this.descriptor.length != key.descriptor.length ) return false; // for ( int index = 0 ; index < this.descriptor.length ; index++ ) // if ( this.descriptor[ index ] != key.descriptor[ index ] ) return false; // // } else return false; if ( this.data == null ) if ( key.data == null ) return true; else return false; else if ( key.data != null ) return this.data.equals( key.data ); else return false; } public int getDescLength() { Object[] array; if ( this.data instanceof DoubleArrayData || this.data instanceof DataArrayData ) array = ( Object[] ) this.data.getValues(); else return -1; if ( array == null ) return -1; else return array.length; } // // public void setVal( double val ) { // // DoubleArrayData data = new DoubleArrayData(); // this.descriptor = new double[1]; // this.descriptor[0] = val; // } // // public double getVal() { // // // no "nil" check // return this.descriptor[0]; // } public String toString() { // String s = "Keypoint: [ ( "+this.x+","+this.y+" ) " + //// "- scale:"+this.scale+" " + //// "- laplacian:"+this.laplacian+" " + //// "- orientation:"+this.orientation+" " + // "- descriptor okay ? "+ ( this.data != null ) + // " ]"; String s = "<KEYPOINT="+this.getClass().getName()+">," + this.x + "," + this.y + "," + this.data + ",</KEYPOINT>"; return s; } @SuppressWarnings("unchecked") public static Keypoint getParsedInstance( String [] words, Offset c ) { Keypoint point = null; double x,y; Data data = null; assert words[c.offset].startsWith( "<KEYPOINT="+Keypoint.class.getName() ) : "Wrong position of offset " + c.offset + ": \"" + words[c.offset] + "\"."; c.offset++; int start,end; String dataClassName = null, s; Class<Data> dataClass = null; Method method; if ( c.offset < words.length ) { x = Double.parseDouble( words[c.offset++] ); y = Double.parseDouble( words[c.offset++] ); s = words[c.offset]; start = s.indexOf( "<DATA=" ); end = s.indexOf( ">" ); dataClassName = s.substring( start+6,end ); try { dataClass = ( Class ) Class.forName( dataClassName ); } catch ( ClassNotFoundException ex ) { ex.printStackTrace(); } try { method = dataClass.getMethod( "getParsedInstance", String[].class, Offset.class ); data = ( Data ) method.invoke( null,words,c ); } catch ( IllegalAccessException ex ) { ex.printStackTrace(); } catch ( InvocationTargetException ex ) { ex.printStackTrace(); } catch ( NoSuchMethodException ex ) { ex.printStackTrace(); } c.offset++; // pass </KEYPOINT> point = new Keypoint( x,y,data ); } return point; } /** This means nothing, except for this being used as a simple ( x,y, <tt>somevalue<tt> ) * keypoint and <tt>somevalue<tt> being stored in scale (used in Harris). * @param key * @return result */ public int compareTo( Keypoint key ) { // if ( this.descriptor == null ) // if ( key.descriptor == null ) return 0; // else return -1; // else // if ( key.descriptor == null ) return 1; // else return new Double( this.getVal()-key.getVal() ).intValue(); if ( this.data == null ) if ( key.data == null ) return 0; else return -1; else if ( key.data == null ) return 1; else return new Double( this.data.distance( key.data ) ).intValue(); } }