/* hwrCoord.java

class to read ink files from a URL and do some basic signal 
processing dedicated to ink.

Copyright, Lambert Schomaker/NICI, March 1996.

Please, refer to the author when using this code by:

Schomaker, L.R.B. (1993).
Using Stroke- or Character-based Self-organiZg Maps
in the Recognition of On-line, Connected Cursive Script.
{\em Pattern Recognition}, 26(3), 443-450.

Schomaker, L.R.B., & Teulings, H.-L. (1990).
A Handwriting Recognition System based on the Properties and Architectures 
of the Human Motor System.
{\em Proceedings of the International Workshop on Frontiers in Handwriting
Recognition (IWFHR)}. (pp. 195-211). Montreal: CENPARMI Concordia.
 */

import java.net.*;
import java.io.*;
import java.util.StringTokenizer;

class hwrCoord {
    /* begin object-attributes */

    double      Ymin_in,Ymax_in;

    int         Inkfilenumber;
    String      Inkfilename;
    int         Npoints;
    int         Npoints_decl = 1000;

    double X[] = new double [Npoints_decl];
    double Y[] = new double [Npoints_decl];
    double Z[] = new double [Npoints_decl];

    hwrVbs  Vbs = new hwrVbs(Npoints_decl/10);

    /* end object-attributes */

    public hwrCoord(int inknumber) {
        if(inknumber >= 0) {
           Inkfilenumber = inknumber;
           Inkfilename = make_url(Inkfilenumber);
           read_coordinates(Inkfilename);
        }
    }

    public int next() {
        ++Inkfilenumber;
        Inkfilename = make_url(Inkfilenumber);
        read_coordinates(Inkfilename);
        return(Inkfilenumber);
    }

    public int previous() {
        --Inkfilenumber;
        if(Inkfilenumber < 1) {
             Inkfilenumber = 1;
        }
        Inkfilename = make_url(Inkfilenumber);
        read_coordinates(Inkfilename);
        return(Inkfilenumber);
    }

/* Actual ink data stuff */

    public void read_coordinates(String urlnam) {
       try {
         URL yahoo = new URL(urlnam);
         DataInputStream dis;
         String inputLine;

         dis = new DataInputStream(yahoo.openStream());
         int kk;

         kk = 0;
         while( (inputLine = dis.readLine()) != null) {
             StringTokenizer st = new StringTokenizer(inputLine);
             if (st.hasMoreTokens()) {
                 X[kk] = Double.valueOf(st.nextToken()).intValue();
                 if (st.hasMoreTokens()) {
                    Y[kk] = Double.valueOf(st.nextToken()).intValue();
                    if (st.hasMoreTokens()) {
                       Z[kk] = Double.valueOf(st.nextToken()).intValue();
                    }
                 }

                 if( (Y[kk] < Ymin_in) || kk == 0) {
                    Ymin_in = Y[kk];
                 }

                 if( (Y[kk] > Ymax_in) || kk == 0) {
                    Ymax_in = Y[kk];
                 }


                 ++kk;
             }
         }

         dis.close();
         Npoints = kk;

      } catch (MalformedURLException me) {
         System.out.println("MalformedURLException: " + me);
      } catch (IOException ioe) {
         System.out.println("IOException: " + ioe);
      }
    }

    public String make_url(int i) {
      String prefix = "http://www.ai.rug.nl/~lambert/recog/hwr-tutor/ink/word";
      String t = new String("000" + i);
      String s = t.substring(t.length()-3);
      String urlnam = prefix + s + ".hwr";
      return(urlnam);
    }


    public void fir_filter(double arrin[], double arrout[], int na, double h[], int nh)
/*
 Time domain filtering by convolution with an impulse response.
 Example smoothing with a rectangular window is done by filling H with
 the value 1/nh at all places. Better impulse responses are designed
 with DESIGN/FCHECK, or via the FFT/IFT method.
 Can also be used for differentiation (see DIFFER).
 
 -Input:
      ARRIN (real array) NA values    input data
      H (real array) NH values        impulse response
      NH (int) #coeff in fir.
  -Output:
      ARROUT (real array) NA values   output data
 Author: L.R.B. Schomaker
 Revised: 26-apr-1989 10:58:57 (comments only) 
*/
{
        double bufin[], bufout[];
        int iodd, idel, np2, iadd, isub, nd, nl;
        double fy, ffy, oldy;
        int i,ii,k,m,j,io,npi,k1;
 
        bufin = new double [nh];
        bufout = new double [nh];
 
        iodd = nh % 2;
        np2 = nh/2;
        iadd = 1 + iodd;
        isub = 1 - iodd;
        nd  = 0;
        ii = 0;

        k = 0;
        for(i=0; i < nh; i++){
                bufin[k++] = arrin[ii++];
        }

        oldy = 0.0;
        for(k=1-iodd; k < (np2+1); k++){
           idel = k - np2;
           fy = 0.0;
           for(m = 0; m < nh; m++){
              k1 = m + idel;
              if(k1 <= 0) k1 = -k1;
              fy = fy + bufin[k1] * h[m];
           }
           ffy = fy;
           if((k == 1) && (iodd == 0)) oldy = fy;
           fy = 0.5 * (iadd * fy + isub * oldy);
           oldy = ffy;
           bufout[k] = fy;
        }

        if(iodd != 1) bufout[0] = bufout[1];

        for(io = 0; io < k; io++){
           arrout[io] = bufout[io];
        }

        npi = 0;

        while(ii < na){
           bufin[npi] = arrin[ii++];
 
           fy = 0.;
           for(m = 0; m < nh; m++){
              nd = ((m+npi+1) % nh);
              fy = fy + bufin[nd] * h[m];
           }
           ffy = fy;
 
           fy = 0.5 * (iadd * fy + isub * oldy);
           oldy = ffy;
 
           arrout[io++] = fy;
           npi++;
           npi = npi % nh;
        }
 
        nl = nd + nh;
        nd = nd + 2;
        nd = nd % nh;
 
        for(k = 0; k < np2; k++){
           fy = 0.;
           for(m = 0; m < nh; m++){
 
              k1 = nd + m;
              if(k1 >= nl) k1 = 2 * nl - k1;
              if(k1 >= nh) k1 = k1 - nh;
              fy = fy + bufin[k1] * h[m];
           }
           nd++;
           ffy = fy;
 
           fy = 0.5 * (iadd * fy + isub * oldy);
           oldy = ffy;
           arrout[io++] = fy;
        }
    }

    public double rmean(double a[], int n)
    {
        int i;
        double sum;
                
        sum = 0.0;
        for(i = 0; i < n; ++i) {
                sum += a[i];
        }
        return(sum/(double) n);
    }

    public void input(double x[], double y[], double z[], int n)
    {
        for(int i = 0; i < n; ++i) { 
           X[i] = x[i];
           Y[i] = y[i];
           Z[i] = z[i];
        }
        Npoints = n;
    }


}

class hwrVbs {
    int Nsegm = 0;
    int t[];
    
    hwrVbs(int n) {
          t = new int[n]; 
    }
}

/* end hwrCoord.java */
