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

////////////////////////////////////////////////////////////////////////////////
//
// FILE:	WPolygon.java
//
// AUTHOR:	Manoj D. Muzumdar
//		archon@ai.mit.edu
//
// DATE:	06-XX-98
//
// COPYRIGHT:	Massachusetts Institute of Technology
//		All rights reserved.
//
// PURPOSE:     Drawing recognition
//
// HISTORY:     11-15-98 archon
//              Now aware of new rec.geo package
//
///////////////////////////////////////////////////////////////////////////////

package rec.core.widgets;

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

/**
 * WPolygon is the base Polygon call and must be overridden.
 */
public class WPolygon extends VisibleWidget
{
  public WPolygon( GPoint[] points )
  {
    setDefaultColor( "polygon" );
    setEnglishName( "Polygon" );
    Assert.check( points.length >= 3,
		  "polygons must have at least 3 sides" );

    m_Polygon = new GPolygon( points );
  }


  protected WPolygon( Vector points )
  {
    setEnglishName( "Polygon" );
    Assert.check( points.size() >= 3,
		  "polygons must have at least 3 sides" );

    GPoint[] arrPoints = new GPoint[points.size()];
    for( int i = 0; i < arrPoints.length; ++i ) {
      arrPoints[i] = (GPoint)points.elementAt( i );
    }

    m_Polygon = new GPolygon( arrPoints );
  }

  public WPolygon( GPoint[] points, int N )
  {
    setEnglishName( "Polygon" );
    Assert.check( N >= 3,
		  "polygons must have at least 3 sides" );
    Assert.check( points.length >= N,
		  "not enough points passed." );

    GPoint[] arrPoints = new GPoint[ N ];
    for( int i = 0; i < N; ++i ) {
      arrPoints[i] = points[i];
    }

    m_Polygon = new GPolygon( arrPoints );
  }

  public WPolygon( PolygonInfo pi )
  {
    setEnglishName( "Polygon" );
    GPoint[] arrPoints = new GPoint[pi.getNumberOfSides()];

    for( int i = 0; i < arrPoints.length; ++i ) {
      arrPoints[i] = pi.getPointAt( i );
    }

    m_Polygon = new GPolygon( arrPoints );
  }

  protected WPolygon( WPolygon poly )
  {
    setEnglishName( "Polygon" );
    m_Polygon = new GPolygon( poly.m_Polygon );
  }

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

  public double size()
  {
    return( m_Polygon.size() );
  }

  public void resize( double scaleFactor )
  {
    m_Polygon.resize( scaleFactor );
  }

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

  /**
   * This blank constructor should be defined in all subclasses.
   */
  protected WPolygon()
  {
    // For subclass use.
  }

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

  public void draw( Graphics graph )
  {
    Graphics2D g = (Graphics2D)graph;
    //    if ( getColor() == null )
    //      g.setColor( Colors.getColor( "polygon" ) );

    //Color c = g.getColor();
    //g.setColor( new Color( c.getRed(), c.getGreen(), c.getBlue(), 100 ) );

    m_Polygon.display( g );
  }

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

  public boolean includes( GPoint gp, double offset )
  {
    return( m_Polygon.includes( gp, offset ) );
  }

  public boolean includes( WLine l, double offset )
  {
    return( m_Polygon.includes( l.getLine(), offset ) );
  }


  public boolean contains( GPoint gp, double offset )
  {
    return m_Polygon.contains( gp, offset );
  }

  public boolean contains( GPoint gp )
  {
    return m_Polygon.contains( gp );
  }


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

  public void move( GPoint gp )
  {
    m_Polygon.translate( getLocation().getCenter(), gp );
  }

  public void rotate( GPoint gp, double angle )
  {
    m_Polygon.rotate( gp, angle );
  }

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

  public Location getLocation()
  {
    return( new Location( m_Polygon.getBounds() ) );
  }

  public Rectangle getBounds()
  {
    return( m_Polygon.getBounds() );
  }

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

  public void translate( int dx, int dy )
  {
    m_Polygon.translate( dx, dy );
  }

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

  public Object clone()
  {
    WPolygon ret = new WPolygon();

    ret.m_Polygon = new GPolygon( m_Polygon );

    return( ret );
  }

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

  public GPolygon getPolygon()
  {
    return( new GPolygon( m_Polygon ) );
  }

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

  public boolean hasEqualAngles()
  {
    GAngle[] arrAngles = m_Polygon.getAngles();
    int num = m_Polygon.getNumberOfAngles();

    double[] angles = new double[num];

    for( int i = 0; i < num; ++i ) {
      angles[i] = Degree.scaleFromRadians(
	arrAngles[i].getAngle() );
      //Console.writeln( "degree: " + angles[i] );
    }

    double stdDev = Analyzer.standardDeviation( angles );
    //Console.writeln( "standard deviation: " + stdDev );

    if( stdDev <= 12.0 )
      return( true );

    return( false );
  }

  public boolean hasEqualSides()
  {
    GSegment[] arrSides = m_Polygon.getSides();
    int num = m_Polygon.getNumberOfSides();

    double[] lines = new double[num];

    for( int i = 0; i < num; ++i ) {
      lines[i] = arrSides[i].getLength();
      //Console.writeln( "length: " + lines[i] );
    }

    double stdDev = Analyzer.standardDeviation( lines );
    //Console.writeln( "standard deviation: " + stdDev );

    double sddm = stdDev / Analyzer.mean( lines );
    //Console.writeln( "standard deviation / mean: " + sddm );

    if( sddm <= 0.1 )
      return( true );

    return( false );
  }

  public boolean isRegular()
  {
    return( hasEqualAngles() && hasEqualSides() );
  }


  public int numSides()
  {
    return m_Polygon.getNumberOfPoints();
  }


  protected GPolygon m_Polygon;
}

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