/*
* Copyright 2005, 2009 Cosmin Basca.
* e-mail: cosmin.basca@gmail.com
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* Please see COPYING for the complete licence.
*/
package robo.vision;
import java.awt.geom.Point2D;
import java.util.List;
import java.util.Vector;
public class EllipseDescriptor
{
public static final String DETECTED_ELLIPSES = "DETECTED ELLIPSES";
private double ELLIPSE_SIMILARITY_DISTANCE = 20.0;
private Point2D center;
private Point2D v1;
private Point2D v2;
private int a;
private int b;
//private double alfa;
public EllipseDescriptor()
{
}
public EllipseDescriptor(Point2D v1,Point2D v2,Point2D c,int a,int b)
{
this.v1 = new Point2D.Double(v1.getX(),v1.getY());
this.v2 = new Point2D.Double(v2.getX(),v2.getY());
this.center = new Point2D.Double(c.getX(),c.getY());
this.a = a;
this.b = b;
}
public void setHalfMinorAxis(int b)
{
this.b = b;
}
public int getHalfMinorAxis()
{
return this.b;
}
public void setHalfMajorAxis(int a)
{
this.a = a;
}
public int getHalfMajorAxis()
{
return this.a;
}
public void setCenter(Point2D c)
{
this.center = new Point2D.Double(c.getX(),c.getY());
}
public void setVertex1(Point2D v)
{
this.v1 = new Point2D.Double(v.getX(),v.getY());
}
public void setVertex2(Point2D v)
{
this.v2 = new Point2D.Double(v.getX(),v.getY());
}
public Point2D getCenter()
{
return this.center;
}
public Point2D getVertex1()
{
return this.v1;
}
public Point2D getVertex2()
{
return this.v2;
}
// in radiani
public double getAlfa()
{
double alfa = 0.0;
if(v1.getX() == v2.getX())
alfa = Math.PI / 2.0; // vertical - 90
else
alfa = Math.tan(( v1.getY() - v2.getY() ) / ( v1.getX() - v2.getX() ));
return alfa;
}
public double distance(EllipseDescriptor ed)
{
double dCen = this.center.distance(ed.getCenter());
double dAlfa = Math.sqrt( ( this.getAlfa()-ed.getAlfa() )*( this.getAlfa()-ed.getAlfa() ) );
return ( Math.sqrt( (a-ed.getHalfMajorAxis())*(a-ed.getHalfMajorAxis()) )+
Math.sqrt( (b-ed.getHalfMinorAxis())*(b-ed.getHalfMinorAxis()) )+
dCen +
dAlfa ) / 4.0;
}
public static List<EllipseDescriptor> getCentroidalEllipses(List<EllipseDescriptor> allEllipses)
{
// build clusters;
Vector<Vector<EllipseDescriptor>> clusters = new Vector<Vector<EllipseDescriptor>>();
Vector<EllipseDescriptor> tmpCluster = null;
for(int i=0;i<allEllipses.size();i++)
{
EllipseDescriptor clusterRep = allEllipses.get(i);
tmpCluster = new Vector<EllipseDescriptor>();
for(int j=0;j<allEllipses.size();j++)
{
if(clusterRep.equals(allEllipses.get(j))) // have one
{
tmpCluster.addElement(allEllipses.get(j));
allEllipses.remove(j--);
clusterRep = EllipseDescriptor.getCentroid(tmpCluster);
}
}
if(tmpCluster.size() > 1)
{
clusters.addElement(tmpCluster);
i = 0;
}
}
// get Centroids and return them
Vector<EllipseDescriptor> centroids = new Vector<EllipseDescriptor>();
for(int i=0;i<clusters.size();i++)
centroids.addElement(EllipseDescriptor.getCentroid(clusters.elementAt(i)));
return centroids;
}
public static EllipseDescriptor getCentroid(Vector<EllipseDescriptor> ellipses)
{
// find the mean x and mean y of centers
double cx[] = new double[ellipses.size()];
double cy[] = new double[ellipses.size()];
for(int i=0;i<ellipses.size();i++)
{
cx[i] = ((EllipseDescriptor)ellipses.elementAt(i)).center.getX();
cy[i] = ((EllipseDescriptor)ellipses.elementAt(i)).center.getY();
}
double meanX = robo.util.Util.getHarmonicMean(cx);
double meanY = robo.util.Util.getHarmonicMean(cy);
int centroid = -1;
double dist = Double.MAX_VALUE;
// find the closest to the center
for(int i=0;i<ellipses.size();i++)
if( Point2D.distance(cx[i],cy[i],meanX,meanY) < dist )
{
dist = Point2D.distance(cx[i],cy[i],meanX,meanY);
centroid = i;
}
if(centroid != -1)
return ellipses.elementAt(centroid);
return null;
}
public boolean equals(Object o)
{
boolean equal = false;
if(o instanceof EllipseDescriptor)
{
//System.out.println(((EllipseDescriptor)o).distance(this));
if( ((EllipseDescriptor)o).distance(this) <= ELLIPSE_SIMILARITY_DISTANCE )
equal = true;
}
return equal;
}
public double getPerimeter()
{
return Math.PI * ( (3*a + 3*b) - Math.sqrt( (a+3*b)*(b+3*a) ) );
}
public double getExcentricity()
{
return Math.sqrt(1 - (double)(b*b)/(double)(a*a) );
}
public String toString()
{
String str = "";
str += "<"+"a: " + String.valueOf(a);
str += " ,b: " + String.valueOf(b);
str += " ,C: (" + center.getX()+","+center.getY()+")";
str += " ,V1 : (" + v1.getX()+","+v1.getY()+")";
str += " ,V2 : (" + v2.getX()+","+v2.getY()+")";
str += " ,Alfa: " + getAlfa();
str += " ,P: " + getPerimeter();
str += " ,Ex: " + getExcentricity();
str += " >";
return str;
}
}