static Error _newQMesh(int nStrips, int nStrippedPts, QMesh *mesh, dxObject *o) { Private priv = NULL; QMesh tmp = NULL; *mesh = NULL; *o = NULL; tmp = (QMesh)DXAllocateZero(sizeof(QMeshS)); if (! tmp) return ERROR; tmp->meshArray = DXNewArray(TYPE_INT, CATEGORY_REAL, 1, 2); if (! tmp->meshArray) goto error; DXReference((dxObject)tmp->meshArray); if ( !DXAllocateArray (tmp->meshArray, nStrips)) goto error; tmp->connectionArray = DXNewArray(TYPE_INT, CATEGORY_REAL, 0); if (! tmp->connectionArray) goto error; DXReference((dxObject)tmp->connectionArray); if ( !DXAllocateArray (tmp->connectionArray, nStrippedPts)) goto error; tmp->meshes = (int *)DXGetArrayData(tmp->meshArray); tmp->connections = (int *)DXGetArrayData(tmp->connectionArray); tmp->nmeshes = nStrips; tmp->nconnections = nStrippedPts; priv = (Private)DXNewPrivate((Pointer)tmp, _deleteQMesh); if (! priv) goto error; *mesh = tmp; *o = (dxObject)priv; return OK; error: if (tmp) { if (tmp->connectionArray) DXDelete((dxObject)tmp->connectionArray); if (tmp->meshArray) DXDelete((dxObject)tmp->meshArray); DXFree((Pointer)tmp); } return ERROR; }
static Error ExtractMatrix(Object o, Matrix *m) { Pointer p; int i, items, shape[2]; Type type; float *fp; if (DXGetObjectClass(o) != CLASS_ARRAY) return ERROR; if (!DXTypeCheck((Array)o, TYPE_FLOAT, CATEGORY_REAL, 2, 3, 3) && !DXTypeCheck((Array)o, TYPE_FLOAT, CATEGORY_REAL, 2, 4, 3) && !DXTypeCheck((Array)o, TYPE_INT, CATEGORY_REAL, 2, 3, 3) && !DXTypeCheck((Array)o, TYPE_INT, CATEGORY_REAL, 2, 4, 3)) return ERROR; if (!DXGetArrayInfo((Array)o, &items, &type, NULL, NULL, shape)) return ERROR; if (items != 1) return ERROR; p = DXGetArrayData((Array)o); items = shape[0] * shape[1]; if (type == TYPE_FLOAT) memcpy((char *)m, (char *)p, items * sizeof(float)); else for (i=0, fp=(float *)m; i<items; i++, fp++) *fp = (float)((int *)p)[i]; return OK; }
static void Negate(Array a) { Type t; Pointer value; if (!DXGetArrayInfo(a, NULL, &t, NULL, NULL, NULL)) return; value = DXGetArrayData(a); if (!value) return; switch (t) { case TYPE_BYTE: *(byte *)value = - *(byte *)value; break; case TYPE_SHORT: *(short *)value = - *(short *)value; break; case TYPE_INT: *(int *)value = - *(int *)value; break; case TYPE_FLOAT: *(float *)value = - *(float *)value; break; case TYPE_DOUBLE: *(double *)value = - *(double *)value; break; case TYPE_UBYTE: case TYPE_USHORT: case TYPE_UINT: default: /* can't do anything with the unsigned values */ break; } }
/* return whether the value is zero or not. 1 = yes, 0 = no * assumed to be a single item array, scalar. */ static int IsZero(Array a) { Type t; Pointer value; if (!DXGetArrayInfo(a, NULL, &t, NULL, NULL, NULL)) return 0; value = DXGetArrayData(a); if (!value) return 0; switch (t) { case TYPE_BYTE: return (byte)0 == *(byte *)value; case TYPE_UBYTE: return (ubyte)0 == *(ubyte *)value; case TYPE_SHORT: return (short)0 == *(short *)value; case TYPE_USHORT: return (ushort)0 == *(ushort *)value; case TYPE_INT: return (int)0 == *(int *)value; case TYPE_UINT: return (uint)0 == *(uint *)value; case TYPE_FLOAT: return (float)0.0 == *(float *)value; case TYPE_DOUBLE: return (double)0.0 == *(double *)value; default: return 0; } /* NOTREACHED */ }
/* return 1 if value is negative, 0 if >= 0 */ static int IsNegative(Array a) { Type t; Pointer value; if (!DXGetArrayInfo(a, NULL, &t, NULL, NULL, NULL)) return 0; value = DXGetArrayData(a); if (!value) return 0; switch (t) { case TYPE_BYTE: return (*(byte *)value < (byte)0); case TYPE_SHORT: return (*(short *)value < (short)0); case TYPE_INT: return (*(int *)value < 0); case TYPE_FLOAT: return (*(float *)value < 0.0); case TYPE_DOUBLE: return (*(double *)value < 0.0); case TYPE_UBYTE: case TYPE_USHORT: case TYPE_UINT: default: return 0; } /* NOT REACHED */ }
/* return whether two values are the same or not. in this case, we * don't care what the values are, so a byte-by-byte compare is good enough. */ static int IsEqual(Array a, Array b) { int size; Pointer valueA, valueB; size = DXGetItemSize(a); valueA = DXGetArrayData(a); valueB = DXGetArrayData(b); if (size <= 0 || !valueA || !valueB) return 0; if (memcmp(valueA, valueB, size) == 0) return 1; return 0; }
static uint32 computeArrayRecipe (Array a) { uint32 crc; Type type; Category category; int items; int rank; int shape[32]; int i, size, tsize; unsigned char *p; crc = 0xFFFFFFFF; DXGetArrayInfo (a, &items, &type, &category, &rank, shape); size = DXGetItemSize(a); tsize = DXTypeSize(type); crc = _dxf_ExCRCByte (crc, type); crc = _dxf_ExCRCByte (crc, category); crc = _dxf_ExCRCInt (crc, items); crc = _dxf_ExCRCByte (crc, rank); if(DXGetArrayClass(a) == CLASS_REGULARARRAY) { Pointer origin; Pointer delta; origin = DXAllocateLocal(2*size); delta = (Pointer)((char *)origin + size); DXGetRegularArrayInfo((RegularArray)a, NULL, origin, delta); crc = _dxf_ExCRCByteV (crc, (unsigned char *) "regulararray", 1, 12); crc = _dxf_ExCRCByteV (crc, origin, tsize, 2*size/tsize); DXFree(origin); } else { p = (unsigned char *) DXGetArrayData (a); if (p) { if (rank) for (i=0; i < rank; i++) crc = _dxf_ExCRCInt (crc, shape[i]); size *= items; crc = _dxf_ExCRCByteV (crc, p, tsize, size/tsize); } else { crc = 0xFFFFFFFF; crc = _dxf_ExCRCInt (crc, 0); } } return (EXTAG(crc)); }
Error _dxf_polylinesToPlines (xfieldT *xf) { int i; int start, end, knt; int *mesh; ENTRY(("_dxf_linesToPlines(0x%x)", xf)); /* allocate permanent xfield pline data of appropriate size */ /* Allocations are a guess based on 100 lines/polyline */ if (!(xf->meshes = DXNewArray(TYPE_INT, CATEGORY_REAL, 1, 2)) || !(DXAllocateArray (xf->meshes, xf->npolylines))) { PRINT(("could not allocate xfield mesh data")); DXErrorGoto(ERROR_NO_MEMORY, "#13000") ; } mesh = (int *)DXGetArrayData(xf->meshes); for (i = 0; i < xf->npolylines; i++) { start = xf->polylines[i]; end = (i+1 == xf->npolylines) ? xf->nedges : xf->polylines[i+1]; knt = end - start; if(xf->invCntns && !DXIsElementValid(xf->invCntns,i)) continue; *mesh++ = start; *mesh++ = knt; } xf->connections_array = (Array)DXReference((dxObject)xf->edges); xf->nconnections = xf->nedges; xf->nmeshes = xf->npolylines; /* record connection info */ xf->posPerConn = 1 ; xf->connectionType = ct_pline; EXIT(("OK")); return OK ; error: if(xf->meshes) DXDelete((dxObject)xf->meshes); EXIT(("ERROR")); return 0 ; }
static Quadruple *getNeighbors (xfieldT *xf) { /* * Gets an array giving all the neighbors of a given quad. * neighbor[quad].p[n] is the quad adjacent to quad quad, across from * quad quad's nth point. A -1 indicates no quad is adjacent across * from the nth point. * * If connections are expressed in a compact representation, then no * neighbors array is necessary. */ ENTRY(("getNeighbors(0x%x)", xf)); if (DXGetArrayClass(xf->connections_array) == CLASS_MESHARRAY) { EXIT(("CLASS_MESHARRAY")); return 0 ; } else { if (!xf->neighbors_array) { EXIT(("couldn't get neighbors from xfield")); DXErrorReturn (ERROR_INTERNAL, "#13870") ; } if (!DXTypeCheck (xf->neighbors_array, TYPE_INT, CATEGORY_REAL, 1, 4)) { EXIT(("neighbors array has bad type")); DXErrorReturn (ERROR_INTERNAL, "#13870") ; } EXIT(("")); return (Quadruple *) DXGetArrayData(xf->neighbors_array) ; } }
/* item[n] = start + n * delta */ static Array MakeLinearList(Array start, Array end, int *n, Array delta) { int i, j; Array a_start = NULL, a_end = NULL, a_delta = NULL; int delstart = 0, delend = 0, deldelta = 0; Array alist[3]; Array output = NULL; int count = 1; int bytes; Type t; Category c; int rank; int shape[MAXSHAPE]; int nitems; int i_start, i_end, i_delta; float f_start, f_end, f_delta, f_count; Pointer dp; int *ip; Object in[MAXCOMPINPUTS]; /* hardcoded in compute */ Object out; String compstr = NULL; char cbuf[64]; Error rc; /* do this or die in compute */ for (i=0; i<MAXCOMPINPUTS; i++) in[i] = NULL; /* find common format of start, end, delta and check for 4 parms */ i = 0; if (start) alist[i++] = start; if (end) alist[i++] = end; if (delta) alist[i++] = delta; if (n) { count = *n; if (i == 3) { DXWarning("too many inputs specified; ignoring delta"); i--; delta = NULL; } } else if (i == 2) count = 2; if (i < 2) { DXSetError(ERROR_BAD_PARAMETER, "not enough inputs specified to generate a list"); return NULL; } if (!DXQueryArrayCommonV(&t, &c, &rank, shape, i, alist)) { DXAddMessage("start, end and/or delta"); return NULL; } /* shortcut the process here if the data is scalar integer or * scalar float. otherwise, if the data is vector or ubyte * or whatever, fall through and use Compute so we can increment * by irregular values. */ if (t != TYPE_INT && t != TYPE_FLOAT) goto complicated; if (c != CATEGORY_REAL || rank != 0) goto complicated; /* compute missing value(s): * start = end - ((count - 1) * delta) * end = start + ((count - 1) * delta) * count = ((end - start) / delta) + 1 * delta = (end - start) / (count - 1) */ /* convert to the common format */ if (start) a_start = DXArrayConvertV(start, t, c, rank, shape); if (end) a_end = DXArrayConvertV(end, t, c, rank, shape); if (delta) a_delta = DXArrayConvertV(delta, t, c, rank, shape); /* for integer, scalar lists */ if (t == TYPE_INT) { if (!start) { i_end = *(int *)DXGetArrayData(a_end); i_delta = *(int *)DXGetArrayData(a_delta); i_start = i_end - ((count - 1) * i_delta); } if (!end) { i_start = *(int *)DXGetArrayData(a_start); i_delta = *(int *)DXGetArrayData(a_delta); i_end = i_start + ((count - 1) * i_delta); } if (!delta) { /* if count == 1, generate a zero of the right type. otherwise * divide to figure out the right delta to make count-1 steps * between start and end. it's count-1 because if you want * N numbers between start and end, you have N-1 increments. */ i_start = *(int *)DXGetArrayData(a_start); i_end = *(int *)DXGetArrayData(a_end); if (count == 1) i_delta = 0; else i_delta = (i_end - i_start) / (count - 1); /* try to catch the case where delta ends up being 0 (like * because the inputs are int and the count is larger than * the difference between start and end). allow it to be zero * only if start == end; i suppose if you ask for 10 things * where start == end you should be able to get them. */ if (i_delta == 0 && i_start != i_end) { DXSetError(ERROR_BAD_PARAMETER, "count too large to generate list between start and end"); goto error; } } /* if all three arrays are there, count must be missing */ if (i == 3) { i_start = *(int *)DXGetArrayData(a_start); i_end = *(int *)DXGetArrayData(a_end); i_delta = *(int *)DXGetArrayData(a_delta); if (i_delta == 0) count = 1; else { if ((i_end >= i_start && i_delta > 0) || (i_end < i_start && i_delta < 0)) count = (int)(((double)i_end-i_start) / (double)i_delta) +1; else { if (i_delta < 0) DXSetError(ERROR_BAD_PARAMETER, "delta must be positive if start is less than end"); else DXSetError(ERROR_BAD_PARAMETER, "delta must be negative if end is less than start"); goto error; } } } output = (Array)DXNewRegularArray(TYPE_INT, 1, count, (Pointer)&i_start, (Pointer)&i_delta); } /* for float, scalar lists */ if (t == TYPE_FLOAT) { if (!start) { f_end = *(float *)DXGetArrayData(a_end); f_delta = *(float *)DXGetArrayData(a_delta); f_start = f_end - ((count - 1.0) * f_delta); } if (!end) { f_start = *(float *)DXGetArrayData(a_start); f_delta = *(float *)DXGetArrayData(a_delta); f_end = f_start + ((count - 1.0) * f_delta); } if (!delta) { /* if count == 1, generate a zero of the right type. otherwise * divide to figure out the right delta to make count-1 steps * between start and end. it's count-1 because if you want * N numbers between start and end, you have N-1 increments. */ f_start = *(float *)DXGetArrayData(a_start); f_end = *(float *)DXGetArrayData(a_end); if (count == 1) f_delta = 0.0; else f_delta = (f_end - f_start) / (count - 1.0); /* try to catch the case where delta ends up being 0 (like * because the inputs are int and the count is larger than * the difference between start and end). allow it to be zero * only if start == end; i suppose if you ask for 10 things * where start == end you should be able to get them. */ if (f_delta == 0.0 && f_start != f_end) { DXSetError(ERROR_BAD_PARAMETER, "count too large to generate list between start and end"); goto error; } } /* if all three arrays are there, count must be missing */ if (i == 3) { f_start = *(float *)DXGetArrayData(a_start); f_end = *(float *)DXGetArrayData(a_end); f_delta = *(float *)DXGetArrayData(a_delta); if (f_delta == 0.0) count = 1; else { if ((f_end >= f_start && f_delta > 0) || (f_end < f_start && f_delta < 0)) { /* the intermediate float variable below is to minimize * float round-off error. if delta is 0.1 and you * ask for a list between 0 and 1, it does the math in * double, the delta used is actually 0.10000001, and * you get counts = 10.9999999 instead of 11. when * converted directly to int it becomes just 10 and your * list ends at 0.9 instead of 1. * math in base 2 has some problems. */ f_count = ((f_end - f_start) / f_delta) +1; count = (int)f_count; } else { if (f_delta < 0) DXSetError(ERROR_BAD_PARAMETER, "delta must be positive if start is less than end"); else DXSetError(ERROR_BAD_PARAMETER, "delta must be negative if end is less than start"); goto error; } } } output = (Array)DXNewRegularArray(TYPE_FLOAT, 1, count, (Pointer)&f_start, (Pointer)&f_delta); } DXDelete((Object)a_start); DXDelete((Object)a_end); DXDelete((Object)a_delta); /* return Array */ return output; /* input is a vector, or a data type different from int or float. * use compute so this code doesn't have to be replicated for each * different shape and type. */ complicated: nitems = 1; for (j=0; j<rank; j++) nitems *= shape[j]; /* compute missing value(s): * start = end - ((count - 1) * delta) * end = start + ((count - 1) * delta) * count = ((end - start) / delta) + 1 * delta = (end - start) / (count - 1) */ if (!start) { compstr = DXNewString("$0 - (($1 - 1) * $2)"); if (!compstr) goto error; in[0] = (Object)compstr; in[1] = (Object)end; in[3] = (Object)delta; in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0); if (!in[2]) goto error; if (!DXAddArrayData((Array)in[2], 0, 1, (Pointer)&count)) goto error; /* i need to explain this - it's basically so if compute was * going to try to cache this, it could add a reference and * then later when i call delete the object won't get deleted * out from underneath compute. (i know compute doesn't cache * things, but a different module might.) */ DXReference((Object)compstr); DXReference(in[2]); rc = m_Compute(in, &out); DXDelete((Object)compstr); compstr = NULL; DXDelete(in[2]); in[2] = NULL; if (rc == ERROR) goto error; start = (Array)out; delstart++; } if (!end) { compstr = DXNewString("$0 + (($1 - 1) * $2)"); if (!compstr) goto error; in[0] = (Object)compstr; in[1] = (Object)start; in[3] = (Object)delta; in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0); if (!in[2]) goto error; if (!DXAddArrayData((Array)in[2], 0, 1, (Pointer)&count)) goto error; DXReference((Object)compstr); DXReference(in[2]); rc = m_Compute(in, &out); DXDelete((Object)compstr); compstr = NULL; DXDelete(in[2]); in[2] = NULL; if (rc == ERROR) goto error; end = (Array)out; delend++; } if (!delta) { /* if count == 1, generate a zero of the right type. otherwise * divide to figure out the right delta to make count-1 steps * between start and end. it's count-1 because if you want * N numbers between start and end, you have N-1 increments. */ if (count == 1) compstr = DXNewString("$1 - $1"); else compstr = DXNewString("($2 - $0) / ($1 - 1)"); if (!compstr) goto error; in[0] = (Object)compstr; in[1] = (Object)start; in[3] = (Object)end; in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0); if (!in[2]) goto error; if (!DXAddArrayData((Array)in[2], 0, 1, (Pointer)&count)) goto error; DXReference((Object)compstr); DXReference(in[2]); rc = m_Compute(in, &out); DXDelete((Object)compstr); compstr = NULL; DXDelete(in[2]); in[2] = NULL; if (rc == ERROR) goto error; delta = (Array)out; deldelta++; /* try to catch the case where delta ends up being 0 (like * because the inputs are int and the count is larger than * the difference between start and end). allow it to be zero * only if start == end; i suppose if you ask for 10 things * where start == end you should be able to get them. */ if (IsZero(delta) && !IsEqual(start, end)) { DXSetError(ERROR_BAD_PARAMETER, "count too large to generate list between start and end"); goto error; } } /* if all three arrays are there, count must be missing */ if (i == 3) { char tbuf[512]; int firsttime = 1; int lastcount = 0; /* this loop allows us to to handle vectors or matricies as * well as scalars. it requires that the deltas compute to * a consistent count. like start=[0 2 4], end=[4 8 16], * would work if delta=[1 2 4] but not if delta was [1 2 2]. */ for (j=0; j < nitems; j++) { /* i think this code only works for vectors - i'm not sure * what it will do with rank=2 data. */ /* this point of this next compute expression: * if the delta is 0, don't divide by zero - the count is 1. * if the end is smaller than the start, the delta has to be * negative. if it's not, return -1. you can't generate a * negative count from the equations, so this is a safe signal. */ sprintf(tbuf, "float($2.%d) == 0.0 ? " " 1 : " " ( (($1.%d >= $0.%d) && ($2.%d > 0) || " " ($1.%d < $0.%d) && ($2.%d < 0)) ? " " int(float($1.%d - $0.%d) / float($2.%d)) + 1 : " " -1 ) ", j, j, j, j, j, j, j, j, j, j); compstr = DXNewString(tbuf); if (!compstr) goto error; in[0] = (Object)compstr; in[1] = (Object)start; in[2] = (Object)end; in[3] = (Object)delta; DXReference((Object)compstr); rc = m_Compute(in, &out); DXDelete((Object)compstr); compstr = NULL; if (rc == ERROR) goto error; if (!DXExtractInteger(out, &count)) { DXSetError(ERROR_BAD_PARAMETER, "can't compute number of items"); goto error; } DXDelete((Object)out); if (count == 0) continue; if (count < 0) { if (IsNegative(delta)) DXSetError(ERROR_BAD_PARAMETER, "delta must be positive if start is less than end"); else DXSetError(ERROR_BAD_PARAMETER, "delta must be negative if end is less than start"); goto error; } if (firsttime) { lastcount = count; firsttime = 0; } else { if (count != lastcount) { DXSetError(ERROR_BAD_PARAMETER, "inconsistent number of items required by inputs"); goto error; } } } } /* now have 4 consistant values - once again make sure they are * converted into an identical format. */ a_start = DXArrayConvertV(start, t, c, rank, shape); a_end = DXArrayConvertV(end, t, c, rank, shape); a_delta = DXArrayConvertV(delta, t, c, rank, shape); /* make empty array with n items */ output = DXNewArrayV(t, c, rank, shape); if (!output) goto error; if (!DXAddArrayData(output, 0, count, NULL)) goto error; dp = DXGetArrayData(output); if (!dp) goto error; /* foreach n */ /* call compute to add delta */ /* memcpy to right offset in array */ /* end */ bytes = DXGetItemSize(output); sprintf(cbuf, "%s($0 + ($1 * $2))", TypeName(t)); compstr = DXNewString(cbuf); if (!compstr) goto error; in[0] = (Object)compstr; in[1] = (Object)a_start; in[3] = (Object)a_delta; in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0); if (!in[2]) goto error; if (!DXAddArrayData((Array)in[2], 0, 1, NULL)) goto error; ip = (int *)DXGetArrayData((Array)in[2]); DXReference((Object)compstr); DXReference(in[2]); for (i=0; i<count; i++) { *ip = i; rc = m_Compute(in, &out); if (rc == ERROR) goto error; memcpy(INCVOID(dp, bytes*i), DXGetArrayData((Array)out), bytes); DXDelete((Object)out); } DXDelete((Object)compstr); DXDelete(in[2]); DXDelete((Object)a_start); DXDelete((Object)a_end); DXDelete((Object)a_delta); if (delstart) DXDelete((Object)start); if (delend) DXDelete((Object)end); if (deldelta) DXDelete((Object)delta); /* return Array */ return output; error: DXDelete((Object)output); DXDelete((Object)compstr); DXDelete((Object)a_start); DXDelete((Object)a_end); DXDelete((Object)a_delta); if (delstart) DXDelete((Object)start); if (delend) DXDelete((Object)end); if (deldelta) DXDelete((Object)delta); return NULL; }
static Error DoSXEnum( Object o, char *name, char *dep ){ Array a; int n, i, *to; Object oo; /* If the supplied object is a field... */ switch( DXGetObjectClass( o ) ){ case CLASS_FIELD: /* See how many items there are in the requested component. */ a = (Array) DXGetComponentValue( (Field) o, dep ); if( !a ) { DXSetError( ERROR_DATA_INVALID, "field has no \"%s\" component", dep ); return( ERROR ); } DXGetArrayInfo( a, &n, NULL, NULL, NULL, NULL ); /* Create a new array to hold the enumeration, and get a pointer to it. */ a = (Array) DXNewArray( TYPE_INT, CATEGORY_REAL, 0 ); if( !DXAddArrayData( a, 0, n, NULL ) ) return( ERROR ); to = (int *) DXGetArrayData( a ); /* Add this new array to the field. */ DXSetComponentValue( (Field) o, name, (Object) a ); /* Store a value for the "dep" attribute of the new array. */ DXSetComponentAttribute( (Field) o, name, "dep", (Object) DXNewString( dep ) ); /* Store the enumeration values. */ for( i=0; i<n; i++ ) *(to++) = i; /* Indicate that the component values have changed, and complete the * output field. */ DXChangedComponentValues( (Field) o, name ); if( !DXEndField( (Field) o ) ) return( ERROR ); break; /* If the supplied object is a group, call this function recursively for * each member of the group. */ case CLASS_GROUP: for( i=0; oo=(Object)DXGetEnumeratedMember((Group)o,i,NULL); i++ ){ if( !DoSXEnum( oo, name, dep ) ) return( ERROR ); } break; } return( OK ); }
static void CaptionKeyStruck(void *data, DXKeyPressEvent *event) { CaptionData sdata = (CaptionData)data; ModuleInput min[2]; ModuleOutput mout[1]; Object caption, strattr, posattr; Object postion; float *xyz; int i, oldl, n, *ptr; char *oldstr; char *newstr; Object obType = NULL; int x = event->x; int y = event->y; char c = event->key; if (sdata->label == NULL) return; caption = DXGetMember((Group)sdata->obj, sdata->label); if (caption) { /* * If there was already a member by that name, make sure its * an appropriate object and get its state attributes. */ obType = DXGetAttribute(caption, "object type"); if (!obType || strcmp(DXGetString((String)obType), "caption")) return; strattr = DXGetAttribute(caption, "string"); posattr = DXGetAttribute(caption, "position"); } else { /* * Otherwise, we'll initialize the state. We'll need an object * type attribute to put on the result (We re-use the one on the * input if there already was a caption) */ obType = (Object)DXNewString("caption"); /* * Initial state is an empty string at the current mouse * position. */ strattr = (Object)DXNewString(""); posattr = (Object)DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 1, 3); DXAddArrayData((Array)posattr, 0, 1, NULL); xyz = (float *)DXGetArrayData((Array)posattr); xyz[0] = ((float)x)/sdata->w; xyz[1] = ((float)(sdata->h - y))/sdata->w; xyz[2] = 0.0; } DXExtractString(strattr, &oldstr); /* * Update the string. */ oldl = strlen(oldstr); if (c == 0x8 /* BACKSPACE */) { if (oldl > 0) { newstr = (char *)DXAllocate(oldl + 1); for (i = 0; i < oldl-1; i++) newstr[i] = oldstr[i]; newstr[oldl-1] = '\0'; } } else { newstr = (char *)DXAllocate(oldl + 2); for (i = 0; i < oldl; i++) newstr[i] = oldstr[i]; newstr[oldl] = c; newstr[oldl+1] = '\0'; } strattr = (Object)DXNewString(newstr); DXReference(strattr); DXReference(posattr); /* * Use CallModule to call the Caption module. This creates the * new caption object. */ DXModSetObjectInput(min+0, "string", strattr); DXModSetObjectInput(min+1, "position", posattr); DXModSetObjectOutput(mout+0, "caption", &caption); DXCallModule("Caption", 2, min, 1, mout); /* * Replace attributes onto caption */ DXSetAttribute(caption, "string", strattr); DXSetAttribute(caption, "position", posattr); DXSetAttribute(caption, "object type", obType); /* * Replace it into scene object group */ DXSetMember((Group)sdata->obj, sdata->label, caption); DXDelete(strattr); DXDelete(posattr); return; }
static void CaptionMouseButton(void *data, DXMouseEvent *event) { Object caption; Object obType; CaptionData sdata = (CaptionData)data; int b = WHICH_BUTTON(event); int x, y; x = event->x; y = event->y; if (sdata->label == NULL) return; /* * Get the member by name. If no caption by this name exists, * there's nothing to move, so we return. */ caption = DXGetMember((Group)sdata->obj, sdata->label); if (! caption) return; /* * Make sure its an appropriate object */ obType = DXGetAttribute(caption, "object type"); if (!obType || strcmp(DXGetString((String)obType), "caption")) return; /* * Only should see left buttons, but check anyway. */ if (b == 0) { ModuleInput min[2]; ModuleOutput mout[1]; Object strattr, posattr; float *xyz; /* * If its a caption object, it better have these attributes. * A little error checking might be called for. */ strattr = DXGetAttribute(caption, "string"); posattr = (Object)DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 1, 3); DXAddArrayData((Array)posattr, 0, 1, NULL); xyz = (float *)DXGetArrayData((Array)posattr); /* * Move to the current position (0-1 space requires the division * by the screen width in pixels. */ xyz[0] = ((float)x)/sdata->w; xyz[1] = ((float)(sdata->h - y))/sdata->w; xyz[2] = 0.0; DXReference(strattr); DXReference(posattr); /* * Use CallModule to call the Caption module. This creates the * new caption object. */ DXModSetObjectInput(min+0, "string", strattr); DXModSetObjectInput(min+1, "position", posattr); DXModSetObjectOutput(mout+0, "caption", &caption); DXCallModule("Caption", 2, min, 1, mout); /* * Replace attributes onto caption */ DXSetAttribute(caption, "string", strattr); DXSetAttribute(caption, "position", posattr); DXSetAttribute(caption, "object type", obType); /* * Replace it into scene object group */ DXSetMember((Group)sdata->obj, sdata->label, caption); DXDelete(strattr); DXDelete(posattr); } return; }
Error DXGetInputs(Object *in, int dxfd) { static int firsttime = 1; int nin = 0; Group iobj = NULL; int i; int *iptr; int count = 0; if (firsttime && ! callsetup (dxfd)) { host_status = HOST_CLOSED; return ERROR; } /* * Import the remote object, extract the number of inputs and outputs, * and rip them apart appropriately. group members are: * input parm count, * input object list (the pointers values don't mean anything in this * address space; the interesting part is whether they are NULL or not), * the output parm count, * and then each input object which isn't null. */ iobj = (Group) _dxfImportBin_FP(dxfd); if(iobj == NULL) goto error; if (!DXExtractInteger (DXGetEnumeratedMember (iobj, 0, NULL), &nin)) goto error; memset(in, '\0', sizeof(Object)*nin); iptr = (int *)DXGetArrayData((Array)DXGetEnumeratedMember (iobj, 1, NULL)); /* was nout */ if (!DXExtractInteger (DXGetEnumeratedMember (iobj, 2, NULL), &number_of_outputs)) goto error; count = 3; for (i=0; i<nin; i++) { if (iptr[i] == (int)NULL) continue; in[i] = DXGetEnumeratedMember(iobj, count++, NULL); } /* when does iobj get freed? */ /* and how does nout get saved? */ last_inputs = (Object)iobj; in_module++; return OK; error: DXDelete ((Object) iobj); last_inputs = NULL; return ERROR; }
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 ); } }
int _dxfPlineDraw (tdmPortHandleP portHandle, xfieldT *xf, int buttonUp) { Vector *normals ; Point *points = 0 ; struct p2d {float x, y ;} *pnts2d = 0 ; RGBColor *fcolors, *color_map ; char *cache_id ; enum approxE approx ; tdmStripArraySB *stripsSB = 0 ; int type, rank, shape, is_2d ; DEFPORT(portHandle) ; ENTRY(("_dxfPlineDraw(0x%x, 0x%x, %d)", portHandle, xf, buttonUp)); /* * Transparent surfaces are stripped for those ports which implement * transparency with the screen door technique, but we need to sort them * as individual polygons to apply the more accurate alpha composition * method supported by Starbase. * * Connection-dependent colors are not supported by Starbase strips. */ approx = buttonUp ? xf->attributes.buttonUp.approx : xf->attributes.buttonDown.approx ; if ( #ifdef ALLOW_LINES_APPROX_BY_DOTS (approx == approx_dots) || #endif (xf->colorsDep == dep_connections)) { int status ; PRINT(("drawing as individual polygons")); status = _dxfLineDraw (portHandle, xf, buttonUp) ; EXIT(("")); return status ; } /* * Extract rendering data from the xfield. */ if (DXGetArrayClass(xf->fcolors_array) == CLASS_CONSTANTARRAY) fcolors = (Pointer) DXGetArrayEntry(xf->fcolors, 0, NULL) ; else fcolors = (Pointer) DXGetArrayData(xf->fcolors_array) ; color_map = (RGBColor *) DXGetArrayData(xf->cmap_array) ; if (DXGetArrayClass(xf->normals_array) == CLASS_CONSTANTARRAY) normals = (Pointer) DXGetArrayEntry(xf->normals, 0, NULL) ; else normals = (Pointer) DXGetArrayData(xf->normals_array) ; #if 0 if (xf->colorsDep != dep_field) { /* * Dense fields of varying colors are visually confusing * without hidden surface, even with wireframe approximation. */ hidden_surface (FILDES, TRUE, FALSE) ; } else /* RE : <LUMBA281> */ { hidden_surface(FILDES, TRUE, FALSE); } #endif hidden_surface(FILDES, TRUE, FALSE); if (xf->colorsDep == dep_field) { /* render field in constant color */ cache_id = "CpfPline" ; SET_COLOR(fill_color, 0) ; SET_COLOR(line_color, 0) ; } else { cache_id = "CpfPline" ; } /* * Render strips. */ PRINT(("%s", cache_id)); if (stripsSB = tdmGetTmeshCacheSB (cache_id, xf)) { /* * Use pre-constructed Starbase strips obtained from executive cache. */ register tdmTmeshCacheSB *stripArray, *end ; PRINT(("got strips from cache")); PrintBounds() ; stripArray = stripsSB->stripArray ; end = &stripArray[stripsSB->num_strips] ; for ( ; stripArray < end ; stripArray++) { polyline_with_data3d (FILDES, stripArray->clist, stripArray->numverts, stripArray->numcoords, stripArray->vertex_flags, NULL) ; } } else { /* * Construct an array of Starbase strips and cache it. */ register int vsize ; int *connections, (*strips)[2] ; int cOffs, nOffs, vertex_flags, facet_flags, numStrips ; tdmTmeshCacheSB *stripArray ; PRINT(("building new strips")); /* determine vertex and facet types and sizes */ vertex_flags = 0 ; facet_flags = UNIT_NORMALS ; vsize = 3 ; if (fcolors && xf->colorsDep != dep_field) { /* vertex has at least 6 floats, with color at float 3 */ vsize = 6 ; cOffs = 3 ; vertex_flags |= VERTEX_COLOR ; } /* get positions */ if (is_2d = IS_2D (xf->positions_array, type, rank, shape)) pnts2d = (struct p2d *) DXGetArrayData(xf->positions_array) ; else points = (Point *) DXGetArrayData(xf->positions_array) ; /* get strip topology */ connections = (int *)DXGetArrayData(xf->connections_array) ; strips = (int (*)[2])DXGetArrayData(xf->meshes) ; numStrips = xf->nmeshes ; DebugMessage() ; /* allocate space for Starbase strip data */ stripsSB = (tdmStripArraySB *) tdmAllocate(sizeof(tdmStripArraySB)) ; if (!stripsSB) { PRINT(("out of memory allocating strip structure")); DXErrorGoto (ERROR_INTERNAL, "#13000") ; } stripsSB->stripArray = 0 ; stripsSB->num_strips = 0 ; /* allocate array of Starbase strips */ stripArray = stripsSB->stripArray = (tdmTmeshCacheSB *) tdmAllocate(numStrips*sizeof(tdmTmeshCacheSB)); if (!stripArray) { PRINT(("out of memory allocating array of strips")); DXErrorGoto (ERROR_INTERNAL, "#13000") ; } for ( ; stripsSB->num_strips < numStrips ; stripsSB->num_strips++) { /* each iteration constructs and draws one Starbase strip */ register float *clist = 0, *gnormals = 0 ; register int i, dV, *pntIdx, numPnts ; stripArray->clist = 0 ; stripArray->gnormals = 0 ; /* get the number of points in this strip */ numPnts = strips[stripsSB->num_strips][1] ; /* allocate coordinate list */ stripArray->clist = clist = (float *) tdmAllocate(numPnts*vsize*sizeof(float)) ; if (!clist) { PRINT(("out of memory allocating coordinate list")); DXErrorGoto(ERROR_INTERNAL, "#13000") ; } /* get the sub-array of connections making up this strip */ pntIdx = &connections[strips[stripsSB->num_strips][0]] ; /* copy vertex coordinates into clist */ if (is_2d) for (i=0, dV=0 ; i<numPnts ; i++, dV+=vsize) { *(struct p2d *)(clist+dV) = pnts2d[pntIdx[i]] ; ((Point *)(clist+dV))->z = 0 ; } else for (i=0, dV=0 ; i<numPnts ; i++, dV+=vsize) *(Point *)(clist+dV) = points[pntIdx[i]] ; /* copy vertex colors */ if (vertex_flags & VERTEX_COLOR) if (color_map) for (i=0, dV=cOffs ; i<numPnts ; i++, dV+=vsize) *(RGBColor *)(clist+dV) = color_map[((char *)fcolors)[pntIdx[i]]] ; else for (i=0, dV=cOffs ; i<numPnts ; i++, dV+=vsize) *(RGBColor *)(clist+dV) = fcolors[pntIdx[i]] ; /* save other strip info */ stripArray->numverts = numPnts ; stripArray->numcoords = vsize-3 ; stripArray->vertex_flags = vertex_flags ; stripArray->facet_flags = facet_flags ; polyline_with_data3d (FILDES, clist, numPnts, vsize-3, vertex_flags, NULL) ; /* increment strip */ stripArray++ ; } /* cache strip array */ tdmPutTmeshCacheSB (cache_id, xf, stripsSB) ; } /* restore hidden surface OFF */ hidden_surface(FILDES, FALSE, FALSE) ; EXIT(("OK")); return OK ; error: tdmFreeTmeshCacheSB((Pointer)stripsSB) ; hidden_surface(FILDES, FALSE, FALSE) ; EXIT(("ERROR")); return ERROR ; }
static Error ConvertFieldObject(Object out, char *strin) { Class cl; int i, rank, shape[30], numitems; Type type; Category category; Array data, new_data; RGBColor *dp_old, *dp_new; Object subo; float red, green, blue, hue, sat, val; if (!(cl = DXGetObjectClass(out))) return ERROR; switch (cl) { case CLASS_GROUP: for (i=0; (subo = DXGetEnumeratedMember((Group)out, i, NULL)); i++) { if (!ConvertFieldObject((Object)subo, strin)) return ERROR; } break; case CLASS_FIELD: if (DXEmptyField((Field)out)) return OK; data = (Array)DXGetComponentValue((Field)out,"data"); if (!data) { DXSetError(ERROR_MISSING_DATA,"#10240", "data"); return ERROR; } DXGetArrayInfo(data,&numitems,&type,&category,&rank,shape); if ((type != TYPE_FLOAT)||(category != CATEGORY_REAL)) { DXSetError(ERROR_DATA_INVALID,"#10331", "data"); return ERROR; } if ((rank != 1)||(shape[0] != 3)) { DXSetError(ERROR_DATA_INVALID,"#10331", "data"); return ERROR; } new_data = DXNewArray(TYPE_FLOAT,CATEGORY_REAL,1,3); new_data = DXAddArrayData(new_data, 0, numitems, NULL); dp_old = (RGBColor *)DXGetArrayData(data); dp_new = (RGBColor *)DXGetArrayData(new_data); if (!strcmp(strin,"hsv")) { for (i=0; i<numitems; i++) { if (!_dxfHSVtoRGB(dp_old[i].r, dp_old[i].g, dp_old[i].b, &red, &green, &blue)) return ERROR; dp_new[i] = DXRGB(red,green,blue); } } else { for (i=0; i<numitems; i++) { if (!_dxfRGBtoHSV(dp_old[i].r, dp_old[i].g, dp_old[i].b, &hue, &sat, &val)) return ERROR; dp_new[i] = DXRGB(hue, sat, val); } } DXSetComponentValue((Field)out, "data", (Object)new_data); DXChangedComponentValues((Field)out,"data"); DXEndField((Field)out); break; default: break; } return OK; }
int _dxfPlineDraw (tdmPortHandleP portHandle, xfieldT *xf, int buttonUp) { Point *points = 0 ; struct p2d {float x, y ;} *pnts2d = 0 ; Vector *normals ; RGBColor *fcolors, *color_map ; Type type ; int rank, shape, is_2d ; float *opacities, *opacity_map ; char *cache_id ; tdmStripDataXGL *stripsXGL = 0 ; DEFPORT(portHandle) ; DPRINT("\n(_dxfPlineDraw") ; if(xf->colorsDep == dep_connections) return _dxfLineDraw(portHandle, xf, buttonUp); /* * Extract required data from the xfield. */ if (is_2d = IS_2D(xf->positions_array, type, rank, shape)) pnts2d = (struct p2d *) DXGetArrayData(xf->positions_array) ; else points = (Point *) DXGetArrayData(xf->positions_array) ; color_map = (RGBColor *) DXGetArrayData(xf->cmap_array) ; opacity_map = (float *) DXGetArrayData(xf->omap_array) ; if (DXGetArrayClass(xf->fcolors_array) == CLASS_CONSTANTARRAY) fcolors = (Pointer) DXGetArrayEntry(xf->fcolors, 0, NULL) ; else fcolors = (Pointer) DXGetArrayData(xf->fcolors_array) ; if (DXGetArrayClass(xf->opacities_array) == CLASS_CONSTANTARRAY) opacities = (Pointer) DXGetArrayEntry(xf->opacities, 0, NULL) ; else opacities = (Pointer) DXGetArrayData(xf->opacities_array) ; DebugMessage() ; /* set default attributes for surface and wireframe approximation */ xgl_object_set (XGLCTX, XGL_CTX_LINE_COLOR_SELECTOR, XGL_LINE_COLOR_VERTEX, XGL_3D_CTX_LINE_COLOR_INTERP, TRUE, 0) ; /* override above attributes according to color dependencies and lighting */ if (xf->colorsDep == dep_field) { /* * Field has constant color. Get color from context. */ CLAMP(&fcolors[0],&fcolors[0]) ; cache_id = "CpfPline" ; /* get line color from context */ xgl_object_set (XGLCTX, XGL_CTX_LINE_COLOR_SELECTOR, XGL_LINE_COLOR_CONTEXT, XGL_CTX_LINE_COLOR, &fcolors[0], NULL) ; } else { /* * Field has varying colors. Get colors from point data. */ cache_id = "CppPline" ; } DPRINT1("\n%s", cache_id) ; #if 0 /* may want this when we add transparent lines */ /* * Set up a simple 50% screen door approximation for opacities < 0.75. * We can't do opacity dep position or connection with this technique, * but constant opacity per field is adequate for many visualizations. * * USE_SCREEN_DOOR should only be true if we're using the GT through * the XGL 3.0 interface on Solaris; no other access to this effect is * provided by Sun. The GT with XGL 3.0 also provides alpha * transparency of some sort. It's not implemented here. */ xgl_object_set (XGLCTX, XGL_CTX_SURF_FRONT_FILL_STYLE, XGL_SURF_FILL_SOLID, NULL) ; if (opacities && USE_SCREEN_DOOR) if ((opacity_map? opacity_map[*(char *)opacities]: opacities[0]) < 0.75) xgl_object_set (XGLCTX, XGL_CTX_SURF_FRONT_FILL_STYLE, XGL_SURF_FILL_STIPPLE, XGL_CTX_SURF_FRONT_FPAT, SCREEN_DOOR_50, NULL) ; #endif if (stripsXGL = _dxf_GetTmeshCacheXGL (cache_id, xf)) { /* * Use pre-constructed xgl strips obtained from executive cache. */ register Xgl_pt_list *pt_list, *end ; DPRINT("\ngot strips from cache"); pt_list = stripsXGL->pt_lists ; end = &pt_list[stripsXGL->num_strips] ; for ( ; pt_list < end ; pt_list++) xgl_multipolyline (XGLCTX, NULL, 1, pt_list) ; } else { /* * Construct an array of xgl strips and cache it. */ register int vsize, fsize ; int v_cOffs, v_nOffs, vertex_flags, numStrips ; int *connections, (*strips)[2] ; Xgl_pt_list *xgl_pt_list ; DPRINT("\nbuilding new strips"); /* determine vertex types and sizes */ vsize = 3 ; fsize = 0 ; vertex_flags = XGL_D_3 | XGL_FLT | XGL_NFLG | XGL_NHOM | XGL_DIRECT ; if (fcolors && xf->colorsDep != dep_field) { /* vertex has 3 more floats to accomodate color */ v_cOffs = vsize ; vsize += 3 ; vertex_flags |= XGL__CLR ; } /* get strip topology */ connections = (int *)DXGetArrayData(xf->connections_array) ; strips = (int (*)[2])DXGetArrayData(xf->meshes) ; numStrips = xf->nmeshes ; /* allocate space for strip data */ stripsXGL = (tdmStripDataXGL *) tdmAllocate(sizeof(tdmStripDataXGL)); if (!stripsXGL) DXErrorGoto (ERROR_INTERNAL, "#13000") ; stripsXGL->pt_lists = 0 ; stripsXGL->facet_lists = 0 ; stripsXGL->num_strips = 0 ; /* allocate array of xgl point lists */ xgl_pt_list = stripsXGL->pt_lists = (Xgl_pt_list *) tdmAllocate(numStrips*sizeof(Xgl_pt_list)); if (!xgl_pt_list) DXErrorGoto (ERROR_INTERNAL, "#13000") ; for ( ; stripsXGL->num_strips < numStrips ; stripsXGL->num_strips++) { /* each iteration constructs and draws one xgl strip */ register float *clist, *flist ; register int i, dV, *pntIdx, numPnts ; /* get the number of points in this strip */ numPnts = strips[stripsXGL->num_strips][1] ; /* allocate coordinate list */ xgl_pt_list->pts.color_normal_f3d = (Xgl_pt_color_normal_f3d *) (clist = (float *) tdmAllocate(numPnts*vsize*sizeof(float))) ; if (!clist) DXErrorGoto (ERROR_INTERNAL, "#13000") ; /* get the sub-array of connections making up this strip */ pntIdx = &connections[strips[stripsXGL->num_strips][0]] ; /* copy vertex coordinates into clist */ if (is_2d) for (i=0, dV=0 ; i<numPnts ; i++, dV+=vsize) { *(struct p2d *)(clist+dV) = pnts2d[pntIdx[i]] ; ((Point *)(clist+dV))->z = 0 ; } else for (i=0, dV=0 ; i<numPnts ; i++, dV+=vsize) *(Point *)(clist+dV) = points[pntIdx[i]] ; /* copy vertex colors */ if (vertex_flags & XGL__CLR) if (color_map) for (i=0, dV=v_cOffs ; i<numPnts ; i++, dV+=vsize) CLAMP((clist+dV), &color_map[((char *)fcolors)[pntIdx[i]]]); else for (i=0, dV=v_cOffs ; i<numPnts ; i++, dV+=vsize) CLAMP((clist+dV),&fcolors[pntIdx[i]] ) ; /* set up other point list info */ xgl_pt_list->bbox = NULL ; xgl_pt_list->num_pts = numPnts ; xgl_pt_list->pt_type = vertex_flags ; /* send strip to xgl, increment pointlist pointers */ xgl_multipolyline (XGLCTX, NULL, 1, xgl_pt_list++) ; } /* cache all strip data */ _dxf_PutTmeshCacheXGL (cache_id, xf, stripsXGL) ; } DPRINT(")") ; return OK ; error: _dxf_FreeTmeshCacheXGL((Pointer)stripsXGL) ; DPRINT("\nerror)") ; return ERROR ; }
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 ); } }
static int doLeaf(Object *in, Object *out) { int i, result=0; Array array; Field field; Pointer *in_data[2], *out_data[1]; int in_knt[2], out_knt[1]; Type type; Category category; int rank, shape; Object attr, src_dependency_attr = NULL; char *src_dependency = NULL; /* * Irregular positions info */ int p_knt, p_dim; float *p_positions; int c_knt = -1; /* User-added declarations */ float *scratch, *in_ptr, size; Point inpoint, *out_pos_ptr; ArrayHandle handle; Array connections; Line *conn_ptr; /* * positions and/or connections are required, so the first must * be a field. */ if (DXGetObjectClass(in[0]) != CLASS_FIELD) { DXSetError(ERROR_DATA_INVALID, "positions and/or connections unavailable in array object"); goto error; } else { field = (Field)in[0]; if (DXEmptyField(field)) return OK; /* * Determine the dependency of the source object's data * component. */ src_dependency_attr = DXGetComponentAttribute(field, "data", "dep"); if (! src_dependency_attr) { DXSetError(ERROR_MISSING_DATA, "\"input\" data component is missing a dependency attribute"); goto error; } if (DXGetObjectClass(src_dependency_attr) != CLASS_STRING) { DXSetError(ERROR_BAD_CLASS, "\"input\" dependency attribute"); goto error; } src_dependency = DXGetString((String)src_dependency_attr); array = (Array)DXGetComponentValue(field, "positions"); if (! array) { DXSetError(ERROR_BAD_CLASS, "\"input\" contains no positions component"); goto error; } /* change to doLeaf so that regular positions are not expanded */ if (!(handle = DXCreateArrayHandle(array))) goto error; scratch = DXAllocate(3*sizeof(float)); if (!scratch) goto error; DXGetArrayInfo(array, &p_knt, NULL, NULL, NULL, &p_dim); } /* New User code starts here */ /* Make the new positions array for the output */ array = DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 1, 3); if (! array) goto error; /* Check that the positions are three dimensional: */ if (p_dim != 3) { DXSetError(ERROR_DATA_INVALID,"input positions must be 3-dimensional"); goto error; } /* Allocate space in the new positions array */ if (! DXAddArrayData(array, 0, 4*p_knt, NULL)) goto error; /* Get a pointer to the output positions */ out_pos_ptr = (Point *)DXGetArrayData(array); /* Make a connections component for the output */ connections = DXNewArray(TYPE_INT, CATEGORY_REAL, 1, 2); /* Allocate space in the new connections array */ if (! DXAddArrayData(connections, 0, 2*p_knt, NULL)) goto error; DXSetAttribute((Object)connections, "element type", (Object)DXNewString("lines")); /* Get a pointer to the new connections */ conn_ptr = (Line *)DXGetArrayData(connections); /* Now "draw" the x's */ for (i=0; i< p_knt; i++) { /* the following line accesses the position via the * array handling routines */ in_ptr = (float *)DXIterateArray(handle, i, in_ptr, scratch); inpoint = DXPt(in_ptr[0], in_ptr[1], in_ptr[2]); DXExtractFloat(in[1], &size); out_pos_ptr[4*i] = DXPt(inpoint.x - size, inpoint.y, inpoint.z); out_pos_ptr[4*i+1] = DXPt(inpoint.x + size, inpoint.y, inpoint.z); out_pos_ptr[4*i+2] = DXPt(inpoint.x, inpoint.y - size, inpoint.z); out_pos_ptr[4*i+3] = DXPt(inpoint.x, inpoint.y + size, inpoint.z); conn_ptr[2*i] = DXLn(4*i, 4*i+1); conn_ptr[2*i+1] = DXLn(4*i+2, 4*i+3); } /* Clean up; we're about to significantly modify the positions and connections */ DXChangedComponentStructure((Field)out[0],"positions"); DXChangedComponentStructure((Field)out[0],"connections"); /* Now place the new positions and connections in the output field */ DXSetComponentValue((Field)out[0], "positions", (Object)array); DXSetComponentValue((Field)out[0], "connections", (Object)connections); /* Finalize the field */ DXEndField((Field)out[0]); /* Delete scratch and handle */ DXFree((Pointer)scratch); DXFreeArrayHandle(handle); /* return */ return OK; error: /* Delete scratch and handle */ DXFree((Pointer)scratch); DXFreeArrayHandle(handle); return ERROR; }
static void * Slide2DInitMode(Object args, int w, int h, int *mask) { Slide2DData sdata = (Slide2DData)DXAllocateZero(sizeof(struct slide2DData)); if (! sdata) return NULL; /* * Parse the argument. It better be a string or an integer. */ if (! args) { DXWarning("Slide2D: argument required (index 0 used)"); sdata->label = NULL; sdata->index = 0; } else if (DXGetObjectClass(args) == CLASS_STRING) { sdata->args = DXReference(args); sdata->label = DXGetString((String)args); } else if (DXGetObjectClass(args) == CLASS_ARRAY) { Type t; DXGetArrayInfo((Array)args, NULL, &t, NULL, NULL, NULL); if (t == TYPE_INT) { sdata->args = DXReference(args); sdata->index = *(int *)DXGetArrayData((Array)args); sdata->label = NULL; } else if (t == TYPE_UBYTE || t == TYPE_BYTE || t == TYPE_STRING) { sdata->args = DXReference(args); sdata->label = (char *)DXGetArrayData((Array)args); sdata->index = -1; } else { DXWarning("Slide2D: argument must be string or int (index 0 used)"); sdata->label = NULL; sdata->index = 0; } } /* * Save the window width and height for scaling purposes */ sdata->w = w; sdata->h = h; /* * Initially, the button is up */ sdata->strokeStart = 1; /* * Pay attention to only the left and middle buttons */ *mask = DXEVENT_LEFT | DXEVENT_MIDDLE; return (void *)sdata; }
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; }
Error _dxf_quadsToQmesh (xfieldT *xf, void *globals) { DEFGLOBALDATA(globals) ; Quadruple *neighbors ; /* neighbors array gives a quad's neighbors */ Qstrip *stripArray = 0 ; /* temp array of strips */ int point[MaxQstripSize] ; /* array into which to build point list */ char *usedArray = 0 ; /* marks quads already used */ int nStrips = 0 ; /* number of strips generated */ int nStrippedPts = 0 ; /* number of points stripped */ int nPtsInStrip ; /* number of points in current strip */ int start_quad ; /* first quad of the strip */ int quad ; /* the current quad */ int dir, i0, i1, i2, i3 ; /* the 4 indexes into quads[quad].p[?] */ int prev_quad, prev_i0, /* used to determine the same current info */ prev_i1,prev_i2,prev_i3 ; Quadruple *quads ; /* array of original quad connections */ int nquads ; /* number of original quad connections */ int i, j, k ; /* misc. indices */ QMesh qmesh = NULL; dxObject qmesho = NULL; ENTRY(("_dxf_quadsToQmesh(0x%x)", xf)); qmesho = _dxf_QueryObject(MESHHASH, (dxObject)xf->field); if (qmesho) { xf->meshObject = DXReference(qmesho); qmesh = (QMesh)DXGetPrivateData((Private)qmesho); _installQMeshInfo(xf, qmesh); return OK; } if (xf->connectionType != ct_quads) { EXIT(("xf->connectionType not ct_quads")); return OK ; } PRINT(("invalid connections: %d", xf->invCntns? DXGetInvalidCount(xf->invCntns): 0)) ; neighbors = getNeighbors(xf); /* get quad connection info; quad connections are replaced by strips */ quads = DXGetArrayData(xf->connections_array) ; nquads = xf->nconnections ; /*npoints = xf->npositions ;*/ xf->origNConnections = nquads; xf->origConnections_array = xf->connections_array; xf->connections_array = NULL; /* allocate temporary array to hold maximum possible number of strips */ if (!(stripArray = (Qstrip *) tdmAllocate(sizeof(Qstrip) * nquads))) { PRINT(("out of memory")); DXErrorGoto (ERROR_NO_MEMORY, "#13000") ; } if (neighbors) { /* quad connections expressed explicitly, we need usedArray */ if (!(usedArray = tdmAllocateZero(sizeof(char) * Bytes(nquads)))) { PRINT(("out of memory")); DXErrorGoto (ERROR_NO_MEMORY, "#13000") ; } /* strip the field, placing strip info into temporary arrays */ for (start_quad = 0; start_quad < nquads; start_quad++) { if (GoodQuad(start_quad)) { nPtsInStrip = 0 ; quad = start_quad ; InitFirstQuad(i0,i1,i2,i3) ; /* pick 1st quad initial vertices */ AddPoint(quad,i1) ; /* add the 1st two... */ AddPoint(quad,i0) ; /* ...points to the mesh */ while (quad >= 0) /* while there's a valid quad... */ { AddPoint(quad,i3) ; /* add another quad to the strip */ AddPoint(quad,i2) ; MarkQuad(quad) ; /* mark it as used */ NextQuad(quad) ; /* move on to next quad */ } /* save strip points */ AllocateAndCopyQstripPointArray() ; } } tdmFree((Pointer)usedArray) ; usedArray = NULL; } else { /* quad connections expressed in compact mesh array form */ int n, counts[100] ; if (!DXQueryGridConnections (xf->origConnections_array, &n, counts) || n != 2) DXErrorGoto (ERROR_INTERNAL, "#13140") ; PRINT(("counts[0] = %d", counts[0])); PRINT(("counts[1] = %d", counts[1])); for (n = 0, i = 0 ; i < counts[0]-1 ; i++) { j = 0 ; while (j < counts[1]-1) { for ( ; j < counts[1]-1 && !ValidQuad(xf->invCntns, n) ; j++, n++) /* skip invalid quads up to end of row/column */ ; if (j == counts[1]-1) break ; /* start triangle strip */ nPtsInStrip = 0 ; point[nPtsInStrip++] = n + i ; point[nPtsInStrip++] = n + i + counts[1] ; while (j < counts[1]-1 && nPtsInStrip < MaxQstripSize && ValidQuad(xf->invCntns, n)) { /* add valid quads up to end of row/column or strip limit */ point[nPtsInStrip++] = n + i + 1 ; point[nPtsInStrip++] = n + i + 1 + counts[1] ; j++ ; n++ ; } /* save strip points */ AllocateAndCopyQstripPointArray() ; } } } PRINT(("stripped %d quadrangles", (nStrippedPts - 2*nStrips)/2)); PRINT(("generated %d triangle strips", nStrips)); PRINT(("average number of triangles per strip: %f", nStrips? (nStrippedPts - 2*nStrips)/(float)nStrips: 0)); if (! _newQMesh(nStrips, nStrippedPts, &qmesh, &qmesho)) goto error; for (i=j=k=0 ; i<nStrips ; i++) { qmesh->meshes[j++] = k; qmesh->meshes[j++] = stripArray[i].points; memcpy(qmesh->connections+k, stripArray[i].point, stripArray[i].points*sizeof(int)); k += stripArray[i].points; } _dxf_InsertObject(MESHHASH, (dxObject)(xf->field), (dxObject)qmesho); xf->meshObject = DXReference(qmesho); _installQMeshInfo(xf, qmesh); /* free temporary array of strips */ if (usedArray) tdmFree((Pointer)usedArray); if (stripArray) FreeTempStrips() ; EXIT(("OK")); return OK ; error: if (usedArray) tdmFree((Pointer)usedArray); if (stripArray) FreeTempStrips() ; EXIT(("ERROR")); return 0 ; }
Error _dxfValidate(Field f) { Array current = NULL; Array target = NULL; char *tname, *cname; int ncurrent, ntarget, *ip; int index; unsigned char *cp; int i, j, lim, nitems; Type type, ref_type; Category cat; String s = NULL; Object o = NULL; int rank, shape[MAXRANK]; int counts[MAXRANK]; for (i=0; (current=(Array)DXGetEnumeratedComponentValue(f, i, &cname)); i++) { /* dep */ if ((s = (String)DXGetAttribute((Object)current, "dep")) != NULL) { /* make sure number of items matches number of items in dep */ if ((DXGetObjectClass((Object)s) != CLASS_STRING) || ((tname = DXGetString(s)) == NULL)) { DXSetError(ERROR_DATA_INVALID, Err_MustBeString, "dep", cname); return ERROR; } if ((target = (Array)DXGetComponentValue(f, tname)) == NULL) { DXSetError(ERROR_DATA_INVALID, Err_MissingComp, tname, "dep", cname); return ERROR; } if (DXGetObjectClass((Object)target) != CLASS_ARRAY) { DXSetError(ERROR_DATA_INVALID, Err_NotArray, tname, "dep", cname); return ERROR; } if (!DXGetArrayInfo(current, &nitems, &type, &cat, &rank, shape)) return ERROR; ncurrent = nitems; if (!DXGetArrayInfo(target, &nitems, &type, &cat, &rank, shape)) return ERROR; ntarget = nitems; if (ncurrent != ntarget) { DXSetError(ERROR_DATA_INVALID, Err_DiffCount, "dep", ncurrent, cname, ntarget, tname); return ERROR; } } /* end of if (has dep) */ /* ref */ if ((s = (String)DXGetAttribute((Object)current, "ref")) != NULL) { if ((DXGetObjectClass((Object)s) != CLASS_STRING) || ((tname = DXGetString(s)) == NULL)) { DXSetError(ERROR_DATA_INVALID, Err_MustBeString, "ref", cname); return ERROR; } if ((target = (Array)DXGetComponentValue(f, tname)) == NULL) { DXSetError(ERROR_DATA_INVALID, Err_MissingComp, tname, "ref", cname); return ERROR; } if (DXGetObjectClass((Object)target) != CLASS_ARRAY) { DXSetError(ERROR_DATA_INVALID, Err_NotArray, tname, "ref", cname); return ERROR; } if (!DXGetArrayInfo(current, &nitems, &type, &cat, &rank, shape)) return ERROR; if ( !( type == TYPE_INT || type == TYPE_UBYTE ) ) { DXSetError(ERROR_DATA_INVALID, Err_RefNotInt, cname); return ERROR; } ref_type = type; ncurrent = nitems; for (j=0; j<rank; j++) ncurrent *= shape[j]; if (ncurrent > 0) { if (!DXGetArrayInfo(target, &nitems, &type, &cat, &rank, shape)) return ERROR; ntarget = nitems; /* only do this if they are already irregular */ if (DXGetArrayClass(current) == CLASS_ARRAY) { if ((ip = (int *)DXGetArrayData(current)) == NULL) return ERROR; cp = (unsigned char *) ip; /* neighbors can have -1's as indicies */ lim = strcmp(cname, "neighbors") ? 0 : -1; for (j=0; j < ncurrent; j++) { if (ref_type == TYPE_INT) index = *(ip++); else index = *(cp++); if (index < lim || index >= ntarget) { DXSetError(ERROR_DATA_INVALID, Err_OutOfRange, j+1, ending(j+1), cname, index, lim, ntarget-1); return ERROR; } } } else if (DXQueryGridConnections(current, &rank, counts)) { for (j=0, ncurrent=1; j<rank; j++) ncurrent *= counts[j]; if (ncurrent > ntarget) { DXSetError(ERROR_DATA_INVALID, Err_DiffCount, "ref", ncurrent, cname, ntarget, tname); return ERROR; } } else { /* mesh array of mixed path and irregular arrays. */ /* have to handle the terms separately */ } } } /* end of if (has ref) */ /* der - can be string lists here */ if ((o = DXGetAttribute((Object)current, "der")) != NULL) { if (DXExtractString(o, &tname)) { /* simple string? */ if ((target = (Array)DXGetComponentValue(f, tname)) == NULL) { DXSetError(ERROR_DATA_INVALID, Err_MissingComp, tname, "der", cname); return ERROR; } if (DXGetObjectClass((Object)target) != CLASS_ARRAY) { DXSetError(ERROR_DATA_INVALID, Err_NotArray, tname, "der", cname); return ERROR; } } else if (DXExtractNthString(o, 0, &tname)) { /* string list? */ for (j=0; DXExtractNthString(o, j, &tname); j++) { if ((target = (Array)DXGetComponentValue(f, tname)) == NULL) { DXSetError(ERROR_DATA_INVALID, Err_MissingComp, tname, "der", cname); return ERROR; } if (DXGetObjectClass((Object)target) != CLASS_ARRAY) { DXSetError(ERROR_DATA_INVALID, Err_NotArray, tname, "der", cname); return ERROR; } } } else { /* neither string or string list */ DXSetError(ERROR_DATA_INVALID, Err_MustBeStringList, "der", cname); return ERROR; } } /* end of if (has der) */ /* element type */ if ((s = (String)DXGetAttribute((Object)current, "element type")) != NULL) { if ((DXGetObjectClass((Object)s) != CLASS_STRING) || ((tname = DXGetString(s)) == NULL)) { DXSetError(ERROR_DATA_INVALID, Err_MustBeString, "element type", cname); return ERROR; } if (!strcmp(cname, "connections") && DXQueryGridConnections(current, &rank, counts)) { if (!elemtypecheck(rank, tname)) return ERROR; } } /* end of if (has element type) */ } /* for each component in the field */ /* check for missing positions component if the field has more than * one component. */ if (i > 1 && !DXGetComponentValue(f, "positions")) DXWarning("importing a field with no `positions' component"); return OK; }
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 ); }
static int doLeaf(Object *in, Object *out) { int result=0; Field field; Category category; Category lookup_category; int rank, shape[30]; char *cat_comp; char *data_comp; char *lookup_comp; char name_str[256]; char *opstr; int operation; int lookup_knt; int lookup_knt_provided = 0; Array cat_array = NULL; Array data_array = NULL; Array out_array = NULL; Array array = NULL; Array lookup_array = NULL; float *out_data; int data_knt, cat_knt; int out_knt=0; Type cat_type, data_type, lookup_type; float floatmax; ICH invalid; if (DXGetObjectClass(in[0]) == CLASS_FIELD) { field = (Field)in[0]; if (DXEmptyField(field)) return OK; } if (!DXExtractString((Object)in[1], &opstr)) opstr = STR_COUNT; if (!strcmp(opstr, STR_COUNT)) operation = STAT_COUNT; else if (!strcmp(opstr, STR_MEAN)) operation = STAT_MEAN; else if (!strcmp(opstr, STR_SD)) operation = STAT_SD; else if (!strcmp(opstr, STR_VAR)) operation = STAT_VAR; else if (!strcmp(opstr, STR_MIN)) operation = STAT_MIN; else if (!strcmp(opstr, STR_MAX)) operation = STAT_MAX; else if (!strcmp(opstr, STR_ACCUM)) operation = STAT_ACCUM; else operation = STAT_UNDEF; if (operation == STAT_UNDEF) { DXSetError(ERROR_BAD_PARAMETER, "statistics operation must be one of: count, mean, sd, var, min, max"); goto error; } if (!DXExtractString((Object)in[2], &cat_comp)) cat_comp = STR_DATA; if (!DXExtractString((Object)in[3], &data_comp)) data_comp = STR_DATA; if (in[0]) { if (DXGetObjectClass(in[0]) != CLASS_FIELD) { DXSetError(ERROR_BAD_CLASS, "\"input\" should be a field"); goto error; } cat_array = (Array)DXGetComponentValue((Field)in[0], cat_comp); if (! cat_array) { DXSetError(ERROR_MISSING_DATA, "\"input\" has no \"%s\" categorical component", cat_comp); goto error; } if (DXGetObjectClass((Object)cat_array) != CLASS_ARRAY) { DXSetError(ERROR_BAD_CLASS, "categorical component \"%s\" of \"input\" should be an array", cat_comp); goto error; } if (!HasInvalid((Field)in[0], cat_comp, &invalid)) { DXSetError(ERROR_INTERNAL, "Bad invalid component"); goto error; } if (invalid) { DXSetError(ERROR_DATA_INVALID, "categorical component must not contain invalid data"); goto error; } DXGetArrayInfo(cat_array, &cat_knt, &cat_type, &category, &rank, shape); if ( (cat_type != TYPE_BYTE && cat_type != TYPE_UBYTE && cat_type != TYPE_INT && cat_type != TYPE_UINT) || category != CATEGORY_REAL || !((rank == 0) || ((rank == 1)&&(shape[0] == 1)))) { DXSetError(ERROR_DATA_INVALID, "categorical component %s must be scalar non-float", cat_comp); goto error; } if (operation != STAT_COUNT) { data_array = (Array)DXGetComponentValue((Field)in[0], data_comp); if (! data_array) { DXSetError(ERROR_MISSING_DATA, "\"input\" has no \"%s\" data component", data_comp); goto error; } if (DXGetObjectClass((Object)data_array) != CLASS_ARRAY) { DXSetError(ERROR_BAD_CLASS, "data component \"%s\" of \"input\" should be an array", data_comp); goto error; } DXGetArrayInfo(data_array, &data_knt, &data_type, &category, &rank, shape); if ( (data_type != TYPE_BYTE && data_type != TYPE_UBYTE && data_type != TYPE_INT && data_type != TYPE_UINT && data_type != TYPE_FLOAT && data_type != TYPE_DOUBLE) || category != CATEGORY_REAL || !((rank == 0) || ((rank == 1)&&(shape[0] == 1)))) { DXSetError(ERROR_DATA_INVALID, "data component \"%s\" must be scalar", data_comp); goto error; } if (data_knt != cat_knt) { DXSetError(ERROR_DATA_INVALID, "category and data counts must be the same"); goto error; } } } if (in[4]) { if (DXExtractString((Object)in[4], &lookup_comp)) { lookup_array = (Array)DXGetComponentValue((Field)in[0], lookup_comp); if (!lookup_array) { DXSetError(ERROR_MISSING_DATA, "\"input\" has no \"%s\" lookup component", lookup_comp); goto error; } } else if (DXExtractInteger((Object)in[4], &lookup_knt)) { lookup_knt_provided = 1; out_knt = lookup_knt; } else if (DXGetObjectClass((Object)in[4]) == CLASS_ARRAY) { lookup_array = (Array)in[4]; sprintf(name_str, "%s lookup", cat_comp); lookup_comp = name_str; } else { DXSetError(ERROR_DATA_INVALID, "lookup component must be string, integer, or array"); goto error; } } else { sprintf(name_str, "%s lookup", cat_comp); lookup_comp = name_str; lookup_array = (Array)DXGetComponentValue((Field)in[0], lookup_comp); } if (lookup_array) { DXGetArrayInfo(lookup_array, &lookup_knt, &lookup_type, &lookup_category, &rank, shape); out_knt = lookup_knt; } else if (!lookup_knt_provided){ if (!DXStatistics((Object)in[0], cat_comp, NULL, &floatmax, NULL, NULL)) { DXSetError(ERROR_INTERNAL, "Bad statistics on categorical component"); goto error; } out_knt = (int)(floatmax+1.5); } out_array = DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 0); if (! out_array) goto error; if (! DXSetAttribute((Object)out_array, "dep", (Object)DXNewString("positions"))) goto error; if (! DXAddArrayData(out_array, 0, out_knt, NULL)) goto error; if (out[0]) { if (DXGetObjectClass(out[0]) != CLASS_FIELD) { DXSetError(ERROR_INTERNAL, "non-field object found in output"); goto error; } if (DXGetComponentValue((Field)out[0], "data")) DXDeleteComponent((Field)out[0], "data"); if (! DXSetComponentValue((Field)out[0], "data", (Object)out_array)) goto error; if (lookup_array) { if (! DXSetComponentValue((Field)out[0], lookup_comp, (Object)lookup_array)) goto error; } } else { out[0] = (Object)DXNewField(); array = DXMakeGridPositions(1, out_knt, 0.0, 1.0); if (!array) goto error; DXSetComponentValue((Field)out[0], "positions", (Object)array); array = DXMakeGridConnections(1, out_knt); if (!array) goto error; DXSetComponentValue((Field)out[0], "connections", (Object)array); DXSetComponentValue((Field)out[0], "data", (Object)out_array); if (lookup_array) { if (! DXSetComponentValue((Field)out[0], lookup_comp, (Object)lookup_array)) goto error; } } out_data = DXGetArrayData(out_array); if (! out_data) goto error; result = CategoryStatistics_worker( out_data, cat_knt, out_knt, cat_array, data_array, cat_type, data_type, operation); if (! result) { if (DXGetError()==ERROR_NONE) DXSetError(ERROR_INTERNAL, "error return from user routine"); goto error; } result = (DXEndField((Field)out[0]) != NULL); error: return result; }
Error DXCallOutboard (PFE m, int dxfd) { static int firsttime = 1; Array oarr; int nin = 0; int nout = 0; Object *ilist = NULL; Object *olist = NULL; Error ret = ERROR; Error modret; ErrorCode ecode; char *emessptr = NULL; Group iobj = NULL; Group oobj = NULL; Array code = NULL; String mess = NULL; int i; int *iptr; int count = 0; int one = 1; int zero = 0; if (firsttime && ! callsetup (dxfd)) { host_status = HOST_CLOSED; return ERROR; } /* * Import the remote object, extract the number of inputs and outputs, * and rip them apart appropriately. group members are: * input parm count, * input object list (the pointers values don't mean anything in this * address space; the interesting part is whether they are NULL or not), * the output parm count, * and then each input object which isn't null. */ iobj = (Group) _dxfImportBin_FP(dxfd); if(iobj == NULL) goto finish_up; if (!DXExtractInteger (DXGetEnumeratedMember (iobj, 0, NULL), &nin)) goto finish_up; ilist = (Object *) DXAllocateZero(sizeof (Object) * nin); if (!ilist) goto finish_up; iptr = (int *)DXGetArrayData((Array)DXGetEnumeratedMember (iobj, 1, NULL)); if (!DXExtractInteger (DXGetEnumeratedMember (iobj, 2, NULL), &nout)) goto finish_up; count = 3; for (i=0; i<nin; i++) { if (iptr[i] == (int)NULL) continue; ilist[i] = DXGetEnumeratedMember(iobj, count++, NULL); } olist = (Object *) DXAllocateZero(sizeof (Object) * nout); if (!olist) goto finish_up; /* * Call the module, and save the error code if set. */ DXResetError(); _dxd_exOutboard = TRUE; modret = m (ilist, olist); _dxd_exOutboard = FALSE; /* * get these now, before we do something else which overwrites them. */ ecode = DXGetError (); emessptr = DXGetErrorMessage(); /* * now BEFORE we do anything which allocates memory or new objects * check the return objects for validity. we saw a case where the * object being returned was deleted, and then the DXNewGroup() * below got the exact same address allocated, so when we put the * group together we put a reference to the parent group into the * same group as a child. bad things followed... * * (the two calls above to geterror & geterrormsg don't allocate anything; * they return a value & ptr to a static respectively) */ for (i = 0; i < nout; i++) { if (olist[i] == NULL) continue; switch (DXGetObjectClass(olist[i])) { case CLASS_DELETED: case CLASS_MIN: case CLASS_MAX: if (ecode == ERROR_NONE) { DXSetError(ERROR_BAD_CLASS, "bad object returned as output %d from outboard module", i); ecode = DXGetError (); emessptr = DXGetErrorMessage(); } else DXAddMessage("bad object returned as output %d from outboard module", i); olist[i] = NULL; default: /* Lots of other classes */ break; } } /* * Set up for return, at least the return code and message. */ oobj = DXNewGroup (); if (oobj == NULL) goto finish_up; if (!(code = DXNewArray (TYPE_INT, CATEGORY_REAL, 0))) goto finish_up; if (! DXAddArrayData (code, 0, 1, (Pointer) &ecode)) goto finish_up; mess = DXNewString (emessptr); if (mess == NULL) goto finish_up; if (! DXSetEnumeratedMember (oobj, 0, (Object) code) || ! DXSetEnumeratedMember (oobj, 1, (Object) mess)) goto finish_up; /* * If everything is OK then go ahead and return any objects too. */ if (modret == OK) { /* send output list so the caller can tell which outputs * were set. only send the non-NULL ones. */ oarr = DXNewArray(TYPE_INT, CATEGORY_REAL, 0); if (!oarr) goto finish_up; for (i = 0; i < nout; i++) { if (! DXAddArrayData(oarr, i, 1, (olist+i) ? (Pointer)&one : (Pointer)&zero)) goto finish_up; } if (! DXSetEnumeratedMember(oobj, 2, (Object)oarr)) goto finish_up; count = 3; for (i = 0; i < nout; i++) { if (olist[i] == NULL) continue; if (! DXSetEnumeratedMember (oobj, count++, olist[i])) goto finish_up; } } if (!_dxfExportBin_FP ((Object)oobj, dxfd)) goto finish_up; /* * if you get to this point, there were no other errors. */ ret = OK; finish_up: /* * get rid of space not needed anymore. this doesn't matter for * one-shots, but for persistent modules we will run out of memory * eventually if these aren't deleted. */ DXDelete ((Object) iobj); DXDelete ((Object) oobj); DXFree ((Pointer) ilist); DXFree ((Pointer) olist); return ret; }