/***********************************************************************/
/* Open Visualization Data Explorer                                    */
/* (C) Copyright IBM Corp. 1989,1999                                   */
/* ALL RIGHTS RESERVED                                                 */
/* This code licensed under the                                        */
/*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
/***********************************************************************/

#include <dxconfig.h>



#include <string.h>
#include <stdarg.h>
#include "arrayClass.h"


/*
 * General regular grids.  A regular grid in n-space is specified by
 * an n-dimensional origin and a set of n n-dimensional deltas.
 */

Array
DXMakeGridPositionsV(int n, int *counts, float *origin, float *deltas)
{
    Array as[100];
    float zero[100];
    int i;
    
    ASSERT(n<100);

    /* zero */
    for (i=0; i<n; i++)
	zero[i] = 0;

    /* create the terms */
    for (i=0; i<n; i++) {
	as[i] = (Array) DXNewRegularArray(TYPE_FLOAT, n, counts[i],
	    (Pointer)(i==0? origin : zero), (Pointer)&deltas[i*n]);
	if (!as[i])
	    return NULL;
    }

    /* create the product */
    return (Array) DXNewProductArrayV(n, as);
}


Array DXMakeGridPositions(int n, ...)
{
    int counts[100];
    float origin[100], deltas[100];
    int i;
    va_list arg;

    ASSERT(n<100);

    /* collect args */
    va_start(arg,n);
    for (i=0; i<n; i++)
	counts[i] = va_arg(arg, int);
    for (i=0; i<n; i++)
	origin[i] = va_arg(arg, double);
    for (i=0; i<n*n; i++)
	deltas[i] = va_arg(arg, double);
    va_end(arg);

    /* call V version */
    return DXMakeGridPositionsV(n, counts, origin, deltas);
}


Array
DXQueryGridPositions(Array a, int *n, int *counts, float *origin, float *deltas)
{
    Array as[100];
    float orig[100], delt[100];
    int i, j, nn;

    /* is it a product array? */
    if (DXGetArrayClass(a)!=CLASS_PRODUCTARRAY)
	return NULL;

    /* get and return n */
    if (!DXGetProductArrayInfo((ProductArray)a, &nn, as))
	return NULL;
    ASSERT(nn<100);
    if (n)
	*n = nn;

    /* is it floating point? (implies terms are floating point) */
    /* all other type checking is done by e.g. DXGetProductArrayInfo() */
    if (a->type != TYPE_FLOAT)
	return NULL;

    /* is # terms == dimensionality? */
    if (a->rank!=1 || nn!=a->shape[0])
	return NULL;

    /* zero origin */	
    if (origin)
	for (i=0; i<nn; i++)
	    origin[i] = 0;

    /* are the terms regular arrays? */
    for (i=0; i<nn; i++) {
	ASSERT(as[i]->type==TYPE_FLOAT);
	ASSERT(as[i]->shape[0]==nn);
	ASSERT(as[i]->rank==1);
	if (DXGetArrayClass(as[i])!=CLASS_REGULARARRAY)
	    return NULL;
	if (!DXGetRegularArrayInfo((RegularArray)(as[i]),
				 counts? counts+i: NULL,
				 (Pointer)orig,
				 (Pointer)(deltas? deltas+i*nn : NULL)))
	    return NULL;
	if (origin)
	    for (j=0; j<nn; j++)
		origin[j] += orig[j];
    }	

    return a;
}


/*
 * Aligned grid connections
 */
static char *
elementname(int rank, char *str)
{
    switch(rank) {
      case 0:
	strcpy(str, "points");
	break;
      case 1:
	strcpy(str, "lines");
	break;
      case 2:
	strcpy(str, "quads");
	break;
      case 3:
	strcpy(str, "cubes");
	break;
      default:
	sprintf(str, "cubes%dD", rank);
	break;
    }
    return str;
}


Array
DXMakeGridConnectionsV(int n, int *counts)
{
    Array as[100];
    Array a;
    char et[32];
    int i;
    
    ASSERT(n<100);

    /* create the terms */
    for (i=0; i<n; i++) {
	as[i] = (Array) DXNewPathArray(counts[i]);
	if (!as[i])
	    return NULL;
    }

    /* create the product */
    a = (Array) DXNewMeshArrayV(n, as);
    if (!a)
	return NULL;
    
    /* set the element type */
    DXSetStringAttribute((Object)a, "element type", elementname(n, et));
    return a;
}


Array DXMakeGridConnections(int n, ...)
{
    int counts[100];
    int i;
    va_list arg;

    ASSERT(n<100);

    /* collect args */
    va_start(arg,n);
    for (i=0; i<n; i++)
	counts[i] = va_arg(arg, int);
    va_end(arg);

    /* call V version */
    return DXMakeGridConnectionsV(n, counts);
}


Array
DXQueryGridConnections(Array a, int *n, int *counts)
{
    Array as[100];
    int i, nn;

    /* is it a product? */
    if (DXGetArrayClass(a)!=CLASS_MESHARRAY)
	return NULL;

    /* get and return n */
    if (!DXGetMeshArrayInfo((MeshArray)a, &nn, as))
	return NULL;
    ASSERT(nn<100);
    if (n)
	*n = nn;

    /* are the terms regular connections? */
    for (i=0; i<nn; i++) {
	if (DXGetArrayClass(as[i])!=CLASS_PATHARRAY)
	    return NULL;
	if (!DXGetPathArrayInfo((PathArray)as[i], counts? &(counts[i]) : NULL))
	    return NULL;
    }

    return a;
}
