// (c) MIT 2003.  All rights reserved.

////////////////////////////////////////////////////////////////////////////////
//
// FILE:	CircleRecognizer.java
//
// AUTHOR:	Manoj D. Muzumdar
//		archon@ai.mit.edu
//
//              Adapted from code written by Luke Weisman
//              luke@ai.mit.edu
//
// DATE:	06-XX-98
//
// COPYRIGHT:	Massachusetts Institute of Technology
//		All rights reserved.
//
// PURPOSE:	Drawing recognition
//
// HISTORY:     09-XX-98 archon
//              Modified to fit with new recognition model.
//
//              11-15-98 archon
//              Now aware of new rec.geo package.
//
//              Mar 99  archon
//              Made more accurate in light of oval recognition.
//
////////////////////////////////////////////////////////////////////////////////

package rec.core.recognizers;

import java.util.*;
import java.awt.*;
import rec.util.*;
import rec.geo.*;
import rec.sys.*;
import rec.core.widgets.*;

public class CircleRecognizer extends Recognizer
{
  public static boolean isCircle( rec.sys.Squiggle st )
  {
    if( st.getLength() < 50 )
      return( false );

    // Make sure endpoints connect.

    if( Geometry.distance( st.getFirstPoint(), st.getLastPoint() ) > 10.0 )
      return( false );

    // Addition check to make sure it is a circle; this is in light of my
    //   need for ovals and curves; need to desensitize circle recognition.

    // Calculate concentric bounding circles.

    Rectangle bounds = st.getBounds();

    double rad1 = (bounds.width + bounds.height) / 5.0;
    double rad2 = (bounds.width + bounds.height) / 3.0;

    GPoint cen = st.getLocation().getCenter();

    int num = st.getNumberOfPoints();

    for( int i = 0; i < num; ++i ) {

      GPoint p = st.getPointAt( i );

      double dist = Geometry.distance( p, cen );

      // Return false if outside the concentric circles.

      if( dist < rad1 || dist > rad2 )
	return( false );
    }

    // Looks like we have a circle!

    return( true );
  }

  //////////////////////////////////////////////////////////////////////////////

  public CircleRecognizer()
  {
  }

  //////////////////////////////////////////////////////////////////////////////

  public boolean recognize( Surface s, Widget w )
  {
    rec.sys.Squiggle st = (rec.sys.Squiggle)w;

    if( st.getLength() < 40 )
      return( false );
    
    if( isCircle( st ) ) {

      //Console.writeln( "circle online" );

      WCircle c = new WCircle( st.getBounds() );
      s.replaceWidget( st, c );

      return( true );
    }

    return( false );
  }

  public Iterator getInputTypes()
  {
    Vector v = new Vector();

    v.addElement( "rec.sys.Squiggle" );

    return( v.iterator() );
  }

  public Iterator getOutputTypes()
  {
    Vector v = new Vector();

    v.addElement( "rec.core.widgets.WCircle" );

    return( v.iterator() );
  }
}

////////////////////////////////////////////////////////////////////////////////
