This is plnxtv.c in view mode; [Download] [Up]
/* Draws the next view of a 3-d plot. The physical coordinates of */ /* the points for the next view are placed in the n points of arrays */ /* u and v. The silhouette found so far is stored in the heap as a */ /* set of m peak points. */ #include "plplot.h" #include <stdio.h> #if defined(PLSTDC) && defined(STDLIB) #include <stdlib.h> #else extern char *malloc(); extern char *realloc(); extern void free(); #endif /* This routine now dynamically allocates the memory it needs for hidden */ /* line removal. Memory is allocated in blocks of 2*BINC*sizeof(int) */ /* bytes. Large values of BINC give better performance but also */ /* allocate more memory than is needed. If your 3D plots are very */ /* "spiky" or you are working with very large matrices then you will */ /* probably want to increase BINC. */ #define BINC 50 static int *oldhiview; static int *oldloview; static int *newhiview; static int *newloview; static int mhi, xxhi, newhisize; static int mlo, xxlo, newlosize; void goldhivw(ohivw) int **ohivw; { *ohivw = oldhiview; } void goldlovw(olovw) int **olovw; { *olovw = oldloview; } static int pl3mode=0; /* 0 3d solid; 1 mesh plot */ static int pl3upv=1; /* 1 update view; 0 no update */ void set3mode(mod) int mod; { pl3mode = mod; } void set3upd(updm) int updm; { pl3upv = updm; } void plnxtv(u, v, n, init) int *u, *v, n, init; { void plnxtvhi(), plnxtvlo(); plnxtvhi(u,v,n,init); if(pl3mode) plnxtvlo(u,v,n,init); } static void plnxtvhi(u,v,n,init) int *u, *v, n, init; { int i, j, first; int sx1, sx2, sy1, sy2; int su1, su2, sv1, sv2; int cx, cy, px, py; int seg, ptold, lstold, pthi, pnewhi, newhi, change, ochange; void savehipoint(), swaphiview(); sy2 = sy1 = sx2 = sx1 = 0; ochange = lstold = 0; first = 1; pnewhi = 0; /* For the initial set of points, just display them and store them as */ /* the peak points. */ if (init == 1) { /* heap not yet allocated so ... */ if(!( oldhiview = (int *)malloc(2*n*sizeof(int)))) plexit("Out of memory."); movphy(u[0],v[0]); oldhiview[0] = u[0]; oldhiview[1] = v[0]; for (i=1; i<n; i++){ draphy(u[i],v[i]); oldhiview[2*i] = u[i]; oldhiview[2*i+1] = v[i]; } mhi = n; return; } /* Otherwise, we need to consider hidden-line removal problem. We scan */ /* over the points in both the old (i.e. oldhiview[]) and */ /* new (i.e. u[] and v[]) arrays in order of increasing x coordinate. */ /* At each stage, we find the line segment in the other array (if one */ /* exists) that straddles the x coordinate of the point. We */ /* have to determine if the point lies above or below the line segment, */ /* and to check if the below/above status has changed since the last */ /* point. */ /* If pl3upv = 0 we do not update the view, this is useful for drawing */ /* lines on the graph after we are done plotting points. Hidden line */ /* removal is still done, but the view is not updated. */ xxhi = 0; i = 0; j = 0; if(pl3upv != 0) { newhisize = 2*(mhi+BINC); if(!( newhiview = (int *)malloc(newhisize*sizeof(int)))) { free((VOID *)oldhiview); plexit("Out of memory."); } } /* (oldhiview[2*i], oldhiview[2*i]) is the i'th point in the old array */ /* (u[j], v[j]) is the j'th point in the new array */ while (i < mhi || j < n) { /* The coordinates of the point under consideration are (px,py). */ /* The line segment joins (sx1,sy1) to (sx2,sy2). */ /* "ptold" is true if the point lies in the old array. We set it */ /* by comparing the x coordinates of the i'th old point */ /* and the j'th new point, being careful if we have fallen past */ /* the edges. Having found the point, load up the point and */ /* segment coordinates appropriately. */ ptold = ((oldhiview[2*i] < u[j] && i<mhi) || j>= n); if (ptold) { px = oldhiview[2*i]; py = oldhiview[2*i+1]; seg = j>0 && j<n; if (seg) { sx1 = u[j-1]; sy1 = v[j-1]; sx2 = u[j]; sy2 = v[j]; } } else { px = u[j]; py = v[j]; seg = i>0 && i<mhi; if (seg) { sx1 = oldhiview[2*(i-1)]; sy1 = oldhiview[2*(i-1)+1]; sx2 = oldhiview[2*i]; sy2 = oldhiview[2*i+1]; } } /* Now determine if the point is higher than the segment, using the */ /* logical function "above". We also need to know if it is */ /* the old view or the new view that is higher. "newhi" is set true */ /* if the new view is higher than the old */ if(seg) pthi = plabv(px,py,sx1,sy1,sx2,sy2); else pthi = 1; newhi = (ptold && !pthi) || (!ptold && pthi); change = (newhi && !pnewhi) || (!newhi && pnewhi); /* There is a new intersection point to put in the peak array if the */ /* state of "newhi" changes */ if (first) { movphy(px,py); first = 0; lstold = ptold; savehipoint(px,py); pthi = 0; ochange = 0; } else if (change) { /* Take care of special cases at end of arrays. If pl3upv */ /* is 0 the endpoints are not connected to the old view. */ if (pl3upv==0 && ((!ptold && j==0)||(ptold && i==0))) { movphy(px,py); lstold = ptold; pthi = 0; ochange = 0; } else if (pl3upv==0 && ((!ptold && i>=mhi)||(ptold && j>=n))) { movphy(px,py); lstold = ptold; pthi = 0; ochange = 0; } /* If pl3upv is not 0 then we do want to connect the current line */ /* with the previous view at the endpoints. */ /* Also find intersection point with old view. */ else { if (i == 0) { sx1 = oldhiview[0]; sy1 = -1; sx2 = oldhiview[0]; sy2 = oldhiview[1]; } else if (i >= mhi) { sx1 = oldhiview[2*(mhi-1)]; sy1 = oldhiview[2*(mhi-1)+1]; sx2 = oldhiview[2*(mhi-1)]; sy2 = -1; } else { sx1 = oldhiview[2*(i-1)]; sy1 = oldhiview[2*(i-1)+1]; sx2 = oldhiview[2*i]; sy2 = oldhiview[2*i+1]; } if (j == 0) { su1 = u[0]; sv1 = -1; su2 = u[0]; sv2 = v[0]; } else if (j >= n) { su1 = u[n-1]; sv1 = v[n-1]; su2 = u[n]; sv2 = -1; } else { su1 = u[j-1]; sv1 = v[j-1]; su2 = u[j]; sv2 = v[j]; } /* Determine the intersection */ pl3cut(sx1,sy1,sx2,sy2,su1,sv1,su2,sv2,&cx,&cy); if (cx == px && cy == py) { if (lstold && !ochange) movphy(px,py); else draphy(px,py); savehipoint(px,py); lstold = 1; pthi = 0; } else { if (lstold && !ochange) movphy(cx,cy); else draphy(cx,cy); lstold = 1; savehipoint(cx,cy); } ochange =1; } } /* If point is high then draw plot to point and update view. */ if (pthi) { if (lstold && ptold) movphy(px,py); else draphy(px,py); savehipoint(px,py); lstold = ptold; ochange = 0; } pnewhi = newhi; if (ptold) i = i+1; else j = j+1; } /* Set oldhiview */ swaphiview(); } static void savehipoint(px, py) int px, py; { int *temp; if(pl3upv == 0) return; if( xxhi >= newhisize ) { /* allocate additional space */ newhisize += 2*BINC; if(!(temp = (int *)realloc((VOID *)newhiview,newhisize*sizeof(int)))) { free((VOID *)oldhiview); free((VOID *)newhiview); plexit("Out of memory."); } newhiview = temp; } newhiview[xxhi] = px; xxhi++; newhiview[xxhi] = py; xxhi++; } static void swaphiview() { if(pl3upv != 0) { mhi = xxhi/2; free((VOID *)oldhiview); oldhiview = newhiview; } } static void plnxtvlo(u,v,n,init) int *u, *v, n, init; { int i, j, first; int sx1, sx2, sy1, sy2; int su1, su2, sv1, sv2; int cx, cy, px, py; int seg, ptold, lstold, ptlo, pnewlo, newlo, change, ochange; void savelopoint(), swaploview(); sy2 = sy1 = sx2 = sx1 = 0; ochange = lstold = 0; first = 1; pnewlo = 0; /* For the initial set of points, just display them and store them as */ /* the peak points. */ if (init == 1) { /* heap not yet allocated so ... */ if(!( oldloview = (int *)malloc(2*n*sizeof(int)))) plexit("Out of memory."); movphy(u[0],v[0]); oldloview[0] = u[0]; oldloview[1] = v[0]; for (i=1; i<n; i++){ draphy(u[i],v[i]); oldloview[2*i] = u[i]; oldloview[2*i+1] = v[i]; } mlo = n; return; } /* Otherwise, we need to consider hidden-line removal problem. We scan */ /* over the points in both the old (i.e. oldloview[]) and */ /* new (i.e. u[] and v[]) arrays in order of increasing x coordinate. */ /* At each stage, we find the line segment in the other array (if one */ /* exists) that straddles the x coordinate of the point. We */ /* have to determine if the point lies above or below the line segment, */ /* and to check if the below/above status has changed since the last */ /* point. */ /* If pl3upv = 0 we do not update the view, this is useful for drawing */ /* lines on the graph after we are done plotting points. Hidden line */ /* removal is still done, but the view is not updated. */ xxlo = 0; i = 0; j = 0; if(pl3upv != 0) { newlosize = 2*(mlo+BINC); if(!( newloview = (int *)malloc(newlosize*sizeof(int)))) { free((VOID *)oldloview); plexit("Out of memory."); } } /* (oldloview[2*i], oldloview[2*i]) is the i'th point in the old array */ /* (u[j], v[j]) is the j'th point in the new array */ while (i < mlo || j < n) { /* The coordinates of the point under consideration are (px,py). */ /* The line segment joins (sx1,sy1) to (sx2,sy2). */ /* "ptold" is true if the point lies in the old array. We set it */ /* by comparing the x coordinates of the i'th old point */ /* and the j'th new point, being careful if we have fallen past */ /* the edges. Having found the point, load up the point and */ /* segment coordinates appropriately. */ ptold = ((oldloview[2*i] < u[j] && i<mlo) || j>= n); if (ptold) { px = oldloview[2*i]; py = oldloview[2*i+1]; seg = j>0 && j<n; if (seg) { sx1 = u[j-1]; sy1 = v[j-1]; sx2 = u[j]; sy2 = v[j]; } } else { px = u[j]; py = v[j]; seg = i>0 && i<mlo; if (seg) { sx1 = oldloview[2*(i-1)]; sy1 = oldloview[2*(i-1)+1]; sx2 = oldloview[2*i]; sy2 = oldloview[2*i+1]; } } /* Now determine if the point is lower than the segment, using the */ /* logical function "above". We also need to know if it is */ /* the old view or the new view that is lower. "newlo" is set true */ /* if the new view is lower than the old */ if(seg) ptlo = !plabv(px,py,sx1,sy1,sx2,sy2); else ptlo = 1; newlo = (ptold && !ptlo) || (!ptold && ptlo); change = (newlo && !pnewlo) || (!newlo && pnewlo); /* There is a new intersection point to put in the peak array if the */ /* state of "newlo" changes */ if (first) { movphy(px,py); first = 0; lstold = ptold; savelopoint(px,py); ptlo = 0; ochange = 0; } else if (change) { /* Take care of special cases at end of arrays. If pl3upv */ /* is 0 the endpoints are not connected to the old view. */ if (pl3upv==0 && ((!ptold && j==0)||(ptold && i==0))) { movphy(px,py); lstold = ptold; ptlo = 0; ochange = 0; } else if (pl3upv==0 && ((!ptold && i>=mlo)||(ptold && j>=n))) { movphy(px,py); lstold = ptold; ptlo = 0; ochange = 0; } /* If pl3upv is not 0 then we do want to connect the current line */ /* with the previous view at the endpoints. */ /* Also find intersection point with old view. */ else { if (i == 0) { sx1 = oldloview[0]; sy1 = 100000; sx2 = oldloview[0]; sy2 = oldloview[1]; } else if (i >= mlo) { sx1 = oldloview[2*(mlo-1)]; sy1 = oldloview[2*(mlo-1)+1]; sx2 = oldloview[2*(mlo-1)]; sy2 = 100000; } else { sx1 = oldloview[2*(i-1)]; sy1 = oldloview[2*(i-1)+1]; sx2 = oldloview[2*i]; sy2 = oldloview[2*i+1]; } if (j == 0) { su1 = u[0]; sv1 = 100000; su2 = u[0]; sv2 = v[0]; } else if (j >= n) { su1 = u[n-1]; sv1 = v[n-1]; su2 = u[n]; sv2 = 100000; } else { su1 = u[j-1]; sv1 = v[j-1]; su2 = u[j]; sv2 = v[j]; } /* Determine the intersection */ pl3cut(sx1,sy1,sx2,sy2,su1,sv1,su2,sv2,&cx,&cy); if (cx == px && cy == py) { if (lstold && !ochange) movphy(px,py); else draphy(px,py); savelopoint(px,py); lstold = 1; ptlo = 0; } else { if (lstold && !ochange) movphy(cx,cy); else draphy(cx,cy); lstold = 1; savelopoint(cx,cy); } ochange =1; } } /* If point is low then draw plot to point and update view. */ if (ptlo) { if (lstold && ptold) movphy(px,py); else draphy(px,py); savelopoint(px,py); lstold = ptold; ochange = 0; } pnewlo = newlo; if (ptold) i = i+1; else j = j+1; } /* Set oldloview */ swaploview(); } static void savelopoint(px, py) int px, py; { int *temp; if(pl3upv == 0) return; if( xxlo >= newlosize ) { /* allocate additional space */ newlosize += 2*BINC; if(!(temp = (int *)realloc((VOID *)newloview,newlosize*sizeof(int)))) { free((VOID *)oldloview); free((VOID *)newloview); plexit("Out of memory."); } newloview = temp; } newloview[xxlo] = px; xxlo++; newloview[xxlo] = py; xxlo++; } static void swaploview() { if(pl3upv != 0) { mlo = xxlo/2; free((VOID *)oldloview); oldloview = newloview; } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.