Path: utzoo!attcan!uunet!wuarchive!cs.utexas.edu!news-server.csri.toronto.edu!csri.toronto.edu!corkum From: corkum@csri.toronto.edu (Brent Thomas Corkum) Newsgroups: comp.graphics Subject: point in a volume: PART III - the final chapter Message-ID: <1990Oct3.121706.11932@jarvis.csri.toronto.edu> Date: 3 Oct 90 16:17:06 GMT References: <1990Oct3.121330.11851@jarvis.csri.toronto.edu> Organization: CSRI, University of Toronto Lines: 650 In article <1990Oct3.121330.11851@jarvis.csri.toronto.edu> corkum@csri.toronto.edu (Brent Thomas Corkum) writes: > >Due to popular demand I am posting my generalised point in a volume (polytope) >tester. It's written in C, and handles concave,convex polygons making >up a concave or convex volume. The polygons may have any number of >vertices. I don't really like posting it but I don't have, and don't care >to have, anonymous ftp capability, so if anyone wants to donate some space >to make this available, mail me. > > >The following two postings contain information and source code for my >point inside a volume tester. The first file contains the readme file >that explains how to compile and run the test program. The test program >illustrates the use of the point inside a volume tester, and gives an example. > >Feel free to distribute this code, I place it in the public domain with >the only criteria for using it being proper acknowledgement. You may >use it in commercial software free of charge with only the above >restriction. So have fun. > >Brent Corkum >corkum@boulder.civ.toronto.edu (128.100.14.11) or >corkum@csri.toronto.edu #include #include #include #define TRUE 1 #define FALSE 0 /* This program will determine if point (x,y,z) is inside a closed polytope defined by the list "polygons" which contains "numpolys" concave or convex polygons. The main subroutine of the program reads in a closed polytope from a .geo file and then prompts the user for a point to check. The Insidepolytope subroutine is then called which will return TRUE if the point is inside the polytope. J. Andrew Wyllie and Brent Corkum Data Visualization Laboratory Dept Of Civil Engineering University of Toronto Canada September 1990 */ /* The following structures are used to keep track of nodes and elements */ /* The node structure holds the x,y and z coordinates of the node */ /* The element structur will hold the number of nodes and a list of the nodes included in the structure */ struct Nodes{ float x; float y; float z; }*node; struct Elements{ int numnodes; int *nodes; }*element; int numpolys; float DotProduct(); /* The function main is used to read in a polytope and prompt for a point to be checked */ void main(void) { register int i,j,k; int numnodes,numverts,vert,check; float x,y,z,xtemp,ytemp,ztemp; char fname[50]; FILE *in; printf("enter .geo file name\n"); gets(fname); /* read in a polytope from a .geo file */ in=fopen(fname,"rt"); if(!in){ printf("file cannot be opened\n"); exit(1); } printf("file open\n"); /* read in the number of nodes and the number of elements */ if(!fscanf(in,"%d%d%*d\n",&numnodes,&numpolys))exit(1); /* allocate space for the arrays of node and element structures */ node = (struct Nodes *)malloc(numnodes*sizeof(struct Nodes)); element = (struct Elements *)malloc(numpolys*sizeof(struct Elements)); if(!node || !element){ printf("memory allocation error , abort\n"); exit(1); } printf("reading nodes\n"); for(i=0;i, abort\n"); exit(1); } for(k=0;k node[element[i].nodes[j]].x ? node[element[i].nodes[j]].x : xmin; xmax = xmax < node[element[i].nodes[j]].x ? node[element[i].nodes[j]].x : xmax; ymin = ymin > node[element[i].nodes[j]].y ? node[element[i].nodes[j]].y : ymin; ymax = ymax < node[element[i].nodes[j]].y ? node[element[i].nodes[j]].y : ymax; zmin = zmin > node[element[i].nodes[j]].z ? node[element[i].nodes[j]].z : zmin; zmax = zmax < node[element[i].nodes[j]].z ? node[element[i].nodes[j]].z : zmax; } } /* check to see if point is inside bounding brick */ if((x > xmax)||(x < xmin)|| (y > ymax)||(y < ymin)|| (z > zmax)||(z < zmin)) return(0); /* point outside bounding brick */ printf("inside bounding box\n"); /* If the point is inside the bounding brick */ /* Generate a random ray from point (x,y,z) */ xdir = (1.0*rand())/(32767*1.0); dir = (1.0*rand())/(32767*1.0); if(dir<0.5)xdir= -xdir; ydir = (1.0*rand())/(32767*1.0); dir = (1.0*rand())/(32767*1.0); if(dir<0.5)ydir= -ydir; zdir = (1.0*rand())/(32767*1.0); dir = (1.0*rand())/(32767*1.0); if(dir<0.5)zdir= -zdir; if(xdir==0.0 && ydir ==0.0 && zdir==0.0){ xdir=1.0;ydir=0.0;zdir=0.0; } Normalize(&xdir,&ydir,&zdir); /* Now find out how many polygons the random ray intersects */ for(k=0;k=0){ /* ray intersects embedding plane */ /* now find intersection point */ xint=x+xdir*t; yint=y+ydir*t; zint=z+zdir*t; /* calculate rotation transformation matrix to x-y plane */ Vector_rot(nx,ny,nz,0.0,0.0,1.0,rot); /* now transform polygon to x-y plane */ Transformpolygon(pl,numverts,rot); /* now transform intersection point to the x-y plane */ Transformpoint(&xint,&yint,&zint,rot); /* map the 3-d to the 2-d array */ for(l=0;ly1){ xlast=x1;x1=x2;x2=xlast; ylast=y1;y1=y2;y2=ylast; } if(y>y2&&yx)&&(x2x))){ ++intersect; } } else{ flag=TRUE; j=i; while(flag){ k=j==numpoints-1?0:j+1; y4=data[k*2+3]; if(y4!=y){ if(((y1y))||((y1>y)&&(y>y4)))++intersect; flag=FALSE; } else ++j; } } } } } if(intersect%2!=0){ return(1); } else return(0); } float DotProduct(u1,u2,u3,v1,v2,v3) float u1,u2,u3,v1,v2,v3; { float dp; dp = u1*v1 + u2*v2 + u3*v3; return(dp); } Parallel_Normal_Vectors(u1,u2,u3,v1,v2,v3) float u1,u2,u3,v1,v2,v3; { float eps,a,cp1,cp2,cp3; eps = 1e-4; cp1 = (u2*v3 - u3*v2); cp2 = (u3*v1 - u1*v3); cp3 = (u1*v2 - u2*v1); a = cp1*cp1 + cp2*cp2 + cp3*cp3; if(alenv)eps = 1e-5*lenu; else eps = 1e-5*lenv; dx = u1 - v1; dx = dx<0.0 ? -dx : dx; dy = u2 - v2; dy = dy<0.0 ? -dy : dy; dz = u3 - v3; dz = dz<0.0 ? -dz : dz; if(dx eps){ /* if this is not true a = sin(180) */ colinear = 0; /* vectors are not colinear */ /* scale u X v so that its length = angle between u and v */ drot[0] *= asin(a)/a; drot[1] *= asin(a)/a; drot[2] *= asin(a)/a; /* normalize this vector */ a = sqrt(drot[0] * drot[0] + drot[1] * drot[1] + drot[2] * drot[2]); drot[0] /= a; drot[1] /= a; drot[2] /= a; } else { colinear = 1; a = 0.0; } /* if dot product of u and v < 0 then subtract a from 180 degrees (pi) */ dp = u1*v1 + u2*v2 + u3*v3; if(dp<0.0) a = pi - a; /* if u and v are colinear, must set the arbitrary rotation vector drot */ if(colinear){ if(!Parallel_Normal_Vectors(u1,u2,u3,0.0,1.0,0.0)){ tri[0]=u1;tri[1]=u2;tri[2]=u3; tri[3]=v1;tri[4]=v2;tri[5]=v3; tri[6]=0.0;tri[7]=1.0;tri[8]=0.0; Plane_normal(tri,3,&drot[0],&drot[1],&drot[2]); } else{ tri[0]=u1;tri[1]=u2;tri[2]=u3; tri[3]=v1;tri[4]=v2;tri[5]=v3; tri[6]=1.0;tri[7]=0.0;tri[8]=0.0; Plane_normal(tri,3,&drot[0],&drot[1],&drot[2]); } } /* calculate transformation matrix */ s = sin(a); c = cos(a); t = 1.0 - c; rotation[0][0] = t * drot[0] * drot[0] + c; rotation[0][1] = t * drot[0] * drot[1] + s * drot[2]; rotation[0][2] = t * drot[0] * drot[2] - s * drot[1]; rotation[0][3] = 0.0; rotation[1][0] = t * drot[0] * drot[1] - s * drot[2]; rotation[1][1] = t * drot[1] * drot[1] + c; rotation[1][2] = t * drot[1] * drot[2] + s * drot[0]; rotation[1][3] = 0.0; rotation[2][0] = t * drot[0] * drot[2] + s * drot[1]; rotation[2][1] = t * drot[1] * drot[2] - s * drot[0]; rotation[2][2] = t * drot[2] * drot[2] + c; rotation[2][3] = 0.0; rotation[3][0] = 0.0; rotation[3][1] = 0.0; rotation[3][2] = 0.0; rotation[3][3] = 1.0; return(1); } Transformpolygon(poly,count,mm) int count; float *poly,mm[4][4]; { int i; float xtemp,ytemp,ztemp; for(i=0;i