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

package rec.simulate.widgets;
// -*-Mode: Java-*- 
// WSimAnchor.java -- 
// Author: Christine Alvarado <calvarad@ai.mit.edu> 
// Maintainer: Christine Alvarado <calvarad@ai.mit.edu> 
// Version: 
// Created: <Wed May 26 14:08:41 1999> 
// Time-stamp: <2001-09-10 18:29:18 moltmans> 
// Keywords: 

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

public abstract class WSimDamper extends WSimConstraint
{
  public WSimDamper( GSegment base )
  {
    setDefaultColor( "damper", "sim_constraint" );
    setEnglishName( "Damper" );
    m_body1 = null;
    m_body2 = null;

    // fill up the components
    m_Components = new GShape[4];
    GPoint p1;
    GPoint p2;
    GPoint p3;
    GPoint p4;
    GPoint head;
    GPoint tail;
    
    // create the damper at the origin with no rotation, and then rotate 
    // it and move it into its correct position
    head = new GPoint( -1 * base.size() / 2, 0.0 );
    tail = new GPoint( base.size() / 2, 0.0 );
    m_Components[0] = new GSegment( head, tail );
    // make the cross section, about 1/4 the length of the base
    double dist = base.size() / 8;
    p1 = new GPoint( -1 * dist, dist );
    p2 = new GPoint( -1 * dist, -1 * dist );
    p3 = new GPoint( dist, -1 * dist );
    p4 = new GPoint( dist, dist );

    m_Components[1] = new GSegment( p1, p4 );
    m_Components[2] = new GSegment( p2, p3 );
    m_Components[3] = new GSegment( p3, p4 );

    // rotate to the correct angle
    rotate( new GPoint( 0.0, 0.0 ), -1 * base.getAngle() );
    
    m_Size = base.size();

    move( base.getMidpoint() );
    
    m_Name = "Damper" + getId();

  }

  // the anchor must be attached to one body
  public boolean attach( WSimBody b )
  {
    if ( ( m_body1 != null ) && ( m_body2 != null ) ) {
      Console.writeln( "Spring already attached to two bodies.  Cannot attach to body" + b.getName() );
      return false;
    }
    // check to see if one of the ends is touching or inside the body in 
    // question.
    // the offset is set to 10, meaning the end must be close to the body
    if ( m_body1 == null ) {
      if ( b.includes( getHeadPoint(), 10 ) || 
	   b.contains( getHeadPoint(), 0 ) ) {
	m_body1 = b;
	return true;
      }
    }
    if ( m_body2 == null ) {
      if ( b.includes( getTailPoint(), 10 ) || 
	   b.contains( getTailPoint(), 0 ) ) {
	m_body2 = b;
	return true;
      }
    }
    return false;
    
  }

  public GPoint getTailPoint() 
  {
    return ((GSegment)m_Components[0]).getTailPoint();
  }

  public GPoint getHeadPoint() 
  {
    return ((GSegment)m_Components[0]).getHeadPoint();
  }


  public void detach() 
  {
    m_body1 = null;
    m_body2 = null;
  }

  public int numAttached()
  {
    int count = 0;
    if( m_body1 != null )
      count++;
    if( m_body2 != null )
      count++;
    return count;
  }

  public List getBodies() 
  {
    List list = new ArrayList( numAttached() );
    if( m_body1 != null )
      list.add( m_body1 );
    if( m_body2 != null )
      list.add( m_body2 );
    return list;
  }

  public GPoint getAttachmentPoint( WSimBody body ) 
  {
    if( body.equals( m_body1 ) )
      return getHeadPoint();
    else if( body.equals( m_body2 ) )
      return getTailPoint();
    else
      return null;
  }

  protected WSimBody m_body1;
  protected WSimBody m_body2;

} 

