Makefile000064400105260101400000000011570566533370400124000ustar00stuerzl00000000000000####################################################################### ## Makefile ## ## ## ## (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) ## ## This code may be used only for non-commercial purposes ! ## ## Coauthorship of any publications using this code is claimed. ## ####################################################################### OBJ=geom.o disc.o dt.o CC=gcc CFLAGS=-g -J -DASCII -Wall main.exe: $(OBJ) gcc -g -o main.exe *.o -lm -ds en >nul ## ## ## ## (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) ## ## This code may be used only for non-commercial purposes ! ## ## Coauthorship of any publications using this code is claimed. ## ####################################################################### OBJ=geodisc.c000064400105260101400000000306160566533351600120310ustar00stuerzl00000000000000/**********************************************************************/ /* disco.c */ /* */ /* (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /* Coauthorship of any publications using this code is claimed. */ /**********************************************************************/ #include #include #include #include #include #include "geom.h" #include "disc.h" /****************************************************************************/ static int ray_intersect_plane(TVector3f *normal,double ndotp,TEdge *edge, double *t) { double ndotd; ndotd = DotVector(*normal,edge->direction); if (ndotd == 0.0) { *t = 1E30; /* far far away */ return(0); } *t = (ndotp - DotVector(*normal,edge->origin)) / ndotd; return(1); } /****************************************************************************/ static void insert_seg2(TDiscL2 **disc2d,TPoint2f *point1,TPoint2f *point2, DISCONTINUITY d,int side) { int project; double temp,np; TVector2f normal,dir; TDiscoSeg *seg; SubVector2(dir,*point2,*point1); NormalizeVector2(temp,dir); if (temp == 0.0) /* zero vector */ return; TurnVector2Left2(normal,dir); np = DotVector2(normal,*point1); seg = (TDiscoSeg *) calloc(1,sizeof(TDiscoSeg)); seg->discontinuity = d; seg->point[0] = *point1; seg->point[1] = *point2; project = FindProject2(normal); seg->t[0] = Projectd1(project,*point1); seg->t[1] = Projectd1(project,*point2); seg->side = side; if (seg->t[0] > seg->t[1]) { /* ensure correct order */ SWAP(seg->t[0],seg->t[1],temp); SWAP(seg->point[0],seg->point[1],dir); seg->side = -seg->side; } if (*disc2d == NULL) { *disc2d = (TDiscL2 *)calloc(1,sizeof(TDiscL2)); (*disc2d)->project = project; } seg->next = (*disc2d)->seg; (*disc2d)->seg = seg; } void free_disco_2d(TDiscL2 *disc2d) { TDiscoSeg *seg,*next; if (disc2d == NULL) return; seg = disc2d->seg; while (seg != NULL) { next = seg->next; free(seg); seg = next; } free(disc2d); } /****************************************************************************/ static int calc_side3d(TPlane *plane,TEdge *edge) { double ndotd,ndoto,t; ndotd = DotVector(plane->normal,edge->direction); ndoto = DotVector(plane->normal,edge->origin); if (ndotd != 0.0) { t = (plane->np - ndoto) / ndotd; if (t <= 0.0) { /* we are only on 1 side! */ if (ndotd > 0.0) return(1); /* towards front */ else return(-1); /* towards back */ } } else { if (ndoto > plane->np) /* lies before */ return(1); else if (ndoto < plane->np) /* lies behind */ return(-1); else /* ray in the plane */ return(0); } return(2); /* on both sides */ } static void insert_bsp(TBSP **bsp,TVector3f *normal,double np,TWedge *wedge) { int side1,side2; if (*bsp == NULL) { *bsp = (TBSP *)calloc(1,sizeof(TBSP)); (*bsp)->plane.normal = *normal; (*bsp)->plane.np = np; (*bsp)->discontinuity = D2; (*bsp)->wedge[0] = wedge; (*bsp)->nWedge = 1; return; } side1 = calc_side3d(&(*bsp)->plane,wedge->edge[0]); side2 = calc_side3d(&(*bsp)->plane,wedge->edge[1]); if (side1 == 2 || side2 == 2) { /* different sides */ insert_bsp(&(*bsp)->front,normal,np,wedge); insert_bsp(&(*bsp)->back,normal,np,wedge); } else if (side1 == 0 && side2 == 0) { /* new wedge */ if ((*bsp)->nWedge > MAXWEDGE) printf("ERROR"); (*bsp)->wedge[(*bsp)->nWedge] = wedge; (*bsp)->nWedge++; } else if (side1 == 0 || side2 == 0) { /* one is in */ if (side1 > 0 || side2 > 0) /* other is front */ insert_bsp(&(*bsp)->front,normal,np,wedge); else /* other is back */ insert_bsp(&(*bsp)->back,normal,np,wedge); } else if (side1 != side2) { /* different sides */ insert_bsp(&(*bsp)->front,normal,np,wedge); insert_bsp(&(*bsp)->back,normal,np,wedge); } else if (side1 > 0) /* front only */ insert_bsp(&(*bsp)->front,normal,np,wedge); else /* back only */ insert_bsp(&(*bsp)->back,normal,np,wedge); } static void gen_wedge(TBSP **bsp,TPoint3f *point,TEdge *edge0,TEdge *edge1, TWedge *wedge) { double temp,np; TVector3f normal; CrossVector(normal,edge0->direction,edge1->direction); NormalizeVector(temp,normal); np = DotVector(normal,*point); wedge->edge[0] = edge0; wedge->edge[1] = edge1; wedge->discontinuity = D2; insert_bsp(bsp,&normal,np,wedge); } /****************************************************************************/ TDisco *calc_disco_mesh(TPolygon *shooter,TPolygon *shader) { int i,j,w,idx,r1,r2; double temp; TDisco *disco; temp = DotVector(shooter->normal,shader->normal); /* same plane? */ if (temp == 1.0 && shooter->ndotp == shader->ndotp) return(NULL); if (temp == -1.0 && shooter->ndotp == -shader->ndotp) return(NULL); disco = (TDisco *)calloc(1,sizeof(TDisco)); disco->nEdges = shooter->n * shader->n; disco->edge = (TEdge *)calloc(disco->nEdges,sizeof(TEdge)); disco->nWedges = disco->nEdges * 2; disco->wedge = (TWedge *)calloc(disco->nWedges,sizeof(TWedge)); /* generate all rays */ for (i = 0; i < shooter->n; i++) { for (j = 0; j < shader->n; j++) { idx = i * shader->n + j; disco->edge[idx].origin = shader->vert[j]; SubVector(disco->edge[idx].direction,shader->vert[j], shooter->vert[i]); NormalizeVector(temp,disco->edge[idx].direction); } } /* now generate all EV wedges */ w = 0; for (i = 0; i < shooter->n; i++) { for (j = 0; j < shader->n; j++) { r1 = i * shader->n + j; r2 = ((i + 1) % shooter->n) * shader->n + j; gen_wedge(&disco->bsp,&shader->vert[j], &disco->edge[r1],&disco->edge[r2],&disco->wedge[w]); w++; } } /* now generate all VE wedges */ for (i = 0; i < shooter->n; i++) { for (j = 0; j < shader->n; j++) { r1 = i * shader->n + j; r2 = i * shader->n + ((j + 1) % shader->n); gen_wedge(&disco->bsp,&shader->vert[j], &disco->edge[r1],&disco->edge[r2],&disco->wedge[w]); w++; } } return(disco); } static void free_bsp(TBSP *bsp) { if (bsp == NULL) return; free_bsp(bsp->front); free_bsp(bsp->back); free(bsp); } void free_disco_mesh(TDisco *disco) { free_bsp(disco->bsp); free(disco->edge); free(disco->wedge); free(disco); } /****************************************************************************/ static void calc_wedges(TBSP *bsp,TPolygon *pp) { int i,behind,front; double np; if (bsp == NULL) return; behind = 0; front = 0; for (i = 0; i < pp->n; i++) { np = DotVector(bsp->plane.normal,pp->vert[i]); if (np < bsp->plane.np) behind++; else if (np > bsp->plane.np) front++; } if (front == pp->n) /* all before */ calc_wedges(bsp->front,pp); else if (behind == pp->n) calc_wedges(bsp->back,pp); else { calc_wedges(bsp->front,pp); calc_wedges(bsp->back,pp); for (i = 0; i < bsp->nWedge; i++) { bsp->wedge[i]->marked = 1; bsp->wedge[i]->edge[0]->marked = 1; bsp->wedge[i]->edge[1]->marked = 1; } } } TDiscL2 *construct_disco(TDisco *disco,TPolygon *pp,TDiscL2 *disc2d) { int i; double t; TVector3f temp; DISCONTINUITY disc; for (i = 0; i < disco->nWedges; i++) disco->wedge[i].marked = 0; calc_wedges(disco->bsp,pp); for (i = 0; i < disco->nEdges; i++) { if (! disco->edge[i].marked) continue; if (DistPt2Plane(disco->edge[i].origin,pp->normal,pp->ndotp) == 0.0) disco->edge[i].inplane = 1; else disco->edge[i].inplane = 0; (void) ray_intersect_plane(&pp->normal,pp->ndotp,&disco->edge[i],&t); temp = disco->edge[i].direction; ScaleVector(temp,t); AddVector(disco->edge[i].intersection,temp,disco->edge[i].origin); Project2d(pp->project,disco->edge[i].intersection, disco->edge[i].intersect2); } for (i = 0; i < disco->nWedges; i++) { if (! disco->wedge[i].marked) continue; disc = disco->wedge[i].discontinuity; if (disco->wedge[i].edge[0]->inplane && disco->wedge[i].edge[1]->inplane) disc = D0; insert_seg2(&disc2d,&disco->wedge[i].edge[0]->intersect2, &disco->wedge[i].edge[1]->intersect2,disc,0); } return(disc2d); } /****************************************************************************/ int find_d0_segments(TPolygon *thePoly,TPolygon *poly,TDiscL2 **disc2d) { int i,side; double d; TPoint3f *p1,*p2; TPoint2f d1,d2,norm,v; d = DotVector(thePoly->normal,poly->normal); if (d == 1.0 || d == -1.0) /* same plane */ return(0); p1 = NULL; for (i = 0; i < poly->n; i++) { if (Inplane(poly->vert[i],thePoly->normal,thePoly->ndotp)) { p1 = &poly->vert[i]; break; } } if (p1 == NULL) /* none found */ return(0); p2 = &poly->vert[(i + 1) % poly->n]; if (! Inplane(*p2,thePoly->normal,thePoly->ndotp)) { if (i != 0) { printf("1+"); /* only 1 vertex inplane? */ return(0); } p2 = &poly->vert[poly->n - 1]; /* p1 = p[0]! */ if (! Inplane(*p2,thePoly->normal,thePoly->ndotp)) { printf("1-"); /* only 1 vertex inplane? */ return(0); } } /* in p1/p2 we have the possible candidate line now! */ Project2d(thePoly->project,*p1,d1); Project2d(thePoly->project,*p2,d2); Project2d(thePoly->project,poly->normal,norm); SubVector2(v,d2,d1); if (DotVector2(norm,v) < 0.0) side = 1; /* right */ else side = -1; /* left */ insert_seg2(disc2d,&d1,&d2,D0,side); return(1); } /****************************************************************************/ int clip_segments(TPoly2 *pp,TDiscL2 *disc2d,TSegment *segs) { int i,flag,idx1,idx2,nSeg; double eps; TDiscoSeg *seg; nSeg = 0; if (disc2d == NULL) return(nSeg); eps = 1.0E-6; /* FIXME: should depend on polygon size */ seg = disc2d->seg; while (seg != NULL) { flag = 0; for (i = 0; i < pp->n; i++) { if (PointNear2(pp->vert[i],seg->point[0],eps)) { idx1 = i; flag++; } else if (PointNear2(pp->vert[i],seg->point[1],eps)) { idx2 = i; flag++; } } if (flag >= 2) { if (idx1 < idx2) idx1 = idx2 - idx1; else idx1 = idx1 - idx2; if (idx1 != 1 && idx1 != pp->n - 1) nSeg++; /* not between adj vertices */ } else { segs[nSeg].point1 = seg->point[0]; segs[nSeg].point2 = seg->point[1]; segs[nSeg].discontinuity = seg->discontinuity; if (clip2poly2(pp,&segs[nSeg].point1,&segs[nSeg].point2)) { flag = 0; for (i = 0; i < pp->n; i++) { if (PointNear2(pp->vert[i],segs[nSeg].point1,eps)) { idx1 = i; flag++; } else if (PointNear2(pp->vert[i],segs[nSeg].point2,eps)) { idx2 = i; flag++; } } if (flag >= 2) { if (idx1 < idx2) idx1 = idx2 - idx1; else idx1 = idx1 - idx2; if (idx1 != 1 && idx1 != pp->n - 1) nSeg++; /* not between adj vertices */ } else nSeg++; } } seg = seg->next; } return(nSeg); } int inside_d0(TDiscL2 *disc2d,TPoint2f *point2) { double side,t; TDiscoSeg *seg; if (disc2d == NULL || disc2d->seg == NULL) return(0); seg = disc2d->seg; if (isonline(point2,&seg->point[0],&seg->point[1])) return(1); side = calc_side(&seg->point[0],&seg->point[1],point2); t = Projectd1(disc2d->project,*point2); /* FIXME */ while (seg != NULL) { if (seg->t[0] <= t && t <= seg->t[1]) { if ((seg->side > 0.0 && side < 0.0) || (seg->side < 0.0 && side > 0.0)) return(0); } seg = seg->next; } return(1); } #define BORDER_SHIFT 1E-4 int move_d0(TPolygon *poly,TDiscL2 *disc2d,TPoint2f *point2,int inside, TVector2f *shift) { int moved; double dist,side,t,np,reflen,len,shiftlen; TDiscoSeg *seg; TVector2f line,norm,move; if (disc2d == NULL) return(0); reflen = 1.0; /* FIXME: should depend on polygon size */ InitPoint2(*shift,0.0,0.0); moved = 0; seg = disc2d->seg; t = Projectd1(disc2d->project,*point2); /* FIXME */ while (seg != NULL) { SubVector2(line,seg->point[1],seg->point[0]); NormalizeVector2(side,line); TurnVector2Left2(norm,line); np = DotVector2(norm,seg->point[0]); dist = DistPt2Line(*point2,norm,np); len = reflen * (seg->side == inside) ? -BORDER_SHIFT : BORDER_SHIFT; if (dist >= len) { /* too near */ if (seg->t[0] <= t && t <= seg->t[1]) { shiftlen = len - dist; move = norm; ScaleVector2(move,shiftlen); AddVector2(*shift,move,*shift); moved = 1; } } seg = seg->next; } return(moved); } (line,seg->point[1],seg->point[0]); NormalizeVector2(side,line); TurnVector2Left2(norm,line); np = DotVectordisc.h000064400105260101400000000034770566533351000120350ustar00stuerzl00000000000000/**********************************************************************/ /* disc.h */ /* */ /* (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /* Coauthorship of any publications using this code is claimed. */ /**********************************************************************/ #define MAXWEDGE 4 #define MAXSEGS 256 typedef enum DISCONTINUITY { NONE, D0, D1, D2, DINF } DISCONTINUITY; typedef struct TSegment { DISCONTINUITY discontinuity; TPoint2f point1; TPoint2f point2; } TSegment; typedef struct TEdge { char marked; char inplane; TPoint3f origin; /* edge origin */ TVector3f direction; /* edge direction */ TPoint3f intersection; TPoint2f intersect2; } TEdge; typedef struct TWedge { DISCONTINUITY discontinuity; char marked; TEdge *edge[2]; } TWedge; typedef struct TBSP { DISCONTINUITY discontinuity; int nWedge; TPlane plane; TWedge *wedge[MAXWEDGE]; struct TBSP *front; struct TBSP *back; } TBSP; typedef struct TDisco { int nWedges; TWedge *wedge; int nEdges; TEdge *edge; TBSP *bsp; } TDisco; typedef struct TDiscoSeg { DISCONTINUITY discontinuity; int side; TPoint2f point[2]; double t[2]; struct TDiscoSeg *next; } TDiscoSeg; typedef struct TDiscL2 { char project; TLine line; TDiscoSeg *seg; } TDiscL2; /* disc.c */ TDisco *calc_disco_mesh(TPolygon *shooter1,TPolygon *shader); TDiscL2 *construct_disco(TDisco *disco,TPolygon *pp, TDiscL2 *disc2d); int clip_segments(TPoly2 *pp,TDiscL2 *disc2d,TSegment *segs); void free_bsp2(TDiscL2 *disc2d); void free_disco_mesh(TDisco *disco); int find_d0_segments(TPolygon *thePoly,TPolygon *poly,TDiscL2 **disc2d); e; TPoint2f point[2]; double t[2]; struct TDiscoSeg *next; } TDiscoSeg; typedef struct TDiscL2 { char project; TLine line; TDiscoSeg *seg; } TDiscL2; /* disc.c */ TDisco *calc_disco_mdisco.txt000064400105260101400000000044060566533347600126100ustar00stuerzl00000000000000/**********************************************************************/ /* disco.txt */ /* */ /* (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /* Coauthorship of any publications using this code is claimed. */ /**********************************************************************/ TDisco *calc_disco_mesh(TPolygon *shooter,TPolygon *shader); Given a polygon 'shooter' and a polygon 'shader' constructs and returns the corresponding 3d-discontinuity structure (wedges). TDiscL2 *construct_disco(TDisco *disco,TPolygon *pp,TDiscL2 *disc2d); Given a 3d-discontinuity structure 'disco' and a polygon 'pp' accumulates the 2d-discontinuities in disc2d. The 2d-discontinuities are not (!) clipped to the polygon. int clip_segments(TPoly2 *pp,TDiscL2 *disc2d,TSegment *segs); Clips the 2d-discontinuties 'disc2d' to the 2d-polygon 'pp'. Result is are the discontinuity-segments in the array 'segs'. The number of discontinuity-segments is returned. void free_disco_mesh(TDisco *disco); void free_disco_2d(TDiscL2 *disc2d); Frees the memory allocated by calc_disco_mesh or construct_disco. Example: TDisco *disc3d[..]; TDiscL2 *disc2d; TPolygon poly3d,shooter,shader; TPoly2 poly2d; int nSeg; TSegment segs[...]; /* construct 2d polygon from 3d polygon */ FindProject(poly3d.normal,poly3d.project); poly2d.n = poly3d.nPts; for (i = 0; i < poly3d.nPts; i++) Project2d(poly3d.project,poly3d.vert[i],poly2d.vert[i]; /* construct all 3d-discontinuities caused by shooter */ for (all shader) disc3d[shader] = calc_disco_mesh(&shooter,&shader); /* construct all 2d-discos from all 3d-discos for a polygon 'poly3d' and clip the 2d-discos to the polygon */ disc2d = NULL; for (all shader) disc2d = construct_disco(disc3d[shader],&poly3d,disc2d); nSeg = clip_segments(poly2d,disc2d,segs); int find_d0_segments(TPolygon *thePoly,TPolygon *poly,TDiscL2 **disc2d); Find all D0 segments caused by the polygon 'poly' on the polygon 'thePoly'. The result is accumulated in disc2d. Example: disc2d = NULL; for (all polygons) (void) find_d0_segments(thePoly,poly,&disc2d); l 2d-discos from all 3d-discos for a polygon 'poly3d' and clip the 2d-discos to the polygon */ disc2d = NULL; for (all shader) disc2d = construct_disco(disc3d[shader],&poly3d,disc2d); nSeg = clip_segments(poly2d,disc2d,segs); int find_d0_segmendt.c000064400105260101400000000543400566533354700115220ustar00stuerzl00000000000000/**********************************************************************/ /* Delaunay-Triangulation-Module */ /* */ /* (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /* Coauthorship of any publications using this code is claimed. */ /**********************************************************************/ #include "dt.h" #include #include #include #include #include #define SITEALLOC 1000 static TRIANG *_surf; /******************************** geometr2 ************************/ #define v2length_2(v) ((v).x * (v).x + (v).y * (v).y) #define v2dist_2(v1,v2) ((v1).x - (v2).x) * ((v1).x - (v2).x) + \ ((v1).y - (v2).y) * ((v1).y - (v2).y) #define v2dot(v1,v2) ((v1).x * (v2).x + (v1).y * (v2).y) #define v2cross(v1,v2) ((v1).x * (v2).y - (v1).y * (v2).x) #define v2midpnt(v1,v2,v) \ { \ (v).x = ((v1).x + (v2).x) * 0.5; \ (v).y = ((v1).y + (v2).y) * 0.5; \ } #define v2sub(v1,v2,v) \ { \ (v).x = (v1).x - (v2).x; \ (v).y = (v1).y - (v2).y; \ } #define v2add(v1,v2,v) \ { \ (v).x = (v1).x + (v2).x; \ (v).y = (v1).y + (v2).y; \ } #define v2turnl(v1,v) \ { \ (v).x = -(v1).y; \ (v).y = (v1).x; \ } #define v2turnr(v1,v) \ { \ (v).x = (v1).y; \ (v).y = -(v1).x; \ } #define v2divk(v,k) \ { \ (v).x /= (k); \ (v).y /= (k); \ } #define v2normalize(v) \ { \ FLOAT _len = v2length_2(v); \ \ if (_len != 0.0) \ { \ _len = sqrt(_len); \ v2divk(v,_len); \ } \ } #define v2scale(v,s) \ { \ (v).x *= (s); \ (v).y *= (s); \ } #define v2addto(v,v1) \ { \ (v).x += (v1).x; \ (v).y += (v1).y; \ } #define incircle(a,b,c,d) (distcircle(a,b,c,d) > 0.0) DOUBLE distcircle(PNT2 *a,PNT2 *b,PNT2 *c,PNT2 *d) { DOUBLE az,bz,cz,dz,result; az = a->x * a->x + a->y * a->y; bz = b->x * b->x + b->y * b->y; cz = c->x * c->x + c->y * c->y; dz = d->x * d->x + d->y * d->y; result = ( a->y * (bz * c->x + cz * d->x + b->x * dz) + az * (b->x * c->y + b->y * d->x + c->x * d->y) + a->x * (b->y * cz + bz * d->y + c->y * dz) + bz * c->y * d->x + b->x * cz * d->y + b->y * c->x * dz ) - ( az * (b->y * c->x + c->y * d->x + b->x * d->y) + a->x * (bz * c->y + cz * d->y + b->y * dz) + a->y * (b->x * cz + c->x * dz + bz * d->x) + b->y * cz * d->x + bz * c->x * d->y + b->x * c->y * dz ); return(result); } #define calc_ccw(a,b,c) \ ((a->x - c->x) * (b->y - c->y) - (b->x - c->x) * (a->y - c->y)) DOUBLE ccw(PNT2 *a,PNT2 *b,PNT2 *c) /* > 0.0 iff A, B, C form a counterclockwise oriented triangle */ { DOUBLE result; if ((a->x == b->x && a->y == b->y) || (a->x == c->x && a->y == c->y) || (b->x == c->x && b->y == c->y)) return(0.0); result = calc_ccw(a,b,c); if (fabs(result) < 1.0E-10) { /* we need a more stable result */ result += calc_ccw(a,c,b); result += calc_ccw(b,a,c); result += calc_ccw(b,c,a); result += calc_ccw(c,a,b); result += calc_ccw(c,b,a); result /= 6.0; } if (result == -0.0) result = 0.0; return(result); } #define LINE_EPS 1E-6 BOOLEAN approxonline(PNT2 *x,PNT2 *a,PNT2 *b) /* return TRUE if point in LINE_EPS region of line */ { DOUBLE len1,len2,len3,la,lb,lc,dist; VEC2 t; len1 = v2dist_2(*x,*a); len2 = v2dist_2(*x,*b); if (len1 < LINE_EPS * LINE_EPS || len2 < LINE_EPS * LINE_EPS) return(TRUE); v2sub(*b,*a,t); len3 = v2length_2(t); if (len1 > len3 || len2 > len3) return(FALSE); len3 = sqrt(len3); la = t.y / len3; lb = -t.x / len3; lc = -(la * a->x + lb * a->y); dist = la * x->x + lb * x->y + lc; if (fabs(dist) < LINE_EPS) return(TRUE); return(FALSE); } #define SWAP(a,b,t) { t = a; a = b; b = t; } /* use intersect_test before that proc to test if the lines really intersect */ BOOLEAN vintersect(PNT2 *p1,PNT2 *p2,PNT2 *p3,PNT2 *p4,PNT2 *inter) { DOUBLE a1,a2,b1,b2,c1,c2; DOUBLE denom,num; if (approxonline(p1,p3,p4)) { *inter = *p1; return(TRUE); } if (approxonline(p2,p3,p4)) { *inter = *p2; return(TRUE); } a1 = p2->y - p1->y; /* calc: a1 x + b1 y + c1 = 0 */ b1 = p1->x - p2->x; c1 = p2->x * p1->y - p1->x * p2->y; a2 = p4->y - p3->y; /* calc: a2 x + b2 y + c2 = 0 */ b2 = p3->x - p4->x; c2 = p4->x * p3->y - p3->x * p4->y; denom = a1 * b2 - a2 * b1; if (fabs(denom) < 1E-10) /* collinear :-( */ return(FALSE); num = b1 * c2 - b2 * c1; inter->x = num / denom; num = a2 * c1 - a1 * c2; inter->y = num / denom; return(TRUE); } /**************************************************************/ #define NEIGHBOURSIZE 100 static INT n_index; static NEIGHBOURS n_list[NEIGHBOURSIZE]; static VOID free_neighbours(VOID) { n_index = 0; } static NEIGHBOURS *alloc_neighbour_node(SITE_PTR site,DISCONTINUITY d) { NEIGHBOURS *n; if (n_index >= NEIGHBOURSIZE) fprintf(stderr,"No more neighbours\n"); n = &n_list[n_index]; n_index++; n->site = site; n->d = d; n->next = NULL; return(n); } /****************************************************************/ /* Edge storage management*/ /****************************************************************/ #define NYL -1 static VOID delete_all_edges(VOID) { _surf->next_edge = 0; _surf->avail_edge = NYL; _surf->n_edges = 0; } static EDGE_PTR alloc_edge(VOID) { EDGE_PTR ans; _surf->n_edges++; if (_surf->avail_edge == NYL) ans = _surf->next_edge, _surf->next_edge += 4; else ans = _surf->avail_edge, _surf->avail_edge = onext(_surf->avail_edge); return(ans); } static VOID free_edge(EDGE_PTR e) { e ^= e & 3; onext(e) = _surf->avail_edge; _surf->avail_edge = e; _surf->n_edges--; } /****************************************************************/ /* Quad-edge manipulation primitives */ /****************************************************************/ static EDGE_PTR makeedge(SITE_PTR origin,SITE_PTR destination,DISCONTINUITY d) { register EDGE_PTR temp, ans; assert(origin != destination); assert(X(origin) != X(destination) || Y(origin) != Y(destination)); temp = alloc_edge(); ans = temp; disco(ans) = d; onext(temp) = ans; orig(temp) = origin; onext(++temp) = ans + 3; onext(++temp) = ans + 2; orig(temp) = destination; onext(++temp) = ans + 1; Edge(origin) = ans; Edge(destination) = sym(ans); return(ans); } static VOID splice(EDGE_PTR a,EDGE_PTR b) { EDGE_PTR alpha, beta, temp; alpha = rot(onext(a)); beta = rot(onext(b)); temp = onext(alpha); onext(alpha) = onext(beta); onext(beta) = temp; temp = onext(a); onext(a) = onext(b); onext(b) = temp; Edge(orig(a)) = a; Edge(orig(b)) = b; } static VOID swapedge(EDGE_PTR e) { EDGE_PTR a,b,syme; a = oprev(e); syme = sym(e); b = oprev(syme); splice(e, a); splice(syme, b); splice(e, lnext(a)); splice(syme, lnext(b)); orig(e) = dest(a); Edge(orig(a)) = a; /* correct point references */ dest(e) = dest(b); Edge(orig(b)) = b; } static EDGE_PTR connect_left(EDGE_PTR a, EDGE_PTR b,DISCONTINUITY d) { register EDGE_PTR ans; ans = makeedge(dest(a), orig(b),d); splice(ans, lnext(a)); splice(sym(ans), b); return(ans); } static EDGE_PTR connect_right(EDGE_PTR a, EDGE_PTR b,DISCONTINUITY d) { register EDGE_PTR ans; ans = makeedge(dest(a), orig(b),d); splice(ans, sym(a)); splice(sym(ans), oprev(b)); return(ans); } static VOID deleteedge(EDGE_PTR e) /* disconnects e from the rest of the structure and destroys it. */ { if (e == _surf->Last_locate_edge || e == sym(_surf->Last_locate_edge)) _surf->Last_locate_edge = onext(e); Edge(orig(e)) = oprev(e); /* reset point references */ Edge(dest(e)) = lnext(e); splice(e, oprev(e)); splice(sym(e), oprev(sym(e))); free_edge(e); } static VOID splitedge(EDGE_PTR e,SITE_PTR site) { EDGE_PTR t,newe; t = lnext(e); splice(sym(e),t); Edge(orig(t)) = t; /* to make sure it's ok ! */ dest(e) = site; newe = connect_left(e,t,disco(e)); Edge(site) = newe; } /****************************************************************/ /* Quad-edge storage allocation */ /****************************************************************/ #define my_alloc(str_name, str_type, str_cnt) \ if (NULL == ((str_name) = (str_type *) \ malloc ((unsigned) ((str_cnt) * sizeof(str_type))))) \ fprintf(stderr," cannot malloc %s \n",#str_name) static VOID sef_alloc(INT n) { my_alloc(_surf->sa, struct SITE, n ); my_alloc(_surf->org, SITE_PTR, 12*n ); my_alloc(_surf->next, EDGE_PTR, 12*n ); my_alloc(_surf->ei, struct EDGE_INFO, 3*n ); } static VOID sef_free(VOID) { free((char *)_surf->sa); free((char *)_surf->org); free((char *)_surf->next); free((char *)_surf->ei); } static VOID sef_enlarge(INT additional) { INT n; TRIANG old_surf,*temp; old_surf = *_surf; n = _surf->alloced_sites; _surf->alloced_sites += additional; sef_alloc(_surf->alloced_sites); memcpy(_surf->sa,old_surf.sa,sizeof(struct SITE) * n); memcpy(_surf->org,old_surf.org,sizeof(SITE_PTR) * 12 * n); memcpy(_surf->next,old_surf.next,sizeof(EDGE_PTR) * 12 * n); memcpy(_surf->ei,old_surf.ei,sizeof(struct EDGE_INFO) * 3 * n); temp = _surf; _surf = &old_surf; sef_free(); _surf = temp; } /****************************************************************/ /* Site location */ /* find an edge where site lies left or on ! */ /****************************************************************/ #define SITECMP(vec,site) (fabs(vec.x - X(site)) < 1E-16 && \ fabs(vec.y - Y(site)) < 1E-16) static BOOLEAN v_locate ( VEC2 site, EDGE_PTR *edge,SITE_PTR *oldsite ) { register EDGE_PTR e; INT i; i = 0; e = _surf->Last_locate_edge; while (1) { i++; if (SITECMP(site,orig(e))) { *edge = e; *oldsite = orig(e); return(TRUE); } else if (SITECMP(site,dest(e))) { *edge = e; *oldsite = dest(e); return(TRUE); } else if (v_rightof(site,e)) e = sym(e); else if (v_leftoron(site,onext(e))) e = onext(e); else if (v_leftoron(site,dprev(e))) e = dprev(e); else break; } /* As Gordon said: Check it! */ assert(v_leftoron(site,e)); assert(v_leftof(site,lnext(e))); assert(v_leftof(site,lprev(e))); assert(v_rightoron(site,sym(e))); assert(v_rightof(site,dprev(e))); assert(v_rightof(site,onext(e))); assert(dest(lnext(e)) == orig(lprev(e))); assert(dest(onext(e)) == orig(dprev(e))); assert(dest(lnext(e)) == orig(dprev(e))); *edge = e; *oldsite = 0; return(FALSE); } /****************************************************************/ /* Incremental Site Insertion */ /* with a lot of ideas by Dani Lischinski */ /****************************************************************/ /* recursive edge flipping to the right of an edge */ static VOID fix_edge_right(EDGE_PTR *e) { EDGE_PTR f,g; if (disco_edge(*e)) return; f = oprev(*e); g = dnext(*e); if (incircle(&Site(dest(*e)),&Site(dest(onext(*e))),&Site(orig(*e)), &Site(dest(f)))) { swapedge(*e); fix_edge_right(&f); fix_edge_right(&g); } } /* triangulate anew the loop to the left of first */ /* ??? maybe this only works if all vertices lie to the left of last */ /* i.e. the edge preceeding first ??? */ static VOID triangulate_left(EDGE_PTR first) { EDGE_PTR last,a,b,ea,t1,t2; last = lprev(first); while (lnext(lnext(first)) != last) { /* still > triangle */ ea = lnext(first); t1 = first; while (ea != last) { t2 = lnext(ea); if (t2 == last && t1 == first) break; if (leftof(dest(ea),t1)) { if (t1 == first) { first = sym(connect_left(ea,t1,DINF)); t1 = first; } else t1 = sym(connect_left(ea,t1,DINF)); a = oprev(t1); b = dnext(t1); fix_edge_right(&a); fix_edge_right(&b); ea = t2; } else { t1 = ea; ea = t2; } } } a = lnext(last); b = lprev(last); fix_edge_right(&a); fix_edge_right(&b); fix_edge_right(&last); } /****************************************************************/ /* Incremental Delaunay Triangulation Procedure */ /****************************************************************/ /* this one does not flip unflippable edges ! */ static VOID incremental_delaunay(SITE_PTR site,EDGE_PTR edge) { SITE_PTR first; EDGE_PTR e,t,base; EDGE_PTR a,b,c,d; e = edge; /* site lies left or on edge ! */ if (onedge(site,e)) { /* we are on an existing edge */ a = oprev(e); b = dnext(e); c = lnext(e); d = lprev(e); splitedge(e,site); connect_left(e,lprev(e),DINF); connect_left(oprev(e),sym(e),DINF); fix_edge_right(&a); fix_edge_right(&b); fix_edge_right(&c); fix_edge_right(&d); return; } first = orig(e); base = makeedge(first,site,DINF); splice(base,e); do { base = connect_left(e,sym(base),DINF); e = oprev(base); } while (dest(e) != first); while (1) { t = oprev(e); if (flipable(e) && rightof(dest(t),e) && incircle(&origv(e),&destv(t),&destv(e),&Site(site))) { swapedge(e); e = oprev(e); continue; } else if (orig(e) == first) break; e = lprev(onext(e)); } } VOID insert_edge(TRIANG *surf, SITE_PTR a,SITE_PTR b, DISCONTINUITY discontinuity,SITE_PTR *new_sites,INT *n_new) { EDGE_PTR ea,eb,t,ne; SITE_PTR last,cross; VEC2 inter; BOOLEAN inters; if (n_new != NULL) *n_new = 0; /* at the beginning no new stuff */ _surf = surf; ea = Edge(a); /* get edge with a as orig */ eb = Edge(b); /* get edge with b as orig */ last = orig(eb); while (orig(ea) != last) { while (rightof(b,ea) || leftoron(b,onext(ea))) ea = onext(ea); assert(dest(onext(ea)) != last); /*assert(! online(dest(onext(ea)),a,b)); new online approx */ if (online(dest(ea),a,b)) { disco(ea) = discontinuity; ea = sym(ea); continue; } t = ea; while (1) { if (online(dest(lnext(t)),a,b)) { if (lnext(lnext(lnext(t))) == ea) { disco(lnext(lnext(t))) = discontinuity; ea = sym(lnext(t)); break; } else { ne = connect_left(lnext(t),ea,discontinuity); ea = sym(lnext(t)); triangulate_left(lnext(ne)); triangulate_left(oprev(ne)); break; } } else if (leftofline(dest(lnext(t)),a,b)) { /* left not on! */ if (flipable(lnext(t))) deleteedge(lnext(t)); else { /* 2 x-ing disco edges */ inters = vintersect(&origv(lnext(t)),&destv(lnext(t)), &Site(a),&Site(b),&inter); assert(inters); assert(inter.x != X(orig(lnext(t))) || inter.y != Y(orig(lnext(t)))); /* orig not on edge but cross == dest */ assert(inter.x != X(dest(lnext(t))) || inter.y != Y(dest(lnext(t)))); /* dest not on edge but cross = dest */ if (new_sites == NULL) fprintf(stderr,"can't create site for x-ing edges"); if (surf->n_sites == surf->alloced_sites) /* full */ sef_enlarge(SITEALLOC); cross = surf->n_sites++; Site(cross) = inter; Invis(cross) = 0; Info(cross) = NULL; /* has to be set by caller later on */ new_sites[(*n_new)++] = cross; splitedge(lnext(t),cross); ne = connect_left(lnext(t),ea,discontinuity); ea = sym(lnext(t)); triangulate_left(lnext(ne)); triangulate_left(oprev(ne)); break; } } else t = lnext(t); } } } /****************************************************************/ /* Top-level Delaunay Triangulation Procedure */ /****************************************************************/ VOID init_surface(TRIANG **surf,DOUBLE x0,DOUBLE y0,DOUBLE x1,DOUBLE y1) { DOUBLE lenx,leny; EDGE_PTR a,b,c; *surf = (TRIANG *)calloc(sizeof(TRIANG),1); _surf = *surf; _surf->alloced_sites = SITEALLOC; sef_alloc(_surf->alloced_sites); delete_all_edges(); _surf->bbox.min.x = x0; _surf->bbox.min.y = y0; _surf->bbox.max.x = x1; _surf->bbox.max.y = y1; _surf->n_edges = 0; /******************** Generate Basic Mesh **************************/ _surf->n_sites = 4; /* we generate a 10% bigger square */ lenx = (x1 - x0) / 10.0; leny = (y1 - y0) / 10.0; X(0) = x0 - lenx; Y(0) = y0 - leny; Invis(0) = 1; Info(0) = NULL; X(1) = x1 + lenx; Y(1) = y0 - leny; Invis(1) = 1; Info(1) = NULL; X(2) = x1 + lenx; Y(2) = y1 + leny; Invis(2) = 1; Info(2) = NULL; X(3) = x0 - lenx; Y(3) = y1 + leny; Invis(3) = 1; Info(3) = NULL; a = makeedge(0,3,DBDRY); b = makeedge(1,2,DBDRY); c = connect_left(sym(b),a,DBDRY); _surf->One_bndry_edge = sym(c); c = sym(connect_right(rprev(c),c,DINF)); c = connect_left(b,sym(c),DBDRY); _surf->Last_locate_edge = _surf->One_bndry_edge; /* init locate */ } VOID delete_surface(TRIANG *surf) { _surf = surf; sef_free(); } BOOLEAN insert_site(TRIANG *surf,DOUBLE x,DOUBLE y,SITE_PTR *site,VOIDPTR info) { EDGE_PTR e; VEC2 xy; SITE_PTR n; _surf = surf; if (x < _surf->bbox.min.x || x > _surf->bbox.max.x || y < _surf->bbox.min.y || y > _surf->bbox.max.y) { fprintf(stderr,"SITE outside! %g,%g [%g,%g - %g,%g]\n",x,y, _surf->bbox.min.x,_surf->bbox.min.y, _surf->bbox.max.x,_surf->bbox.max.y); return(FALSE); } xy.x = x; xy.y = y; if (v_locate(xy,&e,site)) { /* already there ! */ Info(*site) = info; return(FALSE); } if (surf->n_sites == surf->alloced_sites) /* we're full ! */ sef_enlarge(SITEALLOC); n = surf->n_sites++; Site(n) = xy; Invis(n) = 0; /* it's visible */ Info(n) = info; incremental_delaunay(n,e); *site = n; return(TRUE); } INT locate_point(TRIANG *surf,DOUBLE x,DOUBLE y,SITE_PTR sites[3]) { EDGE_PTR e; SITE_PTR site; VEC2 xy; _surf = surf; if (x < _surf->bbox.min.x || x > _surf->bbox.max.x || y < _surf->bbox.min.y || y > _surf->bbox.max.y) { fprintf(stderr,"POINT outside! %g,%g [%g,%g - %g,%g]\n",x,y, _surf->bbox.min.x,_surf->bbox.min.y, _surf->bbox.max.x,_surf->bbox.max.y); return(0); } xy.x = x; xy.y = y; if (v_locate(xy,&e,&site)) { /* already there */ sites[0] = site; return(1); } sites[0] = orig(e); sites[1] = dest(e); sites[2] = dest(lnext(e)); return(0); } VOID get_coords(TRIANG *surf,SITE_PTR site,DOUBLE *x,DOUBLE *y) { _surf = surf; *x = X(site); *y = Y(site); } VOIDPTR get_info(TRIANG *surf,SITE_PTR site) { _surf = surf; return(Info(site)); } VOID set_info(TRIANG *surf,SITE_PTR site,VOIDPTR info) { _surf = surf; Info(site) = info; } VOID get_neighbours(TRIANG *surf,SITE_PTR site,NEIGHBOURS **neigh) { EDGE_PTR e,t; NEIGHBOURS *n; _surf = surf; free_neighbours(); /* make room */ *neigh = NULL; e = Edge(site); t = e; do { if (! Invis(dest(e))) { n = alloc_neighbour_node(dest(e),disco(e)); n->next = *neigh; *neigh = n; } e = oprev(e); } while (t != e); } LONG for_all_sites(TRIANG *surf,VOID (*siteproc)(TRIANG *surf,SITE_PTR s)) { LONG cnt; SITE_PTR site; _surf = surf; cnt = 0; for (site = 0; site < surf->n_sites; site++) { if (Invis(site)) continue; if (siteproc != NULL) (*siteproc)(surf,site); cnt++; } return(cnt); } LONG for_all_edges(TRIANG *surf, VOID (*edgeproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,DISCONTINUITY d)) { LONG i,cnt; EDGE_PTR e; _surf = surf; if (_surf->avail_edge != -1) fprintf(stderr,"Aw, Shit not all edges are valid !\n"); e = 0; cnt = 0; for (i = 0; i < _surf->n_edges; i++, e += 4) { if (Invis(orig(e)) || Invis(dest(e))) continue; if (edgeproc != NULL) (*edgeproc)(surf,orig(e),dest(e),disco(e)); cnt++; } return(cnt); } LONG for_all_triangles(TRIANG *surf, VOID (*triproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3, DISCONTINUITY d1,DISCONTINUITY d2,DISCONTINUITY d3)) { LONG cnt; EDGE_PTR e,t; SITE_PTR site; _surf = surf; cnt = 0; for (site = 0; site < surf->n_sites; site++) { if (Invis(site)) continue; e = Edge(site); t = e; do { if (! Invis(dest(e)) && ! Invis(dest(onext(e))) && Y(site) < Y(dest(onext(e)))) { if (Y(site) < Y(dest(e)) || (Y(site) == Y(dest(e)) && X(site) < X(dest(e)))) { if (triproc != NULL) { if (rightof(dest(onext(e)),e)) printf("XX"); (*triproc)(surf,site,dest(e),dest(onext(e)), disco(e),disco(lnext(e)),disco(lprev(e))); } cnt++; } } e = oprev(e); } while (t != e); } return(cnt); } VOID flip_flipable_edges(TRIANG *surf,BOOLEAN (*testproc)(VOIDPTR s1,VOIDPTR s2, VOIDPTR s3,VOIDPTR s4)) { INT i; DOUBLE dist1,dist2; EDGE_PTR e; SITE_PTR s1,s2,s3,s4; _surf = surf; if (_surf->avail_edge != -1) fprintf(stderr,"Aw, Shit not all edges are valid !\n"); e = 0; for (i = 0; i < _surf->n_edges; i++, e += 4) { s1 = orig(e); s2 = dest(e); if (disco_edge(e) || Invis(s1) || Invis(s2)) continue; s3 = dest(oprev(e)); /* point on right */ s4 = dest(onext(e)); /* point on left */ dist1 = distcircle(&Site(s1),&Site(s3),&Site(s2),&Site(s4)); dist2 = distcircle(&Site(s3),&Site(s2),&Site(s4),&Site(s1)); if (dist1 >= 0.0 && dist2 >= 0.0) { /* both are inside */ if ((*testproc)(Info(s1),Info(s2),Info(s3),Info(s4))) swapedge(e); } } } e = 0; for (i = 0; i < _surf->n_edges; i++, e += 4) { s1 = orig(e); s2 = dest(e); if (disco_edge(e) || Invis(s1) || Invis(s2)) continue; s3 = dest(oprev(e)); /* point on right */ s4 = dest(onext(e)); /* point on left */ dist1 = distcircle(&Site(s1),&Site(s3),&Site(s2)dt.h000064400105260101400000000170410566533355600115240ustar00stuerzl00000000000000/**********************************************************************/ /* Delaunay-Triangulation Module */ /* header file */ /* */ /* (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /* Coauthorship of any publications using this code is claimed. */ /**********************************************************************/ #define VOID void /* VOID f() = procedure */ #define VOIDPTR void * #ifndef NULL #define NULL ((void *)0L) #endif #define PP(x) x #define Const const #define Extern extern #define Register register #define Signed signed #define Static static #define Unsigned unsigned #define Volatile volatile typedef Unsigned int WORD; /* the machine word */ typedef Unsigned char BOOLEAN; typedef Unsigned char BYTE; /* 8 bit unsigned */ typedef Signed char CHAR; /* 8 bit signed */ #if defined(__GNUC__) || ! defined(__STDC__) typedef char UCHAR; /* for Strings */ #else typedef Unsigned char UCHAR; /* for Strings */ #endif typedef Signed short INT; /* 16 bit signed */ typedef Unsigned short UINT; /* 16 bit unsigned */ typedef Signed long LONG; /* 32 bit signed */ typedef Unsigned long ULONG; /* 32 bit unsigned */ typedef double FLOAT; typedef double DOUBLE; #define FALSE ((BOOLEAN) 0) #define TRUE ((BOOLEAN) 1) typedef struct { FLOAT x; FLOAT y; } VEC2, PNT2; typedef struct { PNT2 min; PNT2 max; } BOX2; /******************************************************************************* For a description see the reference for the Quad-edge data structure: Leonidas Guibas and Jorge Stolfi, "Primitives for the manipulation of general subdivisions and the computations of Voronoi diagrams", ACM TOG 4,74-123 (1985) *******************************************************************************/ /**************************** Common data structures **************************/ typedef LONG SITE_PTR; typedef LONG EDGE_PTR; typedef LONG INFO_PTR; typedef enum DISCONTINUITY { DBDRY, DTEMP, D0, D1, D2, DINF } DISCONTINUITY; struct SITE { VEC2 vc; EDGE_PTR edge; BOOLEAN invisible; VOIDPTR info; }; struct EDGE_INFO { DISCONTINUITY disco; }; typedef struct TRIANG { LONG n_sites; LONG n_edges; LONG alloced_sites; struct SITE *sa ; EDGE_PTR *next ; SITE_PTR *org ; struct EDGE_INFO *ei ; EDGE_PTR One_bndry_edge; BOX2 bbox; EDGE_PTR Last_locate_edge; EDGE_PTR next_edge; EDGE_PTR avail_edge; } TRIANG; typedef struct NEIGHBOURS { struct NEIGHBOURS *next; SITE_PTR site; DISCONTINUITY d; } NEIGHBOURS; /******************************************************************************/ /********************** Macros for manipulation of quad-edges *****************/ /* Following edge ordering is used: ** ** ^ ^ \ / ** lnext(e) \ / rprev(e) dprev(e) \ / dnext(e) ** \ / V ** ^ | ** e | sym(e) | ** | V ** ^ / \ ** lprev(e) / \ rnext(e) onext(e) / \ oprev(e) ** / \ V V */ /* SITE_PTR s */ #define X(s) _surf->sa[s].vc.x #define Y(s) _surf->sa[s].vc.y #define Edge(s) _surf->sa[s].edge #define Invis(s) _surf->sa[s].invisible #define Site(s) _surf->sa[s].vc #define Info(s) _surf->sa[s].info /* EDGE_PTR a */ #define sym(a) ((a) ^ 2) #define rot(a) ( (((a) + 1) & 3) | ((a) & ~3) ) #define rotinv(a) ( (((a) + 3) & 3) | ((a) & ~3) ) #define onext(a) _surf->next[a] #define oprev(a) rot(onext(rot(a))) #define lnext(a) rot(onext(rotinv(a))) #define lprev(a) sym(onext(a)) #define rnext(a) rotinv(onext(rot(a))) #define rprev(a) onext(sym(a)) #define dnext(a) sym(onext(sym(a))) #define dprev(a) rotinv(onext(rotinv(a))) #define orig(a) _surf->org[a] #define dest(a) orig(sym(a)) #define left(a) orig(rotinv(a)) #define right(a) orig(rot(a)) #define origv(a) _surf->sa[orig(a)].vc #define destv(a) _surf->sa[dest(a)].vc #define leftv(a) _surf->fa[left(a)].vc #define rightv(a) _surf->fa[right(a)].vc #define info(a) _surf->ei[(a)>>2] #define disco(a) (info(a).disco) /******************************************************************************/ /********************************* MISC ***************************************/ #define flipable(e) (disco(e) > D2) #define disco_edge(e) (disco(e) <= D2) #define rightofline(X,a,b) (ccw(&Site(X),&Site(a),&Site(b))< 0.0) #define rightoronline(X,a,b) (ccw(&Site(X),&Site(a),&Site(b))<=0.0) #define leftofline(X,a,b) (ccw(&Site(X),&Site(a),&Site(b))> 0.0) #define leftoronline(X,a,b) (ccw(&Site(X),&Site(a),&Site(b))>=0.0) /*#define online(X,a,b) (ccw(&Site(X),&Site(a),&Site(b))==0.0)*/ #define online(X,a,b) approxonline(&Site(X),&Site(a),&Site(b)) #define rightof(X,e) (ccw(&Site(X),&origv(e),&destv(e))< 0.0) #define rightoron(X,e) (ccw(&Site(X),&origv(e),&destv(e))<=0.0) #define leftof(X,e) (ccw(&Site(X),&origv(e),&destv(e))> 0.0) #define leftoron(X,e) (ccw(&Site(X),&origv(e),&destv(e))>=0.0) /*#define onedge(X,e) (ccw(&Site(X),&origv(e),&destv(e))==0.0)*/ #define onedge(X,e) approxonline(&Site(X),&origv(e),&destv(e)) #define v_rightofline(X,a,b) (ccw(&X,&a,&b)< 0.0) #define v_rightoronline(X,a,b) (ccw(&X,&a,&b)<=0.0) #define v_leftofline(X,a,b) (ccw(&X,&a,&b)> 0.0) #define v_leftoronline(X,a,b) (ccw(&X,&a,&b)>=0.0) /*#define v_online(X,a,b) (ccw(&X,&a,&b)==0.0)*/ #define v_online(X,a,b) approxonline(&X,&a,&b) #define v_rightof(X,e) (ccw(&X,&origv(e),&destv(e))< 0.0) #define v_rightoron(X,e) (ccw(&X,&origv(e),&destv(e))<=0.0) #define v_leftof(X,e) (ccw(&X,&origv(e),&destv(e))> 0.0) #define v_leftoron(X,e) (ccw(&X,&origv(e),&destv(e))>=0.0) /*#define v_onedge(X,e) (ccw(&X,&origv(e),&destv(e))==0.0)*/ #define v_onedge(X,e) approxonline(&X,&origv(e),&destv(e)) /****************************** PROTOTYPES ***********************************/ VOID init_surface(TRIANG **surf,double x0,double y0,double x1,double y1); VOID delete_surface(TRIANG *surf); BOOLEAN insert_site(TRIANG *surf,double x,double y,SITE_PTR *site,VOIDPTR info); INT locate_point(TRIANG *surf,DOUBLE x,DOUBLE y,SITE_PTR sites[3]); VOID get_coords(TRIANG *surf,SITE_PTR site,double *x,double *y); VOIDPTR get_info(TRIANG *surf,SITE_PTR site); VOID set_info(TRIANG *surf,SITE_PTR site,VOIDPTR info); VOID get_neighbours(TRIANG *surf,SITE_PTR site,NEIGHBOURS **neigh); LONG for_all_sites(TRIANG *surf,VOID (*siteproc)(TRIANG *surf,SITE_PTR s)); LONG for_all_edges(TRIANG *surf, VOID (*edgeproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,DISCONTINUITY d)); LONG for_all_triangles(TRIANG *surf, VOID (*triproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3, DISCONTINUITY d1,DISCONTINUITY d2,DISCONTINUITY d3)); VOID flip_flipable_edges(TRIANG *surf,BOOLEAN (*testproc)(VOIDPTR s1, VOIDPTR s2,VOIDPTR s3,VOIDPTR s4)); VOID insert_edge(TRIANG *surf, SITE_PTR a,SITE_PTR b, DISCONTINUITY discontinuity,SITE_PTR *new_sites,INT *n_new); f, VOID (*edgeproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,DISCONTINUITY d)); LONG for_all_triangles(TRIANG *surf, VOID (*triproc)(TRIANG *surf,SITE_PTR s1,SITE_PTR s2,SITE_PTR s3, DISCONTINUITY d1,DISCONTINUITY d2,DISCONTINUITY d3)); VOID flip_flipable_edges(TRIANG *surf,BOOLEAN (*testproc)(VOIDPTR s1, VOIDPTR s2,VOIDPTR s3,VOIDPTR s4)); VOID insert_edge(TRIANG *surf, SITE_PTR a,SITE_PTR b, DISCONTINUITY discontinuity,Sgeom.c000064400105260101400000000101160566533352600120300ustar00stuerzl00000000000000/**********************************************************************/ /* geom.c */ /* */ /* (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /* Coauthorship of any publications using this code is claimed. */ /**********************************************************************/ #include #include #include #include #include #include "geom.h" /********************* clip a line to the surface ***************************/ /* right is > 0.0 */ #define calc_ccw(v1,v2,p) \ ((v2->u - v1->u) * (v1->v - p->v) - (v2->v - v1->v) * (v1->u - p->u)) double calc_side(TPoint2f *v1,TPoint2f *v2,TPoint2f *p) { double side; if ((v1->u == p->u && v1->v == p->v) || (v2->u == p->u && v2->v == p->v)) return(0.0); side = calc_ccw(v1,v2,p); if (fabs(side) < 1E-7) { /* need a more precise result */ side += calc_ccw(v1,p,v2); side += calc_ccw(v2,v1,p); side += calc_ccw(v2,p,v1); side += calc_ccw(p,v1,v2); side += calc_ccw(p,v2,v1); side /= 6.0; } if (side == -0.0) side = 0.0; return(side); } #define LINE_EPS 1E-14 int isonline(TPoint2f *x,TPoint2f *a,TPoint2f *b) /* return TRUE if point in LINE_EPS region of line */ { double len1,len2,len3,la,lb,lc,dist; TVector2f t; len1 = DistPnt2_2(*x,*a); len2 = DistPnt2_2(*x,*b); if (len1 < LINE_EPS * LINE_EPS || len2 < LINE_EPS * LINE_EPS) return(1); SubVector2(t,*a,*b); len3 = DotVector2(t,t); if (len1 > len3 || len2 > len3) return(0); len3 = sqrt(len3); la = t.v / len3; lb = -t.u / len3; lc = -(la * a->u + lb * a->v); dist = la * x->u + lb * x->v + lc; if (fabs(dist) < LINE_EPS) return(1); return(0); } int intersect_lines(TPoint2f *p1,TPoint2f *p2,TPoint2f *p3,TPoint2f *p4, TPoint2f *inter) { double a1,a2,b1,b2,c1,c2; double denom,num; double side1,side2; if (isonline(p1,p3,p4)) { *inter = *p1; return(1); } if (isonline(p2,p3,p4)) { *inter = *p2; return(1); } side1 = calc_side(p3,p4,p1); side2 = calc_side(p3,p4,p2); if (side1 > 0.0 && side2 > 0.0) return(0); if (side1 < 0.0 && side2 < 0.0) return(0); a1 = p2->v - p1->v; /* calc: a1 x + b1 y + c1 = 0 */ b1 = p1->u - p2->u; c1 = p2->u * p1->v - p1->u * p2->v; a2 = p4->v - p3->v; /* calc: a2 x + b2 y + c2 = 0 */ b2 = p3->u - p4->u; c2 = p4->u * p3->v - p3->u * p4->v; denom = a1 * b2 - a2 * b1; if (fabs(denom) < 1E-10) /* collinear :-( */ return(0); num = b1 * c2 - b2 * c1; inter->u = num / denom; num = a2 * c1 - a1 * c2; inter->v = num / denom; if (! isonline(inter,p1,p2)) printf("error 1"); if (! isonline(inter,p3,p4)) printf("error 2"); return(1); } int inside_poly2(TPoly2 *pp,TPoint2f *point2) { int i,mask; double side; TPoint2f *v1,*v2; mask = 0; v1 = &pp->vert[pp->n - 1]; for (i = 0; i < pp->n; i++) { v2 = &pp->vert[i]; side = calc_side(v1,v2,point2); if (side >= 0.0) /* right or online is outside */ mask |= 1 << i; v1 = v2; } return(mask); } int clip2poly2(TPoly2 *pp,TPoint2f *p1,TPoint2f *p2) { int i,mask1,mask2; TPoint2f *v1,*v2,inter; TVector2f temp; mask1 = inside_poly2(pp,p1); mask2 = inside_poly2(pp,p2); if (mask1 == 0 && mask2 == 0) /* both are inside */ return(1); v1 = &pp->vert[pp->n - 1]; for (i = 0; i < pp->n; i++) { v2 = &pp->vert[i]; if (mask1 & mask2) /* either one or both are outside */ return(0); /* on the same side */ if ((mask1 ^ mask2) & (1 << i)) { /* different sides */ if (! intersect_lines(p1,p2,v1,v2,&inter)) printf("Really ?"); if (mask1 & (1 << i)) { /* p1 is outside */ *p1 = inter; mask1 = inside_poly2(pp,p1); /* reclassify */ } else { /* (mask2 & (1 << i)) */ /* p2 is outside */ *p2 = inter; mask2 = inside_poly2(pp,p2); /* reclassify */ } } v1 = v2; } SubVector2(temp,*p2,*p1); if (DotVector2(temp,temp) < 1.0E-6) return(0); /* clipped to nothing */ return(1); } ) & (1 << i)) { /* different sides */ if (! intersect_lines(p1,p2,v1,v2,&inter)) printf("Really ?"); if (mask1 & (1 << i)) { /* p1 is outside */ *p1 = inter; mask1 = inside_poly2(pp,p1); /* reclassify */ } else { /* (mask2 & (1 << i)) */ /* p2 is outside */ *p2 = inter; mask2 = inside_poly2(pp,p2); /* reclassify */ } } v1 = v2; } SubVector2(temp,*p2,*p1); if (DotVector2(temgeom.h000064400105260101400000000464620566533353500120520ustar00stuerzl00000000000000/**********************************************************************/ /* geom.h */ /* */ /* (c) 1992-1994 by Wolfgang Stuerzlinger (wRZL) */ /* This code may be used only for non-commercial purposes ! */ /* Coauthorship of any publications using this code is claimed. */ /**********************************************************************/ #define kMaxPolyPoints 16 typedef struct { double u, v; } TPoint2f; typedef struct { float x, y, z; } TPoint3f; /* to save space */ typedef TPoint2f TVector2f; typedef TPoint3f TVector3f; typedef struct TLine { TVector2f normal; double np; } TLine; typedef struct TPlane { TVector3f normal; double np; } TPlane; typedef struct TPolygon { int n; char project; double ndotp; TVector3f normal; TPoint3f vert[kMaxPolyPoints]; } TPolygon; typedef struct TPoly2 { int n; TPoint2f vert[kMaxPolyPoints]; } TPoly2; #define SWAP(a,b,t) { t = a; a = b; b = t; } #ifndef M_PI #define M_PI 3.14159265358979 #endif #define InitPoint(p,x1,y1,z1) (p).x=x1, (p).y=y1, (p).z=z1 #define ZeroVector(a) (a).x = 0.0, (a).y = 0.0, (a).z = 0.0 #define PointEqual(a,b) ((a).x == (b).x && (a).y == (b).y && (a).z == (b).z) #define NegVector(a) (a).x = ((a).x) ? -(a).x : 0.0, \ (a).y = ((a).y) ? -(a).y : 0.0, \ (a).z = ((a).z) ? -(a).z : 0.0 #define AbsVector(c,a) (c).x=fabs((a).x),(c).y=fabs((a).y),(c).z=fabs((a).z) #define AddVector(c,a,b) (c).x=(a).x+(b).x, (c).y=(a).y+(b).y, (c).z=(a).z+(b).z #define SubVector(c,a,b) (c).x=(a).x-(b).x, (c).y=(a).y-(b).y, (c).z=(a).z-(b).z #define CrossVector(c,a,b) (c).x = (a).y*(b).z - (a).z*(b).y, \ (c).y = (a).z*(b).x - (a).x*(b).z, \ (c).z = (a).x*(b).y - (a).y*(b).x #define DotVector(a,b) ((a).x*(b).x + (a).y*(b).y + (a).z*(b).z) #define ScaleVector(c,s) (c).x*=(s), (c).y*=(s), (c).z*=(s) #define NormalizeVector(n,a) ((n)=sqrt(DotVector(a,a)), \ (n)?((a).x/=n, (a).y/=n, (a).z/=n):0.0) #define DistPnt(a,b) sqrt(((b).x - (a).x) * ((b).x - (a).x) + \ ((b).y - (a).y) * ((b).y - (a).y) + ((b).z - (a).z) * ((b).z - (a).z)) #define LenVector(a) sqrt(DotVector(a,a)) #define AvgVector(c,a,b) (c).x=((a).x+(b).x) * 0.5, (c).y=((a).y+(b).y) * 0.5, \ (c).z=((a).z+(b).z) * 0.5 #define VolVector(a,b,c) \ ((a).x*(b).y*(c).z + (a).y*(b).z*(c).x + (a).z*(b).x*(c).y - \ (a).z*(b).y*(c).x - (a).x*(b).z*(c).y - (a).y*(b).x*(c).z) #define DistPt2Plane(p,n,np) (DotVector(n,p) - (np)) #define Inplane(p,n,np) (fabs(DistPt2Plane(p,n,np)) < 1E-14) #define InsideBbox(mini,maxi,p) ((p).x >= (mini).x && (p).x <= (maxi).x && \ (p).y >= (mini).y && (p).y <= (maxi).y && \ (p).z >= (mini).z && (p).z <= (maxi).z) #define MakeBbox(mini,maxi,point) { \ if ((point).x < (mini).x) (mini).x = (point).x; \ else if ((point).x > (maxi).x) (maxi).x = (point).x; \ if ((point).y < (mini).y) (mini).y = (point).y; \ else if ((point).y > (maxi).y) (maxi).y = (point).y; \ if ((point).z < (mini).z) (mini).z = (point).z; \ else if ((point).z > (maxi).z) (maxi).z = (point).z; } #define JoinBbox(min1,max1,min2,max2) { \ if ((min2).x < (min1).x) (min1).x = (min2).x; \ if ((min2).y < (min1).y) (min1).y = (min2).y; \ if ((min2).z < (min1).z) (min1).z = (min2).z; \ if ((max2).x > (max1).x) (max1).x = (max2).x; \ if ((max2).y > (max1).y) (max1).y = (max2).y; \ if ((max2).z > (max1).z) (max1).z = (max2).z; } #define BboxOutside(min1,max1,min2,max2) \ ((min1).x > (max2).x || (min1).y > (max2).y || (min1).z > (max2).z || \ (max1).x < (min2).x || (max1).y < (min2).y || (max1).z < (min2).z) #define FindProject(norm,project) { \ TVector3f _n; \ AbsVector(_n,norm); \ if (_n.x > _n.y && _n.x > _n.z) \ project = ((norm).x >= 0.0) ? 0 : 3; \ else if (_n.y > _n.z) \ project = ((norm).y >= 0.0) ? 4 : 1; \ else \ project = ((norm).z >= 0.0) ? 2 : 5; } #define Project2d(project,d3,d2) switch (project) { \ case 0: (d2).u = (d3).y; (d2).v = (d3).z; break; \ case 1: (d2).u = (d3).x; (d2).v = (d3).z; break; \ case 2: (d2).u = (d3).x; (d2).v = (d3).y; break; \ case 3: (d2).u = -(d3).y; (d2).v = (d3).z; break; \ case 4: (d2).u = -(d3).x; (d2).v = (d3).z; break; \ case 5: (d2).u = -(d3).x; (d2).v = (d3).y; break; } #define Project3d(surf,d2,d3) switch ((surf).project) { \ case 0: (d3).y = (d2).u; (d3).z = (d2).v; \ (d3).x = ((surf).ndotp - (d3).y * (surf).normal.y - \ (d3).z * (surf).normal.z) / (surf).normal.x; break; \ case 1: (d3).x = (d2).u; (d3).z = (d2).v; \ (d3).y = ((surf).ndotp - (d3).x * (surf).normal.x - \ (d3).z * (surf).normal.z) / (surf).normal.y; break; \ case 2: (d3).x = (d2).u; (d3).y = (d2).v; \ (d3).z = ((surf).ndotp - (d3).x * (surf).normal.x - \ (d3).y * (surf).normal.y) / (surf).normal.z; break; \ case 3: (d3).y = -(d2).u; (d3).z = (d2).v; \ (d3).x = ((surf).ndotp - (d3).y * (surf).normal.y - \ (d3).z * (surf).normal.z) / (surf).normal.x; break; \ case 4: (d3).x = -(d2).u; (d3).z = (d2).v; \ (d3).y = ((surf).ndotp - (d3).x * (surf).normal.x - \ (d3).z * (surf).normal.z) / (surf).normal.y; break; \ case 5: (d3).x = -(d2).u; (d3).y = (d2).v; \ (d3).z = ((surf).ndotp - (d3).x * (surf).normal.x - \ (d3).y * (surf).normal.y) / (surf).normal.z; break; } #define InitPoint2(p,x,y) (p).u=x, (p).v=y #define PointEqual2(a,b) ((a).u == (b).u && (a).v == (b).v) #define PointNear2(a,b,eps) (fabs((a).u - (b).u) < (eps) && \ fabs((a).v - (b).v) < (eps)) #define NegVector2(a) (a).u = ((a).u) ? -(a).u : 0.0, \ (a).v = ((a).v) ? -(a).v : 0.0 #define AbsVector2(c,a) (c).u=fabs((a).u),(c).v=fabs((a).v) #define AddVector2(c,a,b) (c).u=(a).u+(b).u, (c).v=(a).v+(b).v #define SubVector2(c,a,b) (c).u=(a).u-(b).u, (c).v=(a).v-(b).v #define ScaleVector2(c,s) (c).u*=(s), (c).v*=(s) #define AvgVector2(c,a,b) (c).u=((a).u+(b).u) * 0.5, (c).v=((a).v+(b).v) * 0.5 #define DotVector2(a,b) ((a).u*(b).u + (a).v*(b).v) #define DistPnt2_2(a,b) sqrt(((b).u - (a).u) * ((b).u - (a).u) + \ ((b).v - (a).v) * ((b).v - (a).v)) #define DistPnt2(a,b) sqrt(DistPnt2_2(a,b)) #define LenVector2(a) sqrt(DotVector2(a,a)) #define CrossVector2(a,b) ((a).u*(b).v - (a).v*(b).u) #define NormalizeVector2(n,a) ((n)=sqrt(DotVector2(a,a)), \ (n)?((a).u/=n, (a).v/=n):0.0) #define TurnVector2Left2(c,a) (c).u = ((a).v)?-(a).v:0.0, (c).v = (a).u #define TurnVector2Right2(c,a) (c).u = (a).v, (c).v = ((a).u)?-(a).u:0.0 #define DistPt2Line(p,n,np) (DotVector2(n,p) - (np)) #define RightofPoints2(v1,v2,p) (calc_side(v1,v2,p) > 0.0) #define OutsideBbox2(mini,maxi,p) ((p).u < (mini).u || (p).u > (maxi).u || \ (p).v < (mini).v || (p).v > (maxi).v) #define InsideBbox2(mini,maxi,p) ((p).u >= (mini).u && (p).u <= (maxi).u && \ (p).v >= (mini).v && (p).v <= (maxi).v) #define BboxOutside2(min1,max1,min2,max2) \ ((min1).u > (max2).u || (min1).v > (max2).v || \ (max1).u < (min2).u || (max1).v < (min2).v) #define MakeBbox2(mini,maxi,point) { \ if ((point).u < (mini).u) (mini).u = (point).u; \ else if ((point).u > (maxi).u) (maxi).u = (point).u; \ if ((point).v < (mini).v) (mini).v = (point).v; \ else if ((point).v > (maxi).v) (maxi).v = (point).v; } #define Projectd1(project,d2) ((project == 0) ? (d2).v : (d2).u) #define FindProject2(d2) ((fabs((d2).u) > fabs((d2).v)) ? 0 : 1) #define Projectd2(project,normal,ndotp,d2,d) if (project == 0) { \ (d2).v = d; (d2).u = (ndotp - (d2).v * (normal).v) / (normal).u; } \ else { (d2).u = d; (d2).v = (ndotp - (d2).u * (normal).u) / (normal).v; } #define sign(x) ((x > 0) ? 1 : ((x < 0) ? -1 : 0)) #define v3pmulm(p1,m,p) \ { \ p.x = (p1).x * m[0][0] + (p1).y * m[1][0] + \ (p1).z * m[2][0] + m[3][0]; \ p.y = (p1).x * m[0][1] + (p1).y * m[1][1] + \ (p1).z * m[2][1] + m[3][1]; \ p.z = (p1).x * m[0][2] + (p1).y * m[1][2] + \ (p1).z * m[2][2] + m[3][2]; \ } #define v4pmulm(p1,m,p,w) \ { \ p.x = p1.x * m[0][0] + p1.y * m[1][0] + \ p1.z * m[2][0] + m[3][0]; \ p.y = p1.x * m[0][1] + p1.y * m[1][1] + \ p1.z * m[2][1] + m[3][1]; \ p.z = p1.x * m[0][2] + p1.y * m[1][2] + \ p1.z * m[2][2] + m[3][2]; \ w = p1.x * m[0][3] + p1.y * m[1][3] + \ p1.z * m[2][3] + m[3][3]; \ } #define v3vmulm(v1,m,v) \ { \ v.x = v1.x * m[0][0] + v1.y * m[1][0] + \ v1.z * m[2][0]; \ v.y = v1.x * m[0][1] + v1.y * m[1][1] + \ v1.z * m[2][1]; \ v.z = v1.x * m[0][2] + v1.y * m[1][2] + \ v1.z * m[2][2]; \ } #define m3trans(xt,yt,zt,one,two) \ { \ one[3][0] += xt; \ one[3][1] += yt; \ one[3][2] += zt; \ two[3][0] -= two[0][0] * xt + two[1][0] * yt + \ two[2][0] * zt; \ two[3][1] -= two[0][1] * xt + two[1][1] * yt + \ two[2][1] * zt; \ two[3][2] -= two[0][2] * xt + two[1][2] * yt + \ two[2][2] * zt; \ } #define m3rotx(alpha,one,two) \ { \ double _t; \ double _s = sin(alpha); \ double _c = cos(alpha); \ \ _t = one[0][1]; \ one[0][1] = _t * _c - one[0][2] * _s; \ one[0][2] = _t * _s + one[0][2] * _c; \ _t = one[1][1]; \ one[1][1] = _t * _c - one[1][2] * _s; \ one[1][2] = _t * _s + one[1][2] * _c; \ _t = one[2][1]; \ one[2][1] = _t * _c - one[2][2] * _s; \ one[2][2] = _t * _s + one[2][2] * _c; \ _t = one[3][1]; \ one[3][1] = _t * _c - one[3][2] * _s; \ one[3][2] = _t * _s + one[3][2] * _c; \ _t = two[1][0]; \ two[1][0] = _t * _c - two[2][0] * _s; \ two[2][0] = _t * _s + two[2][0] * _c; \ _t = two[1][1]; \ two[1][1] = _t * _c - two[2][1] * _s; \ two[2][1] = _t * _s + two[2][1] * _c; \ _t = two[1][2]; \ two[1][2] = _t * _c - two[2][2] * _s; \ two[2][2] = _t * _s + two[2][2] * _c; \ } #define m3roty(alpha,one,two) \ { \ double _t; \ double _s = sin(alpha); \ double _c = cos(alpha); \ \ _t = one[0][0]; \ one[0][0] = _t * _c + one[0][2] * _s; \ one[0][2] = -_t * _s + one[0][2] * _c; \ _t = one[1][0]; \ one[1][0] = _t * _c + one[1][2] * _s; \ one[1][2] = -_t * _s + one[1][2] * _c; \ _t = one[2][0]; \ one[2][0] = _t * _c + one[2][2] * _s; \ one[2][2] = -_t * _s + one[2][2] * _c; \ _t = one[3][0]; \ one[3][0] = _t * _c + one[3][2] * _s; \ one[3][2] = -_t * _s + one[3][2] * _c; \ _t = two[0][0]; \ two[0][0] = _t * _c + two[2][0] * _s; \ two[2][0] = -_t * _s + two[2][0] * _c; \ _t = two[0][1]; \ two[0][1] = _t * _c + two[2][1] * _s; \ two[2][1] = -_t * _s + two[2][1] * _c; \ _t = two[0][2]; \ two[0][2] = _t * _c + two[2][2] * _s; \ two[2][2] = -_t * _s + two[2][2] * _c; \ } #define m3rotz(alpha,one,two) \ { \ double _t; \ double _s = sin(alpha); \ double _c = cos(alpha); \ \ _t = one[0][0]; \ one[0][0] = _t * _c - one[0][1] * _s; \ one[0][1] = _t * _s + one[0][1] * _c; \ _t = one[1][0]; \ one[1][0] = _t * _c - one[1][1] * _s; \ one[1][1] = _t * _s + one[1][1] * _c; \ _t = one[2][0]; \ one[2][0] = _t * _c - one[2][1] * _s; \ one[2][1] = _t * _s + one[2][1] * _c; \ _t = one[3][0]; \ one[3][0] = _t * _c - one[3][1] * _s; \ one[3][1] = _t * _s + one[3][1] * _c; \ _t = two[0][0]; \ two[0][0] = _t * _c - two[1][0] * _s; \ two[1][0] = _t * _s + two[1][0] * _c; \ _t = two[0][1]; \ two[0][1] = _t * _c - two[1][1] * _s; \ two[1][1] = _t * _s + two[1][1] * _c; \ _t = two[0][2]; \ two[0][2] = _t * _c - two[1][2] * _s; \ two[1][2] = _t * _s + two[1][2] * _c; \ } #define m3scale(xs,ys,zs,one,two) \ { \ double _x = 1.0 / (xs); \ double _y = 1.0 / (ys); \ double _z = 1.0 / (zs); \ \ one[0][0] *= xs; \ one[0][1] *= ys; \ one[0][2] *= zs; \ one[1][0] *= xs; \ one[1][1] *= ys; \ one[1][2] *= zs; \ one[2][0] *= xs; \ one[2][1] *= ys; \ one[2][2] *= zs; \ one[3][0] *= xs; \ one[3][1] *= ys; \ one[3][2] *= zs; \ two[0][0] *= _x; \ two[0][1] *= _x; \ two[0][2] *= _x; \ two[1][0] *= _y; \ two[1][1] *= _y; \ two[1][2] *= _y; \ two[2][0] *= _z; \ two[2][1] *= _z; \ two[2][2] *= _z; \ } #ifdef NEVER #define m3mmulm(m1,m2,m)\ {\ m[0][0] =m1[0][0] * m2[0][0] + m1[0][1] * m2[1][0] +\ m1[0][2] * m2[2][0];\ m[0][1] =m1[0][0] * m2[0][1] + m1[0][1] * m2[1][1] +\ m1[0][2] * m2[2][1];\ m[0][2] =m1[0][0] * m2[0][2] + m1[0][1] * m2[1][2] +\ m1[0][2] * m2[2][2];\ m[1][0] =m1[1][0] * m2[0][0] + m1[1][1] * m2[1][0] +\ m1[1][2] * m2[2][0];\ m[1][1] =m1[1][0] * m2[0][1] + m1[1][1] * m2[1][1] +\ m1[1][2] * m2[2][1];\ m[1][2] =m1[1][0] * m2[0][2] + m1[1][1] * m2[1][2] +\ m1[1][2] * m2[2][2];\ m[2][0] =m1[2][0] * m2[0][0] + m1[2][1] * m2[1][0] +\ m1[2][2] * m2[2][0];\ m[2][1] =m1[2][0] * m2[0][1] + m1[2][1] * m2[1][1] +\ m1[2][2] * m2[2][1];\ m[2][2] =m1[2][0] * m2[0][2] + m1[2][1] * m2[1][2] +\ m1[2][2] * m2[2][2];\ m[3][0] =m1[3][0] * m2[0][0] + m1[3][1] * m2[1][0] +\ m1[3][2] * m2[2][0] + m2[3][0];\ m[3][1] =m1[3][0] * m2[0][1] + m1[3][1] * m2[1][1] +\ m1[3][2] * m2[2][1] + m2[3][1];\ m[3][2] =m1[3][0] * m2[0][2] + m1[3][1] * m2[1][2] +\ m1[3][2] * m2[2][2] + m2[3][2];\ } #endif #define m3unit(m)\ { \ m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; \ m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; \ m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; \ m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; \ } #define m3copy(m,m1)\ { \ m1[0][0] = m[0][0]; m1[0][1] = m[0][1]; m1[0][2] = m[0][2]; \ m1[1][0] = m[1][0]; m1[1][1] = m[1][1]; m1[1][2] = m[1][2]; \ m1[2][0] = m[2][0]; m1[3][1] = m[3][1]; m1[2][2] = m[2][2]; \ m1[3][0] = m[3][0]; m1[3][1] = m[3][1]; m1[3][2] = m[3][2]; \ } #define m4unit(m)\ { \ m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; m[0][3] = 0.0; \ m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; m[1][3] = 0.0; \ m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; m[2][3] = 1.0; \ m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; m[3][3] = 0.0; \ } #define m4copy(m,m1)\ { \ m1[0][0] = m[0][0]; m1[0][1] = m[0][1]; \ m1[0][2] = m[0][2]; m1[0][3] = m[0][3]; \ m1[1][0] = m[1][0]; m1[1][1] = m[1][1]; \ m1[1][2] = m[1][2]; m1[1][3] = m[1][3]; \ m1[2][0] = m[2][0]; m1[3][1] = m[3][1]; \ m1[2][2] = m[2][2]; m1[2][3] = m[2][3]; \ m1[3][0] = m[3][0]; m1[3][1] = m[3][1]; \ m1[3][2] = m[3][2]; m1[3][3] = m[3][3]; \ } typedef double mat3[4][3]; typedef double mat4[4][4]; /******************************** prototypes ******************************/ double calc_side(TPoint2f *v1,TPoint2f *v2,TPoint2f *p2); int isonline(TPoint2f *x,TPoint2f *a,TPoint2f *b); int inside_poly2(TPoly2 *ep,TPoint2f *point2); int clip2poly2(TPoly2 *ep,TPoint2f *p1,TPoint2f *p2); m[2][0]; m1[3][1] = m[3][1]; \ m1[2][2] = m[2][2]; m1[2][3] = m[2][3]; \ m1[3][0] = m[3][0]; m1[3][1] = m[3][1]; \ m1[3][2] = m[3][2]; m1[3][3] = m[3][3]; \ } typedef double mat3[4][3]; typedef dou \ one[1][1] = _t * _c - one[1][2] * _s; \ one[1][2] = _t * _s + one[1][2] * _c; \ _t = one[2][1]; \ one[2][1] = _t * _c - one[2][2] * _s; \ one[2][2] = _t * _s + one[2][2] * _c; \ _t = one[3][1]; \ one[3][1] = _t * _c - one[3][2] * _s; \ one[3][2] = _t * _s + one[3][2] * _c; \ _t = two[1][0]; \ two[1][0] = _t * _c - two[2][0] * _s; \ two[2][0] = _t * _s + two[2][0] * _c; \ _t = two[1][1]; \ two[1][1] = _t * _c - two[2][1] * _s; \ two[2][1] = _t * _s + two[2][1] * _c; \ _t = two[1][2]; \ two[1][2] = _t * _c - two[2][2] * _s; \ two[2][2] = _t * _s + two[2][2] * _c; \ } #define m3roty(alpha,one,two) \ { \ double _t; \ double _s = sin(alpha); \ double _c = cos(alpha); \ \ _t = one[0][0]; \ one[0][0] = _t * _c + one[0][2] * _s; \ one[0][2] = -_t * _s + one[0][2] * _c; \ _t = one[1][0]; \ one[1][0] = _t * _c + one[1][2] * _s; \ one[1][2] = -_t * _s + one[1][2] * _c; \ _t = one[2][0]; \ one[2][0] = _t * _c + one[2][2] * _s; \ one[2][2] = -_t * _s + one[2][2] * _c; \ _t = one[3][0]; \ one[3][0] = _t * _c + one[3][2] * _s; \ one[3][2] = -_t * _s + one[3][2] * _c; \ _t = two[0][0]; \ two[0][0] = _t * _c + two[2][0] * _s; \ two[2][0] = -_t * _s + two[2][0] * _c; \ _t = two[0][1]; \ two[0][1] = _t * _c + two[2][1] * _s; \ two[2][1] = -_t * _s + two[2][1] * _c; \ _t = two[0][2]; \ two[0][2]