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

////////////////////////////////////////////////////////////////////////////////
//
// FILE:	ForceRecognizer.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 ForceRecognizer extends Recognizer
{
  public static WMForce isForce( WLine l1, WLine l2, WLine l3 )
  {
    GSegment s1 = new GSegment( l1.getHead(), l1.getTail() );
    GSegment s2 = new GSegment( l2.getHead(), l2.getTail() );
    GSegment s3 = new GSegment( l3.getHead(), l3.getTail() );

    GSegment a1 = null;
    GSegment a2 = null;
    GSegment body = null;


    if( Estimator.isSameSize( s1.size(), s2.size() )
	&& Estimator.arePerpendicular( s1, s2 )
	&& s3.size() > (s1.size() * 2) ) {
      a1 = s1;
      a2 = s2;
      body = s3;
    }
    else if( Estimator.isSameSize( s2.size(), s3.size() )
	     && Estimator.arePerpendicular( s2, s3 )
	     && s1.size() > (s2.size() * 2) ) {
      a1 = s2;
      a2 = s3;
      body = s1;
    }
    else if( Estimator.isSameSize( s1.size(), s3.size() )
	     && Estimator.arePerpendicular( s1, s3 )
	     && s2.size() > (s1.size() * 2.0) ) {
      a1 = s1;
      a2 = s3;
      body = s2;
    }

    // Return if initial tests fail.

    else {
      return( null );
    }

    GPoint c1 = Estimator.connects( body, a1, 20.0 );
    GPoint c2 = Estimator.connects( body, a2, 20.0 );

    // Incorrect connection.

    if( c1 != null && c2 != null && c1.equals( c2 ) ) {

      if( c1.equals( body.getHeadPoint() ) )
	return( new WMForce( body.getMidpoint(),
			     Geometry.angle( body.getTailPoint(),
					     body.getHeadPoint() ),
			     body.size(),
			     null ) );

      if( c1.equals( body.getTailPoint() ) )
	return( new WMForce( body.getMidpoint(),
			     Geometry.angle( body.getHeadPoint(),
					     body.getTailPoint() ),
			     body.size(),
			     null ) );
    }

    return( null );
  }


  public ForceRecognizer()
  {
  }



  public boolean recognize( Surface s, Widget w )
  {
    WLine l = (WLine)w;

    GeometryCalculator gc = new GeometryCalculator( s );

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

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

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

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

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

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

	  if( vw2 instanceof WLine && !vw2.equals( l )
	      && !vw2.equals( vw1 ) ) {
              
	    WMForce wf = isForce( l, (WLine)vw1, (WLine)vw2 );

	    if( wf != null ) {

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

	      s.addWidget( wf );

	      return( true );
	    }
	  }
	}
      }
    }

    return( false );
  }

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

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

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

    return( v.iterator() );
  }

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

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

    return( v.iterator() );
  }
}

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