// n=2 instantons,  Evgeny Demidov 22 May 2004
import java.awt.*;
import java.awt.event.*;
import java.util.StringTokenizer;

public class inst2 extends java.applet.Applet
  implements MouseListener, MouseMotionListener, KeyListener{
Image buffImage;          Graphics buffGraphics;
int n = 25, ins=1, w,h,h1,w2,
    max=450, m2=max/2, a=max/n, a2=a/2, ar=a2-1, dx,dy,dz;
double xo=0,yo=0, xr=0,yr=0, st=.3, al=0;
Label  lbA;    TextField tfA;

public void init() {
  w = Integer.parseInt(getParameter("width"));
  h = Integer.parseInt(getParameter("height"));  h1 = h-1; w2 = w/2;
  String s=getParameter("XY"); if (s != null) {
    StringTokenizer ST = new StringTokenizer(s);
    xo = Double.valueOf(ST.nextToken()).doubleValue();
    yo = Double.valueOf(ST.nextToken()).doubleValue();
    st = Double.valueOf(ST.nextToken()).doubleValue() / max;}
  s = getParameter("alpha"); if (s != null) al=Double.valueOf(s).doubleValue();
  s=getParameter("ins"); if (s != null) ins = Integer.parseInt(s);
  buffImage = createImage(w, h);
  buffGraphics = buffImage.getGraphics();
//  setBackground(Color.white);
  addMouseListener(this);
  addMouseMotionListener(this);
  this.setLayout( new FlowLayout(FlowLayout.LEFT, 0, 0) );
  lbA = new Label("a");  add(lbA);
  tfA = new TextField( "" + (float)al, 5);  add(tfA);
  tfA.addKeyListener(this);
  drawField();
}

public void destroy(){
  removeMouseListener(this);
  removeMouseMotionListener(this);
}
public void mouseClicked(MouseEvent e) {}      //1.1 event handling
public void mousePressed(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent  e) {}
public void mouseMoved(MouseEvent e){}
public void keyTyped(KeyEvent e){}
public void keyPressed(KeyEvent e){}
public void keyReleased(KeyEvent e){
  final int keyEnter = 10;
  if (e.getKeyCode() == keyEnter){
    try{ al = Double.valueOf(tfA.getText()).doubleValue();
    }catch(NumberFormatException ne){}
    drawField();  repaint();
  }
}

public void mouseReleased(MouseEvent e) {
  double xt = xo+(e.getX()-m2)*st,
         yt = yo-(e.getY()-m2)*st;
  if ( e.isControlDown() ) {
    if ( e.isShiftDown() )  st *= 3;  else  st *= 2;}
  else if ( e.isAltDown() ) {
    if ( e.isShiftDown() )  st /= 3;  else  st /= 2;}
  else return;
  xo = xt;  yo = yt;
  drawField();  repaint();
}

public void mouseDragged(MouseEvent e) {
  xr = xo + st*(e.getX() - m2);  
  yr = yo - st*(e.getY() - m2);  
  drawField();  repaint();
}

public void drawField(){
  buffGraphics.setColor(Color.white);
  buffGraphics.fillRect(0,0, w, h);
  buffGraphics.setColor(Color.lightGray);
  buffGraphics.drawRect(0,0, max,max);
  int d = (int)(1/st),
      ix = m2 + (int)((.5*Math.cos(-al*ins)-xo-.5)/st),
      iy = m2 - (int)((-.5*Math.sin(-al*ins)-yo+.5)/st);
  buffGraphics.drawOval(ix,iy, d,d);
  ix = m2 + (int)((xr-xo)/st);  iy = m2 - (int)((yr-yo)/st);
  buffGraphics.drawLine(ix,0, ix, max );
  buffGraphics.drawLine(0,iy, max,iy );
  double x,y;
  for (iy = max-a2; iy>0; iy-=a){
   y = yo - st*(iy-m2);
   N(xr,y); arrow(max+a,iy, -dz,dy);
   for (ix = max-a2; ix>0; ix-=a){
    x = xo + st*(ix-m2);
    N(x,y); arrow(ix,iy, dx,dy);}}
  for (ix = max-a2; ix>0; ix-=a){
   x = xo + st*(ix-m2);
   N(x,yr); arrow(ix,max+a, dx,-dz);}
}

public void N(double x, double y){
  double r,f, fi,th, c,s,t;
  r = Math.sqrt(x*x+y*y);  f = ins*Math.atan2(y,x) - al;
  c = Math.cos(f);  s = Math.sin(f);  t=r-c;
  fi = Math.atan2(s,t);   fi += fi;   t=r/Math.sqrt(t*t+s*s);
  th = 2*Math.atan(t*t);
//System.out.println(""+fi+"  "+th);
  dx = (int)(ar*Math.cos(th));  t = ar*Math.sin(th);
  dy = -(int)(t*Math.sin(fi));  dz = (int)(t*Math.cos(fi));
  if (dz > 0) buffGraphics.setColor(Color.red);
//  if (Math.abs(fi) < Math.PI/2) buffGraphics.setColor(Color.red);
     else buffGraphics.setColor(Color.blue);
}

public void arrow(int ix, int iy, int dx, int dy){
  int xa = ix + dx,  ya = iy + dy;
  buffGraphics.drawLine(ix-dx,iy-dy, xa,ya );
  int dx2 = dx/3,  dy2 = dy/3;
  buffGraphics.drawLine(xa,ya, ix+dy2, iy-dx2 );
  buffGraphics.drawLine(xa,ya, ix-dy2, iy+dx2 );
}

public void paint(Graphics g) {
  g.drawImage(buffImage, 0, 0, this);
  showStatus( "x="+(float)xr+"   y="+(float)yr);
}

public void update(Graphics g){ paint(g); }

}