/***********************************************************************/ /* 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" */ /***********************************************************************/ /* XXX - equivalence loop, prisms, efficient degenerate removal */ /* XXX - the diagonal isn't preserved with band quad->tri decomp */ /* XXX - color map component */ #include /* XXX - traverse once to get values and once to set them (attributes). merge */ #ifndef _ISOSURFACE_PASS_NUMBER /* * The following commands may be useful in rebuilding isosurface in * the form it had before the large change (rewrite): * * rlog -d'<93/02/06' ${file} | grep '^revis' | head -1 * co -d'93/02/06' ${file} * * for the files: * isosurface.m _isosurface.h _isosurface.c _contour.c _irriso.c _regiso.c */ /***************************************************\ * Generic instantiation system: * * for each of the base types: float, char * * create a copy of those routines that * * handle those specific types * \***************************************************/ extern int _dxd_isosurface_task_counter; #define _ISOSURFACE_PASS_NUMBER 1 /*------------------------------*/ #define ERROR_SECTION if ( DXGetError() == ERROR_NONE ) \ DXDebug ( "I0D", "No error set at %s:%d", __FILE__,__LINE__) #define VALUE_COUNT(a) ( (a)->number ) #define STRUCT_COUNT(a) ( ((a)->module==BAND) ? 1 : (a)->number ) #define MOD_NAME(a) ( ((a)->module==BAND) ? "Band" : "Isosurface") #define ATTR_NAME(a) ( ((a)->module==BAND) ? "Band value" : "Isosurface value") #endif /* ( not defined _ISOSURFACE_PASS_NUMBER ) */ #if ( _ISOSURFACE_PASS_NUMBER == 1 ) /* ** -------- Include Files ------------------------------------------------- ** -------- Type Information ---------------------------------------------- ** -------- Constants ----------------------------------------------------- ** -------- storage areas ------------------------------------------------- ** -------- Inline Macros ------------------------------------------------- ** -------- Function Prototypes ------------------------------------------- */ #include #include #include "_isosurface.h" #include "_getfield.h" #ifdef DXD_LONG_HASHKEY #endif #define TST_HASH_INTS if(sizeof(PointId)!=sizeof(int32))\ DXErrorGoto(ERROR_UNEXPECTED,"64 bit porting error") /* the following function resides in the file: showboundary.m */ extern Array _dxf_resample_array ( component_info comp, int dep_ref, int Nin, int Nout, int *push, int *pull ); static RGBColor DEFAULT_SURFACE_COLOR = { 0.5, 0.7, 1.0 }; /*bluish slate grey*/ static RGBColor DEFAULT_LINE_COLOR = { 0.7, 0.7, 0.0 }; /* sizeof unsigned int is 4 bytes, 32 bits */ #define NEWBIT(n) ((Pointer)DXAllocateLocalZero((((n)+31)/32)*4)) #define SETBIT(a,i,v) (((unsigned int*)(a))[((i)/32)]|=((v)<<((i)&31))) #define GETBIT(a,i) (1&(((unsigned int*)(a))[((i)/32)]>>((i)&31))) #define NOWHITEBOX_TEST #define INCLUDES_BAND #define ABS(x) (((x)<0.0)?-(x):(x)) typedef struct { Line edge; int seq; #if 0 float t; /* XXX - intrusive in the contour connection table ? */ #endif } iso_edge_hash_rec; typedef iso_edge_hash_rec *iso_edge_hash_ptr; #ifdef INCLUDES_BAND typedef enum { DEP_CONNECTIONS, DEP_POSITIONS } data_dep; #define NEITHER_VALUE -1 typedef int band_value_sel; typedef struct { Line edge; band_value_sel select; int seq; } band_edge_hash_rec; typedef band_edge_hash_rec *band_edge_hash_ptr; #endif typedef struct { int count; HashTable table; Pointer set_vertices; } hash_table_rec; typedef hash_table_rec *hash_table_ptr; typedef struct { Pointer set_connections; Vector **index; SegList *list; } grad_table_rec; typedef grad_table_rec *grad_table_ptr; typedef struct { int count; SegList *conn; SegList *conn_id; } conn_list_rec; typedef conn_list_rec *conn_list_ptr; #ifdef WHITEBOX_TEST struct { int case_signatures [ 256 ]; int polygonalizations [ 8 ]; } histograms; #endif Field remove_degenerates ( Field in ); #endif /* ( _ISOSURFACE_PASS_NUMBER == 1 ) */ /*---------------------------------------------*\ | Begin generic templates. \*---------------------------------------------*/ /* Moved to _getfield.c */ /*---------------------------------------------*\ | End generic templates. \*---------------------------------------------*/ #if ( _ISOSURFACE_PASS_NUMBER == 1 ) static Pointer copy_seglist_to_memory ( SegList *list, Pointer mem, int itemsize, int count ) { SegListSegment *sublist = NULL; int items = 0; char *location = NULL; int segsize = 0; DXASSERTGOTO ( list != ERROR ); DXASSERTGOTO ( mem != ERROR ); DXASSERTGOTO ( count == DXGetSegListItemCount ( list ) ); if ( count == 0 ) return mem; if ( !DXInitGetNextSegListSegment ( list ) ) goto error; for ( items = 0, location = (char *) mem; ( NULL != ( sublist = DXGetNextSegListSegment ( list ) ) ); items += segsize, location += ( segsize * itemsize ) ) { if ( ERROR == ( segsize = DXGetSegListSegmentItemCount ( sublist ) ) ) goto error; if ( !memcpy ( location, (char *) DXGetSegListSegmentPointer ( sublist ), ( segsize * itemsize ) ) ) DXErrorGoto2 ( ERROR_INTERNAL, "#11800", /* C standard library call, %s, returns error */ "memcpy()" ) } DXASSERTGOTO ( items == count ); return mem; error: ERROR_SECTION; return ERROR; } static array_info copy_seglist_to_array ( SegList *list, array_info array ) { DXASSERT ( array != ERROR ); if ( copy_seglist_to_memory ( list, array->data, array->itemsize, array->items ) ) return array; else return ERROR; } static Error tally_dependers ( field_info input_info, int *posi, int *conn ) { component_info comp; int i; DXASSERTGOTO ( posi != ERROR ); DXASSERTGOTO ( conn != ERROR ); for ( i=0, *posi=0, *conn=0, comp=input_info->comp_list; icomp_count; i++, comp++ ) { if ( ( 0 == strcmp ( comp->name, "positions" ) ) || ( ( NULL != comp->std_attribs[(int)DEP] ) && ( ERROR != comp->std_attribs[(int)DEP]->value ) && ( 0 == strcmp ( comp->std_attribs[(int)DEP]->value, "positions" ) ) ) ) (*posi)++; else if ( ( 0 == strcmp ( comp->name, "connections" ) ) || ( ( NULL != comp->std_attribs[(int)DEP] ) && ( ERROR != comp->std_attribs[(int)DEP]->value ) && ( 0 == strcmp ( comp->std_attribs[(int)DEP]->value, "connections" ) ) ) ) (*conn)++; } return OK; error: ERROR_SECTION; return ERROR; } static SegList *set_c_ID ( SegList *list, int index, int ID ) { int length = DXGetSegListItemCount ( list ); int *list_item; DXASSERT ( length <= index ); while ( length < index ) if ( ERROR == ( list_item = (int*) DXNewSegListItem ( list ) ) ) return ERROR; else { *list_item = ID; length++; } DXASSERT ( length == DXGetSegListItemCount ( list ) ); return list; } static SegList *set_cval ( SegList *list, int index, float val ) { int length = DXGetSegListItemCount ( list ); float *list_item; DXASSERT ( length <= index ); while ( length < index ) if ( ERROR == ( list_item = (float*) DXNewSegListItem ( list ) ) ) return ERROR; else { *list_item = val; length++; } DXASSERT ( length == DXGetSegListItemCount ( list ) ); return list; } static Error interp ( array_info info, Pointer scratch, int I, int J, double t, Pointer dest, int tot, int out_size ) { typedef unsigned int unsigned_int; typedef unsigned char unsigned_char; typedef unsigned short unsigned_short; Pointer si = scratch; Pointer sj = (Pointer)&(((char*)scratch)[out_size]); int i; if (t == 0) { if (!info->get_item(I, info, dest)) goto error; } else if (t == 1) { if (!info->get_item(J, info, dest)) goto error; } else { if ( !info->get_item ( I, info, si ) || !info->get_item ( J, info, sj ) ) goto error; for(i=0; iitemsize/sizeof(CTYPE);\ for(i=0;itype ) { case TYPE_FLOAT: INTERP ( float ); break; case TYPE_DOUBLE: INTERP ( double ); break; case TYPE_INT: INTERP ( int ); break; case TYPE_BYTE: INTERP ( char ); break; case TYPE_UINT: INTERP ( unsigned_int ); break; case TYPE_UBYTE: INTERP ( unsigned_char ); break; case TYPE_USHORT: INTERP ( unsigned_char ); break; case TYPE_SHORT: INTERP ( unsigned_short ); break; } #undef INTERP #endif return OK; error: ERROR_SECTION; return ERROR; } static Field create_output_arrays ( Field output, /* handle */ int nP, /* N positions */ int Pd, /* positions dim */ int nC, /* N connections */ int Cd, /* connections dim */ int nN, /* N normals */ RGBColor color, /* default color */ float Dv, /* data value (isos. only) */ data_dep Dd, /* data dependency */ iso_module_types module /* isosurface/band */ ) { Array array = NULL; DXASSERTGOTO ( output != ERROR ); DXASSERTGOTO ( DXGetObjectClass ( (Object) output ) == CLASS_FIELD ); /* * Basic assumptions for isosurface output: * Colors and Data are regular (constant) dep positions. * Positions and Connections are always irregular. * Normals are for surfaces. * Connections are used for surfaces and contours only. * Connections are 1d (Lines) or 2d (Triangles) or nonexistant. * int 0 is usable as float, char, ... 0. * (int[2] for double), (int[3] for RBGColor) * * XXX - libdx * assume that DXSetAttribute(array) and DXSetComponentAttribute * are interchangeable. */ if ( !_dxf_MakeFieldEmpty ( output ) ) goto error; if ( nP == 0 ) return output; else { /* POSITIONS */ if ( ( ERROR == ( array = DXNewArray ( TYPE_FLOAT, CATEGORY_REAL, 1, Pd ) ) ) || !DXAllocateArray ( array, nP ) || !DXAddArrayData ( array, 0, nP, NULL ) || !DXTrim ( array ) || !DXSetAttribute ( (Object)array, "dep", (Object) DXNewString ( "positions" ) ) || !DXSetComponentValue ( output, "positions", (Object) array ) ) goto error; array = NULL; /* COLORS */ /* XXX - conditional */ if ( ( ERROR == ( array = (Array)DXNewConstantArray ( ((Dd==DEP_POSITIONS)? nP: nC), (Pointer)&color, TYPE_FLOAT, CATEGORY_REAL, 1, 3 ) ) ) || !DXSetAttribute ( (Object)array, "dep", (Object) DXNewString ( (Dd==DEP_POSITIONS)?"positions" :"connections" ) ) || !DXSetComponentValue ( output, "colors", (Object) array ) ) goto error; array = NULL; /* DATA */ switch ( module ) { case ISOSURFACE: DXASSERTGOTO ( Dd == DEP_POSITIONS ); if ( ERROR == ( array = (Array)DXNewConstantArray ( nP, (Pointer)&Dv, TYPE_FLOAT, CATEGORY_REAL, 0, 0 ) ) ) goto error; break; case BAND: if ( ( ERROR == ( array = DXNewArray ( TYPE_FLOAT, CATEGORY_REAL, 0, 0 ) ) ) || !DXAllocateArray ( array, ((Dd==DEP_POSITIONS)? nP: nC) ) || !DXAddArrayData ( array, 0, ((Dd==DEP_POSITIONS)? nP: nC), NULL ) || !DXTrim ( array ) ) goto error; break; } if ( !DXSetComponentValue ( output, "data", (Object) array ) || !DXSetComponentAttribute ( output, "data", "dep", (Object) DXNewString ( ( (Dd==DEP_POSITIONS) ? "positions" : "connections" ) ) ) ) goto error; array = NULL; /* NORMALS */ if ( ( nN != 0 ) && ( ( ERROR == ( array = DXNewArray ( TYPE_FLOAT, CATEGORY_REAL, 1, 3 ) ) ) || !DXAllocateArray ( array, nP ) || !DXAddArrayData ( array, 0, nP, NULL ) || !DXTrim ( array ) || !DXSetAttribute ( (Object)array, "dep", (Object) DXNewString ( "positions" ) ) || !DXSetComponentValue ( output, "normals", (Object) array ) ) ) goto error; array = NULL; } if ( nC != 0 ) { char *element_type; switch ( Cd ) { case 1: if ( !_dxf_SetFuzzAttribute ( output, 3 ) ) goto error; element_type = "lines"; break; case 2: element_type = "triangles"; break; default: DXASSERTGOTO ( ( Cd == 1 ) || ( Cd == 2 ) ); } /* CONNECTIONS */ if ( ( ERROR == ( array = DXNewArray ( TYPE_INT, CATEGORY_REAL, 1, ( Cd + 1 ) ) ) ) || !DXAllocateArray ( array, nC ) || !DXAddArrayData ( array, 0, nC, (Pointer) NULL ) || !DXTrim ( array ) || !DXSetAttribute ( (Object)array, "ref", (Object) DXNewString ( "positions" ) ) || !DXSetAttribute ( (Object)array, "element type", (Object) DXNewString ( element_type ) ) || !DXSetComponentValue ( output, "connections", (Object) array ) ) goto error; array = NULL; } return ( output ); error: ERROR_SECTION; DXDelete ( (Object) array ); array = NULL; return ERROR; } static int iso_edge_compare_func ( Key i, Element j ) { /* XXX - requires pre-sorting! */ return ( ( ( ((iso_edge_hash_ptr)i)->edge.p == ((iso_edge_hash_ptr)j)->edge.p ) && ( ((iso_edge_hash_ptr)i)->edge.q == ((iso_edge_hash_ptr)j)->edge.q ) ) ? 0 : 1 ); } #ifdef INCLUDES_BAND static int band_edge_compare_func ( Key i, Element j ) { /* XXX - requires pre-sorting! */ return ( ( ( ((band_edge_hash_ptr)i)->edge.p == ((band_edge_hash_ptr)j)->edge.p ) && ( ((band_edge_hash_ptr)i)->edge.q == ((band_edge_hash_ptr)j)->edge.q ) && ( ((band_edge_hash_ptr)i)->select == ((band_edge_hash_ptr)j)->select ) ) ? 0 : 1 ); } #endif static PseudoKey iso_edge_hash_func ( Key i ) { #define k1 ((int)((iso_edge_hash_ptr)i)->edge.p) #define k2 ((int)((iso_edge_hash_ptr)i)->edge.q) #define PRIME_1 10607 #define PRIME_2 18913 PseudoKey address = ( ( k1 * PRIME_1 ) + ( k2 * PRIME_2 ) ); #if 0 DXDebug ( "I", "Address(%d,%d) = %d", k1, k2, address ); #endif return address; #undef PRIME_1 #undef PRIME_2 #undef k1 #undef k2 } #ifdef INCLUDES_BAND static PseudoKey band_edge_hash_func ( Key i ) { #define k1 ((int)((band_edge_hash_ptr)i)->edge.p) #define k2 ((int)((band_edge_hash_ptr)i)->edge.q) #define k3 ((int)((band_edge_hash_ptr)i)->select) #define PRIME_1 10607 #define PRIME_2 18913 #define PRIME_3 28001 PseudoKey address = (( k1 * PRIME_1 )+ ( k2 * PRIME_2 )+ ( k3 * PRIME_3 )); #if 0 DXDebug ( "I", "Address(%d,%d,%d) = %d", k1, k2, k3, address ); #endif return address; #undef PRIME_1 #undef PRIME_2 #undef PRIME_3 #undef k1 #undef k2 #undef k3 } #endif static int iso_hash_enter ( Line *edge, hash_table_ptr hash, int *o ) { iso_edge_hash_rec element; iso_edge_hash_ptr element_ptr; if ( edge->p <= edge->q ) element.edge = *edge; else { element.edge.p = edge->q; element.edge.q = edge->p; } if ( NULL != ( element_ptr = (iso_edge_hash_ptr) DXQueryHashElement ( hash->table, (Key)&element ) ) ) *o = element_ptr->seq; else { *o = element.seq = (hash->count)++; if ( hash->set_vertices != NULL ) { SETBIT ( hash->set_vertices, element.edge.p, 1 ); SETBIT ( hash->set_vertices, element.edge.q, 1 ); } if ( !DXInsertHashElement ( hash->table, (Element)&element ) ) goto error; } return OK; error: ERROR_SECTION; return ERROR; } #ifdef INCLUDES_BAND static int band_hash_enter ( Line *edge, band_value_sel select, hash_table_ptr hash, int *o ) { band_edge_hash_rec element; band_edge_hash_ptr element_ptr; /* DXASSERTGOTO ( ( edge->p == edge->q ) == ( select == NEITHER_VALUE ) ); */ if ( edge->p <= edge->q ) element.edge = *edge; else { element.edge.p = edge->q; element.edge.q = edge->p; } element.select = select; if ( NULL != ( element_ptr = (band_edge_hash_ptr) DXQueryHashElement ( hash->table, (Key)&element ) ) ) *o = element_ptr->seq; else { *o = element.seq = (hash->count)++; if ( !DXInsertHashElement ( hash->table, (Element)&element ) ) goto error; } return OK; error: ERROR_SECTION; return ERROR; } #endif static int iso_hash_enter_indirect ( int *conn, Line *edge, hash_table_ptr hash, int *o, float *data_values ) { Line lookup; if ( data_values [ edge->p ] == 0.0 ) { lookup.p = conn [ edge->p ]; lookup.q = conn [ edge->p ]; } else if ( data_values [ edge->q ] == 0.0 ) { lookup.p = conn [ edge->q ]; lookup.q = conn [ edge->q ]; } else { lookup.p = conn [ edge->p ]; lookup.q = conn [ edge->q ]; } return iso_hash_enter ( &lookup, hash, o ); } #ifdef INCLUDES_BAND static int band_hash_enter_indirect ( int *conn, Line *edge, band_value_sel select, hash_table_ptr hash, int *o, float *data_values, float *band_values ) { Line lookup; if ( select == NEITHER_VALUE ) { lookup.p = conn [ edge->p ]; lookup.q = conn [ edge->q ]; } else { if ( data_values [ edge->p ] == band_values [ select ] ) { lookup.p = conn [ edge->p ]; lookup.q = conn [ edge->p ]; } else if ( data_values [ edge->q ] == band_values [ select ] ) { lookup.p = conn [ edge->q ]; lookup.q = conn [ edge->q ]; } else { lookup.p = conn [ edge->p ]; lookup.q = conn [ edge->q ]; } } return band_hash_enter ( &lookup, select, hash, o ); } #endif #define IVTX(E,N) iso_hash_enter_indirect \ ( conn, E, vtab, &poly[N], data_values ) #define BVTX(E,S,N) band_hash_enter_indirect \ ( conn, E, S, vtab, &poly[N], data_values, band_values ) #define BCHK(E,S) DXASSERT \ ( ( E->p == E->q ) == ( S == NEITHER_VALUE ) ) #define TRI(A,B,C) \ if (( poly[A] != poly[B] )&&( poly[B] != poly[C] )&&( poly[C] != poly[A] ))\ if (ERROR == ( tp = (Triangle*)DXNewSegListItem ( tlis ))) goto error;\ else { tp->p = poly[A]; tp->q = poly[B]; tp->r = poly[C]; } static Error make_iso_line ( int *conn, Line *e0, Line *e1, hash_table_ptr vtab, hash_table_ptr ltab, float *data_values ) { int poly[2]; int XXX; #ifdef WHITEBOX_TEST histograms.polygonalizations[2]++; #endif if ( !IVTX ( e0, 0 ) || !IVTX ( e1, 1 ) ) goto error; if ( poly[0] != poly[1] ) if ( !iso_hash_enter ( (Line*)poly, ltab, &XXX ) ) goto error; return OK; error: ERROR_SECTION; return ERROR; } #ifdef INCLUDES_BAND static Error make_band_line ( int *conn, Line *e0, Line *e1, band_value_sel s0, band_value_sel s1, hash_table_ptr vtab, SegList *llis, float *data_values, float *band_values ) { int poly[2]; Line *lp; #ifdef WHITEBOX_TEST histograms.polygonalizations[2]++; #endif BCHK(e0,s0);BCHK(e1,s1); if ( !BVTX ( e0, s0, 0 ) || !BVTX ( e1, s1, 1 ) ) goto error; if ( poly[0] != poly[1] ) if ( ERROR == ( lp = (Line*) DXNewSegListItem ( llis ) ) ) goto error; else { lp->p = poly[0]; lp->q = poly[1]; } return OK; error: ERROR_SECTION; return ERROR; } #endif static Error make_iso_poly_3 ( int *conn, Line *e0, Line *e1, Line *e2, hash_table_ptr vtab, SegList *tlis, float *data_values ) { int poly[3]; Triangle *tp; #ifdef WHITEBOX_TEST histograms.polygonalizations[3]++; #endif if ( !IVTX ( e0, 0 ) || !IVTX ( e1, 1 ) || !IVTX ( e2, 2 ) ) goto error; TRI ( 0, 1, 2 ); return OK; error: ERROR_SECTION; return ERROR; } #ifdef INCLUDES_BAND static Error make_band_poly_3 ( int *conn, Line *e0, Line *e1, Line *e2, band_value_sel s0, band_value_sel s1, band_value_sel s2, hash_table_ptr vtab, SegList *tlis, float *data_values, float *band_values ) { int poly[3]; Triangle *tp; #ifdef WHITEBOX_TEST histograms.polygonalizations[3]++; #endif BCHK(e0,s0);BCHK(e1,s1);BCHK(e2,s2); if ( !BVTX ( e0, s0, 0 ) || !BVTX ( e1, s1, 1 ) || !BVTX ( e2, s2, 2 ) ) goto error; TRI ( 0, 1, 2 ); return OK; error: ERROR_SECTION; return ERROR; } #endif static Error make_iso_poly_4 ( int *conn, Line *e0, Line *e1, Line *e2, Line *e3, hash_table_ptr vtab, SegList *tlis, float *data_values ) { Triangle *tp; int poly[4]; #ifdef WHITEBOX_TEST histograms.polygonalizations[4]++; #endif if ( !IVTX ( e0, 0 ) || !IVTX ( e1, 1 ) || !IVTX ( e2, 2 ) || !IVTX ( e3, 3 ) ) goto error; TRI ( 0, 1, 2 ); TRI ( 0, 2, 3 ); return OK; error: ERROR_SECTION; return ERROR; } #ifdef INCLUDES_BAND static Error make_band_poly_4 ( int *conn, Line *e0, Line *e1, Line *e2, Line *e3, band_value_sel s0, band_value_sel s1, band_value_sel s2, band_value_sel s3, hash_table_ptr vtab, SegList *tlis, float *data_values, float *band_values ) { Triangle *tp; int poly[4]; #ifdef WHITEBOX_TEST histograms.polygonalizations[4]++; #endif BCHK(e0,s0);BCHK(e1,s1);BCHK(e2,s2);BCHK(e3,s3); if ( !BVTX ( e0, s0, 0 ) || !BVTX ( e1, s1, 1 ) || !BVTX ( e2, s2, 2 ) || !BVTX ( e3, s3, 3 ) ) goto error; TRI ( 0, 1, 2 ); TRI ( 0, 2, 3 ); return OK; error: ERROR_SECTION; return ERROR; } #endif static Error make_iso_poly_5 ( int *conn, Line *e0, Line *e1, Line *e2, Line *e3, Line *e4, hash_table_ptr vtab, SegList *tlis, float *data_values ) { Triangle *tp; int poly[5]; #ifdef WHITEBOX_TEST histograms.polygonalizations[5]++; #endif if ( !IVTX ( e0, 0 ) || !IVTX ( e1, 1 ) || !IVTX ( e2, 2 ) || !IVTX ( e3, 3 ) || !IVTX ( e4, 4 ) ) goto error; TRI ( 0, 1, 2 ); TRI ( 0, 2, 3 ); TRI ( 0, 3, 4 ); return OK; error: ERROR_SECTION; return ERROR; } #ifdef INCLUDES_BAND static Error make_band_poly_5 ( int *conn, Line *e0, Line *e1, Line *e2, Line *e3, Line *e4, band_value_sel s0, band_value_sel s1, band_value_sel s2, band_value_sel s3, band_value_sel s4, hash_table_ptr vtab, SegList *tlis, float *data_values, float *band_values ) { Triangle *tp; int poly[5]; #ifdef WHITEBOX_TEST histograms.polygonalizations[5]++; #endif BCHK(e0,s0);BCHK(e1,s1);BCHK(e2,s2);BCHK(e3,s3);BCHK(e4,s4); if ( !BVTX ( e0, s0, 0 ) || !BVTX ( e1, s1, 1 ) || !BVTX ( e2, s2, 2 ) || !BVTX ( e3, s3, 3 ) || !BVTX ( e4, s4, 4 ) ) goto error; TRI ( 0, 1, 2 ); TRI ( 0, 2, 3 ); TRI ( 0, 3, 4 ); return OK; error: ERROR_SECTION; return ERROR; } #endif static Error make_iso_poly_6 ( int *conn, Line *e0, Line *e1, Line *e2, Line *e3, Line *e4, Line *e5, hash_table_ptr vtab, SegList *tlis, float *data_values ) { Triangle *tp; int poly[6]; #ifdef WHITEBOX_TEST histograms.polygonalizations[6]++; #endif if ( !IVTX ( e0, 0 ) || !IVTX ( e1, 1 ) || !IVTX ( e2, 2 ) || !IVTX ( e3, 3 ) || !IVTX ( e4, 4 ) || !IVTX ( e5, 5 ) ) goto error; TRI ( 0, 1, 2 ); TRI ( 0, 2, 3 ); TRI ( 0, 3, 4 ); TRI ( 0, 4, 5 ); return OK; error: ERROR_SECTION; return ERROR; } #ifdef INCLUDES_BAND static Error make_band_poly_6 ( int *conn, Line *e0, Line *e1, Line *e2, Line *e3, Line *e4, Line *e5, band_value_sel s0, band_value_sel s1, band_value_sel s2, band_value_sel s3, band_value_sel s4, band_value_sel s5, hash_table_ptr vtab, SegList *tlis, float *data_values, float *band_values ) { Triangle *tp; int poly[6]; #ifdef WHITEBOX_TEST histograms.polygonalizations[6]++; #endif BCHK(e0,s0);BCHK(e1,s1);BCHK(e2,s2);BCHK(e3,s3);BCHK(e4,s4);BCHK(e5,s5); if ( !BVTX ( e0, s0, 0 ) || !BVTX ( e1, s1, 1 ) || !BVTX ( e2, s2, 2 ) || !BVTX ( e3, s3, 3 ) || !BVTX ( e4, s4, 4 ) || !BVTX ( e5, s5, 5 ) ) goto error; TRI ( 0, 1, 2 ); TRI ( 0, 2, 3 ); TRI ( 0, 3, 4 ); TRI ( 0, 4, 5 ); return OK; error: ERROR_SECTION; return ERROR; } #endif static Error make_iso_poly_7 ( int *conn, Line *e0, Line *e1, Line *e2, Line *e3, Line *e4, Line *e5, Line *e6, hash_table_ptr vtab, SegList *tlis, float *data_values ) { Triangle *tp; int poly[7]; #ifdef WHITEBOX_TEST histograms.polygonalizations[7]++; #endif if ( !IVTX ( e0, 0 ) || !IVTX ( e1, 1 ) || !IVTX ( e2, 2 ) || !IVTX ( e3, 3 ) || !IVTX ( e4, 4 ) || !IVTX ( e5, 5 ) || !IVTX ( e6, 6 ) ) goto error; TRI ( 0, 1, 3 ); TRI ( 0, 3, 4 ); TRI ( 0, 4, 6 ); TRI ( 6, 4, 5 ); TRI ( 1, 2, 3 ); return OK; error: ERROR_SECTION; return ERROR; } #undef IVTX #undef BVTX #undef POLY #ifdef INCLUDES_BAND static Error band_convert_line ( Line *line, float data_values[2], float *value_p, int index, hash_table_ptr vtx_hash, SegList *line_list, int equivalence ) { float value_low = value_p [ index ]; float value_high = value_p [ index + 1 ]; static Line line_edge[3] = { { 0, 1 }, { 0, 0 }, { 1, 1 } }; int signature = 0; if ( equivalence == 1 ); if ( data_values[0] > value_low ) signature += 1; if ( data_values[0] > value_high ) signature += 2; if ( data_values[1] > value_low ) signature += 4; if ( data_values[1] > value_high ) signature += 8; #ifdef WHITEBOX_TEST DXDebug ( "I", "Signature = %d", signature ); histograms.case_signatures[signature]++; #endif switch ( signature ) { /* * This table was entered symbolically into a file called table.DB * and then converted to 'C' code in a file 'table.C' by a script * named 'table.MAK'. * All files currently reside in the directory ~allain/kalvin. */ #define LINE(A,B,C,D) if ( !make_band_line ( (int *)line, \ &line_edge[A], \ &line_edge[B], \ ((C==0)?-1:(index+C-1)), \ ((D==0)?-1:(index+D-1)), \ vtx_hash, line_list, data_values, value_p ) ) goto error; case 0: case 15: break; case 1: LINE ( 1,0, 0,1 ); break; case 3: LINE ( 0,0, 2,1 ); break; case 4: LINE ( 0,2, 1,0 ); break; case 5: LINE ( 1,2, 0,0 ); break; case 7: LINE ( 0,2, 2,0 ); break; case 12: LINE ( 0,0, 1,2 ); break; case 13: LINE ( 1,0, 0,2 ); break; default: DXSetError ( ERROR_ASSERTION, "case signature %d", signature ); goto error; #undef LINE } return OK; error: ERROR_SECTION; return ERROR; } #endif static Error iso_convert_triangle ( Triangle *tri, float data_values[3], hash_table_ptr vtx_hash, hash_table_ptr edge_hash, int equivalence ) { static Line tri_edge[3] = { { 0, 1 }, { 1, 2 }, { 2, 0 } }; int signature = 0; if ( equivalence == 1 ) { if ( data_values[0] > 0.0 ) signature += 1; if ( data_values[1] > 0.0 ) signature += 2; if ( data_values[2] > 0.0 ) signature += 4; } else { if ( data_values[0] == 0.0 ) signature += 1; if ( data_values[1] == 0.0 ) signature += 2; if ( data_values[2] == 0.0 ) signature += 4; } #ifdef WHITEBOX_TEST DXDebug ( "I", "Signature = %d", signature ); histograms.case_signatures[signature]++; #endif switch ( signature ) { /* * This table was entered symbolically into a file called table.DB * and then converted to 'C' code in a file 'table.C' by a script * named 'table.MAK'. * All files currently reside in the directory ~allain/kalvin. */ #define LINE(A,B) if ( !make_iso_line ( (int *)tri, &tri_edge[A], \ &tri_edge[B], vtx_hash, edge_hash, data_values ) ) \ goto error; case 0: break; case 1: LINE ( 0, 2 ); break; case 2: LINE ( 0, 1 ); break; case 3: LINE ( 1, 2 ); break; case 4: LINE ( 1, 2 ); break; case 5: LINE ( 0, 1 ); break; case 6: LINE ( 0, 2 ); break; case 7: break; #undef LINE } return OK; error: ERROR_SECTION; return ERROR; } #ifdef INCLUDES_BAND static Error band_convert_triangle ( Triangle *tri, float data_values[3], float *value_p, int index, hash_table_ptr vtx_hash, SegList *tri_list, int equivalence ) { float value_low = value_p [ index ]; float value_high = value_p [ index + 1 ]; static Line tri_edge[6] = { { 0, 1 }, { 1, 2 }, { 2, 0 }, { 0, 0 }, { 1, 1 }, { 2, 2 } }; int signature = 0; if ( equivalence == 1 ); if ( data_values[0] > value_low ) signature += 1; if ( data_values[0] > value_high ) signature += 2; if ( data_values[1] > value_low ) signature += 4; if ( data_values[1] > value_high ) signature += 8; if ( data_values[2] > value_low ) signature += 16; if ( data_values[2] > value_high ) signature += 32; #ifdef WHITEBOX_TEST DXDebug ( "I", "Signature = %d", signature ); histograms.case_signatures[signature]++; #endif switch ( signature ) { /* * This table was entered symbolically into a file called table.DB * and then converted to 'C' code in a file 'table.C' by a script * named 'table.MAK'. * All files currently reside in the directory ~allain/kalvin. */ #define POLY3(A,B,C,D,E,F) if(!make_band_poly_3((int*)tri, \ &tri_edge[A], \ &tri_edge[B], \ &tri_edge[C], \ ((D==0)?-1:(index+D-1)), \ ((E==0)?-1:(index+E-1)), \ ((F==0)?-1:(index+F-1)), \ vtx_hash, tri_list, data_values, value_p ) ) goto error; #define POLY4(A,B,C,D,E,F,G,H) if(!make_band_poly_4((int*)tri, \ &tri_edge[A], \ &tri_edge[B], \ &tri_edge[C], \ &tri_edge[D], \ ((E==0)?-1:(index+E-1)), \ ((F==0)?-1:(index+F-1)), \ ((G==0)?-1:(index+G-1)), \ ((H==0)?-1:(index+H-1)), \ vtx_hash, tri_list, data_values, value_p ) ) goto error; #define POLY5(A,B,C,D,E,F,G,H,I,J) if(!make_band_poly_5((int*)tri, \ &tri_edge[A], \ &tri_edge[B], \ &tri_edge[C], \ &tri_edge[D], \ &tri_edge[E], \ ((F==0)?-1:(index+F-1)), \ ((G==0)?-1:(index+G-1)), \ ((H==0)?-1:(index+H-1)), \ ((I==0)?-1:(index+I-1)), \ ((J==0)?-1:(index+J-1)), \ vtx_hash, tri_list, data_values, value_p ) ) goto error; case 0: case 63: break; case 1: POLY3 ( 0,2,3, 1,1,0 ); break; case 3: POLY4 ( 0,0,2,2, 2,1,1,2 ); break; case 4: POLY3 ( 4,1,0, 0,1,1 ); break; case 5: POLY4 ( 3,4,1,2, 0,0,1,1 ); break; case 7: POLY5 ( 0,4,1,2,2, 2,0,1,1,2 ); break; case 12: POLY4 ( 0,0,1,1, 1,2,2,1 ); break; case 13: POLY5 ( 3,0,1,1,2, 0,2,2,1,1 ); break; case 15: POLY4 ( 2,1,1,2, 2,2,1,1 ); break; case 16: POLY3 ( 2,1,5, 1,1,0 ); break; case 17: POLY4 ( 3,0,1,5, 0,1,1,0 ); break; case 19: POLY5 ( 0,0,1,5,2, 2,1,1,0,2 ); break; case 20: POLY4 ( 0,4,5,2, 1,0,0,1 ); break; case 21: POLY3 ( 3,4,5, 0,0,0 ); break; case 23: POLY4 ( 0,4,5,2, 2,0,0,2 ); break; case 28: POLY5 ( 0,0,1,5,2, 1,2,2,0,1 ); break; case 29: POLY4 ( 3,0,1,5, 0,2,2,0 ); break; case 31: POLY3 ( 2,1,5, 2,2,0 ); break; case 48: POLY4 ( 2,1,1,2, 1,1,2,2 ); break; case 49: POLY5 ( 3,0,1,1,2, 0,1,1,2,2 ); break; case 51: POLY4 ( 0,0,1,1, 2,1,1,2 ); break; case 52: POLY5 ( 0,4,1,2,2, 1,0,2,2,1 ); break; case 53: POLY4 ( 3,4,1,2, 0,0,2,2 ); break; case 55: POLY3 ( 0,4,1, 2,0,2 ); break; case 60: POLY4 ( 0,0,2,2, 1,2,2,1 ); break; case 61: POLY3 ( 3,0,2, 0,2,2 ); break; default: DXSetError ( ERROR_ASSERTION, "case signature %d", signature ); goto error; #undef POLY3 #undef POLY4 #undef POLY5 } return OK; error: ERROR_SECTION; return ERROR; } #endif static Error iso_convert_quadrilateral ( Quadrilateral *quad, float data_values[4], hash_table_ptr vtx_hash, hash_table_ptr edge_hash, int equivalence ) { #if 0 Triangle n_tri; float n_data_values[3]; int i, j; static int cvt[2][3] = { { 0, 2, 3 }, { 0, 3, 1 } }; for ( i=0; i<2; i++ ) { for ( j=0; j<3; j++ ) { n_data_values[j] = data_values [ cvt[i][j] ]; ((int *)&n_tri)[j] = ((int *)quad) [ cvt[i][j] ]; } if ( !iso_convert_triangle ( &n_tri, n_data_values, vtx_hash, edge_hash, equivalence ) ) goto error; } #else static Line quad_edge[4] = { { 0, 1 }, { 1, 3 }, { 2, 3 }, { 0, 2 } }; int signature = 0; if ( equivalence == 1 ) { if ( data_values[0] > 0.0 ) signature += 1; if ( data_values[1] > 0.0 ) signature += 2; if ( data_values[2] > 0.0 ) signature += 4; if ( data_values[3] > 0.0 ) signature += 8; } else { if ( data_values[0] == 0.0 ) signature += 1; if ( data_values[1] == 0.0 ) signature += 2; if ( data_values[2] == 0.0 ) signature += 4; if ( data_values[3] == 0.0 ) signature += 8; } #ifdef WHITEBOX_TEST DXDebug ( "I", "Signature = %d", signature ); histograms.case_signatures[signature]++; #endif switch ( signature ) { /* * This table was entered symbolically into a file called table.DB * and then converted to 'C' code in a file 'table.C' by a script * named 'table.MAK'. * All files currently reside in the directory ~allain/kalvin. */ #define LINE(A,B) if ( !make_iso_line ( (int *)quad, &quad_edge[A], \ &quad_edge[B], vtx_hash, edge_hash, data_values ) ) \ goto error; case 0: break; case 1: LINE ( 0,3 ); break; case 2: LINE ( 0,1 ); break; case 3: LINE ( 1,3 ); break; case 4: LINE ( 2,3 ); break; case 5: LINE ( 0,2 ); break; case 6: LINE ( 0,1 ); LINE ( 2,3 ); break; case 7: LINE ( 1,2 ); break; case 8: LINE ( 1,2 ); break; case 9: LINE ( 0,3 ); LINE ( 1,2 ); break; case 10: LINE ( 0,2 ); break; case 11: LINE ( 2,3 ); break; case 12: LINE ( 1,3 ); break; case 13: LINE ( 0,1 ); break; case 14: LINE ( 0,3 ); break; case 15: break; #undef LINE } #endif return OK; error: ERROR_SECTION; return ERROR; } #ifdef INCLUDES_BAND static Error band_convert_quadrilateral ( Quadrilateral *quad, float data_values[4], float *value_p, int index, hash_table_ptr vtx_hash, SegList *tri_list, int equivalence ) { #if 0 Triangle n_tri; float n_data_values[3]; int i, j; static int cvt[2][3] = { { 0, 2, 3 }, { 0, 3, 1 } }; for ( i=0; i<2; i++ ) { for ( j=0; j<3; j++ ) { n_data_values[j] = data_values [ cvt[i][j] ]; ((int *)&n_tri)[j] = ((int *)quad) [ cvt[i][j] ]; } if ( !band_convert_triangle ( &n_tri, n_data_values, value_p, index, vtx_hash, tri_list, equivalence ) ) goto error; } #else float value_low = value_p [ index ]; float value_high = value_p [ index + 1 ]; static Line quad_edge[8] = { { 0, 1 }, { 1, 3 }, { 2, 3 }, { 0, 2 }, { 0, 0 }, { 1, 1 }, { 2, 2 }, { 3, 3 } }; int signature = 0; if ( equivalence == 1 ); if ( data_values[0] > value_low ) signature += 1; if ( data_values[0] > value_high ) signature += 2; if ( data_values[1] > value_low ) signature += 4; if ( data_values[1] > value_high ) signature += 8; if ( data_values[2] > value_low ) signature += 16; if ( data_values[2] > value_high ) signature += 32; if ( data_values[3] > value_low ) signature += 64; if ( data_values[3] > value_high ) signature += 128; #ifdef WHITEBOX_TEST DXDebug ( "I", "Signature = %d", signature ); histograms.case_signatures[signature]++; #endif switch ( signature ) { #define POLY3(A,B,C,D,E,F) if(!make_band_poly_3((int*)quad, \ &quad_edge[A], \ &quad_edge[B], \ &quad_edge[C], \ ((D==0)?-1:(index+D-1)), \ ((E==0)?-1:(index+E-1)), \ ((F==0)?-1:(index+F-1)), \ vtx_hash, tri_list, data_values, value_p ) ) goto error; #define POLY4(A,B,C,D,E,F,G,H) if(!make_band_poly_4((int*)quad, \ &quad_edge[A], \ &quad_edge[B], \ &quad_edge[C], \ &quad_edge[D], \ ((E==0)?-1:(index+E-1)), \ ((F==0)?-1:(index+F-1)), \ ((G==0)?-1:(index+G-1)), \ ((H==0)?-1:(index+H-1)), \ vtx_hash, tri_list, data_values, value_p ) ) goto error; #define POLY5(A,B,C,D,E,F,G,H,I,J) if(!make_band_poly_5((int*)quad, \ &quad_edge[A], \ &quad_edge[B], \ &quad_edge[C], \ &quad_edge[D], \ &quad_edge[E], \ ((F==0)?-1:(index+F-1)), \ ((G==0)?-1:(index+G-1)), \ ((H==0)?-1:(index+H-1)), \ ((I==0)?-1:(index+I-1)), \ ((J==0)?-1:(index+J-1)), \ vtx_hash, tri_list, data_values, value_p ) ) goto error; #define POLY6(A,B,C,D,E,F,G,H,I,J,K,L) if(!make_band_poly_6((int*)quad, \ &quad_edge[A], \ &quad_edge[B], \ &quad_edge[C], \ &quad_edge[D], \ &quad_edge[E], \ &quad_edge[F], \ ((G==0)?-1:(index+G-1)), \ ((H==0)?-1:(index+H-1)), \ ((I==0)?-1:(index+I-1)), \ ((J==0)?-1:(index+J-1)), \ ((K==0)?-1:(index+K-1)), \ ((L==0)?-1:(index+L-1)), \ vtx_hash, tri_list, data_values, value_p ) ) goto error; case 0: case 255: break; case 1: POLY3 ( 4,0,3, 0,1,1 ); break; case 3: POLY4 ( 0,0,3,3, 2,1,1,2 ); break; case 4: POLY3 ( 0,5,1, 1,0,1 ); break; case 5: POLY4 ( 4,5,1,3, 0,0,1,1 ); break; case 7: POLY5 ( 0,5,1,3,3, 2,0,1,1,2 ); break; case 12: POLY4 ( 0,0,1,1, 1,2,2,1 ); break; case 13: POLY5 ( 4,0,1,1,3, 0,2,2,1,1 ); break; case 15: POLY4 ( 3,1,1,3, 2,2,1,1 ); break; case 16: POLY3 ( 3,2,6, 1,1,0 ); break; case 17: POLY4 ( 4,0,2,6, 0,1,1,0 ); break; case 19: POLY5 ( 0,0,2,6,3, 2,1,1,0,2 ); break; case 20: POLY3 ( 0,5,1, 1,0,1 ); POLY3 ( 3,2,6, 1,1,0 ); break; case 21: POLY5 ( 4,5,1,2,6, 0,0,1,1,0 ); break; case 23: POLY6 ( 0,5,1,2,6,3, 2,0,1,1,0,2 ); break; case 28: POLY3 ( 3,2,6, 1,1,0 ); POLY4 ( 0,0,1,1, 1,2,2,1 ); break; case 29: POLY6 ( 4,0,1,1,2,6, 0,2,2,1,1,0 ); break; case 31: POLY5 ( 3,1,1,2,6, 2,2,1,1,0 ); break; case 48: POLY4 ( 3,2,2,3, 1,1,2,2 ); break; case 49: POLY5 ( 4,0,2,2,3, 0,1,1,2,2 ); break; case 51: POLY4 ( 0,0,2,2, 2,1,1,2 ); break; case 52: POLY3 ( 0,5,1, 1,0,1 ); POLY4 ( 3,2,2,3, 1,1,2,2 ); break; case 53: POLY6 ( 4,5,1,2,2,3, 0,0,1,1,2,2 ); break; case 55: POLY5 ( 0,5,1,2,2, 2,0,1,1,2 ); break; case 60: POLY4 ( 3,2,2,3, 1,1,2,2 ); POLY4 ( 0,0,1,1, 1,2,2,1 ); break; case 61: POLY3 ( 4,0,3, 0,2,2 ); POLY6 ( 0,1,1,2,2,3, 2,2,1,1,2,2 ); break; case 63: POLY4 ( 2,1,1,2, 2,2,1,1 ); break; case 64: POLY3 ( 1,7,2, 1,0,1 ); break; case 65: POLY3 ( 4,0,3, 0,1,1 ); POLY3 ( 1,7,2, 1,0,1 ); break; case 67: POLY3 ( 2,1,7, 1,1,0 ); POLY4 ( 3,0,0,3, 2,2,1,1 ); break; case 68: POLY4 ( 0,5,7,2, 1,0,0,1 ); break; case 69: POLY5 ( 4,5,7,2,3, 0,0,0,1,1 ); break; case 71: POLY6 ( 0,5,7,2,3,3, 2,0,0,1,1,2 ); break; case 76: POLY5 ( 0,0,1,7,2, 1,2,2,0,1 ); break; case 77: POLY6 ( 4,0,1,7,2,3, 0,2,2,0,1,1 ); break; case 79: POLY5 ( 3,1,7,2,3, 2,2,0,1,1 ); break; case 80: POLY4 ( 3,1,7,6, 1,1,0,0 ); break; case 81: POLY5 ( 4,0,1,7,6, 0,1,1,0,0 ); break; case 83: POLY6 ( 0,0,1,7,6,3, 2,1,1,0,0,2 ); break; case 84: POLY5 ( 0,5,7,6,3, 1,0,0,0,1 ); break; case 85: POLY4 ( 4,5,7,6, 0,0,0,0 ); break; case 87: POLY5 ( 0,5,7,6,3, 2,0,0,0,2 ); break; case 92: POLY6 ( 0,0,1,7,6,3, 1,2,2,0,0,1 ); break; case 93: POLY5 ( 4,0,1,7,6, 0,2,2,0,0 ); break; case 95: POLY4 ( 3,1,7,6, 2,2,0,0 ); break; case 112: POLY5 ( 3,1,7,2,3, 1,1,0,2,2 ); break; case 113: POLY6 ( 4,0,1,7,2,3, 0,1,1,0,2,2 ); break; case 115: POLY5 ( 0,0,1,7,2, 2,1,1,0,2 ); break; case 116: POLY6 ( 0,5,7,2,3,3, 1,0,0,2,2,1 ); break; case 117: POLY5 ( 4,5,7,2,3, 0,0,0,2,2 ); break; case 119: POLY4 ( 0,5,7,2, 2,0,0,2 ); break; case 124: POLY3 ( 1,7,2, 2,0,2 ); POLY6 ( 0,0,1,2,3,3, 1,2,2,2,2,1 ); break; case 125: POLY6 ( 4,0,1,7,2,3, 0,2,2,0,2,2 ); break; case 127: POLY3 ( 1,7,2, 2,0,2 ); break; case 192: POLY4 ( 1,1,2,2, 1,2,2,1 ); break; case 193: POLY3 ( 4,0,3, 0,1,1 ); POLY4 ( 1,1,2,2, 1,2,2,1 ); break; case 195: POLY4 ( 0,0,3,3, 2,1,1,2 ); POLY4 ( 1,1,2,2, 1,2,2,1 ); break; case 196: POLY5 ( 0,5,1,2,2, 1,0,2,2,1 ); break; case 197: POLY6 ( 4,5,1,2,2,3, 0,0,2,2,1,1 ); break; case 199: POLY3 ( 0,5,1, 2,0,2 ); POLY6 ( 0,1,2,2,3,3, 2,2,2,1,1,2 ); break; case 204: POLY4 ( 0,0,2,2, 1,2,2,1 ); break; case 205: POLY5 ( 4,0,2,2,3, 0,2,2,1,1 ); break; case 207: POLY4 ( 3,2,2,3, 2,2,1,1 ); break; case 208: POLY5 ( 3,1,1,2,6, 1,1,2,2,0 ); break; case 209: POLY6 ( 4,0,1,1,2,6, 0,1,1,2,2,0 ); break; case 211: POLY3 ( 3,2,6, 2,2,0 ); POLY6 ( 0,0,1,1,2,3, 2,1,1,2,2,2 ); break; case 212: POLY6 ( 0,5,1,2,6,3, 1,0,2,2,0,1 ); break; case 213: POLY5 ( 4,5,1,2,6, 0,0,2,2,0 ); break; case 215: POLY6 ( 3,0,5,1,2,6, 2,2,0,2,2,0 ); break; case 220: POLY5 ( 0,0,2,6,3, 1,2,2,0,1 ); break; case 221: POLY4 ( 4,0,2,6, 0,2,2,0 ); break; case 223: POLY3 ( 3,2,6, 2,2,0 ); break; case 240: POLY4 ( 3,1,1,3, 1,1,2,2 ); break; case 241: POLY5 ( 4,0,1,1,3, 0,1,1,2,2 ); break; case 243: POLY4 ( 0,0,1,1, 2,1,1,2 ); break; case 244: POLY5 ( 0,5,1,3,3, 1,0,2,2,1 ); break; case 245: POLY4 ( 4,5,1,3, 0,0,2,2 ); break; case 247: POLY3 ( 0,5,1, 2,0,2 ); break; case 252: POLY4 ( 0,0,3,3, 1,2,2,1 ); break; case 253: POLY3 ( 4,0,3, 0,2,2 ); break; default: DXSetError ( ERROR_ASSERTION, "case signature %d", signature ); goto error; #undef POLY3 #undef POLY4 #undef POLY5 #undef POLY6 } #endif return OK; error: ERROR_SECTION; return ERROR; } #endif static Error iso_convert_tetrahedron ( Tetrahedron *tet, float data_values[4], hash_table_ptr vtx_hash, SegList *tri_list, int equivalence ) { static Line tetra_edge[6] = { { 0, 1 }, { 1, 2 }, { 0, 2 }, { 0, 3 }, { 1, 3 }, { 2, 3 } }; int signature = 0; if ( equivalence == 1 ) { if ( data_values[0] > 0.0 ) signature += 1; if ( data_values[1] > 0.0 ) signature += 2; if ( data_values[2] > 0.0 ) signature += 4; if ( data_values[3] > 0.0 ) signature += 8; } else { if ( data_values[0] == 0.0 ) signature += 1; if ( data_values[1] == 0.0 ) signature += 2; if ( data_values[2] == 0.0 ) signature += 4; if ( data_values[3] == 0.0 ) signature += 8; } #ifdef WHITEBOX_TEST DXDebug ( "I", "Signature = %d", signature ); histograms.case_signatures[signature]++; #endif switch ( signature ) { /* * This table was entered symbolically into a file called table.DB * and then converted to 'C' code in a file 'table.C' by a script * named 'table.MAK'. * All files currently reside in the directory ~allain/kalvin. */ /* coded in inversions imply that the table is reversed */ #define POLY3(A,B,C) if(!make_iso_poly_3((int*)tet, \ &tetra_edge[C], &tetra_edge[B], &tetra_edge[A], \ vtx_hash, tri_list, data_values ) ) goto error; #define POLY4(A,B,C,D) if(!make_iso_poly_4((int*)tet, \ &tetra_edge[D], &tetra_edge[C], \ &tetra_edge[B], &tetra_edge[A], \ vtx_hash, tri_list, data_values ) ) goto error; case 0: break; case 1: POLY3 ( 0, 2, 3 ); break; case 2: POLY3 ( 0, 4, 1 ); break; case 3: POLY4 ( 1, 2, 3, 4 ); break; case 4: POLY3 ( 1, 5, 2 ); break; case 5: POLY4 ( 0, 1, 5, 3 ); break; case 6: POLY4 ( 0, 4, 5, 2 ); break; case 7: POLY3 ( 3, 4, 5 ); break; case 8: POLY3 ( 3, 5, 4 ); break; case 9: POLY4 ( 0, 2, 5, 4 ); break; case 10: POLY4 ( 0, 3, 5, 1 ); break; case 11: POLY3 ( 1, 2, 5 ); break; case 12: POLY4 ( 1, 4, 3, 2 ); break; case 13: POLY3 ( 0, 1, 4 ); break; case 14: POLY3 ( 0, 3, 2 ); break; case 15: break; #undef POLY3 #undef POLY4 default: break; } return OK; error: ERROR_SECTION; return ERROR; } static Error iso_convert_cube ( Cube *cube, float data_values[8], hash_table_ptr vtx_hash, SegList *tri_list, int equivalence ) { static Line cube_edge[12] = { { 0, 1 }, { 1, 3 }, { 0, 2 }, { 2, 3 }, { 4, 5 }, { 5, 7 }, { 4, 6 }, { 6, 7 }, { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 } }; int signature = 0; if ( equivalence == 1 ) { if ( data_values[0] > 0.0 ) signature += 1; if ( data_values[1] > 0.0 ) signature += 2; if ( data_values[2] > 0.0 ) signature += 4; if ( data_values[3] > 0.0 ) signature += 8; if ( data_values[4] > 0.0 ) signature += 16; if ( data_values[5] > 0.0 ) signature += 32; if ( data_values[6] > 0.0 ) signature += 64; if ( data_values[7] > 0.0 ) signature += 128; } else { if ( data_values[0] == 0.0 ) signature += 1; if ( data_values[1] == 0.0 ) signature += 2; if ( data_values[2] == 0.0 ) signature += 4; if ( data_values[3] == 0.0 ) signature += 8; if ( data_values[4] == 0.0 ) signature += 16; if ( data_values[5] == 0.0 ) signature += 32; if ( data_values[6] == 0.0 ) signature += 64; if ( data_values[7] == 0.0 ) signature += 128; } #ifdef WHITEBOX_TEST DXDebug ( "I", "Signature = %d", signature ); histograms.case_signatures[signature]++; #endif switch ( signature ) { /* * This table was entered symbolically into a file called table.DB * and then converted to 'C' code in a file 'table.C' by a script * named 'table.MAK'. * All files currently reside in the directory ~allain/kalvin. */ #define POLY3(A,B,C) if(!make_iso_poly_3((int*)cube, \ &cube_edge[A], &cube_edge[B], &cube_edge[C], \ vtx_hash, tri_list, data_values ) ) goto error; #define POLY4(A,B,C,D) if(!make_iso_poly_4((int*)cube, \ &cube_edge[A], &cube_edge[B], &cube_edge[C], \ &cube_edge[D], \ vtx_hash, tri_list, data_values ) ) goto error; #define POLY5(A,B,C,D,E) if(!make_iso_poly_5((int*)cube, \ &cube_edge[A], &cube_edge[B], &cube_edge[C], \ &cube_edge[D], &cube_edge[E], \ vtx_hash, tri_list, data_values ) ) goto error; #define POLY6(A,B,C,D,E,F) if(!make_iso_poly_6((int*)cube, \ &cube_edge[A], &cube_edge[B], &cube_edge[C], \ &cube_edge[D], &cube_edge[E], &cube_edge[F], \ vtx_hash, tri_list, data_values ) ) goto error; #define POLY7(A,B,C,D,E,F,G) if(!make_iso_poly_7((int*)cube, \ &cube_edge[A], &cube_edge[B], &cube_edge[C], \ &cube_edge[D], &cube_edge[E], &cube_edge[F], \ &cube_edge[G], \ vtx_hash, tri_list, data_values ) ) goto error; case 0: break; case 1: POLY3 ( 0, 2, 8 ); break; case 2: POLY3 ( 0, 9, 1 ); break; case 3: POLY4 ( 1, 2, 8, 9 ); break; case 4: POLY3 ( 2, 3, 10 ); break; case 5: POLY4 ( 0, 3, 10, 8 ); break; case 6: POLY3 ( 0, 9, 1 ); POLY3 ( 2, 3, 10 ); break; case 7: POLY5 ( 1, 3, 10, 8, 9 ); break; case 8: POLY3 ( 1, 11, 3 ); break; case 9: POLY3 ( 1, 11, 3 ); POLY3 ( 0, 2, 8 ); break; case 10: POLY4 ( 0, 9, 11, 3 ); break; case 11: POLY5 ( 2, 8, 9, 11, 3 ); break; case 12: POLY4 ( 1, 11, 10, 2 ); break; case 13: POLY5 ( 0, 1, 11, 10, 8 ); break; case 14: POLY5 ( 0, 9, 11, 10, 2 ); break; case 15: POLY4 ( 8, 9, 11, 10 ); break; case 16: POLY3 ( 4, 8, 6 ); break; case 17: POLY4 ( 0, 2, 6, 4 ); break; case 18: POLY3 ( 4, 8, 6 ); POLY3 ( 0, 9, 1 ); break; case 19: POLY5 ( 1, 2, 6, 4, 9 ); break; case 20: POLY3 ( 4, 8, 6 ); POLY3 ( 2, 3, 10 ); break; case 21: POLY5 ( 0, 3, 10, 6, 4 ); break; case 22: POLY3 ( 4, 8, 6 ); POLY3 ( 2, 3, 10 ); POLY3 ( 0, 9, 1 ); break; case 23: POLY6 ( 1, 3, 10, 6, 4, 9 ); break; case 24: POLY3 ( 4, 8, 6 ); POLY3 ( 1, 11, 3 ); break; case 25: POLY4 ( 0, 2, 6, 4 ); POLY3 ( 1, 11, 3 ); break; case 26: POLY3 ( 4, 8, 6 ); POLY4 ( 0, 9, 11, 3 ); break; case 27: POLY6 ( 2, 6, 4, 9, 11, 3 ); break; case 28: POLY3 ( 4, 8, 6 ); POLY4 ( 1, 11, 10, 2 ); break; case 29: POLY6 ( 0, 1, 11, 10, 6, 4 ); break; case 30: POLY3 ( 4, 8, 6 ); POLY5 ( 0, 9, 11, 10, 2 ); break; case 31: POLY5 ( 4, 9, 11, 10, 6 ); break; case 32: POLY3 ( 4, 5, 9 ); break; case 33: POLY3 ( 4, 5, 9 ); POLY3 ( 0, 2, 8 ); break; case 34: POLY4 ( 0, 4, 5, 1 ); break; case 35: POLY5 ( 1, 2, 8, 4, 5 ); break; case 36: POLY3 ( 2, 3, 10 ); POLY3 ( 4, 5, 9 ); break; case 37: POLY4 ( 0, 3, 10, 8 ); POLY3 ( 4, 5, 9 ); break; case 38: POLY4 ( 0, 4, 5, 1 ); POLY3 ( 2, 3, 10 ); break; case 39: POLY6 ( 1, 3, 10, 8, 4, 5 ); break; case 40: POLY3 ( 4, 5, 9 ); POLY3 ( 1, 11, 3 ); break; case 41: POLY3 ( 4, 5, 9 ); POLY3 ( 1, 11, 3 ); POLY3 ( 0, 2, 8 ); break; case 42: POLY5 ( 0, 4, 5, 11, 3 ); break; case 43: POLY6 ( 2, 8, 4, 5, 11, 3 ); break; case 44: POLY3 ( 4, 5, 9 ); POLY4 ( 1, 11, 10, 2 ); break; case 45: POLY3 ( 4, 5, 9 ); POLY5 ( 0, 1, 11, 10, 8 ); break; case 46: POLY6 ( 0, 4, 5, 11, 10, 2 ); break; case 47: POLY5 ( 4, 5, 11, 10, 8 ); break; case 48: POLY4 ( 5, 9, 8, 6 ); break; case 49: POLY5 ( 0, 2, 6, 5, 9 ); break; case 50: POLY5 ( 0, 8, 6, 5, 1 ); break; case 51: POLY4 ( 1, 2, 6, 5 ); break; case 52: POLY4 ( 5, 9, 8, 6 ); POLY3 ( 2, 3, 10 ); break; case 53: POLY6 ( 0, 3, 10, 6, 5, 9 ); break; case 54: POLY3 ( 2, 3, 10 ); POLY5 ( 0, 8, 6, 5, 1 ); break; case 55: POLY5 ( 1, 3, 10, 6, 5 ); break; case 56: POLY3 ( 1, 11, 3 ); POLY4 ( 5, 9, 8, 6 ); break; case 57: POLY3 ( 1, 11, 3 ); POLY5 ( 0, 2, 6, 5, 9 ); break; case 58: POLY6 ( 0, 8, 6, 5, 11, 3 ); break; case 59: POLY5 ( 2, 6, 5, 11, 3 ); break; case 60: POLY4 ( 5, 9, 8, 6 ); POLY4 ( 1, 11, 10, 2 ); break; case 61: POLY7 ( 0, 1, 11, 10, 6, 5, 9 ); break; case 62: POLY7 ( 0, 8, 6, 5, 11, 10, 2 ); break; case 63: POLY4 ( 5, 11, 10, 6 ); break; case 64: POLY3 ( 6, 10, 7 ); break; case 65: POLY3 ( 6, 10, 7 ); POLY3 ( 0, 2, 8 ); break; case 66: POLY3 ( 6, 10, 7 ); POLY3 ( 0, 9, 1 ); break; case 67: POLY3 ( 6, 10, 7 ); POLY4 ( 1, 2, 8, 9 ); break; case 68: POLY4 ( 2, 3, 7, 6 ); break; case 69: POLY5 ( 0, 3, 7, 6, 8 ); break; case 70: POLY3 ( 0, 9, 1 ); POLY4 ( 2, 3, 7, 6 ); break; case 71: POLY6 ( 1, 3, 7, 6, 8, 9 ); break; case 72: POLY3 ( 6, 10, 7 ); POLY3 ( 1, 11, 3 ); break; case 73: POLY3 ( 6, 10, 7 ); POLY3 ( 1, 11, 3 ); POLY3 ( 0, 2, 8 ); break; case 74: POLY3 ( 6, 10, 7 ); POLY4 ( 0, 9, 11, 3 ); break; case 75: POLY3 ( 6, 10, 7 ); POLY5 ( 2, 8, 9, 11, 3 ); break; case 76: POLY5 ( 1, 11, 7, 6, 2 ); break; case 77: POLY6 ( 0, 1, 11, 7, 6, 8 ); break; case 78: POLY6 ( 0, 9, 11, 7, 6, 2 ); break; case 79: POLY5 ( 7, 6, 8, 9, 11 ); break; case 80: POLY4 ( 4, 8, 10, 7 ); break; case 81: POLY5 ( 0, 2, 10, 7, 4 ); break; case 82: POLY4 ( 4, 8, 10, 7 ) POLY3 ( 0, 9, 1 ); break; case 83: POLY6 ( 1, 2, 10, 7, 4, 9 ); break; case 84: POLY5 ( 2, 3, 7, 4, 8 ); break; case 85: POLY4 ( 0, 3, 7, 4 ); break; case 86: POLY5 ( 2, 3, 7, 4, 8 ); POLY3 ( 0, 9, 1 ); break; case 87: POLY5 ( 1, 3, 7, 4, 9 ); break; case 88: POLY4 ( 4, 8, 10, 7 ); POLY3 ( 1, 11, 3 ); break; case 89: POLY5 ( 0, 2, 10, 7, 4 ); POLY3 ( 1, 11, 3 ); break; case 90: POLY4 ( 4, 8, 10, 7 ); POLY4 ( 0, 9, 11, 3 ); break; case 91: POLY7 ( 2, 10, 7, 4, 9, 11, 3 ); break; case 92: POLY6 ( 1, 11, 7, 4, 8, 2 ); break; case 93: POLY5 ( 0, 1, 11, 7, 4 ); break; case 94: POLY7 ( 2, 0, 9, 11, 7, 4, 8 ); break; case 95: POLY4 ( 4, 9, 11, 7 ); break; case 96: POLY3 ( 6, 10, 7 ); POLY3 ( 4, 5, 9 ); break; case 97: POLY3 ( 6, 10, 7 ); POLY3 ( 4, 5, 9 ); POLY3 ( 0, 2, 8 ); break; case 98: POLY3 ( 6, 10, 7 ); POLY4 ( 0, 4, 5, 1 ); break; case 99: POLY3 ( 6, 10, 7 ); POLY5 ( 1, 2, 8, 4, 5 ); break; case 100: POLY4 ( 2, 3, 7, 6 ); POLY3 ( 4, 5, 9 ); break; case 101: POLY5 ( 0, 3, 7, 6, 8 ); POLY3 ( 4, 5, 9 ); break; case 102: POLY4 ( 0, 4, 5, 1 ); POLY4 ( 2, 3, 7, 6 ); break; case 103: POLY7 ( 8, 4, 5, 1, 3, 7, 6 ); break; case 104: POLY3 ( 6, 10, 7 ); POLY3 ( 4, 5, 9 ); POLY3 ( 1, 11, 3 ); break; case 105: POLY3 ( 6, 10, 7 ); POLY3 ( 4, 5, 9 ); POLY3 ( 1, 11, 3 ); POLY3 ( 0, 2, 8 ); break; case 106: POLY3 ( 6, 10, 7 ); POLY5 ( 0, 4, 5, 11, 3 ); break; case 107: POLY3 ( 6, 10, 7 ); POLY6 ( 2, 8, 4, 5, 11, 3 ); break; case 108: POLY3 ( 4, 5, 9 ); POLY5 ( 1, 11, 7, 6, 2 ); break; case 109: POLY3 ( 4, 5, 9 ); POLY6 ( 0, 1, 11, 7, 6, 8 ); break; case 110: POLY7 ( 11, 7, 6, 2, 0, 4, 5 ); break; case 111: POLY6 ( 11, 7, 6, 8, 4, 5 ); break; case 112: POLY5 ( 5, 9, 8, 10, 7 ); break; case 113: POLY6 ( 0, 2, 10, 7, 5, 9 ); break; case 114: POLY6 ( 0, 8, 10, 7, 5, 1 ); break; case 115: POLY5 ( 1, 2, 10, 7, 5 ); break; case 116: POLY6 ( 2, 3, 7, 5, 9, 8 ); break; case 117: POLY5 ( 0, 3, 7, 5, 9 ); break; case 118: POLY7 ( 8, 2, 3, 7, 5, 1, 0 ); break; case 119: POLY4 ( 1, 3, 7, 5 ); break; case 120: POLY3 ( 1, 11, 3 ); POLY5 ( 5, 9, 8, 10, 7 ); break; case 121: POLY3 ( 1, 11, 3 ); POLY6 ( 0, 2, 10, 7, 5, 9 ); break; case 122: POLY7 ( 5, 11, 3, 0, 8, 10, 7 ); break; case 123: POLY6 ( 2, 10, 7, 5, 11, 3 ); break; case 124: POLY7 ( 7, 5, 9, 8, 2, 1, 11 ); break; case 125: POLY6 ( 0, 1, 11, 7, 5, 9 ); break; case 126: POLY3 ( 5, 11, 7 ); POLY3 ( 0, 8, 2 ); break; case 127: POLY3 ( 5, 11, 7 ); break; case 128: POLY3 ( 5, 7, 11 ); break; case 129: POLY3 ( 5, 7, 11 ); POLY3 ( 0, 2, 8 ); break; case 130: POLY3 ( 5, 7, 11 ); POLY3 ( 0, 9, 1 ); break; case 131: POLY3 ( 5, 7, 11 ); POLY4 ( 1, 2, 8, 9 ); break; case 132: POLY3 ( 5, 7, 11 ); POLY3 ( 2, 3, 10 ); break; case 133: POLY3 ( 5, 7, 11 ); POLY4 ( 0, 3, 10, 8 ); break; case 134: POLY3 ( 5, 7, 11 ); POLY3 ( 0, 9, 1 ); POLY3 ( 2, 3, 10 ); break; case 135: POLY3 ( 5, 7, 11 ); POLY5 ( 1, 3, 10, 8, 9 ); break; case 136: POLY4 ( 1, 5, 7, 3 ); break; case 137: POLY3 ( 0, 2, 8 ); POLY4 ( 1, 5, 7, 3 ); break; case 138: POLY5 ( 0, 9, 5, 7, 3 ); break; case 139: POLY6 ( 2, 8, 9, 5, 7, 3 ); break; case 140: POLY5 ( 1, 5, 7, 10, 2 ); break; case 141: POLY6 ( 0, 1, 5, 7, 10, 8 ); break; case 142: POLY6 ( 0, 9, 5, 7, 10, 2 ); break; case 143: POLY5 ( 5, 7, 10, 8, 9 ); break; case 144: POLY3 ( 5, 7, 11 ); POLY3 ( 4, 8, 6 ); break; case 145: POLY3 ( 5, 7, 11 ); POLY4 ( 0, 2, 6, 4 ); break; case 146: POLY3 ( 5, 7, 11 ); POLY3 ( 4, 8, 6 ); POLY3 ( 0, 9, 1 ); break; case 147: POLY3 ( 5, 7, 11 ); POLY5 ( 1, 2, 6, 4, 9 ); break; case 148: POLY3 ( 5, 7, 11 ); POLY3 ( 4, 8, 6 ); POLY3 ( 2, 3, 10 ); break; case 149: POLY3 ( 5, 7, 11 ); POLY5 ( 0, 3, 10, 6, 4 ); break; case 150: POLY3 ( 5, 7, 11 ); POLY3 ( 4, 8, 6 ); POLY3 ( 2, 3, 10 ); POLY3 ( 0, 9, 1 ); break; case 151: POLY3 ( 5, 7, 11 ); POLY6 ( 1, 3, 10, 6, 4, 9 ); break; case 152: POLY3 ( 4, 8, 6 ); POLY4 ( 1, 5, 7, 3 ); break; case 153: POLY4 ( 0, 2, 6, 4 ); POLY4 ( 1, 5, 7, 3 ); break; case 154: POLY3 ( 4, 8, 6 ); POLY5 ( 0, 9, 5, 7, 3 ); break; case 155: POLY7 ( 9, 5, 7, 3, 2, 6, 4 ); break; case 156: POLY3 ( 4, 8, 6 ); POLY5 ( 1, 5, 7, 10, 2 ); break; case 157: POLY7 ( 10, 6, 4, 0, 1, 5, 7 ); break; case 158: POLY3 ( 4, 8, 6 ); POLY6 ( 0, 9, 5, 7, 10, 2 ); break; case 159: POLY6 ( 9, 5, 7, 10, 6, 4 ); break; case 160: POLY4 ( 4, 7, 11, 9 ); break; case 161: POLY4 ( 4, 7, 11, 9 ); POLY3 ( 0, 2, 8 ); break; case 162: POLY5 ( 0, 4, 7, 11, 1 ); break; case 163: POLY6 ( 1, 2, 8, 4, 7, 11 ); break; case 164: POLY4 ( 4, 7, 11, 9 ); POLY3 ( 2, 3, 10 ); break; case 165: POLY4 ( 4, 7, 11, 9 ); POLY4 ( 0, 3, 10, 8 ); break; case 166: POLY3 ( 2, 3, 10 ); POLY5 ( 0, 4, 7, 11, 1 ); break; case 167: POLY7 ( 1, 3, 10, 8, 4, 7, 11 ); break; case 168: POLY5 ( 1, 9, 4, 7, 3 ); break; case 169: POLY5 ( 1, 9, 4, 7, 3 ) POLY3 ( 0, 2, 8 ); break; case 170: POLY4 ( 0, 4, 7, 3 ); break; case 171: POLY5 ( 2, 8, 4, 7, 3 ); break; case 172: POLY6 ( 1, 9, 4, 7, 10, 2 ); break; case 173: POLY7 ( 1, 9, 4, 7, 10, 8, 0 ); break; case 174: POLY5 ( 0, 4, 7, 10, 2 ); break; case 175: POLY4 ( 4, 7, 10, 8 ); break; case 176: POLY5 ( 6, 7, 11, 9, 8 ); break; case 177: POLY6 ( 0, 2, 6, 7, 11, 9 ); break; case 178: POLY6 ( 0, 8, 6, 7, 11, 1 ); break; case 179: POLY5 ( 1, 2, 6, 7, 11 ); break; case 180: POLY3 ( 2, 3, 10 ); POLY5 ( 6, 7, 11, 9, 8 ); break; case 181: POLY7 ( 6, 7, 11, 9, 0, 3, 10 ); break; case 182: POLY3 ( 2, 3, 10 ); POLY6 ( 0, 8, 6, 7, 11, 1 ); break; case 183: POLY6 ( 1, 3, 10, 6, 7, 11 ); break; case 184: POLY6 ( 1, 9, 8, 6, 7, 3 ); break; case 185: POLY7 ( 9, 0, 2, 6, 7, 3, 1 ); break; case 186: POLY5 ( 0, 8, 6, 7, 3 ); break; case 187: POLY4 ( 2, 6, 7, 3 ); break; case 188: POLY7 ( 7, 10, 2, 1, 9, 8, 6 ); break; case 189: POLY3 ( 6, 7, 10 ); POLY3 ( 0, 1, 9 ); break; case 190: POLY6 ( 0, 8, 6, 7, 10, 2 ); break; case 191: POLY3 ( 6, 7, 10 ); break; case 192: POLY4 ( 5, 6, 10, 11 ); break; case 193: POLY4 ( 5, 6, 10, 11 ); POLY3 ( 0, 2, 8 ); break; case 194: POLY4 ( 5, 6, 10, 11 ); POLY3 ( 0, 9, 1 ); break; case 195: POLY4 ( 5, 6, 10, 11 ); POLY4 ( 1, 2, 8, 9 ); break; case 196: POLY5 ( 2, 3, 11, 5, 6 ); break; case 197: POLY6 ( 0, 3, 11, 5, 6, 8 ); break; case 198: POLY3 ( 0, 9, 1 ); POLY5 ( 2, 3, 11, 5, 6 ); break; case 199: POLY7 ( 3, 11, 5, 6, 8, 9, 1 ); break; case 200: POLY5 ( 1, 5, 6, 10, 3 ); break; case 201: POLY5 ( 0, 1, 5, 6, 8 ); POLY3 ( 2, 10, 3 ); break; case 202: POLY6 ( 0, 9, 5, 6, 10, 3 ); break; case 203: POLY7 ( 3, 2, 8, 9, 5, 6, 10 ); break; case 204: POLY4 ( 1, 5, 6, 2 ); break; case 205: POLY5 ( 0, 1, 5, 6, 8 ); break; case 206: POLY5 ( 0, 9, 5, 6, 2 ); break; case 207: POLY4 ( 5, 6, 8, 9 ); break; case 208: POLY5 ( 4, 8, 10, 11, 5 ); break; case 209: POLY6 ( 0, 2, 10, 11, 5, 4 ); break; case 210: POLY3 ( 0, 9, 1 ); POLY5 ( 4, 8, 10, 11, 5 ); break; case 211: POLY7 ( 4, 9, 1, 2, 10, 11, 5 ); break; case 212: POLY6 ( 2, 3, 11, 5, 4, 8 ); break; case 213: POLY5 ( 0, 3, 11, 5, 4 ); break; case 214: POLY3 ( 0, 9, 1 ); POLY6 ( 2, 3, 11, 5, 4, 8 ); break; case 215: POLY6 ( 3, 11, 5, 4, 9, 1 ); break; case 216: POLY6 ( 1, 5, 4, 8, 10, 3 ); break; case 217: POLY7 ( 10, 3, 1, 5, 4, 0, 2 ); break; case 218: POLY7 ( 5, 4, 8, 10, 3, 0, 9 ); break; case 219: POLY3 ( 4, 9, 5 ); POLY3 ( 2, 10, 3 ); break; case 220: POLY5 ( 1, 5, 4, 8, 2 ); break; case 221: POLY4 ( 0, 1, 5, 4 ); break; case 222: POLY6 ( 5, 4, 8, 2, 0, 9 ); break; case 223: POLY3 ( 4, 9, 5 ); break; case 224: POLY5 ( 4, 6, 10, 11, 9 ); break; case 225: POLY3 ( 0, 2, 8 ); POLY5 ( 4, 6, 10, 11, 9 ); break; case 226: POLY6 ( 0, 4, 6, 10, 11, 1 ); break; case 227: POLY7 ( 4, 6, 10, 11, 1, 2, 8 ); break; case 228: POLY6 ( 2, 3, 11, 9, 4, 6 ); break; case 229: POLY7 ( 6, 8, 0, 3, 11, 9, 4 ); break; case 230: POLY7 ( 11, 1, 0, 4, 6, 2, 3 ); break; case 231: POLY3 ( 1, 3, 11 ); POLY3 ( 4, 6, 8 ); break; case 232: POLY6 ( 1, 9, 4, 6, 10, 3 ); break; case 233: POLY3 ( 0, 2, 8 ); POLY6 ( 1, 9, 4, 6, 10, 3 ); break; case 234: POLY5 ( 0, 4, 6, 10, 3 ); break; case 235: POLY6 ( 4, 6, 10, 3, 2, 8 ); break; case 236: POLY5 ( 1, 9, 4, 6, 2 ); break; case 237: POLY6 ( 1, 9, 4, 6, 8, 0 ); break; case 238: POLY4 ( 0, 4, 6, 2 ); break; case 239: POLY3 ( 4, 6, 8 ); break; case 240: POLY4 ( 8, 10, 11, 9 ); break; case 241: POLY5 ( 0, 2, 10, 11, 9 ); break; case 242: POLY5 ( 0, 8, 10, 11, 1 ); break; case 243: POLY4 ( 1, 2, 10, 11 ); break; case 244: POLY5 ( 2, 3, 11, 9, 8 ); break; case 245: POLY4 ( 0, 3, 11, 9 ); break; case 246: POLY6 ( 8, 2, 3, 11, 1, 0 ); break; case 247: POLY3 ( 1, 3, 11 ); break; case 248: POLY5 ( 1, 9, 8, 10, 3 ); break; case 249: POLY6 ( 10, 3, 1, 9, 0, 2 ); break; case 250: POLY4 ( 0, 8, 10, 3 ); break; case 251: POLY3 ( 2, 10, 3 ); break; case 252: POLY4 ( 1, 9, 8, 2 ); break; case 253: POLY3 ( 0, 1, 9 ); break; case 254: POLY3 ( 0, 8, 2 ); break; case 255: break; default: break; #undef POLY3 #undef POLY4 #undef POLY5 #undef POLY6 #undef POLY7 } return OK; error: ERROR_SECTION; return ERROR; } static Error iso_convert_prism ( Prism *prism, float data_values[6], hash_table_ptr vtx_hash, SegList *tri_list, int equivalence ) { int signature = 0; DXErrorGoto2 ( ERROR_NOT_IMPLEMENTED, "#11380", /* %s is an invalid connections type */ "\"prism\"" ); if ( equivalence == 1 ) { if ( data_values[0] > 0.0 ) signature += 1; if ( data_values[1] > 0.0 ) signature += 2; if ( data_values[2] > 0.0 ) signature += 4; if ( data_values[3] > 0.0 ) signature += 8; if ( data_values[4] > 0.0 ) signature += 16; if ( data_values[5] > 0.0 ) signature += 32; } else { if ( data_values[0] == 0.0 ) signature += 1; if ( data_values[1] == 0.0 ) signature += 2; if ( data_values[2] == 0.0 ) signature += 4; if ( data_values[3] == 0.0 ) signature += 8; if ( data_values[4] == 0.0 ) signature += 16; if ( data_values[5] == 0.0 ) signature += 32; } #ifdef WHITEBOX_TEST DXDebug ( "I", "Signature = %d", signature ); histograms.case_signatures[signature]++; #endif switch ( signature ) { /* * This table was entered symbolically into a file called table.DB * and then converted to 'C' code in a file 'table.C' by a script * named 'table.MAK'. * All files currently reside in the directory ~allain/kalvin. */ default: break; #undef LINE } return OK; error: ERROR_SECTION; return ERROR; } static Field create_iso_points ( field_info input_info, float *value_ptr, int is_grown, Error (*convert_connection) (void *, float *, hash_table_ptr, hash_table_ptr, int), /* (void *, float *, hash_table_ptr, SegList *, int),*/ Field out ) { float value = value_ptr [ 0 ]; array_info pi_info, ci_info, di_info = NULL; array_info po_info = NULL; hash_table_rec vtx_hash; Line line; Point point[2]; float data[2]; double t; iso_edge_hash_ptr element_ptr = NULL; int i, j; field_info output_info = NULL; int position_dim; int connection_shape; int XXX; array_info a_info; component_info comp; Array array = NULL; Pointer scratch = NULL; Pointer out_data = NULL; InvalidComponentHandle i_handle = NULL; DXASSERTGOTO ( ERROR != input_info ); DXASSERTGOTO ( ERROR != value_ptr ); DXASSERTGOTO ( ERROR != out ); vtx_hash.count = 0; vtx_hash.table = NULL; vtx_hash.set_vertices = NULL; pi_info = (array_info) &(input_info->std_comps[(int)POSITIONS]->array); ci_info = (array_info) &(input_info->std_comps[(int)CONNECTIONS]->array); di_info = (array_info) &(input_info->std_comps[(int)DATA]->array); if ( ( NULL != input_info->std_comps[(int)INVALID_CONNECTIONS] ) && ( ERROR == ( i_handle = DXCreateInvalidComponentHandle ( (Object)input_info->field, NULL, "connections" ) ) ) ) goto error; DXASSERTGOTO ( pi_info->get_item != ERROR ); DXASSERTGOTO ( ci_info->get_item != ERROR ); DXASSERTGOTO ( di_info->get_item != ERROR ); if ( ( pi_info->shape[0] != 1 ) && ( pi_info->shape[0] != 2 ) && ( pi_info->shape[0] != 3 ) ) DXErrorGoto3 ( ERROR_INVALID_DATA, "#11400", /* %s has invalid dimensionality; does not match %s */ "\"positions\" component", "\"connections\"" ); position_dim = pi_info->shape[0]; connection_shape = ci_info->shape[0]; DXASSERTGOTO ( connection_shape == 2 ); DXASSERTGOTO ( ci_info->items >= ci_info->original_items ); TST_HASH_INTS; if ( ( ERROR == ( vtx_hash.table = DXCreateHash ( sizeof(iso_edge_hash_rec), iso_edge_hash_func, iso_edge_compare_func ) ) ) ) goto error; if ( ci_info->get_item == _dxf_get_conn_grid_LINES ) { array_info t0; int II; int I0; t0 = (array_info) &(((struct _array_allocator *)((mesh_array_info)ci_info)->terms)[0]); DXASSERTGOTO ( ((grid_connections_info)ci_info)->counts != NULL ); DXASSERTGOTO ( t0->items == ( ((grid_connections_info)ci_info)->counts[0] - 1 ) ); if ( ((mesh_array_info)ci_info)->grow_offsets != NULL ) { DXASSERTGOTO ( is_grown ); I0 = ((mesh_array_info)ci_info)->grow_offsets[0]; } else I0 = 0; if ( !ci_info->get_item ( I0, ci_info, &line ) || !di_info->get_item ( line.p, di_info, &data[0] ) ) goto error; data[0] -= value; for ( II=I0; II<( I0 + t0->original_items ); II++, line.p++, line.q++, data[0] = data[1] ) { if ( !di_info->get_item ( line.q, di_info, &data[1] ) ) goto error; data[1] -= value; /* iso_convert_line */ if ( ( NULL != i_handle ) && DXIsElementInvalid (i_handle, II) ) continue; else if ( ( ( data[0] <= 0.0 ) && ( data[1] > 0.0 ) ) || ( ( data[0] > 0.0 ) && ( data[1] <= 0.0 ) ) ) /* XXX indirect with dummy line */ if ( !iso_hash_enter ( &line, &vtx_hash, &XXX ) ) goto error; } } else { for ( i=0; ioriginal_items; i++ ) if ( ( NULL != i_handle ) && DXIsElementInvalid ( i_handle, i ) ) continue; else if ( !ci_info->get_item ( i, ci_info, &line ) ) goto error; else { if ( !di_info->get_item ( line.p, di_info, &data[0] ) || !di_info->get_item ( line.q, di_info, &data[1] ) ) goto error; data[0] -= value; data[1] -= value; /* iso_convert_line */ if ( ( ( data[0] <= 0.0 ) && ( data[1] > 0.0 ) ) || ( ( data[0] > 0.0 ) && ( data[1] <= 0.0 ) ) ) /* XXX indirect with dummy line */ if ( !iso_hash_enter ( &line, &vtx_hash, &XXX ) ) goto error; } } if ( !create_output_arrays ( out, vtx_hash.count, position_dim, 0, 0, 0, DEFAULT_LINE_COLOR, value, DEP_POSITIONS, ISOSURFACE ) ) goto error; if ( vtx_hash.count == 0 ) goto done; if ( ( ERROR == ( output_info = ( _dxf_InMemory ( out ) ) ) ) || !DXInitGetNextHashElement ( vtx_hash.table ) ) goto error; DXASSERTGOTO ( output_info->std_comps[(int)POSITIONS] != NULL ); po_info = (array_info) &(output_info->std_comps[(int)POSITIONS]->array); for ( j=0, comp=input_info->comp_list; jcomp_count; j++, comp++ ) { if ( ( 0 != strcmp ( comp->name, "positions" ) ) && ( ( NULL == comp->std_attribs[(int)DEP] ) || ( ERROR == comp->std_attribs[(int)DEP]->value ) || ( 0 != strcmp ( comp->std_attribs[(int)DEP]->value, "positions" ) ) ) ) continue; if ( ( 0 == strcmp ( comp->name, "data" ) ) || ( 0 == strncmp ( comp->name, "original", 8 ) ) || ( NULL != comp->std_attribs[(int)REF] ) ) continue; a_info = (array_info) &(comp->array); if ( CLASS_CONSTANTARRAY == a_info->class ) { if ( ( ERROR == ( array = (Array)DXNewConstantArrayV ( vtx_hash.count, DXGetConstantArrayData ( a_info->array ), a_info->type, a_info->category, a_info->rank, a_info->shape ) ) ) || !DXSetComponentValue ( out, comp->name, (Object) array ) || !DXSetComponentAttribute ( out, comp->name, "dep", (Object) DXNewString ( "positions" ) ) ) goto error; continue; } if ( ( ERROR == ( array = DXNewArrayV ( a_info->type, a_info->category, a_info->rank, &a_info->shape[0] ) ) ) || !DXAllocateArray ( array, vtx_hash.count ) || !DXAddArrayData ( array, 0, vtx_hash.count, NULL ) || !DXTrim ( array ) || !DXSetComponentValue ( out, comp->name, (Object) array ) || !DXSetComponentAttribute ( out, comp->name, "dep", (Object) DXNewString ( "positions" ) ) || !_dxf_SetIterator ( comp ) || ( ERROR == ( out_data = DXGetArrayData ( array ))) || ( ERROR == ( scratch = DXAllocateLocal ( 2 * a_info->itemsize ))) || !DXInitGetNextHashElement ( vtx_hash.table ) ) goto error; array = NULL; for ( i = 0; ( NULL != ( element_ptr = (iso_edge_hash_ptr) DXGetNextHashElement ( vtx_hash.table ) ) ); i++ ) { DXASSERTGOTO ( element_ptr->seq < po_info->items ); if ( element_ptr->edge.p == element_ptr->edge.q ) t = 0.0; else { if ( !di_info->get_item ( element_ptr->edge.p, di_info, &data[0] )|| !di_info->get_item ( element_ptr->edge.q, di_info, &data[1] ) ) goto error; data[0] -= value; data[1] -= value; if ( data[0] == 0.0 ) t = 0.0; else if ( data[1] == 0.0 ) t = 1.0; else t = (double)data[0] / ( (double)data[0] - (double)data[1] ); DXASSERTGOTO ( ( t >= 0.0 ) && ( t <= 1.0 ) ); } if ( !interp ( a_info, scratch, element_ptr->edge.p, element_ptr->edge.q, t, &(((char*)out_data) [ a_info->itemsize * element_ptr->seq ]), a_info->itemsize/sizeof(float), a_info->itemsize) ) goto error; } DXFree ( scratch ); scratch = NULL; } done: /* This is create_iso_points */ if ( !DXSetIntegerAttribute ( (Object) out, "shade", 0 ) ) goto error; DXFreeInvalidComponentHandle ( i_handle ); DXDestroyHash ( vtx_hash.table ); DXFree ( scratch ); _dxf_FreeInMemory ( output_info ); i_handle = NULL; vtx_hash.table = NULL; vtx_hash.count = 0; output_info = NULL; scratch = NULL; return DXEndField ( out ); error: ERROR_SECTION; DXFreeInvalidComponentHandle ( i_handle ); DXDestroyHash ( vtx_hash.table ); DXFree ( scratch ); _dxf_FreeInMemory ( output_info ); i_handle = NULL; vtx_hash.table = NULL; vtx_hash.count = 0; output_info = NULL; scratch = NULL; return ERROR; } #ifdef INCLUDES_BAND static float *band_value_list ( Field field, float *vp, int *number, float *min_max, float *old_min, float *old_max ) { float *value2_ptr = NULL; int i; *number += 2; if ( ( ERROR == ( value2_ptr = (float *) DXAllocate ( (*number) * sizeof (float) ))) || ! memcpy ( (char *)(&value2_ptr[1]), (char *)vp, ( ((*number)-2) * sizeof (float) ) ) ) goto error; if ( min_max != NULL ) { value2_ptr[0] = min_max[0]; value2_ptr[(*number)-1] = min_max[1]; } else if ( !DXStatistics ( (Object)field, "data", &value2_ptr[0], &value2_ptr[(*number)-1], NULL, NULL ) ) goto error; /* If values in the input list are outside min,max: prune them off */ while ( ( value2_ptr[1] < value2_ptr[0] ) && ( (*number) > 2 ) ) { for ( i=2; i<(*number); i++ ) value2_ptr[i-1] = value2_ptr[i]; (*number)--; } while ( ( value2_ptr[(*number)-2] > value2_ptr[(*number)-1] ) && ( (*number) > 2 ) ) { value2_ptr[(*number)-2] = value2_ptr[(*number)-1]; (*number)--; } DXASSERTGOTO ( value2_ptr[0] <= value2_ptr[(*number)-1] ); *old_min = value2_ptr [ 0 ]; *old_max = value2_ptr [ (*number) - 1 ]; #if 0 /* The following "fudge" can result in band values slightly outside the */ /* range of the input data. For example: if you use AutoColor prior to */ /* band and then use the calculated colormap to color the band output, the */ /* colormap may not encompass the data. Thus I'm removing it now and will */ /* check if it introduces problems. suits 9/5/96 */ /* Ensure floating point inequality with min and max */ value2_ptr[0] = ( value2_ptr[0] == 0 )? -DXD_MIN_FLOAT : ( value2_ptr[0] > 0 )? value2_ptr[0] * ( 1.0 - DXD_FLOAT_EPSILON ) : value2_ptr[0] * ( 1.0 + DXD_FLOAT_EPSILON ); value2_ptr[*number-1] = ( value2_ptr[(*number)-1] == 0 )? DXD_MIN_FLOAT : ( value2_ptr[(*number)-1] > 0 )? value2_ptr[(*number)-1] * ( 1.0 + DXD_FLOAT_EPSILON ) : value2_ptr[(*number)-1] * ( 1.0 - DXD_FLOAT_EPSILON ); #endif return value2_ptr; error: ERROR_SECTION; DXFree ( (Pointer) value2_ptr ); return ERROR; } static Field create_band_lines ( field_info input_info, float *value_ptr, int number, band_remap_types remap, int is_grown, float *min_max, Error (*convert_connection) (void *,float *,float *,int,hash_table_ptr,SegList *,int), Field out ) { array_info pi_info, ci_info, di_info = NULL; array_info po_info, co_info, do_info = NULL; hash_table_rec vtx_hash; SegList *line_list = NULL; SegList *cval_list = NULL; Line line; Point point[2]; float data[2]; double t; band_edge_hash_ptr element_ptr = NULL; int D; int i, j; field_info output_info = NULL; int position_dim; int connection_shape; int connection_count; float value_low, value_high; float old_min, old_max; float *value2_ptr = NULL; SegList *c_ID_list = NULL; int *c_ID_pull = NULL; int n_c_dep, n_p_dep; array_info a_info; component_info comp; Array array = NULL; Pointer scratch = NULL; Pointer out_data = NULL; int itemsize; InvalidComponentHandle i_handle = NULL; DXASSERTGOTO ( ERROR != convert_connection ); DXASSERTGOTO ( ERROR != input_info ); DXASSERTGOTO ( ERROR != value_ptr ); DXASSERTGOTO ( ERROR != out ); vtx_hash.count = 0; vtx_hash.table = NULL; vtx_hash.set_vertices = NULL; if ( ( NULL != input_info->std_comps[(int)INVALID_CONNECTIONS] ) && ( ERROR == ( i_handle = DXCreateInvalidComponentHandle ( (Object)input_info->field, NULL, "connections" ) ) ) ) goto error; if ( ERROR == ( value2_ptr = band_value_list ( input_info->field, value_ptr, &number, min_max, &old_min, &old_max ) ) ) goto error; pi_info = (array_info) &(input_info->std_comps[(int)POSITIONS]->array); ci_info = (array_info) &(input_info->std_comps[(int)CONNECTIONS]->array); di_info = (array_info) &(input_info->std_comps[(int)DATA]->array); DXASSERTGOTO ( pi_info->get_item != ERROR ); DXASSERTGOTO ( ci_info->get_item != ERROR ); DXASSERTGOTO ( di_info->get_item != ERROR ); if ( ( pi_info->shape[0] != 1 ) && ( pi_info->shape[0] != 2 ) && ( pi_info->shape[0] != 3 ) ) DXErrorGoto3 ( ERROR_INVALID_DATA, "#11400", /* %s has invalid dimensionality; does not match %s */ "\"positions\" component", "\"connections\"" ); position_dim = pi_info->shape[0]; connection_shape = ci_info->shape[0]; DXASSERTGOTO ( connection_shape == 2 ); DXASSERTGOTO ( ci_info->items >= ci_info->original_items ); TST_HASH_INTS; if ( ( ERROR == ( vtx_hash.table = DXCreateHash ( sizeof(band_edge_hash_rec), band_edge_hash_func, band_edge_compare_func ) ) ) || ( ERROR == ( line_list = DXNewSegList ( sizeof(Line), 1000, 1000 ) ) ) ) goto error; if ( remap != ORIGINAL_DATA ) if ( ERROR == ( cval_list = DXNewSegList ( sizeof(float), 1000, 1000 ))) goto error; if ( !tally_dependers ( input_info, &n_c_dep, &n_p_dep ) ) goto error; if ( ( n_c_dep > 1 ) && ( ERROR == ( c_ID_list = DXNewSegList ( sizeof(int), 1000, 1000 ) ) ) ) goto error; if ( ci_info->get_item == _dxf_get_conn_grid_LINES ) { array_info t0; int II; int I0; t0 = (array_info) &(((struct _array_allocator *)((mesh_array_info)ci_info)->terms)[0]); DXASSERTGOTO ( ((grid_connections_info)ci_info)->counts != NULL ); DXASSERTGOTO ( t0->items == ( ((grid_connections_info)ci_info)->counts[0] - 1 ) ); if ( ((mesh_array_info)ci_info)->grow_offsets != NULL ) { DXASSERTGOTO ( is_grown ); I0 = ((mesh_array_info)ci_info)->grow_offsets[0]; } else I0 = 0; if ( !ci_info->get_item ( I0, ci_info, &line ) || !di_info->get_item ( line.p, di_info, &data[0] ) ) goto error; for ( II=I0; II<( I0 + t0->original_items ); II++, line.p++, line.q++, data[0] = data[1] ) { if ( !di_info->get_item ( line.q, di_info, &data[1] ) ) goto error; if ( ( NULL != i_handle ) && DXIsElementInvalid (i_handle, II) ) continue; else for ( D=0; Doriginal_items; i++ ) if ( ( NULL != i_handle ) && DXIsElementInvalid ( i_handle, i ) ) continue; else if ( !ci_info->get_item ( i, ci_info, &line ) ) goto error; else { if ( !di_info->get_item ( line.p, di_info, &data[0] ) || !di_info->get_item ( line.q, di_info, &data[1] ) ) goto error; for ( D=0; D 0 ) && ( c_ID_list != NULL ) ) { if ( ( ERROR == ( c_ID_pull = DXAllocateLocal ( connection_count * sizeof(int) ) ) ) || !copy_seglist_to_memory ( c_ID_list, c_ID_pull, sizeof(int), connection_count ) ) goto error; DXDeleteSegList ( c_ID_list ); c_ID_list = NULL; } if ( ( ERROR == ( output_info = ( _dxf_InMemory ( out ) ) ) ) || !DXInitGetNextHashElement ( vtx_hash.table ) ) goto error; DXASSERTGOTO ( output_info->std_comps[(int)POSITIONS] != NULL ); po_info = (array_info) &(output_info->std_comps[(int)POSITIONS]->array); co_info = (array_info) &(output_info->std_comps[(int)CONNECTIONS]->array); do_info = (array_info) &(output_info->std_comps[(int)DATA]->array); if ( !copy_seglist_to_array ( line_list, co_info ) ) goto error; if ( remap != ORIGINAL_DATA ) { if ( !copy_seglist_to_array ( cval_list, do_info ) ) goto error; } DXDeleteSegList ( line_list ); line_list = NULL; DXDeleteSegList ( cval_list ); cval_list = NULL; for ( j=0, comp=input_info->comp_list; jcomp_count; j++, comp++ ) { if ( ( 0 != strcmp ( comp->name, "positions" ) ) && ( ( NULL == comp->std_attribs[(int)DEP] ) || ( ERROR == comp->std_attribs[(int)DEP]->value ) || ( 0 != strcmp ( comp->std_attribs[(int)DEP]->value, "positions" ) ) ) ) continue; if ( ( ( 0 == strcmp ( comp->name, "data" ) ) && ( remap != ORIGINAL_DATA ) ) || ( 0 == strncmp ( comp->name, "original", 8 ) ) || ( NULL != comp->std_attribs[(int)REF] ) ) continue; a_info = (array_info) &(comp->array); if ( CLASS_CONSTANTARRAY == a_info->class ) { if ( ( ERROR == ( array = (Array)DXNewConstantArrayV ( vtx_hash.count, DXGetConstantArrayData ( a_info->array ), a_info->type, a_info->category, a_info->rank, a_info->shape ) ) ) || !DXSetComponentValue ( out, comp->name, (Object) array ) || !DXSetComponentAttribute ( out, comp->name, "dep", (Object) DXNewString ( "positions" ) ) ) goto error; continue; } if ( ( ERROR == ( array = DXNewArrayV ( TYPE_FLOAT, a_info->category, a_info->rank, &a_info->shape[0] ) ) ) || !DXAllocateArray ( array, vtx_hash.count ) || !DXAddArrayData ( array, 0, vtx_hash.count, NULL ) || !DXTrim ( array ) || !DXSetComponentValue ( out, comp->name, (Object) array ) || !DXSetComponentAttribute ( out, comp->name, "dep", (Object) DXNewString ( "positions" ) ) || !_dxf_SetIterator ( comp ) || ( ERROR == ( out_data = DXGetArrayData ( array ))) || !(itemsize = DXGetItemSize(array)) || ( ERROR == ( scratch = DXAllocateLocal ( 2 * itemsize))) || !DXInitGetNextHashElement ( vtx_hash.table ) ) goto error; array = NULL; for ( i = 0; ( NULL != ( element_ptr = (band_edge_hash_ptr) DXGetNextHashElement ( vtx_hash.table ) ) ); i++ ) { DXASSERTGOTO ( element_ptr->seq < po_info->items ); if ( element_ptr->edge.p == element_ptr->edge.q ) t = 0.0; else { if ( !di_info->get_item ( element_ptr->edge.p, di_info, &data[0] )|| !di_info->get_item ( element_ptr->edge.q, di_info, &data[1] ) ) goto error; /* DXASSERTGOTO ( element_ptr->select != NEITHER_VALUE ); */ value_low = value2_ptr [ element_ptr->select ]; if ( data[0] == value_low ) t = 0.0; else if ( data[1] == value_low ) t = 1.0; else t = ( (double)data[0] - (double)value_low ) / ( (double)data[0] - (double)data[1] ); DXASSERTGOTO ( ( t >= 0.0 ) && ( t <= 1.0 ) ); } if ( !interp ( a_info, scratch, element_ptr->edge.p, element_ptr->edge.q, t, &(((char*)out_data) [ a_info->itemsize * element_ptr->seq ]), itemsize/sizeof(float), itemsize) ) goto error; } DXFree ( scratch ); scratch = NULL; } for ( j=0, comp=input_info->comp_list; jcomp_count; j++, comp++ ) { if ( ( NULL == comp->std_attribs[(int)DEP] ) || ( ERROR == comp->std_attribs[(int)DEP]->value ) || ( 0 != strcmp ( comp->std_attribs[(int)DEP]->value, "connections" ) ) ) continue; if ( ( 0 == strcmp ( comp->name, "connections" ) ) || ( 0 == strncmp ( comp->name, "original", 8 ) ) || ( 0 == strcmp ( comp->name, "invalid connections" ) ) || ( NULL != comp->std_attribs[(int)REF] ) ) continue; a_info = (array_info) &(comp->array); if ( ( ERROR == ( array = _dxf_resample_array ( comp, 1, ((array_info) &(comp->array))->items, connection_count, NULL, c_ID_pull ) ) ) || !DXSetComponentValue ( out, comp->name, (Object)array ) || !DXSetComponentAttribute ( out, comp->name, "dep", (Object) DXNewString ( "connections" ) ) ) goto error; } if ( !remove_degenerates ( out ) ) goto error; done: /* This is create_band_lines */ if ( DXGetAttribute ( (Object)input_info->field, "shade" ) ) if ( !DXSetAttribute ( (Object) out, "shade", DXGetAttribute ( (Object)input_info->field, "shade" ) ) ) goto error; DXDestroyHash ( vtx_hash.table ); DXFree ( (Pointer) value2_ptr ); _dxf_FreeInMemory ( output_info ); DXDeleteSegList ( c_ID_list ); DXFree ( c_ID_pull ); DXFree ( scratch ); DXFreeInvalidComponentHandle ( i_handle ); vtx_hash.table = NULL; vtx_hash.count = 0; value2_ptr = NULL; output_info = NULL; i_handle = NULL; c_ID_list = NULL; c_ID_pull = NULL; scratch = NULL; return DXEndField ( out ); error: ERROR_SECTION; DXDestroyHash ( vtx_hash.table ); DXFree ( (Pointer) value2_ptr ); _dxf_FreeInMemory ( output_info ); DXDeleteSegList ( c_ID_list ); DXFree ( c_ID_pull ); DXFree ( scratch ); DXFreeInvalidComponentHandle ( i_handle ); vtx_hash.table = NULL; vtx_hash.count = 0; value2_ptr = NULL; output_info = NULL; i_handle = NULL; c_ID_list = NULL; c_ID_pull = NULL; scratch = NULL; return ERROR; } #endif static Field create_iso_contours ( field_info input_info, float *value_ptr, int is_grown, Error (*convert_connection) (void *, float *, hash_table_ptr, hash_table_ptr, int), /* (void *, float *, hash_table_ptr, SegList *, int),*/ Field out ) { float value = value_ptr [ 0 ]; array_info pi_info, ci_info, di_info = NULL; array_info po_info, co_info = NULL; hash_table_rec vtx_hash; hash_table_rec edge_hash; Quadrilateral quad; Point point[2]; float data[4]; double t; iso_edge_hash_ptr element_ptr = NULL; int i, j; field_info output_info = NULL; int position_dim; int connection_shape; SegList *c_ID_list = NULL; int *c_ID_pull = NULL; int n_c_dep, n_p_dep; array_info a_info; component_info comp; Array array = NULL; Pointer scratch = NULL; Pointer out_data = NULL; InvalidComponentHandle i_handle = NULL; DXASSERTGOTO ( ERROR != convert_connection ); DXASSERTGOTO ( ERROR != input_info ); DXASSERTGOTO ( ERROR != value_ptr ); DXASSERTGOTO ( ERROR != out ); vtx_hash.count = 0; vtx_hash.table = NULL; vtx_hash.set_vertices = NULL; edge_hash.count = 0; edge_hash.table = NULL; edge_hash.set_vertices = NULL; pi_info = (array_info) &(input_info->std_comps[(int)POSITIONS]->array); ci_info = (array_info) &(input_info->std_comps[(int)CONNECTIONS]->array); di_info = (array_info) &(input_info->std_comps[(int)DATA]->array); if ( ( NULL != input_info->std_comps[(int)INVALID_CONNECTIONS] ) && ( ERROR == ( i_handle = DXCreateInvalidComponentHandle ( (Object)input_info->field, NULL, "connections" ) ) ) ) goto error; DXASSERTGOTO ( pi_info->get_item != ERROR ); DXASSERTGOTO ( ci_info->get_item != ERROR ); DXASSERTGOTO ( di_info->get_item != ERROR ); if ( ( pi_info->shape[0] != 2 ) && ( pi_info->shape[0] != 3 ) ) DXErrorGoto3 ( ERROR_INVALID_DATA, "#11400", /* %s has invalid dimensionality; does not match %s */ "\"positions\" component", "\"connections\"" ); position_dim = pi_info->shape[0]; connection_shape = ci_info->shape[0]; DXASSERTGOTO ( ( connection_shape == 3 ) || ( connection_shape == 4 ) ); DXASSERTGOTO ( ci_info->items >= ci_info->original_items ); TST_HASH_INTS; if ( ( ERROR == ( vtx_hash.table = DXCreateHash ( sizeof(iso_edge_hash_rec), iso_edge_hash_func, iso_edge_compare_func ) ) ) || ( ERROR == ( edge_hash.table = DXCreateHash ( sizeof(iso_edge_hash_rec), iso_edge_hash_func, iso_edge_compare_func ) ) ) ) goto error; if ( !tally_dependers ( input_info, &n_c_dep, &n_p_dep ) ) goto error; if ( ( n_c_dep > 1 ) && ( ERROR == ( c_ID_list = DXNewSegList ( sizeof(int), 1000, 1000 ) ) ) ) goto error; if ( ci_info->get_item == _dxf_get_conn_grid_QUADS ) { array_info t0, t1; int II, JJ; int I0, J0; t0 = (array_info) &(((struct _array_allocator *)((mesh_array_info)ci_info)->terms)[0]); t1 = (array_info) &(((struct _array_allocator *)((mesh_array_info)ci_info)->terms)[1]); DXASSERTGOTO ( ((grid_connections_info)ci_info)->counts != NULL ); DXASSERTGOTO ( t0->items == ( ((grid_connections_info)ci_info)->counts[0] - 1 ) ); DXASSERTGOTO ( t1->items == ( ((grid_connections_info)ci_info)->counts[1] - 1 ) ); if ( ((mesh_array_info)ci_info)->grow_offsets != NULL ) { DXASSERTGOTO ( is_grown ); I0 = ((mesh_array_info)ci_info)->grow_offsets[0]; J0 = ((mesh_array_info)ci_info)->grow_offsets[1]; } else I0 = J0 = 0; for ( II=I0; II<( I0 + t0->original_items ); II++ ) { if ( !ci_info->get_item ( ( ( II * t1->items ) + J0 ), ci_info, &quad ) || !di_info->get_item ( quad.p, di_info, &data[0] ) || !di_info->get_item ( quad.r, di_info, &data[2] ) ) goto error; data[0] -= value; data[2] -= value; for ( JJ=J0; JJ<( J0 + t1->original_items ); JJ++, quad.p++, quad.q++, quad.r++, quad.s++, data[0] = data[1], data[2] = data[3] ) { if ( !di_info->get_item ( quad.q, di_info, &data[1] ) || !di_info->get_item ( quad.s, di_info, &data[3] ) ) goto error; data[1] -= value; data[3] -= value; if ( ( NULL != i_handle ) && DXIsElementInvalid ( i_handle, ((II*t1->items)+JJ) ) ) continue; else if ( !convert_connection ( &quad, data, &vtx_hash, &edge_hash, /* equivalence */ 1 ) ) goto error; else if ( ( NULL != c_ID_list ) && !set_c_ID ( c_ID_list, edge_hash.count, ((II*t1->items)+JJ) ) ) goto error; } } } else { for ( i=0; ioriginal_items; i++ ) if ( ( NULL != i_handle ) && DXIsElementInvalid ( i_handle, i ) ) continue; else if ( !ci_info->get_item ( i, ci_info, &quad ) ) goto error; else { for ( j=0; jget_item ( ((int *)&quad)[j], di_info, &data[j] ) ) goto error; data[j] -= value; } if ( !convert_connection ( &quad, data, &vtx_hash, &edge_hash, /* equivalence */ 1 ) ) goto error; else if ( ( NULL != c_ID_list ) && !set_c_ID ( c_ID_list, edge_hash.count, i ) ) goto error; } } if ( edge_hash.count == 0 ) if ( !_dxf_MakeFieldEmpty ( out ) ) goto error; else goto done; if ( !create_output_arrays ( out, vtx_hash.count, position_dim, edge_hash.count, 1, 0, DEFAULT_LINE_COLOR, value, DEP_POSITIONS, ISOSURFACE ) ) goto error; if ( vtx_hash.count == 0 ) goto done; if ( ( edge_hash.count > 0 ) && ( c_ID_list != NULL ) ) { if ( ( ERROR == ( c_ID_pull = DXAllocateLocal ( edge_hash.count * sizeof(int) ) ) ) || !copy_seglist_to_memory ( c_ID_list, c_ID_pull, sizeof(int), edge_hash.count ) ) goto error; DXDeleteSegList ( c_ID_list ); c_ID_list = NULL; } if ( ( ERROR == ( output_info = ( _dxf_InMemory ( out ) ) ) ) || !DXInitGetNextHashElement ( vtx_hash.table ) || !DXInitGetNextHashElement ( edge_hash.table ) ) goto error; DXASSERTGOTO ( output_info->std_comps[(int)POSITIONS] != NULL ); DXASSERTGOTO ( output_info->std_comps[(int)CONNECTIONS] != NULL ); po_info = (array_info) &(output_info->std_comps[(int)POSITIONS]->array); co_info = (array_info) &(output_info->std_comps[(int)CONNECTIONS]->array); for ( i = 0; ( NULL != ( element_ptr = (iso_edge_hash_ptr) DXGetNextHashElement ( edge_hash.table ) ) ); i++ ) { DXASSERTGOTO ( element_ptr->seq < co_info->items ); ((Line *)co_info->data) [ element_ptr->seq ] = element_ptr->edge; } DXDestroyHash ( edge_hash.table ); edge_hash.table = NULL; edge_hash.count = 0; for ( j=0, comp=input_info->comp_list; jcomp_count; j++, comp++ ) { if ( ( 0 != strcmp ( comp->name, "positions" ) ) && ( ( NULL == comp->std_attribs[(int)DEP] ) || ( ERROR == comp->std_attribs[(int)DEP]->value ) || ( 0 != strcmp ( comp->std_attribs[(int)DEP]->value, "positions" ) ) ) ) continue; if ( ( 0 == strcmp ( comp->name, "data" ) ) || ( 0 == strncmp ( comp->name, "original", 8 ) ) || ( NULL != comp->std_attribs[(int)REF] ) ) continue; a_info = (array_info) &(comp->array); if ( CLASS_CONSTANTARRAY == a_info->class ) { if ( ( ERROR == ( array = (Array)DXNewConstantArrayV ( vtx_hash.count, DXGetConstantArrayData ( a_info->array ), a_info->type, a_info->category, a_info->rank, a_info->shape ) ) ) || !DXSetComponentValue ( out, comp->name, (Object) array ) || !DXSetComponentAttribute ( out, comp->name, "dep", (Object) DXNewString ( "positions" ) ) ) goto error; continue; } if ( ( ERROR == ( array = DXNewArrayV ( a_info->type, a_info->category, a_info->rank, &a_info->shape[0] ) ) ) || !DXAllocateArray ( array, vtx_hash.count ) || !DXAddArrayData ( array, 0, vtx_hash.count, NULL ) || !DXTrim ( array ) || !DXSetComponentValue ( out, comp->name, (Object) array ) || !DXSetComponentAttribute ( out, comp->name, "dep", (Object) DXNewString ( "positions" ) ) || !_dxf_SetIterator ( comp ) || ( ERROR == ( out_data = DXGetArrayData ( array ))) || ( ERROR == ( scratch = DXAllocateLocal ( 2 * a_info->itemsize ))) || !DXInitGetNextHashElement ( vtx_hash.table ) ) goto error; array = NULL; for ( i = 0; ( NULL != ( element_ptr = (iso_edge_hash_ptr) DXGetNextHashElement ( vtx_hash.table ) ) ); i++ ) { DXASSERTGOTO ( element_ptr->seq < po_info->items ); if ( element_ptr->edge.p == element_ptr->edge.q ) t = 0.0; else { if ( !di_info->get_item ( element_ptr->edge.p, di_info, &data[0] )|| !di_info->get_item ( element_ptr->edge.q, di_info, &data[1] ) ) goto error; data[0] -= value; data[1] -= value; if ( data[0] == 0.0 ) t = 0.0; else if ( data[1] == 0.0 ) t = 1.0; else t = (double)data[0] / ( (double)data[0] - (double)data[1] ); DXASSERTGOTO ( ( t >= 0.0 ) && ( t <= 1.0 ) ); } if ( !interp ( a_info, scratch, element_ptr->edge.p, element_ptr->edge.q, t, &(((char*)out_data) [ a_info->itemsize * element_ptr->seq ]), a_info->itemsize/sizeof(float), a_info->itemsize) ) goto error; } DXFree ( scratch ); scratch = NULL; } for ( j=0, comp=input_info->comp_list; jcomp_count; j++, comp++ ) { if ( ( NULL == comp->std_attribs[(int)DEP] ) || ( ERROR == comp->std_attribs[(int)DEP]->value ) || ( 0 != strcmp ( comp->std_attribs[(int)DEP]->value, "connections" ) ) ) continue; if ( ( 0 == strcmp ( comp->name, "connections" ) ) || ( 0 == strncmp ( comp->name, "original", 8 ) ) || ( 0 == strcmp ( comp->name, "invalid connections" ) ) || ( NULL != comp->std_attribs[(int)REF] ) ) continue; a_info = (array_info) &(comp->array); if ( ( ERROR == ( array = _dxf_resample_array ( comp, 1, ((array_info) &(comp->array))->items, edge_hash.count, NULL, c_ID_pull ) ) ) || !DXSetComponentValue ( out, comp->name, (Object)array ) || !DXSetComponentAttribute ( out, comp->name, "dep", (Object) DXNewString ( "connections" ) ) ) goto error; } if ( !remove_degenerates ( out ) ) goto error; done: /* This is create_iso_contours */ if ( !DXSetIntegerAttribute ( (Object) out, "shade", 0 ) ) goto error; DXDestroyHash ( edge_hash.table ); DXDestroyHash ( vtx_hash.table ); _dxf_FreeInMemory ( output_info ); DXDeleteSegList ( c_ID_list ); DXFree ( c_ID_pull ); DXFree ( scratch ); DXFreeInvalidComponentHandle ( i_handle ); edge_hash.table = NULL; edge_hash.count = 0; vtx_hash.table = NULL; vtx_hash.count = 0; output_info = NULL; i_handle = NULL; c_ID_list = NULL; c_ID_pull = NULL; scratch = NULL; return DXEndField ( out ); error: ERROR_SECTION; DXDestroyHash ( edge_hash.table ); DXDestroyHash ( vtx_hash.table ); _dxf_FreeInMemory ( output_info ); DXDeleteSegList ( c_ID_list ); DXFree ( c_ID_pull ); DXFree ( scratch ); DXFreeInvalidComponentHandle ( i_handle ); edge_hash.table = NULL; edge_hash.count = 0; vtx_hash.table = NULL; vtx_hash.count = 0; output_info = NULL; i_handle = NULL; c_ID_list = NULL; c_ID_pull = NULL; scratch = NULL; return ERROR; } #ifdef INCLUDES_BAND static Field create_band_surface ( field_info input_info, float *value_ptr, int number, band_remap_types remap, int is_grown, float *min_max, Error (*convert_connection) (void *,float *,float *,int,hash_table_ptr,SegList *,int), Field out ) { array_info pi_info, ci_info, di_info, ni_info = NULL; array_info po_info, co_info, do_info, no_info = NULL; hash_table_rec vtx_hash; SegList *tri_list = NULL; SegList *cval_list = NULL; Quadrilateral quad; Point point[4]; float data[4]; double t; band_edge_hash_ptr element_ptr = NULL; int D; int i, j; field_info output_info = NULL; int position_dim; int connection_shape; int connection_count; float value_low, value_high; float old_min, old_max; float *value2_ptr = NULL; int have_normals = 0; SegList *c_ID_list = NULL; int *c_ID_pull = NULL; int n_c_dep, n_p_dep; array_info a_info; component_info comp; Array array = NULL; Pointer scratch = NULL; Pointer out_data = NULL; int itemsize; InvalidComponentHandle i_handle = NULL; DXASSERTGOTO ( ERROR != input_info ); DXASSERTGOTO ( ERROR != value_ptr ); DXASSERTGOTO ( ERROR != convert_connection ); DXASSERTGOTO ( ERROR != out ); vtx_hash.count = 0; vtx_hash.table = NULL; vtx_hash.set_vertices = NULL; if ( ( NULL != input_info->std_comps[(int)INVALID_CONNECTIONS] ) && ( ERROR == ( i_handle = DXCreateInvalidComponentHandle ( (Object)input_info->field, NULL, "connections" ) ) ) ) goto error; if ( ERROR == ( value2_ptr = band_value_list ( input_info->field, value_ptr, &number, min_max, &old_min, &old_max ) ) ) goto error; pi_info = (array_info) &(input_info->std_comps[(int)POSITIONS]->array); ci_info = (array_info) &(input_info->std_comps[(int)CONNECTIONS]->array); di_info = (array_info) &(input_info->std_comps[(int)DATA]->array); ni_info = (input_info->std_comps[(int)NORMALS]==NULL)? NULL: (array_info) &(input_info->std_comps[(int)NORMALS]->array); DXASSERTGOTO ( pi_info->get_item != ERROR ); DXASSERTGOTO ( ci_info->get_item != ERROR ); DXASSERTGOTO ( di_info->get_item != ERROR ); if ( ( pi_info->shape[0] != 2 ) && ( pi_info->shape[0] != 3 ) ) DXErrorGoto3 ( ERROR_INVALID_DATA, "#11400", /* %s has invalid dimensionality; does not match %s */ "\"positions\" component", "\"connections\"" ); position_dim = pi_info->shape[0]; connection_shape = ci_info->shape[0]; DXASSERTGOTO ( ( connection_shape == 3 ) || ( connection_shape == 4 ) ); DXASSERTGOTO ( ci_info->items >= ci_info->original_items ); TST_HASH_INTS; if ( ( ERROR == ( vtx_hash.table = DXCreateHash ( sizeof(band_edge_hash_rec), band_edge_hash_func, band_edge_compare_func ) ) ) || ( ERROR == ( tri_list = DXNewSegList ( sizeof(Triangle), 1000, 1000 ) ) ) ) goto error; if ( remap != ORIGINAL_DATA ) if ( ERROR == ( cval_list = DXNewSegList ( sizeof(float), 1000, 1000 ))) goto error; if ( !tally_dependers ( input_info, &n_c_dep, &n_p_dep ) ) goto error; if ( ( n_c_dep > 1 ) && ( ERROR == ( c_ID_list = DXNewSegList ( sizeof(int), 1000, 1000 ) ) ) ) goto error; if ( ci_info->get_item == _dxf_get_conn_grid_QUADS ) { array_info t0, t1; int II, JJ; int I0, J0; t0 = (array_info) &(((struct _array_allocator *)((mesh_array_info)ci_info)->terms)[0]); t1 = (array_info) &(((struct _array_allocator *)((mesh_array_info)ci_info)->terms)[1]); DXASSERTGOTO ( ((grid_connections_info)ci_info)->counts != NULL ); DXASSERTGOTO ( t0->items == ( ((grid_connections_info)ci_info)->counts[0] - 1 ) ); DXASSERTGOTO ( t1->items == ( ((grid_connections_info)ci_info)->counts[1] - 1 ) ); if ( ((mesh_array_info)ci_info)->grow_offsets != NULL ) { DXASSERTGOTO ( is_grown ); I0 = ((mesh_array_info)ci_info)->grow_offsets[0]; J0 = ((mesh_array_info)ci_info)->grow_offsets[1]; } else I0 = J0 = 0; for ( II=I0; II<( I0 + t0->original_items ); II++ ) { if ( !ci_info->get_item ( ( ( II * t1->items ) + J0 ), ci_info, &quad ) || !di_info->get_item ( quad.p, di_info, &data[0] ) || !di_info->get_item ( quad.r, di_info, &data[2] ) ) goto error; for ( JJ=J0; JJ<( J0 + t1->original_items ); JJ++, quad.p++, quad.q++, quad.r++, quad.s++, data[0] = data[1], data[2] = data[3] ) { if ( !di_info->get_item ( quad.q, di_info, &data[1] ) || !di_info->get_item ( quad.s, di_info, &data[3] ) ) goto error; if ( ( NULL != i_handle ) && DXIsElementInvalid ( i_handle, ((II*t1->items)+JJ) ) ) continue; else for ( D=0; Doriginal_items; i++ ) if ( ( NULL != i_handle ) && DXIsElementInvalid ( i_handle, i ) ) continue; else if ( !ci_info->get_item ( i, ci_info, &quad ) ) goto error; else { for ( j=0; jget_item ( ((int *)&quad)[j], di_info, &data[j] ) ) goto error; for ( D=0; D 0 ) && ( c_ID_list != NULL ) ) { if ( ( ERROR == ( c_ID_pull = DXAllocateLocal ( connection_count * sizeof(int) ) ) ) || !copy_seglist_to_memory ( c_ID_list, c_ID_pull, sizeof(int), connection_count ) ) goto error; DXDeleteSegList ( c_ID_list ); c_ID_list = NULL; } if ( ( ERROR == ( output_info = ( _dxf_InMemory ( out ) ) ) ) || !DXInitGetNextHashElement ( vtx_hash.table ) ) goto error; DXASSERTGOTO ( output_info->std_comps[(int)POSITIONS] != NULL ); po_info = (array_info) &(output_info->std_comps[(int)POSITIONS]->array); co_info = (array_info) &(output_info->std_comps[(int)CONNECTIONS]->array); do_info = (array_info) &(output_info->std_comps[(int)DATA]->array); no_info = (output_info->std_comps[(int)NORMALS]==NULL)? NULL: (array_info) &(output_info->std_comps[(int)NORMALS]->array); if ( !copy_seglist_to_array ( tri_list, co_info ) ) goto error; if ( remap != ORIGINAL_DATA ) if ( !copy_seglist_to_array ( cval_list, do_info ) ) goto error; DXDeleteSegList ( tri_list ); tri_list = NULL; DXDeleteSegList ( cval_list ); cval_list = NULL; DXASSERTGOTO ( ERROR != do_info->data ); for ( j=0, comp=input_info->comp_list; jcomp_count; j++, comp++ ) { if ( ( 0 != strcmp ( comp->name, "positions" ) ) && ( ( NULL == comp->std_attribs[(int)DEP] ) || ( ERROR == comp->std_attribs[(int)DEP]->value ) || ( 0 != strcmp ( comp->std_attribs[(int)DEP]->value, "positions" ) ) ) ) continue; if ( ( ( 0 == strcmp ( comp->name, "data" ) ) && ( remap != ORIGINAL_DATA ) ) || ( 0 == strncmp ( comp->name, "original", 8 ) ) || ( NULL != comp->std_attribs[(int)REF] ) ) continue; a_info = (array_info) &(comp->array); if ( CLASS_CONSTANTARRAY == a_info->class ) { if ( ( ERROR == ( array = (Array)DXNewConstantArrayV ( vtx_hash.count, DXGetConstantArrayData ( a_info->array ), a_info->type, a_info->category, a_info->rank, a_info->shape ) ) ) || !DXSetComponentValue ( out, comp->name, (Object) array ) || !DXSetComponentAttribute ( out, comp->name, "dep", (Object) DXNewString ( "positions" ) ) ) goto error; continue; } if ( ( ERROR == ( array = DXNewArrayV ( TYPE_FLOAT, a_info->category, a_info->rank, &a_info->shape[0] ) ) ) || !DXAllocateArray ( array, vtx_hash.count ) || !DXAddArrayData ( array, 0, vtx_hash.count, NULL ) || !DXTrim ( array ) || !DXSetComponentValue ( out, comp->name, (Object) array ) || !DXSetComponentAttribute ( out, comp->name, "dep", (Object) DXNewString ( "positions" ) ) || !_dxf_SetIterator ( comp ) || ( ERROR == ( out_data = DXGetArrayData ( array ))) || !(itemsize = DXGetItemSize(array)) || ( ERROR == ( scratch = DXAllocateLocal ( 2 * itemsize))) || !DXInitGetNextHashElement ( vtx_hash.table ) ) goto error; array = NULL; for ( i = 0; ( NULL != ( element_ptr = (band_edge_hash_ptr) DXGetNextHashElement ( vtx_hash.table ) ) ); i++ ) { DXASSERTGOTO ( element_ptr->seq < po_info->items ); if ( element_ptr->edge.p == element_ptr->edge.q ) t = 0.0; else { if ( !di_info->get_item ( element_ptr->edge.p, di_info, &data[0] )|| !di_info->get_item ( element_ptr->edge.q, di_info, &data[1] ) ) goto error; /* DXASSERTGOTO ( element_ptr->select != NEITHER_VALUE ); */ value_low = value2_ptr [ element_ptr->select ]; if ( data[0] == value_low ) t = 0.0; else if ( data[1] == value_low ) t = 1.0; else t = ( (double)data[0] - (double)value_low ) / ( (double)data[0] - (double)data[1] ); DXASSERTGOTO ( ( t >= 0.0 ) && ( t <= 1.0 ) ); } if ( !interp ( a_info, scratch, element_ptr->edge.p, element_ptr->edge.q, t, &(((char*)out_data) [ itemsize * element_ptr->seq ]), itemsize/sizeof(float), itemsize) ) goto error; } DXFree ( scratch ); scratch = NULL; } for ( j=0, comp=input_info->comp_list; jcomp_count; j++, comp++ ) { if ( ( NULL == comp->std_attribs[(int)DEP] ) || ( ERROR == comp->std_attribs[(int)DEP]->value ) || ( 0 != strcmp ( comp->std_attribs[(int)DEP]->value, "connections" ) ) ) continue; if ( ( 0 == strcmp ( comp->name, "connections" ) ) || ( 0 == strncmp ( comp->name, "original", 8 ) ) || ( 0 == strcmp ( comp->name, "invalid connections" ) ) || ( NULL != comp->std_attribs[(int)REF] ) ) continue; a_info = (array_info) &(comp->array); if ( ( ERROR == ( array = _dxf_resample_array ( comp, 1, ((array_info) &(comp->array))->items, connection_count, NULL, c_ID_pull ) ) ) || !DXSetComponentValue ( out, comp->name, (Object)array ) || !DXSetComponentAttribute ( out, comp->name, "dep", (Object) DXNewString ( "connections" ) ) ) goto error; } if ( !remove_degenerates ( out ) ) goto error; done: /* This is create_band_surface */ if ( DXGetAttribute ( (Object)input_info->field, "shade" ) ) if ( !DXSetAttribute ( (Object) out, "shade", DXGetAttribute ( (Object)input_info->field, "shade" ) ) ) goto error; DXDestroyHash ( vtx_hash.table ); DXFree ( (Pointer) value2_ptr ); _dxf_FreeInMemory ( output_info ); DXDeleteSegList ( c_ID_list ); DXFree ( c_ID_pull ); DXFree ( scratch ); DXFreeInvalidComponentHandle ( i_handle ); vtx_hash.table = NULL; vtx_hash.count = 0; value2_ptr = NULL; output_info = NULL; i_handle = NULL; c_ID_list = NULL; c_ID_pull = NULL; scratch = NULL; return DXEndField ( out ); error: ERROR_SECTION; DXDestroyHash ( vtx_hash.table ); DXFree ( (Pointer) value2_ptr ); _dxf_FreeInMemory ( output_info ); DXDeleteSegList ( c_ID_list ); DXFree ( c_ID_pull ); DXFree ( scratch ); DXFreeInvalidComponentHandle ( i_handle ); vtx_hash.table = NULL; vtx_hash.count = 0; value2_ptr = NULL; output_info = NULL; i_handle = NULL; c_ID_list = NULL; c_ID_pull = NULL; scratch = NULL; return ERROR; } #endif #if 1 #define IsFlippedTet_METHOD _dxf_IsFlippedTet_4x4_method #else #define IsFlippedTet_METHOD _dxf_IsFlippedTet_3x3_method #endif #if ( IsFlippedTet_METHOD == _dxf_IsFlippedTet_4x4_method ) static /* required here and in showboundary.m */ int _dxf_IsFlippedTet_4x4_method ( Tetrahedron tet, Point *geom ) { /* * Calculate the geometric determinate of a tetrahedron, use it's sign. * The expression below is the matrix we are 'determining', with 'g' * representing geometry, 't' representing tetrahedral connection indices. * * +-----------------------+----------------------------------------------+ * | a11 a12 a13 a14 | 1.0 1.0 1.0 1.0 | * | a21 a22 a23 a24 | g[t.p].x g[t.q].x g[t.r].x g[t.s].x | * | a31 a32 a33 a34 | g[t.p].y g[t.q].y g[t.r].y g[t.s].y | * | a41 a42 a43 a44 | g[t.p].z g[t.q].z g[t.r].z g[t.s].z | * +-----------------------+----------------------------------------------+ */ int ret; double a11, a12, a13, a14, a21, a22, a23, a24, a31, a32, a33, a34, a41, a42, a43, a44; double d; DXASSERTGOTO ( geom != NULL ); a11=1.0; a12=1.0; a13=1.0; a14=1.0; a21=geom[tet.p].x; a22=geom[tet.q].x; a23=geom[tet.r].x; a24=geom[tet.s].x; a31=geom[tet.p].y; a32=geom[tet.q].y; a33=geom[tet.r].y; a34=geom[tet.s].y; a41=geom[tet.p].z; a42=geom[tet.q].z; a43=geom[tet.r].z; a44=geom[tet.s].z; d = a11*(a22*(a33*a44-a43*a34)-a23*(a32*a44-a42*a34)+a24*(a32*a43-a42*a33)) -a12*(a21*(a33*a44-a43*a34)-a23*(a31*a44-a41*a34)+a24*(a31*a43-a41*a33)) +a13*(a21*(a32*a44-a42*a34)-a22*(a31*a44-a41*a34)+a24*(a31*a42-a41*a32)) -a14*(a21*(a32*a43-a42*a33)-a22*(a31*a43-a41*a33)+a23*(a31*a42-a41*a32)); ret = ( ABS(d) < DXD_MIN_FLOAT ) ? 0 : ( d < 0.0 )? 1 : -1; DXDebug ( "I", "_dxf_IsFlippedTet_4x4_method() = %g = %d", d, ret ); return ret; error: ERROR_SECTION; return ERROR; } #endif #if ( IsFlippedTet_METHOD == _dxf_IsFlippedTet_3x3_method ) static /* required here and in showboundary.m */ int _dxf_IsFlippedTet_3x3_method ( Tetrahedron tet, Point *geom ) { /* * Calculate the geometric determinate of a tetrahedron, use it's sign. * Three delta vectors method. * *+-------------+-----------------------------------------------------------+ *| a11 a12 a13 | (g[t.p].x-g[t.q].x) (g[t.p].x-g[t.r].x) (g[t.p].x-g[t.s].x) *| a21 a22 a23 | (g[t.p].y-g[t.q].y) (g[t.p].y-g[t.r].y) (g[t.p].y-g[t.s].y) *| a31 a32 a33 | (g[t.p].z-g[t.q].z) (g[t.p].z-g[t.r].z) (g[t.p].z-g[t.s].z) *+-------------+-----------------------------------------------------------+ */ int ret; double a11, a12, a13, a21, a22, a23, a31, a32, a33; double d; DXASSERTGOTO ( geom != NULL ); a11 = geom[tet.p].x - geom[tet.q].x; a21 = geom[tet.p].y - geom[tet.q].y; a31 = geom[tet.p].z - geom[tet.q].z; a12 = geom[tet.p].x - geom[tet.r].x; a22 = geom[tet.p].y - geom[tet.r].y; a32 = geom[tet.p].z - geom[tet.r].z; a13 = geom[tet.p].x - geom[tet.s].x; a23 = geom[tet.p].y - geom[tet.s].y; a33 = geom[tet.p].z - geom[tet.s].z; d = a11*(a22*a33-a32*a23) - a12*(a21*a33-a31*a23) + a13*(a21*a32-a31*a22); ret = ( ABS(d) < DXD_MIN_FLOAT ) ? 0 : ( d < 0.0 )? 1 : -1; DXDebug ( "I", "_dxf_IsFlippedTet_3x3_method() = %g = %d", d, ret ); return ret; error: ERROR_SECTION; return ERROR; } #endif extern int _dxf_get_flip ( field_info input_info, int *have_connections, int *have_nondegeneracy ) { array_info p_info, c_info = NULL; Array array; Point pseudo_pt[4]; static Tetrahedron pseudo_tet = { 0, 1, 2, 3 }; int flipq; int i; /* XXX - DXEmptyField call belongs here */ if ( NULL == input_info->std_comps[(int)CONNECTIONS] ) DXErrorGoto2 ( ERROR_INVALID_DATA, "#10240", /* missing %s component */ "connections" ); if ( (input_info->std_comps[(int)CONNECTIONS]->element_type != TETRAHEDRA) && (input_info->std_comps[(int)CONNECTIONS]->element_type != CUBES ) ) DXErrorGoto3 ( ERROR_INVALID_DATA, "#10203", /* %s must be one of: %s */ "connections element type", "tetrahedra, cubes" ); p_info = (array_info) &(input_info->std_comps[(int)POSITIONS]->array); c_info = (array_info) &(input_info->std_comps[(int)CONNECTIONS]->array); if ( p_info->get_item == NULL ) if ( !_dxf_SetIterator ( input_info->std_comps[(int)POSITIONS] ) ) goto error; if ( c_info->get_item == NULL ) if ( !_dxf_SetIterator ( input_info->std_comps[(int)CONNECTIONS] ) ) goto error; if ( c_info->items != 0 ) *have_connections = 1; for ( i=0, flipq=0; ( ( flipq == 0 ) && ( i < c_info->items ) ); i++ ) { switch ( input_info->std_comps[(int)CONNECTIONS]->element_type ) { case TETRAHEDRA: { Tetrahedron tet; if ( !c_info->get_item ( i, c_info, &tet ) || !p_info->get_item ( tet.p, p_info, &pseudo_pt[0] ) || !p_info->get_item ( tet.q, p_info, &pseudo_pt[1] ) || !p_info->get_item ( tet.r, p_info, &pseudo_pt[2] ) || !p_info->get_item ( tet.s, p_info, &pseudo_pt[3] ) ) goto error; } break; case CUBES: { Cube cube; /* XXX - 0132 */ if ( !c_info->get_item ( i, c_info, &cube ) || !p_info->get_item ( cube.p, p_info, &pseudo_pt[0] ) || !p_info->get_item ( cube.s, p_info, &pseudo_pt[1] ) || !p_info->get_item ( cube.u, p_info, &pseudo_pt[3] ) || !p_info->get_item ( cube.v, p_info, &pseudo_pt[2] ) ) goto error; } break; default: goto error; } flipq = IsFlippedTet_METHOD ( pseudo_tet, pseudo_pt ); } if ( ( flipq == 1 ) || ( flipq == -1 ) ) *have_nondegeneracy = 1; else /* arbitrary */ flipq = 1; return flipq; error: ERROR_SECTION; return ERROR; } static Vector *tetra_grad ( Point *p0, Point *p1, Point *p2, Point *p3, float d0, float d1, float d2, float d3, Vector *gradient ) { float A, B, C, D; float invD; float px, py, pz, pw; float a0, a1, a2, a3; float b0, b1, b2, b3; float c0, c1, c2, c3; float ab01, ac01, bc01, ab23, ac23, bc23; /* * (Somewhat mixed symbology, EG: a0,a1,a2 represents x,y,z coordinates). * * Algorithm as from _gradient.c/worker_3D_tetrahedra_manhattan * which is this: * * We now form 4-vectors whose first 3 coordinates are the x, y, and z * coordinates of a vertex of the tetrahedron, and whose 4th coordinate * w is the scalar data value associated with that vertex. There are * 4 such 4-vectors. We then find the equation of the 3D hyperplane * in 4D space which is determined by these 4 4-vectors. We seek * an equation of the form: w = K1 * x + K2 * y + K3 * z + K4. * In this equation, K1 == df/dx, K2 == df/dy, and K3 == df/dz. * * * To find the equation, we represent the first point * and its data value p3 as a 4-vector . We form * difference 4-vectors a, b, and c whose first three coordinates * are the x, y, and z differences between the remaining three * points of the tetrahedron and the first point, and whose last * coordinate is the difference between the data values of the * points of the tetrahedron and the data value of the first point. * The equation is given by the determinant: * * | x - px y - py z - pz w - pw | * | a0 a1 a2 a3 | == 0 * | b0 b1 b2 b3 | * | c0 c1 c2 c3 | * * The trick here is to solve this determinant with as few * multiplications as possible. */ px = p0->x; py = p0->y; pz = p0->z; pw = d0; a0 = p1->x - px; a1 = p1->y - py; a2 = p1->z - pz; a3 = d1 - pw; b0 = p2->x - px; b1 = p2->y - py; b2 = p2->z - pz; b3 = d2 - pw; c0 = p3->x - px; c1 = p3->y - py; c2 = p3->z - pz; c3 = d3 - pw; ab01 = ( a0 * b1 ) - ( b0 * a1 ); ac01 = ( a0 * c1 ) - ( c0 * a1 ); bc01 = ( b0 * c1 ) - ( c0 * b1 ); ab23 = ( a2 * b3 ) - ( b2 * a3 ); ac23 = ( a2 * c3 ) - ( c2 * a3 ); bc23 = ( b2 * c3 ) - ( c2 * b3 ); A = ( a1 * bc23 ) - ( b1 * ac23 ) + ( c1 * ab23 ); B = ( a0 * bc23 ) - ( b0 * ac23 ) + ( c0 * ab23 ); C = ( a3 * bc01 ) - ( b3 * ac01 ) + ( c3 * ab01 ); D = ( a2 * bc01 ) - ( b2 * ac01 ) + ( c2 * ab01 ); if ( ( D >= -DXD_MIN_FLOAT ) && ( D <= DXD_MIN_FLOAT ) ) { /* Degenerate tetrahedron. */ /* Note: still will get 0 magnitude gradient when all dvalues equal */ DXDebug ( "I", "Degenerate tetrahedron." ); gradient->x = gradient->y = gradient->z = 0.0; } else { /* Normal tetrahedron. */ invD = 1.0 / D; gradient->x = A * invD; gradient->y = -B * invD; gradient->z = C * invD; } return gradient; } static Error flip_normals_and_triangles ( field_info input_info, field_info output_info, int normal_direction ) { array_info pi_info, ci_info = NULL; array_info co_info, no_info = NULL; Point pseudo_pt[4]; static Tetrahedron pseudo_tet = { 0, 1, 2, 3 }; int flipq; Vector *np; Triangle *tp; float length; int i, save; int have_connects = 0; int have_nondegen = 0; DXASSERTGOTO ( ( normal_direction == 1 ) || ( normal_direction == -1 ) ); pi_info = (array_info) &(input_info->std_comps[(int)POSITIONS]->array); ci_info = (array_info) &(input_info->std_comps[(int)CONNECTIONS]->array); co_info = (array_info) &(output_info->std_comps[(int)CONNECTIONS]->array); no_info = (array_info) &(output_info->std_comps[(int)NORMALS]->array); DXASSERTGOTO ( pi_info->get_item != ERROR ); DXASSERTGOTO ( ci_info->get_item != ERROR ); if ( ERROR == ( flipq = _dxf_get_flip ( input_info, &have_connects, &have_nondegen ) ) ) goto error; if ( ( have_connects == 1 ) && ( have_nondegen == 0 ) ) DXErrorGoto ( ERROR_INVALID_DATA, "#11836" /* all connections are degenerate */ ); switch ( input_info->std_comps[(int)CONNECTIONS]->element_type ) { case CUBES: flipq *= -1; break; default: ; } #if 0 DXWarning ( "normal_direction = %d, flipq = %d", normal_direction, flipq ); #endif if ( normal_direction == flipq ) for ( i=0, tp=(Triangle*)co_info->data; iitems; i++, tp++ ) { save = tp->p; tp->p = tp->q; tp->q = save; } if ( normal_direction == 1 ) { for ( i=0, np=(Vector*) no_info->data; iitems; i++, np++ ) if ( ( length = DXLength ( *np ) ) != 0.0 ) /* CONSTANT NORMALS */ { np->x /= length; np->y /= length; np->z /= length; } } else for ( i=0, np=(Vector*) no_info->data; i< no_info->items; i++, np++ ) if ( ( length = -DXLength ( *np ) ) != 0.0 ) /* CONSTANT NORMALS */ { np->x /= length; np->y /= length; np->z /= length; } return OK; error: ERROR_SECTION; return ERROR; } static grad_table_ptr create_special_gradient ( field_info input_info, hash_table_ptr vtx_hash, grad_table_ptr grad ) { array_info pi_info, ci_info, di_info = NULL; Cube connection; Point centroid; Point point[8]; float data[8]; Vector ccg; Point d; Vector *g[8]; int i, j, k; int connection_shape; float dist, invdist; float _small_ = sqrt ( DXD_MIN_FLOAT ); InvalidComponentHandle i_handle = NULL; pi_info = (array_info) &(input_info->std_comps[(int)POSITIONS]->array); ci_info = (array_info) &(input_info->std_comps[(int)CONNECTIONS]->array); di_info = (array_info) &(input_info->std_comps[(int)DATA]->array); if ( ( NULL != input_info->std_comps[(int)INVALID_CONNECTIONS] ) && ( ERROR == ( i_handle = DXCreateInvalidComponentHandle ( (Object)input_info->field, NULL, "connections" ) ) ) ) goto error; DXASSERTGOTO ( pi_info->get_item != ERROR ); DXASSERTGOTO ( ci_info->get_item != ERROR ); DXASSERTGOTO ( di_info->get_item != ERROR ); connection_shape = ci_info->shape[0]; DXASSERTGOTO ( ( connection_shape == 4 ) || ( connection_shape == 8 ) ); for ( i=0; iitems; i++ ) if ( ( NULL != i_handle ) && DXIsElementInvalid ( i_handle, i ) ) continue; else if ( !ci_info->get_item ( i, ci_info, &connection ) ) goto error; else for ( j=0; jset_vertices, ((int*)&connection)[j] ) ) #else if ( 1 ) #endif { for ( k=0; kget_item ( ((int*)&connection)[k], di_info, &data[k] ) || !pi_info->get_item ( ((int*)&connection)[k], pi_info, &point[k])) goto error; if ( k == 0 ) centroid = point[0]; else { centroid.x += point[k].x; centroid.y += point[k].y; centroid.z += point[k].z; } if ( NULL == ( g[k] = grad->index[((int*)&connection)[k]]) ) { if ( ERROR == ( g[k] = grad->index[((int*)&connection)[k]] = (Vector*) DXNewSegListItem ( grad->list ) ) ) goto error; else g[k]->x = g[k]->y = g[k]->z = 0.0; } } /* XXX - dist was not used in this calculation? */ #define WEIGHTED_CONTRIBUTION(N) \ d.x = centroid.x-point[N].x; d.y = centroid.y-point[N].y;\ d.z = centroid.z-point[N].z; \ dist = ABS(d.x) + ABS(d.y) + ABS(d.z); \ if (dist > DXD_MIN_FLOAT) { invdist = 1.0 / dist; \ g[N]->x += ccg.x * invdist; \ g[N]->y += ccg.y * invdist; \ g[N]->z += ccg.z * invdist; } #if 0 if (dist > 0.0) { \ g[N]->x += ccg.x; \ g[N]->y += ccg.y; \ g[N]->z += ccg.z; } if (dist > _small_) { invdist = 1.0 / ( dist * dist ); \ g[N]->x += ccg.x * invdist; \ g[N]->y += ccg.y * invdist; \ g[N]->z += ccg.z * invdist; } #endif if ( connection_shape == 4 ) { centroid.x *= 0.25; centroid.y *= 0.25; centroid.z *= 0.25; if ( !tetra_grad ( &point[0], &point[1], &point[2], &point[3], data[0], data[1], data[2], data[3], &ccg ) ) goto error; WEIGHTED_CONTRIBUTION ( 0 ); WEIGHTED_CONTRIBUTION ( 1 ); WEIGHTED_CONTRIBUTION ( 2 ); WEIGHTED_CONTRIBUTION ( 3 ); } else if ( connection_shape == 8 ) { centroid.x *= 0.125; centroid.y *= 0.125; centroid.z *= 0.125; /* PSUV=0356 */ if ( !tetra_grad ( &point[0], &point[3], &point[5], &point[6], data[0], data[3], data[5], data[6], &ccg ) ) goto error; WEIGHTED_CONTRIBUTION ( 0 ); WEIGHTED_CONTRIBUTION ( 1 ); WEIGHTED_CONTRIBUTION ( 2 ); WEIGHTED_CONTRIBUTION ( 3 ); WEIGHTED_CONTRIBUTION ( 4 ); WEIGHTED_CONTRIBUTION ( 5 ); WEIGHTED_CONTRIBUTION ( 6 ); WEIGHTED_CONTRIBUTION ( 7 ); } break /*j*/; } #undef WEIGHTED_CONTRIBUTION DXFreeInvalidComponentHandle ( i_handle ); i_handle = NULL; return grad; error: ERROR_SECTION; DXFreeInvalidComponentHandle ( i_handle ); i_handle = NULL; return ERROR; } static /* * Special scan to remove geometrically degenerate connectives. * Zero area triangles. * (Zero length lines we'll ignore until problems are revealed) * * Comment: since this field was constructed by isosurface, * we skip some integrity checks, about connection dependency and so on. * XXX: * since edge degeneration is coalesced, point compare by ID should be OK. * (below its by geometric value) */ Field remove_degenerates ( Field in ) { #if 1 /* XXX - should not remove follow-ons, EG "color map" ? */ /* * Remove unused points. */ if ( DXEmptyField ( in ) ) return in; if ( !DXInvalidateUnreferencedPositions ( (Object)in ) || !DXCull ( (Object)in ) ) return ERROR; return in; #else array_info p_info; array_info c_info; component_info comp; Array array; int *new_pts = NULL; int *new_tris = NULL; Triangle *tri_base, *t_a = NULL; Point *pts_base, *p_a = NULL; int i, j; int nto, npo; DXDebug ( "I", "start:RemoveDegenerates()" ); /* * Initialize bad_pts to 0, bad_tris to 0, new_pts[i] to i. * Foreach tri * if any two of the three points coincide then * set higher of 2 points' new_pts to the other matching * mark bad_pts of higher * mark bad_tri * Foreach pt * if not a bad_pt then * Copy the coordinates up in memory * Assign a unique ID for the point * else * Assign the ID of the coincident point * Set the component array lengths based on the new point count. * Foreach tri * if not a bad_tri then * set the three ID's based on new_pts * Set the connections component lengths based on the new triangle count. * Clean up. */ /* XXX - QueryConnectivity ( in, 0 ) == HAS_TRIANGLES */ if ( !DXEmptyField ( in->field ) ) { p_info = (array_info) &(in->std_comps[(int)POSITIONS]->array); c_info = (array_info) &(in->std_comps[(int)CONNECTIONS]->array); tri_base = (Triangle *) c_info->data; pts_base = (Point *) p_info->data; #define SETUP_AREAS \ {if ((ERROR==(new_pts=(int*)DXAllocateLocal(p_info->items*sizeof(int))))\ ||(ERROR==(new_tris=(int*)DXAllocateLocal(c_info->items*sizeof(int)))))\ goto error; \ DXDebug ( "I", "RemoveDegenerates: Doin' it at i=%d.", i ); \ for ( j=0; jitems; j++ ) new_tris [ j ] = j; \ for ( j=0; jitems; j++ ) new_pts [ j ] = j; } for ( i=0, nto=c_info->items, t_a=tri_base; iitems; i++, t_a++ ) { if ( 0 == memcmp ( (char *) &pts_base [ t_a->p ], (char *) &pts_base [ t_a->q ], sizeof ( Point ) ) ) { if ( new_tris == NULL ) SETUP_AREAS; new_tris [ i ] = -1; nto--; if ( t_a->p < t_a->q ) new_pts [ t_a->q ] = t_a->p; else new_pts [ t_a->p ] = t_a->q; } if ( 0 == memcmp ( (char *) &pts_base [ t_a->q ], (char *) &pts_base [ t_a->r ], sizeof ( Point ) ) ) { if ( new_tris == NULL ) SETUP_AREAS; new_tris [ i ] = -1; nto--; if ( t_a->q < t_a->r ) new_pts [ t_a->r ] = t_a->q; else new_pts [ t_a->q ] = t_a->r; } if ( 0 == memcmp ( (char *) &pts_base [ t_a->r ], (char *) &pts_base [ t_a->p ], sizeof ( Point ) ) ) { if ( new_tris == NULL ) SETUP_AREAS; new_tris [ i ] = -1; nto--; if ( t_a->r < t_a->p ) new_pts [ t_a->p ] = t_a->r; else new_pts [ t_a->r ] = t_a->p; } } #undef SETUP_AREAS if ( new_tris == NULL ) return in; #if 0 Warning ( "Areas = %s", ( new_tris == NULL )? "NULL" : "Stuffed" ); for ( i=0; iitems; i++ ) if ( new_tris[i] != i ) DXWarning ( "bad[%d] = [%d,%d,%d], {[%g,%g,%g],[%g,%g,%g],[%g,%g,%g]}", i, tri_base[i].p, tri_base[i].q, tri_base[i].r, pts_base [ tri_base[i].p ].x, pts_base [ tri_base[i].p ].y, pts_base [ tri_base[i].p ].z, pts_base [ tri_base[i].q ].x, pts_base [ tri_base[i].q ].y, pts_base [ tri_base[i].q ].z, pts_base [ tri_base[i].r ].x, pts_base [ tri_base[i].r ].y, pts_base [ tri_base[i].r ].z ); #endif for ( i=0, npo=0; iitems; i++ ) if ( new_pts [ i ] == i ) new_pts [ i ] = npo++; else new_pts [ i ] = new_pts [ new_pts [ i ] ]; for ( i=0, nto=0, t_a=tri_base; iitems; i++, t_a++ ) if ( new_tris [ i ] != -1 ) { new_tris [ i ] = nto++; t_a->p = new_pts [ t_a->p ]; t_a->q = new_pts [ t_a->q ]; t_a->r = new_pts [ t_a->r ]; } for ( j=0, comp=in->comp_list; jcomp_count; j++, comp++ ) { if ( ( 0 == strcmp ( comp->name, "positions" ) ) || ( ( NULL != comp->std_attribs[(int)DEP] ) && ( ERROR != comp->std_attribs[(int)DEP]->value ) && ( 0 == strcmp ( comp->std_attribs[(int)DEP]->value, "positions" ) ) ) ) { if ( ( ERROR == ( array = _dxf_resample_array ( comp, 1, p_info->items, npo, new_pts, NULL ) ) ) || !DXSetComponentValue ( in->field, comp->name, (Object)array ) ) goto error; } else if ( ( 0 == strcmp ( comp->name, "connections" ) ) || ( ( NULL != comp->std_attribs[(int)DEP] ) && ( ERROR != comp->std_attribs[(int)DEP]->value ) && ( 0 == strcmp ( comp->std_attribs[(int)DEP]->value, "connections" ) ) ) ) if ( ( ERROR == ( array = _dxf_resample_array ( comp, 1, c_info->items, nto, new_tris, NULL ) ) ) || !DXSetComponentValue ( in->field, comp->name, (Object)array ) ) goto error; } DXFree ( (Pointer) new_tris ); new_tris = NULL; DXFree ( (Pointer) new_pts ); new_pts = NULL; } return in; error: ERROR_SECTION; DXFree ( (Pointer) new_tris ); new_tris = NULL; DXFree ( (Pointer) new_pts ); new_pts = NULL; return ERROR; #endif } static Field create_iso_surface ( field_info input_info, float *value_ptr, int is_grown, iso_norm_types normal_type, int normal_direction, Interpolator gradient_interpolator, Error (*convert_connection) (void *, float *, hash_table_ptr, hash_table_ptr, int), /* (void *, float *, hash_table_ptr, SegList *, int),*/ Field out ) { float value = value_ptr [ 0 ]; array_info pi_info, ci_info, di_info = NULL; array_info po_info, co_info, no_info = NULL; hash_table_rec vtx_hash; grad_table_rec grad_table; SegList *tri_list = NULL; Cube cube; Point point[8]; float data[8]; double t; iso_edge_hash_ptr element_ptr = NULL; int i, j; field_info output_info = NULL; int position_dim; int connection_count; int connection_shape; Object copy_g = NULL; SegList *c_ID_list = NULL; int *c_ID_pull = NULL; int n_c_dep, n_p_dep; array_info a_info; component_info comp; Array array = NULL; Pointer scratch = NULL; Pointer out_data = NULL; InvalidComponentHandle i_handle = NULL; DXASSERTGOTO ( ERROR != input_info ); DXASSERTGOTO ( ERROR != value_ptr ); DXASSERTGOTO ( ERROR != convert_connection ); DXASSERTGOTO ( ERROR != out ); vtx_hash.count = 0; vtx_hash.table = NULL; vtx_hash.set_vertices = NULL; grad_table.index = NULL; grad_table.list = NULL; pi_info = (array_info) &(input_info->std_comps[(int)POSITIONS]->array); ci_info = (array_info) &(input_info->std_comps[(int)CONNECTIONS]->array); di_info = (array_info) &(input_info->std_comps[(int)DATA]->array); if ( ( NULL != input_info->std_comps[(int)INVALID_CONNECTIONS] ) && ( ERROR == ( i_handle = DXCreateInvalidComponentHandle ( (Object)input_info->field, NULL, "connections" ) ) ) ) goto error; DXASSERTGOTO ( pi_info->get_item != ERROR ); DXASSERTGOTO ( ci_info->get_item != ERROR ); DXASSERTGOTO ( di_info->get_item != ERROR ); if ( ( pi_info->shape[0] != 3 ) ) DXErrorGoto3 ( ERROR_INVALID_DATA, "#11400", /* %s has invalid dimensionality; does not match %s */ "\"positions\" component", "\"connections\"" ); position_dim = pi_info->shape[0]; connection_shape = ci_info->shape[0]; DXASSERTGOTO ( ( connection_shape == 4 ) || ( connection_shape == 8 ) ); TST_HASH_INTS; if ( ( ERROR == ( vtx_hash.table = DXCreateHash ( sizeof(iso_edge_hash_rec), iso_edge_hash_func, iso_edge_compare_func )) ) || ( ERROR == ( tri_list = DXNewSegList ( sizeof(Triangle), 1000, 1000 ) ) ) ) goto error; if ( !tally_dependers ( input_info, &n_c_dep, &n_p_dep ) ) goto error; if ( ( n_c_dep > 1 ) && ( ERROR == ( c_ID_list = DXNewSegList ( sizeof(int), 1000, 1000 ) ) ) ) goto error; if ( normal_type == NORMALS_COMPUTED ) if ( ( ERROR == ( grad_table.list = DXNewSegList ( sizeof(Vector), 1000, 1000 ) ) ) || ( ERROR == ( grad_table.index = (Vector**) DXAllocateLocalZero ( pi_info->items * sizeof(Vector*) ) ) ) || ( ERROR == ( vtx_hash.set_vertices = NEWBIT ( pi_info->items ) ) ) ) goto error; DXASSERTGOTO ( ci_info->items >= ci_info->original_items ); if ( ci_info->get_item == _dxf_get_conn_grid_CUBES ) { array_info t0, t1, t2; int II, JJ, KK; int I0, J0, K0; t0 = (array_info) &(((struct _array_allocator *)((mesh_array_info)ci_info)->terms)[0]); t1 = (array_info) &(((struct _array_allocator *)((mesh_array_info)ci_info)->terms)[1]); t2 = (array_info) &(((struct _array_allocator *)((mesh_array_info)ci_info)->terms)[2]); DXASSERTGOTO ( ((mesh_array_info)ci_info)->grid == TTRUE ); DXASSERTGOTO ( ((grid_connections_info)ci_info)->counts != NULL ); DXASSERTGOTO ( t0->items == ( ((grid_connections_info)ci_info)->counts[0] - 1 ) ); DXASSERTGOTO ( t1->items == ( ((grid_connections_info)ci_info)->counts[1] - 1 ) ); DXASSERTGOTO ( t2->items == ( ((grid_connections_info)ci_info)->counts[2] - 1 ) ); if ( ((mesh_array_info)ci_info)->grow_offsets != NULL ) { DXASSERTGOTO ( is_grown ); I0 = ((mesh_array_info)ci_info)->grow_offsets[0]; J0 = ((mesh_array_info)ci_info)->grow_offsets[1]; K0 = ((mesh_array_info)ci_info)->grow_offsets[2]; } else I0 = J0 = K0 = 0; for ( II=I0; II<( I0 + t0->original_items ); II++ ) for ( JJ=J0; JJ<( J0 + t1->original_items ); JJ++ ) { if ( !ci_info->get_item ( (((( II * t1->items ) + JJ ) * t2->items ) + K0 ), ci_info, &cube ) || !di_info->get_item ( cube.p, di_info, &data[0] ) || !di_info->get_item ( cube.r, di_info, &data[2] ) || !di_info->get_item ( cube.t, di_info, &data[4] ) || !di_info->get_item ( cube.v, di_info, &data[6] ) ) goto error; data[0] -= value; data[2] -= value; data[4] -= value; data[6] -= value; for ( KK=K0; KK<( K0 + t2->original_items ); KK++, cube.p++, cube.q++, cube.r++, cube.s++, cube.t++, cube.u++, cube.v++, cube.w++, data[0] = data[1], data[2] = data[3], data[4] = data[5], data[6] = data[7] ) { if ( !di_info->get_item ( cube.q, di_info, &data[1] ) || !di_info->get_item ( cube.s, di_info, &data[3] ) || !di_info->get_item ( cube.u, di_info, &data[5] ) || !di_info->get_item ( cube.w, di_info, &data[7] ) ) goto error; data[1] -= value; data[3] -= value; data[5] -= value; data[7] -= value; if ( ( NULL != i_handle ) && DXIsElementInvalid ( i_handle, ((((II*t1->items)+JJ)*t2->items)+KK) ) ) continue; else if ( !convert_connection ( &cube, data, &vtx_hash, (hash_table_ptr) tri_list, /* XXX parameter 4 */ /* equivalence */ 1 ) ) goto error; else if ( ( NULL != c_ID_list ) && !set_c_ID ( c_ID_list, DXGetSegListItemCount ( tri_list ), ((((II*t1->items)+JJ)*t2->items)+KK) ) ) goto error; } } } else { for ( i=0; ioriginal_items; i++ ) if ( ( NULL != i_handle ) && DXIsElementInvalid ( i_handle, i ) ) continue; else if ( !ci_info->get_item ( i, ci_info, &cube ) ) goto error; else { for ( j=0; jget_item ( ((int *)&cube)[j], di_info, &data[j] ) ) goto error; data[j] -= value; } if ( !convert_connection ( &cube, data, &vtx_hash, (hash_table_ptr) tri_list, /* XXX parameter 4 */ /* equivalence */ 1 ) ) goto error; else if ( ( NULL != c_ID_list ) && !set_c_ID ( c_ID_list, DXGetSegListItemCount ( tri_list ), i ) ) goto error; } } connection_count = DXGetSegListItemCount ( tri_list ); if ( connection_count == 0 ) if ( !_dxf_MakeFieldEmpty ( out ) ) goto error; else goto done; if ( normal_type == NORMALS_COMPUTED ) { if ( !create_output_arrays ( out, vtx_hash.count, position_dim, connection_count, 2, vtx_hash.count, DEFAULT_SURFACE_COLOR, value, DEP_POSITIONS, ISOSURFACE ) ) goto error; if ( vtx_hash.count == 0 ) goto done; if ( !create_special_gradient ( input_info, &vtx_hash, &grad_table ) ) goto error; } else { if ( !create_output_arrays ( out, vtx_hash.count, position_dim, connection_count, 2, 0, DEFAULT_SURFACE_COLOR, value, DEP_POSITIONS, ISOSURFACE ) ) goto error; if ( vtx_hash.count == 0 ) goto done; } if ( ( connection_count > 0 ) && ( c_ID_list != NULL ) ) { if ( ( ERROR == ( c_ID_pull = DXAllocateLocal ( connection_count * sizeof(int) ) ) ) || !copy_seglist_to_memory ( c_ID_list, c_ID_pull, sizeof(int), connection_count ) ) goto error; DXDeleteSegList ( c_ID_list ); c_ID_list = NULL; } if ( ERROR == ( output_info = ( _dxf_InMemory ( out ) ) ) ) goto error; DXASSERTGOTO ( output_info->std_comps[(int)POSITIONS] != NULL ); DXASSERTGOTO ( output_info->std_comps[(int)CONNECTIONS] != NULL ); po_info = (array_info) &(output_info->std_comps[(int)POSITIONS]->array); co_info = (array_info) &(output_info->std_comps[(int)CONNECTIONS]->array); no_info = ( normal_type == NORMALS_COMPUTED )? (array_info) &(output_info->std_comps[(int)NORMALS]->array) : NULL; if ( !copy_seglist_to_array ( tri_list, co_info ) ) goto error; DXDeleteSegList ( tri_list ); tri_list = NULL; for ( j=0, comp=input_info->comp_list; jcomp_count; j++, comp++ ) { if ( ( 0 != strcmp ( comp->name, "positions" ) ) && ( ( NULL == comp->std_attribs[(int)DEP] ) || ( ERROR == comp->std_attribs[(int)DEP]->value ) || ( 0 != strcmp ( comp->std_attribs[(int)DEP]->value, "positions" ) ) ) ) continue; if ( ( 0 == strcmp ( comp->name, "data" ) ) || ( 0 == strncmp ( comp->name, "original", 8 ) ) || ( NULL != comp->std_attribs[(int)REF] ) ) continue; if ( ( 0 == strcmp ( comp->name, "normals" ) ) && ( normal_type != NO_NORMALS ) ) continue; a_info = (array_info) &(comp->array); if ( CLASS_CONSTANTARRAY == a_info->class ) { if ( ( ERROR == ( array = (Array)DXNewConstantArrayV ( vtx_hash.count, DXGetConstantArrayData ( a_info->array ), a_info->type, a_info->category, a_info->rank, a_info->shape ) ) ) || !DXSetComponentValue ( out, comp->name, (Object) array ) || !DXSetComponentAttribute ( out, comp->name, "dep", (Object) DXNewString ( "positions" ) ) ) goto error; continue; } if ( ( ERROR == ( array = DXNewArrayV ( a_info->type, a_info->category, a_info->rank, &a_info->shape[0] ) ) ) || !DXAllocateArray ( array, vtx_hash.count ) || !DXAddArrayData ( array, 0, vtx_hash.count, NULL ) || !DXTrim ( array ) || !DXSetComponentValue ( out, comp->name, (Object) array ) || !DXSetComponentAttribute ( out, comp->name, "dep", (Object) DXNewString ( "positions" ) ) || !_dxf_SetIterator ( comp ) || ( ERROR == ( out_data = DXGetArrayData ( array ))) || ( ERROR == ( scratch = DXAllocateLocal ( 2 * a_info->itemsize ))) || !DXInitGetNextHashElement ( vtx_hash.table ) ) goto error; array = NULL; for ( i = 0; ( NULL != ( element_ptr = (iso_edge_hash_ptr) DXGetNextHashElement ( vtx_hash.table ) ) ); i++ ) { DXASSERTGOTO ( element_ptr->seq < po_info->items ); if ( element_ptr->edge.p == element_ptr->edge.q ) t = 0.0; else { if ( !di_info->get_item ( element_ptr->edge.p, di_info, &data[0] )|| !di_info->get_item ( element_ptr->edge.q, di_info, &data[1] ) ) goto error; data[0] -= value; data[1] -= value; if ( data[0] == 0.0 ) t = 0.0; else if ( data[1] == 0.0 ) t = 1.0; else { t = (double)data[0] / ((double)data[0] - (double)data[1]); } DXASSERTGOTO ( ( t >= 0.0 ) && ( t <= 1.0 ) ); } if ( !interp ( a_info, scratch, element_ptr->edge.p, element_ptr->edge.q, t, &(((char*)out_data) [ a_info->itemsize * element_ptr->seq ]), a_info->itemsize/sizeof(float), a_info->itemsize) ) goto error; if ( ( a_info == pi_info ) && ( normal_type == NORMALS_COMPUTED ) ) { DXASSERTGOTO ( grad_table.index [ element_ptr->edge.p ] ); DXASSERTGOTO ( grad_table.index [ element_ptr->edge.q ] ); point[0] = *grad_table.index [ element_ptr->edge.p ]; point[1] = *grad_table.index [ element_ptr->edge.q ]; point[0].x += ( point[1].x - point[0].x ) * t; point[0].y += ( point[1].y - point[0].y ) * t; point[0].z += ( point[1].z - point[0].z ) * t; ((Vector *)no_info->data) [ element_ptr->seq ] = point[0]; } } DXFree ( scratch ); scratch = NULL; } for ( j=0, comp=input_info->comp_list; jcomp_count; j++, comp++ ) { if ( ( NULL == comp->std_attribs[(int)DEP] ) || ( ERROR == comp->std_attribs[(int)DEP]->value ) || ( 0 != strcmp ( comp->std_attribs[(int)DEP]->value, "connections" ) ) ) continue; if ( ( 0 == strcmp ( comp->name, "connections" ) ) || ( 0 == strncmp ( comp->name, "original", 8 ) ) || ( NULL != comp->std_attribs[(int)REF] ) ) continue; a_info = (array_info) &(comp->array); if ( ( ERROR == ( array = _dxf_resample_array ( comp, 1, ((array_info) &(comp->array))->items, connection_count, NULL, c_ID_pull ) ) ) || !DXSetComponentValue ( out, comp->name, (Object)array ) || !DXSetComponentAttribute ( out, comp->name, "dep", (Object) DXNewString ( "connections" ) ) ) goto error; } _dxf_FreeInMemory ( output_info ); if ( ERROR == ( output_info = _dxf_InMemory ( out ) ) ) goto error; switch ( normal_type ) { case GRADIENT_NORMALS: { Object inv_bef = DXExists ( (Object) out, "invalid positions" ); if ( ( ERROR == ( copy_g = DXCopy ( (Object) gradient_interpolator, COPY_STRUCTURE ) ) ) || !DXMap ( (Object) out, copy_g, "positions", "normals" ) ) goto error; if ( !inv_bef && DXExists ( (Object) out, "invalid positions" ) ) { DXWarning ( "Isosurface: Mapping external gradient reveals invalid points." ); DXWarning ( "Isosurface: Check that external gradient encompasses data." ); } _dxf_FreeInMemory ( output_info ); DXDelete ( copy_g ); copy_g = NULL; if ( ERROR == ( output_info = ( _dxf_InMemory ( out ) ) ) ) goto error; } case NORMALS_COMPUTED: if ( !flip_normals_and_triangles ( input_info, output_info, normal_direction ) ) goto error; break; case NO_NORMALS: break; } /* Do this last since it invalidates (( output_info )) */ if ( !remove_degenerates ( out ) ) goto error; done: /* This is create_iso_surface */ if ( DXGetAttribute ( (Object)input_info->field, "shade" ) ) if ( !DXSetAttribute ( (Object) out, "shade", DXGetAttribute ( (Object)input_info->field, "shade" ) ) ) goto error; DXDestroyHash ( vtx_hash.table ); DXFree ( vtx_hash.set_vertices ); DXFree ( (Pointer) grad_table.index ); DXDeleteSegList ( grad_table.list ); DXDeleteSegList ( tri_list ); DXDeleteSegList ( c_ID_list ); DXFree ( c_ID_pull ); DXFree ( scratch ); _dxf_FreeInMemory ( output_info ); DXFreeInvalidComponentHandle ( i_handle ); i_handle = NULL; vtx_hash.table = NULL; vtx_hash.set_vertices = NULL; grad_table.index = NULL; grad_table.list = NULL; output_info = NULL; tri_list = NULL; c_ID_list = NULL; c_ID_pull = NULL; scratch = NULL; return DXEndField ( out ); error: ERROR_SECTION; DXDestroyHash ( vtx_hash.table ); DXFree ( vtx_hash.set_vertices ); DXFree ( (Pointer) grad_table.index ); DXDeleteSegList ( grad_table.list ); DXDeleteSegList ( tri_list ); DXDeleteSegList ( c_ID_list ); DXFree ( c_ID_pull ); DXFree ( scratch ); _dxf_FreeInMemory ( output_info ); DXFreeInvalidComponentHandle ( i_handle ); i_handle = NULL; vtx_hash.table = NULL; vtx_hash.set_vertices = NULL; grad_table.index = NULL; grad_table.list = NULL; output_info = NULL; tri_list = NULL; c_ID_list = NULL; c_ID_pull = NULL; scratch = NULL; return ERROR; } static Error isosurface_field ( Field input, int number, float *values, float *min_max, iso_module_types module, band_remap_types remap, Field *out_h, int *skipvec, iso_norm_types normal_type, Interpolator gradient_interpolator, int is_grown, int normal_direction ) { Array data_array; int i; Interpolator copy_g = NULL; field_info input_info = NULL; array_info p_info, c_info, d_info = NULL; Field (*create_output) () = NULL; Error (*convert_connection) () = NULL; #ifdef WHITEBOX_TEST for ( i=0; i<8; i++ ) histograms.polygonalizations[i] = 0; for ( i=0; i<256; i++ ) histograms.case_signatures [i] = 0; #endif DXASSERTGOTO ( input != ERROR ); DXASSERTGOTO ( !DXEmptyField ( input ) ); DXASSERTGOTO ( DXGetObjectClass ( (Object)input ) == CLASS_FIELD ); if ( !DXInvalidateConnections ( (Object) input ) || ( ERROR == ( input_info = _dxf_InMemory ( input ) ) ) ) goto error; if ( input_info->std_comps[(int)POSITIONS] == NULL ) DXErrorGoto3 ( ERROR_INVALID_DATA, "#10250", /*%s is missing %s component*/ "'data' parameter", "\"positions\"" ); if ( input_info->std_comps[(int)CONNECTIONS] == NULL ) DXErrorGoto3 ( ERROR_INVALID_DATA, "#10250", /*%s is missing %s component*/ "'data' parameter", "\"connections\"" ); if ( input_info->std_comps[(int)DATA] == NULL ) DXErrorGoto3 ( ERROR_INVALID_DATA, "#10250", /*%s is missing %s component*/ "'data' parameter", "\"data\"" ); if ( ( input_info->std_comps[(int)DATA]->std_attribs[(int)DEP] == NULL ) || ( strcmp ( input_info->std_comps[(int)DATA]->std_attribs[(int)DEP]->value, "positions" ) != 0 ) ) DXErrorGoto2 ( ERROR_INVALID_DATA, "#11251", /* %s must be dependent on positions */ "the \"data\" component" ); p_info = (array_info) &(input_info->std_comps[(int)POSITIONS]->array); c_info = (array_info) &(input_info->std_comps[(int)CONNECTIONS]->array); d_info = (array_info) &(input_info->std_comps[(int)DATA]->array); if ( ( d_info->rank != 0 ) && ( ( d_info->rank != 1 ) || ( d_info->shape[0] != 1 ) ) ) DXErrorGoto2 ( ERROR_INVALID_DATA, "#10081", /* %s must be scalar or 1-vector */ "\"data\" component" ); if ( !_dxf_SetIterator ( input_info->std_comps[(int)POSITIONS] ) || !_dxf_SetIterator ( input_info->std_comps[(int)CONNECTIONS] ) || !_dxf_SetIterator_i ( input_info->std_comps[(int)DATA] ) ) goto error; switch ( module ) { case ISOSURFACE: switch ( input_info->std_comps[(int)CONNECTIONS]->element_type ) { case LINES: create_output = create_iso_points; convert_connection = NULL; break; case QUADRILATERALS: create_output = create_iso_contours; convert_connection = iso_convert_quadrilateral; break; case TRIANGLES: create_output = create_iso_contours; convert_connection = iso_convert_triangle; break; case CUBES: create_output = create_iso_surface; convert_connection = iso_convert_cube; break; case TETRAHEDRA: create_output = create_iso_surface; convert_connection = iso_convert_tetrahedron; break; case PRISMS: create_output = create_iso_surface; convert_connection = iso_convert_prism; break; case CUBES4D: case NONE: case ET_UNKNOWN: default: DXErrorGoto2 ( ERROR_INVALID_DATA, "#11380", /* %s is an invalid connections type */ input_info->std_comps[(int)CONNECTIONS]->name ); } break; #ifdef INCLUDES_BAND case BAND: switch ( input_info->std_comps[(int)CONNECTIONS]->element_type ) { case LINES: create_output = create_band_lines; convert_connection = band_convert_line; break; case QUADRILATERALS: create_output = create_band_surface; convert_connection = band_convert_quadrilateral; break; case TRIANGLES: create_output = create_band_surface; convert_connection = band_convert_triangle; break; case CUBES: case TETRAHEDRA: case PRISMS: case CUBES4D: case NONE: case ET_UNKNOWN: default: DXErrorGoto2 ( ERROR_INVALID_DATA, "#11380", /* %s is an invalid connections type */ input_info->std_comps[(int)CONNECTIONS]-> std_attribs[ELEMENT_TYPE]->value ); } #endif } if ( ( create_output == create_iso_points ) || ( create_output == create_iso_contours ) ) { for ( i=0; i 0 ) ? OBJ_OK : OBJ_EMPTY; } break; default: DXErrorGoto2 ( ERROR_INVALID_DATA, "#10190", /* %s must be a field or a group */ "'data' parameter" ); } error: ERROR_SECTION; return OBJ_ERROR; } static /* * Special return codes: Pointer and NULL are both acceptable as * non-error conditions. when DXGetError() signifies that there is error, * then there is one. * * XXX - Important: * Statistics will give an error if called with an DXEmptyField * or a group containing no fields with "data" components * (as with EmptyFields) */ iso_arg_type * stats ( iso_arg_type *iso_arg, float **deletable ) { float min, mean, max; int i; DXASSERTGOTO ( deletable != NULL ); *deletable = NULL; if ( ( !iso_arg->have_minmax ) && ( DXGetObjectClass ( iso_arg->self ) == CLASS_GROUP ) && ( DXGetGroupClass ( (Group) iso_arg->self ) == CLASS_COMPOSITEFIELD ) ) { switch ( iso_object_type_check ( iso_arg->self ) ) { case OBJ_EMPTY: return iso_arg; /* XXX - This is a hack */ case OBJ_OK: break; case OBJ_ERROR: goto error; } if ( !DXStatistics ( iso_arg->self, "data", &iso_arg->band_min_cf, &iso_arg->band_max_cf, NULL, NULL ) ) goto error; iso_arg->have_minmax = 1; } if ( iso_arg->isovals ) return iso_arg; if ( _dxd_user_def_values ) { iso_arg->isovals = _dxd_user_def_values; return iso_arg; } if ( ( DXGetObjectClass ( iso_arg->self ) == CLASS_GROUP ) && ( DXGetGroupClass ( (Group) iso_arg->self ) == CLASS_GROUP ) ) return iso_arg; /* No error: Isovalues are not evaluated over generic groups */ switch ( iso_object_type_check ( iso_arg->self ) ) { case OBJ_EMPTY: return iso_arg; /* XXX - This is a hack */ case OBJ_OK: break; case OBJ_ERROR: goto error; } if ( !DXStatistics ( iso_arg->self, "data", &min, &max, &mean, NULL ) || ( ERROR == ( iso_arg->isovals = (float*) DXAllocate ( sizeof(float) * VALUE_COUNT ( iso_arg ) ) ) ) ) goto error; *deletable = iso_arg->isovals; if ( iso_arg->use_mean ) { iso_arg->isovals[0] = mean; DXMessage ( "%s: 'value' defaults to mean: %g .", MOD_NAME ( iso_arg ), iso_arg->isovals[0] ); } else if ( VALUE_COUNT(iso_arg) > 0 ) { for ( i=0; iisovals[i] = min + ( ( max - min ) * ( (float) ( i + 1 ) ) / ( (float) ( VALUE_COUNT(iso_arg) + 1 ) ) ); if ( VALUE_COUNT ( iso_arg ) == 1 ) DXMessage ( "%s: 'value' is %g .", MOD_NAME ( iso_arg ), iso_arg->isovals[0] ); else DXMessage ( "%s: 'value' is %d values ranging from %g to %g .", MOD_NAME ( iso_arg ), VALUE_COUNT ( iso_arg ), iso_arg->isovals [ 0 ], iso_arg->isovals [ VALUE_COUNT ( iso_arg ) - 1 ] ); } return iso_arg; error: ERROR_SECTION; DXFree ( (Pointer) *deletable ); *deletable = NULL; return ERROR; } #define SavedCopiesMaxDEF 1024 static struct { CompositeField cf [ SavedCopiesMaxDEF ]; int used; } SavedCopies; #define init_saved_copies_DEF \ { SavedCopies.used = -1; } #define free_saved_copies_DEF \ {while(SavedCopies.used>-1) \ DXDelete((Object)SavedCopies.cf[SavedCopies.used--]);} static CompositeField copy_grow_save ( CompositeField input ) { char *growl[100]; char *dep; int ll; int i, j; Field f; Object a; CompositeField copy = NULL; for ( i=0; ( NULL != ( f = (Field)DXGetEnumeratedMember ( (Group)input, i, NULL ) ) ); i++ ) if ( !DXEmptyField ( f ) ) { for ( j=0, ll=0; ( NULL != ( a = DXGetEnumeratedComponentValue ( f, j, &growl[ll] ) ) ); j++ ) { if ( ll >= 100 ) DXErrorGoto ( ERROR_UNEXPECTED, "more than 100 components to grow in copy_grow_save" ); if ( NULL != growl[ll] ) if ( ( 0 == strcmp ( growl[ll], "positions" ) ) || ( 0 == strcmp ( growl[ll], "connections" ) ) || ( 0 == strcmp ( growl[ll], "data" ) ) ) ll++; else if ( ( NULL != ( a = DXGetAttribute ( a, "dep" ) ) ) && ( CLASS_STRING == DXGetObjectClass ( a ) ) && ( NULL != ( dep = DXGetString ( (String)a ) ) ) && ( ( 0 == strcmp ( dep, "positions" ) ) || ( 0 == strcmp ( dep, "connections" ) ) ) ) ll++; } break; } growl [ ll ] = NULL; if ( DXQueryDebug ( "I" ) ) { DXDebug ( "I", "Grow component list length = %d", ll ); for ( i=0; i=(i+4)) ? " = `%s',`%s',`%s',`%s'" : (ll==(i+3)) ? " = `%s',`%s',`%s'" : (ll==(i+2)) ? " = `%s',`%s'" : " = `%s'", growl[i], growl[i+1], growl[i+2], growl[i+3] ); } DXASSERTGOTO ( DXGetGroupClass ( (Group) input ) == CLASS_COMPOSITEFIELD ); if ( SavedCopies.used >= ( SavedCopiesMaxDEF - 1 ) ) DXErrorGoto ( ERROR_UNEXPECTED, "more compositefields to grow in copy_grow_save" ); /* XXX - COPY_STRUCTURE vs COPY_ATTRIBUTES */ if ( ERROR == ( copy = (CompositeField) DXCopy ( (Object) input, COPY_STRUCTURE ) ) ) if ( DXGetError() != ERROR_NONE ) /* proper error */ goto error; else DXErrorGoto ( ERROR_INTERNAL, "DXCopy: returned error but didn't set the ErrorCode" ) else if ( DXGetError() != ERROR_NONE ) DXMessageGoto ( "DXCopy: set the ErrorCode but didn't return error" ) /* else: properly succeeded */ if ( !DXGrowV ( (Object) copy, 1, GROW_NONE, growl ) ) if ( DXGetError() != ERROR_NONE ) /* proper error */ goto error; else DXErrorGoto ( ERROR_INTERNAL, "DXGrow: returned error but didn't set the ErrorCode" ) else if ( DXGetError() != ERROR_NONE ) DXMessageGoto ( "DXGrow: set the ErrorCode but didn't return error" ) /* else: properly succeeded */ SavedCopies.cf [ ++SavedCopies.used ] = copy; return copy; error: ERROR_SECTION; DXDelete ( (Object) copy ); copy = NULL; return ERROR; } /* * Traversal section: * See parts.c/DXProcessParts for desired bahavior * for a traverser such as this. * Who calls who: * m_Isosurface * _dxf_IsosurfaceObject * stats * iso_part * stats * iso_part{recursive} * DXAddTask with iso_added_task * - or - * iso_added_task * isosurface_field */ /*-----------------------------------------*\ \*-----------------------------------------*/ static Error add_attribute ( Object object, iso_arg_type *iso_arg, int i ) { Array array = NULL; Pointer valp = NULL; int valc; DXASSERTGOTO ( ERROR != iso_arg->isovals ); /* if i<0 and module==ISOSURFACE, add entire array of isovals */ if (iso_arg->module==BAND || (iso_arg->module==ISOSURFACE && i<0)) { valp = iso_arg->isovals; valc = iso_arg->number; } else { valp = &iso_arg->isovals[i]; valc = 1; } if ( object != NULL ) { if ( ( ERROR == ( array = DXNewArray ( TYPE_FLOAT, CATEGORY_REAL, 0, 0 ) ) ) || !DXAllocateArray ( array, valc ) || !DXAddArrayData ( array, 0, valc, valp ) || !DXTrim ( array ) || !DXSetAttribute ( object, ATTR_NAME(iso_arg), (Object)array ) ) goto error; if ( ( iso_arg->module == ISOSURFACE && i > -1 ) && ( CLASS_GROUP == DXGetObjectClass ( iso_arg->parent[0] ) ) && ( CLASS_SERIES == DXGetGroupClass ( (Group) iso_arg->parent[0] ) ) && ( NULL == DXGetAttribute ( (Object)object, "series position" ) ) ) if ( !DXSetAttribute ( object, "series position", (Object)array ) ) goto error; } return OK; error: ERROR_SECTION; return ERROR; } /*-----------------------------------------*\ set by DXAddTask called by DXExecuteTaskGroup \*-----------------------------------------*/ static Error iso_added_task ( Pointer args ) { iso_arg_type *argcast = (iso_arg_type *) args; Field *outputs = NULL; int *skipvec = NULL; float min, max; int i; int have_hit; int can_cull_fields; int can_setmember; if ( !args ) DXErrorGoto ( ERROR_MISSING_DATA, "during DXAdd(ed)Task" ); if ( OBJ_ERROR == iso_object_type_check ( argcast->self ) ) goto error; if ( !DXStatistics ( argcast->self, "data", &min, &max, NULL, NULL ) ) DXMessageGoto ( "Statistics on field \"data\" component" ) switch ( DXGetObjectClass ( argcast->parent[0] ) ) { case CLASS_XFORM: case CLASS_SCREEN: case CLASS_CLIPPED: can_cull_fields = 0; break; case CLASS_GROUP: can_cull_fields = ( DXGetGroupClass ( (Group) argcast->parent[0] ) == CLASS_COMPOSITEFIELD ); break; default: DXErrorGoto ( ERROR_UNEXPECTED, "parent not a group" ); break; } have_hit = 0; if ( argcast->module == BAND ) have_hit = 1; else for ( i=0; ( ( i < VALUE_COUNT ( argcast ) ) && !have_hit ); i++ ) if ( ( argcast->isovals[i] >= min ) && ( argcast->isovals[i] <= max ) ) have_hit = 1; /* this trivial case shadda been done call -1 */ if ( !have_hit && can_cull_fields ) /* XXX */ goto ok; if ( ( ERROR == ( outputs = (Field *) DXAllocateZero ( sizeof(Field) * STRUCT_COUNT ( argcast ) ) ) ) || ( ERROR == ( skipvec = (int *) DXAllocate ( sizeof(int) * STRUCT_COUNT ( argcast ) ) ) ) ) goto error; for ( i=0; iisovals[i] >= min ) && ( argcast->isovals[i] <= max ) ) skipvec[i] = 0; else /* skip test not valid for a 2-valued system */ skipvec[i] = ( argcast->module == ISOSURFACE ) ? 1 : 0; if ( can_cull_fields ) { for ( i=0; iself, argcast->number, argcast->isovals, (argcast->have_minmax)? &argcast->band_min_cf : NULL, argcast->module, argcast->remap, outputs, skipvec, argcast->normal_type, argcast->gradient_interpolator, argcast->is_grown, argcast->normal_direction ) || ( DXGetError() != ERROR_NONE ) ) goto error; /* if(argcast->is_grown)DXShrink(); not required: grown area is Deleted */ for ( i=0; iparent[i] ) ) { case CLASS_GROUP: if ( ( CLASS_SERIES == DXGetGroupClass ( (Group) argcast->parent[i] ) ) && ( -1 != argcast->series_ordinal ) ) { if ( !DXSetSeriesMember ( (Series) argcast->parent[i], argcast->series_ordinal, (double) argcast->series_FP_val, (Object) outputs[i] ) ) goto error; } else if ( !DXSetMember ( (Group) argcast->parent[i], argcast->member_name, (Object) outputs[i] ) ) goto error; break; case CLASS_XFORM: if ( !DXSetXformObject ( (Xform) argcast->parent[i], (Object) outputs[i] ) ) goto error; break; case CLASS_SCREEN: if ( !DXSetScreenObject ( (Screen) argcast->parent[i], (Object) outputs[i] ) ) goto error; break; case CLASS_CLIPPED: if ( !DXSetClippedObjects ( (Clipped) argcast->parent[i], (Object) outputs[i], NULL ) ) goto error; break; } } if (argcast && argcast->parent && argcast->module == ISOSURFACE && argcast->task_counter == 0) { add_attribute((Object)argcast->parent[0], argcast, -1); } ok: DXFree ( (Pointer) outputs ); DXFree ( (Pointer) skipvec ); DXFree ( (Pointer) argcast->isovals ); DXFree ( (Pointer) argcast->parent ); outputs = NULL; skipvec = NULL; argcast->isovals = NULL; argcast->parent = NULL; return OK; error: ERROR_SECTION; if ( outputs ) { for ( i=0; iisovals ); DXFree ( (Pointer) argcast->parent ); skipvec = NULL; argcast->isovals = NULL; argcast->parent = NULL; return ERROR; } /*--------------------------------*\ recursive \*--------------------------------*/ static Error iso_part ( iso_arg_type iso_arg ) { Class class; int i; iso_arg_type call_arg; float *deletable_isovals = NULL; CompositeField grown; call_arg = iso_arg; call_arg.isovals = NULL; call_arg.parent = NULL; /* Significantly: copy over the invariant attributes */ /* * Traverse down from: * iso_arg.parent * iso_arg.self to call_arg.parent * call_arg.self * * Or act on iso_arg.self if a leaf. */ switch ( class = DXGetObjectClass ( iso_arg.self ) ) { case CLASS_FIELD: /* XXX - output culling is 'kosher'? */ /* * DXCopy Arrayed data (make unique) and submit task. */ if ( !DXEmptyField ( (Field) iso_arg.self ) ) { /* * The stats>DXStatistics call will fail on EmptyFields. * hence it had to be moved here. */ if ( !stats ( &iso_arg, &deletable_isovals ) ) goto error; DXASSERTGOTO ( iso_arg.isovals != NULL ); /* * arguments are copied so that they can be deleted * without contention by each added task */ if ( ( ERROR == ( call_arg.parent = (Object *) DXAllocate ( STRUCT_COUNT(&iso_arg) * sizeof (Object) ))) || ( ERROR == ( call_arg.isovals = (float *) DXAllocate ( VALUE_COUNT(&iso_arg) * sizeof (float) ) ) ) || ! memcpy ( (char *)call_arg.parent, (char *)iso_arg.parent, ( STRUCT_COUNT(&iso_arg) * sizeof (Object) ) ) || ! memcpy ( (char *)call_arg.isovals, (char *)iso_arg.isovals, ( VALUE_COUNT(&iso_arg) * sizeof (float) ) ) ) goto error; /* * Recall that DXAddTask will copy its input when * it is passed in as non-zero length. */ call_arg.task_counter = _dxd_isosurface_task_counter++; if ( !DXAddTask ( iso_added_task, (Pointer)&call_arg, sizeof( iso_arg_type ), (double)1.0 ) ) goto error; } break; case CLASS_XFORM: case CLASS_SCREEN: case CLASS_CLIPPED: call_arg.isovals = iso_arg.isovals; if ( ERROR == ( call_arg.parent = (Object *) DXAllocate ( STRUCT_COUNT(&iso_arg) * sizeof (Object) ) ) ) goto error; for ( i=0; iDXStatistics call would fail on EmptyFields. * hence it had to be moved away from the top of this routine. */ if ( !stats ( &iso_arg, &deletable_isovals ) ) goto error; /* * DXCopy and DXGrow if a composite field and forming local gradient * Form contents of variable call_arg with each group member. * - miscellaneous settings are copied. * - isovalues are referenced * - parents are created from attribute copy of the group * - parents are setmembered up one level within 'grandparent' * Call IsoPart with call_arg across the membership of the group. */ if ( ( DXGetGroupClass ( (Group)iso_arg.self ) == CLASS_COMPOSITEFIELD ) && /* Valid complaint: only useful for volume connections! */ is_volume_topology ( (CompositeField)iso_arg.self ) && ( iso_arg.normal_type == NORMALS_COMPUTED ) ) { if ( ERROR == ( grown = copy_grow_save ( (CompositeField) iso_arg.self )) ) goto error; iso_arg.self = (Object)grown; call_arg.is_grown = 1; } if ( DXGetError() != ERROR_NONE ) /* is_volume_topology */ goto error; call_arg.isovals = iso_arg.isovals; if ( ERROR == ( call_arg.parent = (Object *) DXAllocate ( STRUCT_COUNT(&iso_arg) * sizeof (Object) ) ) ) goto error; for ( i=0; i