📄 sac.c
字号:
#include "qhull_a.h"char qh_version[] = "sac 96/8/19";#define DIM 3 /* dimension of points, must be 3! */#define MAXpoints 1000 /* not critical */static void new_facet( void);static void add_vertex_to_facet( int id);static void add_potential_half_edge( int a, int b);static void process_facet( void);static int construct_hull( double (*points)[3], int * num_rings, int rings[]);int sac_qhull( int npts, const double (*input_array)[DIM], double (*points)[DIM], int * size_rings, int rings[], int * num_faces, double (*faces)[DIM+1]){ boolT ismalloc; int curlong, totlong, exitcode; char options [200]; int v, d, numv, numr, numf; coordT array[MAXpoints][DIM]; facetT *facet; vertexT *vertex; vertexT **vertexp; numf = 0; if ( npts > MAXpoints ) { fprintf( stderr, "sac_qhull asked to compute hull of %d points," " but is only compiled to accept a maximum of %d.\n" " To proceed, re-compile with a larger value of MAXpoints.\n", npts, MAXpoints); return 0; } /* copy the points given */ for ( v=0 ; v<npts ; v++ ) for ( d=0 ; d<DIM ; d++ ) array[v][d] = input_array[v][d]; ismalloc= False; /* True if qh_freeqhull should 'free(array)' */ qh_init_A (stdin, stdout, stderr, 0, NULL); exitcode= setjmp (qh errexit); if (exitcode) { return exitcode; } strcat (qh rbox_command, "user_eg cube"); sprintf (options, "qhull s Tcv C-0"); qh_initflags (options); qh_init_B (array[0], npts, DIM, ismalloc); qh_qhull(); qh_check_output(); FORALLfacets { if ( faces!=0 ) { for ( d=0 ; d<3 ; d++ ) faces[numf][d] = facet->normal[d]; faces[numf++][3] = facet->offset; } new_facet(); FOREACHvertex_( facet->vertices) { add_vertex_to_facet( vertex->id); } process_facet(); } numv = construct_hull( points, size_rings, rings); if ( num_faces!=0 ) *num_faces = numf; qh NOerrexit= True; qh_freeqhull (!qh_ALL); qh_memfreeshort (&curlong, &totlong); return numv;} /* sac_qhull */struct half_edge_entry { int this_id, other_id; int confirmed; struct half_edge_entry * next; };/* The table structure used to store information about half-edges * as they are discovered. The entries are indexed by the vertex of * smallest ID, and held in unsorted linked-lists for each first vertex. */static struct half_edge_entry * vertex_table[MAXpoints];/* For efficiency we maintain a linked list of free half-edge structure * nodes, and refer to this first when allocating nodes. */static struct half_edge_entry * half_edge_free_list = 0;/* For each facet we need to store the list of its vertices (IDs) */static int temp_vertex_list[MAXpoints], temp_vertex_list_size = 0;/* vertex_map[ID] says where to find vertex with given ID in the point * list that is output. That is, we don't assume that qhull ID's form * a contiguous set, although they probably do! */static int vertex_map[MAXpoints];/* static to say whether the tables have been initialised yet */static int sac_tables_initialised = 0;/* counters for the number of features found */static int max_vertex_id = 0, num_half_edges = 0, num_faces = 0;/* Should be called once for each facet, before calling add_vertex_to_facet */static void new_facet( void){ int i; if ( !sac_tables_initialised ) { for ( i=0 ; i<MAXpoints ; i++ ) { vertex_map[i] = 0; vertex_table[i] = 0; } max_vertex_id = 0; num_half_edges = num_faces = 0; sac_tables_initialised = 1; } temp_vertex_list_size = 0; return;}static void add_vertex_to_facet( int id){ if ( id<0 || id>=MAXpoints ) { fprintf( stderr, "Bad point index generated (%d)\n", id); exit( 1); } num_half_edges++; temp_vertex_list[temp_vertex_list_size++] = id; vertex_map[id] = 1; if ( id>max_vertex_id ) max_vertex_id = id; return;}static void process_facet( void){ int i, j; for ( i=0 ; i<temp_vertex_list_size-1 ; i++ ) for ( j=i+1 ; j<temp_vertex_list_size ; j++ ) add_potential_half_edge( temp_vertex_list[i], temp_vertex_list[j]); num_faces++; return;}static void add_potential_half_edge( int a, int b){ struct half_edge_entry * hep, * new_he; if ( a>b ) { add_potential_half_edge( b, a); return; } /* look for an entry for this potential half edge */ hep = vertex_table[a]; while ( hep!=0 ) { if ( hep->other_id==b ) /* then this edge has been seen before */ { /* check whether it's already been seen twice -- error */ if ( hep->confirmed ) { fprintf( stderr, "Bad edge generated, id's %d and %d\n", hep->this_id, hep->other_id); exit( 1); } /* otherwise, confirm the entry */ hep->confirmed = 1; return; } hep = hep->next; } /* if we get here, there was no existing entry */ if ( half_edge_free_list != 0 ) { new_he = half_edge_free_list; half_edge_free_list = half_edge_free_list->next; } else { new_he = (struct half_edge_entry *) malloc( sizeof(struct half_edge_entry)); if ( new_he==0 ) { fprintf( stderr, "Malloc failed on half-edge entry\n"); exit( 1); } } new_he->this_id = a; new_he->other_id = b; new_he->confirmed = 0; new_he->next = vertex_table[a]; vertex_table[a] = new_he; return;}static int construct_hull( double (*points)[3], int * num_rings, int rings[]){ int nexte, d, v, num_vertices, num_actual_half_edges, otherv; vertexT *vertex; struct half_edge_entry * hep, * free_he, * next_he; /* reset the 'tables initialised' flag */ sac_tables_initialised = 0; /* count number of vertices, and set up the vertex map */ num_vertices = 0; for ( v=0 ; v<=max_vertex_id ; v++ ) { if ( vertex_map[v] ) vertex_map[v] = num_vertices++; } /* check the Euler characteristic: 2V - H + 2F = 4, H = half-edges */ if ( 2*num_vertices - num_half_edges + 2*num_faces != 4 ) { fprintf( stderr, "Bad Euler characteristic for hull " "(%d vertices, %d half-edges, %d faces\n", num_vertices, num_half_edges, num_faces); exit( 1); } /* now fill in the vertex coordinates entries */ if ( points!=0 ) { FORALLvertices { for ( d=0 ; d<3 ; d++ ) points[vertex_map[vertex->id]][d] = vertex->point[d]; } } nexte = num_vertices; num_actual_half_edges = 0; /* now process the half-edges */ for ( v=0 ; v<=max_vertex_id ; v++ ) { hep = vertex_table[v]; if ( hep==0 ) continue; if ( rings!= 0 ) rings[vertex_map[v]] = nexte; while ( hep!=0 ) { next_he = hep->next; /* There are 3 things that can happen to each node. If it is * unconfirmed, we dispose of it. If it confirmed, and it's the * first time that it's been seen (v==this_id), we move it to * the list for other_id. Otherwise, we dispose of it. */ if ( hep->confirmed ) { num_actual_half_edges++; if ( hep->this_id==v ) { otherv = hep->other_id; hep->next = vertex_table[otherv]; vertex_table[otherv] = hep; free_he = 0; } else { otherv = hep->this_id; free_he = hep; } if ( num_actual_half_edges <= num_half_edges ) { if ( rings!=0 ) rings[nexte] = vertex_map[otherv]; nexte++; } } else /* ! hep->confirmed */ free_he = hep; hep = next_he; /* To dispose, add the node to the free list of nodes */ if ( free_he!=0 ) { free_he->next = half_edge_free_list; half_edge_free_list = free_he; } } /* terminate the ring entries for the current vertex */ if ( rings!=0 ) rings[nexte] = -1; nexte++; } if ( num_actual_half_edges != num_half_edges ) { fprintf( stderr, "Inconsistent half-edges in hull (%d vertices, " "%d expected half-edges, %d half-edges found, %d faces\n", num_vertices, num_half_edges, num_actual_half_edges, num_faces); exit( 1); } if ( num_rings!=0 ) * num_rings = nexte; return num_vertices;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -