import java.applet.*; import java.awt.*; import java.awt.image.*; import java.awt.event.*; import java.io.*; import java.net.*; import java.text.*; import java.util.*; import java.util.zip.*; import netscape.javascript.*; import javax.comm.*; import javax.sound.midi.*; import javax.sound.midi.spi.*; import javax.sound.sampled.*; import javax.sound.sampled.spi.*; import javax.xml.parsers.*; import javax.xml.transform.*; import javax.xml.transform.dom.*; import javax.xml.transform.sax.*; import javax.xml.transform.stream.*; import org.xml.sax.*; import org.xml.sax.ext.*; import org.xml.sax.helpers.*; public class Map1 extends BApplet {PSystem ps;
Arcball arcball;


SinCosField2D myMap;


void setup() {
  size(500, 500);
  ps = (PSystem)loadPlugin("PSystem");
  arcball = (Arcball)loadPlugin("Arcball");
  
  myMap = new SinCosField2D();
}

void loop() {
  background(0xff99CCCC);

  stroke(255, 0, 0, 100);
  translate(width/2, height/2, 0);
  arcball.run();
  translate(-width/2, -height/2, 0);
  myMap.draw2DVectors(width, height, 100, 100, 20);
}


class SinCosField2D extends Map {

  SinCosField2D() {
    super(2, 2);
  }

  void map(float[] in, float[] out) {
    out[0] = ((sin(TWO_PI*(in[0] + (float)mouseX / width)) + 1) / 2) * ((cos(frame / 100.0f + TWO_PI*in[1]) + 1) / 2);
    out[1] = ((cos(frame / 77.0f + TWO_PI*in[0]) + 1) / 2) * ((sin(TWO_PI*(in[1] + (float)mouseY / height)) + 1) / 2);
  }
  
}

class SqField2D extends Map {

  SqField2D() {
    super(2, 2);
  }

  void map(float[] in, float[] out) {
    out[0] = sqrt(in[0]);
    out[1] = in[1] * in[1];
  }
  
}

class SinCosField3D extends Map {

  SinCosField3D() {
    super(3, 3);
  }

  void map(float[] in, float[] out) {
    out[0] = ((sin(TWO_PI*(in[0] + (float)mouseX / width)) + 1) / 2) * ((cos(frame / 100.0f + TWO_PI*in[1]) + 1) / 2);
    out[1] = ((cos(frame / 77.0f + TWO_PI*in[0]) + 1) / 2) * ((sin(TWO_PI*(in[1] + (float)mouseY / height)) + 1) / 2);
    out[2] = in[2] * in[2];
  }

}


class Map {
  int inDim;
  int outDim;
  boolean isPolar = false;

  Map(int inDim, int outDim) {
    this.inDim = inDim;
    this.outDim = outDim;
  }

  void map(float[] in, float[] out) {
    for (int i = 0; i < outDim; i++) {
      out[i] = 0;
    }
  }

  void draw2DVectors(float fieldWidth, float fieldHeight, int xCells, int yCells, float baseLength) {
    if (isPolar) {
      draw2DVectorsPolar(fieldWidth, fieldHeight, xCells, yCells, baseLength);
    }
    else {
      draw2DVectorsCartesian(fieldWidth, fieldHeight, xCells, yCells, baseLength);
    }
  }

  void draw3DVectors(float fieldWidth, float fieldHeight, float fieldDepth, int xCells, int yCells, int zCells, float baseLength) {
    if (outDim != 3 || inDim != 3) {
      return;
    }

    float[] output = new float[3];
    float[] input = new float[3];

    float xInc = fieldWidth / xCells;
    float yInc = fieldHeight / yCells;
    float zInc = fieldDepth / zCells;

    float xIn, yIn, zIn;

    for (int x = 0; x < xCells; x++) {

      for (int y = 0; y < yCells; y++) {

        for (int z = 0; z < zCells; z++) {

          xIn = (x + 0.5f) / (float)xCells;
          yIn = (y + 0.5f) / (float)yCells;
          zIn = (z + 0.5f) / (float)zCells;
          
          input[0] = xIn;
          input[1] = yIn;
          input[2] = zIn;

          map(input, output);

          push();
          translate((x + 0.5f) * xInc, (y + 0.5f) * yInc, (z + 0.5f) * zInc);
          line(0, 0, 0, baseLength * output[0], baseLength * output[1], baseLength * output[2]);
          pop();
        }
      }
    }
  }

  void draw2DVectorsCartesian(float fieldWidth, float fieldHeight, int xCells, int yCells, float baseLength) {
    if (outDim != 2 || inDim != 2) {
      return;
    }

    float[] output = new float[2];
    float[] input = new float[2];

    float xInc = fieldWidth / xCells;
    float yInc = fieldHeight / yCells;

    float xIn, yIn;

    for (int x = 0; x < xCells; x++) {

      for (int y = 0; y < yCells; y++) {

        xIn = (x + 0.5f) / (float)xCells;
        yIn = (y + 0.5f) / (float)yCells;
        input[0] = xIn;
        input[1] = yIn;

        map(input, output);

        push();
        translate((x + 0.5f) * xInc, (y + 0.5f) * yInc);
        line(0, 0, baseLength * output[0], baseLength * output[1]);
        pop();
      }
    }
  }

  void draw2DVectorsPolar(float fieldWidth, float fieldHeight, int xCells, int yCells, float baseLength) {
    if (outDim != 2 || inDim != 2) {
      return;
    }

    float[] output = new float[2];
    float[] input = new float[2];

    float xInc = fieldWidth / xCells;
    float yInc = fieldHeight / yCells;

    float xIn, yIn;

    for (int x = 0; x < xCells; x++) {

      for (int y = 0; y < yCells; y++) {

        xIn = (x + 0.5f) / (float)xCells;
        yIn = (y + 0.5f) / (float)yCells;
        input[0] = xIn;
        input[1] = yIn;

        map(input, output);

        push();
        translate((x + 0.5f) * xInc, (y + 0.5f) * yInc);
        line(0, 0, output[1] * baseLength * cos(TWO_PI * output[0]), output[1] * baseLength * sin(TWO_PI * output[0]));
        pop();
      }
    }
  }

}


}