// Antenna array 
// Karl L. Barrus <klbarrus@nwlink.com>
// July 2, 1996
//
// Copyright (c) 1996 Karl L. Barrus
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your
// option) any later version.
// 
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
// 
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 675 Mass Ave, Cambridge, MA 02139, USA.

import java.awt.*;

public class Antenna extends java.applet.Applet
{  
	final int x_dim = 200;  
    final int y_dim = 200;  
    AntennaCanvas graph;  
    Label d_number;  
    Label d_distance;  
    Label d_phase;  
    Label v_number;  
    Label v_distance;  
    Label v_phase;  
    Scrollbar sb_number;  
    Scrollbar sb_distance;  
    Scrollbar sb_phase;  
    
    public void init()  
    {	
        setLayout( null );
        
// this is horrendous but I can't get GridBagLayout and GridBagConstraint to
// do what I want just yet	
        
        graph = new AntennaCanvas( this );	
        graph.reshape( 0, 0, x_dim, y_dim );	
        add( graph );	
        
        d_number = new Label( "num" );	
        d_number.reshape( x_dim + 10, 30, 90, 20 );	
        add( d_number );	
        
        d_distance = new Label( "dist" );	
        d_distance.reshape( x_dim + 10, 90, 90, 20 );	
        add( d_distance );	d_phase = new Label( "phase" );	
        d_phase.reshape( x_dim + 10, 150, 90, 20 );	
        add( d_phase );	
        
        sb_number = new Scrollbar( Scrollbar.HORIZONTAL, 2, 0, 2, 10 );	
        sb_number.setPageIncrement( 2 );	
        sb_number.reshape( x_dim + 100, 30, 200, 20 );	
        add( sb_number );	
        
        sb_distance = new Scrollbar( Scrollbar.HORIZONTAL, 10, 0, 1, 20 );	
        sb_distance.setPageIncrement( 2 );	
        sb_distance.reshape( x_dim + 100, 90, 200, 20 );	
        add( sb_distance );	
        
        sb_phase = new Scrollbar( Scrollbar.HORIZONTAL, 0, 0, 0, 359 );	
        sb_phase.setPageIncrement( 20 );	
        sb_phase.reshape( x_dim + 100, 150, 200, 20 );	
        add( sb_phase );	
        
        v_number = new Label( String.valueOf( sb_number.getValue() ) );	
        v_number.reshape( x_dim + 300, 30, 100, 20 );	
        add( v_number );	
        
        v_distance = new Label( String.valueOf( sb_distance.getValue() ) );	
        v_distance.reshape( x_dim + 300, 90, 100, 20 );	
        add( v_distance );	
        
        v_phase = new Label( String.valueOf( sb_phase.getValue() ) );	
        v_phase.reshape( x_dim + 300, 150, 100, 20 );	
        add( v_phase );	
        
        repaint();  
    }  
    
    public boolean handleEvent( Event event )  
    {    
        if ( event.id == Event.SCROLL_ABSOLUTE ||	     
             event.id == Event.SCROLL_LINE_DOWN ||		 
             event.id == Event.SCROLL_LINE_UP ||		 
             event.id == Event.SCROLL_PAGE_DOWN ||		 
             event.id == Event.SCROLL_PAGE_UP )	
        {	  
            v_number.setText( String.valueOf( sb_number.getValue() ) );	  
            v_distance.setText( String.valueOf( sb_distance.getValue() ) );	  
            v_phase.setText( String.valueOf( sb_phase.getValue() ) );	  
            graph.repaint();	  
            return true;	
        }	
        
        return super.handleEvent( event );  
    }  
    
    public void paint( Graphics g )  
    {	
        graph.paint( g );  
    }
}

class AntennaCanvas extends Canvas
{  
    Antenna parent;  
    double phase;  
    double dist;  
    double n;  
    double r[] = new double[ 180 ];  
    int x[] = new int[ 181 ];  
    int y[] = new int[ 181 ];  
    
    AntennaCanvas( Antenna applet )  
    {	
        parent = applet;  
    }  
    
    private double f( int degree )  
    {    
        double result;	
        double sina = Math.sin( degree * Math.PI / 180.0 );	
        double x    = ( dist * sina + phase ) / 2.0;	
        
        try	{	  
            result = Math.abs( Math.sin( n * x ) / Math.sin( x ) );	
        }	
        catch ( ArithmeticException ae )	
        {      
            result = 0.0;	
        }	
        
        return result;  
    }  
    
    public void paint( Graphics g )  
    {	
        int i;	
        g.setColor( Color.lightGray );	
        g.fillRect( 0, 0, parent.x_dim, parent.y_dim );	
        g.setColor( Color.black );	
        
        for ( i = 0; i <= parent.x_dim; i += 20 )	  
            g.drawLine( i, 0, i, parent.y_dim );    
        
        for ( i = 0; i <= parent.y_dim; i += 20 )	  
            g.drawLine( 0, i, parent.x_dim, i );	
        
        n     = parent.sb_number.getValue();	
        dist  = 2.0 * Math.PI * parent.sb_distance.getValue() / 10.0;    
        phase = parent.sb_phase.getValue() * Math.PI / 180.0;	    
        
        for ( i = 0; i <= 179; i++ )	  
            r[ i ] = f( i * 2 + 1 );	
        
        scale();	
        
        for ( i = 0; i <= 179; i++ )	
        {	  
            double angle = ( ( double ) ( i * 2 + 1 ) ) * Math.PI / 180.0; 	  
            int xs = parent.x_dim / 2;	  
            int ys = parent.y_dim / 2;	  
            x[ i ] = ( int ) ( r[ i ] * Math.cos( angle ) * xs ) + xs;	  
            y[ i ] = ( int ) ( ys - ( r[ i ] * Math.sin( angle ) * ys ) );	
        }	
        
        x[ 180 ] = x[ 0 ];	
        y[ 180 ] = y[ 0 ];	
        g.setColor( Color.red );	
        g.drawPolygon( x, y, x.length );
    }  
    
    private void scale()  
    {	
        double max = 0.0;	
        int i;	
        
        for ( i = 0; i <= 179; i++ )	  
            if ( r[ i ] > max )	    
                max = r[ i ];	
        
        for ( i = 0; i <= 179; i++ )	  
            r[ i ] /= max;
    }
}