/*--------------------------------------------------------------------- DoubleTriangle builds the initial double triangle. It first finds 3 noncollinear points and makes two faces out of them, in opposite order. It then finds a fourth point that is not coplanar with that face. The vertices are stored in the face structure in counterclockwise order so that the volume between the face and the point is negative. Lastly, the 3 newfaces to the fourth point are constructed and the data structures are cleaned up. ---------------------------------------------------------------------*/ void DoubleTriangle( void ) { tVertex v0, v1, v2, v3; tFace f0, f1 = NULL; int vol; /* Find 3 noncollinear points. */ v0 = vertices; while ( Collinear( v0, v0->next, v0->next->next ) ) if ( ( v0 = v0->next ) == vertices ) printf("DoubleTriangle: All points are Collinear!\n"), exit(0); v1 = v0->next; v2 = v1->next; /* Mark the vertices as processed. */ v0->mark = PROCESSED; v1->mark = PROCESSED; v2->mark = PROCESSED; /* Create the two "twin" faces. */ f0 = MakeFace( v0, v1, v2, f1 ); f1 = MakeFace( v2, v1, v0, f0 ); /* Link adjacent face fields. */ f0->edge[0]->adjface[1] = f1; f0->edge[1]->adjface[1] = f1; f0->edge[2]->adjface[1] = f1; f1->edge[0]->adjface[1] = f0; f1->edge[1]->adjface[1] = f0; f1->edge[2]->adjface[1] = f0; /* Find a fourth, noncoplanar point to form tetrahedron. */ v3 = v2->next; vol = VolumeSign( f0, v3 ); while ( !vol ) { if ( ( v3 = v3->next ) == v0 ) printf("DoubleTriangle: All points are coplanar!\n"), exit(0); vol = VolumeSign( f0, v3 ); } /* Insure that v3 will be the first added. */ vertices = v3; if ( debug ) { fprintf(stderr, "DoubleTriangle: finished. Head repositioned at v3.\n"); PrintOut( vertices ); } }
/*--------------------------------------------------------------------- Convexity checks that the volume between every face and every point is negative. This shows that each point is inside every face and therefore the hull is convex. ---------------------------------------------------------------------*/ void Convexity( void ) { register tFace f; register tVertex v; int vol; f = faces; do { v = vertices; do { if ( v->mark ) { vol = VolumeSign( f, v ); if ( vol < 0 ) break; } v = v->next; } while ( v != vertices ); f = f->next; } while ( f != faces ); if ( f != faces ) fprintf( stderr, "Checks: NOT convex.\n"); else if ( check ) fprintf( stderr, "Checks: convex.\n"); }
char SegTriCross( tPointi T, tPointd q, tPointd r ) { int vol0, vol1, vol2; vol0 = VolumeSign( q, Vertices[ T[0] ], Vertices[ T[1] ], r ); vol1 = VolumeSign( q, Vertices[ T[1] ], Vertices[ T[2] ], r ); vol2 = VolumeSign( q, Vertices[ T[2] ], Vertices[ T[0] ], r ); /* Same sign: segment intersects interior of triangle. */ if ( ( ( vol0 > 0 ) && ( vol1 > 0 ) && ( vol2 > 0 ) ) || ( ( vol0 < 0 ) && ( vol1 < 0 ) && ( vol2 < 0 ) ) ) return 'f'; /* Opposite sign: no intersection between segment and triangle */ if ( ( ( vol0 > 0 ) || ( vol1 > 0 ) || ( vol2 > 0 ) ) && ( ( vol0 < 0 ) || ( vol1 < 0 ) || ( vol2 < 0 ) ) ) return '0'; else if ( ( vol0 == 0 ) && ( vol1 == 0 ) && ( vol2 == 0 ) ) return '0'; /* Two zeros: segment intersects vertex. */ else if ( ( ( vol0 == 0 ) && ( vol1 == 0 ) ) || ( ( vol0 == 0 ) && ( vol2 == 0 ) ) || ( ( vol1 == 0 ) && ( vol2 == 0 ) ) ) return 'v'; /* One zero: segment intersects edge. */ else if ( ( vol0 == 0 ) || ( vol1 == 0 ) || ( vol2 == 0 ) ) return 'e'; else fprintf( stderr, "Error 2 in SegTriCross\n" ); return '0'; }
char SegmentTriangleIntersection::SegTriCross( tPointi T, tPointd q, tPointd r ) { double vol0, vol1, vol2; vol0 = VolumeSign( q, Vertices[ T[0] ], Vertices[ T[1] ], r ); vol1 = VolumeSign( q, Vertices[ T[1] ], Vertices[ T[2] ], r ); vol2 = VolumeSign( q, Vertices[ T[2] ], Vertices[ T[0] ], r ); //printf( "SegTriCross: vol0 = %f; vol1 = %f; vol2 = %f\n", vol0, vol1, vol2 ); /* Same sign: segment intersects interior of triangle. */ if ( ( ( vol0 > 0 ) && ( vol1 > 0 ) && ( vol2 > 0 ) ) || ( ( vol0 < 0 ) && ( vol1 < 0 ) && ( vol2 < 0 ) ) ) return 'f'; /* Opposite sign: no intersection between segment and triangle */ if ( ( ( vol0 > 0 ) || ( vol1 > 0 ) || ( vol2 > 0 ) ) && ( ( vol0 < 0 ) || ( vol1 < 0 ) || ( vol2 < 0 ) ) ) return '0'; else if ( ( vol0 == 0 ) && ( vol1 == 0 ) && ( vol2 == 0 ) ) fprintf( stderr, "Error 1 in SegTriCross\n" ), exit(EXIT_FAILURE); /* Two zeros: segment intersects vertex. */ else if ( ( ( vol0 == 0 ) && ( vol1 == 0 ) ) || ( ( vol0 == 0 ) && ( vol2 == 0 ) ) || ( ( vol1 == 0 ) && ( vol2 == 0 ) ) ) return 'v'; /* One zero: segment intersects edge. */ else if ( ( vol0 == 0 ) || ( vol1 == 0 ) || ( vol2 == 0 ) ) return 'e'; else fprintf( stderr, "Error 2 in SegTriCross\n" ), exit(EXIT_FAILURE); }
/*--------------------------------------------------------------------- AddOne is passed a vertex. It first determines all faces visible from that point. If none are visible then the point is marked as not onhull. Next is a loop over edges. If both faces adjacent to an edge are visible, then the edge is marked for deletion. If just one of the adjacent faces is visible then a new face is constructed. ---------------------------------------------------------------------*/ int AddOne( tVertex p ) { tFace f; tEdge e, temp; int vol; int vis = FALSE; if ( debug ) { fprintf(stderr, "AddOne: starting to add v%d.\n", p->vnum); PrintOut( vertices ); } /* Mark faces visible from p. */ f = faces; do { vol = VolumeSign( f, p ); if (debug) fprintf(stderr, "faddr: %p paddr: %p Vol = %d\n", f,p,vol); if ( vol < 0 ) { f->visible = VISIBLE; vis = TRUE; } f = f->next; } while ( f != faces ); /* If no faces are visible from p, then p is inside the hull. */ if ( !vis ) { p->onhull = !ONHULL; return FALSE; } /* Mark edges in interior of visible region for deletion. Erect a newface based on each border edge. */ e = edges; do { temp = e->next; if ( e->adjface[0]->visible && e->adjface[1]->visible ) /* e interior: mark for deletion. */ e->deleted = REMOVED; else if ( e->adjface[0]->visible || e->adjface[1]->visible ) /* e border: make a new face. */ e->newface = MakeConeFace( e, p ); e = temp; } while ( e != edges ); return TRUE; }
int chIsPointInside(int pos[]) { int s = 1; struct tVertexStructure p; tFace f; if(faces == NULL) return 0; p.v[X] = pos[0]; p.v[Y] = pos[1]; p.v[Z] = pos[2]; f = faces; do { if(VolumeSign(f,&p) < 0) s = 0; f = f ->next; } while(s==1 && f!=faces); return s; }