/***********************************************************************/ /* 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" */ /***********************************************************************/ /* * $Header: /home/gda/dxcvs/dx/src/exec/dxmods/_refinetopo.c,v 1.3 1999/05/10 15:45:20 gda Exp $: */ #include #include #include #include #include #include #define ELT_NONE 0 #define ELT_LINES 1 #define ELT_QUADS 2 #define ELT_TRIANGLES 3 #define ELT_CUBES 4 #define ELT_TETRAHEDRA 5 #define PAIR(to,from) (((to)<<16)|(from)) static Object ChgTopologyObject(Object, int); static Error ChgTopologyField(Pointer); typedef Field (*PFF)(); static Field None2None(Field); static Error PolylinesToLines(Field); static Field Cubes2Tetrahedra(Field); static Field RegCubes2Tetrahedra(Field); static Field IrregCubes2Tetrahedra(Field); static Field Quads2Triangles(Field); static Field RegQuads2Triangles(Field); static Field IrregQuads2Triangles(Field); extern Error _dxfTriangulateField(Field); static int GetTypeID(char *); static char *GetTypeName(int); Object _dxfChgTopology(Object object, char *type) { Object copy; int targetType; targetType = GetTypeID(type); if (targetType == ELT_NONE) { DXSetError(ERROR_BAD_PARAMETER, "#11380", type); return NULL; } copy = DXCopy(object, COPY_STRUCTURE); if (! copy) return NULL; if (! DXCreateTaskGroup()) goto error; if (! ChgTopologyObject(copy, targetType)) goto error; if (! DXExecuteTaskGroup() || DXGetError() != ERROR_NONE) goto error; return copy; error: DXDelete(copy); return NULL; } typedef struct { Field field; int targetType; } ChgTopologyTask; static Object ChgTopologyObject(Object object, int targetType) { int i; Object child; ChgTopologyTask task; task.targetType = targetType; switch (DXGetObjectClass(object)) { case CLASS_FIELD: task.field = (Field)object; if (! DXAddTask(ChgTopologyField, (Pointer)&task, sizeof(task), 1.0)) return NULL; return object; case CLASS_GROUP: i = 0; while (NULL != (child=DXGetEnumeratedMember((Group)object,i++,NULL))) if (! ChgTopologyObject(child, targetType)) return NULL; return object; case CLASS_XFORM: if (! DXGetXformInfo((Xform)object, &child, 0)) return NULL; if (! ChgTopologyObject(child, targetType)) return NULL; else return object; case CLASS_CLIPPED: if (! DXGetClippedInfo((Clipped)object, &child, 0)) return NULL; if (! ChgTopologyObject(child, targetType)) return NULL; else return object; default: DXSetError(ERROR_INVALID_DATA, "#11381"); return NULL; } } static Error ChgTopologyField(Pointer ptr) { Field field; PFF method; Object attr; char *srcString; int srcType, targetType; field = ((ChgTopologyTask *)ptr)->field; targetType = ((ChgTopologyTask *)ptr)->targetType; if (DXEmptyField(field)) return OK; attr = DXGetComponentAttribute(field, "connections", "element type"); if (! attr) { if (DXGetComponentValue(field, "faces")) { if (targetType != ELT_TRIANGLES) { DXSetError(ERROR_INVALID_DATA, "can only refine faces/loops/edges data to triangles"); goto error; } return _dxfTriangulateField(field); } else if (DXGetComponentValue(field, "polylines")) { if (targetType != ELT_LINES) { DXSetError(ERROR_INVALID_DATA, "can only refine polylines data to lines"); goto error; } return PolylinesToLines(field); } DXSetError(ERROR_MISSING_DATA, "#10255", "connections", "element type"); goto error; } if (! DXExtractString(attr, &srcString)) { DXSetError(ERROR_INVALID_DATA, "#10200", "element type attribute"); goto error; } srcType = GetTypeID(srcString); if (srcType == ELT_NONE) { DXSetError(ERROR_BAD_PARAMETER, "#11380", srcString); goto error; } if (srcType != targetType) { switch(PAIR(srcType, targetType)) { case PAIR(ELT_NONE,ELT_NONE): method = None2None; break; case PAIR(ELT_CUBES,ELT_TETRAHEDRA): method = Cubes2Tetrahedra; break; case PAIR(ELT_QUADS,ELT_TRIANGLES): method = Quads2Triangles; break; default: DXSetError(ERROR_BAD_PARAMETER, "#12120", srcString, GetTypeName(targetType)); goto error; } if (! (*method)(field)) goto error; DXDeleteComponent(field, "neighbors"); if (! DXEndField(field)) goto error; } return OK; error: return ERROR; } static int GetTypeID(char *str) { if (! strcmp(str, "lines")) return ELT_LINES; else if (! strcmp(str, "quads")) return ELT_QUADS; else if (! strcmp(str, "triangles")) return ELT_TRIANGLES; else if (! strcmp(str, "cubes")) return ELT_CUBES; else if (! strcmp(str, "tetrahedra")) return ELT_TETRAHEDRA; else return ELT_NONE; } static char * GetTypeName(int type) { switch(type) { case ELT_LINES: return "lines"; case ELT_QUADS: return "quads"; case ELT_TRIANGLES: return "triangles"; case ELT_CUBES: return "cubes"; case ELT_TETRAHEDRA: return "tetrahedra"; default: return "unknown element type"; } } static Field None2None(Field field) { return field; } static Field Cubes2Tetrahedra(Field field) { Array cArray; if (DXEmptyField(field)) return field; cArray = (Array)DXGetComponentValue(field, "connections"); if (! cArray) { DXSetError(ERROR_MISSING_DATA, "#10240", "connections"); return NULL; } if (DXQueryGridConnections(cArray, NULL, NULL)) field = RegCubes2Tetrahedra(field); else field = IrregCubes2Tetrahedra(field); if (! field) return NULL; if (! DXSetComponentAttribute(field, "connections", "element type", (Object)DXNewString("tetrahedra"))) return NULL; return field; } #define TETRA(t, a, b, c, d) \ { \ *(t)++ = (a); \ *(t)++ = (b); \ *(t)++ = (c); \ *(t)++ = (d); \ } static Field RegCubes2Tetrahedra(Field field) { MeshArray mArray; Array cArray, dIn, dOut; int i, j, parity, xB, yB, zB, vPerE; int x, y, z, X, Y, Z, xParity, yParity, zParity; int counts[3], offsets[3]; int nCubes, nTetras, *tetras; Array outArray; int n, inElement; Object attr; char *str, *name; InvalidComponentHandle iinvalids = NULL, oinvalids = NULL; cArray = NULL; dOut = NULL; mArray = (MeshArray)DXGetComponentValue(field, "connections"); if (! mArray) return field; if (! DXTypeCheckV((Array)mArray, TYPE_INT, CATEGORY_REAL, 1, NULL)) { DXSetError(ERROR_INVALID_DATA, "#11382"); return NULL; } DXGetArrayInfo((Array)mArray, &nCubes, NULL, NULL, NULL, &vPerE); iinvalids = DXCreateInvalidComponentHandle((Object)field, NULL, "connections"); if (! iinvalids) goto error; if (vPerE != 8) { DXSetError(ERROR_INVALID_DATA, "#11004", "cubes", 8); goto error; } DXQueryGridConnections((Array)mArray, NULL, counts); DXGetMeshOffsets(mArray, offsets); nTetras = 5 * nCubes; cArray = DXNewArray(TYPE_INT, CATEGORY_REAL, 1, 4); if (! cArray) goto error; if (! DXAddArrayData(cArray, 0, nTetras, NULL)) goto error; if (NULL == (tetras = (int *)DXGetArrayData(cArray))) goto error; oinvalids = DXCreateInvalidComponentHandle((Object)cArray, NULL, "connections"); if (! oinvalids) goto error; parity = 0; for (i = 0; i < 3; i++) if (offsets[i] & 0x01) parity = ! parity; Z = 1; Y = counts[2]; X = counts[1] * counts[2]; inElement = 0; xB = 0; xParity = parity; for (x = 0; x < (counts[0] - 1); x++) { yB = xB; yParity = xParity; for (y = 0; y < (counts[1] - 1); y++) { zB = yB; zParity = yParity; for (z = 0; z < (counts[2] - 1); z++, inElement++) { if (zParity) { TETRA(tetras, zB+X+Y, zB, zB+Y, zB+Y+Z); TETRA(tetras, zB+Y+Z, zB, zB+X+Z, zB+X+Y); TETRA(tetras, zB+X+Z, zB+Y+Z, zB+Z, zB); TETRA(tetras, zB+X+Y, zB+X+Z, zB+X, zB); TETRA(tetras, zB+Y+Z, zB+X+Z, zB+X+Y+Z, zB+X+Y); } else { TETRA(tetras, zB+X+Y+Z, zB+Y, zB+Y+Z, zB+Z); TETRA(tetras, zB+Y, zB+X+Y+Z, zB+X+Y, zB+X); TETRA(tetras, zB+X+Y+Z, zB+Z, zB+X+Z, zB+X); TETRA(tetras, zB+X, zB+Z, zB+Y, zB+X+Y+Z); TETRA(tetras, zB+X, zB+Z, zB, zB+Y); } if (DXIsElementInvalid(iinvalids, inElement)) { int j, k = 5 * inElement; for (j = 0; j < 5; j++) if (! DXSetElementInvalid(oinvalids, k+j)) goto error; } zParity = ! zParity; zB += Z; } yParity = ! yParity; yB += Y; } xParity = ! xParity; xB += X; } if (! DXSaveInvalidComponent(field, oinvalids)) goto error; DXFreeInvalidComponentHandle(iinvalids); DXFreeInvalidComponentHandle(oinvalids); iinvalids = oinvalids = NULL; if (! DXSetComponentValue(field, "connections", (Object)cArray)) goto error; cArray = NULL; j = 0; while (NULL != (dIn=(Array)DXGetEnumeratedComponentValue(field, j++, &name))) { if (! strcmp(name, "invalid connections")) continue; if (NULL == (attr = DXGetComponentAttribute(field, name, "dep"))) continue; if (DXGetObjectClass(attr) != CLASS_STRING || NULL == (str = DXGetString((String)attr))) { DXSetError(ERROR_MISSING_DATA, "#10200", "dependency attribute"); goto error; } if (!strcmp(str, "connections") && strcmp(name, "connections")) { int i, size, nD, r, s[32]; Type t; Category c; char *dataIn, *dataOut; DXGetArrayInfo(dIn, &nD, &t, &c, &r, s); if (nD != nCubes) { DXSetError(ERROR_INVALID_DATA, "#10400", name, "connections"); goto error; } if (DXQueryConstantArray(dIn, NULL, NULL)) { dOut = (Array)DXNewConstantArrayV(5*nCubes, DXGetConstantArrayData(dIn), t, c, r, s); } else { if (NULL == (dOut = DXNewArrayV(t, c, r, s))) goto error; if (! DXAddArrayData(dOut, 0, 5*nCubes, NULL)) goto error; if (0 == (size = DXGetItemSize(dIn))) goto error; dataIn = (char *)DXGetArrayData(dIn); dataOut = (char *)DXGetArrayData(dOut); if (! dataIn || ! dataOut) goto error; for (i = 0; i < nCubes; i++) { for (j = 0; j < 5; j++) { memcpy(dataOut, dataIn, size); dataOut += size; } dataIn += size; } } if (! DXSetComponentValue(field, name, (Object)dOut)) goto error; dOut = NULL; } } return field; error: DXFreeInvalidComponentHandle(iinvalids); DXFreeInvalidComponentHandle(oinvalids); DXDelete((Object)cArray); DXDelete((Object)dOut); return NULL; } static Field IrregCubes2Tetrahedra(Field field) { Array cArrayIn, cArrayOut, dIn, dOut; int i, j, k, vPerE; int nCubes, *cubes; Array outArray; int nTetras, *tetras; int nDim, dataSize; char *dataIn, *dPtr, *dataOut; Object attr; char *str, *name; InvalidComponentHandle iinvalids = NULL, oinvalids = NULL; dOut = NULL; cArrayOut = NULL; tetras = NULL; dataOut = NULL; cArrayIn = (Array)DXGetComponentValue(field, "connections"); if (! cArrayIn) return field; if (! DXTypeCheckV((Array)cArrayIn, TYPE_INT, CATEGORY_REAL, 1, NULL)) { DXSetError(ERROR_INVALID_DATA, "#11382"); return NULL; } DXGetArrayInfo((Array)cArrayIn, &nCubes, NULL, NULL, NULL, &vPerE); if (vPerE != 8) { DXSetError(ERROR_INVALID_DATA, "#11004", "cubes", 8); return NULL; } iinvalids = DXCreateInvalidComponentHandle((Object)field, NULL, "connections"); if (! iinvalids) goto error; cubes = (int *)DXGetArrayData(cArrayIn); nTetras = nCubes * 6; cArrayOut = DXNewArray(TYPE_INT, CATEGORY_REAL, 1, 4); if (! cArrayOut) goto error; if (! DXAddArrayData(cArrayOut, 0, nTetras, NULL)) goto error; oinvalids = DXCreateInvalidComponentHandle((Object)cArrayOut, NULL, "connections"); if (! oinvalids) goto error; tetras = (int *)DXGetArrayData(cArrayOut); if (! tetras) goto error; for (i = 0; i < nCubes; i++) { TETRA(tetras, cubes[0], cubes[3], cubes[5], cubes[1]); TETRA(tetras, cubes[5], cubes[2], cubes[7], cubes[3]); TETRA(tetras, cubes[5], cubes[4], cubes[7], cubes[2]); TETRA(tetras, cubes[5], cubes[3], cubes[0], cubes[2]); TETRA(tetras, cubes[5], cubes[2], cubes[0], cubes[4]); TETRA(tetras, cubes[4], cubes[2], cubes[6], cubes[7]); if (DXIsElementInvalid(iinvalids, i)) { int j; for (j = 6*i; j < 6*(i+1); j++) if (! DXSetElementInvalid(oinvalids, j)) goto error; } cubes += 8; } j = 0; while (NULL != (dIn=(Array)DXGetEnumeratedComponentValue(field, j++, &name))) { if (! strcmp(name, "invalid connections")) continue; if (NULL == (attr = DXGetComponentAttribute(field, name, "dep"))) continue; if (DXGetObjectClass(attr) != CLASS_STRING || NULL == (str = DXGetString((String)attr))) { DXSetError(ERROR_MISSING_DATA, "#10200", "dependency attribute"); goto error; } if (!strcmp(str, "connections") && strcmp(name, "connections")) { int nD, r, s[32]; Type t; Category c; DXGetArrayInfo(dIn, &nD, &t, &c, &r, s); if (nD != nCubes) { DXSetError(ERROR_INVALID_DATA, "#10400", name, "connections"); goto error; } if (DXQueryConstantArray(dIn, NULL, NULL)) { dOut = (Array)DXNewConstantArrayV(6*nCubes, DXGetConstantArrayData(dIn), t, c, r, s); } else { if (NULL == (dOut = DXNewArrayV(t, c, r, s))) goto error; if (! DXAddArrayData(dOut, 0, nTetras, NULL)) goto error; if (0 == (dataSize = DXGetItemSize(dIn))) goto error; dataIn = (char *)DXGetArrayData(dIn); dataOut = (char *)DXGetArrayData(dOut); if (! dataIn || ! dataOut) goto error; for (i = 0; i < nCubes; i++) { for (k = 0; k < 6; k++) { memcpy(dataOut, dataIn, dataSize); dataOut += dataSize; } dataIn += dataSize; } } if (! DXSetComponentValue(field, name, (Object)dOut)) goto error; } } if (! DXSaveInvalidComponent(field, oinvalids)) goto error; DXFreeInvalidComponentHandle(iinvalids); DXFreeInvalidComponentHandle(oinvalids); iinvalids = oinvalids = NULL; if (! DXSetComponentValue(field, "connections", (Object)cArrayOut)) goto error; return field; error: DXFreeInvalidComponentHandle(iinvalids); DXFreeInvalidComponentHandle(oinvalids); DXDelete((Object)dOut); DXDelete((Object)cArrayOut); return NULL; } static Field Quads2Triangles(Field field) { Array cArray; if (DXEmptyField(field)) return field; cArray = (Array)DXGetComponentValue(field, "connections"); if (! cArray) { DXSetError(ERROR_MISSING_DATA, "#10240", "connections"); return NULL; } if (DXQueryGridConnections(cArray, NULL, NULL)) field = RegQuads2Triangles(field); else field = IrregQuads2Triangles(field); if (! field) return NULL; if (! DXSetComponentAttribute(field, "connections", "element type", (Object)DXNewString("triangles"))) return NULL; return field; } #define TRIANGLE(t, a, b, c) \ { \ *(t)++ = (a); \ *(t)++ = (b); \ *(t)++ = (c); \ } static Field RegQuads2Triangles(Field field) { MeshArray mArray; Array cArray, dIn, dOut; int i, j, parity, xB, yB, zB; int x, y, z, X, Y, Z, vPerE; int offsets[3], counts[3]; int nQuads, nTris, *tris, *tPtr; Array outArray; int n, inElement; Object attr; char *str, *name; InvalidComponentHandle iinvalids = NULL, oinvalids = NULL; cArray = NULL; dOut = NULL; mArray = (MeshArray)DXGetComponentValue(field, "connections"); if (! mArray) return field; if (! DXTypeCheckV((Array)mArray, TYPE_INT, CATEGORY_REAL, 1, NULL)) { DXSetError(ERROR_INVALID_DATA, "#11382"); return NULL; } DXGetArrayInfo((Array)mArray, &nQuads, NULL, NULL, NULL, &vPerE); if (vPerE != 4) { DXSetError(ERROR_INVALID_DATA, "#11004", "cubes", 4); return NULL; } iinvalids = DXCreateInvalidComponentHandle((Object)field, NULL, "connections"); if (! iinvalids) goto error; DXQueryGridConnections((Array)mArray, NULL, counts); DXGetMeshOffsets(mArray, offsets); nTris = 2 * nQuads; cArray = DXNewArray(TYPE_INT, CATEGORY_REAL, 1, 3); if (! cArray) goto error; if (! DXAddArrayData(cArray, 0, nTris, NULL)) goto error; oinvalids = DXCreateInvalidComponentHandle((Object)cArray, NULL, "connections"); if (! oinvalids) goto error; if (NULL == (tris = (int *)DXGetArrayData(cArray))) goto error; inElement = 0; Y = 1; X = counts[1]; xB = 0; for (x = 0; x < (counts[0] - 1); x++) { yB = xB; for (y = 0; y < (counts[1] - 1); y++, inElement++) { TRIANGLE(tris, yB, yB+Y+X, yB+Y); TRIANGLE(tris, yB, yB+X, yB+Y+X); if (DXIsElementInvalid(iinvalids, inElement)) { if (! DXSetElementInvalid(oinvalids, inElement<<1)) goto error; if (! DXSetElementInvalid(oinvalids, (inElement<<1)+1)) goto error; } yB += Y; } xB += X; } if (! DXSaveInvalidComponent(field, oinvalids)) goto error; DXFreeInvalidComponentHandle(iinvalids); DXFreeInvalidComponentHandle(oinvalids); iinvalids = oinvalids = NULL; if (! DXSetComponentValue(field, "connections", (Object)cArray)) goto error; cArray = NULL; j = 0; while (NULL != (dIn=(Array)DXGetEnumeratedComponentValue(field, j++, &name))) { if (! strcmp(name, "invalid connections")) continue; if (NULL == (attr = DXGetComponentAttribute(field, name, "dep"))) continue; if (DXGetObjectClass(attr) != CLASS_STRING || NULL == (str = DXGetString((String)attr))) { DXSetError(ERROR_MISSING_DATA, "#10051", "dependency attribute"); goto error; } if (! strcmp(str, "connections") && strcmp(name, "connections")) { int i, size, nD, r, s[32]; Type t; Category c; char *dataIn, *dataOut; DXGetArrayInfo(dIn, &nD, &t, &c, &r, s); if (nD != nQuads) { DXSetError(ERROR_INVALID_DATA, "#10400", name, "connections"); goto error; } if (DXQueryConstantArray(dIn, NULL, NULL)) { dOut = (Array)DXNewConstantArrayV(2*nD, DXGetConstantArrayData(dIn), t, c, r, s); } else { if (NULL == (dOut = DXNewArrayV(t, c, r, s))) goto error; if (! DXAddArrayData(dOut, 0, 2*nD, NULL)) goto error; if (0 == (size = DXGetItemSize(dIn))) goto error; dataIn = (char *)DXGetArrayData(dIn); dataOut = (char *)DXGetArrayData(dOut); for (i = 0; i < nQuads; i++) { memcpy(dataOut, dataIn, size); dataOut += size; memcpy(dataOut, dataIn, size); dataOut += size; dataIn += size; } } if (! DXSetComponentValue(field, name, (Object)dOut)) goto error; dOut = NULL; } } return field; error: DXFreeInvalidComponentHandle(iinvalids); DXFreeInvalidComponentHandle(oinvalids); DXDelete((Object)cArray); DXDelete((Object)dOut); return NULL; } static Field IrregQuads2Triangles(Field field) { Array pArray, cArrayIn, cArrayOut, dIn, dOut; int i, j, k; int nQuads, *quads; Array outArray; int nTris, *tris; int nDim, dataSize, vPerE; char *dataIn, *dPtr, *dataOut; Object attr; char *str, *name; InvalidComponentHandle iinvalids = NULL, oinvalids = NULL; dOut = NULL; cArrayOut = NULL; tris = NULL; dataOut = NULL; pArray = (Array)DXGetComponentValue(field, "positions"); cArrayIn = (Array)DXGetComponentValue(field, "connections"); if (! pArray || ! cArrayIn) return field; if (! DXTypeCheckV((Array)cArrayIn, TYPE_INT, CATEGORY_REAL, 1, NULL)) { DXSetError(ERROR_INVALID_DATA, "#11382"); return NULL; } DXGetArrayInfo((Array)cArrayIn, &nQuads, NULL, NULL, NULL, &vPerE); if (vPerE != 4) { DXSetError(ERROR_INVALID_DATA, "#11004", "cubes", 4); return NULL; } DXGetArrayInfo(pArray, NULL, NULL, NULL, NULL, &nDim); if (! DXTypeCheckV(pArray, TYPE_FLOAT, CATEGORY_REAL, 1, NULL)) { DXSetError(ERROR_INVALID_DATA, "#11383"); return NULL; } if (nDim != 2 && nDim != 3) { DXSetError(ERROR_INVALID_DATA, "#11002", "cubes"); return NULL; } quads = (int *)DXGetArrayData(cArrayIn); iinvalids = DXCreateInvalidComponentHandle((Object)field, NULL, "connections"); if (! iinvalids) goto error; nTris = 2*nQuads; cArrayOut = DXNewArray(TYPE_INT, CATEGORY_REAL, 1, 3); if (! cArrayOut) goto error; if (! DXAddArrayData(cArrayOut, 0, nTris, NULL)) goto error; /* * 3 vertices per tris, 2 tris per quads, nQuads */ tris = (int *)DXGetArrayData(cArrayOut); if (! tris) goto error; oinvalids = DXCreateInvalidComponentHandle((Object)cArrayOut, NULL, "connections"); if (! oinvalids) goto error; for (i = 0; i < nQuads; i++) { TRIANGLE(tris, quads[0], quads[3], quads[1]); TRIANGLE(tris, quads[0], quads[2], quads[3]); if (DXIsElementInvalid(iinvalids, i)) { if (! DXSetElementInvalid(oinvalids, i<<1) || ! DXSetElementInvalid(oinvalids, (i<<1)+1)) goto error; } quads += 4; } if (! DXSaveInvalidComponent(field, oinvalids)) goto error; DXFreeInvalidComponentHandle(iinvalids); DXFreeInvalidComponentHandle(oinvalids); iinvalids = oinvalids = NULL; if (! DXSetComponentValue(field, "connections", (Object)cArrayOut)) goto error; j = 0; while(NULL != (dIn=(Array)DXGetEnumeratedComponentValue(field, j++, &name))) { if (! strcmp(name, "invalid connections")) continue; if (NULL == (attr = DXGetComponentAttribute(field, name, "dep"))) continue; if (DXGetObjectClass(attr) != CLASS_STRING || NULL == (str = DXGetString((String)attr))) { DXSetError(ERROR_MISSING_DATA, "#10051", "dependency attribute"); goto error; } if (! strcmp(str, "connections") && strcmp(name, "connections")) { int nD, r, s[32]; Type t; Category c; DXGetArrayInfo(dIn, &nD, &t, &c, &r, s); if (nD != nQuads) { DXSetError(ERROR_INVALID_DATA, "#10400", name, "connections"); goto error; } if (DXQueryConstantArray(dIn, NULL, NULL)) { dOut = (Array)DXNewConstantArrayV(nTris, DXGetConstantArrayData(dIn), t, c, r, s); } else { if (NULL == (dOut = DXNewArrayV(t, c, r, s))) goto error; if (0 == (dataSize = DXGetItemSize(dIn))) goto error; dataIn = (char *)DXGetArrayData(dIn); if (! DXAddArrayData(dOut, 0, nTris, NULL)) goto error; dataIn = (char *)DXGetArrayData(dIn); dataOut = (char *)DXGetArrayData(dOut); if (! dataIn || ! dataOut) goto error; for (i = 0; i < nQuads; i++) { memcpy(dataOut, dataIn, dataSize); dataOut += dataSize; memcpy(dataOut, dataIn, dataSize); dataOut += dataSize; dataIn += dataSize; } } if (! DXSetComponentValue(field, name, (Object)dOut)) goto error; } } return field; error: DXFreeInvalidComponentHandle(iinvalids); DXFreeInvalidComponentHandle(oinvalids); DXFree((Pointer)tris); DXDelete((Object)dOut); DXDelete((Object)cArrayOut); return NULL; } static Error PolylinesToLines(Field field) { Array pA, eA, lA = NULL, inA, outA = NULL; int nP, nE, nL, nA; int *polylines, *edges, *lines; int i, j, k, p, e, l; Object o; char *name; InvalidComponentHandle invP = NULL, invL = NULL; pA = (Array)DXGetComponentValue(field, "polylines"); eA = (Array)DXGetComponentValue(field, "edges"); if (! pA || ! eA) { DXSetError(ERROR_MISSING_DATA, "polylines or edges component"); goto error; } DXGetArrayInfo(pA, &nP, NULL, NULL, NULL, NULL); DXGetArrayInfo(eA, &nE, NULL, NULL, NULL, NULL); nL = nE - nP; lA = DXNewArray(TYPE_INT, CATEGORY_REAL, 1, 2); if (! lA) goto error; if (! DXAddArrayData(lA, 0, nL, NULL)) goto error; if (! DXSetAttribute((Object)lA, "element type", (Object)DXNewString("lines"))) goto error; if (! DXSetComponentValue(field, "connections", (Object)lA)) goto error; polylines = (int *)DXGetArrayData(pA); edges = (int *)DXGetArrayData(eA); lines = (int *)DXGetArrayData(lA); invP = DXCreateInvalidComponentHandle((Object)field, NULL, "polylines"); if (invP) { invL = DXCreateInvalidComponentHandle((Object)field, NULL, "connections"); if (! invL) goto error; } for (p = l = 0; p < nP; p++) { int start = polylines[p]; int end = ((p == nP-1) ? nE : polylines[p+1]) - 1; int inv = DXIsElementInvalid(invP, p); for (e = start; e < end; e++, lines += 2, l++) { lines[0] = edges[e]; lines[1] = edges[e+1]; if (inv) if (! DXSetElementInvalid(invL, l)) goto error; } } if (invP) { DXFreeInvalidComponentHandle(invP); invP = NULL; if (! DXSaveInvalidComponent(field, invL)) goto error; DXFreeInvalidComponentHandle(invL); invL = NULL; } for (i = 0; NULL != (o = DXGetEnumeratedComponentValue(field, i, &name)); i++) { Type t; Category c; int r, s[32]; if (DXGetObjectClass(o) != CLASS_ARRAY) continue; if (! strcmp(name, "polylines") || ! strcmp(name, "invalid polylines")) continue; inA = (Array)o; o = DXGetAttribute(o, "dep"); if (! o || DXGetObjectClass(o) != CLASS_STRING || strcmp(DXGetString((String)o), "polylines")) { continue; } DXGetArrayInfo(inA, &nA, &t, &c, &r, s); if (nA != nP) { DXSetError(ERROR_INVALID_DATA, "%s deps polylines but has a different size"); goto error; } if (DXGetArrayClass(inA) == CLASS_CONSTANTARRAY) { outA = (Array)DXNewConstantArray(nL, DXGetConstantArrayData(inA), t, c, r, s); if (! outA) goto error; } else { int size; ubyte *inData, *outData; outA = DXNewArrayV(t, c, r, s); if (! outA) goto error; if (! DXAddArrayData(outA, 0, nL, NULL)) goto error; size = DXGetItemSize(inA); inData = (ubyte *)DXGetArrayData(inA); outData = (ubyte *)DXGetArrayData(outA); for (k = 0; k < nP; k++, inData += size) { int start = polylines[k]; int end = ((k == nP-1) ? nE : polylines[k+1]) - 1; int j, knt = end - start; for (j = 0; j < knt; j++, outData += size) memcpy(outData, inData, size); } } if (! DXSetComponentValue(field, name, (Object)outA)) goto error; if (! DXSetComponentAttribute(field, name, "dep", (Object)DXNewString("connections"))) goto error; } DXDeleteComponent(field, "polylines"); DXDeleteComponent(field, "edges"); DXDeleteComponent(field, "invalid polylines"); return OK; error: if (invP) DXFreeInvalidComponentHandle(invP); if (invL) DXFreeInvalidComponentHandle(invL); if (outA) DXDelete((Object)outA); if (lA) DXDelete((Object)lA); return ERROR; }