/***********************************************************************/ /* 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 #include #include #include #include #include "_connectgrids.h" struct arg_radius { Object ino; Field base; float radius; float exponent; Array missing; }; struct arg_nearest { Object ino; Field base; int number; float *radius; float radiusvalue; float exponent; Array missing; }; struct arg_scatter { Object ino; Field base; Array missing; }; typedef struct matrix2D { float A[2][2]; float b[2]; } Matrix2D; typedef struct vector2D { float x, y; } Vector2D; #define PI 3.14156 #define E .0001 /* fuzz */ #define FLOOR(x) ((x)+E>0? (int)((x)+E) : (int)((x)+E)-1) /* fuzzy floor */ #define CEIL(x) ((x)-E>0? (int)((x)-E)+1 : (int)((x)-E)) /* fuzzy ceiling */ #define ABS(x) ((x)<0? -(x) : (x)) #define RND(x) (x<0? x-0.5 : x+0.5) #define POW(x,y) (pow((double)x, (double)y)) #define INSERT_NEAREST_BUFFER(TYPE) \ { \ TYPE *holder=(TYPE *)bufdata; \ float distancesq=0; \ switch(shape_base[0]) { \ case (1): \ distancesq= \ (gridposition1D-inputposition_ptr[l])* \ (gridposition1D-inputposition_ptr[l]); \ break; \ case (2): \ distancesq = (gridposition2D.x- \ inputposition_ptr[2*l])* \ (gridposition2D.x- \ inputposition_ptr[2*l]) + \ (gridposition2D.y- \ inputposition_ptr[2*l+1])* \ (gridposition2D.y- \ inputposition_ptr[2*l+1]); \ break; \ case (3): \ distancesq = (gridposition.x- \ inputposition_ptr[3*l])* \ (gridposition.x- \ inputposition_ptr[3*l]) + \ (gridposition.y- \ inputposition_ptr[3*l+1])* \ (gridposition.y- \ inputposition_ptr[3*l+1]) + \ (gridposition.z- \ inputposition_ptr[3*l+2])* \ (gridposition.z- \ inputposition_ptr[3*l+2]); \ break; \ } \ /* first try to insert into the already present buffer */ \ for (m=0; mm; n--) { \ bufdistance[n] = bufdistance[n-1]; \ memcpy(&holder[shape[0]*n], &holder[shape[0]*(n-1)], \ DXGetItemSize(newcomponent)); \ } \ bufdistance[m]=distancesq; \ memcpy(&holder[shape[0]*m], tmpdata, \ DXGetItemSize(newcomponent)); \ goto filled_buf##TYPE; \ } \ } \ if (numvalid == 0) { \ bufdistance[0] = distancesq; \ memcpy(&holder[0], tmpdata, DXGetItemSize(newcomponent)); \ numvalid++; \ } \ filled_buf##TYPE: \ tmpdata += datastep; \ continue; \ } \ #define ACCUMULATE_DATA(TYPE) \ { \ TYPE *holder; \ float dis; \ float radiussq = radiusvalue*radiusvalue; \ int dc; \ for (ii=0, holder=(TYPE *)bufdata; iiino; newino = DXApplyTransform(ino,NULL); switch (DXGetObjectClass(newino)) { case CLASS_FIELD: base = arg->base; radius = arg->radius; radiusvalue = arg->radiusvalue; missing = arg->missing; numnearest = arg->number; exponent = arg->exponent; if (!ConnectNearest((Group)newino, base, numnearest, radius, radiusvalue, exponent, missing)) goto error; break; case CLASS_GROUP: switch (DXGetGroupClass((Group)newino)) { case CLASS_COMPOSITEFIELD: /* for now, can't handle a composite field */ DXSetError(ERROR_NOT_IMPLEMENTED,"input cannot be a composite field"); goto error; base = arg->base; radius = arg->radius; radiusvalue = arg->radiusvalue; missing = arg->missing; numnearest = arg->number; exponent = arg->exponent; if (!ConnectNearest((Group)newino, base, numnearest, radius, radiusvalue, exponent, missing)) goto error; break; default: DXSetError(ERROR_NOT_IMPLEMENTED,"input must be a single field"); goto error; /* recurse on the members of the group */ for (i=0; (subino=DXGetEnumeratedMember((Group)newino, i, NULL)); i++) { base = arg->base; radius = arg->radius; radiusvalue = arg->radiusvalue; missing = arg->missing; numnearest = arg->number; exponent = arg->exponent; if (!ConnectNearest((Group)subino, base, numnearest, radius, radiusvalue, exponent, missing)) goto error; } break; } break; default: DXSetError(ERROR_DATA_INVALID,"input must be a field or a group"); goto error; } DXDelete((Object)newino); return OK; error: DXDelete((Object)newino); return ERROR; } static Error ConnectRadiusField(Pointer p) { struct arg_radius *arg = (struct arg_radius *)p; Object ino, newino=NULL; Field base; float radius; float exponent; Array missing; /* this one recurses on object ino */ ino = arg->ino; newino = DXApplyTransform(ino,NULL); switch (DXGetObjectClass(newino)) { case CLASS_FIELD: base = arg->base; radius = arg->radius; missing = arg->missing; exponent = arg->exponent; if (!ConnectRadius((Field)newino, base, radius, exponent, missing)) goto error; break; case CLASS_GROUP: DXSetError(ERROR_NOT_IMPLEMENTED,"input cannot be a group"); goto error; break; default: DXSetError(ERROR_DATA_INVALID,"input must be a field"); goto error; } DXDelete((Object)newino); return OK; error: DXDelete((Object)newino); return ERROR; } static Error ConnectNearest(Group ino, Field base, int numnearest, float *radius, float radiusvalue, float exponent, Array missing) { int componentsdone, anyinvalid=0; Matrix matrix; Matrix2D matrix2D; Array positions_base, positions_ino, oldcomponent=NULL, newcomponent; InvalidComponentHandle out_invalidhandle=NULL, in_invalidhandle=NULL; int counts[8], rank_base, shape_base[8], shape_ino[8], rank_ino; int rank, shape[8], i, j, k, l, m, n, numvalid, pos_count=0; int numitemsbase, compcount, numitemsino, numitems; float distanceweight, distance=0, *data=NULL, *dp, *scratch=NULL; ArrayHandle handle=NULL; Type type; Point gridposition = {0, 0, 0}; Vector2D gridposition2D = {0, 0}; float gridposition1D=0, origin=0, delta=0; float *bufdistance=NULL; char *bufdata=NULL; char *name; Category category; float *inputposition_ptr; int data_count, invalid_count=0, ii, datastep, dc, regular; char *old_data_ptr=NULL, *tmpdata=NULL; float *new_data_ptr_f=NULL, *missingval_f=NULL; int *new_data_ptr_i=NULL, *missingval_i=NULL; short *new_data_ptr_s=NULL, *missingval_s=NULL; double *new_data_ptr_d=NULL, *missingval_d=NULL; byte *new_data_ptr_b=NULL, *missingval_b=NULL; ubyte *new_data_ptr_ub=NULL, *missingval_ub=NULL; ushort *new_data_ptr_us=NULL, *missingval_us=NULL; uint *new_data_ptr_ui=NULL, *missingval_ui=NULL; if (DXEmptyField((Field)ino)) return OK; positions_base = (Array)DXGetComponentValue((Field)base, "positions"); if (!positions_base) { DXSetError(ERROR_MISSING_DATA,"base field has no positions"); goto error; } positions_ino = (Array)DXGetComponentValue((Field)ino, "positions"); if (!positions_ino) { DXSetError(ERROR_MISSING_DATA,"input field has no positions"); goto error; } DXGetArrayInfo(positions_base, &numitemsbase, &type, &category, &rank_base, shape_base); regular = 0; if ((DXQueryGridPositions((Array)positions_base,NULL,counts, (float *)&matrix.b,(float *)&matrix.A) )) { regular = 1; if (shape_base[0]==2) { matrix2D.A[0][0] = matrix.A[0][0]; matrix2D.A[1][0] = matrix.A[0][1]; matrix2D.A[0][1] = matrix.A[0][2]; matrix2D.A[1][1] = matrix.A[1][0]; matrix2D.b[0] = matrix.b[0]; matrix2D.b[1] = matrix.b[1]; } else if (shape_base[0]==1) { origin = matrix.b[0]; delta = matrix.A[0][0]; } } else { /* irregular positions */ if (!(handle = DXCreateArrayHandle(positions_base))) goto error; scratch = DXAllocateLocal(DXGetItemSize(positions_base)); if (!scratch) goto error; } if ((type != TYPE_FLOAT)||(category != CATEGORY_REAL)) { DXSetError(ERROR_DATA_INVALID, "positions component must be type float, category real"); goto error; } out_invalidhandle = DXCreateInvalidComponentHandle((Object)base, NULL, "positions"); if (!out_invalidhandle) goto error; DXSetAllValid(out_invalidhandle); in_invalidhandle = DXCreateInvalidComponentHandle((Object)ino, NULL, "positions"); if (!in_invalidhandle) return ERROR; DXGetArrayInfo(positions_ino, &numitemsino, &type, &category, &rank_ino, shape_ino); if ((type != TYPE_FLOAT)||(category != CATEGORY_REAL)) { DXSetError(ERROR_DATA_INVALID, "positions component must be type float, category real"); goto error; } if (rank_base == 0) shape_base[0] = 1; if (rank_base > 1) { DXSetError(ERROR_DATA_INVALID, "rank of base positions cannot be greater than 1"); goto error; } if (rank_ino == 0) shape_ino[0] = 1; if (rank_ino > 1) { DXSetError(ERROR_DATA_INVALID, "rank of input positions cannot be greater than 1"); goto error; } if ((shape_base[0]<0)||(shape_base[0]>3)) { DXSetError(ERROR_DATA_INVALID, "only 1D, 2D, and 3D positions for base supported"); goto error; } if (shape_base[0] != shape_ino[0]) { DXSetError(ERROR_DATA_INVALID, "dimensionality of base (%dD) does not match dimensionality of input (%dD)", shape_base[0], shape_ino[0]); goto error; } if ((shape_ino[0]<0)||(shape_ino[0]>3)) { DXSetError(ERROR_DATA_INVALID, "only 1D, 2D, and 3D positions for input supported"); goto error; } /* first set the extra counts to one to simplify the code for handling 1, 2, and 3 dimensions */ if (regular) { if (shape_base[0]==1) { counts[1]=1; counts[2]=1; } else if (shape_base[0]==2) { counts[2]=1; } } else { counts[0]=numitemsbase; counts[1]=1; counts[2]=1; } /* need to get the components we are going to copy into the new field */ /* copied wholesale from gda */ compcount = 0; componentsdone = 0; while (NULL != (oldcomponent=(Array)DXGetEnumeratedComponentValue((Field)ino, compcount, &name))) { Object attr; data_count=0; invalid_count=0; if (DXGetObjectClass((Object)oldcomponent) != CLASS_ARRAY) goto component_done; if (!strcmp(name,"positions") || !strcmp(name,"connections") || !strcmp(name,"invalid positions")) goto component_done; /* if the component refs anything, leave it */ if (DXGetComponentAttribute((Field)ino,name,"ref")) goto component_done; attr = DXGetComponentAttribute((Field)ino,name,"der"); if (attr) goto component_done; attr = DXGetComponentAttribute((Field)ino,name,"dep"); if (!attr) { /* does it der? if so, throw it away */ attr = DXGetComponentAttribute((Field)ino,name,"der"); if (attr) goto component_done; /* it doesn't ref, doesn't dep and doesn't der. Copy it to the output and quit */ if (!DXSetComponentValue((Field)base,name,(Object)oldcomponent)) goto error; goto component_done; } if (DXGetObjectClass(attr) != CLASS_STRING) { DXSetError(ERROR_DATA_INVALID, "dependency attribute not type string"); goto error; } if (strcmp(DXGetString((String)attr),"positions")){ DXWarning("Component '%s' is not dependent on positions!",name); DXWarning("Regrid will remove '%s' and output the base grid 'data' component if it exists",name); goto component_done; } /* if the component happens to be "invalid positions" ignore it */ if (!strcmp(name,"invalid positions")) goto component_done; componentsdone++; DXGetArrayInfo((Array)oldcomponent,&numitems, &type, &category, &rank, shape); if (rank==0) shape[0]=1; /* check that the missing component, if present, matches the component we're working on */ if (missing) switch (type) { case (TYPE_FLOAT): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), float, type, shape[0], missingval_f); break; case (TYPE_INT): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), int, type, shape[0], missingval_i); break; case (TYPE_DOUBLE): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), double, type, shape[0], missingval_d); break; case (TYPE_SHORT): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), short, type, shape[0], missingval_s); break; case (TYPE_BYTE): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), byte, type, shape[0], missingval_b); break; case (TYPE_UINT): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), uint, type, shape[0], missingval_ui); break; case (TYPE_USHORT): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), ushort, type, shape[0], missingval_us); break; case (TYPE_UBYTE): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), ubyte, type, shape[0], missingval_ub); break; default: DXSetError(ERROR_DATA_INVALID,"unsupported data type"); goto error; } if (rank == 0) shape[0] = 1; if (rank > 1) { DXSetError(ERROR_NOT_IMPLEMENTED,"rank larger than 1 not implemented"); goto error; } if (numitems != numitemsino) { DXSetError(ERROR_BAD_PARAMETER, "number of items in %s component not equal to number of positions", name); goto error; } newcomponent = DXNewArrayV(type, category, rank, shape); if (!DXAddArrayData(newcomponent, 0, numitemsbase, NULL)) goto error; old_data_ptr = (char *)DXGetArrayData(oldcomponent); switch (type) { case (TYPE_FLOAT): new_data_ptr_f = (float *)DXGetArrayData(newcomponent); break; case (TYPE_INT): new_data_ptr_i = (int *)DXGetArrayData(newcomponent); break; case (TYPE_SHORT): new_data_ptr_s = (short *)DXGetArrayData(newcomponent); break; case (TYPE_BYTE): new_data_ptr_b = (byte *)DXGetArrayData(newcomponent); break; case (TYPE_DOUBLE): new_data_ptr_d = (double *)DXGetArrayData(newcomponent); break; case (TYPE_UINT): new_data_ptr_ui = (uint *)DXGetArrayData(newcomponent); break; case (TYPE_UBYTE): new_data_ptr_ub = (ubyte *)DXGetArrayData(newcomponent); break; case (TYPE_USHORT): new_data_ptr_us = (ushort *)DXGetArrayData(newcomponent); break; default: DXSetError(ERROR_DATA_INVALID,"unrecognized data type"); goto error; } /* need to allocate a buffer of length n to hold the nearest neighbors*/ bufdata = (char *)DXAllocateLocal(numnearest*DXGetItemSize(newcomponent)*shape[0]); if (!bufdata) goto error; bufdistance = (float *)DXAllocateLocal(numnearest*sizeof(float)); if (!bufdistance) goto error; data = (float *)DXAllocateLocalZero(sizeof(float)*shape[0]); if (!data) goto error; datastep = DXGetItemSize(newcomponent); /* loop over all the grid points */ inputposition_ptr = (float *)DXGetArrayData(positions_ino); for (i=0; im; n--) { bufdistance[n] = bufdistance[n-1]; } bufdistance[m]=distance; goto filled_buf; } } if (numvalid == 0) { bufdistance[0] = distance; numvalid++; } filled_buf: tmpdata += datastep; continue; } } /* have now looped over all the scattered points */ if (radius && (bufdistance[0]>radiusvalue)) { anyinvalid=1; if (!DXSetElementInvalid(out_invalidhandle, invalid_count)) goto error; } /* increment the invalid positions array pointer */ invalid_count++; } } } /* put the invalid component in the field */ if (anyinvalid) { if (!DXSaveInvalidComponent(base, out_invalidhandle)) goto error; } DXFree((Pointer)bufdistance); } } DXFreeInvalidComponentHandle(out_invalidhandle); DXFreeInvalidComponentHandle(in_invalidhandle); DXFree((Pointer)scratch); DXFreeArrayHandle(handle); if (!DXEndField(base)) goto error; return OK; error: DXFreeInvalidComponentHandle(out_invalidhandle); DXFreeInvalidComponentHandle(in_invalidhandle); DXFree((Pointer)scratch); DXFreeArrayHandle(handle); DXFree((Pointer)bufdistance); DXFree((Pointer)bufdata); DXFree((Pointer)data); DXFree((Pointer)missingval_f); DXFree((Pointer)missingval_s); DXFree((Pointer)missingval_i); DXFree((Pointer)missingval_d); DXFree((Pointer)missingval_b); DXFree((Pointer)missingval_ui); DXFree((Pointer)missingval_ub); DXFree((Pointer)missingval_us); return ERROR; } static Error ConnectRadius(Field ino, Field base, float radius, float exponent, Array missing) { Array positions_base; if (DXEmptyField((Field)ino)) return OK; positions_base = (Array)DXGetComponentValue((Field)base,"positions"); if (!positions_base) { DXSetError(ERROR_MISSING_DATA,"missing positions component in base"); goto error; } if (DXQueryGridPositions((Array)positions_base,NULL,NULL,NULL,NULL)) { if (!ConnectRadiusRegular(ino,base,radius,exponent, missing)) goto error; } else { if (!ConnectRadiusIrregular(ino,base,radius,exponent, missing)) goto error; } if (!DXEndField(base)) goto error; return OK; error: return ERROR; } static Error ConnectRadiusIrregular(Field ino, Field base, float radius, float exponent, Array missing) { int componentsdone, valid; Array positions_base, positions_ino; Array oldcomponent=NULL, newcomponent=NULL; InvalidComponentHandle out_invalidhandle=NULL, in_invalidhandle=NULL; int numitemsbase, numitemsino; int rank_base, rank_ino, shape_base[30], shape_ino[30], i, j; int anyinvalid=1, compcount, rank, shape[30]; int numitems; Type type; ubyte *flagbuf=NULL; float *distancebuf=NULL; Category category; float *pos_ino_ptr, *pos_base_ptr; char *name; /* all points within radius of a given grid position will be averaged * (weighted) to give a data point to that position. If there are are * none within that range, the missing value is used. If missing is * NULL, then an invalid position indication is placed there and cull * will be used at the end */ in_invalidhandle = DXCreateInvalidComponentHandle((Object)ino, NULL, "positions"); if (!in_invalidhandle) goto error; if (!missing) { out_invalidhandle = DXCreateInvalidComponentHandle((Object)base, NULL, "positions"); if (!out_invalidhandle) goto error; anyinvalid = 0; } positions_base = (Array)DXGetComponentValue((Field)base, "positions"); if (!positions_base) { DXSetError(ERROR_MISSING_DATA,"base field has no positions"); goto error; } positions_ino = (Array)DXGetComponentValue((Field)ino, "positions"); if (!positions_ino) { DXSetError(ERROR_MISSING_DATA,"input field has no positions"); goto error; } DXGetArrayInfo(positions_base, &numitemsbase, &type, &category, &rank_base, shape_base); if ((type != TYPE_FLOAT)||(category != CATEGORY_REAL)) { DXSetError(ERROR_DATA_INVALID, "only real, floating point positions for base accepted"); goto error; } if ((rank_base > 1 ) || (shape_base[0] > 3)) { DXSetError(ERROR_DATA_INVALID, "only 1D, 2D, or 3D positions for base accepted"); goto error; } DXGetArrayInfo(positions_ino, &numitemsino, &type, &category, &rank_ino, shape_ino); if ((type != TYPE_FLOAT)||(category != CATEGORY_REAL)) { DXSetError(ERROR_DATA_INVALID, "only real, floating point positions for input accepted"); goto error; } if ((rank_ino > 1 ) || (shape_ino[0] > 3)) { DXSetError(ERROR_DATA_INVALID, "only 1D, 2D, or 3D positions for input accepted"); goto error; } if (shape_base[0] != shape_ino[0]) { DXSetError(ERROR_DATA_INVALID, "base positions are %dD; input positions are %dD", shape_base[0], shape_ino[0]); goto error; } /* regular arrays? XXX */ pos_ino_ptr = (float *)DXGetArrayData(positions_ino); /* make a buffer to hold the distances and flags */ flagbuf = (ubyte *)DXAllocateLocalZero((numitemsbase*numitemsino*sizeof(ubyte))); if (!flagbuf) goto error; distancebuf = (float *)DXAllocateLocalZero((numitemsbase*numitemsino*sizeof(float))); if (!distancebuf) goto error; if (out_invalidhandle) { DXSetAllValid(out_invalidhandle); } /* call irregular method */ pos_base_ptr = (float *)DXGetArrayData(positions_base); if (!(FillBuffersIrreg(numitemsbase, numitemsino, flagbuf, distancebuf, pos_ino_ptr, pos_base_ptr, out_invalidhandle, in_invalidhandle, &anyinvalid, shape_base[0], radius))) goto error; /* need to get the components we are going to copy into the new field */ /* copied wholesale from gda */ compcount = 0; componentsdone=0; while (NULL != (oldcomponent=(Array)DXGetEnumeratedComponentValue((Field)ino, compcount, &name))) { Object attr; if (DXGetObjectClass((Object)oldcomponent) != CLASS_ARRAY) goto component_done; if (!strcmp(name,"positions") || !strcmp(name,"connections") || !strcmp(name,"invalid positions")) goto component_done; /* if the component refs anything, leave it */ if (DXGetComponentAttribute((Field)ino,name,"ref")) goto component_done; attr = DXGetComponentAttribute((Field)ino,name,"der"); if (attr) goto component_done; attr = DXGetComponentAttribute((Field)ino,name,"dep"); if (!attr) { /* does it der? if so, throw it away */ attr = DXGetComponentAttribute((Field)ino,name,"der"); if (attr) goto component_done; /* it doesn't ref, doesn't dep and doesn't der. Copy it to the output and quit */ if (!DXSetComponentValue((Field)base,name,(Object)oldcomponent)) goto error; goto component_done; } if (DXGetObjectClass(attr) != CLASS_STRING) { DXSetError(ERROR_DATA_INVALID, "dependency attribute not type string"); goto error; } if (strcmp(DXGetString((String)attr),"positions")){ DXWarning("Component '%s' is not dependent on positions!",name); DXWarning("Regrid will remove '%s' and output the base grid 'data' component if it exists",name); goto component_done; } /* if the component happens to be "invalid positions" ignore it */ if (!strcmp(name,"invalid positions")) goto component_done; componentsdone++; DXGetArrayInfo((Array)oldcomponent, &numitems, &type, &category, &rank, shape); if (rank == 0) shape[0] = 1; if (rank > 1) { DXSetError(ERROR_NOT_IMPLEMENTED, "rank larger than 1 not implemented"); goto error; } if (numitems != numitemsino) { DXSetError(ERROR_BAD_PARAMETER, "number of items in %s component not equal to number of positions", name); goto error; } newcomponent = DXNewArrayV(type, category, rank, shape); if (!DXAddArrayData(newcomponent, 0, numitemsbase, NULL)) goto error; /* here's where I use my preset buffers to fill the new array */ /* XXX here do something about missing */ if (!FillDataArray(type, oldcomponent, newcomponent, flagbuf, distancebuf, numitemsbase, numitemsino, shape[0], exponent, missing, name)) goto error; if (!DXChangedComponentValues((Field)base,name)) goto error; if (!DXSetComponentValue((Field)base,name,(Object)newcomponent)) goto error; newcomponent = NULL; if (!DXSetComponentAttribute((Field)base, name, "dep", (Object)DXNewString("positions"))) goto error; component_done: compcount++; } if (componentsdone==0) { if (missing) { DXWarning("no position-dependent components found; missing value provided cannot be used"); } else { for (i=0; i 1 ) || (shape_base[0] > 3)) { DXSetError(ERROR_DATA_INVALID, "only 1D, 2D, or 3D positions for base accepted"); goto error; } DXGetArrayInfo(positions_ino, &numitemsino, &type, &category, &rank_ino, shape_ino); if ((type != TYPE_FLOAT)||(category != CATEGORY_REAL)) { DXSetError(ERROR_DATA_INVALID, "only real, floating point positions for input accepted"); goto error; } if ((rank_ino > 1 ) || (shape_ino[0] > 3)) { DXSetError(ERROR_DATA_INVALID, "only 1D, 2D, or 3D positions for input accepted"); goto error; } if (shape_base[0] != shape_ino[0]) { DXSetError(ERROR_DATA_INVALID, "base positions are %dD; input positions are %dD", shape_base[0], shape_ino[0]); goto error; } /* regular arrays? XXX */ pos_ino_ptr = (float *)DXGetArrayData(positions_ino); /* need to get the components we are going to copy into the new field */ /* copied wholesale from gda */ compcount = 0; componentsdone=0; while (NULL != (oldcomponent=(Array)DXGetEnumeratedComponentValue((Field)ino, compcount, &name))) { Object attr; if (DXGetObjectClass((Object)oldcomponent) != CLASS_ARRAY) goto component_done; if (!strcmp(name,"positions") || !strcmp(name,"connections") || !strcmp(name,"invalid positions")) goto component_done; /* if the component refs anything, leave it */ if (DXGetComponentAttribute((Field)ino,name,"ref")) goto component_done; attr = DXGetComponentAttribute((Field)ino,name,"der"); if (attr) goto component_done; attr = DXGetComponentAttribute((Field)ino,name,"dep"); if (!attr) { /* does it der? if so, throw it away */ attr = DXGetComponentAttribute((Field)ino,name,"der"); if (attr) goto component_done; /* it doesn't ref, doesn't dep and doesn't der. Copy it to the output and quit */ if (!DXSetComponentValue((Field)base,name,(Object)oldcomponent)) goto error; goto component_done; } if (DXGetObjectClass(attr) != CLASS_STRING) { DXSetError(ERROR_DATA_INVALID, "dependency attribute not type string"); goto error; } if (strcmp(DXGetString((String)attr),"positions")){ DXWarning("Component '%s' is not dependent on positions!",name); DXWarning("Regrid will remove '%s' and output the base grid 'data' component if it exists",name); goto component_done; } /* if the component happens to be "invalid positions" ignore it */ if (!strcmp(name,"invalid positions")) goto component_done; componentsdone++; DXGetArrayInfo((Array)oldcomponent,&numitems, &type, &category, &rank, shape); if (rank==0) shape[0]=1; /* check that the missing component, if present, matches the component we're working on */ if (missing) switch (type) { case (TYPE_FLOAT): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), float, type, shape[0], missingval_f); break; case (TYPE_INT): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), int, type, shape[0], missingval_i); break; case (TYPE_BYTE): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), byte, type, shape[0], missingval_b); break; case (TYPE_DOUBLE): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), double, type, shape[0], missingval_d); break; case (TYPE_SHORT): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), short, type, shape[0], missingval_s); break; case (TYPE_UBYTE): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), ubyte, type, shape[0], missingval_ub); break; case (TYPE_USHORT): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), ushort, type, shape[0], missingval_us); break; case (TYPE_UINT): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), uint, type, shape[0], missingval_ui); break; default: DXSetError(ERROR_DATA_INVALID,"unsupported data type"); goto error; } if (rank == 0) shape[0] = 1; if (rank > 1) { DXSetError(ERROR_NOT_IMPLEMENTED,"rank larger than 1 not implemented"); goto error; } if (numitems != numitemsino) { DXSetError(ERROR_BAD_PARAMETER, "number of items in %s component not equal to number of positions", name); goto error; } weights_ptr = (float *)DXAllocateLocalZero(numitemsbase*sizeof(float)); /* I need a floating point buffer to hold the weighted sum data */ data_ptr = (float *)DXAllocateLocalZero(numitemsbase*sizeof(float)*shape[0]); if (!weights_ptr) goto error; if (!data_ptr) goto error; /* new component is for the eventual output data */ newcomponent = DXNewArrayV(type, category, rank, shape); if (!DXAddArrayData(newcomponent, 0, numitemsbase, NULL)) goto error; /* allocate the exact hit buf */ exact_hit = (byte *)DXAllocateLocalZero(numitemsbase*sizeof(byte)); switch (type) { case (TYPE_FLOAT): data_in_f = (float *)DXGetArrayData(oldcomponent); data_f = (float *)DXGetArrayData(newcomponent); break; case (TYPE_INT): data_in_i = (int *)DXGetArrayData(oldcomponent); data_i = (int *)DXGetArrayData(newcomponent); break; case (TYPE_DOUBLE): data_in_d = (double *)DXGetArrayData(oldcomponent); data_d = (double *)DXGetArrayData(newcomponent); break; case (TYPE_SHORT): data_in_s = (short *)DXGetArrayData(oldcomponent); data_s = (short *)DXGetArrayData(newcomponent); break; case (TYPE_BYTE): data_in_b = (byte *)DXGetArrayData(oldcomponent); data_b = (byte *)DXGetArrayData(newcomponent); break; case (TYPE_UBYTE): data_in_ub = (ubyte *)DXGetArrayData(oldcomponent); data_ub = (ubyte *)DXGetArrayData(newcomponent); break; case (TYPE_USHORT): data_in_us = (ushort *)DXGetArrayData(oldcomponent); data_us = (ushort *)DXGetArrayData(newcomponent); break; case (TYPE_UINT): data_in_ui = (uint *)DXGetArrayData(oldcomponent); data_ui = (uint *)DXGetArrayData(newcomponent); break; default: DXSetError(ERROR_DATA_INVALID,"unsupported data type"); goto error; } #define INCREMENT_DATA_1D(type, data_in) \ { \ for (i=0; i max) { \ tmpval = min; \ min = max; \ max = tmpval; \ } \ /* minvec and maxvec are the indices corresponding to the \ bounding box around the sample point */ \ for (j=CEIL(min); j <= FLOOR(max) ; j++) \ if (j>=0 && j 0.0)&&(!exact_hit[j])) { \ weights_ptr[j] += 1.0/POW(distance,exponent); \ for (c = 0; c maxvec2D.x) { \ tmpval = minvec2D.x; \ minvec2D.x = maxvec2D.x; \ maxvec2D.x = tmpval; \ } \ if (minvec2D.y > maxvec2D.y) { \ tmpval = minvec2D.y; \ minvec2D.y = maxvec2D.y; \ maxvec2D.y = tmpval; \ } \ /* minvec and maxvec are the indices corresponding to \ the bounding box around the sample point */ \ tmpmat = matrix2D; \ for (j=CEIL(minvec2D.x); j <= FLOOR(maxvec2D.x) ; j++) \ if (j>=0 && j=0 && k 0.0)&&(!exact_hit[cntr])) { \ weights_ptr[cntr] += 1.0/POW(distance,exponent); \ for (c=0; c maxvec.x) { \ tmpval = minvec.x; \ minvec.x = maxvec.x; \ maxvec.x = tmpval; \ } \ if (minvec.y > maxvec.y) { \ tmpval = minvec.y; \ minvec.y = maxvec.y; \ maxvec.y = tmpval; \ } \ if (minvec.z > maxvec.z) { \ tmpval = minvec.z; \ minvec.z = maxvec.z; \ maxvec.z = tmpval; \ } \ /* minvec and maxvec are the indices corresponding to the */ \ /* bounding box around the sample point */ \ tmpmat=matrix; \ rsquared = radius * radius; \ for (j=CEIL(minvec.x); j <= FLOOR(maxvec.x) ; j++) \ if (j>=0 && j=0 && k=0 && l 0.0)&&(!exact_hit[cntr])) { \ weights_ptr[cntr] += 1.0/POW(distance,exponent); \ for (c=0; c=0 && j=0 && j=0 && k=0 && j=0 && k=0 && l 0) { for (k=0; kino; newino = DXApplyTransform(ino,NULL); switch (DXGetObjectClass(newino)) { case CLASS_FIELD: base = arg->base; missing = arg->missing; if (!ConnectScatter((Field)newino, base, missing)) goto error; break; case CLASS_GROUP: DXSetError(ERROR_NOT_IMPLEMENTED,"input cannot be a group"); goto error; break; default: DXSetError(ERROR_DATA_INVALID,"input must be a field"); goto error; } DXDelete((Object)newino); return OK; error: DXDelete((Object)newino); return ERROR; } static Error ConnectScatter(Field ino, Field base, Array missing) { Matrix matrix, inverse; Matrix2D matrix2D, inverse2D; Type type; Category category; Array positions_base, positions_ino, oldcomponent=NULL, newcomponent; InvalidComponentHandle out_invalidhandle=NULL, in_invalidhandle=NULL; int rank, shape[8]; int counts[8], rank_base, shape_base[8], shape_ino[8], rank_ino; int nitemsbase, nitemsino, nitems, compcount, componentsdone; float *ino_positions; char *name; int i,j,k, ijk[3], index, *count=NULL; float xyz[3], sum, eps=.000001; float *old_data_f=NULL, *new_data_ptr_f=NULL, *missingval_f=NULL; int *old_data_i=NULL, *new_data_ptr_i=NULL, *missingval_i=NULL; short *old_data_s=NULL, *new_data_ptr_s=NULL, *missingval_s=NULL; double *old_data_d=NULL, *new_data_ptr_d=NULL, *missingval_d=NULL; byte *old_data_b=NULL, *new_data_ptr_b=NULL, *missingval_b=NULL; ubyte *old_data_ub=NULL, *new_data_ptr_ub=NULL, *missingval_ub=NULL; ushort *old_data_us=NULL, *new_data_ptr_us=NULL, *missingval_us=NULL; uint *old_data_ui=NULL, *new_data_ptr_ui=NULL, *missingval_ui=NULL; if (DXEmptyField((Field)ino)) return OK; positions_base = (Array)DXGetComponentValue((Field)base, "positions"); if (!positions_base) { DXSetError(ERROR_MISSING_DATA,"base field has no positions"); goto error; } positions_ino = (Array)DXGetComponentValue((Field)ino, "positions"); if (!positions_ino) { DXSetError(ERROR_MISSING_DATA,"input field has no positions"); goto error; } /*Grid Position Data*/ DXGetArrayInfo(positions_base, &nitemsbase, &type, &category, &rank_base, shape_base); if ((DXQueryGridPositions((Array)positions_base,NULL,counts, (float *)&matrix.b,(float *)&matrix.A) )) { if (shape_base[0]==2) { matrix2D.A[0][0] = matrix.A[0][0]; matrix2D.A[1][0] = matrix.A[0][1]; matrix2D.A[0][1] = matrix.A[0][2]; matrix2D.A[1][1] = matrix.A[1][0]; matrix2D.b[0] = matrix.b[0]; matrix2D.b[1] = matrix.b[1]; inverse2D=Invert2D(matrix2D); inverse.A[0][0]=inverse2D.A[0][0]; inverse.A[0][1]=inverse2D.A[0][1]; inverse.A[1][0]=inverse2D.A[1][0]; inverse.A[1][1]=inverse2D.A[1][1]; } else if (shape_base[0]==1) { /*origin = matrix.b[0];*/ /*delta = matrix.A[0][0];*/ DXSetError(ERROR_DATA_INVALID, "Only 2D and 3D grids supported"); goto error; } } else { /* irregular positions */ DXSetError(ERROR_DATA_INVALID, "irregular grids not currently supported for radius=0"); goto error; } if ((type != TYPE_FLOAT)||(category != CATEGORY_REAL)) { DXSetError(ERROR_DATA_INVALID, "positions component must be type float, category real"); goto error; } /*Scatter Position Data*/ DXGetArrayInfo(positions_ino, &nitemsino, &type, &category, &rank_ino, shape_ino); if ((type != TYPE_FLOAT)||(category != CATEGORY_REAL)) { DXSetError(ERROR_DATA_INVALID, "positions component must be type float, category real"); goto error; } if (rank_base == 0) shape_base[0] = 1; if (rank_base > 1) { DXSetError(ERROR_DATA_INVALID, "rank of base positions cannot be greater than 1"); goto error; } if (rank_ino == 0) shape_ino[0] = 1; if (rank_ino > 1) { DXSetError(ERROR_DATA_INVALID, "rank of input positions cannot be greater than 1"); goto error; } if ((shape_base[0]<0)||(shape_base[0]>3)) { DXSetError(ERROR_DATA_INVALID, "only 1D, 2D, and 3D positions for base supported"); goto error; } if (shape_base[0] != shape_ino[0]) { DXSetError(ERROR_DATA_INVALID, "dimensionality of base (%dD) does not match dimensionality of input (%dD)", shape_base[0], shape_ino[0]); goto error; } /* first set the extra counts to one to simplify the code for handling 1, 2, and 3 dimensions */ if (shape_base[0]==1) { counts[1]=1; counts[2]=1; } else if (shape_base[0]==2) { counts[2]=1; } /*Will mark as invalid if 'missing' not specified*/ if (!missing){ out_invalidhandle = DXCreateInvalidComponentHandle((Object)base, NULL, "positions"); if (!out_invalidhandle) goto error; DXSetAllInvalid(out_invalidhandle); } in_invalidhandle = DXCreateInvalidComponentHandle((Object)ino, NULL, "positions"); if (!in_invalidhandle) return ERROR; /* need to get the components we are going to copy into the new field */ /* copied portions from ConnectNearest -JAB */ compcount = 0; componentsdone = 0; while (NULL != (oldcomponent=(Array)DXGetEnumeratedComponentValue(ino, compcount, &name))) { Object attr; if (DXGetObjectClass((Object)oldcomponent) != CLASS_ARRAY) goto component_done; if (!strcmp(name,"positions") || !strcmp(name,"connections") || !strcmp(name,"invalid positions")) goto component_done; /* if the component refs anything, leave it */ if (DXGetComponentAttribute((Field)ino,name,"ref")) goto component_done; attr = DXGetComponentAttribute((Field)ino,name,"der"); if (attr) goto component_done; attr = DXGetComponentAttribute((Field)ino,name,"dep"); if (!attr) { /* does it der? if so, throw it away */ attr = DXGetComponentAttribute((Field)ino,name,"der"); if (attr) goto component_done; /* it doesn't ref, doesn't dep and doesn't der. Copy it to the output and quit */ if (!DXSetComponentValue((Field)base,name,(Object)oldcomponent)) goto error; goto component_done; } if (DXGetObjectClass(attr) != CLASS_STRING) { DXSetError(ERROR_DATA_INVALID, "dependency attribute not type string"); goto error; } if (strcmp(DXGetString((String)attr),"positions")){ DXWarning("Component '%s' is not dependent on positions!",name); DXWarning("Regrid will remove '%s' and output the base grid 'data' component if it exists",name); goto component_done; } /* if the component happens to be "invalid positions" ignore it */ if (!strcmp(name,"invalid positions")) goto component_done; componentsdone++; DXGetArrayInfo((Array)oldcomponent,&nitems, &type, &category, &rank, shape); if (rank==0) shape[0]=1; /* check that the missing component, if present, matches the component we're working on. If missing not present, 0 is used as default */ switch (type) { case (TYPE_FLOAT): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), float, type, shape[0], missingval_f); break; case (TYPE_INT): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), int, type, shape[0], missingval_i); break; case (TYPE_DOUBLE): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), double, type, shape[0], missingval_d); break; case (TYPE_SHORT): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), short, type, shape[0], missingval_s); break; case (TYPE_BYTE): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), byte, type, shape[0], missingval_b); break; case (TYPE_UINT): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), uint, type, shape[0], missingval_ui); break; case (TYPE_USHORT): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), ushort, type, shape[0], missingval_us); break; case (TYPE_UBYTE): CHECK_AND_ALLOCATE_MISSING(missing, DXGetItemSize(oldcomponent), ubyte, type, shape[0], missingval_ub); break; default: DXSetError(ERROR_DATA_INVALID,"unsupported data type"); goto error; } if (rank > 1) { DXSetError(ERROR_NOT_IMPLEMENTED,"rank larger than 1 not implemented"); goto error; } if (nitems != nitemsino) { DXSetError(ERROR_BAD_PARAMETER, "number of items in %s component not equal to number of positions", name); goto error; } /*Intialize newcomponent with missing value*/ newcomponent = DXNewArrayV(type, category, rank, shape); if (!DXAddArrayData(newcomponent, 0, nitemsbase, NULL)) goto error; switch (type) { case (TYPE_FLOAT): old_data_f = (float *)DXGetArrayData(oldcomponent); new_data_ptr_f = (float *)DXGetArrayData(newcomponent); for(i=0;i=counts[j]){ index=-1; } } /* Finds data array index number for grid position*/ if(index !=-1){ for(j=0;jj;k--){ ijk[j]=ijk[j]*counts[k]; } index=index+ijk[j]; } } if(index >= 0 && index