예제 #1
0
static Field
RefineField(Field field, char *args, int l)
{
    int	  limit = ((Args *)args)->limit;
    Field newField;
    Array array;

    if (DXEmptyField(field))
	return DXEndField(DXNewField());
    
    field = (Field)DXCopy((Object)field, COPY_STRUCTURE);
    if (! field)
	return NULL;

    array = (Array)DXGetComponentValue(field, "connections");

    if (DXQueryGridConnections(array, NULL, NULL))
	newField = _dxfRefineReg(field, limit);
    else
	newField = _dxfRefineIrreg(field, limit);

    if (newField == NULL)
	DXDelete((Object)field);
    
    return newField;
}
예제 #2
0
Error
m_MakeXEfficient(Object *in, Object *out)
{
    int i;

    /*
     * Initialize all outputs to NULL
     */
    out[0] = NULL;

    /*
     * Error checks: required inputs are verified.
     */

    /* Parameter "input" is required. */
    if (in[0] == NULL)
    {
        DXSetError(ERROR_MISSING_DATA, "\"input\" must be specified");
        return ERROR;
    }


    /*
     * Since output "output" is structure Field/Group, it initially
     * is a copy of input "input".
     */
    out[0] = DXCopy(in[0], COPY_STRUCTURE);
    if (! out[0])
        goto error;

    /*
     * If in[0] was an array, then no copy is actually made - Copy
     * returns a pointer to the input object.  Since this can't be written to
     * we postpone explicitly copying it until the leaf level, when we'll need
     * to be creating writable arrays anyway.
     */
    if (out[0] == in[0])
        out[0] = NULL;

    /*
     * Call the hierarchical object traversal routine
     */
    if (!traverse(in, out))
        goto error;

    return OK;

error:
    /*
     * On error, any successfully-created outputs are deleted.
     */
    for (i = 0; i < 1; i++)
    {
        if (in[i] != out[i])
            DXDelete(out[i]);
        out[i] = NULL;
    }
    return ERROR;
}
예제 #3
0
파일: mach.c 프로젝트: JasonChunZheng/vtf
Error m_MachNumber (Object * in,Object * out) {
   Object * get;
   int fields,i,ngases;

   /* Verify input */
   if (in[0]==NULL) {
      DXSetError(ERROR_MISSING_DATA,"Input field 0 must be specified");
      goto error;
   }
   if (!DXExtractInteger(in[0],&ngases)) {
      DXSetError(ERROR_DATA_INVALID,"Could not extract INTEGER from field 0");
      goto error;
   }
   fields=INPUT_FIELDS+ngases;
   if (ngases < NGASES_MIN || ngases > NGASES_MAX) {
      DXSetError(ERROR_BAD_PARAMETER,
                 "The value of input field 0 must be %d <= X <= %d",
                 NGASES_MIN,NGASES_MAX);
      goto error;
   }
   for (i=1; i<fields; i++) {
      if (in[i]==NULL) {
         DXSetError(ERROR_MISSING_DATA,"Input field %d must be specified",i);
         goto error;
      }
   }

   /* Since this module is meant to operate on an existing Field / MultiGrid
    * object, initialize the output fields as a copy of the second input
    * field.  */
   for (i=0; i<OUTPUT_FIELDS; i++) {
      if (!(out[i]=DXCopy(in[1],COPY_STRUCTURE)))
         goto error;
      /* If in[1] is an array, DXCopy() will return a pointer to the input
       * object. Since this cannot be written to, an exception will be
       * raised.  */
      if (in[1]==out[i]) {
         DXSetError(ERROR_DATA_INVALID,
                    "Input fields 1-%d should be Field / MultiGrid objects",
                    fields);
         goto error;
      }
   }

   /* Skip the first input field as it is not a Field / MultiGrid object.  */
   get=in+1;
   if (!traverse (w_MachNumber,get,fields-1,out,OUTPUT_FIELDS))
      goto error;

   return OK;
   
error:
   for (i=0; i<OUTPUT_FIELDS; i++) {
      DXDelete(out[i]);
      out[i]=NULL;
   }
   return ERROR;
}
예제 #4
0
Error
m_Options(Object *in, Object *out)
{
    Object a, v;
    char *s;
    int i;

    /* check input object */
    if (!in[0]) {
	DXSetError(ERROR_BAD_PARAMETER, "#10000", "input");
	return ERROR;
    }
   
    /* create output copy */
    out[0] = DXCopy(in[0], COPY_HEADER);
    if (!out[0])
	return ERROR;

    /* arrays don't copy by default - you have to call something special
     *  to get a new copy.
     */
    if (out[0] == in[0] && DXGetObjectClass(in[0]) == CLASS_ARRAY) {
	out[0] = (Object)_dxfReallyCopyArray((Array)in[0]);
	if (!out[0])
	    return ERROR;
    }

    /* set attributes */
    for (i=0; i<PAIRS; i++) {
	a = in[2*i+1];
	v = in[2*i+2];
	if (a) {
	    if (!DXExtractString(a, &s)) {
		DXSetError(ERROR_BAD_PARAMETER, "#10200", "attribute name");
		goto error;
	    }
	    /* NB - ok for v to be NULL - this deletes the attribute */
	    if (!DXSetAttribute(out[0], s, v)) 
		goto error;
	}
    }
    
    return OK;

error:
    if (out[0] != in[0])
	DXDelete(out[0]);
    out[0] = NULL;
    return ERROR;
}
예제 #5
0
파일: SXEnum.c 프로젝트: astrobuff/starlink
Error m_SXEnum( Object *in, Object*out){
/*
*+
*  Name:
*     SXEnum

*  Purpose:
*     enumerating the positions or connections in a field

*  Language:
*     ANSI C

*  Syntax:
*     output = SXEnum( input, name, dep );

*  Classification:
*     Realisation

*  Description:
*     The SXEnum module creates the component specified by "name", and adds
*     it to the "output" field. The values in the new component start at zero
*     and increment by one for each position or connection in the field.
*
*     The new component is in one-to-one correspondance with either the
*     "positions" or "connections" component, dependant on "dep".

*  Parameters:
*     input = field (Given)
*        input field [none]
*     name = string (Given)
*        name of component to store the enumeration ["data"]
*     dep = string (Given)
*        object to be enumerated; "positions" or "connections" ["positions"]
*     output = field (Returned)
*        output field

*  Components:
*     Adds a component with the given "name", deleting any existing
*     component. All other components are copied from the "input" field.

*  Examples:
*     In this example, the 17th frame is extracted from a data set
*     containing scattered data, and a field created holding only those
*     positions with offsets between 10 and 20.
*
*        input = Import("/usr/lpp/dx/samples/data/CO2.general");
*        frame17 = Select(input,17);
*        enum = SXEnum(frame17,"index","positions");
*        marked = Mark(enum,"index");
*        included = Include(marked,10,20,1);
*        subset = Unmark(included,"index");

*  Returned Value:
*     OK, unless an error occurs in which case ERROR is returned and the
*     DX error code is set.

*  Copyright:
*     Copyright (C) 1995 Central Laboratory of the Research Councils.
*     All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful,but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 51 Franklin Street,Fifth Floor, Boston, MA
*     02110-1301, USA

*  Authors:
*     DSB: David Berry (STARLINK)
*     {enter_new_authors_here}

*  History:
*     25-SEP-1995 (DSB):
*        Original version
*     {enter_further_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*-
*/

/*  Local Variables. */

      char   *dep;
      char   *name;
      Object  o=NULL;


/*  Check that the "input" object has been supplied. */

      if( !in[0] ){
         DXSetError( ERROR_BAD_PARAMETER, "missing parameter \"input\".");
         goto error;
      }


/*  Get a value for the "name" object. */

      if( !in[1] ){
         name = "data";

      } else {
         name = DXGetString( (String) in[1] );
         if( !name ){
            DXSetError( ERROR_BAD_PARAMETER, "unable to get string parameter \"name\".");
            goto error;
         }
      }


/*  Get a value for the "dep" object. */

      if( !in[2] ){
         dep = "positions";

      } else {
         dep = DXGetString( (String) in[2] );
         if( !dep ){
            DXSetError( ERROR_BAD_PARAMETER, "unable to get string parameter \"dep\".");
            goto error;
         }

         if( strcmp( dep, "positions" ) && strcmp( dep, "connections" ) ){
            DXSetError( ERROR_BAD_PARAMETER, "bad value (\"%s\") obtained for parameter \"dep\".",dep );
            goto error;
         }

      }


/*  Get a modifiable copy of the "input" object. */

      o = (Object) DXCopy( in[0], COPY_STRUCTURE );
      if( !o ) goto error;


/*  Enumerate it. */

      if( !DoSXEnum( o, name, dep ) ) goto error;


/*  Return the output object. */

      out[0] = o;
      return( OK );

error:
      DXDelete( o );
      return( ERROR );

}
예제 #6
0
static void
Slide2DEndStroke(void *data, DXMouseEvent *event)
{
    Slide2DData sdata = (Slide2DData)data;
    int b = WHICH_BUTTON(event);
    int dx, dy;
    Object member;
    char *name;
    Point corners[8];
    int i;

    if (!sdata)
	return;

    sdata = (Slide2DData)data;
    if (! sdata)
	return;
    
    dx = sdata->buttonPosition[b].x - event->x;
    dy = -(sdata->buttonPosition[b].y - event->y);

    sdata->buttonPosition[b].x = event->x;
    sdata->buttonPosition[b].y = event->y;

    sdata->strokeStart = 1;
    
    /*
     * End stroke.  If its the left button or up'n'downish right button,
     * we operate on a member of the scene group.  If its a left'n'right
     * middle button, we operate on the camera
     */
    if (b == 0 || ((b == 1) && (abs(dy) > abs(dx))))
    {
	Group og = (Group)sdata->obj, ng;

	/*
	 * Can't do anything if we don't have a scene object group or an 
	 * arg telling us what member to operate on
	 */
	if ((sdata->label == NULL && sdata->index == -1) || !sdata->obj)
	    return;

	/*
	 * Create a new group header.
	 */
	ng = (Group)DXCopy(sdata->obj, COPY_ATTRIBUTES);
	if (! ng)
	    return;

	/*
	 * Loop through the scene object group.  For each member NOT matching
	 * the argument, just copy it into the new group.  Otherwise, twiddle
	 * its transform matrix and put it there.
	 */
	i = 0;
	while (NULL != (member = DXGetEnumeratedMember((Group)og, i++, &name)))
	{
	    if ((sdata->label && !strcmp(name, sdata->label)) 
		    || ((i-1) == sdata->index))
	    {
		Object attr;

		/* 
		 * This is the one to manipulate.  It better be a 
		 * 'transformed object' type.
		 */

		attr = DXGetAttribute(member, "object type");
		if (! attr)
		    continue;
		
		if (strcmp(DXGetString((String)attr), "transformed object"))
		    continue;

		if (b == 0)
		{
		    Vector x;
		    Xform oldx = (Xform)member;
		    Matrix oldm, newm;
		    Object xchild;

		    /*
		     * Its the left button.  Determine the world space
		     * vector corresponding to the screen-space stroke, and
		     * concatenate it onto the matrix already associated with
		     * the object, and create a new DX Transform object with
		     * the old transforms child and the concatenated matrices.
		     */

		    x.x = -(dx * sdata->gt);
		    x.y = -(dy * sdata->gt);
		    x.z = 0.0;

		    DXGetXformInfo(oldx, &xchild, &oldm);

		    newm = DXTranslate(x);
		    newm = DXConcatenate(oldm, newm);
		    member = (Object)DXNewXform(xchild, newm);
		    DXSetAttribute(member, "object type", attr);
		}
		else if (DXBoundingBox(member, corners))
		{
		    Angle r;
		    Xform oldx = (Xform)member;
		    Matrix oldm, newm;
		    Object xchild;
		    Vector center;

		    /*
		     * Then its an up'n'down middle button stroke. Create
		     * a matrix that transforms the object back to the origin,
		     * rotates it, and then back to where it was.
		     */


		    DXGetXformInfo(oldx, &xchild, &oldm);

		    /*
		     * Move the object so its center is at the origin
		     */
		    center.x = -(corners[0].x + corners[7].x) / 2.0;
		    center.y = -(corners[0].y + corners[7].y) / 2.0;
		    center.z = -(corners[0].z + corners[7].z) / 2.0;
		    newm = DXTranslate(center);
		    oldm = DXConcatenate(oldm, newm);


		    /*
		     * Rotate
		     */
		    r = dy * sdata->gr * (2*3.14159);
		    newm = DXRotateZ(r);
		    oldm = DXConcatenate(oldm, newm);

		    /*
		     * Move the object back to its original location
		     */
		    center.x = -center.x;
		    center.y = -center.y;
		    center.z = -center.z;
		    newm = DXTranslate(center);
		    oldm = DXConcatenate(oldm, newm);

		    member = (Object)DXNewXform(xchild, oldm);
		    DXSetAttribute(member, "object type", attr);
		}
	    }
	    DXSetMember(ng, name, member);
	}

	DXDelete(sdata->obj);
	sdata->obj = DXReference((Object)ng);


    }
    else if ((b == 1) && (abs(dx) > abs(dy)))
    {
	/*
	 * Its a left'n'right middle button.  Alter the camera's width
	 * parameter based on a scaled stroke dx.
	 */
	sdata->width += (sdata->width * dx)/sdata->w;
    }

    return;

}
예제 #7
0
Error m_SXConstruct( Object *in, Object*out){
/*
*+
*  Name:
*     SXConstruct

*  Purpose:
*     constructs a regular field with regular connections

*  Language:
*     ANSI C

*  Syntax:
*     output = SXConstruct( object, lower, upper, deltas, counts );

*  Classification:
*     Realization

*  Description:
*     The SXConstruct module constructs a field with regular positions
*     and connections covering a volume with specified bounds. It is
*     similar to the standard Construct module, but is somewhat easier to
*     use if a simple grid is required.

*     If "object" is given, its bounds define the extent of the output
*     field. Otherwise, the vectors given for "upper" and "lower" define
*     the extent of the output field.

*     If "deltas" is supplied, it defines the distances between adjacent
*     positions on each axis. It should be a vector with the same number
*     of dimensions as "upper" and "lower", or a single value (in which
*     case the supplied value is used for all axes). The upper and lower
*     bounds are expanded if necessary until they span an integer number
*     of deltas.
*
*     If "deltas" is not supplied, then "counts" must be supplied and
*     should be an integer vector giving the number of positions on each
*     axis, or a single integer (in which case the same value is used for
*     all axes).

*  Parameters:
*     object = field (given)
*        object to define extent of new field [none]
*     lower = vector (Given)
*        explicit lower bounds of new field [none]
*     upper = vector (Given)
*        explicit upper bounds of new field [none]
*     deltas = scalar or vector (Given)
*        increment for each axis
*     counts = integer or vector (Given)
*        number of positions along each axis
*     output = field (Returned)
*        output field

*  Components:
*     The output has "positions", "connections" and "box" components, but
*     no "data" component.

*  Examples:
*     This example imports a scattered data set from "C02.general",
*     extracts a single frame, uses SXConstruct to make a grid covering the
*     bounds of the frame, with increments of 10.0 along each axis, and
*     then uses SXBIN to find the mean data value in each of the square
*     connections of this new grid. the resulting field is displayed.
*
*     data = Import("/usr/lpp/dx/samples/data/CO2.general");
*     frame17 = Select(data,17);
*     newgrid = SXConstruct(frame17,deltas=10);
*     binned = SXBin(frame17,newgrid);
*     coloured = AutoColor(binned);
*     camera = AutoCamera(coloured);
*     Display(coloured,camera);

*  See Also:
*     Construct, Grid

*  Returned Value:
*     OK, unless an error occurs in which case ERROR is returned and the
*     DX error code is set.

*  Copyright:
*     Copyright (C) 1995 Central Laboratory of the Research Councils.
*     All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful,but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 51 Franklin Street,Fifth Floor, Boston, MA
*     02110-1301, USA

*  Authors:
*     DSB: David Berry (STARLINK)
*     {enter_new_authors_here}

*  History:
*     18-OCT-1995 (DSB):
*        Original version
*     {enter_further_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*-
*/


/*  Local Variables. */


      int      cnt[3];       /* Counts */
      int     *counts;       /* Pointers to counts */
      float    del[3];       /* Deltas */
      float    del3d[9];     /* 3-D Deltas */
      float   *deltas;       /* Pointers to deltas */
      float   *lower;        /* Pointer to lower bounds */
      float   *upper;        /* Pointer to upper bounds */
      float    lbnd[3];      /* lower bounds */
      float    ubnd[3];      /* upper bounds */
      int      ndim;         /* No. of components for each vector */
      int      ndim2;        /* No. of dimensions in second object */
      Object   o=NULL;       /* Output object */
      float    bnd;          /* Current bound value */
      Point    box[8];       /* Bounding box */
      Category cat;          /* Array category */
      Array    array;        /* An array */
      float   *box_ptr;      /* Pointer to box array */
      int      i;            /* Loop count */
      int      j;            /* Loop count */
      int      ncorn;        /* No. of corners in the bounding box */
      int      rank;         /* Array rank */
      float    tmp;          /* Swapping space */
      Type     type;         /* Array numeric type */


/*  If OBJECT was supplied, check it is a field. */

      if( in[0] ){

         if( DXGetObjectClass(in[0]) != CLASS_FIELD ){
            DXSetError( ERROR_BAD_TYPE, "input object is not a field" );
            goto error;
         }


/*  Take a copy of it. */

         o = DXCopy( in[0], COPY_STRUCTURE );


/*  Get the bounding box component from the object */

         array = (Array) DXGetComponentValue( (Field) o, "box" );


/*  If no bounding box was found, create one. */

         if( !array ){
            if( !DXBoundingBox( o, box ) ){
               DXSetError( ERROR_UNEXPECTED, "cannot obtain a bounding box." );
               goto error;
            }
            array = (Array) DXGetComponentValue( (Field) o, "box" );
         }


/*  Get a pointer to the bounding box array and the number of items in
 *  the array, etc. */

         box_ptr = (float *) DXGetArrayData( array );
         DXGetArrayInfo( array, &ncorn, &type, &cat, &rank, &ndim );

         if( type != TYPE_FLOAT ){
            DXSetError( ERROR_BAD_TYPE, "input object positions are not TYPE_FLOAT");
            goto error;
         }

         if( cat != CATEGORY_REAL ){
            DXSetError( ERROR_BAD_TYPE, "input object positions are not REAL");
            goto error;
         }

         if( rank > 1 ){
            DXSetError( ERROR_BAD_TYPE, "input object positions have rank larger than 1");
            goto error;
         }

         if( rank == 0 ) ndim = 1;

         if( ndim > 3 ){
            DXSetError( ERROR_BAD_TYPE, "input object positions have more than 3 dimensions");
            goto error;
         }


/*  Store the bounds for each dimension. */

         for( j=0; j<ndim; j++){
            lbnd[j] = FLT_MAX;
            ubnd[j] = FLT_MIN;
         }

         for( i=0; i<ncorn; i++ ){
            for( j=0; j<ndim; j++ ){
               bnd = *(box_ptr++);
               if( bnd < lbnd[j] ) lbnd[j]=bnd;
               if( bnd > ubnd[j] ) ubnd[j]=bnd;
            }
         }


/*  Delete the copy of the input object */

         DXDelete( o );
         o = NULL;
         array = NULL;


/*  If OBJECT was not supplied, get the bounds from LOWER and UPPER. */

      } else {

         if( !in[1] ) {
            DXSetError( ERROR_MISSING_DATA, "No lower bounds supplied");
            goto error;

         } else {
            lower = SXGet1r( "lower", in[1], &ndim );
            if( !lower ) goto error;

            if( ndim > 3 ){
               DXSetError( ERROR_BAD_TYPE, "lower bounds have more than 3 dimensions");
               goto error;
            }

         }

         if( !in[2] ) {
            DXSetError( ERROR_MISSING_DATA, "No upper bounds supplied");
            goto error;

         } else {
            upper = SXGet1r( "upper", in[2], &ndim2 );
            if( !upper ) goto error;

            if( ndim2 != ndim ){
               DXSetError( ERROR_BAD_TYPE, "number of upper and lower bounds does not match");
               goto error;
            }

         }

         for( j=0; j<ndim; j++){
            lbnd[j] = lower[j];
            ubnd[j] = upper[j];
         }

      }


/*  Ensure bounds are OK. */

      for( j=0; j<ndim; j++ ){
         if( ubnd[j] < lbnd[j] ) {
            tmp = ubnd[j];
            ubnd[j] = lbnd[j];
            lbnd[j] = tmp;
         }
      }


/*  If DELTAS was supplied, get its values and check dimensionality. */

      if( in[3] ){
         deltas = SXGet1r( "deltas", in[3], &ndim2 );

         if( ndim2 == 1 ){
            for( j=0; j<ndim; j++){
               del[j] = *deltas;
            }

         } else {
            if( ndim2 != ndim ){
               DXSetError( ERROR_BAD_TYPE, "incorrect number of deltas given");
               goto error;
            } else {
               for( j=0; j<ndim; j++){
                  del[j] = deltas[j];
               }
            }
         }


/*  Find the corresponding counts and adjust lower bounds */

         for( j=0; j<ndim; j++ ){
            if( del[j] > 0.0 ){
               cnt[j] = 1 + (int) ( 0.9999 + (ubnd[j]-lbnd[j])/del[j] );
               lbnd[j] = 0.5*( ubnd[j] + lbnd[j] - ( cnt[j] - 1 )*del[j] );
            } else {
               DXSetError( ERROR_BAD_TYPE, "negative or zero delta given");
               goto error;
            }
         }


/*  If COUNTS was supplied, get its values and check dimensionality. */

      } else if( in[4] ){
         counts = SXGet1i( "counts", in[4], &ndim2 );

         if( ndim2 == 1 ){
            for( j=0; j<ndim; j++){
               cnt[j] = *counts;
            }

         } else {
            if( ndim2 != ndim ){
               DXSetError( ERROR_BAD_TYPE, "incorrect number of counts given");
               goto error;
            } else {
               for( j=0; j<ndim; j++){
                  cnt[j] = counts[j];
               }
            }
         }


/*  Find corresponding DELTAS */

         for( j=0; j<ndim; j++ ){
            if( cnt[j] > 1 ) {
               del[j] = ( ubnd[j] - lbnd[j] )/( (float) cnt[j] - 1 );

            } else {
               cnt[j] = 1;
               del[j] = 1.0;
               tmp = 0.5*( ubnd[j]+ lbnd[j] );
               ubnd[j] = tmp;
               lbnd[j] = tmp;
            }

         }


/*  report an error if neither COUNTS nor DELTAS was supplied. */

      } else {
         DXSetError( ERROR_MISSING_DATA, "no deltas or counts given");
         goto error;
      }


/*  Construct the n-d delta vectors, form the increments on each axis. */

      for( j=0; j<9; j++ ) del3d[j] = 0.0;
      for( j=0; j<ndim; j++ ) del3d[ j*(ndim+1) ] = del[j];


/*  Create the output field. */

      o = (Object) DXNewField();
      if( !o ) goto error;


/* Create the positions array and put it in the field. */

      array = DXMakeGridPositionsV( ndim, cnt, lbnd, del3d );
      if( !array ) goto error;
      if( !DXSetComponentValue( (Field) o, "positions", (Object) array ) ) goto error;
      array = NULL;


/* Create the connections array and put it in the field. */

      array = DXMakeGridConnectionsV( ndim, cnt );
      if( !array ) goto error;
      if( !DXSetComponentValue( (Field) o, "connections", (Object) array ) ) goto error;
      array = NULL;


/*  Finish the field */

      if( !DXEndField( (Field) o ) ) goto error;


/*  Return the output field. */

      out[0] = o;
      return( OK );

error:
      DXDelete( o );
      return( ERROR );

}
예제 #8
0
int
m_Convert(Object *in, Object *out)
{
  Array    incolorvec, outcolorvec;
  int      ismap, isfield, count, i, ii, numitems, addpoints;
  char     *colorstrin, *colorstrout; 
  char     newstrin[30], newstrout[30];
  Object   gout;
  float    *dpin=NULL, *dpout=NULL;

  gout=NULL;
  incolorvec = NULL;
  outcolorvec = NULL;
   
  if (!in[0]) {
    DXSetError(ERROR_MISSING_DATA,"#10000","data");
    return ERROR;
  }
  out[0] = in[0];
  ismap = 0; 
  isfield = 0; 
  

  /*
   *  if it's an array (vector or list of vectors)
   */

  if (DXGetObjectClass(in[0]) == CLASS_ARRAY) {
    if (!(DXQueryParameter((Object)in[0], TYPE_FLOAT, 3, &numitems))) {
      /* must be a list of 3-vectors or a field */
      DXSetError(ERROR_BAD_PARAMETER,"#10550","data");
      out[0] = NULL;
      return ERROR;
    }
    if (!(incolorvec = DXNewArray(TYPE_FLOAT,CATEGORY_REAL, 1, 3))){
      out[0] = NULL;
      return ERROR;
    }
    if (!(DXAddArrayData(incolorvec,0,numitems,NULL)))
      goto error;
    if (!(dpin = (float *)DXGetArrayData(incolorvec)))
      goto error;
    if (!(DXExtractParameter((Object)in[0], TYPE_FLOAT, 3, numitems,
			   (Pointer)dpin))) {
      /* must be a list of 3-vectors or a field */
      DXSetError(ERROR_BAD_PARAMETER,"#10550","data");
      goto error;
    }

    /*    
     *  also make the output array
     */
    if (!(outcolorvec = DXNewArray(TYPE_FLOAT,CATEGORY_REAL, 1, 3)))
      goto error;
    if (!(DXAddArrayData(outcolorvec,0,numitems,NULL)))
      goto error;
    if (!(dpout = (float *)DXGetArrayData(outcolorvec)))
      goto error;

  }
  else { 
    if (_dxfIsColorMap(in[0])) 
      ismap = 1;
    else {
      DXResetError();
      isfield = 1;
    }
  }




  
  /* now extract the to and from space names */
  /*  get color name  */
  if (!(in[1]))
    colorstrin = "hsv";
  else 
    if (!DXExtractString((Object)in[1], &colorstrin)) {
      /* invalid input string */
      DXSetError(ERROR_BAD_PARAMETER,"#10200","incolorspace");
      goto error;
    }
  /*  convert color name to all lower case and remove spaces */
  count = 0;
  i = 0;
  while ( i<29 && colorstrin[i] != '\0') {
    if (isalpha(colorstrin[i])){
      if (isupper(colorstrin[i]))
	newstrin[count]= tolower(colorstrin[i]);
      else
	newstrin[count]= colorstrin[i];
      count++;
    }
    i++;
  }

  newstrin[count]='\0';
  if (strcmp(newstrin,"rgb")&&strcmp(newstrin,"hsv")) {
    DXSetError(ERROR_BAD_PARAMETER,"#10210", newstrin, "incolorspace");
    goto error;
  }
  
  
  if (!in[2]) 
    colorstrout = "rgb";
  else if (!DXExtractString((Object)in[2], &colorstrout)) {
      /* invalid outcolorspace string */
    DXSetError(ERROR_BAD_PARAMETER,"#10200","outcolorspace");
    goto error;
  }
  
  /*  convert color name to all lower case and remove spaces */
  count = 0;
  i = 0;
  while ( i<29 && colorstrout[i] != '\0') {
    if (isalpha(colorstrout[i])){
      if (isupper(colorstrout[i]))
	newstrout[count]= tolower(colorstrout[i]);
      else
	newstrout[count]= colorstrout[i];
      count++;
    }
    i++;
  }
  newstrout[count]='\0';
  if (strcmp(newstrout,"rgb")&&strcmp(newstrout,"hsv")){
    /* invalid outcolorspace string */
    DXSetError(ERROR_BAD_PARAMETER,"#10210", newstrout, "outcolorspace");
    goto error;
  }
  
  if (!strcmp(newstrin,newstrout)) {
    DXWarning("incolorspace and outcolorspace are the same");
    return OK;
  }

  if (!in[3]) {
     /* default behavior is to treat maps like maps (adding points)
        and to treat fields like fields (not adding points) */
  }
  else {
     if (!DXExtractInteger(in[3], &addpoints)) {
        DXSetError(ERROR_BAD_PARAMETER, "#10070",
                   "addpoints");
        goto error;
     }
     if ((addpoints < 0) || (addpoints > 1)) {
        DXSetError(ERROR_BAD_PARAMETER, "#10070",
                   "addpoints");
        goto error;
     }
     if (isfield && addpoints) {
        DXSetError(ERROR_BAD_PARAMETER, "#10370",
         "for a field with greater than 1D positions, addpoints", "0");
        goto error;
     }
     if (ismap && (!addpoints)) {
        /* treat the map like a field */
        ismap = 0;
        isfield = 1;
     }
  }

  /* we have been given a vector value or list of values, not a map */
  if ((!ismap)&&(!isfield)) {
    if (!strcmp(newstrin,"hsv")) {
      for (ii = 0; ii < numitems*3; ii = ii+3) {
	if (!(_dxfHSVtoRGB(dpin[ii], dpin[ii+1], dpin[ii+2],
		       &dpout[ii], &dpout[ii+1], &dpout[ii+2]))) 
	  goto error;
      }
    }
    else {
      for (ii = 0; ii < numitems*3; ii = ii+3) {
	if (!(_dxfRGBtoHSV(dpin[ii], dpin[ii+1], dpin[ii+2],
		       &dpout[ii], &dpout[ii+1], &dpout[ii+2]))) 
	  goto error;
      }
    }
    out[0] = (Object)outcolorvec;
    DXDelete((Object)incolorvec);
    return OK;
  }

  /* we have a map or field */
  else {
    if (ismap) {
      if (!(ConvertObject(in[0], newstrin, &gout)))
        goto error;
    }
    else {
      gout = DXCopy(in[0], COPY_STRUCTURE);
      if (!gout) goto error;
      if (!(ConvertFieldObject(gout, newstrin)))
         goto error;
    }
    out[0] = gout;
    return OK;
  }

  error:
    out[0] = NULL;
    DXDelete((Object)gout);
    DXDelete((Object)incolorvec);
    DXDelete((Object)outcolorvec);
    return ERROR;
}
예제 #9
0
Error m_SXRegrid( Object *in, Object *out ){
/*
*+
*  Name:
*     SXRegrid

*  Purpose:
*     samples a field at positions defined by a another field

*  Language:
*     ANSI C

*  Syntax:
*     output = SXRegrid( input, grid, nearest, radius, scale, exponent,
*                        coexp, type );

*  Classification:
*     Realisation

*  Description:
*     The SXRegrid module samples the "data" component of the "input"
*     field at the positions held in the "positions" component of the
*     "grid" field. It is similar to the standard "Regrid" module, but
*     provides more versatility in assigning weights to each input position,
*     the option of returning the sums of the weights or the weighted sum
*     instead of the weighted mean, and seems to be much faster. Both
*     supplied fields can hold scattered or regularly gridded points, and
*     need not contain "connections" components. The "data" component in the
*     "input" field must depend on "positions".
*
*     For each grid position, a set of near-by positions in the input
*     field are found (using "nearest" and "radius"). Each of these input
*     positions is given a weight dependant on its distance from the current
*     grid position. The output data value (defined at the grid position) can
*     be the weighted mean or weighted sum of these input data values, or
*     the sum of the weights (selected by "type").
*
*     The weight for each input position is of the form:
*
*        (d/d0)**exponent
*
*     where "d" is the distance from the current grid position to the
*     current input position. If a single value is given for "scale" then
*     that value is used for the d0 constant for all the near-by input
*     positions. If more than 1 value is given for "scale" then the first
*     value is used for the closest input position, the second value for the
*     next closest, etc. The last supplied value is used for any remaining
*     input positions. A value of zero for "scale" causes the
*     corresponding input position to be given zero weight.
*
*     If "coexp" is not zero, then the above weights are modified to
*     become:
*
*        exp( coexp*( (d/d0)**exponent ) )
*
*     If "nearest" is given an integer value, it specifies N, the maximum
*     number of near-by input positions to use for each output position.
*     The N input positions which are closest to the output position are
*     used. If the string "infinity" is given, then all input positions
*     closer than the distance given by "radius" are used. Using "radius",
*     you may specify a maximum radius (from the output position) within
*     which to find the near-by input positions. If the string "infinity"
*     is given for "radius" then no limit is placed on the radius.

*  Parameters:
*     input = field (Given)
*        field or group with positions to regrid [none]
*     grid = field (Given)
*        grid to use as template [none]
*     nearest = integer or string (Given)
*        number of nearest neighbours to use, or "infinity" [1]
*     radius = scalar or string (Given)
*        radius from grid point to consider, or "infinity" ["infinity"]
*     scale = scalar or vector or scalar list (Given)
*        scale lengths for weights [1.0]
*     exponent = scalar (Given)
*        weighting exponent [1.0]
*     coexp = scalar (Given)
*        exponential co-efficient for weights [0.0]
*     type = integer (Given)
*        type of output values required: 0 - weighted mean, 1 - weighted sum,
*                                        2 - sum of weights [0]
*     output = field (Returned)
*        regridded field

*  Components:
*     All components except the "data" component are copied from the "grid"
*     field. The output "data" component added by this module depends on
*     "positions". An "invalid positions" component is added if any output
*     data values could not be calculated (e.g. if there are no near-by input
*     data values to define the weighted mean, or if the weights are too
*     large to be represented, or if the input grid position was invalid).

*  Examples:
*     This example maps the scattered data described in "CO2.general" onto a
*     regular grid, and displays it. SXRegrid is used to find the data value
*     at the nearest input position to each grid position.
*
*        input = Import("/usr/lpp/dx/samples/data/CO2.general")$
*        frame17 = Select(input,17);
*        camera = AutoCamera(frame17);
*        grid = Construct([-100,-170],deltas=[10,10],counts=[19,34]);
*        regrid = SXRegrid(frame17,grid);
*        coloured = AutoColor(regrid);
*        Display(coloured,camera);
*
*     The next example produces a grid containing an estimate of the density
*     of the scattered points (i.e. the number of points per unit area). The
*     positions of the original scattered points are shown as dim grey
*     circles. SXRegrid finds the 5 closest input positions at each grid
*     position. Zero weight is given to the closest 3 positions. The fourth
*     position has a weight which is half the density of the points within the
*     circle passing through the fourth point (i.e. if the fourth point
*     is at a distance D from the current grid position, there are 3 points
*     within a circle of radius D, so the density within that circle is
*     3/(PI*(D**2)) ). The fifth position has a weight which is half the
*     density of the points within the circle passing through the fifth
*     point. The output data value is the sum of the weights (because
*     "type" is set to 2), which is the mean of the densities within the
*     circles touching the fourth and fifth points.
*
*        input = Import("/usr/lpp/dx/samples/data/CO2.general")$
*        frame17 = Select(input,17);
*        camera = AutoCamera(frame17);
*        glyphs=AutoGlyph(frame17,scale=0.1,ratio=1);
*        glyphs=Color(glyphs,"dim grey");
*        grid = Construct([-100,-170],deltas=[10,10],counts=[19,34]);
*        density=SXRegrid(frame17,grid,nearest=5,scale=[0,0,0,0.691,0.798],
*                         exponent=-2,type=2);
*        coloured = AutoColor(density);
*        collected=Collect(coloured,glyphs);
*        Display(collected,camera);

*  See Also:
*     SXBin, ReGrid, Map, Construct

*  Returned Value:
*     OK, unless an error occurs in which case ERROR is returned and the
*     DX error code is set.

*  Copyright:
*     Copyright (C) 1995 Central Laboratory of the Research Councils.
*     All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful,but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 51 Franklin Street,Fifth Floor, Boston, MA
*     02110-1301, USA

*  Authors:
*     DSB: David Berry (STARLINK)
*     {enter_new_authors_here}

*  History:
*     3-OCT-1995 (DSB):
*        Original version
*     {enter_further_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*-
*/


/*  Local Variables: */

      Category cat;          /* Array category type */
      float    coexp;        /* Exponential co-efficient for weights */
      Type     dtype;        /* Type of current input data array */
      float    ext;          /* Amount by which to extend grid bounds */
      int      fld;          /* Field counter */
      Object   grid;         /* The grid object */
      float   *gridpos;      /* Pointer to grid positions array */
      int      i;            /* Loop count */
      void    *indata[MAXFLD];/* Pointer to input data array */
      float   *inpos;        /* Pointer to input positions array */
      Array    inpos_array;  /* Input positions array */
      Object   input;        /* A copy of the input object */
      int      iopt;         /* Index of selected option */
      int      j;            /* Loop count */
      float    lbnd[3];      /* Lower bounds of grid */
      char    *opt;          /* Textual option for a parameter value */
      float    radius;       /* Max. radius for contributing input positions */
      char     more;         /* Are there more input fields to do? */
      int      nearest;       /* Max. no. of input positions which can contribute to an output position */
      Fpair   *next;         /* The next Fpair structure in the linked list */
      int      ndim;         /* No. of dimensions in grid positions array */
      int      nfld;         /* No. of fields sharing current positions array */
      int      npos;         /* No. of input positions */
      int      npindim;      /* No. of dimensions in input positions array */
      int      nsamp;        /* No. of grid positions */
      int      nscale;       /* No. of scale distances supplied */
      int      outbad[MAXFLD];/* No. of invalid output positions in each field*/
      void    *outdata[MAXFLD];/* Pointers to output data arrays */
      Array    outdata_array;/* Output data array */
      Object   output;       /* The output object */
      int      outtype;      /* Type of output values required */
      float    exponent;     /* Power for weights */
      int      rank;         /* Array rank */
      float    rsc;          /* Reciprocal squared scale distance*/
      float   *rscale;       /* Scale distances for weights */
      int      tag;          /* The tag for the current input positions array */
      Type     type;         /* Array numeric type */
      float    ubnd[3];      /* Upper bounds of grid */
      int      veclen[MAXFLD];/* Dimensionality of each input data array */


/*  Initialise all created objects so that they can safely be deleted if
 *  an error occurs. */

      input = NULL;
      output = NULL;
      grid = NULL;
      outdata_array = NULL;


/*  Check that the "input" object has been supplied. */

      if( !in[0] ) {
         DXSetError( ERROR_BAD_PARAMETER, "missing parameter \"input\"." );
         goto error;
      }


/*  Remove (cull) all invalid positions and connections from the input. It is
 *  necessary to take a copy of the input first, because the input object
 *  itself cannot be modified. */

      input = DXCopy( in[0], COPY_STRUCTURE );
      if( !DXCull( input ) ) goto error;


/*  Check that the "grid" object has been supplied. */

      if( !in[1] ) {
         DXSetError( ERROR_BAD_PARAMETER, "missing parameter \"grid\"." );
         goto error;
      }


/*  Get a pointer to an array holding the grid positions, and get the
 *  size and shape of the grid. Any invalid positions are flagged with the
 *  value FLT_MAX (defined in float.h). */

      gridpos = SXGetGrid( in[1], &nsamp, &ndim, lbnd, ubnd, &grid );
      if( !gridpos ) goto error;


/*  Get the number of input positions allowed to contribute to each
 *  output position. */

      if( !in[2] ){
         nearest = 1;

      } else {

         opt = "infinity";
         if( !SXGet0is( "nearest", in[2], INT_MAX, 1, 1, &opt, &nearest, &iopt ) ) goto error;
         if( iopt == 0 ) nearest = INT_MAX;

      }


/*  Get the maximum radius for input positions which contribute to each
 *  output position. */

      if( !in[3] ){
         radius = FLT_MAX;

      } else {

         opt = "infinity";
         if( !SXGet0rs( "radius", in[3], FLT_MAX, 0.0, 1, &opt, &radius, &iopt ) ) goto error;
         if( iopt == 0 ) radius = FLT_MAX;

      }


/*  If a maximum radius has been given, extend the bounds by one radius
 *  at each end to catch some extra input positions. Otherwise, extend
 *  the bounds by 10%. */

      if( radius < FLT_MAX ){
         for( j=0; j<ndim; j++ ){
            lbnd[j] -= radius;
            ubnd[j] += radius;
         }

      } else {
         for( j=0; j<ndim; j++ ){
            ext = 0.1*( ubnd[j] - lbnd[j] );
            lbnd[j] -= ext;
            ubnd[j] += ext;
         }

      }


/*  Get the scale distances used to create weights for each input
 *  position. Convert them to squared reciprocal scale distances. If
 *  no value is supplied for the "scale" parameter, use a single scale
 *  length of 1.0 */

      if( !in[4] ){
         rsc = 1.0;
         rscale = &rsc;
         nscale = 1;

      } else {
         rscale = SXGet1r( "scale", in[4], &nscale );
         if( !rscale ) goto error;

         for( i=0; i<nscale; i++ ) {
            rsc = rscale[i];
            if( rsc != 0.0 ){
               rscale[i] = 1.0/(rsc*rsc);
            } else {
               rscale[i] = 0.0;
            }
         }

      }


/*  Get the exponent used to create weights for each input position. */

      if( !in[5] ){
         exponent = 1.0;
      } else {
         if( !SXGet0rs( "exponent", in[5], FLT_MAX, -FLT_MAX, 0, &opt, &exponent, &iopt ) ) goto error;
      }


/*  Get the co-efficient to used in the exponential when creating weights for
 *  each input position. */

      if( !in[6] ){
         coexp = 0.0;
      } else {
         if( !SXGet0rs( "coexp", in[6], FLT_MAX, -FLT_MAX, 0, &opt, &coexp, &iopt ) ) goto error;
      }


/*  Get the type of output value required. */

      if( !in[7] ){
         outtype = 0;
      } else {
         if( !SXGet0is( "type", in[7], 2, 0, 0, &opt, &outtype, &iopt ) ) goto error;
      }


/*  Produce a copy of the "input" object to use as the output, replacing all
 *  fields within it with the grid field. Also form a linked list of Fpair
 *  structures describing the fields. */

      output = SXMakeOut( input, (Field) grid, 1, 1, 3, "positions" );
      if( !output ) goto error;


/*  Abort if no fields were found. */

      if( !head ) {
         DXSetError( ERROR_DATA_INVALID, "no fields found in \"input\"." );
         goto error;
      }


/*  Go through the list of fields looking for fields which share the same
 *  positions component. */

      more = 1;
      while( more ){


/*  Find the first field with a non-zero positions tag. */

         next = head;
         while( next && !next->postag ) next = next->next;


/*  If no non-zero positions tags were found, we've finished. */

         if( !next ){
            more = 0;
            break;
         }


/*  Find the input positions array. Get its shape, size and type. Check it is
 *  usable. */

         inpos_array = (Array) next->pos;
         if( !DXGetArrayInfo( inpos_array, &npos, &type, &cat, &rank, &npindim ) ) goto error;

         if( type != TYPE_FLOAT ){
            DXSetError( ERROR_DATA_INVALID, "positions component in \"input\" is not of type FLOAT." );
            goto error;
         }

         if( cat != CATEGORY_REAL ){
            DXSetError( ERROR_DATA_INVALID, "positions component in \"input\" is not of category REAL." );
            goto error;
         }

         if( rank > 1 ){
            DXSetError( ERROR_DATA_INVALID, "rank %d positions component found in \"input\".", rank );
            goto error;
         }

         if( rank == 0 ){   /* Scalar data is equivalent to 1-d vector data */
            rank = 1;
            npindim = 1;
         }

         if( npindim != ndim ){
            DXSetError( ERROR_DATA_INVALID, "dimensionality of \"input\" (%d) does not match \"grid\" (%d).", npindim, ndim );
            goto error;
         }


/*  Get a pointer to the positions values. */

         inpos = (float *) DXGetArrayData( inpos_array );


/*  Find all fields which have the same positions tag and the same data
 *  type. */

         tag = next->postag;
         dtype = next->datatype;

         nfld = 0;
         while( next ){

            if( next->postag == tag && next->datatype == dtype ){


/*  Increment the number of fields found so far which share this
 *  positions component. */

               nfld++;

               if( nfld > MAXFLD ){
                  DXSetError( ERROR_MAX, "\"input\" has too many fields.", MAXFLD );
                  goto error;
               }


/*  Store a pointer to the input data array, and its dimensionality. */

              indata[nfld-1] = (void *) DXGetArrayData( (Array) next->data );
              veclen[nfld-1] = next->datalen;


/*  Make a new array to hold the output data values. The output data will
 *  have the same dimensionality as the input data unless the required output
 *  data is "sum of weights" (i.e. if parameter "type" is 2), in which case the
 *  output data will be scalar. */

              if( outtype == 2 ) veclen[nfld-1] = 1;

              outdata_array = DXNewArrayV( dtype, CATEGORY_REAL, 1, &veclen[nfld-1] );
              if( !outdata_array ) goto error;

              if( !DXAddArrayData( outdata_array, 0, nsamp, NULL ) ) goto error;


/*  Get a pointer to the output data array. */

              outdata[nfld-1] = (void *) DXGetArrayData( outdata_array );
              if( !outdata[nfld-1] ) goto error;


/*  Place the new data component in the output field, and indicate that
 *  it now does not need to be deleted explicitly in the event of an error. */

              if( !DXSetComponentValue( next->outfld, "data", (Object) outdata_array ) ) goto error;
              outdata_array = NULL;


/*  Indicate that the data component of the output field has been
 *  changed. */

              DXChangedComponentValues( next->outfld, "data" );


/*  Indicate that the data values are dependant on positions. */

              if( !DXSetComponentAttribute( next->outfld, "data", "dep",
                                        (Object) DXNewString("positions")) ) goto error;

            }

            next = next->next;

         }


/*  Now sample the input data arrays at the output positions, storing the
 *  resulting sample values in the output data arrays. */

         if( dtype == TYPE_FLOAT ){
            if( ! SXSampleF( nfld, ndim, veclen, npos, inpos, (float **)indata,
                             nsamp, gridpos, (float **) outdata, lbnd, ubnd,
                             nearest, radius, rscale, nscale, exponent, coexp,
                             outtype, outbad ) ) goto error;
         } else {
            if( ! SXSampleD( nfld, ndim, veclen, npos, inpos, (double **)indata,
                             nsamp, gridpos, (double **) outdata, lbnd, ubnd,
                             nearest, radius, rscale, nscale, exponent, coexp,
                             outtype, outbad ) ) goto error;
         }


/*  Loop round all the fields that have just been created. */

         next = head;
         fld = 0;
         while( next ){
            if( next->postag == tag ){


/*  Create invalid positions components in each output field which have any
 *  undefined data values */

               if( outbad[fld] ){
                  if( dtype == TYPE_FLOAT ){
                     if( !SXSetInvPosF( (Object) next->outfld, nsamp, veclen[fld],
                                        (float *) outdata[fld], "positions" ) ) goto error;
                  } else {
                     if( !SXSetInvPosD( (Object) next->outfld, nsamp, veclen[fld],
                                        (double *) outdata[fld], "positions" ) ) goto error;
                  }
               }



/*  Complete the construction of this output field. */

               DXEndField( next->outfld );


/*  Increment the field index, and indicate that this input field has
 *  been done. */

               fld++;
               next->postag = 0;

            }

            next = next->next;

         }


      }

error:

/*  Free the storage used to hold the link list of Fpair structures
 *  describing the fields in the "input" object. */

      while( head ){
         next = head->next;
         DXFree( (Pointer) head );
         head = next;
      }


/*  Delete the copy of the input objects. Return the "output" object with a good status. */

      DXDelete( grid );
      DXDelete( input );


/*  If all is OK, return the "output" object with a good status. */

      if( DXGetError() == ERROR_NONE ){
         out[0] = output;
         return( OK );


/*  If an error has occurred, ensure temporary objects are deleted and return
 *  with a bad status. */

      } else {
         DXDelete( (Object) outdata_array );
         DXDelete( output );
         return( ERROR );
      }

}
예제 #10
0
int
m_Unmark(Object *in, Object *out)
{
    char   *target;
    Object attr;

    if (!_dxfParmCheck(1, in[0], "input", NULL, NULL,
		       1, in[1], "component name", 1,
		          NULL, NULL, 0, 0)) {
	out[0] = NULL;
	return ERROR;
    }

    if (_dxfDXEmptyObject(in[0])) {
	DXWarning("#4000", "input");
	out[0] = in[0];
	return OK;
    }

    if (in[1])
	attr = in[1];
    else 
	attr = DXGetAttribute(in[0], "marked component");
    
    if (!attr || !DXExtractString(attr, &target))
    {
	DXSetError(ERROR_BAD_PARAMETER, "component name");
	return ERROR;
    }

    /* the only way it makes sense to unmark a field which doesn't have
     *  a data component is if the component you are unmarking is 'data'.
     *  (that is interpreted as a request to move the 'saved data' component
     *  back into 'data'.)
     */
    if (!DXExists(in[0], "data") && strcmp(target, "data")) {
        DXSetError(ERROR_MISSING_DATA, "#10252", "input", "data");
	return ERROR;
    }


    out[0] = DXCopy(in[0], COPY_STRUCTURE);
    if (!out[0])
	return ERROR;


    /* special case unmarking the 'data' component - ignore the existing
     *  'data' component and overwrite it with the 'saved data' component.
     *  if no saved data, just leave the data component alone.
     */
    if (!strcmp(target, "data")) {
        if (!DXExists(out[0], "saved data")) {
            DXWarning("#10250", "input", "`saved data'");
            return OK;
        }

        if (!DXRename(out[0], "saved data", "data")) {
	    DXAddMessage("while trying to create output field");
	    goto error;
	}

        return OK;
    }

     
    /* normal case.  put data back to its original name, and then check for
     *  saved data and put it back to data.
     */
    if (!DXRename(out[0], "data", target)) {
	DXAddMessage("while trying to create output field");
	goto error;
    }


    /* if 'saved data' exists, move it back into 'data'
     */
    if (DXExists(out[0], "saved data") &&
	!DXRename(out[0], "saved data", "data")) {
	    DXAddMessage("while trying to create output field");
	    goto error;
	}
    
    if (DXGetAttribute(out[0], "marked component"))
	DXSetAttribute(out[0], "marked component", NULL);

    return OK;

  error:
    DXDelete(out[0]);
    out[0] = NULL;
    return ERROR;
}
예제 #11
0
파일: SXBin.c 프로젝트: astrobuff/starlink
Error m_SXBin( Object *in, Object *out ){
/*
*+
*  Name:
*     SXBin

*  Purpose:
*     bins a field into a grid defined by a another field

*  Language:
*     ANSI C

*  Syntax:
*     output = SXBin( input, grid, type );

*  Classification:
*     Realization

*  Description:
*     The SXBin module bins the "data" component of the "input" field into
*     the bins defined by the "connections" component of the "grid" field.
*     The input field can hold scattered or regularly gridded points, but
*     the "data" component must depend on "positions". The "grid" field must
*     contain "connections" and "positions" components but need not contain
*     a "data" component. The input"data" component must be either TYPE_FLOAT
*     or TYPE_DOUBLE.
*
*     The "data" component in the "output" field contains either the mean
*     or sum of the "input" data values falling within each connection, or
*     the number of data values falling within each connection, as specified
*     by "type".
*
*     When binning a regular grid into another regular grid, beware of the
*     tendancy to produce artificial large scale structure representing the
*     "beat frequency" of the two grids.

*  Parameters:
*     input = field (Given)
*        field or group with positions to bin [none]
*     grid = field (Given)
*        grid to define the bins [none]
*     type = integer (Given)
*        type of output values required: 0 - mean, 1 - sum,
*                                        2 - count [0]
*     output = field (Returned)
*        bined field

*  Components:
*     All components except the "data" component are copied from the "grid"
*     field. The output "data" component added by this module depends on
*     "connections". An "invalid connections" component is added if any output
*     data values could not be calculated (e.g. if the mean is required of an
*     empty bin).

*  Examples:
*     This example bins the scattered data described in "CO2.general" onto a
*     regular grid, and displays it. SXBin is used to find the mean data
*     value in each grid connection.
*
*        input = Import("/usr/lpp/dx/samples/data/CO2.general")$
*        frame17 = Select(input,17);
*        camera = AutoCamera(frame17);
*        grid = Construct([-100,-170],deltas=[10,10],counts=[19,34]);
*        bin = SXBin(frame17,grid);
*        coloured = AutoColor(bin);
*        Display(coloured,camera);
*
*     This example produces a grid containing an estimate of the density of
*     the scattered points (i.e. the number of points per unit area). The
*     positions of the original scattered points are shown as dim grey
*     circles. SXBin finds the number of input positions in each bin,
*     Measure finds the area of each bin, and Compute divides the counts
*     by the areas to get the densities:
*
*        input = Import("/usr/lpp/dx/samples/data/CO2.general")$
*        frame17 = Select(input,17);
*        camera = AutoCamera(frame17);
*        glyphs = AutoGlyph(frame17,scale=0.1,ratio=1);
*        glyphs = Color(glyphs,"dim grey");
*        grid = Construct([-100,-170],deltas=[40,40],counts=[6,10]);
*        counts = SXBin(frame17,grid,type=2);
*        areas = Measure(counts,"element");
*        density = Compute("$0/$1",counts,areas);
*        coloured = AutoColor(density);
*        collected=Collect(coloured,glyphs);
*        Display(collected,camera);

*  See Also:
*     SXRegrid, Map, Construct, Measure

*  Returned Value:
*     OK, unless an error occurs in which case ERROR is returned and the
*     DX error code is set.

*  Copyright:
*     Copyright (C) 1995 Central Laboratory of the Research Councils.
*     All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful,but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 51 Franklin Street,Fifth Floor, Boston, MA
*     02110-1301, USA

*  Authors:
*     DSB: David Berry (STARLINK)
*     {enter_new_authors_here}

*  History:
*     9-OCT-1995 (DSB):
*        Original version
*     {enter_further_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*-
*/


/*  Local Variables: */

      Array    a;            /* Array to hold reduced dimension positions */
      float   *a_ptr;        /* Pointer to reduced dimension positions */
      Category cat;          /* Array category type */
      Type     dtype;        /* Type of current input data array */
      int      fld;          /* Field counter */
      Object   grid;         /* The grid object */
      int      i;            /* Loop count */
      void    *indata[MAXFLD];/* Pointer to input data array */
      float   *inpos;        /* Pointer to input positions array */
      Array    inpos_array;  /* Input positions array */
      Object   input;        /* A copy of the input object */
      Interpolator interp;   /* Interpolator for grid */
      int      j;            /* Loop count */
      Array    map;          /* Map from input position to output bin number */
      int     *map_ptr;      /* Pointer to map */
      char     more;         /* Are there more input fields to do? */
      Fpair   *next;         /* The next Fpair structure in the linked list */
      int      ndim;         /* No. of dimensions in grid positions array */
      int      nfld;         /* No. of fields sharing current positions array */
      int      npos;         /* No. of input positions */
      int      npindim;      /* No. of dimensions in input positions array */
      int      nbin;         /* No. of grid positions */
      int      outbad[MAXFLD];/* No. of invalid output positions in each field*/
      void    *outdata[MAXFLD];/* Pointers to output data arrays */
      Array    outdata_array;/* Output data array */
      Object   output;       /* The output object */
      int      outtype;      /* Type of output values required */
      float   *pa;           /* Pointer to next reduced dimension position */
      float   *pin;          /* Pointer to next full dimension position */
      int      rank;         /* Array rank */
      int      tag;          /* The tag for the current input positions array */
      Type     type;         /* Array numeric type */
      int      veclen[MAXFLD];/* Dimensionality of each input data array */
      int     *work;         /* Pointer to work array */


/*  Initialise all created objects so that they can safely be deleted if
 *  an error occurs. */

      input = NULL;
      output = NULL;
      grid = NULL;
      outdata_array = NULL;
      work = NULL;
      a = NULL;


/*  Check that the "input" object has been supplied. */

      if( !in[0] ) {
         DXSetError( ERROR_BAD_PARAMETER, "missing parameter \"input\"." );
         goto error;
      }


/*  Remove (cull) all invalid positions and connections from the input. It is
 *  necessary to take a copy of the input first, because the input object
 *  itself cannot be modified. */

      input = DXCopy( in[0], COPY_STRUCTURE );
      if( !DXCull( input ) ) goto error;


/*  Check that the "grid" object has been supplied. */

      if( !in[1] ) {
         DXSetError( ERROR_BAD_PARAMETER, "missing parameter \"grid\"." );
         goto error;
      }


/*  Create an interpolator which identifies the grid connection containing any
 *  given position. */

      interp = SXGetIntp( in[1], &nbin, &ndim, &grid );
      if( !interp ) goto error;


/*  Allocate a work array for use by SXBinD or SXBinF. */

      work = (int *) DXAllocate( sizeof( int )*nbin );
      if( !work ) goto error;


/*  Get the type of output value required. */

      if( !in[2] ){
         outtype = 0;
      } else {
         if( !SXGet0is( "type", in[2], 2, 0, 0, NULL, &outtype, NULL ) ) goto error;
      }


/*  Produce a copy of the "input" object to use as the output, replacing all
 *  fields within it with the grid field. Also form a linked list of Fpair
 *  structures describing the fields. */

      output = SXMakeOut( input, (Field) grid, 1, 1, 3, "positions" );
      if( !output ) goto error;


/*  Abort if no fields were found. */

      if( !head ) {
         DXSetError( ERROR_DATA_INVALID, "no fields found in \"input\"." );
         goto error;
      }


/*  Go through the list of fields looking for fields which share the same
 *  positions component. */

      more = 1;
      while( more ){


/*  Find the first field with a non-zero positions tag. */

         next = head;
         while( next && !next->postag ) next = next->next;


/*  If no non-zero positions tags were found, we've finished. */

         if( !next ){
            more = 0;
            break;
         }


/*  Find the input positions array. Get its shape, size and type. Check it is
 *  usable. */

         inpos_array = (Array) next->pos;
         if( !DXGetArrayInfo( inpos_array, &npos, &type, &cat, &rank, &npindim ) ) goto error;

         if( type != TYPE_FLOAT ){
            DXSetError( ERROR_DATA_INVALID, "positions component in \"input\" is not of type FLOAT." );
            goto error;
         }

         if( cat != CATEGORY_REAL ){
            DXSetError( ERROR_DATA_INVALID, "positions component in \"input\" is not of category REAL." );
            goto error;
         }

         if( rank > 1 ){
            DXSetError( ERROR_DATA_INVALID, "rank %d positions component found in \"input\".", rank );
            goto error;
         }

         if( rank == 0 ){   /* Scalar data is equivalent to 1-d vector data */
            rank = 1;
            npindim = 1;
         }

         if( npindim < ndim ){
            DXSetError( ERROR_DATA_INVALID, "dimensionality of \"input\" (%d) is less than \"grid\" (%d).", npindim, ndim );
            goto error;
         }


/*  Get a pointer to the positions values. */

         inpos = (float *) DXGetArrayData( inpos_array );


/*  If the number of dimensions in the input positions is greater than the
 *  number of dimensions in the grid, remove trailing dimensions from the
 *  input positions so that they match the dimensionality of the grid. */

         if( npindim > ndim ){
            a = DXNewArrayV( TYPE_FLOAT, CATEGORY_REAL, 1, &ndim );
            if( !DXAddArrayData( a, 0, npos, NULL ) ) goto error;
            a_ptr = (float *) DXGetArrayData( a );

            for( i=0; i<npos; i++ ){
               pin = inpos + i*npindim;
               pa = a_ptr + i*ndim;
               for(j=0;j<ndim;j++) pa[j] = pin[j];
            }

            inpos_array = a;

         } else {
            a = NULL;
         }

/*  Create an array of the same shape and size as the input positions
 *  array, which holds integer identifiers for the grid connections
 *  containing each input position. These identifiers start at 1 and
 *  go upto nbin. Positions returned holding an identifier of zero do
 *  not fall within the supplied grid. */

         map = (Array) DXMap( (Object) inpos_array, (Object) interp,
                              NULL, NULL );
         map_ptr = (int *) DXGetArrayData( map );


/*  Find all fields which have the same positions tag and the same data
 *  type. */

         tag = next->postag;
         dtype = next->datatype;

         nfld = 0;
         while( next ){

            if( next->postag == tag && next->datatype == dtype ){


/*  Increment the number of fields found so far which share this
 *  positions component. */

               nfld++;

               if( nfld > MAXFLD ){
                  DXSetError( ERROR_MAX, "\"input\" has too many fields.", MAXFLD );
                  goto error;
               }


/*  Store a pointer to the input data array, and its dimensionality. */

              indata[nfld-1] = (void *) DXGetArrayData( (Array) next->data );
              veclen[nfld-1] = next->datalen;


/*  Make a new array to hold the output data values. The output data will
 *  have the same dimensionality as the input data unless the required output
 *  data is "counts (i.e if parameter "type" is 2), in which case the
 *  output data will be scalar. */

              if( outtype == 2 ) veclen[nfld-1] = 1;

              outdata_array = DXNewArrayV( dtype, CATEGORY_REAL, 1, &veclen[nfld-1] );
              if( !outdata_array ) goto error;

              if( !DXAddArrayData( outdata_array, 0, nbin, NULL ) ) goto error;


/*  Get a pointer to the output data array. */

              outdata[nfld-1] = (void *) DXGetArrayData( outdata_array );
              if( !outdata[nfld-1] ) goto error;


/*  Place the new data component in the output field, and indicate that
 *  it now does not need to be deleted explicitly in the event of an error. */

              if( !DXSetComponentValue( next->outfld, "data", (Object) outdata_array ) ) goto error;
              outdata_array = NULL;

            }

            next = next->next;

         }


/*  Now bin the input data arrays into the output connections, storing the
 *  resulting bin values in the output data arrays. */

         if( dtype == TYPE_FLOAT ){
            if( ! SXBinF( nfld, veclen, npos, (float **)indata, nbin,
                          (float **) outdata, map_ptr, work, outtype,
                          outbad ) ) goto error;
         } else {
            if( ! SXBinD( nfld, veclen, npos, (double **)indata, nbin,
                          (double **) outdata, map_ptr, work, outtype,
                          outbad ) ) goto error;
         }


/*  Loop round all the fields that have just been created. */

         next = head;
         fld = 0;
         while( next ){
            if( next->postag == tag ){


/*  Create invalid positions components in each output field which have any
 *  undefined data values */

               if( outbad[fld] ){
                  if( dtype == TYPE_FLOAT ){
                     if( !SXSetInvPosF( (Object) next->outfld, nbin, veclen[fld],
                                        (float *) outdata[fld], "connections" ) ) goto error;
                  } else {
                     if( !SXSetInvPosD( (Object) next->outfld, nbin, veclen[fld],
                                        (double *) outdata[fld], "connections" ) ) goto error;
                  }
               }


/*  Indicate that the data values are dependant on connections. */

               if( !DXSetComponentAttribute( next->outfld, "data", "dep",
                                        (Object) DXNewString("connections")) ) goto error;


/*  Indicate that the data component of the output field has been
 *  changed. */

               DXChangedComponentValues( next->outfld, "data" );


/*  Complete the construction of this output field. */

               DXEndField( next->outfld );


/*  Increment the field index, and indicate that this input field has
 *  been done. */

               fld++;
               next->postag = 0;

            }

            next = next->next;

         }


/*  Delete the array used to store the reduced dimensionality input positions
 *  (if used). */

         if( a ) {
            DXDelete( (Object) a );
            a = NULL;
         }


      }

error:

/*  Free the storage used to hold the link list of Fpair structures
 *  describing the fields in the "input" object. */

      while( head ){
         next = head->next;
         DXFree( (Pointer) head );
         head = next;
      }


/*  Free the work array. */

      if( work ) DXFree( (Pointer) work );


/*  Delete the copy of the input and grid objects, and the array used to
 *  store the reduced dimensionality input positions (if used). */

      DXDelete( grid );
      DXDelete( input );
      if( a ) DXDelete( (Object) a );


/*  If all is OK, return the "output" object with a good status. */

      if( DXGetError() == ERROR_NONE ){
         out[0] = output;
         return( OK );


/*  If an error has occurred, ensure temporary objects are deleted and return
 *  with a bad status. */

      } else {
         DXDelete( (Object) outdata_array );
         DXDelete( output );
         return( ERROR );
      }

}