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

////////////////////////////////////////////////////////////////////////////////
//
// FILE:	GearRecognizer.java
//
// AUTHOR:	Manoj D. Muzumdar
//		archon@ai.mit.edu
//
// DATE:	Mar 99
//
// COPYRIGHT:	Massachusetts Institute of Technology
//		All rights reserved.
//
// PURPOSE:	Mechanical engineering drawing recognition
//
// HISTORY:     Mar 99  archon  created
//
////////////////////////////////////////////////////////////////////////////////

package rec.meche;

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

public class GearRecognizer extends Recognizer
{
  public static WMGear isGear( WCircle c, WLine l1, WLine l2,
			       WLine l3, WLine l4 )
  {
    double d1 = Geometry.distance( c.getCenter(),
				   l1.getLine().getMidpoint() );
    double d2 = Geometry.distance( c.getCenter(),
				   l2.getLine().getMidpoint() );
    double d3 = Geometry.distance( c.getCenter(),
				   l3.getLine().getMidpoint() );
    double d4 = Geometry.distance( c.getCenter(),
				   l4.getLine().getMidpoint() );
    double rad = c.getRadius();

    if( l1.size() < c.size() / 2.0
	&& l2.size() < c.size() / 2.0
	&& l3.size() < c.size() / 2.0
	&& l4.size() < c.size() / 2.0
	&& d1 > rad && d1 < 2.0 * rad
	&& d2 > rad && d2 < 2.0 * rad
	&& d3 > rad && d3 < 2.0 * rad
	&& d4 > rad && d4 < 2.0 * rad
	&& Estimator.isSameAngle( c.getCenter(), l1.getHead(),
				  c.getCenter(), l1.getTail() )
	&& Estimator.isSameAngle( c.getCenter(), l2.getHead(),
				  c.getCenter(), l2.getTail() )
	&& Estimator.isSameAngle( c.getCenter(), l3.getHead(),
				  c.getCenter(), l3.getTail() )
	&& Estimator.isSameAngle( c.getCenter(), l4.getHead(),
				  c.getCenter(), l4.getTail() ) ) {

      return( new WMGear( c.getCenter(),
			  Math.PI / 2.0,
			  c.size(),
			  null ) );
    }

    return( null );
  }

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

  public GearRecognizer()
  {
  }

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

  public boolean recognize( Surface s, Widget w )
  {
    GeometryCalculator gc = new GeometryCalculator( s );

    Vector vect = new Vector( gc.getVisibleWidgets() );

    if( vect.size() < 5 )
      return( false );

    if( w instanceof WCircle ) {

      WCircle c = (WCircle)w;

      for( int i = 0; i < vect.size(); ++i ) {

	Widget vw1 = (Widget)vect.elementAt( i );

	if( vw1 instanceof WLine ) {

	  for( int j = 0; j < vect.size(); ++j ) {

	    Widget vw2 = (Widget)vect.elementAt( j );

	    if( vw2 instanceof WLine && !vw2.equals( vw1 ) ) {

	      for( int k = 0; k < vect.size(); ++k ) {

		Widget vw3 = (Widget)vect.elementAt( k );

		if( vw3 instanceof WLine && !vw3.equals( vw1 )
		    && !vw3.equals( vw2 ) ) {

		  for( int q = 0; q < vect.size(); ++q ) {

		    Widget vw4 = (Widget)vect.elementAt( q );

		    if( vw4 instanceof WLine && !vw4.equals( vw1 )
			&& !vw4.equals( vw2 ) && !vw4.equals( vw3 ) ) {

		      WMGear part = isGear( c, (WLine)vw1, (WLine)vw2,
					    (WLine)vw3, (WLine)vw4 );

		      if( part != null ) {

			s.removeWidget( c );
			s.removeWidget( vw1 );
			s.removeWidget( vw2 );
			s.removeWidget( vw3 );
			s.removeWidget( vw4 );

			s.addWidget( part );

			return( true );
		      }
		    }
		  }
		}
	      }
	    }
	  }
	}
      }
    }

    if( w instanceof WLine ) {

      WLine l = (WLine)w;

      for( int i = 0; i < vect.size(); ++i ) {

	Widget vw1 = (Widget)vect.elementAt( i );

	if( vw1 instanceof WCircle ) {

	  for( int j = 0; j < vect.size(); ++j ) {

	    Widget vw2 = (Widget)vect.elementAt( j );

	    if( vw2 instanceof WLine && !vw2.equals( l ) ) {

	      for( int k = 0; k < vect.size(); ++k ) {

		Widget vw3 = (Widget)vect.elementAt( k );

		if( vw3 instanceof WLine && !vw3.equals( l )
		    && !vw3.equals( vw2 ) ) {

		  for( int q = 0; q < vect.size(); ++q ) {

		    Widget vw4 = (Widget)vect.elementAt( q );

		    if( vw4 instanceof WLine && !vw4.equals( l )
			&& !vw4.equals( vw2 ) && !vw4.equals( vw3 ) ) {

		      WMGear part = isGear( (WCircle)vw1, l, (WLine)vw2,
					    (WLine)vw3, (WLine)vw4 );

		      if( part != null ) {

			s.removeWidget( vw1 );
			s.removeWidget( l );
			s.removeWidget( vw2 );
			s.removeWidget( vw3 );
			s.removeWidget( vw4 );

			s.addWidget( part );

			return( true );
		      }
		    }
		  }
		}
	      }
	    }
	  }
	}
      }
    }

    return( false );
  }

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

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

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

    return( v.iterator() );
  }

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

    v.addElement( "rec.meche.WMGear" );

    return( v.iterator() );
  }
}

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