// Antenna array 
// Karl L. Barrus <klbarrus@nwlink.com>
//
// Jul 2, 1996 - original
// Mar 25, 1997 - updated to JDK 1.1
//
// Copyright (c) 1996-1997 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.*;
import java.awt.event.*;

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.setBounds( 0, 0, x_dim, y_dim );    
        add( graph );    
        
        d_number = new Label( "num" );    
        d_number.setBounds( x_dim + 10, 30, 90, 20 );    
        add( d_number );    
        
        d_distance = new Label( "dist" );    
        d_distance.setBounds( x_dim + 10, 90, 90, 20 );    
        add( d_distance );    
        
        d_phase = new Label( "phase" );    
        d_phase.setBounds( x_dim + 10, 150, 90, 20 );    
        add( d_phase );    
        
        v_number = new Label( "" );    
        v_number.setBounds( x_dim + 300, 30, 100, 20 );    
        add( v_number );    
        
        v_distance = new Label( "" );    
        v_distance.setBounds( x_dim + 300, 90, 100, 20 );    
        add( v_distance );    
        
        v_phase = new Label( "" );    
        v_phase.setBounds( x_dim + 300, 150, 100, 20 );    
        add( v_phase );    
       
        sb_number = new Scrollbar( Scrollbar.HORIZONTAL, 2, 0, 2, 10 );    
        sb_number.addAdjustmentListener( new ScrollbarListener( v_number, graph ) );    
        sb_number.setUnitIncrement( 1 );     
        sb_number.setBlockIncrement( 2 );    
        sb_number.setBounds( x_dim + 100, 30, 200, 20 );    
        add( sb_number );    
        
        sb_distance = new Scrollbar( Scrollbar.HORIZONTAL, 10, 0, 1, 20 );    
        sb_distance.addAdjustmentListener( new ScrollbarListener( v_distance, graph ) );    
        sb_distance.setUnitIncrement( 1 );    
        sb_distance.setBlockIncrement( 2 );    
        sb_distance.setBounds( x_dim + 100, 90, 200, 20 );    
        add( sb_distance );    
        
        sb_phase = new Scrollbar( Scrollbar.HORIZONTAL, 0, 0, 0, 359 );    
        sb_phase.addAdjustmentListener( new ScrollbarListener( v_phase, graph ) );    
        sb_phase.setUnitIncrement( 1 );    
        sb_phase.setBlockIncrement( 20 );    
        sb_phase.setBounds( x_dim + 100, 150, 200, 20 );    
        add( sb_phase );    
        
        v_number.setText( String.valueOf( sb_number.getValue() ) );    
        v_distance.setText( String.valueOf( sb_distance.getValue() ) );    
        v_phase.setText( String.valueOf( sb_phase.getValue() ) );    
        
        repaint();
    }  
    
    public void paint( Graphics g )  
    {    
        graph.paint( g );
    }
}

class ScrollbarListener implements AdjustmentListener
{  
    Label m_label;  
    AntennaCanvas m_canvas;  
    
    ScrollbarListener( Label label, AntennaCanvas canvas )  
    {    
        m_label = label;    
        m_canvas = canvas;
    }  
    
    public void adjustmentValueChanged( AdjustmentEvent ae )  
    {    
        m_label.setText( String.valueOf( ae.getValue() ) );    
        m_canvas.repaint();
    }
}

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;  
    }
}