home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 8 / CDASC08.ISO / NEWS / RADIANCE / SRC / COMMON / CONE.C < prev    next >
C/C++ Source or Header  |  1993-10-07  |  5KB  |  215 lines

  1. /* Copyright (c) 1992 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)cone.c 2.3 10/2/92 LBL";
  5. #endif
  6.  
  7. /*
  8.  *  cone.c - routines for making cones
  9.  *
  10.  *     2/12/86
  11.  */
  12.  
  13. #include  "standard.h"
  14.  
  15. #include  "object.h"
  16.  
  17. #include  "otypes.h"
  18.  
  19. #include  "cone.h"
  20.  
  21. /*
  22.  *     In general, a cone may be any one of a cone, a cylinder, a ring,
  23.  *  a cup (inverted cone), or a tube (inverted cylinder).
  24.  *     Most cones are specified with a starting point and radius and
  25.  *  an ending point and radius.  In the cases of a cylinder or tube,
  26.  *  only one radius is needed.  In the case of a ring, a normal direction
  27.  *  is specified instead of a second endpoint.
  28.  *
  29.  *    mtype (cone|cup) name
  30.  *    0
  31.  *    0
  32.  *    8 P0x P0y P0z P1x P1y P1z R0 R1
  33.  *
  34.  *    mtype (cylinder|tube) name
  35.  *    0
  36.  *    0
  37.  *    7 P0x P0y P0z P1x P1y P1z R
  38.  *
  39.  *    mtype ring name
  40.  *    0
  41.  *    0
  42.  *    8 Px Py Pz Nx Ny Nz R0 R1
  43.  */
  44.  
  45.  
  46. CONE *
  47. getcone(o, getxf)            /* get cone structure */
  48. register OBJREC  *o;
  49. int  getxf;
  50. {
  51.     int  sgn0, sgn1;
  52.     register CONE  *co;
  53.  
  54.     if ((co = (CONE *)o->os) == NULL) {
  55.  
  56.         co = (CONE *)malloc(sizeof(CONE));
  57.         if (co == NULL)
  58.             error(SYSTEM, "out of memory in makecone");
  59.  
  60.         co->ca = o->oargs.farg;
  61.                         /* get radii */
  62.         if (o->otype == OBJ_CYLINDER | o->otype == OBJ_TUBE) {
  63.             if (o->oargs.nfargs != 7)
  64.                 goto argcerr;
  65.             if (co->ca[6] < -FTINY) {
  66.                 objerror(o, WARNING, "negative radius");
  67.                 o->otype = o->otype == OBJ_CYLINDER ?
  68.                         OBJ_TUBE : OBJ_CYLINDER;
  69.                 co->ca[6] = -co->ca[6];
  70.             } else if (co->ca[6] <= FTINY)
  71.                 goto raderr;
  72.             co->p0 = 0; co->p1 = 3;
  73.             co->r0 = co->r1 = 6;
  74.         } else {
  75.             if (o->oargs.nfargs != 8)
  76.                 goto argcerr;
  77.             if (co->ca[6] < -FTINY) sgn0 = -1;
  78.             else if (co->ca[6] > FTINY) sgn0 = 1;
  79.             else sgn0 = 0;
  80.             if (co->ca[7] < -FTINY) sgn1 = -1;
  81.             else if (co->ca[7] > FTINY) sgn1 = 1;
  82.             else sgn1 = 0;
  83.             if (sgn0+sgn1 == 0)
  84.                 goto raderr;
  85.             if (sgn0 < 0 | sgn1 < 0) {
  86.                 objerror(o, o->otype==OBJ_RING?USER:WARNING,
  87.                     "negative radii");
  88.                 o->otype = o->otype == OBJ_CONE ?
  89.                         OBJ_CUP : OBJ_CONE;
  90.             }
  91.             co->ca[6] = co->ca[6]*sgn0;
  92.             co->ca[7] = co->ca[7]*sgn1;
  93.             if (co->ca[7] - co->ca[6] > FTINY) {
  94.                 if (o->otype == OBJ_RING)
  95.                     co->p0 = co->p1 = 0;
  96.                 else {
  97.                     co->p0 = 0; co->p1 = 3;
  98.                 }
  99.                 co->r0 = 6; co->r1 = 7;
  100.             } else if (co->ca[6] - co->ca[7] > FTINY) {
  101.                 if (o->otype == OBJ_RING)
  102.                     co->p0 = co->p1 = 0;
  103.                 else {
  104.                     co->p0 = 3; co->p1 = 0;
  105.                 }
  106.                 co->r0 = 7; co->r1 = 6;
  107.             } else {
  108.                 if (o->otype == OBJ_RING)
  109.                     goto raderr;
  110.                 o->otype = o->otype == OBJ_CONE ?
  111.                         OBJ_CYLINDER : OBJ_TUBE;
  112.                 o->oargs.nfargs = 7;
  113.                 co->p0 = 0; co->p1 = 3;
  114.                 co->r0 = co->r1 = 6;
  115.             }
  116.         }
  117.                         /* get axis orientation */
  118.         if (o->otype == OBJ_RING)
  119.             VCOPY(co->ad, o->oargs.farg+3);
  120.         else {
  121.             co->ad[0] = CO_P1(co)[0] - CO_P0(co)[0];
  122.             co->ad[1] = CO_P1(co)[1] - CO_P0(co)[1];
  123.             co->ad[2] = CO_P1(co)[2] - CO_P0(co)[2];
  124.         }
  125.         co->al = normalize(co->ad);
  126.         if (co->al == 0.0)
  127.             objerror(o, USER, "zero orientation");
  128.                     /* compute axis and side lengths */
  129.         if (o->otype == OBJ_RING) {
  130.             co->al = 0.0;
  131.             co->sl = CO_R1(co) - CO_R0(co);
  132.         } else if (o->otype == OBJ_CONE | o->otype == OBJ_CUP) {
  133.             co->sl = co->ca[7] - co->ca[6];
  134.             co->sl = sqrt(co->sl*co->sl + co->al*co->al);
  135.         } else { /* OBJ_CYLINDER or OBJ_TUBE */
  136.             co->sl = co->al;
  137.         }
  138.         co->tm = NULL;
  139.         o->os = (char *)co;
  140.     }
  141.     if (getxf && co->tm == NULL)
  142.         conexform(co);
  143.     return(co);
  144.  
  145. argcerr:
  146.     objerror(o, USER, "bad # arguments");
  147. raderr:
  148.     objerror(o, USER, "illegal radii");
  149. }
  150.  
  151.  
  152. freecone(o)            /* free memory associated with cone */
  153. OBJREC  *o;
  154. {
  155.     register CONE  *co = (CONE *)o->os;
  156.  
  157.     if (o->os == NULL)
  158.         return;
  159.     if (co->tm != NULL)
  160.         free((char *)co->tm);
  161.     free(o->os);
  162.     o->os = NULL;
  163. }
  164.  
  165.  
  166. conexform(co)            /* get cone transformation matrix */
  167. register CONE  *co;
  168. {
  169.     MAT4  m4;
  170.     register double  d;
  171.     register int  i;
  172.  
  173.     co->tm = (FLOAT (*)[4])malloc(sizeof(MAT4));
  174.     if (co->tm == NULL)
  175.         error(SYSTEM, "out of memory in conexform");
  176.  
  177.                 /* translate to origin */
  178.     setident4(co->tm);
  179.     if (co->r0 == co->r1)
  180.         d = 0.0;
  181.     else
  182.         d = CO_R0(co) / (CO_R1(co) - CO_R0(co));
  183.     for (i = 0; i < 3; i++)
  184.         co->tm[3][i] = d*(CO_P1(co)[i] - CO_P0(co)[i])
  185.                 - CO_P0(co)[i];
  186.     
  187.                 /* rotate to positive z-axis */
  188.     setident4(m4);
  189.     d = co->ad[1]*co->ad[1] + co->ad[2]*co->ad[2];
  190.     if (d <= FTINY*FTINY) {
  191.         m4[0][0] = 0.0;
  192.         m4[0][2] = co->ad[0];
  193.         m4[2][0] = -co->ad[0];
  194.         m4[2][2] = 0.0;
  195.     } else {
  196.         d = sqrt(d);
  197.         m4[0][0] = d;
  198.         m4[1][0] = -co->ad[0]*co->ad[1]/d;
  199.         m4[2][0] = -co->ad[0]*co->ad[2]/d;
  200.         m4[1][1] = co->ad[2]/d;
  201.         m4[2][1] = -co->ad[1]/d;
  202.         m4[0][2] = co->ad[0];
  203.         m4[1][2] = co->ad[1];
  204.         m4[2][2] = co->ad[2];
  205.     }
  206.     multmat4(co->tm, co->tm, m4);
  207.  
  208.                 /* scale z-axis */
  209.     if (co->p0 != co->p1 & co->r0 != co->r1) {
  210.         setident4(m4);
  211.         m4[2][2] = (CO_R1(co) - CO_R0(co)) / co->al;
  212.         multmat4(co->tm, co->tm, m4);
  213.     }
  214. }
  215.