chull.C

Go to the documentation of this file.
00001 /* --
00002 OpenFX version 2.0 - Modelling, Animation and Rendering Package
00003 Copyright (C) 2000 - 2007 OpenFX Development Team
00004 -- */
00005 
00006 /*  CHULL.C  */
00007 #include <stdlib.h>
00008 #include <stdio.h>
00009 #include <setjmp.h>
00010 #include <math.h>
00011 #include <windows.h>
00012 
00013 #include "struct.h"
00014 #include "dstruct.h"
00015 
00016 #include "chull.h"
00017 
00018 jmp_buf jmp_buf_here;
00019 
00020 /* Define structures for O'Rourke's code vertices, edges and faces */
00021 typedef BOOL    bool;
00022 
00023 typedef struct tVertexStructure tsVertex;
00024 typedef tsVertex *tVertex;
00025 
00026 typedef struct tEdgeStructure tsEdge;
00027 typedef tsEdge *tEdge;
00028 
00029 typedef struct tFaceStructure tsFace;
00030 typedef tsFace *tFace;
00031 
00032 struct tVertexStructure {
00033    int      v[3];
00034    int      vnum;
00035    int      OFXid;           /* used by OpenFX for vertex ID when building */
00036    tEdge    duplicate;       /* pointer to incident cone edge (or NULL) */
00037    bool     onhull;                    /* T iff point on hull. */
00038    bool     mark;            /* T iff point already processed. */
00039    tVertex  next, prev;
00040 };
00041 
00042 struct tEdgeStructure {
00043    tFace    adjface[2];
00044    tVertex  endpts[2];
00045    tFace    newface;            /* pointer to incident cone face. */
00046    bool     HULL_DELETE;                /* T iff edge should be HULL_DELETE. */
00047    tEdge    next, prev;
00048 };
00049 
00050 struct tFaceStructure {
00051    tEdge    edge[3];
00052    tVertex  vertex[3];
00053    bool     visible;            /* T iff face visible from new point. */
00054    tFace    next, prev;
00055 };
00056 
00057 /*====================================================================
00058     macros.h
00059  
00060         macros used to access data structures and perform quick tests.
00061 
00062   ====================================================================*/
00063 
00064 /* general-purpose macros */
00065 #define SWAP(t,x,y)     { t = x; x = y; y = t; }
00066 
00067 
00068 #define NEW(p,type)     if ((p=(type *) malloc (sizeof(type))) == NULL) {\
00069                                 longjmp(jmp_buf_here,-1);\
00070                         }
00071 
00072 #define FREE(p)         if (p) { free ((char *) p); p = NULL; }
00073 
00074 
00075 #define HULL_ADD( head, p )  if ( head )  { \
00076                                 p->next = head; \
00077                                 p->prev = head->prev; \
00078                                 head->prev = p; \
00079                                 p->prev->next = p; \
00080                         } \
00081                         else { \
00082                                 head = p; \
00083                                 head->next = head->prev = p; \
00084                         }
00085 
00086 #define HULL_DELETE( head, p ) if ( head )  { \
00087                                 if ( head == head->next ) \
00088                                         head = NULL;  \
00089                                 else if ( p == head ) \
00090                                         head = head->next; \
00091                                 p->next->prev = p->prev;  \
00092                                 p->prev->next = p->next;  \
00093                                 FREE( p ); \
00094                         } 
00095 
00097 
00098 #define DESELECTED 0
00099 #define SELECTED   1
00100 #define MINUNIT       2048L     // was 1024 trying larger to prevent error
00101 #define MAXUNIT   33554432L
00102 
00103 #ifndef min
00104 #define min(a,b)  ( ((a) < (b)) ? (a) : (b) )
00105 #endif
00106 #ifndef max
00107 #define max(a,b)  ( ((a) > (b)) ? (a) : (b) )
00108 #endif
00109 
00110 BOOL    DoubleTriangle( void );
00111 void    ConstructHull( void );
00112 tVertex MakeNullVertex( void );
00113 void    DeleteTemporaryStructures(void);
00114 
00115 /* Define vertex indices. */
00116 #define X   0
00117 #define Y   1
00118 #define Z   2
00119 
00120 /* Global variable definitions for temporary structures */
00121 tVertex vertices = NULL;
00122 tEdge edges      = NULL;
00123 tFace faces      = NULL;
00124 
00125 static HWND      hParent;
00126 static HINSTANCE hThisInstance;
00127 
00128 #if __WATCOMC__
00129 int APIENTRY LibMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00130 #else
00131 BOOL WINAPI DllMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00132 #endif
00133   switch (dwReason) {
00134     case DLL_PROCESS_ATTACH: {
00135       hThisInstance=hDLL;
00136       if(hDLL == NULL)MessageBox ( GetFocus()," NULL instance",NULL, MB_OK);
00137       break;
00138     }
00139     case DLL_PROCESS_DETACH:
00140       break;
00141   }
00142   return TRUE;
00143 }
00144 
00145 BOOL _Xmodeler
00146  (HWND parent_window,HWND info_window,X__STRUCTURE *lpevi){
00147  char text_string[255],name_string[255];
00148  lpEVI=lpevi;
00149  hParent=parent_window;
00150  LoadString(hThisInstance,IDX_STRING2,text_string,256);
00151  LoadString(hThisInstance,IDX_STRING1,name_string,256);
00152  if(MessageBox(hParent,text_string,name_string,MB_OKCANCEL)
00153                == IDCANCEL)return FALSE;
00154  else{
00155    HCURSOR hSave;
00156    vertex *vp;
00157    long i,maxdim;
00158    long xmin=MAXUNIT,xmax=-MAXUNIT,ymin=MAXUNIT,ymax=-MAXUNIT,zmin=MAXUNIT,zmax=-MAXUNIT;
00159    double scale;
00160    if(NvertSelect < 4 || NvertSelect > 32000)return FALSE;
00161    hSave=SetCursor(LoadCursor(NULL,IDC_WAIT));
00162    vp=MainVp; for(i=0;i<Nvert;i++){
00163      if(vp->status == SELECTED){
00164        if(vp->xyz[0] < xmin)xmin=vp->xyz[0];
00165        if(vp->xyz[1] < ymin)ymin=vp->xyz[1];
00166        if(vp->xyz[2] < zmin)zmin=vp->xyz[2];
00167        if(vp->xyz[0] > xmax)xmax=vp->xyz[0];
00168        if(vp->xyz[1] > ymax)ymax=vp->xyz[1];
00169        if(vp->xyz[2] > zmax)zmax=vp->xyz[2];
00170            }
00171      vp++;
00172    }
00173    maxdim=max(xmax-xmin,ymax-ymin);
00174    maxdim=max(maxdim,zmax-zmin);
00175    if(xmax-xmin > MINUNIT &&
00176       ymax-ymin > MINUNIT && 
00177           zmax-zmin > MINUNIT){ // have at least 4 non-planar non-linear vertices
00178      tVertex v;
00179      tEdge   e;
00180      tFace   f;
00181      int vnum=0;
00182      scale=(double)MINUNIT/(double)maxdim;        
00183      vp=MainVp; for(i=0;i<Nvert;i++){
00184        if(vp->status == SELECTED){
00185          v=MakeNullVertex();
00186          v->v[X] = (long)((double)vp->xyz[0]*scale);
00187          v->v[Y] = (long)((double)vp->xyz[1]*scale);
00188          v->v[Z] = (long)((double)vp->xyz[2]*scale);
00189          v->vnum=vnum++;
00190        }
00191        vp++;
00192      }
00193      //{
00194      //char str[128]; sprintf(str,"Making hull with %ld vertices",vnum);
00195      //MessageBox(NULL,str,"Before Making Hull",MB_OK);
00196      //}
00197      if(setjmp(jmp_buf_here) != 0){
00198        DeleteTemporaryStructures();
00199        SetCursor(hSave);
00200        LoadString(hThisInstance,IDX_STRING3,text_string,256);
00201        MessageBox(hParent,text_string,name_string,MB_OKCANCEL);
00202        return FALSE;
00203      }
00204      if(DoubleTriangle()){
00205        long nf=0,ne=0,nv=0;
00206              ConstructHull();
00207        // now build the OpenFX data - first count the number of extra V E F
00208        f=faces; if(f != NULL)do {
00209          nf++;
00210          f = f->next;
00211        } while(f != faces);
00212        e = edges;if(e != NULL)do {
00213          ne++;
00214                e = e->next;
00215        } while (e != edges);
00216        v = vertices; if(v != NULL)do {
00217          nv++;
00218          v = v->next;
00219        } while (v != vertices);
00220        //{
00221        //char str[128]; sprintf(str,"NV = %ld NE = %ld NF = %ld",nv,ne,nf);
00222        //MessageBox(NULL,str,"After Making Hull",MB_OK);
00223        //}
00224        // Now extend the OpenFX
00225        if(!UpdateVertexHeap(Nvert+nv))goto CANTDO;
00226        if(!UpdateEdgeHeap(Nedge+ne))goto CANTDO;
00227        if(!UpdateFaceHeap(Nface+ne))goto CANTDO;
00228        v = vertices; if(v != NULL)do {
00229          CreateVertex();
00230          vp=(MainVp+Nvert-1);
00231          vp->xyz[0]=(long)((double)(v->v[X])/scale);
00232          vp->xyz[1]=(long)((double)(v->v[Y])/scale);
00233          vp->xyz[2]=(long)((double)(v->v[Z])/scale);
00234          vp->status=DESELECTED;
00235          v->OFXid = Nvert-1;
00236          NvertDeselect++; NvertSelect--;
00237          nv++;
00238          v = v->next;
00239        } while (v != vertices);
00240 
00241        e = edges;
00242        if(e != NULL)do {
00243          CreateEdge(e->endpts[0]->OFXid,e->endpts[1]->OFXid);
00244          e = e->next;
00245        } while (e != edges);
00246        f = faces;
00247        if(f != NULL)do {
00248          CreateFace(f->vertex[0]->OFXid,f->vertex[1]->OFXid,f->vertex[2]->OFXid);
00249          f = f->next;
00250        } while(f != faces);
00251        CANTDO:;
00252      }
00253      DeleteTemporaryStructures();
00254      SetCursor(hSave);
00255      LoadString(hThisInstance,IDX_STRING3,text_string,256);
00256      MessageBox(hParent,text_string,name_string,MB_OKCANCEL);
00257    }
00258    else{
00259      LoadString(hThisInstance,IDX_STRING4,text_string,256);
00260      MessageBox(hParent,text_string,name_string,MB_OKCANCEL);
00261      SetCursor(hSave);
00262    }
00263  }
00264  return TRUE;
00265 }
00266 
00267 void DeleteTemporaryStructures(void){
00268  tEdge   e,te;
00269  tFace   f,tf;
00270  tVertex v,tv;
00271  f=faces;
00272  if(f != NULL)do {
00273    tf = f;
00274    f = f->next;
00275          FREE(tf)
00276  } while(f != faces);
00277  e = edges;
00278  if(e != NULL)do {
00279          te = e;
00280          e = e->next;
00281          FREE(te)
00282  } while (e != edges);
00283  v = vertices;
00284  if(v != NULL)do {
00285          tv = v; 
00286          v = v->next;
00287          FREE(tv)
00288  } while (v != vertices);
00289  return;
00290 }
00291 
00292 // THE O'ROURKE CODE BELOW IS MODIFIED TO ALLOW FOR A SOFT LANDING AND
00293 // COMPLY WITH OPENFX DATA STRUCTURE & WINDOWS REQUIREMENTS
00294 
00295 /*
00296 This code is described in "Computational Geometry in C" (Second Edition),
00297 Chapter 4.  It is not written to be comprehensible without the 
00298 explanation in that book.
00299 
00300 Input: 3n integer coordinates for the points.
00301 Output: the 3D convex hull, in postscript with embedded comments
00302         showing the vertices and faces.
00303 
00304 Compile: gcc -o chull chull.c (or simply: make)
00305 
00306 Written by Joseph O'Rourke, with contributions by 
00307   Kristy Anderson, John Kutcher, Catherine Schevon, Susan Weller.
00308 Last modified: March 1998
00309 Questions to orourke@cs.smith.edu.
00310 
00311 --------------------------------------------------------------------
00312 This code is Copyright 1998 by Joseph O'Rourke.  It may be freely 
00313 redistributed in its entirety provided that this copyright notice is 
00314 not removed.
00315 --------------------------------------------------------------------
00316 */
00317 
00318 /* Define flags */
00319 #define ONHULL          TRUE
00320 #define REMOVED         TRUE
00321 #define VISIBLE         TRUE
00322 #define PROCESSED       TRUE
00323 #define SAFE            1000000         /* Range of safe coord values. */
00324 
00325 /* Function declarations */
00326 void    ReadVertices( void );
00327 void    Print( void );
00328 void    SubVec( int a[3], int b[3], int c[3]);
00329 bool    HULL_ADDOne( tVertex p );
00330 int     VolumeSign(tFace f, tVertex p);
00331 int     Volumei( tFace f, tVertex p );
00332 tFace   MakeConeFace( tEdge e, tVertex p );
00333 void    MakeCcw( tFace f, tEdge e, tVertex p );
00334 tEdge   MakeNullEdge( void );
00335 tFace   MakeNullFace( void );
00336 tFace   MakeFace( tVertex v0, tVertex v1, tVertex v2, tFace f );
00337 void    CleanUp( void );
00338 void    CleanEdges( void );
00339 void    CleanFaces( void );
00340 void    CleanVertices( void );
00341 bool    Collinear( tVertex a, tVertex b, tVertex c );
00342 
00343 /*---------------------------------------------------------------------
00344 MakeNullVertex: Makes a vertex, nulls out fields.
00345 ---------------------------------------------------------------------*/
00346 tVertex MakeNullVertex( void ){
00347    tVertex  v;
00348    NEW( v, tsVertex );
00349    v->duplicate = NULL;
00350    v->onhull = !ONHULL;
00351    v->mark = !PROCESSED;
00352    HULL_ADD( vertices, v );
00353 
00354    return v;
00355 }
00356 
00357 /*---------------------------------------------------------------------
00358 SubVec:  Computes a - b and puts it into c.
00359 ---------------------------------------------------------------------*/
00360 void    SubVec( int a[3], int b[3], int c[3]){
00361    int  i;
00362 
00363    for( i=0; i < 2; i++ )
00364       c[i] = a[i] - b[i];
00365 
00366 }
00367 
00368 /*---------------------------------------------------------------------
00369  DoubleTriangle builds the initial double triangle.  It first finds 3 
00370  noncollinear points and makes two faces out of them, in opposite order.
00371  It then finds a fourth point that is not coplanar with that face.  The  
00372  vertices are stored in the face structure in counterclockwise order so 
00373  that the volume between the face and the point is negative. Lastly, the
00374  3 newfaces to the fourth point are constructed and the data structures
00375  are cleaned up. 
00376 ---------------------------------------------------------------------*/
00377 BOOL    DoubleTriangle( void ){
00378    tVertex  v0, v1, v2, v3, t;
00379    tFace    f0, f1 = NULL;
00380    tEdge    e0, e1, e2, s;
00381    int      vol;
00382         
00383    /* Find 3 noncollinear points. */
00384    v0 = vertices;
00385    while ( Collinear( v0, v0->next, v0->next->next ) )
00386       if ( ( v0 = v0->next ) == vertices )
00387           return FALSE;
00388    v1 = v0->next;
00389    v2 = v1->next;
00390         
00391    /* Mark the vertices as processed. */
00392    v0->mark = PROCESSED;
00393    v1->mark = PROCESSED;
00394    v2->mark = PROCESSED;
00395    
00396    /* Create the two "twin" faces. */
00397    f0 = MakeFace( v0, v1, v2, f1 );
00398    f1 = MakeFace( v2, v1, v0, f0 );
00399 
00400    /* Link adjacent face fields. */
00401    f0->edge[0]->adjface[1] = f1;
00402    f0->edge[1]->adjface[1] = f1;
00403    f0->edge[2]->adjface[1] = f1;
00404    f1->edge[0]->adjface[1] = f0;
00405    f1->edge[1]->adjface[1] = f0;
00406    f1->edge[2]->adjface[1] = f0;
00407         
00408    /* Find a fourth, noncoplanar point to form tetrahedron. */
00409    v3 = v2->next;
00410    vol = VolumeSign( f0, v3 );
00411    while ( !vol )   {
00412       if ( ( v3 = v3->next ) == v0 ) 
00413                   return FALSE;
00414       vol = VolumeSign( f0, v3 );
00415    }
00416         
00417    /* Insure that v3 will be the first HULL_ADDed. */
00418    vertices = v3;
00419    return TRUE; 
00420 }
00421 
00422   
00423 /*---------------------------------------------------------------------
00424 ConstructHull HULL_ADDs the vertices to the hull one at a time.  The hull
00425 vertices are those in the list marked as onhull.
00426 ---------------------------------------------------------------------*/
00427 void    ConstructHull( void ){
00428    tVertex  v, vnext;
00429    int      vol;
00430    bool     changed;
00431    v = vertices;
00432    do {
00433       vnext = v->next;
00434       if ( !v->mark ) {
00435          v->mark = PROCESSED;
00436          changed = HULL_ADDOne( v );
00437              CleanUp();
00438       }
00439       v = vnext;
00440    } while ( v != vertices );
00441 }
00442 
00443 /*---------------------------------------------------------------------
00444 HULL_ADDOne is passed a vertex.  It first determines all faces visible from 
00445 that point.  If none are visible then the point is marked as not 
00446 onhull.  Next is a loop over edges.  If both faces adjacent to an edge
00447 are visible, then the edge is marked for deletion.  If just one of the
00448 adjacent faces is visible then a new face is constructed.
00449 ---------------------------------------------------------------------*/
00450 bool    HULL_ADDOne( tVertex p )
00451 {
00452    tFace  f; 
00453    tEdge  e, temp;
00454    int    vol;
00455    bool   vis = FALSE;
00456 
00457    /* Mark faces visible from p. */
00458    f = faces;
00459    do {
00460       vol = VolumeSign( f, p );
00461       if ( vol < 0 ) {
00462          f->visible = VISIBLE;  
00463          vis = TRUE;                      
00464       }
00465       f = f->next;
00466    } while ( f != faces );
00467 
00468    /* If no faces are visible from p, then p is inside the hull. */
00469    if ( !vis ) {
00470       p->onhull = !ONHULL;  
00471       return FALSE; 
00472    }
00473 
00474    /* Mark edges in interior of visible region for deletion.
00475       Erect a newface based on each border edge. */
00476    e = edges;
00477    do {
00478       temp = e->next;
00479       if ( e->adjface[0]->visible && e->adjface[1]->visible )
00480          /* e interior: mark for deletion. */
00481          e->HULL_DELETE = REMOVED;
00482       else if ( e->adjface[0]->visible || e->adjface[1]->visible ) 
00483          /* e border: make a new face. */
00484          e->newface = MakeConeFace( e, p );
00485       e = temp;
00486    } while ( e != edges );
00487    return TRUE;
00488 }
00489 
00490 /*---------------------------------------------------------------------
00491 VolumeSign returns the sign of the volume of the tetrahedron determined by f
00492 and p.  VolumeSign is +1 iff p is on the negative side of f,
00493 where the positive side is determined by the rh-rule.  So the volume 
00494 is positive if the ccw normal to f points outside the tetrahedron.
00495 The final fewer-multiplications form is due to Bob Williamson.
00496 ---------------------------------------------------------------------*/
00497 int  VolumeSign( tFace f, tVertex p ){
00498    double  vol;
00499    int     voli;
00500    double  ax, ay, az, bx, by, bz, cx, cy, cz;
00501 
00502    ax = f->vertex[0]->v[X] - p->v[X];
00503    ay = f->vertex[0]->v[Y] - p->v[Y];
00504    az = f->vertex[0]->v[Z] - p->v[Z];
00505    bx = f->vertex[1]->v[X] - p->v[X];
00506    by = f->vertex[1]->v[Y] - p->v[Y];
00507    bz = f->vertex[1]->v[Z] - p->v[Z];
00508    cx = f->vertex[2]->v[X] - p->v[X];
00509    cy = f->vertex[2]->v[Y] - p->v[Y];
00510    cz = f->vertex[2]->v[Z] - p->v[Z];
00511 
00512    vol =   ax * (by*cz - bz*cy)
00513          + ay * (bz*cx - bx*cz)
00514          + az * (bx*cy - by*cx);
00515 
00516    /* The volume should be an integer. */
00517    if      ( vol >  0.5 )  return  1;
00518    else if ( vol < -0.5 )  return -1;
00519    else                    return  0;
00520 }
00521 /*---------------------------------------------------------------------
00522 Same computation, but computes using ints, and returns the actual volume.
00523 ---------------------------------------------------------------------*/
00524 int  Volumei( tFace f, tVertex p ){
00525    int  vol;
00526    int  ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz;
00527 
00528    ax = f->vertex[0]->v[X] - p->v[X];
00529    ay = f->vertex[0]->v[Y] - p->v[Y];
00530    az = f->vertex[0]->v[Z] - p->v[Z];
00531    bx = f->vertex[1]->v[X] - p->v[X];
00532    by = f->vertex[1]->v[Y] - p->v[Y];
00533    bz = f->vertex[1]->v[Z] - p->v[Z];
00534    cx = f->vertex[2]->v[X] - p->v[X];
00535    cy = f->vertex[2]->v[Y] - p->v[Y];
00536    cz = f->vertex[2]->v[Z] - p->v[Z];
00537 
00538    vol =  (ax * (by*cz - bz*cy)
00539          + ay * (bz*cx - bx*cz)
00540          + az * (bx*cy - by*cx));
00541 
00542    return vol;
00543 }
00544 
00545 /*---------------------------------------------------------------------
00546 MakeConeFace makes a new face and two new edges between the 
00547 edge and the point that are passed to it. It returns a pointer to
00548 the new face.
00549 ---------------------------------------------------------------------*/
00550 tFace   MakeConeFace( tEdge e, tVertex p )
00551 {
00552    tEdge  new_edge[2];
00553    tFace  new_face;
00554    int    i, j;
00555 
00556    /* Make two new edges (if don't already exist). */
00557    for ( i=0; i < 2; ++i ) 
00558       /* If the edge exists, copy it into new_edge. */
00559       if ( !( new_edge[i] = e->endpts[i]->duplicate) ) {
00560          /* Otherwise (duplicate is NULL), MakeNullEdge. */
00561          new_edge[i] = MakeNullEdge();
00562          new_edge[i]->endpts[0] = e->endpts[i];
00563          new_edge[i]->endpts[1] = p;
00564          e->endpts[i]->duplicate = new_edge[i];
00565       }
00566 
00567    /* Make the new face. */
00568    new_face = MakeNullFace();   
00569    new_face->edge[0] = e;
00570    new_face->edge[1] = new_edge[0];
00571    new_face->edge[2] = new_edge[1];
00572    MakeCcw( new_face, e, p ); 
00573         
00574    /* Set the adjacent face pointers. */
00575    for ( i=0; i < 2; ++i )
00576       for ( j=0; j < 2; ++j )  
00577          /* Only one NULL link should be set to new_face. */
00578          if ( !new_edge[i]->adjface[j] ) {
00579             new_edge[i]->adjface[j] = new_face;
00580             break;
00581          }
00582         
00583    return new_face;
00584 }
00585 
00586 /*---------------------------------------------------------------------
00587 MakeCcw puts the vertices in the face structure in counterclock wise 
00588 order.  We want to store the vertices in the same 
00589 order as in the visible face.  The third vertex is always p.
00590 
00591 Although no specific ordering of the edges of a face are used
00592 by the code, the following condition is maintained for each face f:
00593 one of the two endpoints of f->edge[i] matches f->vertex[i]. 
00594 But note that this does not imply that f->edge[i] is between
00595 f->vertex[i] and f->vertex[(i+1)%3].  (Thanks to Bob Williamson.)
00596 ---------------------------------------------------------------------*/
00597 void    MakeCcw( tFace f, tEdge e, tVertex p )
00598 {
00599    tFace  fv;   /* The visible face adjacent to e */
00600    int    i;    /* Index of e->endpoint[0] in fv. */
00601    tEdge  s;    /* Temporary, for swapping */
00602       
00603    if  ( e->adjface[0]->visible )      
00604         fv = e->adjface[0];
00605    else fv = e->adjface[1];
00606        
00607    /* Set vertex[0] & [1] of f to have the same orientation
00608       as do the corresponding vertices of fv. */ 
00609    for ( i=0; fv->vertex[i] != e->endpts[0]; ++i )
00610       ;
00611    /* Orient f the same as fv. */
00612    if ( fv->vertex[ (i+1) % 3 ] != e->endpts[1] ) {
00613       f->vertex[0] = e->endpts[1];  
00614       f->vertex[1] = e->endpts[0];    
00615    }
00616    else {                               
00617       f->vertex[0] = e->endpts[0];   
00618       f->vertex[1] = e->endpts[1];      
00619       SWAP( s, f->edge[1], f->edge[2] );
00620    }
00621    /* This swap is tricky. e is edge[0]. edge[1] is based on endpt[0],
00622       edge[2] on endpt[1].  So if e is oriented "forwards," we
00623       need to move edge[1] to follow [0], because it precedes. */
00624    
00625    f->vertex[2] = p;
00626 }
00627  
00628 /*---------------------------------------------------------------------
00629 MakeNullEdge creates a new cell and initializes all pointers to NULL
00630 and sets all flags to off.  It returns a pointer to the empty cell.
00631 ---------------------------------------------------------------------*/
00632 tEdge   MakeNullEdge( void )
00633 {
00634    tEdge  e;
00635 
00636    NEW( e, tsEdge );
00637    e->adjface[0] = e->adjface[1] = e->newface = NULL;
00638    e->endpts[0] = e->endpts[1] = NULL;
00639    e->HULL_DELETE = !REMOVED;
00640    HULL_ADD( edges, e );
00641    return e;
00642 }
00643 
00644 /*--------------------------------------------------------------------
00645 MakeNullFace creates a new face structure and initializes all of its
00646 flags to NULL and sets all the flags to off.  It returns a pointer
00647 to the empty cell.
00648 ---------------------------------------------------------------------*/
00649 tFace   MakeNullFace( void ){
00650    tFace  f;
00651    int    i;
00652 
00653    NEW( f, tsFace);
00654    for ( i=0; i < 3; ++i ) {
00655       f->edge[i] = NULL;
00656       f->vertex[i] = NULL;
00657    }
00658    f->visible = !VISIBLE;
00659    HULL_ADD( faces, f );
00660    return f;
00661 }
00662 
00663 /*---------------------------------------------------------------------
00664 MakeFace creates a new face structure from three vertices (in ccw
00665 order).  It returns a pointer to the face.
00666 ---------------------------------------------------------------------*/
00667 tFace   MakeFace( tVertex v0, tVertex v1, tVertex v2, tFace fold ){
00668    tFace  f;
00669    tEdge  e0, e1, e2;
00670 
00671    /* Create edges of the initial triangle. */
00672    if( !fold ) {
00673      e0 = MakeNullEdge();
00674      e1 = MakeNullEdge();
00675      e2 = MakeNullEdge();
00676    }
00677    else { /* Copy from fold, in reverse order. */
00678      e0 = fold->edge[2];
00679      e1 = fold->edge[1];
00680      e2 = fold->edge[0];
00681    }
00682    e0->endpts[0] = v0;              e0->endpts[1] = v1;
00683    e1->endpts[0] = v1;              e1->endpts[1] = v2;
00684    e2->endpts[0] = v2;              e2->endpts[1] = v0;
00685         
00686    /* Create face for triangle. */
00687    f = MakeNullFace();
00688    f->edge[0]   = e0;  f->edge[1]   = e1; f->edge[2]   = e2;
00689    f->vertex[0] = v0;  f->vertex[1] = v1; f->vertex[2] = v2;
00690         
00691    /* Link edges to face. */
00692    e0->adjface[0] = e1->adjface[0] = e2->adjface[0] = f;
00693         
00694    return f;
00695 }
00696 
00697 /*---------------------------------------------------------------------
00698 CleanUp goes through each data structure list and clears all
00699 flags and NULLs out some pointers.  The order of processing
00700 (edges, faces, vertices) is important.
00701 ---------------------------------------------------------------------*/
00702 void    CleanUp( void ){
00703    CleanEdges();
00704    CleanFaces();
00705    CleanVertices();
00706 }
00707 
00708 /*---------------------------------------------------------------------
00709 CleanEdges runs through the edge list and cleans up the structure.
00710 If there is a newface then it will put that face in place of the 
00711 visible face and NULL out newface. It also HULL_DELETEs so marked edges.
00712 ---------------------------------------------------------------------*/
00713 void    CleanEdges( void ){
00714    tEdge  e;    /* Primary index into edge list. */
00715    tEdge  t;    /* Temporary edge pointer. */
00716                 
00717    /* Integrate the newface's into the data structure. */
00718    /* Check every edge. */
00719    e = edges;
00720    do {
00721       if ( e->newface ) { 
00722          if ( e->adjface[0]->visible )
00723             e->adjface[0] = e->newface; 
00724          else   e->adjface[1] = e->newface;
00725          e->newface = NULL;
00726       }
00727       e = e->next;
00728    } while ( e != edges );
00729 
00730    /* HULL_DELETE any edges marked for deletion. */
00731    while ( edges && edges->HULL_DELETE ) { 
00732       e = edges;
00733       HULL_DELETE( edges, e );
00734    }
00735    e = edges->next;
00736    do {
00737       if ( e->HULL_DELETE ) {
00738          t = e;
00739          e = e->next;
00740          HULL_DELETE( edges, t );
00741       }
00742       else e = e->next;
00743    } while ( e != edges );
00744 }
00745 
00746 /*---------------------------------------------------------------------
00747 CleanFaces runs through the face list and HULL_DELETEs any face marked visible.
00748 ---------------------------------------------------------------------*/
00749 void    CleanFaces( void ){
00750    tFace  f;    /* Primary pointer into face list. */
00751    tFace  t;    /* Temporary pointer, for deleting. */
00752    while ( faces && faces->visible ) { 
00753       f = faces;
00754       HULL_DELETE( faces, f );
00755    }
00756    f = faces->next;
00757    do {
00758       if ( f->visible ) {
00759          t = f;
00760          f = f->next;
00761          HULL_DELETE( faces, t );
00762       }
00763       else f = f->next;
00764    } while ( f != faces );
00765 }
00766 
00767 /*---------------------------------------------------------------------
00768 CleanVertices runs through the vertex list and HULL_DELETEs the 
00769 vertices that are marked as processed but are not incident to any 
00770 unHULL_DELETEd edges. 
00771 ---------------------------------------------------------------------*/
00772 void    CleanVertices( void ){
00773    tEdge    e;
00774    tVertex  v, t;
00775         
00776    /* Mark all vertices incident to some unHULL_DELETEd edge as on the hull. */
00777    e = edges;
00778    do {
00779       e->endpts[0]->onhull = e->endpts[1]->onhull = ONHULL;
00780       e = e->next;
00781    } while (e != edges);
00782         
00783    /* HULL_DELETE all vertices that have been processed but
00784       are not on the hull. */
00785    while ( vertices && vertices->mark && !vertices->onhull ) { 
00786       v = vertices;
00787       HULL_DELETE( vertices, v );
00788    }
00789    v = vertices->next;
00790    do {
00791       if ( v->mark && !v->onhull ) {    
00792          t = v; 
00793          v = v->next;
00794          HULL_DELETE( vertices, t )
00795       }
00796       else v = v->next;
00797    } while ( v != vertices );
00798         
00799    /* Reset flags. */
00800    v = vertices;
00801    do {
00802       v->duplicate = NULL; 
00803       v->onhull = !ONHULL; 
00804       v = v->next;
00805    } while ( v != vertices );
00806 }
00807 
00808 /*---------------------------------------------------------------------
00809 Collinear checks to see if the three points given are collinear,
00810 by checking to see if each element of the cross product is zero.
00811 ---------------------------------------------------------------------*/
00812 bool    Collinear( tVertex a, tVertex b, tVertex c )
00813 {
00814    return 
00815          ( c->v[Z] - a->v[Z] ) * ( b->v[Y] - a->v[Y] ) -
00816          ( b->v[Z] - a->v[Z] ) * ( c->v[Y] - a->v[Y] ) == 0
00817       && ( b->v[Z] - a->v[Z] ) * ( c->v[X] - a->v[X] ) -
00818          ( b->v[X] - a->v[X] ) * ( c->v[Z] - a->v[Z] ) == 0
00819       && ( b->v[X] - a->v[X] ) * ( c->v[Y] - a->v[Y] ) -
00820          ( b->v[Y] - a->v[Y] ) * ( c->v[X] - a->v[X] ) == 0  ;
00821 }
00822 

Generated on Sun Apr 27 14:20:10 2014 for OpenFX by  doxygen 1.5.6