| 1 | 
greg | 
1.1 | 
#ifndef lint | 
| 2 | 
schorsch | 
2.5 | 
static const char       RCSid[] = "$Id: clip.c,v 2.4 2003/02/25 02:47:21 greg Exp $"; | 
| 3 | 
greg | 
1.1 | 
#endif | 
| 4 | 
  | 
  | 
/* | 
| 5 | 
  | 
  | 
 *  clip.c - routine to clip 3D line segments to a box. | 
| 6 | 
greg | 
2.3 | 
 */ | 
| 7 | 
  | 
  | 
 | 
| 8 | 
greg | 
2.4 | 
#include "copyright.h" | 
| 9 | 
greg | 
1.1 | 
 | 
| 10 | 
greg | 
1.2 | 
#include  "fvect.h" | 
| 11 | 
  | 
  | 
 | 
| 12 | 
greg | 
1.1 | 
#include  "plocate.h" | 
| 13 | 
  | 
  | 
 | 
| 14 | 
greg | 
2.2 | 
#define MAXITER         6       /* maximum possible number of iterations */ | 
| 15 | 
greg | 
1.1 | 
 | 
| 16 | 
greg | 
2.2 | 
 | 
| 17 | 
greg | 
2.3 | 
int | 
| 18 | 
greg | 
1.1 | 
clip(ep1, ep2, min, max)        /* clip a line segment to a box */ | 
| 19 | 
schorsch | 
2.5 | 
RREAL  *ep1, *ep2; | 
| 20 | 
greg | 
1.2 | 
FVECT  min, max; | 
| 21 | 
greg | 
1.1 | 
{ | 
| 22 | 
greg | 
2.2 | 
        int  itlim = MAXITER; | 
| 23 | 
greg | 
1.1 | 
        int  loc1, loc2; | 
| 24 | 
  | 
  | 
        int  accept; | 
| 25 | 
schorsch | 
2.5 | 
        RREAL  *dp; | 
| 26 | 
greg | 
1.1 | 
        double  d; | 
| 27 | 
  | 
  | 
        register int  i, j; | 
| 28 | 
  | 
  | 
 | 
| 29 | 
  | 
  | 
        /* | 
| 30 | 
  | 
  | 
         *      The Cohen-Sutherland algorithm is used to determine | 
| 31 | 
  | 
  | 
         *  what part (if any) of the given line segment is contained | 
| 32 | 
  | 
  | 
         *  in the box specified by the min and max vectors. | 
| 33 | 
  | 
  | 
         *      The routine returns non-zero if any segment is left. | 
| 34 | 
  | 
  | 
         */ | 
| 35 | 
  | 
  | 
         | 
| 36 | 
  | 
  | 
        loc1 = plocate(ep1, min, max); | 
| 37 | 
  | 
  | 
        loc2 = plocate(ep2, min, max); | 
| 38 | 
  | 
  | 
 | 
| 39 | 
  | 
  | 
                        /* check for trivial accept and reject */ | 
| 40 | 
  | 
  | 
                        /* trivial accept is both points inside */ | 
| 41 | 
  | 
  | 
                        /* trivial reject is both points to one side */ | 
| 42 | 
  | 
  | 
         | 
| 43 | 
  | 
  | 
        while (!((accept = !(loc1 | loc2)) || (loc1 & loc2))) { | 
| 44 | 
  | 
  | 
         | 
| 45 | 
greg | 
2.2 | 
                if (itlim-- <= 0)       /* past theoretical limit? */ | 
| 46 | 
  | 
  | 
                        return(0);      /* quit fooling around */ | 
| 47 | 
  | 
  | 
 | 
| 48 | 
greg | 
1.1 | 
                if (!loc1) {            /* make sure first point is outside */ | 
| 49 | 
  | 
  | 
                        dp = ep1; ep1 = ep2; ep2 = dp; | 
| 50 | 
  | 
  | 
                        i = loc1; loc1 = loc2; loc2 = i; | 
| 51 | 
  | 
  | 
                } | 
| 52 | 
  | 
  | 
                 | 
| 53 | 
  | 
  | 
                for (i = 0; i < 3; i++) {               /* chop segment */ | 
| 54 | 
  | 
  | 
                         | 
| 55 | 
  | 
  | 
                        if (loc1 & position(i) & BELOW) { | 
| 56 | 
  | 
  | 
                                d = (min[i] - ep1[i])/(ep2[i] - ep1[i]); | 
| 57 | 
  | 
  | 
                                ep1[i] = min[i]; | 
| 58 | 
  | 
  | 
                        } else if (loc1 & position(i) & ABOVE) { | 
| 59 | 
  | 
  | 
                                d = (max[i] - ep1[i])/(ep2[i] - ep1[i]); | 
| 60 | 
  | 
  | 
                                ep1[i] = max[i]; | 
| 61 | 
  | 
  | 
                        } else | 
| 62 | 
  | 
  | 
                                continue; | 
| 63 | 
  | 
  | 
                         | 
| 64 | 
  | 
  | 
                        for (j = 0; j < 3; j++) | 
| 65 | 
  | 
  | 
                                if (j != i) | 
| 66 | 
  | 
  | 
                                        ep1[j] += (ep2[j] - ep1[j])*d; | 
| 67 | 
  | 
  | 
                        break; | 
| 68 | 
  | 
  | 
                } | 
| 69 | 
  | 
  | 
                loc1 = plocate(ep1, min, max); | 
| 70 | 
  | 
  | 
        } | 
| 71 | 
  | 
  | 
        return(accept); | 
| 72 | 
  | 
  | 
} |