transform3DTo2D.cpp

Go to the documentation of this file.
00001 
00015 #include <dlrNumeric/transform3DTo2D.h>
00016 
00017 namespace dlr {
00018 
00019   namespace numeric {
00020     
00021     // Build a Transform3D from a homogeneous 4x4 matrix.
00022     Transform3DTo2D::
00023     Transform3DTo2D(const Array2D<double>& source)
00024     {
00025       if((source.rows() != 3) || (source.columns() != 4)) {
00026         std::ostringstream message;
00027         message << "Can't create a Transform3DTo2D from a " << source.rows()
00028                 << " x " << source.columns() << "Array2D<double> instance.";
00029         DLR_THROW(ValueException, "Transform3DTo2D::Transform3DTo2D()",
00030                   message.str().c_str());
00031       }
00032       m_00 = source(0); m_01 = source(1); m_02 = source(2); m_03 = source(3);
00033       m_10 = source(4); m_11 = source(5); m_12 = source(6); m_13 = source(7);
00034       m_20 = source(8); m_21 = source(9); m_22 = source(10); m_23 = source(11);
00035 
00036     }
00037 
00038 
00039     // This member function returns a functor which makes it easier to
00040     // transform arrays of points using algorithms such as
00041     // std::transform().
00042     Transform3DTo2DFunctor
00043     Transform3DTo2D::
00044     getFunctor() const {
00045       return Transform3DTo2DFunctor(*this);
00046     }    
00047   
00048   
00049     // Change the Transform3DTo2D value by explicitly setting element values
00050     // as if setting the elements of a 4x4 transformation matrix:
00051     //    [[a00, a01, a02, a03],
00052     //     [a10, a11, a12, a13],
00053     //     [a20, a21, a22, a23],
00054     //     [a30, a31, a32, a33]]
00055     void
00056     Transform3DTo2D::
00057     setTransform(double a00, double a01, double a02, double a03,
00058                  double a10, double a11, double a12, double a13,
00059                  double a20, double a21, double a22, double a23)
00060     {
00061       m_00 = a00; m_01 = a01; m_02 = a02; m_03 = a03;
00062       m_10 = a10; m_11 = a11; m_12 = a12; m_13 = a13;
00063       m_20 = a20; m_21 = a21; m_22 = a22; m_23 = a23;
00064     }
00065 
00066     // This operator returns one element from the matrix
00067     // representation of the coordinate transform by reference.
00068 //   double&
00069 //   Transform3DTo2D::
00070 //   operator()(size_t row, size_t column)
00071 //   {
00072 //     switch(row) {
00073 //     case 0:
00074 //       switch(column) {
00075 //       case 0: return m_00; break;
00076 //       case 1: return m_01; break;
00077 //       case 2: return m_02; break;
00078 //       case 3: return m_03; break;
00079 //       default: break;
00080 //       }
00081 //       break;
00082 //     case 1:
00083 //       switch(column) {
00084 //       case 0: return m_10; break;
00085 //       case 1: return m_11; break;
00086 //       case 2: return m_12; break;
00087 //       case 3: return m_13; break;
00088 //       default: break;
00089 //       }
00090 //       break;
00091 //     case 2:
00092 //       switch(column) {
00093 //       case 0: return this->value<2, 0>(); break;
00094 //       case 1: return m_21; break;
00095 //       case 2: return m_22; break;
00096 //       default: break;
00097 //       }
00098 //       break;
00099 //     default:
00100 //       break;
00101 //     }
00102 //     std::ostringstream message;
00103 //     message << "Index (" << row << ", " << column << ") out of bounds.";
00104 //     DLR_THROW(IndexException, message.str().c_str());
00105 //     return m_00; // Dummy return to keep the compiler happy.
00106 //   }
00107       
00108     // This operator returns one element from the matrix
00109     // representation of the coordinate transform by value.
00110     double
00111     Transform3DTo2D::
00112     operator()(size_t row, size_t column) const
00113     {
00114       // // Avoid ugly duplication of code using ugly const_cast.
00115       // return const_cast<Transform3DTo2D*>(this)->operator()(row, column);
00116       switch(row) {
00117       case 0:
00118         switch(column) {
00119         case 0: return m_00; break;
00120         case 1: return m_01; break;
00121         case 2: return m_02; break;
00122         case 3: return m_03; break;
00123         default: break;
00124         }
00125         break;
00126       case 1:
00127         switch(column) {
00128         case 0: return m_10; break;
00129         case 1: return m_11; break;
00130         case 2: return m_12; break;
00131         case 3: return m_13; break;
00132         default: break;
00133         }
00134         break;
00135       case 2:
00136         switch(column) {
00137         case 0: return this->value<2, 0>(); break;
00138         case 1: return m_21; break;
00139         case 2: return m_22; break;
00140         case 3: return m_23; break;
00141         default: break;
00142         }
00143         break;
00144       default:
00145         break;
00146       }
00147       std::ostringstream message;
00148       message << "Indices (" << row << ", " << column << ") are out of bounds.";
00149       DLR_THROW(IndexException, "Transform3DTo2D::operator()(size_t, size_t)",
00150                 message.str().c_str());
00151       return 0.0; // Dummy return to keep the compiler happy.
00152     }
00153   
00154     // This operator takes a point and applies the coordinate
00155     // transform, returning the result.
00156     Vector2D
00157     Transform3DTo2D::
00158     operator*(const Vector3D& vector0) const
00159     {
00160       return Vector2D(
00161         m_00 * vector0.x() + m_01 * vector0.y() + m_02 * vector0.z() + m_03,
00162         m_10 * vector0.x() + m_11 * vector0.y() + m_12 * vector0.z() + m_13,
00163         m_20 * vector0.x() + m_21 * vector0.y() + m_22 * vector0.z() + m_23);
00164     }
00165 
00166     // The assignment operator simply duplicates its argument.
00167     Transform3DTo2D&
00168     Transform3DTo2D::
00169     operator=(const Transform3DTo2D& source)
00170     {
00171       m_00 = source.m_00; m_01 = source.m_01;
00172       m_02 = source.m_02; m_03 = source.m_03;
00173       m_10 = source.m_10; m_11 = source.m_11;
00174       m_12 = source.m_12; m_13 = source.m_13;
00175       m_20 = source.m_20; m_21 = source.m_21;
00176       m_22 = source.m_22; m_23 = source.m_23;
00177       return *this;
00178     }
00179 
00180     void
00181     Transform3DTo2D::
00182     normalize(double scaleFactor)
00183     {
00184       if((scaleFactor != 1.0) && (scaleFactor != 0.0)) {
00185         m_00 /= scaleFactor;
00186         m_01 /= scaleFactor;
00187         m_02 /= scaleFactor;
00188         m_03 /= scaleFactor;
00189         m_10 /= scaleFactor;
00190         m_11 /= scaleFactor;
00191         m_12 /= scaleFactor;
00192         m_13 /= scaleFactor;
00193         m_20 /= scaleFactor;
00194         m_21 /= scaleFactor;
00195         m_22 /= scaleFactor;
00196         m_23 = 1.0;
00197       }
00198     }
00199 
00200 
00201     /* ================ Non member functions below ================ */
00202 
00203 
00204     // This operator composes a Transform3DTo2D instance with a Transform3D
00205     // instance.
00206     Transform3DTo2D
00207     operator*(const Transform3DTo2D& transform0, const Transform3D& transform1)
00208     {
00209       double a00 = (transform0.value<0, 0>() * transform1.value<0, 0>()
00210                     + transform0.value<0, 1>() * transform1.value<1, 0>()
00211                     + transform0.value<0, 2>() * transform1.value<2, 0>()
00212                     + transform0.value<0, 3>() * transform1.value<3, 0>());
00213       double a01 = (transform0.value<0, 0>() * transform1.value<0, 1>()
00214                     + transform0.value<0, 1>() * transform1.value<1, 1>()
00215                     + transform0.value<0, 2>() * transform1.value<2, 1>()
00216                     + transform0.value<0, 3>() * transform1.value<3, 1>());
00217       double a02 = (transform0.value<0, 0>() * transform1.value<0, 2>()
00218                     + transform0.value<0, 1>() * transform1.value<1, 2>()
00219                     + transform0.value<0, 2>() * transform1.value<2, 2>()
00220                     + transform0.value<0, 3>() * transform1.value<3, 2>());
00221       double a03 = (transform0.value<0, 0>() * transform1.value<0, 3>()
00222                     + transform0.value<0, 1>() * transform1.value<1, 3>()
00223                     + transform0.value<0, 2>() * transform1.value<2, 3>()
00224                     + transform0.value<0, 3>() * transform1.value<3, 3>());
00225       double a10 = (transform0.value<1, 0>() * transform1.value<0, 0>()
00226                     + transform0.value<1, 1>() * transform1.value<1, 0>()
00227                     + transform0.value<1, 2>() * transform1.value<2, 0>()
00228                     + transform0.value<1, 3>() * transform1.value<3, 0>());
00229       double a11 = (transform0.value<1, 0>() * transform1.value<0, 1>()
00230                     + transform0.value<1, 1>() * transform1.value<1, 1>()
00231                     + transform0.value<1, 2>() * transform1.value<2, 1>()
00232                     + transform0.value<1, 3>() * transform1.value<3, 1>());
00233       double a12 = (transform0.value<1, 0>() * transform1.value<0, 2>()
00234                     + transform0.value<1, 1>() * transform1.value<1, 2>()
00235                     + transform0.value<1, 2>() * transform1.value<2, 2>()
00236                     + transform0.value<1, 3>() * transform1.value<3, 2>());
00237       double a13 = (transform0.value<1, 0>() * transform1.value<0, 3>()
00238                     + transform0.value<1, 1>() * transform1.value<1, 3>()
00239                     + transform0.value<1, 2>() * transform1.value<2, 3>()
00240                     + transform0.value<1, 3>() * transform1.value<3, 3>());
00241       double a20 = (transform0.value<2, 0>() * transform1.value<0, 0>()
00242                     + transform0.value<2, 1>() * transform1.value<1, 0>()
00243                     + transform0.value<2, 2>() * transform1.value<2, 0>()
00244                     + transform0.value<2, 3>() * transform1.value<3, 0>());
00245       double a21 = (transform0.value<2, 0>() * transform1.value<0, 1>()
00246                     + transform0.value<2, 1>() * transform1.value<1, 1>()
00247                     + transform0.value<2, 2>() * transform1.value<2, 1>()
00248                     + transform0.value<2, 3>() * transform1.value<3, 1>());
00249       double a22 = (transform0.value<2, 0>() * transform1.value<0, 2>()
00250                     + transform0.value<2, 1>() * transform1.value<1, 2>()
00251                     + transform0.value<2, 2>() * transform1.value<2, 2>()
00252                     + transform0.value<2, 3>() * transform1.value<3, 2>());
00253       double a23 = (transform0.value<2, 0>() * transform1.value<0, 3>()
00254                     + transform0.value<2, 1>() * transform1.value<1, 3>()
00255                     + transform0.value<2, 2>() * transform1.value<2, 3>()
00256                     + transform0.value<2, 3>() * transform1.value<3, 3>());
00257       return Transform3DTo2D(a00, a01, a02, a03,
00258                              a10, a11, a12, a13,
00259                              a20, a21, a22, a23);
00260     }
00261 
00262 
00263     std::ostream&
00264     operator<<(std::ostream& stream, const Transform3DTo2D& transform0)
00265     {
00266       stream << "Transform3DTo2D("
00267              << transform0.value<0, 0>() << ", "
00268              << transform0.value<0, 1>() << ", "
00269              << transform0.value<0, 2>() << ", "
00270              << transform0.value<0, 3>() << ",\n"
00271              << transform0.value<1, 0>() << ", "
00272              << transform0.value<1, 1>() << ", "
00273              << transform0.value<1, 2>() << ", "
00274              << transform0.value<1, 3>() << ",\n"
00275              << transform0.value<2, 0>() << ", "
00276              << transform0.value<2, 1>() << ", "
00277              << transform0.value<2, 2>() << ", "
00278              << transform0.value<2, 3>() << ")";
00279       return stream;
00280     }
00281 
00282     
00283     std::istream&
00284     operator>>(std::istream& stream, Transform3DTo2D& transform0)
00285     {
00286       // If stream is in a bad state, we can't read from it.
00287       if (!stream){
00288         return stream;
00289       }
00290     
00291       // It's a lot easier to use a try block than to be constantly
00292       // testing whether the IO has succeeded, so we tell stream to
00293       // complain if anything goes wrong.
00294       std::ios_base::iostate oldExceptionState = stream.exceptions();
00295       stream.exceptions(
00296         std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit);
00297 
00298       // Now on with the show.
00299       try{
00300         // Construct an InputStream instance so we can use our
00301         // convenience functions.
00302         InputStream inputStream(stream);
00303 
00304         // Advance to the next relevant character.
00305         inputStream.skipWhiteSpace();
00306       
00307         // Read the header.
00308         inputStream.expect("Transform3DTo2D(");
00309 
00310         // Read all the data except the last element.
00311         std::vector<double> inputValues(12);
00312         for(size_t index = 0; index < (inputValues.size() - 1); ++index) {
00313           // Read the value.
00314           inputStream >> inputValues[index];
00315 
00316           // Read punctuation before the next value.
00317           inputStream.expect(",");
00318         }
00319 
00320         // Read the final value.
00321         inputStream >> inputValues[inputValues.size() - 1];
00322 
00323         // Read the closing parenthesis.
00324         inputStream.expect(")");
00325 
00326         // And update the transform.
00327         transform0.setTransform(inputValues[0], inputValues[1],
00328                                 inputValues[2], inputValues[3], 
00329                                 inputValues[4], inputValues[5], 
00330                                 inputValues[6], inputValues[7], 
00331                                 inputValues[8], inputValues[9], 
00332                                 inputValues[10], inputValues[11]);
00333       } catch(std::ios_base::failure) {
00334         // Empty
00335       }
00336       stream.exceptions(oldExceptionState);
00337       return stream;
00338     }
00339 
00340   } // namespace numeric
00341 
00342 } // namespace dlr

Generated on Wed Nov 25 00:42:43 2009 for dlrUtilities Utility Library by  doxygen 1.5.8