home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / graphtal / cylinder.c < prev    next >
C/C++ Source or Header  |  1992-10-22  |  4KB  |  161 lines

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