HyperspaceExplorer 0.7.1
|
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 TAPER_H 00022 #define TAPER_H 00023 00024 #include "Rotope.h" 00025 00027 00031 template <unsigned D> 00032 class taper_base: public VertexData<D> { 00033 00034 public: 00036 taper_base(const VertexData<D> &v): 00037 VertexData<D>(v), _previous_dim(-1), _pre_previous_dim (-1) { } 00038 00040 00073 void taper(unsigned d); 00074 00075 private: 00077 bool alreadyTapered() { return _previous_dim >= 0; } 00078 00080 int _previous_dim; 00082 int _pre_previous_dim; 00083 }; 00084 00086 00116 template <unsigned D, unsigned Dmin, unsigned Dmax> 00117 class Taper: public Taper<D, Dmin, Dmax-1> { 00118 public: 00120 00126 Taper(const VertexData<D> &v): Taper<D, Dmin, Dmax-1>(v) { 00127 taper_base<D>::taper(Dmax); 00128 } 00129 }; 00130 00132 00138 template <unsigned D, unsigned Dmin> 00139 class Taper<D, Dmin, Dmin>: public taper_base<D> { 00140 public: 00142 00147 Taper(const VertexData<D> &v): taper_base<D>(v) { 00148 taper_base<D>::taper(Dmin); 00149 } 00150 }; 00151 00152 template <unsigned D> void taper_base<D>::taper(unsigned d) { 00153 00154 if (d >= D) { 00155 throw std::logic_error( 00156 "taper_base::taper() called on a higher dimension than the " 00157 "vector space allows"); 00158 } 00159 if (VertexData<D>::raw_vertices().size() < 2) { 00160 throw std::logic_error( 00161 "taper_base::taper() can only operate on at least two vertices"); 00162 } 00163 00164 Vector<D> xnew; // connect all vertices to this new vertex 00165 00166 if (!alreadyTapered()) { 00168 double displacement = sqrt(1.-0.25); 00177 for(unsigned i = 0; i < VertexData<D>::raw_vertices().size(); ++i) { 00178 xnew += VertexData<D>::raw_vertices()[i]; 00179 VertexData<D>::raw_vertices()[i][d] -= displacement; 00180 } 00181 xnew *= 1./VertexData<D>::raw_vertices().size(); 00182 00183 xnew[d] = displacement; 00184 } else { 00189 xnew = VertexData<D>::raw_vertices().back(); 00190 double displacement; 00191 00192 if (_pre_previous_dim < 0) { 00198 displacement = sqrt(xnew[_previous_dim]*xnew[_previous_dim]-.25); 00199 xnew[d] = displacement; 00200 00204 xnew[_previous_dim] /= 2.; 00205 } else { 00209 displacement = sqrt(fabs(xnew[_previous_dim]*xnew[_previous_dim]- 00210 xnew[_pre_previous_dim]*xnew[_pre_previous_dim])); 00211 xnew[d] = displacement; 00212 00213 xnew[_previous_dim] /= 2.; 00214 } 00215 for(unsigned i = 0; i < VertexData<D>::raw_vertices().size(); ++i) { 00216 VertexData<D>::raw_vertices()[i][d] -= displacement; 00217 } 00218 00219 } 00220 00221 VertexData<D>::raw_vertices().push_back(xnew); 00222 00223 VertexData<D>::realm() = VertexData<D>::realm().tapered(VertexData<D>::raw_vertices().size()-1); 00224 00225 _pre_previous_dim = _previous_dim; 00226 _previous_dim = d; 00227 00228 VertexData<D>::dimension()++; // object is now one dimension higher 00229 } 00230 00231 #endif