home *** CD-ROM | disk | FTP | other *** search
/ Graphics 16,000 / graphics-16000.iso / msdos / utils / graphtal.lzh / Graphtal.Amiga / Cylinder.C < prev    next >
C/C++ Source or Header  |  1992-11-19  |  4KB  |  163 lines

  1. /*
  2.  * Cylinder.C - methods for cylinder manipulations.
  3.  *
  4.  * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
  5.  *                     University of Berne, Switzerland
  6.  * Copyright (C) 1989, 1991, Craig E. Kolb
  7.  * All rights reserved.
  8.  *
  9.  * This software may be freely copied, modified, and redistributed
  10.  * provided that this copyright notice is preserved on all copies.
  11.  *
  12.  * You may not distribute this software, in whole or in part, as part of
  13.  * any commercial product without the express consent of the authors.
  14.  *
  15.  * There is no warranty or other guarantee of fitness of this software
  16.  * for any purpose.  It is provided solely "as is".
  17.  *
  18.  */
  19.  
  20. #include "Cylinder.h"
  21. #include "transform.h"
  22.  
  23. //___________________________________________________________ Cylinder
  24.  
  25. Cylinder::Cylinder(real radius, const Vector& bottom, const Vector& top)
  26. {
  27.   Vector axis = top - bottom;
  28.   real len = axis.normalize();
  29.  
  30.   /*
  31.    * matrix trans transforms unit cylinder (1, [0,0,0], [0,0,1]) to
  32.    * the given cylinder (radius, bottom, top).
  33.    */
  34.   trans  = new TransMatrix(coordSystemTransform(bottom, axis, 
  35.                         radius, len));
  36.   itrans = new TransMatrix(*trans);
  37.   itrans->invert();
  38. }
  39.  
  40. GeoObject* Cylinder::create(real radius, const Vector& bottom, const Vector& top)
  41. {
  42.   if (radius < EPSILON)
  43.     return NULL;
  44.  
  45.   if ((top-bottom).length() < EPSILON)
  46.     return NULL;
  47.  
  48.   return new Cylinder(radius, bottom, top);
  49. }
  50.  
  51. /*
  52.  * Ray cylinder intersection.
  53.  *
  54.  * The code is adapted from Craig Kolbs rayshade.
  55.  */
  56.  
  57. int Cylinder::intersect(const Ray& ray, real minDist, real& maxDist)
  58. {
  59.   real t1, t2, a, b, c, zpos1, zpos2, disc;
  60.  
  61.   intersectionTests++;
  62.  
  63.   a = ray.getDir()[0]*ray.getDir()[0] + ray.getDir()[1]*ray.getDir()[1];
  64.   if (a < EPSILON*EPSILON)
  65.     /* |ray.getDir()[2]| == 1. */
  66.     return FALSE;
  67.   
  68.   b = ray.getDir()[0]*ray.getOrig()[0]
  69.     + ray.getDir()[1]*ray.getOrig()[1];
  70.   c = ray.getOrig()[0]*ray.getOrig()[0] 
  71.     + ray.getOrig()[1]*ray.getOrig()[1] - 1;
  72.   disc = b*b - a*c;
  73.  
  74.   if(disc < 0.)
  75.     return FALSE;
  76.  
  77.   disc = sqrt(disc);
  78.   t1 = (-b + disc) / a;
  79.   t2 = (-b - disc) / a;
  80.   if (t1 < minDist && t2 < minDist)
  81.     return FALSE;
  82.  
  83.   zpos1 = ray.getOrig()[2] + t1 * ray.getDir()[2];
  84.   zpos2 = ray.getOrig()[2] + t2 * ray.getDir()[2];
  85.   
  86.   if (t1 < minDist || zpos1 < 0. || zpos1 > 1.) {
  87.     if (t2 < minDist || zpos2 < 0. || zpos2 > 1.)
  88.       return FALSE;
  89.     else
  90.       t1 = t2;
  91.   } 
  92.   else if (t2 >= minDist && zpos2 >= 0. && zpos2 <= 1.)
  93.       t1 = (t1 < t2) ? t1 : t2;
  94.   
  95.   if (t1 < maxDist) {
  96.     maxDist = t1;
  97.     intersections++;
  98.     return TRUE;
  99.   }
  100.   return FALSE;
  101. }
  102.  
  103. /*
  104.  * Compute cylinder normal at the given point.
  105.  */
  106.  
  107. Vector Cylinder::normal(const Vector& p) const
  108. {
  109.   /*
  110.    * The normal is equal to the point of intersection in cylinder
  111.    * space, but with Z = 0.;
  112.    */
  113.   return Vector(p[0], p[1], 0);
  114. }
  115.  
  116. /*
  117.  * Split the cylinder into polygon (rectangles)
  118.  */
  119.  
  120. PolygonList* Cylinder::tesselate(const BoundingBox&)
  121. {
  122.   const int resolution = 10;
  123.   real delta = 2*M_PI/(real)resolution;
  124.   real lastX = 1;
  125.   real lastY = 0;
  126.   real x, y;
  127.  
  128.   Polygon* p;
  129.   PolygonList* polys = new PolygonList(resolution);
  130.  
  131.   /* 
  132.    * generate points on the edge of the disc.
  133.    */
  134.  
  135.   for (real alpha=delta; alpha <= 2*M_PI; alpha += delta) {
  136.     x = cos(alpha); y = sin(alpha);
  137.     p = new Polygon(Vector(lastX, lastY, 0), Vector(x, y, 0),
  138.             Vector(x, y, 1), Vector(lastX, lastY, 1));
  139.     p->transform(*trans);
  140.     polys->append(p);
  141.     lastX = x; lastY = y;
  142.   }
  143.  
  144.   return polys;
  145. }
  146.  
  147. /*
  148.  * If a transformation is given for the defined cylinder, postmultiply
  149.  * it to the already computed transformations.
  150.  */
  151.  
  152. int Cylinder::setTransform(TransMatrix* tmat)
  153. {
  154.   TransMatrix* matMul = new TransMatrix((*trans) * (*tmat));
  155.   delete itrans;
  156.   delete trans;
  157.  
  158.   return GeoObject::setTransform(matMul);
  159. }
  160.  
  161.  
  162.  
  163.