/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ #include #include #include #include #include /* * output = Inquire(input, what, value ...); */ /* misc worker routines */ static char *article(char first) { if (first == 'a' || first == 'e' || first == 'i' || first == 'o' || first == 'u') return "an"; return "a"; } #define CHECKIF(o, class, name) \ if (DXGetObjectClass(o) != class) { \ DXSetError(ERROR_INVALID_DATA, "#10371", \ "input", article(name[0]), name); \ return NULL; \ } #define CHECKIF2(o, class, name, class2, name2) \ if (DXGetObjectClass(o) != class && DXGetObjectClass(o) != class2) { \ DXSetError(ERROR_INVALID_DATA, "#10372", \ "input", article(name[0]), name, article(name2[0]), name2);\ return NULL; \ } #define CHECKARRAYIF(o, class, name) \ if (DXGetArrayClass((Array)o) != class) { \ DXSetError(ERROR_INVALID_DATA, "#10371", \ "input", article(name[0]), name); \ return NULL; \ } #define CHECKGROUPIF(o, class, name) \ if (DXGetGroupClass((Group)o) != class) { \ DXSetError(ERROR_INVALID_DATA, "#10371", \ "input", article(name[0]), name); \ return NULL; \ } /* return all fields which aren't empty. */ static Field getpartplus(Object o, int *i, int *count) { int again = 1; Field f; while (again) { f = DXGetPart(o, *i); if (!f) return NULL; (*i)++; if (DXEmptyField(f)) continue; (*count)++; return f; } /* not reached */ return NULL; } /* should be libdx routine */ static Error DXGetComponentCount(Field f, int *i) { *i = 0; while (DXGetEnumeratedComponentValue(f, *i, NULL)) *i++; return OK; } static Object packit(int n, Type t, Category c, int rank, int *shape, Pointer p) { Array a = NULL; a = DXNewArrayV(t, c, rank, shape); if (!a) return NULL; if (!DXAddArrayData(a, 0, n, p)) { DXDelete((Object)a); return NULL; } return (Object)a; } static Object packint(int i) { return packit(1, TYPE_INT, CATEGORY_REAL, 0, NULL, (Pointer)&i); } static Object packfloat(float f) { return packit(1, TYPE_FLOAT, CATEGORY_REAL, 0, NULL, (Pointer)&f); } static Object packintlist(int n, int *i) { return packit(n, TYPE_INT, CATEGORY_REAL, 0, NULL, (Pointer)i); } static Object packfloatlist(int n, float *f) { return packit(n, TYPE_FLOAT, CATEGORY_REAL, 0, NULL, (Pointer)f); } static Object packintvect(int len, int *i) { return packit(1, TYPE_INT, CATEGORY_REAL, 1, &len, (Pointer)i); } static Object packfloatvect(int len, float *f) { return packit(1, TYPE_FLOAT, CATEGORY_REAL, 1, &len, (Pointer)f); } static Object packintvectlist(int n, int len, int *i) { return packit(n, TYPE_INT, CATEGORY_REAL, 1, &len, (Pointer)i); } static Object packfloatvectlist(int n, int len, float *f) { return packit(n, TYPE_FLOAT, CATEGORY_REAL, 1, &len, (Pointer)f); } static Object packfloatmat(int x, int y, float *f) { int shape[2]; shape[0] = x; shape[1] = y; return packit(1, TYPE_FLOAT, CATEGORY_REAL, 2, shape, (Pointer)f); } static Object packstring(char *cp) { return (Object)DXNewString(cp); } /* yes/no question routines */ static int qnull(Object o) { return (o ? 0 : 1); } static int qregp(Object o) { int i, j; Field f; for (i=0, j=0; f=getpartplus(o, &i, &j); ) { if (!DXQueryGridPositions ((Array) DXGetComponentValue(f, "positions"), NULL, NULL, NULL, NULL)) return 0; } return (j > 0) ? 1 : 0; } static int qregc(Object o) { int i, j; Field f; for (i=0, j=0; f=getpartplus(o, &i, &j); ) { if (!DXQueryGridConnections ((Array) DXGetComponentValue(f, "connections"), NULL, NULL)) return 0; } return (j > 0) ? 1 : 0; } static int qreg(Object o, Object compname) { int i, j; char *on; Field f; Array a; if (!compname) return (qregp(o) && qregc(o)); if (!DXExtractString(compname, &on)) return 0; for (i=0, j=0; f=getpartplus(o, &i, &j); ) { if (!(a = (Array)DXGetComponentValue(f, on))) return 0; switch (DXGetArrayClass(a)) { case CLASS_PRODUCTARRAY: if (DXQueryGridPositions(a, NULL, NULL, NULL, NULL) == NULL) return 0; break; case CLASS_MESHARRAY: if (DXQueryGridConnections(a, NULL, NULL) == NULL) return 0; break; default: return 0; } } return (j > 0) ? 1 : 0; } static int qNdgp(Object o, char *cn) { int i, j; Field f; int n; int rank; n = atoi(cn); for (i=0, j=0; f=getpartplus(o, &i, &j); ) { if (!DXQueryGridPositions ((Array) DXGetComponentValue(f, "positions"), &rank, NULL, NULL, NULL)) return 0; if (rank != n) return 0; } return (j > 0) ? 1 : 0; } static int qNdgc(Object o, char *cn) { int i, j; Field f; int n; int rank; n = atoi(cn); for (i=0, j=0; f=getpartplus(o, &i, &j); ) { if (!DXQueryGridConnections ((Array) DXGetComponentValue(f, "connections"), &rank, NULL)) return 0; if (rank != n) return 0; } return (j > 0) ? 1 : 0; } static int qNdp(Object o, char *cn) { int i, j; Field f; int n; int rank, shape; Object pos; n = atoi(cn); for (i=0, j=0; f=getpartplus(o, &i, &j); ) { pos = DXGetComponentValue(f, "positions"); if (!pos) return 0; if (DXGetObjectClass(pos) != CLASS_ARRAY) return 0; if (!DXGetArrayInfo((Array)pos, NULL, NULL, NULL, &rank, NULL)) return 0; if (rank != 1) return 0; if (!DXGetArrayInfo((Array)pos, NULL, NULL, NULL, &rank, &shape)) return 0; if (n != shape) return 0; } return (j > 0) ? 1 : 0; } static int qNdc(Object o, char *cn) { int i, j; Field f; int n; char *cp; Object con; n = atoi(cn); for (i=0, j=0; f=getpartplus(o, &i, &j); ) { if (!(con = DXGetComponentValue(f, "connections"))) return 0; if (DXGetObjectClass(con) != CLASS_ARRAY) return 0; if (!DXGetStringAttribute(con, "element type", &cp)) return 0; if (!strcmp(cp, "lines") && (n != 1)) return 0; if ((!strcmp(cp, "triangles") || !strcmp(cp, "quads")) && (n != 2)) return 0; if ((!strcmp(cp, "tetrahedra") || !strcmp(cp, "cubes")) && (n != 3)) return 0; } return (j > 0) ? 1 : 0; } static int qNdd(Object o, char *cn) { int i, j, n; int rank; Field f; Object data; n = atoi(cn); if (DXGetObjectClass(o) == CLASS_ARRAY) { if (!DXGetArrayInfo((Array)o, NULL, NULL, NULL, &rank, NULL)) return 0; if (n != rank) return 0; return 1; } for (i=0, j=0; f=getpartplus(o, &i, &j); ) { if (!(data = DXGetComponentValue(f, "data"))) return 0; if (DXGetObjectClass(data) != CLASS_ARRAY) return 0; if (!DXGetArrayInfo((Array)data, NULL, NULL, NULL, &rank, NULL)) return 0; if (n != rank) return 0; } return (j > 0) ? 1 : 0; } static int q1dNd(Object o, char *cn) { int i, j, n; int rank, shape; Field f; Object data; n = atoi(cn); if (DXGetObjectClass(o) == CLASS_ARRAY) { if (!DXGetArrayInfo((Array)o, NULL, NULL, NULL, &rank, NULL)) return 0; if (rank != 1) return 0; if (!DXGetArrayInfo((Array)o, NULL, NULL, NULL, &rank, &shape)) return 0; if (n != shape) return 0; return 1; } for (i=0, j=0; f=getpartplus(o, &i, &j); ) { if (!(data = DXGetComponentValue(f, "data"))) return 0; if (DXGetObjectClass(data) != CLASS_ARRAY) return 0; if (!DXGetArrayInfo((Array)data, NULL, NULL, NULL, &rank, NULL)) return 0; if (rank != 1) return 0; if (!DXGetArrayInfo((Array)data, NULL, NULL, NULL, &rank, &shape)) return 0; if (n != shape) return 0; } return (j > 0) ? 1 : 0; } static int qdatadep(Object o, Object on) { int i, j; Field f; Object data; char *dep = NULL; char *attrvalue = NULL; for (i=0, j=0; f=getpartplus(o, &i, &j); ) { if (!(data = DXGetComponentValue(f, "data"))) return 0; if (!on) return 0; /* extract string from 'on' here */ if (!DXExtractString(on, &dep)) return 0; if (!DXGetStringAttribute(data, "dep", &attrvalue)) return 0; if (strcmp(attrvalue, dep)) return 0; } return (j > 0) ? 1 : 0; } static int qdatatype(Object o, Type t) { int i, j; Field f; Type dt; if (DXGetObjectClass(o) == CLASS_ARRAY) { if (!DXGetType(o, &dt, NULL, NULL, NULL)) return 0; if (dt != t) return 0; return 1; } for (i=0, j=0; f=getpartplus(o, &i, &j); ) { if (!DXGetType((Object)f, &dt, NULL, NULL, NULL)) return 0; if (dt != t) return 0; } return (j > 0) ? 1 : 0; } static int qbyte(Object o) { return qdatatype(o, TYPE_UBYTE); } static int qshort(Object o) { return qdatatype(o, TYPE_SHORT); } static int qint(Object o) { return qdatatype(o, TYPE_INT); } static int qfloat(Object o) { return qdatatype(o, TYPE_FLOAT); } static int qdouble(Object o) { return qdatatype(o, TYPE_DOUBLE); } static int qobjtype(Object o, char *match) { switch (DXGetObjectClass(o)) { case CLASS_OBJECT: return !strcmp(match, "object"); case CLASS_PRIVATE: return !strcmp(match, "private"); case CLASS_STRING: return !strcmp(match, "string"); case CLASS_FIELD: return !strcmp(match, "field"); case CLASS_GROUP: return !strcmp(match, "group"); case CLASS_ARRAY: return !strcmp(match, "array"); case CLASS_XFORM: return !strcmp(match, "xform"); case CLASS_SCREEN: return !strcmp(match, "screen"); case CLASS_CLIPPED: return !strcmp(match, "clipped"); case CLASS_CAMERA: return !strcmp(match, "camera"); case CLASS_LIGHT: return !strcmp(match, "light"); default: return 0; } /* notreached */ } static int qobjgtype(Object o, char *match) { switch (DXGetObjectClass(o)) { case CLASS_GROUP: switch (DXGetGroupClass((Group)o)) { case CLASS_SERIES: return !strcmp(match, "series"); case CLASS_COMPOSITEFIELD: return !strcmp(match, "compositefield"); case CLASS_MULTIGRID: return !strcmp(match, "multigrid"); case CLASS_GROUP: return !strcmp(match, "group"); default: return 0; } default: return 0; } /* notreached */ } static int qobjatype(Object o, char *match) { switch (DXGetObjectClass(o)) { case CLASS_ARRAY: switch (DXGetArrayClass((Array)o)) { case CLASS_ARRAY: return !strcmp(match, "array"); case CLASS_REGULARARRAY: return !strcmp(match, "regulararray"); case CLASS_PATHARRAY: return !strcmp(match, "patharray"); case CLASS_PRODUCTARRAY: return !strcmp(match, "productarray"); case CLASS_MESHARRAY: return !strcmp(match, "mesharray"); case CLASS_CONSTANTARRAY: return !strcmp(match, "constantarray"); default: return 0; } default: return 0; } /* notreached */ } /* not called -- don't know what the inquire string should be yet */ static int qhasdata(Object o) { Object child = NULL; int i; switch (DXGetObjectClass(o)) { case CLASS_FIELD: return DXEmptyField((Field)o); case CLASS_GROUP: for (i=0; child = DXGetEnumeratedMember((Group)o, i, NULL); i++) { if (!qhasdata(child)) return 0; } return 1; case CLASS_SCREEN: if (!DXGetScreenInfo((Screen)o, &child, NULL, NULL)) return 1; return qhasdata(o); case CLASS_CLIPPED: if (!DXGetClippedInfo((Clipped)o, &child, NULL)) return 1; return qhasdata(o); case CLASS_XFORM: if (!DXGetXformInfo((Xform)o, &child, NULL)) return 1; return qhasdata(o); default: return 1; } /* notreached */ } static int qobjempty(Object o, char *what) { Object child = NULL; int i; switch (DXGetObjectClass(o)) { case CLASS_FIELD: if (what && what[0] && what[0] != 'f') return 0; return DXEmptyField ((Field)o) ? 1 : 0; case CLASS_GROUP: if (what && what[0] && what[0] != 'g') return 0; if (!DXGetMemberCount ((Group)o, &i)) return 0; if (i > 0) return 0; return 1; case CLASS_ARRAY: if (what && what[0] && what[0] != 'a') return 0; if (!DXGetArrayInfo ((Array)o, &i, NULL, NULL, NULL, NULL)) return 0; if (i > 0) return 0; return 1; case CLASS_SCREEN: if (!DXGetScreenInfo ((Screen)o, &child, NULL, NULL)) return 1; return qobjempty(o, what); case CLASS_CLIPPED: if (!DXGetClippedInfo ((Clipped)o, &child, NULL)) return 1; return qobjempty(o, what); case CLASS_XFORM: if (!DXGetXformInfo ((Xform)o, &child, NULL)) return 1; return qobjempty(o, what); default: return 0; } /* notreached */ } static int qhascomp(Object o, Object name) { char *str = NULL; CHECKIF(o, CLASS_FIELD, "field"); /* component name you are checking for */ if (!DXExtractString(name, &str)) return 0; if (!DXGetComponentValue((Field)o, str)) return 0; return 1; } static int qhasattr(Object o, Object name) { char *str = NULL; /* component name you are checking for */ if (!DXExtractString(name, &str)) return 0; if (!DXGetAttribute(o, str)) return 0; return 1; } static int qhasmember(Object o, Object name) { char *str = NULL; CHECKIF(o, CLASS_GROUP, "group"); /* member name you are checking for */ if (!DXExtractString(name, &str)) return 0; if (!DXGetMember((Group)o, str)) return 0; return 1; } static int qequal(Object o, Object name) { char *input = NULL; char *target = NULL; /* target string you want to match */ if (!DXExtractString(name, &target)) return 0; /* input object string */ if (!DXExtractString(o, &input)) return 0; if (strcmp(input, target)) return 0; return 1; } static int qsame(Object o, Object same) { return (o == same) ? 1 : 0; } static int qimage(Object o) { int n; Array a; char *s; /* an image has got to be a field or a composite field */ if (DXGetObjectClass(o) != CLASS_FIELD) { if (DXGetObjectClass(o) != CLASS_GROUP) return 0; if (DXGetGroupClass((Group)o) != CLASS_COMPOSITEFIELD) return 0; o = DXGetEnumeratedMember((Group)o, 0, NULL); } /* check to see if it's the right shape, etc */ /* check positions */ a = (Array) DXGetComponentValue((Field)o, "positions"); if (!a || !DXQueryGridPositions(a, &n, NULL, NULL, NULL) || n!=2) return 0; /* check connections */ a = (Array) DXGetComponentValue((Field)o, "connections"); if (!a || !DXQueryGridConnections(a, &n, NULL) || n!=2) return 0; /* is there a colors component */ a = (Array) DXGetComponentValue((Field)o, "colors"); if (!a) return 0; /* check dep */ s = DXGetString((String)DXGetAttribute((Object)a, "dep")); if (s && strcmp(s, "positions")) return 0; return 1; } static int qiscontype(Object o, Object name) { int i, j; Field f; char *etype, *match; Object con; /* target string you want to match */ if (!DXExtractString(name, &match)) return 0; for (i=0, j=0; f=getpartplus(o, &i, &j); ) { if (!(con = DXGetComponentValue(f, "connections"))) return 0; if (!DXGetStringAttribute(con, "element type", &etype)) return 0; return !strcmp(etype, match); } return 0; } /* information routines */ static Object qcount(Object o) { int nitems; CHECKIF(o, CLASS_ARRAY, "array"); if (!DXGetArrayInfo((Array)o, &nitems, NULL, NULL, NULL, NULL)) return NULL; return packint(nitems); } static Object qgcount(Object o) { int rank; int *counts = NULL; Array a = (Array)o; Object answer = NULL; CHECKIF(o, CLASS_ARRAY, "array"); switch (DXGetArrayClass(a)) { case CLASS_PRODUCTARRAY: if (!DXQueryGridPositions(a, &rank, NULL, NULL, NULL)) goto notreg; counts = (int *)DXAllocate(rank * sizeof(int)); if (!counts) return NULL; DXQueryGridPositions(a, &rank, counts, NULL, NULL); answer = packintvect(rank, counts); if (!answer) goto notreg; DXFree((Pointer)counts); return answer; case CLASS_MESHARRAY: if (!DXQueryGridConnections(a, &rank, NULL)) goto notreg; counts = (int *)DXAllocate(rank * sizeof(int)); if (!counts) return NULL; DXQueryGridConnections(a, &rank, counts); answer = packintvect(rank, counts); if (!answer) goto notreg; DXFree((Pointer)counts); return answer; } notreg: DXSetError(ERROR_INVALID_DATA, "not regular grid"); return NULL; } static Object qtype(Object o) { Type t; char *cp = "unknown"; CHECKIF(o, CLASS_ARRAY, "array"); if (!DXGetArrayInfo((Array)o, NULL, &t, NULL, NULL, NULL)) return NULL; switch (t) { case TYPE_BYTE: cp = "signed byte"; break; case TYPE_UBYTE: cp = "unsigned byte"; break; case TYPE_SHORT: cp = "short"; break; case TYPE_USHORT: cp = "unsigned short"; break; case TYPE_INT: cp = "integer"; break; case TYPE_UINT: cp = "unsigned integer"; break; case TYPE_FLOAT: cp = "float"; break; case TYPE_DOUBLE: cp = "double"; break; case TYPE_STRING: cp = "string"; break; } return packstring(cp); } static Object qcat(Object o) { Category cat; char *cp = "unknown"; CHECKIF(o, CLASS_ARRAY, "array"); if (!DXGetArrayInfo((Array)o, NULL, NULL, &cat, NULL, NULL)) return NULL; switch (cat) { case CATEGORY_REAL: cp = "real"; break; case CATEGORY_COMPLEX: cp = "complex"; break; case CATEGORY_QUATERNION: cp = "quaternion"; break; } return packstring(cp); } static Object qrank(Object o) { int rank; CHECKIF(o, CLASS_ARRAY, "array"); if (!DXGetArrayInfo((Array)o, NULL, NULL, NULL, &rank, NULL)) return NULL; return packint(rank); } static Object qshape(Object o) { int rank; int *shape = NULL; Object answer = NULL; CHECKIF(o, CLASS_ARRAY, "array"); if (!DXGetArrayInfo((Array)o, NULL, NULL, NULL, &rank, NULL)) return NULL; shape = (int *)DXAllocate(rank * sizeof(int)); if (!shape) return NULL; if (!DXGetArrayInfo((Array)o, NULL, NULL, NULL, &rank, shape)) return NULL; answer = packintvect(rank, shape); if (!answer) goto error; DXFree((Pointer)shape); return answer; error: DXDelete(answer); DXFree((Pointer)shape); return NULL; } static Object qitems(Object o, char *component) { Object comp; CHECKIF(o, CLASS_FIELD, "field"); if (!(comp = DXGetComponentValue((Field)o, component))) { DXSetError(ERROR_INVALID_DATA, "#10258", "input", component); return NULL; } return qcount(comp); } static Object qpos(Object o) { return qitems(o, "positions"); } static Object qconnect(Object o) { return qitems(o, "connections"); } static Object qdata(Object o) { return qitems(o, "data"); } static Object qcompsize(Object o, Object compname) { char *on; if (!compname) { if (DXGetObjectClass(o) == CLASS_FIELD) return qitems(o, "data"); else return qcount(o); } if (!DXExtractString(compname, &on)) { DXSetError(ERROR_BAD_PARAMETER, "#10200", "component name"); return NULL; } return qitems(o, on); } static Object qgriditems(Object o, char *component) { Object comp; CHECKIF(o, CLASS_FIELD, "field"); if (!(comp = DXGetComponentValue((Field)o, component))) { DXSetError(ERROR_INVALID_DATA, "#10258", "input", component); return NULL; } return qgcount(comp); } static Object qcompgridsize(Object o, Object compname) { char *on; if (!compname) return qgcount(o); if (!DXExtractString(compname, &on)) { DXSetError(ERROR_BAD_PARAMETER, "#10200", "component name"); return NULL; } return qgriditems(o, on); } static Object qcgridsize(Object o) { int rank; int *counts = NULL; Array a; Object answer = NULL; CHECKIF(o, CLASS_FIELD, "field"); if (!(a = (Array)DXGetComponentValue((Field)o, "connections"))) { DXSetError(ERROR_INVALID_DATA, "#10258", "input", "connections"); return NULL; } if (!DXQueryGridConnections(a, &rank, NULL)) { DXSetError(ERROR_INVALID_DATA, "input does not have regular connections"); return NULL; } counts = (int *)DXAllocate(rank * sizeof(int)); if (!counts) return NULL; DXQueryGridConnections(a, &rank, counts); answer = packintvect(rank, counts); if (!answer) goto error; DXFree((Pointer)counts); return answer; error: DXDelete(answer); DXFree((Pointer)counts); return NULL; } static Object qpgridsize(Object o) { int rank; int *counts = NULL; Array a; Object answer = NULL; CHECKIF(o, CLASS_FIELD, "field"); if (!(a = (Array)DXGetComponentValue((Field)o, "positions"))) { DXSetError(ERROR_INVALID_DATA, "#10258", "input", "positions"); return NULL; } if (!DXQueryGridPositions(a, &rank, NULL, NULL, NULL)) { DXSetError(ERROR_INVALID_DATA, "input does not have regular positions"); return NULL; } counts = (int *)DXAllocate(rank * sizeof(int)); if (!counts) return NULL; DXQueryGridPositions(a, &rank, counts, NULL, NULL); answer = packintvect(rank, counts); if (!answer) goto error; DXFree((Pointer)counts); return answer; error: DXDelete(answer); DXFree((Pointer)counts); return NULL; } static Object qorigin(Object o) { int rank; float *origin = NULL; Pointer anyorigin = NULL; Array a; Type type; Object answer = NULL; CHECKIF2(o, CLASS_FIELD, "field", CLASS_ARRAY, "regular array"); switch (DXGetObjectClass(o)) { case CLASS_FIELD: if (!(a = (Array)DXGetComponentValue((Field)o, "positions"))) { DXSetError(ERROR_INVALID_DATA, "#10258", "input", "positions"); return NULL; } if (!DXQueryGridPositions(a, &rank, NULL, NULL, NULL)) { DXSetError(ERROR_INVALID_DATA, "input does not have regular positions"); return NULL; } origin = (float *)DXAllocate(rank * sizeof(float)); if (!origin) return NULL; DXQueryGridPositions(a, &rank, NULL, origin, NULL); answer = packfloatvect(rank, origin); if (!answer) goto error; DXFree((Pointer)origin); return answer; case CLASS_ARRAY: if (DXGetArrayClass((Array)o) != CLASS_REGULARARRAY) { DXSetError(ERROR_INVALID_DATA, "#10372", "input", "a", "field", "a", "regular array"); return NULL; } a = (Array)o; if (!DXGetArrayInfo(a, NULL, &type, NULL, NULL, &rank)) /* really shape */ return NULL; anyorigin = DXAllocate(rank * DXTypeSize(type)); if (!anyorigin) return NULL; DXGetRegularArrayInfo((RegularArray)a, NULL, anyorigin, NULL); answer = (Object)DXNewArrayV(type, CATEGORY_REAL, 1, &rank); if (!answer) goto error; if (!DXAddArrayData((Array)answer, 0, 1, anyorigin)) goto error; DXFree((Pointer)anyorigin); return answer; default: DXSetError(ERROR_INVALID_DATA, "input must be a field or regular array"); return NULL; } error: DXDelete(answer); DXFree((Pointer)origin); DXFree(anyorigin); return NULL; } static Object qdeltas(Object o) { int rank; float *deltas = NULL; Pointer anydeltas = NULL; Array a; Type type; Object answer = NULL; CHECKIF2(o, CLASS_FIELD, "field", CLASS_ARRAY, "regular array"); switch (DXGetObjectClass(o)) { case CLASS_FIELD: if (!(a = (Array)DXGetComponentValue((Field)o, "positions"))) { DXSetError(ERROR_INVALID_DATA, "#10258", "input", "positions"); return NULL; } if (!DXQueryGridPositions(a, &rank, NULL, NULL, NULL)) { DXSetError(ERROR_INVALID_DATA, "input does not have regular positions"); return NULL; } deltas = (float *)DXAllocate(rank * rank * sizeof(float)); if (!deltas) return NULL; DXQueryGridPositions(a, &rank, NULL, NULL, deltas); answer = packfloatvectlist(rank, rank, deltas); if (!answer) goto error; DXFree((Pointer)deltas); return answer; case CLASS_ARRAY: if (DXGetArrayClass((Array)o) != CLASS_REGULARARRAY) { DXSetError(ERROR_INVALID_DATA, "#10372", "input", "a", "field", "a", "regular array"); return NULL; } a = (Array)o; if (!DXGetArrayInfo(a, NULL, &type, NULL, NULL, &rank)) /* really shape */ return NULL; anydeltas = DXAllocate(rank * DXTypeSize(type)); if (!anydeltas) return NULL; DXGetRegularArrayInfo((RegularArray)a, NULL, NULL, anydeltas); answer = (Object)DXNewArrayV(type, CATEGORY_REAL, 1, &rank); if (!answer) goto error; if (!DXAddArrayData((Array)answer, 0, 1, anydeltas)) goto error; DXFree((Pointer)anydeltas); return answer; default: DXSetError(ERROR_INVALID_DATA, "input must be a field or regular array"); return NULL; } error: DXDelete(answer); DXFree((Pointer)deltas); DXFree(anydeltas); return NULL; } static Object qprodterms(Object o) { int i, count; Group g = NULL; Array *terms = NULL; CHECKARRAYIF(o, CLASS_PRODUCTARRAY, "product array"); if (!DXGetProductArrayInfo((ProductArray)o, &count, NULL)) return NULL; terms = (Array *)DXAllocate(count * sizeof(Array)); if (!terms) return NULL; if (!DXGetProductArrayInfo((ProductArray)o, &count, terms)) goto error; g = DXNewGroup(); if (!g) goto error; for (i=0; i < count; i++) if (!DXSetMember(g, NULL, (Object)terms[i])) goto error; DXFree((Pointer)terms); return (Object)g; error: DXFree((Pointer)terms); DXDelete((Object)g); return NULL; } static Object qmeshterms(Object o) { int i, count; Group g = NULL; Array *terms = NULL; CHECKARRAYIF(o, CLASS_MESHARRAY, "mesh array"); if (!DXGetMeshArrayInfo((MeshArray)o, &count, NULL)) return NULL; terms = (Array *)DXAllocate(count * sizeof(Array)); if (!terms) return NULL; if (!DXGetMeshArrayInfo((MeshArray)o, &count, terms)) goto error; g = DXNewGroup(); if (!g) goto error; for (i=0; i < count; i++) if (!DXSetMember(g, NULL, (Object)terms[i])) goto error; DXFree((Pointer)terms); return (Object)g; error: DXFree((Pointer)terms); DXDelete((Object)g); return NULL; } static Object qcompcount(Object o) { int i; CHECKIF(o, CLASS_FIELD, "field"); for (i=0; DXGetEnumeratedComponentValue((Field)o, i, NULL); i++) ; return packint(i); } static Object qmembers(Object o) { int i; CHECKIF(o, CLASS_GROUP, "group"); if (!DXGetMemberCount((Group)o, &i)) return NULL; return packint(i); } static Object qmembernames(Object o, char *type) { int i = 0; char **cp = NULL; Array a; if (type[0] == 'c') { CHECKIF(o, CLASS_FIELD, "field"); } else if (type[0] == 'm') { CHECKIF(o, CLASS_GROUP, "group"); } switch (DXGetObjectClass(o)) { case CLASS_GROUP: if (!DXGetMemberCount((Group)o, &i)) return NULL; cp = (char **)DXAllocate(sizeof(char *) * (i+1)); if (!cp) return NULL; for (i=0; DXGetEnumeratedMember((Group)o, i, cp+i); i++) ; break; case CLASS_FIELD: for (i=0; DXGetEnumeratedComponentValue((Field)o, i, NULL); i++) ; cp = (char **)DXAllocate(sizeof(char *) * (i+1)); if (!cp) return NULL; for (i=0; DXGetEnumeratedComponentValue((Field)o, i, cp+i); i++) ; break; default: DXSetError(ERROR_INVALID_DATA, "input is not a field or group"); return NULL; } if (i == 0) a = DXMakeStringList(1, " "); else a = DXMakeStringListV(i, cp); DXFree((Pointer)cp); return (Object)a; } static Object qmemberpos(Object o) { int i = 0; float *pos = NULL; Object answer = NULL; CHECKGROUPIF(o, CLASS_SERIES, "series group"); if (!DXGetMemberCount((Group)o, &i) || i <= 0) return NULL; pos = (float *)DXAllocate(sizeof(float) * (i+1)); if (!pos) return NULL; for (i=0; DXGetSeriesMember((Series)o, i, pos+i); i++) ; answer = packfloatlist(i, pos); DXFree((Pointer)pos); return answer; } static Object qvalid(Object o, char *type) { int icount = 0; Array data = NULL; char *dep = NULL; char *invalid = NULL; InvalidComponentHandle ih; CHECKIF(o, CLASS_FIELD, "field"); data = (Array)DXGetComponentValue((Field)o, "data"); if (!data) return packint(icount); /* follow data dependency. */ if (!DXGetStringAttribute((Object)data, "dep", &dep)) return packint(icount); #define INVLEN 10 /* strlen("invalid "); */ if (!(invalid = (char *)DXAllocate(strlen(dep) + INVLEN))) return ERROR; strcpy(invalid, "invalid "); strcat(invalid, dep); /* if no invalid component, all valid */ if (!DXGetComponentValue((Field)o, invalid)) { DXFree((Pointer)invalid); if (type[0] == 'i') return packint(icount); else return qcount((Object)data); } DXFree((Pointer)invalid); ih = DXCreateInvalidComponentHandle(o, NULL, dep); if (!ih) return packint(icount); if (type[0] == 'i') icount = DXGetInvalidCount(ih); else icount = DXGetValidCount(ih); DXFreeInvalidComponentHandle(ih); return packint(icount); } static Object qcontype(Object o) { int i, j; Field f; Object con, etype; for (i=0, j=0; f=getpartplus(o, &i, &j); ) { if (!(con = DXGetComponentValue(f, "connections"))) return NULL; return DXGetAttribute(con, "element type"); } return NULL; } static Object qnumprocess(Object o) { return packint(DXProcessors(0)); } /* return a string which contains the number of each type of primitive * (connection) in the input object. */ static Object qprimitives(Object o) { Object rc = NULL; int i, j; Field f; int items; char *elem_type; char **ccp = NULL; Array a; struct pc { char con_name[64]; int con_count; char con_total[64]; struct pc *next; } *pcp, *pcp2; pcp = NULL; /* for each field in the input... */ for (i=0, j=0; f=getpartplus(o, &i, &j); ) { /* find out how many connection items there are. * if there is no connections array, then these * must be unconnected points. */ a = (Array)DXGetComponentValue(f, "connections"); if (!a) { elem_type = "points"; a = (Array)DXGetComponentValue(f, "positions"); if (!a) continue; } else if (!DXGetStringAttribute((Object)a, "element type", &elem_type)) elem_type = "unknown"; if (!DXGetArrayInfo(a, &items, NULL, NULL, NULL, NULL)) continue; /* now try to find this connection type in the list. if there * isn't a list yet, or this type doesn't exist, add a new block * to the linked list. */ if (!pcp) { pcp = (struct pc *)DXAllocate(sizeof(struct pc)); if (!pcp) return NULL; memset(pcp, '\0', sizeof(struct pc)); pcp2 = pcp; strcpy(pcp2->con_name, elem_type); } else { for (pcp2 = pcp; pcp2->next; pcp2 = pcp2->next) if (!strcmp(pcp2->con_name, elem_type)) break; /* if we went thru the whole list & didn't find this type * yet, add a new block. otherwise we are at the right block. */ if (strcmp(pcp2->con_name, elem_type)) { pcp2->next = (struct pc *)DXAllocate(sizeof(struct pc)); if (!pcp2->next) return NULL; pcp2 = pcp2->next; memset(pcp2, '\0', sizeof(struct pc)); strcpy(pcp2->con_name, elem_type); } } /* finally, increment the item count */ pcp2->con_count += items; } /* count the number of different primitive types we found * in the input object. */ for (pcp2 = pcp, i = 0; pcp2; pcp2 = pcp2->next) i++; i++; /* add one extra for a trailing null */ ccp = (char **)DXAllocate(sizeof(char *) * i); if (!ccp) return NULL; for (pcp2 = pcp, i = 0; pcp2; pcp2 = pcp2->next, i++) { sprintf(pcp2->con_total, "%d %s", pcp2->con_count, pcp2->con_name); ccp[i] = pcp2->con_total; } ccp[i] = NULL; rc = (Object)DXMakeStringListV(i, ccp); cleanup: for ( ; pcp; pcp = pcp2) { pcp2 = pcp->next; DXFree((Pointer)pcp); } DXFree((Pointer)ccp); return rc; } #define DEG2RAD(x) (x/180.0*M_PI) /* degrees to radians */ #define RAD2DEG(x) (x*180.0/M_PI) /* visa versa */ static Object qcamera(Object o, char *info) { Object answer = NULL; Matrix m; int i[3]; float f[3]; CHECKIF(o, CLASS_CAMERA, "camera"); switch (info[0]) { case 'i': /* is perspective or is orthographic (yes/no questions) */ switch (info[2]) { case 'p': /* perspective */ i[0] = DXGetPerspective((Camera)o, NULL, NULL) == (Camera)o; answer = packint(i[0]); break; case 'o': /* ortho */ i[0] = DXGetOrthographic((Camera)o, NULL, NULL) == (Camera)o; answer = packint(i[0]); break; } break; /* the rest of the cases return int or float values */ case 't': /* to or transform */ switch (info[1]) { case 'o': if (!DXGetView((Camera)o, NULL, (Vector *)f, NULL)) return NULL; answer = packfloatvect(3, f); break; case 'r': m = DXGetCameraMatrix((Camera)o); answer = packfloatmat(4, 3, (float *)&m); break; } break; case 'f': /* from or fieldofview */ switch (info[1]) { case 'r': if (!DXGetView((Camera)o, (Vector *)f, NULL, NULL)) return NULL; answer = packfloatvect(3, f); break; case 'i': if (!DXGetPerspective((Camera)o, f, NULL)) { DXSetError(ERROR_INVALID_DATA, "field of view only valid for perspective camera"); return NULL; } answer = packfloat(f[0]); break; } break; case 'w': /* width */ if (!DXGetOrthographic((Camera)o, f, NULL)) { DXSetError(ERROR_INVALID_DATA, "width only valid for orthographic camera"); return NULL; } answer = packfloat(f[0]); break; case 'b': /* background color */ if (!DXGetBackgroundColor((Camera)o, (RGBColor *)f)) return NULL; answer = packfloatvect(3, f); break; case 'r': /* resolution */ if (!DXGetCameraResolution((Camera)o, &i[0], &i[1])) return NULL; answer = packint(i[0]); break; case 'a': /* angle or aspect */ switch (info[1]) { case 'n': if (!DXGetPerspective((Camera)o, f, NULL)) { DXSetError(ERROR_INVALID_DATA, "angle only valid for perspective camera"); return NULL; } f[0] = 2 * RAD2DEG(atan(f[0]/2.0)); answer = packfloat(f[0]); break; case 's': if (!DXGetCameraResolution((Camera)o, &i[0], &i[1])) return NULL; f[0] = i[0] ? (float)i[1] / i[0] : 0.0; answer = packfloat(f[0]); break; } break; case 'u': /* up */ if (!DXGetView((Camera)o, NULL, NULL, (Vector *)f)) return NULL; answer = packfloatvect(3, f); break; case 'p': /* perspective */ i[0] = DXGetPerspective((Camera)o, NULL, NULL) == (Camera)o; answer = packint(i[0]); break; } return answer; } static Object qclipped(Object o, char *which) { Object c, subo = NULL; CHECKIF(o, CLASS_CLIPPED, "clipped object"); if (!DXGetClippedInfo((Clipped)o, &subo, &c)) return NULL; if (which[0] == 'c') return c; return subo; } static Object qxform(Object o, char *which) { Object subo; Matrix m; CHECKIF(o, CLASS_XFORM, "transformed object"); if (!DXGetXformInfo((Xform)o, &subo, &m)) return NULL; if (which[0] == 'o') return subo; return packfloatmat(4, 3, (float *)&m); } static Object doxform(Object o) { Object subo; Matrix m; CHECKIF(o, CLASS_XFORM, "transformed object"); if (!DXGetXformInfo((Xform)o, &subo, &m)) return NULL; return (Object)DXApplyTransform(subo, &m); } static Object qscreen(Object o, char *which) { Object subo; int position, z; CHECKIF(o, CLASS_SCREEN, "screen object"); if (!DXGetScreenInfo((Screen)o, &subo, &position, &z)) return NULL; if (which[0] == 'o') return subo; if (which[0] == 'p') return packint(position); return packint(z); } Error MakeMany(Object attr, int memcount, int *isstring, Object *answer, char ***strlist) { int i; Type t; Category c; int rank, shape[100]; if (!attr) return ERROR; if (DXGetObjectClass(attr) == CLASS_STRING) { *isstring = 1; (*strlist) = DXAllocate(sizeof(char *) * (memcount+1)); if (!strlist) return ERROR; (*strlist)[0] = DXGetString((String)attr); *answer = NULL; return OK; } *isstring = 0; *strlist = NULL; if (DXGetObjectClass(attr) == CLASS_ARRAY) { if (!DXGetArrayInfo((Array)attr, &i, &t, &c, &rank, shape)) return ERROR; if (!(*answer = (Object)DXNewArrayV(t, c, rank, shape))) return ERROR; if (!DXAddArrayData((Array)*answer, 0, 1, DXGetArrayData((Array)attr))) { DXDelete(*answer); return ERROR; } return OK; } /* ? */ DXSetError(ERROR_INVALID_DATA, "unrecognized attribute object type"); return ERROR; } Error AddStrAttr(Object attr, int attrcount, char **strlist) { if (!attr) return ERROR; (strlist)[attrcount] = DXGetString((String)attr); return OK; } Error AddOtherAttr(Object attr, int attrcount, Object answer) { if (!attr) return ERROR; if (DXGetObjectClass(attr) != CLASS_ARRAY) { DXSetError(ERROR_INVALID_DATA, "unrecognized attribute object type"); return ERROR; } if (!DXAddArrayData((Array)answer, attrcount, 1, DXGetArrayData((Array)attr))) { return ERROR; } return OK; } #define A_OBJECT 0 #define A_MEMBERS 1 #define A_ALL 2 /* THIS ONLY DOES GROUPS OF STRING OBJECTS FOR NOW AS A HACK to get * data driven selector interactors going in the new ui. * attributes can be any type of object and this code should support it. * it also only does `object' and `member'. i'll put `all' in at the * same time i put generic object attributes in. */ static Object qattr(Object in, Object n, int flag) { char *attrname = NULL; char **strlist = NULL; char **objlist = NULL; Object answer = NULL; Object attr = NULL; Object member = NULL; int memcount, attrcount, firstmember, i; int isstring; if (!DXExtractString(n, &attrname)) { DXSetError(ERROR_BAD_PARAMETER, "#10200", "attribute name"); return NULL; } /* prevent errors because of unimplemented code */ if (flag == A_ALL) { DXSetError(ERROR_NOT_IMPLEMENTED, "all attributes"); return NULL; } /* top level object only */ if (flag == A_OBJECT) { answer = DXGetAttribute(in, attrname); if (!answer) DXSetError(ERROR_BAD_PARAMETER, "#10257", "input", attrname); return answer; } /* have to look at members */ switch (DXGetObjectClass(in)) { case CLASS_GROUP: if (!DXGetMemberCount((Group)in, &memcount)) return NULL; if (memcount == 0) { DXSetError(ERROR_INVALID_DATA, "group has no members"); return NULL; } /* find the first group member with this attribute. all members * aren't required to have the attribute - just at least one. */ attrcount = 0; for (i=0; iquestion[0] != '\0'; fp++) { if (strcmp(fp->question, userquestion)) continue; if (fp->qyes) out[0] = SayYesNo((fp->qyes)(in[0])); else if (fp->qyes1p) out[0] = SayYesNo((fp->qyes1p)(in[0], fp->yesvalue)); else if (fp->qyes1i) out[0] = SayYesNo((fp->qyes1i)(in[0], in[2])); else if (fp->qobj) out[0] = (Object)(fp->qobj)(in[0]); else if (fp->qobj1p) out[0] = (Object)(fp->qobj1p)(in[0], fp->objvalue); else if (fp->qobj1i) out[0] = (Object)(fp->qobj1i)(in[0], in[2]); else DXSetError(ERROR_INTERNAL, "inconsistant inquiry table"); /* if a yes/no routine returned a value but someone set an * error along the way, delete the return value and really * return error. */ if ((DXGetError() != ERROR_NONE) && out[0]) { DXDelete(out[0]); out[0] = NULL; } if (!out[0] && (DXGetError() == ERROR_NONE)) DXSetError(ERROR_BAD_PARAMETER, "inquiry failed"); if (invert != 0) { if ((op = fixinvert(out[0])) == NULL) { DXSetError(ERROR_BAD_PARAMETER, "cannot use 'not' with a value other than 0 or 1"); DXDelete(out[0]); out[0] = NULL; return ERROR; } DXDelete(out[0]); out[0] = op; } if (offset != 0) { if ((op = fixoffset(out[0], offset)) == NULL) { DXSetError(ERROR_BAD_PARAMETER, "cannot add or subtract 1 from this type of data"); DXDelete(out[0]); out[0] = NULL; return ERROR; } DXDelete(out[0]); out[0] = op; } return out[0] ? OK : ERROR; } DXSetError(ERROR_BAD_PARAMETER, "#10480", "inquiry"); return ERROR; } /* * new requests: * that you can query max memory and currently available mem * * that things which work on fields also work on composite fields * * that you can compare strings somehow. */