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

package rec.fsm;

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

public class LooseLineRecognizer extends Recognizer
{
  public static boolean isLine( rec.sys.Squiggle ns )
  {
    rec.sys.Squiggle s = ns;

    if( s.getNumberOfPoints() < 2 )
      return( false );

    // Find out if we are we y or x?
    double dx = s.getFirstPoint().x - s.getLastPoint().x;
    double dy = s.getFirstPoint().y - s.getLastPoint().y;

    if( Math.pow( dy, 2.0 ) > Math.pow( dx, 2.0 ) ) {
      // Flip x and y.
      // Make sure not to muck with the real rec.sys.Squiggle.
      s = (rec.sys.Squiggle)s.clone();
      s.reflect();
    }

    GPoint min, max;

    // Find the endpoints.
    if( s.getFirstPoint().x > s.getLastPoint().x ) { 
      min = s.getLastPoint();
      max = s.getFirstPoint();
    }
    else {
      min = s.getFirstPoint();
      max = s.getLastPoint();
    }

    // Compute m.
    double m = (max.y - min.y) / (max.x - min.x);

    // Envelope is 1/5th the length.
    double h2 = Math.pow( min.x - max.x, 2.0 )
                  + Math.pow( min.y - max.y, 2.0 );
    h2 /= 25.0;
    if( h2 < 10.0 )
      h2 = 10.0;

	/*
    // Check each point.
    int jump = s.getNumberOfPoints() / 30;
    if( jump == 0 )
      jump = 1;
      */

    for( int i = 0; i < s.getNumberOfPoints(); /*i += jump*/ ++i ) {

      // Outside of the endpoints.
      if( s.getPointAt( i ).x < min.x
	  || s.getPointAt( i ).x > max.x )
	return( false );

      // Outside of the envelope.
      GPoint p = s.getPointAt( i );

      double y = (p.x - min.x) * m;
      y -= p.y - min.y;

      if( Math.pow( y, 2.0 ) > h2 )
	return( false );
    }

    return( true );
  }

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

  public LooseLineRecognizer()
  {
  }

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

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

    //    Console.writeln( "line recognizer activated" );

/*
    if(Geometry.distance( st.getFirstPoint(), st.getLastPoint() ) < 50 )
      return false;
*/

    if ( isLine( st ) ) {

      Console.writeln( "line online" );

      WLine l = new WLine( st );
      s.replaceWidget( st, l );

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

    return( v.iterator() );
  }
}

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