ftp.nice.ch/pub/next/unix/developer/plplot.3.0.s.tar.gz#/plplot/src/plnxtv.c

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.