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

// $Id: SelectionLoopRecognizer.java,v 1.7 2003/03/06 00:40:47 moltmans Exp $
// Time-stamp: <2000-03-16 22:20:55 moltmans>
package rec.core.recognizers;



/////////////////////////////////////////////////////////////////////////////
//
// FILE:	SelectionLoopRecognizer.java
//
// AUTHOR:	Manoj D. Muzumdar
//		archon@ai.mit.edu
//
// DATE:	June, 1998
//
// COPYRIGHT:	Massachusetts Institute of Technology
//		All rights reserved.
//
// PURPOSE:	Drawing recognition
//
// HISTORY:     September, 1998
//              LW
//              modified from SelectionRecognizer
//
// HISTORY:     September, 1998
//              MDM
//              modified to fit with new recognition model
//
/////////////////////////////////////////////////////////////////////////////


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

public class SelectionLoopRecognizer extends Recognizer
{
  public SelectionLoopRecognizer()
  {
  }

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

  // check for loops with overlapping tails
  public static boolean isBigLoop( rec.sys.Squiggle st )
  {
    int pv = st.getNumberOfPoints();

    if ( pv < 30 )
      return false;

    int trials = pv / 10;
    int step = trials / 10;
    if ( step == 0 )
      step = 1;

    double vk = Math.min( st.getLength() / 10.0, 50.0 );
    for ( int i = 0; i < trials; i += step )
      {
	if ( Geometry.distance( st.getPointAt( i ),
				st.getLastPoint() )
	      < vk )
	  return true;
      }

    return false;
  }

  public static boolean isCircle( rec.sys.Squiggle st )
  {
    if ( st.getNumberOfPoints() < 4 ) 
      return false;

    if( !( Geometry.distance( st.getFirstPoint(),
			      st.getLastPoint() )
	   < Math.min( st.getLength() / 10.0, 50.0 ) ) )
      return( false );

    return( true );
  }

  

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

    WGroup grp = null;

    if( isCircle( st ) || ( isBigLoop( st ) ) ) {

      //Console.writeln( "looking for selection" );

      grp = findGroup( s, st );

      if ( grp == null )
	// didn't find anything.  Exit
	return( false );
      
      // always make a group, no matter what
      WSelection sl = new WSelection( grp, true );
      s.replaceWidget( w, sl );
      
      return true;
      
    }

    return( false );
  }

  protected WGroup findGroup( Surface s, Squiggle st )
  {
    GPolySegment poly = st.getPolygon();
    Rectangle r = poly.getBounds();

    WGroup grp = null;
      Iterator e = s.getSurfacePoolIterator();
      while( e.hasNext() ) {

	VisibleWidget vw = (VisibleWidget)e.next();
	if ( vw.equals( st ) )
	  continue;

  	if( r.contains( vw.getBounds() ) &&
	    poly.contains( vw.getLocation().getCenter() ) )
	{
	  if ( grp == null )
	    grp = new WCircleGroup( st );

	  grp.add( vw );
	}
      }
      return grp;
  }

  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.WSelection" );

    return( v.iterator() );
  }
}

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