cellmain.h

Go to the documentation of this file.
00001 
00002 
00003 
00016 
00017 // Copyright (C) 1997-2010 by Pawel Pilarczyk.
00018 //
00019 // This file is part of the Homology Library.  This library is free software;
00020 // you can redistribute it and/or modify it under the terms of the GNU
00021 // General Public License as published by the Free Software Foundation;
00022 // either version 2 of the License, or (at your option) any later version.
00023 //
00024 // This library is distributed in the hope that it will be useful,
00025 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00026 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00027 // GNU General Public License for more details.
00028 //
00029 // You should have received a copy of the GNU General Public License along
00030 // with this software; see the file "license.txt".  If not, write to the
00031 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00032 // MA 02111-1307, USA.
00033 
00034 // Started in January 2002. Last revision: July 15, 2007.
00035 
00036 
00037 #ifndef _CHOMP_CUBES_CELLMAIN_H_
00038 #define _CHOMP_CUBES_CELLMAIN_H_
00039 
00040 #include "chomp/system/config.h"
00041 #include "chomp/system/textfile.h"
00042 #include "chomp/cubes/pointset.h"
00043 #include "chomp/homology/chains.h"
00044 #include "chomp/struct/bitfield.h"
00045 #include "chomp/struct/integer.h"
00046 #include "chomp/struct/hashsets.h"
00047 #include "chomp/homology/gcomplex.h"
00048 #include "chomp/cubes/pointbas.h"
00049 
00050 #include <iostream>
00051 #include <fstream>
00052 #include <cstdlib>
00053 
00054 namespace chomp {
00055 namespace homology {
00056 
00057 
00058 // --------------------------------------------------
00059 // ------------- CUBICAL CELL BOUNDARY --------------
00060 // --------------------------------------------------
00061 
00072 template <class celltype>
00073 inline celltype CubicalBoundaryCell (const celltype &q, int i,
00074         bool onlyexisting)
00075 {
00076         typedef typename celltype::CoordType coordtype;
00077         coordtype origleft [celltype::MaxDim];
00078         q. leftcoord (origleft);
00079         coordtype origright [celltype::MaxDim];
00080         q. rightcoord (origright);
00081         coordtype newcoord [celltype::MaxDim];
00082         int sd = q. spacedim ();
00083         int d = q. dim ();
00084         int count = 0;
00085 
00086         // if this is the first set of cells
00087         if (i < d)
00088         {
00089                 for (int j = 0; j < sd; ++ j)
00090                 {
00091                         // copy the coordinates of the right vertex
00092                         newcoord [j] = origleft [j];
00093 
00094                         // modify the desired coordinate and finalize
00095                         if (origleft [j] != origright [j])
00096                         {
00097                                 if (i == count ++)
00098                                 {
00099                                         newcoord [j] = origright [j];
00100                                         for (j = j + 1; j < sd; ++ j)
00101                                                 newcoord [j] = origleft [j];
00102                                         if (onlyexisting &&
00103                                                 !celltype::PointBase::check
00104                                                         (newcoord, sd))
00105                                                 return q;
00106                                         return celltype (newcoord,
00107                                                 origright, sd);
00108                                 }
00109                         }
00110                 }
00111                 throw "False cubical cell's dimension.";
00112         }
00113         else
00114         {
00115                 i -= d;
00116                 for (int j = 0; j < sd; ++ j)
00117                 {
00118                         // copy the coordinates of the right vertex
00119                         newcoord [j] = origright [j];
00120 
00121                         // modify the desired coordinate and finalize
00122                         if (origleft [j] != origright [j])
00123                         {
00124                                 if (i == count ++)
00125                                 {
00126                                         newcoord [j] = origleft [j];
00127                                         for (j = j + 1; j < sd; j ++)
00128                                                 newcoord [j] = origright [j];
00129                                         if (onlyexisting &&
00130                                                 !celltype::PointBase::check
00131                                                         (newcoord, sd))
00132                                                 return q;
00133                                         return celltype (origleft,
00134                                                 newcoord, sd);
00135                                 }
00136                         }
00137                 }
00138                 throw "False dimension of a cubical cell.";
00139         }
00140 } /* boundarycell */
00141 
00143 template <class celltype>
00144 inline celltype CubicalBoundaryCell (const celltype &q, int i)
00145 {
00146         return CubicalBoundaryCell (q, i, false);
00147 } /* boundarycell */
00148         
00150 template <class celltype>
00151 inline int CubicalBoundaryLength (const celltype &q)
00152 {
00153         return q. dim () << 1;
00154 } /* boundarylength */
00155 
00157 template <class celltype>
00158 inline int CubicalBoundaryCoef (const celltype &q, int i)
00159 {
00160         int d = q. dim ();
00161         if (i >= d)
00162                 i -= d - 1;
00163         return (i & 1) ? 1 : -1;
00164 } /* boundarycoef */
00165 
00166 
00167 // --------------------------------------------------
00168 // ---------------- CUBICAL CELL I/O ----------------
00169 // --------------------------------------------------
00170 
00173 template <class celltype>
00174 inline std::ostream &WriteCubicalCell (std::ostream &out, const celltype &c)
00175 {
00176         // determine the data to be written
00177         typedef typename celltype::CoordType coordtype;
00178         coordtype lcoord [celltype::MaxDim];
00179         c. leftcoord (lcoord);
00180         int dim = c. spacedim ();
00181         coordtype rcoord [celltype::MaxDim];
00182         c. rightcoord (rcoord);
00183 
00184         if (celltype::OutputBits & celltype::BitProduct)
00185         {
00186                 for (int i = 0; i < dim; ++ i)
00187                 {
00188                         out << '(';
00189                         out << lcoord [i];
00190                         if (rcoord [i] != lcoord [i])
00191                                 out << ',' << rcoord [i];
00192                         out << ')';
00193                         if (i < dim - 1)
00194                                 out << 'x';
00195                 }
00196         }
00197         else
00198         {
00199                 out << '[' << '(';
00200                 int i;
00201                 for (i = 0; i < dim; ++ i)
00202                 {
00203                         out << lcoord [i];
00204                         if (i < dim - 1)
00205                                 out << ',';
00206                 }
00207                 out << ')';
00208                 if (celltype::OutputBits & celltype::BitSpace)
00209                         out << ' ';
00210                 out << '(';
00211                 for (i = 0; i < dim; ++ i)
00212                 {
00213                         out << rcoord [i];
00214                         if (i < dim - 1)
00215                                 out << ',';
00216                 }
00217                 out << ')' << ']';
00218         }
00219         return out;
00220 } /* operator << */
00221 
00235 template <class celltype>
00236 inline std::istream &ReadCubicalCell (std::istream &in, celltype &c)
00237 {
00238         typedef typename celltype::CoordType coordtype;
00239         // make sure that an opening parenthesis is waiting in the input
00240         ignorecomments (in);
00241         int closing = closingparenthesis (in. peek ());
00242         if (closing == EOF)
00243                 throw "Opening parenthesis expected while reading a cell.";
00244 
00245         // read the opening parenthesis
00246         in. get ();
00247         ignorecomments (in);
00248 
00249         // prepare the two vertices of a cubical cell
00250         coordtype c1 [celltype::MaxDim], c2 [celltype::MaxDim];
00251 
00252         // if there is another opening parenthesis...
00253         if (closingparenthesis (in. peek ()) != EOF)
00254         {
00255                 // read coordinates of both vertices and a comma if any
00256                 int dim1 = readcoordinates (in, c1, celltype::MaxDim);
00257                 ignorecomments (in);
00258                 if (in. peek () == ',')
00259                 {
00260                         in. get ();
00261                         ignorecomments (in);
00262                 }
00263                 int dim2 = readcoordinates (in, c2, celltype::MaxDim);
00264 
00265                 // read the closing bracket and verify that the data
00266                 ignorecomments (in);
00267                 if ((in. get () != closing) || (dim1 <= 0) || (dim1 != dim2))
00268                         throw "Failed while reading two vertices of a cell.";
00269 
00270                 // verify the distance between the vertices of the cell
00271                 for (int i = 0; i < dim1; ++ i)
00272                 {
00273                         if ((c1 [i] != c2 [i]) && (c1 [i] + 1 != c2 [i]))
00274                                 throw "Vertices of a read cell are too far.";
00275                 }
00276 
00277                 // create the cubical cell with the given vertices and quit
00278                 c = celltype (c1, c2, dim1);
00279                 return in;
00280         }
00281 
00282         // try reading the first set of coordinates in the cell's definition
00283         coordtype c0 [celltype::MaxDim];
00284         int count = readcoordinates (in, c0, celltype::MaxDim, closing);
00285         if (count <= 0)
00286                 throw "Can't read a cell.";
00287         ignorecomments (in);
00288 
00289         // if it looks like an interval, then read the cell as a product
00290         if ((count == 1) || (count == 2))
00291         {
00292                 int dim = 0;
00293                 c1 [dim] = c0 [0];
00294                 c2 [dim ++] = c0 [count - 1];
00295                 while ((in. peek () == 'x') || (in. peek () == 'X'))
00296                 {
00297                         in. get ();
00298                         ignorecomments (in);
00299                         count = readcoordinates (in, c0, celltype::MaxDim);
00300                         ignorecomments (in);
00301                         if ((count < 1) || (count > 2) ||
00302                                 (dim >= celltype::MaxDim))
00303                                 throw "Wrong interval while reading a cell.";
00304                         if ((count == 2) && (c0 [1] != c0 [0]) &&
00305                                 (c0 [1] - c0 [0] != 1))
00306                                 throw "Too big interval defining a cell.";
00307                         c1 [dim] = c0 [0];
00308                         c2 [dim ++] = c0 [count - 1];
00309                 }
00310                 c = celltype (c1, c2, dim);
00311                 return in;
00312         }
00313 
00314         // if the cell is defined as a full-dim. cube, create it this way
00315         for (int i = 0; i < count; ++ i)
00316                 c1 [i] = c0 [i] + 1;
00317         c = celltype (c0, c1, count);
00318         return in;
00319 } /* operator >> */
00320 
00321 
00322 // --------------------------------------------------
00323 // ----------- INTERSECTION OF TWO CUBES ------------
00324 // --------------------------------------------------
00325 
00328 template<class coordtype>
00329 inline int CommonCell (coordtype *left, coordtype *right,
00330         const coordtype *c1, const coordtype *c2, int spcdim,
00331         const coordtype *wrap = 0)
00332 {
00333         // calculate the coordinates of both vertices of the cubical cell
00334         // and the dimension of the cubical cell
00335         int celldim = 0;
00336         for (int i = 0; i < spcdim; ++ i)
00337         {
00338                 if (c1 [i] == c2 [i])
00339                 {
00340                         left [i] = c1 [i];
00341                         right [i] = c1 [i];
00342                         ++ (right [i]);
00343                         ++ celldim;
00344                 }
00345                 else if ((c1 [i] - c2 [i] == -1) || (wrap && wrap [i] &&
00346                         (c1 [i] - c2 [i] == wrap [i] - 1)))
00347                 {
00348                         left [i] = c2 [i];
00349                         right [i] = c2 [i];
00350                 }
00351                 else if ((c1 [i] - c2 [i] == 1) || (wrap && wrap [i] &&
00352                         (c1 [i] - c2 [i] == -wrap [i] + 1)))
00353                 {
00354                         left [i] = c1 [i];
00355                         right [i] = c1 [i];
00356                 }
00357                 else
00358                         throw "The cubes do not intersect.";
00359         }
00360 
00361         return celldim;
00362 } /* CommonCell */
00363 
00364 
00365 } // namespace homology
00366 } // namespace chomp
00367 
00368 #endif // _CHOMP_CUBES_CELLMAIN_H_
00369 
00371