HyperspaceExplorer 0.7.1
Rotate.h
00001 /*
00002 Hyperspace Explorer - visualizing higher-dimensional geometry
00003 Copyright (C) 2009-2010  Lene Preuss <lene.preuss@gmail.com>
00004 
00005 This program is free software; you can redistribute it and/or modify
00006 it under the terms of the GNU General Public License as published by
00007 the Free Software Foundation; either version 2 of the License, or
00008 (at your option) any later version.
00009 
00010 This program is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 GNU General Public License for more details.
00014 
00015 You should have received a copy of the GNU General Public License along
00016 with this program; if not, write to the Free Software Foundation, Inc.,
00017 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00018 
00019 */
00020 
00021 #ifndef ROTATE_H
00022 #define ROTATE_H
00023 
00024 #include "Rotope.h"
00025 
00026 #include "MultiDimensionalVector.h"
00027 
00029 
00033 template <unsigned D>
00034     class rotate_base: public VertexData<D> {
00035 
00036     public:
00038         rotate_base(const VertexData<D> &v): VertexData<D>(v) { }
00039 
00041         void rotate(unsigned d);
00042 
00043     private:
00045         void checkRotationArguments(unsigned d);
00046 
00048         VecMath::Vector<D> rotate_vertex(const VecMath::Vector<D> &, double,
00049                                          unsigned, unsigned);
00051         void rotate_line(unsigned);
00053         void rotate_triangle(unsigned, const VecMath::MultiDimensionalVector<unsigned, 1> &);
00055         void rotate_quad(unsigned, const VecMath::MultiDimensionalVector<unsigned, 1> &);
00057         void rotate_polygon(unsigned, const VecMath::MultiDimensionalVector<unsigned, 1> &);
00058     };
00059 
00061 
00091 template <unsigned D, unsigned Dmin, unsigned Dmax>
00092     class Rotate: public Rotate<D, Dmin, Dmax-1> {
00093     public:
00095 
00101         Rotate(const VertexData<D> &v): Rotate<D, Dmin, Dmax-1>(v) {
00102             rotate_base<D>::rotate(Dmax);
00103         }
00104 
00105     };
00106 
00108 
00114 template <unsigned D, unsigned Dmin>
00115     class Rotate<D, Dmin, Dmin>: public rotate_base<D> {
00116     public:
00118 
00123         Rotate(const VertexData<D> &v): rotate_base<D>(v) {
00124             rotate_base<D>::rotate(Dmin);
00125         }
00126 
00127     };
00128 
00139 template <unsigned D> void rotate_base<D>::rotate(unsigned d) {
00140 #   if DEBUG_ROTOPES
00141         SingletonLog::Instance().log(__PRETTY_FUNCTION__);
00142 #   endif
00143 
00144     checkRotationArguments(d);
00145 
00146     std::vector<VecMath::Vector<D> > Xold = VertexData<D>::raw_vertices();
00147     for (unsigned i = 1; i <= RotopeInterface::_numSegments; ++i) {
00148         double rot = 1.*i*M_PI/RotopeInterface::_numSegments;
00149         for (typename std::vector<VecMath::Vector<D> >::iterator j = Xold.begin();
00150              j != Xold.end(); ++j) {
00151                  VertexData<D>::raw_vertices().push_back(rotate_vertex(*j, rot, d, d-1));
00152         }
00153     }
00154 
00155     VertexData<D>::dimension()++;   //  object is now one dimension higher
00156 
00157     VertexData<D>::realm() = VertexData<D>::realm().rotated(RotopeInterface::_numSegments, Xold.size());
00158 }
00159 
00160 template <unsigned D> void rotate_base<D>::checkRotationArguments(unsigned d) {
00161     if (d >= D) {
00162         throw std::invalid_argument(
00163            "rotate_base::rotate() called on a higher dimension"
00164            " than the vector space allows");
00165     }
00166     if (d == 0) {
00167         throw std::invalid_argument(
00168                 "rotate_base::rotate() must be called on an object of dimension"
00169                 " at least 1");
00170     }
00171 }
00172 
00178 template <unsigned D> VecMath::Vector<D> rotate_base<D>::rotate_vertex(
00179         const VecMath::Vector<D> &v, double rot,
00180         unsigned new_axis, unsigned old_axis) {
00181 #   if DEBUG_ROTOPES >= 2
00182         SingletonLog::Instance().log(__PRETTY_FUNCTION__);
00183 #   endif
00184     VecMath::Vector<D> v_new(v);
00185     v_new[new_axis] = v_new[old_axis]*sin(rot);
00186     v_new[old_axis] *= cos(rot);
00187     return v_new;
00188 }
00189 
00193 template <unsigned D> void rotate_base<D>::rotate_line(unsigned d) {
00194 #   if DEBUG_ROTOPES
00195         SingletonLog::Instance().log(__PRETTY_FUNCTION__);
00196 #   endif
00197     VecMath::MultiDimensionalVector<unsigned, 1> new_surface; // defines the disk
00198     new_surface.push_back(0);
00199     VertexData<D>::raw_vertices().pop_back();
00200     for (unsigned i = 1; i <= RotopeInterface::_numSegments; ++i) {
00201         double rot = 2.*i*M_PI/RotopeInterface::_numSegments;
00202         VecMath::Vector<D> current = VertexData<D>::raw_vertices()[0];
00203         VecMath::Vector<D> rotated_current = rotate_vertex(current, rot,
00204                                                             d, d-1);
00205         VertexData<D>::raw_vertices().push_back(rotated_current);
00206         new_surface.push_back(VertexData<D>::raw_vertices().size()-1);
00207     }
00208     VertexData<D>::surface().push_back(new_surface);
00209 }
00210 
00215 template <unsigned D> void rotate_base<D>::rotate_triangle(
00216         unsigned d, const VecMath::MultiDimensionalVector<unsigned, 1> &current_surface) {
00217 
00218 #   if DEBUG_ROTOPES
00219         SingletonLog::Instance().log(__PRETTY_FUNCTION__);
00220 #   endif
00221     VecMath::MultiDimensionalVector<unsigned, 1> new_surface; //  defines the first cap
00222     new_surface.push_back(current_surface[0]);
00223 
00224     unsigned old_current = 0;
00229     for (unsigned i = 1; i <= RotopeInterface::_numSegments; ++i) {
00230 
00231         double rot = 2.*i*M_PI/RotopeInterface::_numSegments;
00232 
00233         unsigned cur_index = current_surface[0],
00234                  next_index = current_surface[2];
00235 
00236             VecMath::Vector<D> current = VertexData<D>::raw_vertices()[cur_index];
00237             VecMath::Vector<D> next = VertexData<D>::raw_vertices()[next_index];
00238             VecMath::Vector<D> rotated_current = rotate_vertex(current, rot,
00239                                                                d, d-2);
00240 
00242             VertexData<D>::raw_vertices().push_back(rotated_current);
00243 
00245             new_surface.push_back(VertexData<D>::raw_vertices().size()-1);
00246 
00248             VertexData<D>::addSurface(old_current, next_index,
00249                                        VertexData<D>::raw_vertices().size()-1);
00250 
00251             old_current = VertexData<D>::raw_vertices().size()-1;
00252     }
00254     VertexData<D>::addSurface(new_surface);
00255 }
00256 
00261 template <unsigned D> void rotate_base<D>::rotate_quad(
00262         unsigned d, const VecMath::MultiDimensionalVector<unsigned, 1> &current_surface) {
00263 #   if DEBUG_ROTOPES
00264         SingletonLog::Instance().log(__PRETTY_FUNCTION__);
00265 #   endif
00266     unsigned old_current = current_surface[0];  //  saved index to current vertex
00267     unsigned old_next = current_surface[1];     //  saved index to next vertex
00268 
00269     VecMath::MultiDimensionalVector<unsigned, 1> bottom;       //  defines the first ("bottom") cap
00271     bottom.push_back(current_surface[0]);
00276     VecMath::MultiDimensionalVector<unsigned, 1> top;          //  defines the second ("top") cap
00277     top.push_back(current_surface[2]);
00278 
00284     for (unsigned i = 1; i <= RotopeInterface::_numSegments; ++i) {
00285 
00286         double rot = 2.*i*M_PI/RotopeInterface::_numSegments;
00287 
00288         unsigned cur_index = current_surface[0];
00289         unsigned next_index = current_surface[1];
00290 
00291         VecMath::Vector<D> current = VertexData<D>::raw_vertices()[cur_index];
00292         VecMath::Vector<D> next = VertexData<D>::raw_vertices()[next_index];
00293 
00295         VecMath::Vector<D> rotated_current = rotate_vertex(current, rot, d, d-1);
00296         VecMath::Vector<D> rotated_next = rotate_vertex(next, rot, d, d-1);
00297 
00298         VertexData<D>::raw_vertices().push_back(rotated_current);
00299         VertexData<D>::raw_vertices().push_back(rotated_next);
00300 
00302         VertexData<D>::addSurface(old_current, old_next,
00303                                    VertexData<D>::raw_vertices().size()-1,
00304                                    VertexData<D>::raw_vertices().size()-2);
00305 
00307         old_current = VertexData<D>::raw_vertices().size()-2;
00308         old_next = VertexData<D>::raw_vertices().size()-1;
00309 
00311         bottom.push_back(VertexData<D>::raw_vertices().size()-2);
00312         top.push_back(VertexData<D>::raw_vertices().size()-1);
00313     }
00315     VertexData<D>::addSurface(bottom);
00316     VertexData<D>::addSurface(top);
00317 }
00318 
00323 template <unsigned D> void rotate_base<D>::rotate_polygon(
00324         unsigned d, const VecMath::MultiDimensionalVector<unsigned, 1> &current_surface) {
00325 #   if DEBUG_ROTOPES
00326         SingletonLog::Instance().log(__PRETTY_FUNCTION__);
00327 #   endif
00328 
00329     unsigned offset = 0;
00330 
00331     VertexData<D>::raw_vertices().push_back(VertexData<D>::raw_vertices()[current_surface[0]]);
00332 
00334     for (unsigned i = 1; i <= (RotopeInterface::_numSegments+1)/2; ++i) {
00335 
00336         double rot = 1.*i*M_PI/((RotopeInterface::_numSegments+1)/2);
00337 
00338         for (unsigned j = 0; j < current_surface.size(); j++) {
00339 
00340             unsigned cur_index = j+offset;
00341 
00342             unsigned next_index = j+1+offset;
00343 
00344             VecMath::Vector<D> current = VertexData<D>::raw_vertices()[cur_index-offset];
00345             VecMath::Vector<D> next = VertexData<D>::raw_vertices()[next_index-offset];
00346             VecMath::Vector<D> rotated_current = rotate_vertex(current, rot,
00347                                                                d, d-1);
00348             VecMath::Vector<D> rotated_next = rotate_vertex(next, rot, d, d-1);
00349 
00351             VertexData<D>::raw_vertices().push_back(rotated_next);
00352 #           if DEBUG_ROTOPES >= 2
00353             std::cerr << "j: " << j << "offset: " << offset
00354                       << " cur_index: " << cur_index << " next_index: " << next_index
00355                       << " size: " << VertexData<D>::raw_vertices().size() << "\n";
00356 #           endif
00357             VertexData<D>::addSurface(cur_index, next_index,
00358                                        VertexData<D>::raw_vertices().size()-1,
00359                                        VertexData<D>::raw_vertices().size()-2);
00360 
00361         }
00363         offset += current_surface.size();
00364     }
00365 }
00366 
00367 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends

Generated on Mon Apr 9 2012 20:25:15 for HyperspaceExplorer 0.7.1 by doxygen 1.7.4  -  Hosted bySourceForge.net Logo