// *************************************************************
// **************************************************************
import visad.*;
import visad.util.*;
import visad.browser.*;
import visad.java2d.DisplayImplJ2D;
import visad.java3d.DisplayImplJ3D;
import java.rmi.RemoteException;
import java.math.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.lang.Float;
import java.applet.*;
import javax.swing.*;

// ********************************************************
// The troublesome class, which produces a 3-d scatter plot.  The code
//  runs without modification as either an applet or app.  
// ********************************************************
public class apfrm extends Applet
{
   // *********************************************
   // * These are static objects shared and used  *
   // * for visad...                              *
   // *********************************************
   static RealType x1; 
   static RealType x2; 
   static RealType x3;

   static RealTupleType x1_x2_x3_tuple;
   static DisplayImpl display;
   static ScalarMap x1Map, x2Map, x3Map;
   static ConstantMap[] pointsCMap;
   static DataReferenceImpl data_ref;

   static RealType index;
   static RangeWidget ranWid = null;

   static FlatField vals_ff=null;    
   static Integer1DSet prop_set=null;
   static FunctionType func_i_tuple=null;
  // a couple useful variables
   static Boolean firsttime = Boolean.TRUE;
  // next 2 needed to run as an app
   static boolean inApplet = true;
   static Hashtable parameters = new Hashtable();


   // ******************************************************
   // * This construct done all the work of your           *
   // *  multiinit_workaround()                            *
   // ******************************************************
   apfrm() 
   {
System.out.println("NST INITIALISATION...");
      // *************************************************
      // * Since these objects will be used throughout,  *
      // * there are declared and assigned here once and *
      // * and for all!                                  *
      // *************************************************
      try {
         x1 = new RealType( "x-axis" );
         x2 = new RealType( "y-axis" );
         x3 = new RealType( "z-axis" );
         index = new RealType( "dataIndex"); // !!NST assign here once only!

         x1_x2_x3_tuple = new RealTupleType(x1, x2, x3);
         x1Map = new ScalarMap( x1, Display.XAxis );
         x2Map = new ScalarMap( x2, Display.YAxis );
         x3Map = new ScalarMap( x3, Display.ZAxis );

         pointsCMap = new ConstantMap[] {
            new ConstantMap( 1.0f, Display.Red ),
            new ConstantMap( 0.0f, Display.Green ),
            new ConstantMap( 0.0f, Display.Blue ),
            new ConstantMap( 4.5f, Display.PointSize)
         }; 
         data_ref = new DataReferenceImpl("data_ref");
         display = new DisplayImplJ3D("display");
         display.addMap( x1Map );
         display.addMap( x2Map );
         display.addMap( x3Map );
         display.addReference( data_ref, pointsCMap );

         // ************************************************
         // * !!NST Initialize you applet (Panel) here     *
         // * as Well!                                     *
         // ************************************************
         this.setLayout(new BorderLayout());
         this.setSize( 450, 450 );
         this.add(display.getComponent());
      }
      catch (Exception e) {
         e.printStackTrace();
      }
   }


   // ******************************************************
   //
   // most interesting work goes on here
   //
   // ******************************************************
   public void start()
   {
       boolean problems = false;
       System.out.println("entering start");

       // get the data
       Vector d1 = getdim("d1_");
       Vector d2 = getdim("d2_");
       Vector d3 = getdim("d3_");

       // ***********************************************
       // * make a new index for the data, since it may *
       // * have a different length                     *
       // ***********************************************
       if(!problems) {
          try {
             prop_set = new Integer1DSet( index, d1.size() );  
             func_i_tuple = new FunctionType( index, x1_x2_x3_tuple );
             vals_ff = new FlatField( func_i_tuple, prop_set);
          }
          catch (Exception e)  {
             System.out.println("apfrm::start.ERROR:  Common code section error.");
             System.out.println(e.toString());
            problems = true;
          }
      }
      // *************************************************
      // * The time through we add the maps, while every *
      // * subsequent time we remove  the maps, modify   *
      // * them, and them put them back.                 *
      // *************************************************
      if(!problems) {
         try {
            // ******************************************
            // * !!NST if your data set varies in size  *
            // * you may have to remove the old data    *
            // * reference and add a new one into the   *
            // * display                                *
            // ******************************************
            problems = add3dData( d1, d2, d3, "x", "y", "z" );
//          display.addReference( data_ref, pointsCMap );
         }
         catch (Exception e)  {
            // *******************************************
            // * !!NST Use this to printout errorStack   *
            // * This is most useful, as it will, most   *
            // * of the time, pinpoint to the line in    *
            // * your source code causing the error!     *
            // * And a trace of the call!!!              *
            // *******************************************
            e.printStackTrace();

            // *******************************************
            // *******************************************
//          System.out.println("apfrm::start.ERROR:  Common code II section error.");
//          System.out.println(e.toString());
            problems = true;
         }
      }
       System.out.println("leaving start");
  }


   // ******************************************************
   // put the data into a form that visad can access
   // ******************************************************
   private boolean add3dData(Vector d1, Vector d2, Vector d3, 
             String xname, String yname, String zname )
  
   {
      int dimension=3;
      float[][] point_vals = null;
      boolean problems = false;
      try {
         point_vals = new float[dimension][];
         for ( int i = 0; i < dimension; i++ )  {
            point_vals[i] = new float[ d1.size() ];
            for ( int j = 0; j < d1.size(); j++ ) {
               if(i==0)  point_vals[i][j] = Float.valueOf( (String) d1.elementAt(j)).floatValue();
               else if(i==1) point_vals[i][j] = Float.valueOf( (String) d2.elementAt(j)).floatValue();
               else if(i==2) point_vals[i][j] = Float.valueOf( (String) d3.elementAt(j)).floatValue();
            }
         }
      } catch ( NumberFormatException nfe)  {
         problems = true;
         System.out.println("apfrm::add3dData.ERROR:  3-d plot.  Problem with conversion to float data.");
      }
  
      try  {
         x1Map.setScalarName( xname );
         x2Map.setScalarName( yname );
         x3Map.setScalarName( zname ); 

         vals_ff.setSamples( point_vals ); 
   
         data_ref.setData( vals_ff );         
      }
      catch ( Exception e )  {
         problems = true;
         System.out.println("apfrm::add3dData.ERROR:  3-d plot.  Add data/set name problem.");
         e.printStackTrace();
        showStatus( new String( e.getMessage() ) );
      }
      return(problems);
  }



   // ******************************************************
   // ******************************************************
   //  Get all data for a dimension
   // ******************************************************
   private Vector getdim( String suffix )
   {
      Vector tv = new Vector();
      String tmp = null;   
      int tcnt = 0;
      if(inApplet) {
         while((tmp = getParameter( suffix+tcnt ) ) != null ){
            tv.add( new String(tmp) );
            tcnt++;
         }
      } else {
         while((tmp=(String)parameters.get(suffix+tcnt))!=null){
            tv.add( new String(tmp) );
            tcnt++;
         }
      }
      return(tv);
   }

 
   // ******************************************************
   // observe when everything gets hit in an applet 
   // ******************************************************
   public void close()
   {
       System.out.println("entering/leaving close");
   }


   // ******************************************************
   // observe when everything gets hit in an applet 
   // ******************************************************
   public void stop()
   {
      System.out.println("entering/leaving stop");
   }


   // ******************************************************
   // observe when everything gets hit in an applet 
   // ******************************************************
   public void paint()
   {
       System.out.println("entering/leaving paint");
   }




   // ******************************************************
   // ******************************************************
   // run as an app
   public static void main(String args[])
   {
      inApplet = false;
      Frame appfrm = new Frame("apfrm as app");
      apfrm app = new apfrm();
      appfrm.add( "Center", app );

      // ******************************************************
      // load parms fake parms, since we're running as an app, not an applet
      // ******************************************************
      parameters.put((String)"d1_0",(String)"12.7263");
      parameters.put((String)"d1_1",(String)"12.8872");
      parameters.put((String)"d1_2",(String)"12.7593");
      parameters.put((String)"d1_3",(String)"12.7729");
      parameters.put((String)"d1_4",(String)"12.8134");
      parameters.put((String)"d1_5",(String)"12.368");
      parameters.put((String)"d1_6",(String)"12.5379");
      parameters.put((String)"d1_7",(String)"12.4563");
      parameters.put((String)"d1_8",(String)"12.5902");
      parameters.put((String)"d1_9",(String)"12.5821");
      parameters.put((String)"d1_10",(String)"12.7492");

      parameters.put((String)"d2_0",(String)"-0.6359");
      parameters.put((String)"d2_1",(String)"-0.6598");
      parameters.put((String)"d2_2",(String)"-0.6501");
      parameters.put((String)"d2_3",(String)"-0.6406");
      parameters.put((String)"d2_4",(String)"-0.6496");
      parameters.put((String)"d2_5",(String)"-0.6394");
      parameters.put((String)"d2_6",(String)"-0.607");
      parameters.put((String)"d2_7",(String)"-0.6047");
      parameters.put((String)"d2_8",(String)"-0.5897");
      parameters.put((String)"d2_9",(String)"-0.576");
      parameters.put((String)"d2_10",(String)"-0.6775");

      parameters.put((String)"d3_0",(String)"2.064");
      parameters.put((String)"d3_1",(String)"2.0866");
      parameters.put((String)"d3_2",(String)"2.0712");
      parameters.put((String)"d3_3",(String)"2.0687");
      parameters.put((String)"d3_4",(String)"2.0728");
      parameters.put((String)"d3_5",(String)"1.9956");
      parameters.put((String)"d3_6",(String)"2.0116");
      parameters.put((String)"d3_7",(String)"2.0036");
      parameters.put((String)"d3_8",(String)"2.0147");
      parameters.put((String)"d3_9",(String)"2.0132");
      parameters.put((String)"d3_10",(String)"2.0845");

  
     appfrm.setSize(500,500);
     app.start();                  // test line 6
     app.start();                  // test line 6
     app.start();                  // test line 6
     app.start();                  // test line 6
     app.start();                  // test line 6
     appfrm.show();    

   }

}


