/*  Subroutine to calculate a Cartesian product B-spline surface
    using open uniform knot vectors (see Eq. 6.1}).

	C code for An Introduction to NURBS
	by David F. Rogers. Copyright (C) 2000 David F. Rogers,
	All rights reserved.
	
	Name: bsplsurf.c
	Language: C
	Subroutines called: knot.c, basis.c
	Book reference: Chapter 6, Ex. 6.1, Alg. p. 303


    b[]         = array containing the polygon net points
                  b[1] = x-component
                  b[2] = y-component
                  b[3] = z-component
                  Note: Bi,j = b[] has dimensions of n*m*3 with j varying fastest
                      The polygon net is n x m
    k           = order in the u direction
    l           = order in the w direction
    mbasis[]    = array containing the nonrational basis functions for one value of w (see \eq{5--84})
    mpts        = the number of polygon vertices in w direction
    nbasis[]    = array containing the nonrational basis functions for one value of u (see \eq{5--84})
    npts        = the number of polygon vertices in u direction
    p1          = number of parametric lines in the u direction
    p2          = number of parametric lines in the w direction
    q[]         = array containing the resulting surface
                  q[1] = x-component
                  q[2] = y-component
                  q[3] = z-component
                       for a fixed value of u the next m elements contain
                       the values for the curve q[u[sub i],w] q has dimensions
                       of p1*p2*3. The display surface is p1 x p2
*/

bsplsurf(b,k,l,npts,mpts,p1,p2,q)

int k,l;
int npts,mpts;
int p1,p2;

float b[],q[];

{

/*   allows for 20 data points with basis function of order 5 */

    int i,j,j1,jbas;
    int icount;
    int uinc,winc;
    int nplusc,mplusc;
    int x[30],y[30];
    int temp;

    float nbasis[30],mbasis[30];
    float pbasis;
    float u,w;
    float stepu,stepw;
    
/*    printf("in bsplsurf.c \n");*/

/*    zero and redimension the arrays */


/*    printf("k,l,npts,mpts,p1,p2 = %d %d %d %d %d %d \n",k,l,npts,mpts,p1,p2);*/


    nplusc = npts + k;
    mplusc = mpts + l;    

    for (i = 1; i <= nplusc; i++){
        x[i] = 0;
    }
    for (i = 1; i <= mplusc; i++){
        y[i] = 0;
    }
    for (i = 1; i <= npts; i++){
        nbasis[i] = 0.;
    }
    for (i = 1; i <= mpts; i++){
        mbasis[i] = 0.;
    }

    temp = 3*(p1*p2);

/*  printf("p1*p2*3 = %d \n",temp);*/

    for (i = 1; i <= 3*p1*p2; i++){
        q[i] = 0.;
    }

/*   generate the open uniform knot vectors */

    knot(npts,k,x);       /*  calculate u knot vector */
    knot(mpts,l,y);       /*  calculate w knot vector */

    icount = 1;

/*    calculate the points on the \bsp surface */

    stepu = (float)x[nplusc]/(float)(p1-1);
    stepw = (float)y[mplusc]/(float)(p2-1);
    u = 0.;
    for (uinc = 1; uinc <= p1; uinc++){
/*      printf("u = %f \n",u); */
        if ((float)x[nplusc] - u < 5e-6){
            u = (float)x[nplusc];
        }
        basis(k,u,npts,x,nbasis);    /* basis function for this value of u */
        w = 0.;
        for (winc = 1; winc <= p2; winc++){
/*          printf("w = %f \n",w);*/
            if ((float)y[mplusc] - w < 5e-6){
                w = (float)y[mplusc];
            }
            basis(l,w,mpts,y,mbasis);    /* basis function for this value of w */
            for (i = 1; i <= npts; i++){
                if (nbasis[i] != 0. ){
                jbas = 3*mpts*(i-1);
                for (j = 1; j <= mpts; j++){
                    if (mbasis[j] != 0.){
                    j1 = jbas +3*(j-1) + 1;
                        pbasis = nbasis[i]*mbasis[j];
                        q[icount] = q[icount]+b[j1]*pbasis;  /* calculate surface point */
                        q[icount+1] = q[icount+1]+b[j1+1]*pbasis;
                        q[icount+2] = q[icount+2]+b[j1+2]*pbasis;
/*                      printf("j1,i,j = %d %d %d \n",j1,i,j); */
                }}
        
            }}
            icount = icount + 3;
            w = w + stepw;
        }
        u = u + stepu;
    }
}

