LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiDraw3D.h

00001 /*
00002  * Copyright (C) 2002, 2003, 2004, 2005, 2006
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  *
00005  * This file is part of the LTI-Computer Vision Library (LTI-Lib)
00006  *
00007  * The LTI-Lib is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License (LGPL)
00009  * as published by the Free Software Foundation; either version 2.1 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * The LTI-Lib is distributed in the hope that it will be
00013  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00014  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with the LTI-Lib; see the file LICENSE.  If
00019  * not, write to the Free Software Foundation, Inc., 59 Temple Place -
00020  * Suite 330, Boston, MA 02111-1307, USA.
00021  */
00022 
00023 
00024 /* -----------------------------------------------------------------------
00025  * project ....: LTI Digitale Bild/Signal Verarbeitungsbibliothek
00026  * file .......: ltiDraw.h
00027  * authors ....: Pablo Alvarado
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 28.4.2002
00030  * revisions ..: $Id: ltiDraw3D.h,v 1.3 2006/02/07 18:46:56 ltilib Exp $
00031  */
00032 #ifndef _LTI_DRAW_3D_H
00033 #define _LTI_DRAW_3D_H
00034 
00035 #include "ltiDraw.h"
00036 #include "ltiIoObject.h"
00037 
00038 namespace lti {
00039   template <class T>
00040   class rayTraceObject;
00041 
00042   /**
00043    * Tool for drawing 3D points and lines in a lti::matrix.  The
00044    * template type T specifies the type of elements of the matrix.  To
00045    * draw in a color image you will need for example a
00046    * lti::draw3D<rgbPixel> object.  Use the parameters to set the
00047    * camera position and direction.  You can activate/deactivate a
00048    * z-Buffering using the method resetDeepCtrl(bool), where the
00049    * boolean should be true if you want to activate the z-Buffering, or false
00050    * otherwise.  The default state for the z-Buffering is off.
00051    *
00052    * Example:
00053    *
00054    * \code
00055    *
00056    * double a;
00057    *
00058    * lti::image canvas;                 // the image to draw on
00059    * lti::draw3D<lti::rgbPixel> drawer; // our draw object
00060    * lti::viewer view;                  // a viewer to see what we do
00061    *
00062    * canvas.resize(256,256,lti::Black); // 256x256 are enough
00063    * drawer.use(canvas);
00064    * drawer.setZoom(50);
00065    *
00066    *
00067    * // take pictures all around... (at 1/2 degree steps...)
00068    * for (a=0;a<5*2.0*lti::Pi;a+=0.5*lti::Pi/180.0) {
00069    *   canvas.fill(lti::Black);
00070    *   drawer.resetDeepCtrl(true); // activate the z-Buffering
00071    *   drawer.setCamera(1.5*sin(a),1.5*cos(a),1,0,0,0);
00072 
00073    *   // draw a cube
00074    *   drawer.setColor(lti::White);
00075 
00076    *   // draw the lower plate
00077    *   drawer.set3D(1,1,-1);
00078    *   drawer.line3DTo(-1,1,-1);
00079    *   drawer.line3DTo(-1,-1,-1);
00080    *   drawer.line3DTo(1,-1,-1);
00081    *   drawer.line3DTo(1,1,-1);
00082 
00083    *   // draw the upper plate
00084    *   drawer.set3D(1,1,1);
00085    *   drawer.line3DTo(-1,1,1);
00086    *   drawer.line3DTo(-1,-1,1);
00087    *   drawer.line3DTo(1,-1,1);
00088    *   drawer.line3DTo(1,1,1);
00089    *
00090    *   // and the edges
00091    *   drawer.setColor(lti::Red);
00092    *   drawer.line3D(-1, 1,1,-1, 1,-1);
00093    *   drawer.setColor(lti::Green);
00094    *   drawer.line3D(-1,-1,1,-1,-1,-1);
00095    *   drawer.setColor(lti::Blue);
00096    *   drawer.line3D( 1,-1,1, 1,-1,-1);
00097    *   drawer.setColor(lti::Yellow);
00098    *   drawer.line3D( 1, 1,1, 1, 1,-1);
00099 
00100    *   view.show(canvas);
00101    * }
00102    * \endcode
00103    *
00104    * See also draw3D<T>::parameters for more information about the camera
00105    * parameters.
00106    */
00107   template<class T>
00108   class draw3D : public draw<T> {
00109   public:
00110 
00111     /**
00112      * return a grey value for the proper type T, where the input
00113      * is always between 0 (black) and 1 (white).
00114      */
00115     static T getGray(const float& val);
00116 
00117     /**
00118      * homogene matrix
00119      *
00120      * Due to a MSVC bug the implementation of the class must be here.
00121      */
00122     class hmatrix {
00123     public:
00124       /**
00125        * default constructor
00126        */
00127       hmatrix() {
00128         clear();
00129       };
00130 
00131       /**
00132        * copy constructor
00133        */
00134       hmatrix(const hmatrix& other) {
00135         copy(other);
00136       }
00137 
00138       /**
00139        * destructor
00140        */
00141       ~hmatrix() {
00142       };
00143 
00144       /**
00145        * clean matrix
00146        */
00147       void clear() {
00148         for (int i=0;i<3;i++)
00149           for (int j=0;j<4;j++)
00150             at(i,j) = 0.0;
00151       };
00152 
00153       /**
00154        * multiply with a point
00155        */
00156       dpoint3D operator*(const dpoint3D& p) const {
00157         dpoint3D temp;
00158 
00159         const hmatrix &m = (*this);
00160 
00161         temp.x = m.at(0,0)*p.x + m.at(0,1)*p.y + m.at(0,2)*p.z + m.at(0,3);
00162         temp.y = m.at(1,0)*p.x + m.at(1,1)*p.y + m.at(1,2)*p.z + m.at(1,3);
00163         temp.z = m.at(2,0)*p.x + m.at(2,1)*p.y + m.at(2,2)*p.z + m.at(2,3);
00164 
00165         return temp;
00166       };
00167 
00168       /**
00169        * return value at row m and column n
00170        */
00171       double &at(const int m,const int n) {return mem[m][n];};
00172 
00173       /**
00174        * return value a row m and column n
00175        */
00176       const double &at(const int m,const int n) const {return mem[m][n];};
00177 
00178       /**
00179        * copy member
00180        */
00181       hmatrix& copy(const hmatrix& other) {
00182         int j,i;
00183         for (j=0;j<3;++j) {
00184           for (i=0;i<4;++i) {
00185             mem[j][i] = other.mem[j][i];
00186           }
00187         }
00188         return *this;
00189       }
00190 
00191       /**
00192        * alias for copy member
00193        */
00194       hmatrix& operator=(const hmatrix& other) {
00195         return copy(other);
00196       }
00197 
00198     protected:
00199       double mem[3][4];
00200     };
00201 
00202 
00203     /**
00204      * parameters for draw3D.
00205      *
00206      * Most of the parameters in this class can be accessed through access
00207      * methods in the class draw3D directly.  This simplifies changing
00208      * the parameters and giving them to the drawer object again.
00209      *
00210      * The camera position is given by the <code>cam1</code> point.
00211      * The direction of the camera is given through the second point
00212      * <code>cam2</code>.  The projective algorithm used will ensure that
00213      * this second point cam2 will be mapped exactly at the position given
00214      * by <code>center</code>.
00215      */
00216     class parameters : public ioObject {
00217     public:
00218       /**
00219        * default constructor
00220        */
00221       parameters()
00222         : zoom(1.0),perspective(0.0),center(0.5,0.5),
00223           camPos(0.0,0.0,1.0),elevation(0.0),azimuth(0.0),
00224           lightPosition(0,0,1000000),
00225           diffuseColor(draw3D<T>::getGray(223.0f/255.0f)),
00226           ambientColor(draw3D<T>::getGray(32.0f/255.0f)) {
00227       };
00228 
00229       /**
00230        * copy constructor
00231        */
00232       parameters(const parameters& other) 
00233         : ioObject() {
00234         copy(other);
00235       }
00236 
00237       /**
00238        * returns the name of this type
00239        */
00240       virtual const char* getTypeName() const {
00241         return "draw3D::parameters";
00242       };
00243 
00244       /**
00245        * copy member
00246        */
00247       parameters& copy(const parameters& other) {
00248         camPos = other.camPos;
00249         elevation = other.elevation;
00250         azimuth = other.azimuth;
00251         zoom = other.zoom;
00252         perspective = other.perspective;
00253         center = other.center;
00254         lightPosition = other.lightPosition;
00255         diffuseColor = other.diffuseColor;
00256         ambientColor = other.ambientColor;
00257         return *this;
00258       };
00259 
00260       /**
00261        * alias for copy member
00262        */
00263       parameters& operator=(const parameters& other) {
00264         return copy(other);
00265       }
00266 
00267       /**
00268        * returns a pointer to a clone of the parameters.
00269        */
00270       virtual parameters* clone() const {
00271         return new parameters(*this);
00272       };
00273 
00274       /**
00275        * write the parameters in the given ioHandler
00276        * @param handler the ioHandler to be used
00277        * @param complete if true (the default) the enclosing begin/end will
00278        *        be also written, otherwise only the data block will be written.
00279        * @return true if write was successful
00280        */
00281       virtual bool write(ioHandler& handler,const bool complete=true) const {
00282         bool b=true;
00283 
00284         if (complete) {
00285           b=handler.writeBegin();
00286         }
00287 
00288         if (b) {
00289           lti::write(handler,"camPos",camPos);
00290           lti::write(handler,"elevation",elevation);
00291           lti::write(handler,"azimuth",azimuth);
00292           lti::write(handler,"zoom",zoom);
00293           lti::write(handler,"perspective",perspective);
00294           lti::write(handler,"center",center);
00295           lti::write(handler,"lightPosition",lightPosition);
00296           lti::write(handler,"diffuseColor",diffuseColor);
00297           lti::write(handler,"ambientColor",ambientColor);
00298         }
00299 
00300         if (complete) {
00301           b=b && handler.writeEnd();
00302         }
00303 
00304         return b;
00305       };
00306 
00307       /**
00308        * read the parameters from the given ioHandler
00309        * @param handler the ioHandler to be used
00310        * @param complete if true (the default) the enclosing begin/end will
00311        *        be also written, otherwise only the data block will be written.
00312        * @return true if write was successful
00313        */
00314       virtual bool read(ioHandler& handler,const bool complete=true) {
00315         bool b=true;
00316 
00317         if (complete) {
00318           b=handler.readBegin();
00319         }
00320 
00321         if (b) {
00322           lti::read(handler,"camPos",camPos);
00323           lti::read(handler,"elevation",elevation);
00324           lti::read(handler,"azimuth",azimuth);
00325           lti::read(handler,"zoom",zoom);
00326           lti::read(handler,"perspective",perspective);
00327           lti::read(handler,"center",center);
00328           lti::read(handler,"lightPosition",lightPosition);
00329           lti::read(handler,"diffuseColor",diffuseColor);
00330           lti::read(handler,"ambientColor",ambientColor);
00331         }
00332 
00333         if (complete) {
00334           b=b && handler.readEnd();
00335         }
00336 
00337         return b;
00338       };
00339 
00340       /**
00341        * set position and target position of the camera
00342        */
00343       void setCamera(const double& x1,const double& y1,const double& z1,
00344                      const double& x2,const double& y2,const double& z2) {
00345 
00346 
00347         double dx,dy,dz;
00348         double dx2,dy2,dz2;
00349         double alpha,beta,cosalpha,cosbeta;
00350 
00351         dx = x1-x2;
00352         dy = y1-y2;
00353         dz = z1-z2;
00354 
00355         dx2 = dx*dx;
00356         dy2 = dy*dy;
00357         dz2 = dz*dz;
00358 
00359         if ((dx2+dy2) != 0) {
00360           cosalpha = dx/(sqrt(dx2+dy2));
00361           alpha = abs(acos(cosalpha));
00362           if (dy<0) {
00363             alpha *= -1.0;
00364           }
00365         }
00366         else {
00367           cosalpha = 1.0;
00368           alpha = 0;
00369         }
00370 
00371         if ((dx2+dy2+dz2) != 0) {
00372           cosbeta = sqrt((dx2+dy2)/(dx2+dy2+dz2));
00373           beta  = abs(acos(cosbeta));
00374           if (dz<0) {
00375             beta *= -1.0;
00376           }
00377         }
00378         else {
00379           cosbeta = 1.0;
00380           beta  = 0;
00381         }
00382 
00383         setCamera(x2,y2,z2,(Pi/2.0) - beta,alpha);
00384       }
00385 
00386       /**
00387        * set position and direction of the camera
00388        */
00389       void setCamera(const double& x1,const double& y1,const double& z1,
00390                      const double& theElevation,const double& theAzimuth) {
00391         camPos.copy(dpoint3D(x1,y1,z1));
00392         elevation = theElevation;
00393         azimuth = theAzimuth;
00394       }
00395 
00396       /**
00397        * set position and target position of the camera
00398        */
00399       void setCamera(const dpoint3D& x1,
00400                      const dpoint3D& x2) {
00401         setCamera(x1.x,x1.y,x1.z,x2.x,x2.y,x2.z);
00402       }
00403 
00404       /**
00405        * set position and direction of the camera
00406        */
00407       void setCamera(const dpoint3D& x1,
00408                      const double& theElevation,const double& theAzimuth) {
00409         camPos.copy(x1);
00410         elevation = theElevation;
00411         azimuth = theAzimuth;
00412       }
00413 
00414       // ------------------------------------------------------
00415       // the parameters
00416       // ------------------------------------------------------
00417 
00418       /**
00419        * camera zoom factor (default value: 1.0)
00420        */
00421       double zoom;
00422 
00423       /**
00424        * camera perspective factor.  Set to zero for an orthographic
00425        * projection or greater zero for perspective effects.  You
00426        * can consider this value as zoom/f with f the focal distance.
00427        */
00428       double perspective;
00429 
00430       /**
00431        * view plane center in relative coordinates (default (0.5,0.5), i.e.
00432        * in the center of the used image)
00433        */
00434       dpoint center;
00435 
00436       /**
00437        * camera position (default value: (0,0,1))
00438        */
00439       dpoint3D camPos;
00440 
00441       /**
00442        * elevation is the angle (in radians) between the z-axis and
00443        * the camera axis.
00444        *
00445        * Default value: 0.0
00446        */
00447       double elevation;
00448 
00449       /**
00450        * azimuth is the angle (in radians) between the x-axis and the
00451        * projection of the camera axis on the xy plane.
00452        *
00453        * Default value: 0.0
00454        */
00455       double azimuth;
00456 
00457       /**
00458        * position of the light source.
00459        */
00460       dpoint3D lightPosition;
00461 
00462       /**
00463        * Color (or intensity) of the light source.
00464        *
00465        * To avoid saturation ensure that diffuseColor+ambientColor is smaller
00466        * than the maximum allowed value for T (i.e. 255 for ubyte,
00467        * rgbPixel(255,255,255) or 1.0 for float)
00468        */
00469       T diffuseColor;
00470 
00471       /**
00472        * Color (or intensity) of the ambient light
00473        *
00474        * To avoid saturation ensure that diffuseColor+ambientColor is smaller
00475        * than the maximum allowed value for T (i.e. 255 for ubyte,
00476        * rgbPixel(255,255,255) or 1.0 for float)
00477        */
00478       T ambientColor;
00479     };
00480 
00481 
00482   public:
00483     /**
00484      * default constructor
00485      */
00486     draw3D();
00487     /**
00488      * destructor
00489      */
00490     ~draw3D();
00491 
00492     /**
00493      * return the name of the this object
00494      */
00495     virtual const char* getTypeName() const;
00496 
00497     /**
00498      * Indicates in which image will be drawn
00499      */
00500     void use(matrix<T>& img);
00501 
00502     /**
00503      * set parameters
00504      */
00505     bool setParameters(const parameters& opt);
00506 
00507     /**
00508      * get parameters
00509      */
00510     const parameters& getParameters() const {return param;};
00511 
00512     /**
00513      * get parameters
00514      */
00515     parameters& getParameters() {return param;};
00516 
00517     /**
00518      * set position and target position of the camera
00519      */
00520     void setCamera(const double& x1,const double& y1,const double& z1,
00521                    const double& x2,const double& y2,const double& z2);
00522 
00523     /**
00524      * set position and direction of the camera
00525      */
00526     void setCamera(const double& x1,const double& y1,const double& z1,
00527                    const double& elevation,const double& azimuth);
00528 
00529     /**
00530      * set position and target position of the camera
00531      */
00532     void setCamera(const dpoint3D& x1,
00533                    const dpoint3D& x2);
00534 
00535     /**
00536      * set position and direction of the camera
00537      */
00538     void setCamera(const dpoint3D& x1,
00539                    const double& elevation,const double& azimuth);
00540 
00541     /**
00542      * set perspective.  Set to zero for an orthographic projection or
00543      * greater zero for perspective effects.  You can consider this value
00544      * as -1/f with f the focal distance.  So, to get good results try always
00545      * positive values
00546      */
00547     void setPerspective(const double& p);
00548 
00549     /**
00550      * set camera plane center.
00551      *
00552      * These are relative coordinates, i.e. if you want to map the
00553      * target camera point <code>cam2</code> (see parameters) exactly
00554      * at the center of your image, just setCenter(0.5,0.5).
00555      */
00556     void setCenter(const double& x,const double& y);
00557 
00558     /**
00559      * set camera plane center
00560      *
00561      * These are relative coordinates, i.e. if you want to map the
00562      * target camera point <code>cam2</code> (see parameters) exactly
00563      * at the center of your image, just setCenter(0.5,0.5).
00564      */
00565     void setCenter(const dpoint& x);
00566 
00567     /**
00568      * set zoom factor
00569      */
00570     void setZoom(const double& z);
00571 
00572     /**
00573      * get a read-only reference to the coordinate point in the current image,
00574      * where the origin of the world coordinates will be projected.
00575      */
00576     dpoint getOriginPosition() const;
00577 
00578     /**
00579      * get a read-only reference of the transformation matrix being used.
00580      */
00581     const hmatrix& getCameraMatrix() const;
00582 
00583     /**
00584      * reset z-Buffer.  With this method you can activate/deactivate
00585      * the z-Buffering.  This allows the correct display of your
00586      * drawings.  Note that if you resize the used image (see use()),
00587      * this object will not be able to detect it automatically (this
00588      * would take too much time!) and your program could crash!  To
00589      * avoid problems, call again one of <code>use</code> or
00590      * <code>resetDeepCtrl</code>methods after resizing your image.
00591      *
00592      * @param deep if true, the z-Buffering will be activated,
00593      * otherwise the z-Buffering will be deactivated.
00594      */
00595     void resetDeepCtrl(const bool deep=true);
00596 
00597     /**
00598      * project 3D point into camera plane
00599      */
00600     void p3Dto2D(const double& x,const double& y,const double& z,
00601                  int &x2,int &y2,double &z2) const;
00602 
00603     /**
00604      * project 3D point into camera plane
00605      */
00606     void p3Dto2D(const dpoint3D& p3,point& p2,double &z2) const;
00607 
00608     /**
00609      * sets point with selected color
00610      */
00611     void set3D(const dpoint3D& p);
00612 
00613     /**
00614      * sets 2D point with the selected color if it is in front of
00615      * all other points with the same projection coordinates, considering
00616      * the z-buffering (if enabled) and the given z coordinate.
00617      *
00618      * If the z-buffering is disabled, the pixel at (x,y) will be set.
00619      * @param x position x
00620      * @param y position y
00621      * @param z deep information
00622      */
00623     void set2D(const int& x,const int& y,const double& z);
00624 
00625     /**
00626      * sets marker with selected style
00627      */
00628     void marker3D(const double& x,const double& y,const double& z);
00629 
00630     /**
00631      * sets marker with given style
00632      */
00633     void marker3D(const double& x,
00634                   const double& y,
00635                   const double& z,
00636                   const char* style);
00637 
00638     /**
00639      * sets point with selected color
00640      */
00641     void set3D(const double& x,const double& y,const double& z);
00642 
00643     /**
00644      * sets point with selected color
00645      */
00646     template<class U>
00647     void set3D(const hPoint3D<U>& p) {
00648       set3D(p.x/p.h,p.y/p.h,p.z/p.h);
00649     };
00650 
00651     /**
00652      * draw a line between the last used point and (x,y,z)
00653      */
00654     void line3DTo(const double& x,const double& y,const double& z);
00655 
00656     /**
00657      * draw a line between the last used point and (x,y,z)
00658      */
00659     void line3DTo(const dpoint3D& p);
00660 
00661     /**
00662      * draw a line between a and b
00663      */
00664     void line3D(const dpoint3D& a,const dpoint3D& b);
00665 
00666     /**
00667      * draw a line between (x,y,z) and (x2,y2,z2)
00668      */
00669     void line3D(const double& x, const double& y, const double& z,
00670     const double& x2,const double& y2,const double& z2);
00671 
00672     /**
00673      * draw a box with the opposite corners a and b
00674      */
00675     void box(const dpoint3D& a,
00676              const dpoint3D& b, const bool filled=true);
00677 
00678     /**
00679      * draw a filled box of the actual color with the opposite corners a and b,
00680      * and with the line color given
00681      */
00682     void box(const dpoint3D& a,
00683              const dpoint3D& b,
00684              const T lineColor);
00685 
00686 
00687     /**
00688      * Draw an ellipsoid surface defined through a constant mahalanobis
00689      * distance between the mean vector and the points of the surface, i.e.
00690      * the surface contains all points that satisfy the equation
00691      * (x-mean)^T sigma^(-1)  (x-mean) = cst
00692      *
00693      * The color of the ellipsoid is given with the setColor() method, and
00694      * the lighting conditions with the parameter "lighting".
00695      *
00696      * @param mean point at the center of the ellipsoid.
00697      * @param sigma covariance matrix
00698      * @param cst mahalanobis distace from the points at the surface and the
00699      *            mean value
00700      */
00701     void ellipsoid(const vector<double> &mean,
00702                    const matrix<double> &sigma,
00703                    const double &cst);
00704 
00705 
00706     /**
00707      * Draw the given channel as a 3D structure, where the height of the
00708      * pixel is given by its intensity.  The actual color will be shaded
00709      * to produce the 3D effect.  The y-axis will be inverted, to convert the
00710      * image left coordinate system to the 3D right system.
00711      *
00712      * @param chnl the channel with the 3D information
00713      * @param height the height of the value 1.0 in the channel
00714      * @param gridSize the number of pixels used for a "cell" in the grid.
00715      *                 Use for example point(5,5)
00716      * @param sampleRate determines which pixels in the image are going
00717      *                   to be used in the grid points.  point(1,1) uses
00718      *                   all pixels, point(2,2) each second point and so on.
00719      * @param onlyPoints if true, only the points will be drawn, if false,
00720      *                   boxes or grids will be drawn.
00721      * @param useBoxes if true, boxes will be used to display each pixel,
00722      *                 otherwise a triangular mesh will be used.
00723      * @param heightColor if true, the channel intensity will define the grey
00724      *                    tone for the pixel, otherwise the actual color will
00725      *                    be used.
00726      * @param drawLines if true, the vertical lines at each grid point will
00727      *                  be drawn.
00728      * @param lineColor color for the vertical lines
00729      * @param drawContour if true, the contour of each triangle in the mesh
00730      *                    will be redrawn using the countour color given.
00731      * @param contourColor color used to draw the contour of the triangles.
00732      *                     Only used if drawContour is true
00733      */
00734     void set3D(const channel& chnl,
00735                const float& height,
00736                const point& gridSize = point(5,5),
00737                const point& sampleRate = point(1,1),
00738                const bool onlyPoints = false,
00739                const bool useBoxes = false,
00740                const bool heightColor = false,
00741                const bool drawLines = false,
00742                const T& lineColor = T(),
00743                const bool drawContour = false,
00744                const T& contourColor = T());
00745     
00746     /**
00747      * draw a grid with dimension "size" using the actual drawnig color.
00748      * The grid lies in all three dimensions at size/2. 
00749      */
00750     void grid(const double size,const int nbSteps);
00751 
00752     /**
00753      * draw axis with dimension "size"
00754      */
00755     void axis(const double size);
00756 
00757     /**
00758      * draw axis with dimension "size" and using the given color for each
00759      * axis
00760      */
00761     void axis(const double size,
00762               const T& colorX,
00763               const T& colorY,
00764               const T& colorZ);
00765 
00766 
00767   protected:
00768 
00769     /**
00770      * Triangle is the base for all other polygons.
00771      *
00772      * It is assumed, that the points are given in a "right system", to define
00773      * the normal of the triangle.  The color of the hidden face of the
00774      * triangle can be specified at construct time.
00775      */
00776     class triangle {
00777     public:
00778       /**
00779        * default constructor
00780        */
00781       triangle() {
00782       }
00783 
00784       /**
00785        * Access operator to the three points
00786        */
00787       dpoint3D& operator[](const int idx) {
00788         assert(idx < 3);
00789         return pts[idx];
00790       }
00791 
00792       /**
00793        * Access operator to the three points
00794        */
00795       const dpoint3D& operator[](const int idx) const {
00796         assert(idx < 3);
00797         return pts[idx];
00798       }
00799 
00800       /**
00801        * compute the normal of the triangle.  It will NOT be normalized
00802        */
00803       dpoint3D getNormal() const {
00804         dpoint3D a,b,n;
00805         a.subtract(pts[0],pts[2]);
00806         b.subtract(pts[1],pts[2]);
00807         n.x = a.y*b.z - a.z*b.y;
00808         n.y = a.z*b.x - a.x*b.z;
00809         n.z = a.x*b.y - a.y*b.x;
00810 
00811         return n;
00812       }
00813 
00814       /**
00815        * returns true if the triangle "positive" face is visible for the
00816        * given camera configuration
00817        */
00818       bool visible(const hmatrix& cam) const {
00819         dpoint3D n(getNormal());
00820         return ((cam.at(0,0)*n.x + cam.at(0,1)*n.y + cam.at(0,2)*n.z) >= 0);
00821       }
00822 
00823     protected:
00824       /**
00825        * data
00826        */
00827       dpoint3D pts[3];
00828     };
00829 
00830     void drawSymbol(double x, double y,double z);
00831 
00832     /**
00833      * parameters
00834      */
00835     parameters param;
00836 
00837     /**
00838      * true: use a Z-Buffer
00839      */
00840     bool deepCtrl;
00841 
00842     /**
00843      * Z-Buffer
00844      */
00845     matrix<float> deepImg;
00846 
00847     /**
00848      * actual (last used) 3D point coordinates
00849      */
00850     dpoint3D act;
00851 
00852     /**
00853      * camera homogene transformation matrix
00854      */
00855     hmatrix cam;
00856 
00857     /**
00858      * camera target point
00859      */
00860     dpoint3D camTarget;
00861 
00862     /**
00863      * camera plane center
00864      */
00865     dpoint center;
00866 
00867     /**
00868      * camera plane center in normalized coordinates (0..1)
00869      */
00870     dpoint precenter;
00871 
00872     /**
00873      * checks and corrects 3D line to be within the image
00874      */
00875     bool correctLine (int &x,int &y,double &z,
00876                       const int& x2, const int& y2, const double& z2);
00877 
00878     /**
00879      * compute the shading color from "color", assuming that the
00880      * light source is at z-axis in infinity, and the normal vector to the
00881      * surface is given.
00882      */
00883     T shadingColor(const dpoint3D& nrm,const T& color) const;
00884 
00885     /**
00886      * sets a triangle
00887      */
00888     void set3D(const triangle& t,const bool filled = true);
00889 
00890     /**
00891      * help function for triangle.  Draws a line as io codes in the
00892      * given lists.
00893      * This function expects p1.y <= p2.y
00894      */
00895     void ioLine(const point& p1,const double& z1,
00896                 const point& p2,const double& z2,
00897                 ivector& in, ivector& out,
00898                 dvector& zIn, dvector& zOut,
00899                 const int firstY) const;
00900 
00901     /**
00902      * copysign return abs(a) with the sign of b
00903      */
00904     inline double copysign(const double& a,const double& b);
00905 
00906     /**
00907      * returns 1 if a >= 0.0; -1 otherwise
00908      */
00909     inline int sign(const double& a) {return (a >= 0.0) ? 1 : -1;};
00910 
00911   private:
00912     /**
00913      * some internal variables needed for the 3D channel drawing
00914      */
00915     //@{
00916     const channel* mChannel;
00917     float mHeight;
00918     point mGridSize;
00919     point mSampleRate;
00920     bool mOnlyPoints;
00921     bool mUseBoxes;
00922     bool mHeightColor;
00923     bool mDrawLines;
00924     T mLineColor;
00925     bool mDrawContour;
00926     T mContourColor;
00927     //@}
00928 
00929     /**
00930      * draw a cell
00931      */
00932     void drawCell(const int x,const int y);
00933 
00934   };
00935 
00936   template<class T>
00937   inline double draw3D<T>::copysign(const double& a,const double& b) {
00938     return (sign(a)*sign(b))*a;
00939   }
00940 
00941   // --------------------------------------------------------------------------
00942   // Ray Tracing Objects
00943   // --------------------------------------------------------------------------
00944 
00945   // These are not internal classes of draw3D<> to avoid some bugs of
00946   // MS VC++ with template inner classes.
00947 
00948   /**
00949    * abstract class parent for all objects that can be ray-traced.
00950    *
00951    * All objects derived from this class are used internally in
00952    * lti::draw3D objects.
00953    */
00954   template <class T>
00955   class rayTraceObject : public object {
00956   public:
00957     /**
00958      * The constructor must receive the drawer object, where this
00959      * object will be draw.
00960      */
00961     rayTraceObject(draw3D<T>& drawer);
00962 
00963     /**
00964      * Compute the color value of the pixel at x,y
00965      * @param x x coordinate in the image
00966      * @param y y coordinate in the image
00967      * @param z2 z coordinate of the surface point belonging to the given
00968      *           pixel (required for the z-buffering).
00969      * @param val computed color (or gray) value for the given (x,y) pixel
00970      * @return true if the position corresponds to a pixel on the surface
00971      *              of the object.
00972      */
00973     virtual bool rayTrace(const int x,const int y,
00974                           double& z2,T& val) = 0;
00975 
00976     /**
00977      * render the whole object
00978      * @return true if something was drawn, of false otherwise.
00979      */
00980     virtual bool render() = 0;
00981 
00982     /**
00983      * return the name of the this object
00984      */
00985     virtual const char* getTypeName() const;
00986 
00987   protected:
00988     /**
00989      * Drawer object
00990      */
00991     draw3D<T>& drawer;
00992 
00993     /**
00994      * parameters of the drawer
00995      */
00996     const typename draw3D<T>::parameters& param;
00997 
00998     /**
00999      * camera homogene transformation matrix
01000      */
01001     typename draw3D<T>::hmatrix cam;
01002 
01003     /**
01004      * inverse camera rotation matrix of the drawer object
01005      */
01006     typename draw3D<T>::hmatrix camInv;
01007 
01008     /**
01009      * position of the projected origin of the world coordinates
01010      */
01011     dpoint center;
01012 
01013     /**
01014      * multiply ((a/norm) * (b/norm))*norm
01015      */
01016     T multiplyNormed(const T& a,const T& b) const;
01017 
01018     /**
01019      * add with clipping
01020      */
01021     T addSaturated(const T& a,const T& b) const;
01022 
01023     /**
01024      * compute the vector in world coordinates parallel to the ray
01025      * going through the focal point and the point (x,y) in the image plane.
01026      *
01027      * @param x image coordinate x
01028      * @param y image coordinate y
01029      * @param imgp position of the image point (x,y) (on the image plane) in
01030      *             the world coordinate system
01031      * @param ray  direction of the ray going through the point (x,y) and
01032      *             the focal point.
01033      */
01034     void p2Dto3D(const int& x,
01035                  const int& y,
01036                  dpoint3D& imgp,
01037                  dpoint3D& ray) const;
01038 
01039     /**
01040      * compute the inverse of the camera transformation matrix
01041      * (only the rotation part is created.  The result is left
01042      * in the attribute member camInv
01043      */
01044     void buildInverseCamera();
01045 
01046   };
01047 
01048   /**
01049    * Ray tracing object for ellipsoids
01050    */
01051   template<class T>
01052   class rayTraceEllipsoid : public rayTraceObject<T> {
01053   public:
01054     /**
01055      * The constructor must receive the drawer object, where this
01056      * object will be draw.
01057      */
01058     rayTraceEllipsoid(draw3D<T>& drawer);
01059 
01060     /**
01061      * The constructor must receive the drawer object, where this
01062      * object will be draw.
01063      *
01064      * @param drawer the drawer object where the ellipsoid will be drawn.
01065      * @param theMean mean point of the ellipsoid
01066      * @param covar covariance matrix used in the definition of the
01067      *              ellipsoid.  This should be a 3x3 symmetric positive
01068      *              definite matrix.
01069      * @param theMahDist mahalanobis distance using the given covariance
01070      *                   matrix between the mean point and the surface of
01071      *                   the ellipsoid.
01072      */
01073     rayTraceEllipsoid(draw3D<T>& drawer,
01074                       const dpoint3D& theMean,
01075                       const dmatrix& covar,
01076                       const double& theMahDist = 1);
01077 
01078     /**
01079      * set the parameters of the ellipsoid.
01080      *
01081      * @param theMean mean point of the ellipsoid
01082      * @param covar covariance matrix used in the definition of the
01083      *              ellipsoid. This should be a 3x3 symmetric positive
01084      *              definite matrix.
01085      * @param theMahDist mahalanobis distance using the given covariance
01086      *                   matrix between the mean point and the surface of
01087      *                   the ellipsoid.
01088      */
01089     void setEllipsoid(const dpoint3D& theMean,
01090                       const dmatrix& covar,
01091                       const double& theMahDist = 1);
01092     /**
01093      * Compute the value of the pixel at x,y
01094      * @param x x coordinate in the image
01095      * @param y y coordinate in the image
01096      * @param z2 z coordinate of the surface point belonging to the given
01097      *           pixel (required for the z-buffering).
01098      * @param val computed color (or gray) value for the given (x,y) pixel
01099      * @return true if the position corresponds to a pixel on the surface
01100      *              of the object.
01101      */
01102     virtual bool rayTrace(const int x,const int y,double& z2,T& val);
01103 
01104     /**
01105      * render the whole object.
01106      * @return true if something was drawn, of false otherwise
01107      */
01108     virtual bool render();
01109 
01110     /**
01111      * return the name of the this object
01112      */
01113     virtual const char* getTypeName() const;
01114 
01115   protected:
01116     /**
01117      * Given a point of the image plane in world coordinates and the
01118      * direction of a ray passing through the focal point and the
01119      * image point, compute the intersection of the ray and the
01120      * ellipsoid formed using a constant mahalanobis distance from
01121      * the mean value to the surface of the ellipsoid under
01122      * consideration of the given covariance matrix.
01123      *
01124      * @param ip point of the image plane in world coordinates
01125      *               (see p2Dto3D())
01126      * @param ray point describing the direction of a ray passing through the
01127      *            image point and the focal point
01128      * @param mu  mean value of the ellipsoid
01129      * @param sigma covariance matrix
01130      * @param mah mahalanobis distance between the ellipsoid surface and
01131      *            the mean value mu
01132      * @param lambda imgPnt + lambda*ray is the point on the ellipsoid
01133      *        surface to be considered
01134      * @param sp point at the surface of the ellipsoid
01135      * @return true if point was found, or false if the image point
01136      *              does not belong to the ellipsoid
01137      */
01138     bool intersectRayEllipsoid(const dpoint3D &ip,
01139                                const dpoint3D &ray,
01140                                const dpoint3D &mu,
01141                                const matrix<double> &sigma,
01142                                const double &mah,
01143                                double &lambda,
01144                                dpoint3D &sp);
01145 
01146     /**
01147      * compute the normal vector of an ellipsoid surface at a specific point
01148      */
01149     void calcNormal(const dpoint3D &intersectionPoint,
01150                     const dpoint3D &mu,
01151                     const matrix<double> &sigma,
01152                     dpoint3D &normal) const;
01153 
01154     /**
01155      * mean point of the ellipsoid
01156      */
01157     dpoint3D mean;
01158 
01159     /**
01160      * covariance matrix of the ellipsoid
01161      */
01162     dmatrix sigma;
01163 
01164     /**
01165      * inverse matrix of the covariance matrix
01166      */
01167     dmatrix invMat;
01168 
01169     /**
01170      * mahalanobis distance of the ellipsoid surface to the mean point
01171      * using the given covariance matrix
01172      */
01173     double mahDist;
01174 
01175     /**
01176      * current color of the ellipsoid
01177      */
01178     T storedColor;
01179 
01180   private:
01181     /** @name temporary variables
01182      */
01183     //@{
01184     /**
01185      * temporary variables declared as attributes to save some time
01186      * rendering the ellipsoid. (the code for which this variables
01187      * are required was generated automatically, that's the reason
01188      * why the names are so descriptive...)
01189      */
01190     double t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t16,t17,t18,t21,
01191       t22,t23,t24,t26,t27,t29,t30,t31,t32,t35,t46,t47,t48,t49,t50,t52,t54,
01192       t56,t57,t58,t61,t63,t65,t66,t69,t71,t73,t74,t76,t77,t81,t83,t85,t88,
01193       t91,t93,t96,t98,t99,t102,t104,t106,t108,t110,t114,t117,t119,t125,t127,
01194       t130,t138,t139,t141,t142,t144,t146,t158,t161,t168,t169,t179,t183,t205,
01195       t226;
01196 
01197     /**
01198      * image point
01199      */
01200     dpoint3D ip;
01201 
01202     /**
01203      * surface point
01204      */
01205     dpoint3D sp;
01206 
01207     /**
01208      * ray direction between focal point and surface point
01209      */
01210     dpoint3D ray;
01211 
01212     /**
01213      * normal vector to the ellipsoid surface
01214      */
01215     dpoint3D normal;
01216 
01217     /**
01218      * direction between light source and surface point
01219      */
01220     dpoint3D lDir;
01221 
01222     /**
01223      * temporary factors to find intersections
01224      */
01225     double lambda,cosL;
01226     //@}
01227   };
01228 
01229   // -------------------------------------------------------------------------
01230 
01231   /**
01232    * write the draw3D<>::parameters in the given ioHandler.
01233    * The complete flag indicates
01234    * if the enclosing begin and end should be also be written or not
01235    */
01236   inline bool write(ioHandler& handler,const draw3D<rgbPixel>::parameters& p,
01237              const bool complete = true) {
01238     return p.write(handler,complete);
01239   }
01240 
01241   inline bool write(ioHandler& handler,const draw3D<float>::parameters& p,
01242              const bool complete = true) {
01243     return p.write(handler,complete);
01244   }
01245 
01246   inline bool write(ioHandler& handler,const draw3D<ubyte>::parameters& p,
01247              const bool complete = true) {
01248     return p.write(handler,complete);
01249   }
01250 
01251   inline bool write(ioHandler& handler,const draw3D<double>::parameters& p,
01252              const bool complete = true) {
01253     return p.write(handler,complete);
01254   }
01255 
01256 
01257   /**
01258    * read the draw3D<>::parameters from the given ioHandler.
01259    * The complete flag indicates
01260    * if the enclosing begin and end should be also be written or not
01261    */
01262   inline bool read(ioHandler& handler,draw3D<rgbPixel>::parameters& p,
01263             const bool complete = true) {
01264     return p.read(handler,complete);
01265   }
01266 
01267   inline bool read(ioHandler& handler,draw3D<ubyte>::parameters& p,
01268             const bool complete = true) {
01269     return p.read(handler,complete);
01270   }
01271 
01272   inline bool read(ioHandler& handler,draw3D<float>::parameters& p,
01273             const bool complete = true) {
01274     return p.read(handler,complete);
01275   }
01276 
01277   inline bool read(ioHandler& handler,draw3D<double>::parameters& p,
01278             const bool complete = true) {
01279     return p.read(handler,complete);
01280   }
01281 
01282 
01283 
01284 }
01285 
01286 #endif

Generated on Sat Apr 10 15:25:23 2010 for LTI-Lib by Doxygen 1.6.1