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

package rec.simulate.recognizers;
// -*-Mode: Java-*- 
// SimAnchorRecognizer.java -- 
// Author: Christine Alvarado <calvarad@ai.mit.edu> 
// Maintainer: Christine Alvarado <calvarad@ai.mit.edu> 
// Version: 
// Created: <Wed May 26 16:06:48 1999> 
// Time-stamp: <2001-09-10 18:21:29 moltmans> 
// Keywords: 

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

public class SimAnchorRecognizer extends Recognizer
{
  private WSimAnchor isAnchor( WLine l1, WLine l2, Surface s )
  {
    // I am not sure whether or not to make sure that the anchor is in
    // one object or not, maybe just check that at simulation time.  
    // if it gets to be a problem, we will add the check here at recognition
    // time, but it could possibly make the system slow, especially for
    // many objects, unless we use a more efficient serch alrogithm than 
    // the naive way of checking every object.
 
    // make sure that the lines are about the same size and intersect
    GSegment s1 = new GSegment( l1.getHead(), l1.getTail() );
    GSegment s2 = new GSegment( l2.getHead(), l2.getTail() );
    GPoint intersection;

    if( Estimator.isSameSize( s1.size(), s2.size() )
	&& ((intersection = s1.getIntersectionAtMidpoint( s2, 20 )) != null ) ) {
      // the intersection point will be the center.
      // the components will be two lines which cross at the center.
      double ave_size = (s1.size() + s2.size()) / 2;
      return ( ((SimulateSurface)s).makeSimAnchor( intersection, ave_size ));
    }
    else {
      return null;
    }
    
  }
  

  public SimAnchorRecognizer()
  {
  }

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

    GeometryCalculator gc = new GeometryCalculator( s );

    Iterator it = gc.getVisibleWidgets().iterator();

    while ( it.hasNext() ) {
      VisibleWidget vw1 = (VisibleWidget)it.next();

      if( vw1 instanceof WLine && !vw1.equals( l ) ) {
	// check to see if the lines intersect and are about the 
	// same lengeth and are both inside the same body.
	WSimAnchor a = isAnchor( l, (WLine)vw1, s );

	if ( a != null ) {
	  s.removeWidget( l );
	  s.removeWidget( vw1 );
	  
	  s.addWidget( a );
	  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.simulate.widgets.WSimAnchor" );

    return( v.iterator() );
  }

}
