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

  1. /*
  2.  * Plane.C - methods for plane 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 "Plane.h"
  19.  
  20. //___________________________________________________________ Plane
  21.  
  22. Plane::Plane(const Vector& position, const Vector& normal)
  23. :  pos(position), n(normal)
  24. {
  25.   if (n.normalize() == 0)
  26.   n.normalize();
  27.   D = pos^n;
  28. }
  29.  
  30. GeoObject* Plane::create(const Vector& position, const Vector& normal)
  31. {
  32.   if (equal(normal.sqr(), 0))
  33.     return NULL;
  34.  
  35.   return new Plane(position, normal);
  36. }
  37.  
  38. /*
  39.  * intersect plane with ray.
  40.  */
  41.  
  42. int Plane::intersect(const Ray& ray, real minDist, real& maxDist)
  43. {
  44.   intersectionTests++;
  45.  
  46.   real t = n^ray.getDir();
  47.   if (fabs(t) < minDist)
  48.     return FALSE;
  49.  
  50.   t = (D - (ray.getOrig()^n))/t;
  51.   
  52.   if (t > minDist && t < maxDist) {
  53.     maxDist = t;
  54.     intersections++;
  55.     return TRUE;
  56.   }
  57.   return FALSE;
  58. }
  59.  
  60. /*
  61.  * calculate plane normal
  62.  */
  63.  
  64. Vector Plane::normal(const Vector&) const
  65. {
  66.   return n;
  67. }
  68.  
  69. /*
  70.  * tesselate splits a plane into a polygon (I know it's impossible).
  71.  * It is done by intersecting the plane with the bounding volume. The 
  72.  * resulting polygon is the visible part of the plane within the bounding
  73.  * volume.
  74.  */
  75.  
  76. PolygonList* Plane::tesselate(const BoundingBox& bbox)
  77. {
  78.   int i;
  79.   BoundingBox tbbox(bbox);
  80.   
  81.   if (trans != NULL) 
  82.     tbbox = bbox.transform(*itrans);
  83.  
  84.   /*
  85.    * compute the points on the bounding volume
  86.    */
  87.   Vector bottom[4];
  88.   bottom[0] = Vector(tbbox.xmin(), tbbox.ymin(), tbbox.zmin());
  89.   bottom[1] = Vector(tbbox.xmax(), tbbox.ymin(), tbbox.zmin());
  90.   bottom[2] = Vector(tbbox.xmax(), tbbox.ymax(), tbbox.zmin());
  91.   bottom[3] = Vector(tbbox.xmin(), tbbox.ymax(), tbbox.zmin());
  92.  
  93.   Vector top[4];
  94.   top[0] = Vector(tbbox.xmin(), tbbox.ymin(), tbbox.zmax());
  95.   top[1] = Vector(tbbox.xmax(), tbbox.ymin(), tbbox.zmax());
  96.   top[2] = Vector(tbbox.xmax(), tbbox.ymax(), tbbox.zmax());
  97.   top[3] = Vector(tbbox.xmin(), tbbox.ymax(), tbbox.zmax());
  98.   
  99.   Polygon* p = new Polygon(4);
  100.   PolygonList* polys = NULL;
  101.   Vector iPoint;
  102.   int pointsOnPlane;
  103.  
  104.   for (i=0; i<4; i++) {
  105.     if (pointsOnPlane=intersectPlaneWithSegment(bottom[i], top[i], iPoint)) {
  106.       if (pointsOnPlane == 2) {
  107.         p->addVertex(bottom[i]); 
  108.         p->addVertex(top[i]);
  109.       }
  110.       else
  111.         p->addVertex(iPoint);
  112.     }
  113.   }
  114.   for (i=0; i<4 && p->numVertices() < 4; i++) {
  115.     if (pointsOnPlane=intersectPlaneWithSegment(top[i], top[(i+1)%4], iPoint)) {
  116.       if (pointsOnPlane == 2) {
  117.         p->addVertex(top[i]); 
  118.         p->addVertex(top[(i+1)%4]);
  119.       }
  120.       else
  121.         p->addVertex(iPoint);
  122.     }
  123.   }
  124.   for (i=0; i<4 && p->numVertices() < 4; i++) {
  125.     if (pointsOnPlane=intersectPlaneWithSegment(bottom[i], bottom[(i+1)%4], iPoint)) {
  126.       if (pointsOnPlane == 2) {
  127.         p->addVertex(bottom[i]); 
  128.         p->addVertex(bottom[(i+1)%4]);
  129.       }
  130.       else
  131.         p->addVertex(iPoint);
  132.     }
  133.   }
  134.  
  135.   if (p->numVertices() < 3) {
  136.     delete p; 
  137.     p = NULL;
  138.   }
  139.   else if (p->numVertices() == 4) {
  140.     Vector p1 = p->vertex(0), p2 = p->vertex(1),
  141.            p3 = p->vertex(2), p4 = p->vertex(3);
  142.  
  143.     /*
  144.      * check if any two edges intersects 
  145.      *  -> if yes, swap the corresponding points
  146.      */
  147.     if (!equal(((p2-p1)*(p4-p3)).sqr(),0)) {
  148.       Polygon* swapedP = new Polygon(p1, p2, p4, p3);
  149.       delete p;
  150.       p = swapedP;
  151.     }
  152.     else if (!equal(((p4-p1)*(p2-p3)).sqr(),0)) {
  153.       Polygon* swapedP = new Polygon(p2, p1, p3, p4);
  154.       delete p;
  155.       p = swapedP;
  156.     }
  157.   }
  158.  
  159.   if (p != NULL) {
  160.     if (trans != NULL)
  161.       p->transform(*trans);
  162.     polys = new PolygonList(1);
  163.     polys->append(p);
  164.   }
  165.   
  166.   return polys;
  167. }
  168.  
  169.  
  170. /*
  171.  * Intersect segment p1,p2 with the plane. The return values are
  172.  * 0 (no intersection), 1 (one intersection) or 2 (segment is on the plane).
  173.  */
  174.  
  175. int Plane::intersectPlaneWithSegment(const Vector& p1, const Vector& p2, Vector& h)
  176. {
  177.   /*
  178.    * calculate distance to plane for points p1, p2
  179.    */
  180.   real d1 = (p1 - pos)^n; 
  181.   real d2 = (p2 - pos)^n;
  182.  
  183.   /* 
  184.    * Test if one (both) endpoint(s) of the segment is one the plane.
  185.    */
  186.   if (equal(d1, 0)) {
  187.     if (equal(d2,0))
  188.       return 2;
  189.     else {
  190.       h = p1;
  191.       return 1;
  192.     }
  193.   } 
  194.   else if (equal(d2, 0)) {
  195.     h = p2;
  196.     return 1;
  197.   }
  198.  
  199.   /*
  200.    * If the point p1 and p2 are on the same side of the plane,
  201.    * no intersection is possible.
  202.    */
  203.   if ((d1 < 0 && d2 < 0) || (d1 > 0 && d2 > 0))
  204.     return 0;
  205.  
  206.   Vector dir = p2-p1; dir.normalize();
  207.   real t = n^dir;
  208.  
  209.   h = p1 + ((D-(p1^n))/t)*dir;
  210.  
  211.   return 1;
  212. }
  213.  
  214.  
  215.