twolayer.h

Go to the documentation of this file.
00001 
00002 
00003 
00021 
00022 // Copyright (C) 1997-2010 by Pawel Pilarczyk.
00023 //
00024 // This file is part of the Homology Library.  This library is free software;
00025 // you can redistribute it and/or modify it under the terms of the GNU
00026 // General Public License as published by the Free Software Foundation;
00027 // either version 2 of the License, or (at your option) any later version.
00028 //
00029 // This library is distributed in the hope that it will be useful,
00030 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00031 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00032 // GNU General Public License for more details.
00033 //
00034 // You should have received a copy of the GNU General Public License along
00035 // with this software; see the file "license.txt".  If not, write to the
00036 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00037 // MA 02111-1307, USA.
00038 
00039 // Started in May 2006. Last revision: May 31, 2010.
00040 
00041 
00042 #ifndef _CHOMP_CUBES_TWOLAYER_H_
00043 #define _CHOMP_CUBES_TWOLAYER_H_
00044 
00045 #include "chomp/cubes/cube.h"
00046 #include "chomp/cubes/cell.h"
00047 #include "chomp/cubes/neighbor.h"
00048 #include "chomp/cubes/cubmaps.h"
00049 #include "chomp/struct/bitfield.h"
00050 #include "chomp/system/textfile.h"
00051 
00052 #include <iostream>
00053 #include <fstream>
00054 #include <cstdlib>
00055 #include <cstring>
00056 #include <exception>
00057 
00058 namespace chomp {
00059 namespace homology {
00060 
00061 
00067 typedef short int theLayerType;
00068 
00069 
00070 // --------------------------------------------------
00071 // ---------------- two-layer cubes -----------------
00072 // --------------------------------------------------
00073 
00074 template <class tCell>
00075 class tCell2l;
00076 
00079 template <class tCube>
00080 class tCube2l
00081 {
00082 public:
00084         typedef theLayerType LayerType;
00085 
00087         typedef tCube CubeType;
00088 
00090         typedef typename tCube::CoordType CoordType;
00091 
00093         typedef tCell2l<typename tCube::CellType> CellType;
00094 
00096         static const int MaxDim = tCube::MaxDim;
00097 
00099         typedef typename tCube::PointBase PointBase;
00100 
00102         tCube2l ();
00103         
00105         tCube2l (const tCube &_q, const LayerType &_l);
00106 
00108         tCube2l (const CoordType *coord, int dim);
00109 
00111         tCube2l (const CoordType *coord, int dim, const LayerType &_l);
00112 
00114         tCube2l (int_t number, int dim);
00115 
00117         tCube2l (const tCube2l &c);
00118 
00120         tCube2l &operator = (const tCube2l &c);
00121 
00123         int dim () const;
00124 
00126         template <class intType>
00127         intType *coord (intType *c) const;
00128 
00130         int_t hashkey1 () const;
00131 
00133         int_t hashkey2 () const;
00134 
00136         static const char *name ();
00137 
00139         static const char *pluralname ();
00140 
00142         const LayerType &layer () const;
00143 
00145         const tCube &cube () const;
00146 
00148         void layer (const typename tCube2l<tCube>::LayerType &newlayer);
00149 
00155         static void setlayers (const hashedset<tCube> &X,
00156                 const hashedset<tCube> &A);
00157 
00159         static const hashedset<tCube> &layer1 ();
00160 
00162         static const hashedset<tCube> &layer1b ();
00163 
00166         static const hashedset<tCube> &layer0 ();
00167 
00168 private:
00170         tCube q;
00171 
00173         LayerType l;
00174 
00178         static hashedset<tCube> layer1set;
00179 
00182         static hashedset<tCube> layer1boundary;
00183 
00186         static hashedset<tCube> layer0set;
00187 
00188 }; /* class tCube2l */
00189 
00190 // --------------------------------------------------
00191 
00192 template <class tCube>
00193 hashedset<tCube> tCube2l<tCube>::layer1set (8192);
00194 
00195 template <class tCube>
00196 hashedset<tCube> tCube2l<tCube>::layer1boundary (8192);
00197 
00198 template <class tCube>
00199 hashedset<tCube> tCube2l<tCube>::layer0set (8192);
00200 
00201 // --------------------------------------------------
00202 
00203 template <class tCube>
00204 inline tCube2l<tCube>::tCube2l (): q (), l (0)
00205 {
00206         return;
00207 } /* tCube2l */
00208 
00209 template <class tCube>
00210 inline tCube2l<tCube>::tCube2l (const tCube &_q, const LayerType &_l)
00211 : q (_q), l (_l)
00212 {
00213         return;
00214 } /* tCube2l */
00215 
00216 template <class tCube>
00217 inline tCube2l<tCube>::tCube2l (const CoordType *coord, int dim):
00218         q (coord, dim), l (layer1set. check (q) ? 1 : 0)
00219 {
00220         return;
00221 } /* tCube2l */
00222 
00223 template <class tCube>
00224 inline tCube2l<tCube>::tCube2l (const CoordType *coord, int dim,
00225         const LayerType &_l): q (coord, dim), l (_l)
00226 {
00227         return;
00228 } /* tCube2l */
00229 
00230 template <class tCube>
00231 inline tCube2l<tCube>::tCube2l (int_t number, int dim)
00232 : q (number, dim), l (layer1set. check (q) ? 1 : 0)
00233 {
00234         return;
00235 } /* tCube2l */
00236 
00237 template <class tCube>
00238 inline tCube2l<tCube>::tCube2l (const tCube2l &c): q (c. q), l (c. l)
00239 {
00240         return;
00241 } /* tCube2l */
00242 
00243 template <class tCube>
00244 inline tCube2l<tCube> &tCube2l<tCube>::operator = (const tCube2l<tCube> &c)
00245 {
00246         q = c. q;
00247         l = c. l;
00248         return *this;
00249 } /* tCube2l */
00250 
00251 template <class tCube>
00252 inline int tCube2l<tCube>::dim () const
00253 {
00254         return q. dim ();
00255 } /* dim */
00256 
00257 template <class tCube>
00258 template <class intType>
00259 inline intType *tCube2l<tCube>::coord (intType *c) const
00260 {
00261         return q. coord (c);
00262 } /* coord */
00263 
00264 template <class tCube>
00265 inline int_t tCube2l<tCube>::hashkey1 () const
00266 {
00267         return q. hashkey1 ();
00268 } /* hashkey1 */
00269 
00270 template <class tCube>
00271 inline int_t tCube2l<tCube>::hashkey2 () const
00272 {
00273         return q. hashkey2 () ^ l;
00274 } /* hashkey2 */
00275 
00276 template <class tCube>
00277 inline const char *tCube2l<tCube>::name ()
00278 {
00279         return tCube::name ();
00280 } /* name */
00281 
00282 template <class tCube>
00283 inline const char *tCube2l<tCube>::pluralname ()
00284 {
00285         return tCube::pluralname ();
00286 } /* pluralname */
00287 
00288 template <class tCube>
00289 inline const tCube &tCube2l<tCube>::cube () const
00290 {
00291         return q;
00292 } /* cube */
00293 
00294 template <class tCube>
00295 inline const typename tCube2l<tCube>::LayerType &tCube2l<tCube>::layer ()
00296         const
00297 {
00298         return l;
00299 } /* layer */
00300 
00301 template <class tCube>
00302 inline void tCube2l<tCube>::layer
00303         (const typename tCube2l<tCube>::LayerType &newlayer)
00304 {
00305         l = newlayer;
00306         return;
00307 } /* layer */
00308 
00309 template <class tCube>
00310 inline void tCube2l<tCube>::setlayers (const hashedset<tCube> &X,
00311         const hashedset<tCube> &A)
00312 {
00313         // remember the sets at the layers' boundary
00314         layer0set = A;
00315         layer1set = X;
00316         hashedset<tCube> empty;
00317         layer1boundary = empty;
00318 
00319         // if the set X is empty, then there is no problem at all
00320         if (X. empty ())
00321                 return;
00322 
00323         // determine the set at Layer 1 as neighbors of A in X,
00324         // and create cells at the layers' boundary for identification
00325         hashedset<typename tCube::CellType> idcells;
00326         for (int_t i = 0; i < X. size (); ++ i)
00327         {
00328                 const tCube &q = X [i];
00329                 hashedset<tCube> neighbors;
00330                 int_t ncount = getneighbors (q, 0, layer0set, &neighbors, 0);
00331                 if (!ncount)
00332                         continue;
00333                 layer1boundary. add (q);
00334                 for (int_t j = 0; j < ncount; ++ j)
00335                 {
00336                         idcells. add (typename tCube::CellType
00337                                 (q, neighbors [j]));
00338                 }
00339         }
00340 
00341         // add boundaries of all the cells
00342         for (int_t i = 0; i < idcells. size (); ++ i)
00343         {
00344                 const typename tCube::CellType &c = idcells [i];
00345                 int bsize = boundarylength (c);
00346                 for (int j = 0; j < bsize; ++ j)
00347                         idcells. add (boundarycell (c, j));
00348         }
00349 
00350         // define the identification set
00351         CellType::identify (idcells, layer1set [0]. dim ());
00352         return;
00353 } /* setlayers */
00354 
00355 template <class tCube>
00356 inline const hashedset<tCube> &tCube2l<tCube>::layer1 ()
00357 {
00358         return layer1set;
00359 } /* layer1 */
00360 
00361 template <class tCube>
00362 inline const hashedset<tCube> &tCube2l<tCube>::layer1b ()
00363 {
00364         return layer1boundary;
00365 } /* layer1b */
00366 
00367 template <class tCube>
00368 inline const hashedset<tCube> &tCube2l<tCube>::layer0 ()
00369 {
00370         return layer0set;
00371 } /* layer0 */
00372 
00373 // --------------------------------------------------
00374 
00376 template <class tCube>
00377 inline int operator == (const tCube2l<tCube> &c1,
00378         const tCube2l<tCube> &c2)
00379 {
00380         return (c1. cube () == c2. cube ()) &&
00381                 (c1. layer () == c2. layer ());
00382 } /* operator == */
00383 
00386 template <class tCube>
00387 inline int operator != (const tCube2l<tCube> &c1,
00388         const tCube2l<tCube> &c2)
00389 {
00390         return !(c1 == c2);
00391 } /* operator != */
00392 
00394 template <class tCube>
00395 inline tCube2l<tCube> operator * (const tCube2l<tCube> &c1,
00396         const tCube2l<tCube> &c2)
00397 {
00398         tCube q (c1. cube () * c2. cube ());
00399         typename tCube2l<tCube>::LayerType
00400                 l ((c1. layer () << 2) | c2. layer ());
00401         return tCube2l<tCube> (q, l);
00402 } /* operator * */
00403 
00405 template <class tCube>
00406 inline std::ostream &operator << (std::ostream &out, const tCube2l<tCube> &c)
00407 {
00408         // write the cube
00409         WriteCube (out, c. cube ());
00410 
00411         // write the layer if any
00412         if (c. layer ())
00413                 out << '^' << c. layer ();
00414 
00415         return out;
00416 } /* operator << */
00417 
00419 template <class tCube>
00420 inline std::istream &operator >> (std::istream &in, tCube2l<tCube> &c)
00421 {
00422         // read the cube
00423         tCube q;
00424         ReadCube (in, q);
00425 
00426         // read the layer if any
00427         typename tCube2l<tCube>::LayerType l (0);
00428         ignorecomments (in);
00429         if (in. peek () == '^')
00430         {
00431                 in. get ();
00432                 ignorecomments (in);
00433                 in >> l;
00434         }
00435         else if (tCube2l<tCube>::layer1 (). check (q))
00436                 l = 1;
00437 
00438         c = tCube2l<tCube> (q, l);
00439         return in;
00440 } /* operator >> */
00441 
00444 template <class tCube>
00445 inline std::istream &operator >> (std::istream &in,
00446         hashedset<tCube2l<tCube> > &s)
00447 {
00448         return ReadCubes (in, s);
00449 } /* operator >> */
00450 
00456 template <class tCube>
00457 inline std::istream &operator >> (std::istream &in,
00458         mvmap<tCube2l<tCube>,tCube2l<tCube> > &m)
00459 {
00460         return ReadCubicalMap (in, m);
00461 } /* operator >> */
00462 
00463 
00464 // --------------------------------------------------
00465 // ---------------- two-layer cells -----------------
00466 // --------------------------------------------------
00467 
00470 template <class tCell>
00471 class tCell2l
00472 {
00473 public:
00475         typedef theLayerType LayerType;
00476 
00478         typedef tCell CellType;
00479 
00481         typedef typename tCell::CoordType CoordType;
00482         
00484         static const int MaxDim = tCell::MaxDim;
00485 
00487         typedef typename tCell::PointBase PointBase;
00488 
00490         tCell2l ();
00491         
00493         tCell2l (const tCell &_q, const LayerType &_l);
00494 
00496         tCell2l (const CoordType *c1, const CoordType *c2,
00497                 int spcdim, int celldim = -1, int layer = 0);
00498 
00500         template <class tCube>
00501         tCell2l (const tCube2l<tCube> &q1, const tCube2l<tCube> &q2);
00502 
00505         template <class tCube>
00506         tCell2l (const tCube2l<tCube> &c, int facedim);
00507 
00509         template <class tCube>
00510         explicit tCell2l (const tCube2l<tCube> &c);
00511 
00515         template <class tCellSrc>
00516         tCell2l (const tCell2l<tCellSrc> &q, int offset, int ncoords);
00517 
00519         tCell2l (const tCell2l &c);
00520 
00522         tCell2l &operator = (const tCell2l &c);
00523 
00525         int dim () const;
00526 
00528         int spacedim () const;
00529 
00531         template <class intType>
00532         intType *leftcoord (intType *c) const;
00533 
00535         template <class intType>
00536         intType *rightcoord (intType *c) const;
00537 
00539         int_t hashkey1 () const;
00540 
00542         int_t hashkey2 () const;
00543 
00545         static const char *name ();
00546 
00548         static const char *pluralname ();
00549 
00552         enum OutputBitValues
00553         {
00554                 BitProduct = 0x01,      // unset => two vertices
00555                 BitSpace = 0x02
00556         };
00557         static int OutputBits;
00558 
00560         const LayerType &layer () const;
00561 
00563         const tCell &cell () const;
00564 
00566         void layer (const typename tCell2l<tCell>::LayerType &newlayer);
00567 
00569         static void identify (const hashedset<tCell> &s, int dim);
00570 
00572         static const hashedset<tCell> &identify ();
00573 
00575         static LayerType droplayer (const tCell &q, const LayerType &layer);
00576 
00577 private:
00579         static hashedset<tCell> idset;
00580 
00584         static int iddim;
00585 
00587         tCell q;
00588 
00590         LayerType l;
00591 
00592 }; /* class tCell2l */
00593 
00594 // --------------------------------------------------
00595 
00596 template <class tCell>
00597 int tCell2l<tCell>::OutputBits = 0;
00598 
00599 template <class tCell>
00600 hashedset<tCell> tCell2l<tCell>::idset (8192);
00601 
00602 template <class tCell>
00603 int tCell2l<tCell>::iddim (0);
00604 
00605 // --------------------------------------------------
00606 
00607 template <class tCell>
00608 inline tCell2l<tCell>::tCell2l (): q (), l (0)
00609 {
00610         return;
00611 } /* tCell2l */
00612 
00613 template <class tCell>
00614 inline tCell2l<tCell>::tCell2l (const tCell &_q, const LayerType &_l)
00615 : q (_q), l (_l)
00616 {
00617         if ((l == 1) && idset. check (q))
00618                 l = 0;
00619         return;
00620 } /* tCell2l */
00621 
00622 template <class tCell>
00623 inline tCell2l<tCell>::tCell2l (const typename tCell2l<tCell>::CoordType *c1,
00624         const typename tCell2l<tCell>::CoordType *c2,
00625         int spcdim, int celldim, int layer)
00626 : q (c1, c2, spcdim, celldim), l (layer)
00627 {
00628         if ((l == 1) && idset. check (q))
00629                 l = 0;
00630         return;
00631 } /* tCell2l */
00632 
00633 template <class tCell>
00634 template <class tCube>
00635 inline tCell2l<tCell>::tCell2l (const tCube2l<tCube> &q1,
00636         const tCube2l<tCube> &q2)
00637 : q (q1. cube (), q2. cube ()), l ((q1. layer () < q2. layer ()) ?
00638         q1. layer () : q2. layer ())
00639 {
00640         if ((l == 1) && idset. check (q))
00641                 l = 0;
00642         return;
00643 } /* tCell2l */
00644 
00645 template <class tCell>
00646 template <class tCube>
00647 inline tCell2l<tCell>::tCell2l (const tCube2l<tCube> &c, int facedim)
00648 : q (c. cube (), facedim), l (c. layer ())
00649 {
00650         l = tCell2l<tCell>::droplayer (q, l);
00651         return;
00652 } /* tCell2l */
00653 
00654 template <class tCell>
00655 template <class tCube>
00656 inline tCell2l<tCell>::tCell2l (const tCube2l<tCube> &c)
00657 : q (c. cube ()), l (c. layer ())
00658 {
00659         if ((l == 1) && idset. check (q))
00660                 l = 0;
00661         return;
00662 } /* tCell2l */
00663 
00664 template <class tCell>
00665 template <class tCellSrc>
00666 inline tCell2l<tCell>::tCell2l (const tCell2l<tCellSrc> &c,
00667         int offset, int ncoords)
00668 : q (c. cell (), offset, ncoords), l (c. layer ())
00669 {
00670         if (offset > 0)
00671                 l &= 0x03;
00672         else
00673         {
00674                 l >>= 2;
00675                 l &= 0x03;
00676         }
00677         if ((l == 1) && idset. check (q))
00678                 l = 0;
00679         return;
00680 } /* tCell2l */
00681 
00682 template <class tCell>
00683 inline tCell2l<tCell>::tCell2l (const tCell2l &c): q (c. q), l (c. l)
00684 {
00685         return;
00686 } /* tCell2l */
00687 
00688 template <class tCell>
00689 inline tCell2l<tCell> &tCell2l<tCell>::operator = (const tCell2l<tCell> &c)
00690 {
00691         q = c. q;
00692         l = c. l;
00693         return *this;
00694 } /* tCell2l */
00695 
00696 template <class tCell>
00697 inline int tCell2l<tCell>::dim () const
00698 {
00699         return q. dim ();
00700 } /* dim */
00701 
00702 template <class tCell>
00703 inline int tCell2l<tCell>::spacedim () const
00704 {
00705         return q. spacedim ();
00706 } /* spacedim */
00707 
00708 template <class tCell>
00709 template <class intType>
00710 inline intType *tCell2l<tCell>::leftcoord (intType *c) const
00711 {
00712         return q. leftcoord (c);
00713 } /* leftcoord */
00714 
00715 template <class tCell>
00716 template <class intType>
00717 inline intType *tCell2l<tCell>::rightcoord (intType *c) const
00718 {
00719         return q. rightcoord (c);
00720 } /* rightcoord */
00721 
00722 template <class tCell>
00723 inline int_t tCell2l<tCell>::hashkey1 () const
00724 {
00725         return q. hashkey1 ();
00726 } /* hashkey1 */
00727 
00728 template <class tCell>
00729 inline int_t tCell2l<tCell>::hashkey2 () const
00730 {
00731         return q. hashkey2 () ^ l;
00732 } /* hashkey2 */
00733 
00734 template <class tCell>
00735 inline const char *tCell2l<tCell>::name ()
00736 {
00737         return tCell::name ();
00738 } /* name */
00739 
00740 template <class tCell>
00741 inline const char *tCell2l<tCell>::pluralname ()
00742 {
00743         return tCell::pluralname ();
00744 } /* pluralname */
00745 
00746 template <class tCell>
00747 inline const typename tCell2l<tCell>::LayerType &tCell2l<tCell>::layer ()
00748         const
00749 {
00750         return l;
00751 } /* layer */
00752 
00753 template <class tCell>
00754 inline const tCell &tCell2l<tCell>::cell () const
00755 {
00756         return q;
00757 } /* cell */
00758 
00759 template <class tCell>
00760 inline void tCell2l<tCell>::layer
00761         (const typename tCell2l<tCell>::LayerType &newlayer)
00762 {
00763         l = newlayer;
00764         return;
00765 } /* layer */
00766 
00767 template <class tCell>
00768 inline void tCell2l<tCell>::identify (const hashedset<tCell> &s, int dim)
00769 {
00770         idset = s;
00771         iddim = dim;
00772         return;
00773 } /* identify */
00774 
00775 template <class tCell>
00776 inline const hashedset<tCell> &tCell2l<tCell>::identify ()
00777 {
00778         return idset;
00779 } /* identify */
00780 
00781 template <class tCell>
00782 inline typename tCell2l<tCell>::LayerType tCell2l<tCell>::droplayer
00783         (const tCell &q, const LayerType &layer)
00784 {
00785         if (!layer)
00786                 return layer;
00787         int dim = q. spacedim ();
00788         if (dim <= iddim)
00789         {
00790                 if (idset. check (q))
00791                         return 0;
00792                 else
00793                         return layer;
00794         }
00795         if (dim != iddim + iddim)
00796                 throw "Unknown cells for layer analysis.";
00797         typename tCell2l<tCell>::LayerType layer1 (layer >> 2);
00798         typename tCell2l<tCell>::LayerType layer2 (layer & 0x03);
00799         if ((layer1) && idset. check (tCell (q, 0, iddim)))
00800                 layer1 = 0;
00801         if ((layer2) && idset. check (tCell (q, iddim, iddim)))
00802                 layer2 = 0;
00803         return (layer1 << 2) | layer2;
00804 } /* droplayer */
00805 
00806 // --------------------------------------------------
00807 
00809 template <class tCell>
00810 inline int operator == (const tCell2l<tCell> &c1,
00811         const tCell2l<tCell> &c2)
00812 {
00813         return (c1. cell () == c2. cell ()) &&
00814                 (c1. layer () == c2. layer ());
00815 } /* operator == */
00816 
00819 template <class tCell>
00820 inline int operator != (const tCell2l<tCell> &c1,
00821         const tCell2l<tCell> &c2)
00822 {
00823         return !(c1 == c2);
00824 } /* operator != */
00825 
00827 template <class tCell>
00828 inline tCell2l<tCell> operator * (const tCell2l<tCell> &c1,
00829         const tCell2l<tCell> &c2)
00830 {
00831         tCell q (c1. cell () * c2. cell ());
00832         typename tCell2l<tCell>::LayerType
00833                 l ((c1. layer () << 2) | c2. layer ());
00834         return tCell2l<tCell> (q, l);
00835 } /* operator * */
00836 
00838 template <class tCell>
00839 inline std::ostream &operator << (std::ostream &out, const tCell2l<tCell> &c)
00840 {
00841         // write the cubical cell
00842         WriteCubicalCell (out, c. cell ());
00843 
00844         // write the layer if any
00845         if (c. layer ())
00846                 out << '^' << c. layer ();
00847 
00848         return out;
00849 } /* operator << */
00850 
00852 template <class tCell>
00853 inline std::istream &operator >> (std::istream &in, tCell2l<tCell> &c)
00854 {
00855         // read the cubical cell
00856         tCell q;
00857         ReadCubicalCell (in, q);
00858 
00859         // read the layer if any
00860         typename tCell2l<tCell>::LayerType l (0);
00861         ignorecomments (in);
00862         if (in. peek () == '^')
00863         {
00864                 in. get ();
00865                 ignorecomments (in);
00866                 in >> l;
00867         }
00868 
00869         c = tCell2l<tCell> (q, l);
00870         return in;
00871 } /* operator >> */
00872 
00873 // --------------------------------------------------
00874 
00877 template <class tCell>
00878 inline tCell2l<tCell> boundarycell (const tCell2l<tCell> &q, int i,
00879         bool onlyexisting)
00880 {
00881         tCell c = CubicalBoundaryCell (q. cell (), i, onlyexisting);
00882         if (c == q. cell ())
00883                 return q;
00884         typename tCell2l<tCell>::LayerType l
00885                 (tCell2l<tCell>::droplayer (c, q. layer ()));
00886         return tCell2l<tCell> (c, l);
00887 } /* boundarycell */
00888 
00890 template <class tCell>
00891 inline tCell2l<tCell> boundarycell (const tCell2l<tCell> &q, int i)
00892 {
00893         tCell c = CubicalBoundaryCell (q. cell (), i);
00894         typename tCell2l<tCell>::LayerType l
00895                 (tCell2l<tCell>::droplayer (c, q. layer ()));
00896         return tCell2l<tCell> (c, l);
00897 } /* boundarycell */
00898         
00900 template <class tCell>
00901 inline int boundarylength (const tCell2l<tCell> &q)
00902 {
00903         return CubicalBoundaryLength (q. cell ());
00904 } /* boundarylength */
00905 
00907 template <class tCell>
00908 inline int boundarycoef (const tCell2l<tCell> &q, int i)
00909 {
00910         return CubicalBoundaryCoef (q. cell (), i);
00911 } /* boundarycoef */
00912 
00913 
00914 // --------------------------------------------------
00915 // ---------------- specializations -----------------
00916 // --------------------------------------------------
00917 
00921 template <class tCube>
00922 inline tCube2l<tCube> bit2neighbor (const tCube2l<tCube> &q, int_t number,
00923         bool unconditional = false)
00924 {
00925         throw "Trying to use 'bit2neighbor' for a 2-layer cube.";
00926         return q;
00927 } /* bit2neighbor */
00928 
00932 template <class tCube>
00933 int_t neighbor2bit (const tCube2l<tCube> &q, const tCube2l<tCube> &neighbor)
00934 {
00935         throw "Trying to use 'neighbor2bit' for a 2-layer cube.";
00936         return -1;
00937 } /* neighbor2bit */
00938 
00944 template <class tCube>
00945 bool intersection2l (const tCube &q0, const tCube &q1, BitField *bits)
00946 {
00947         // determine the set of cells at the intersection of layers
00948         const hashedset<typename tCube::CellType> &ident =
00949                 tCell2l<typename tCube::CellType>::identify ();
00950 
00951         // compute the intersection of the cubes
00952         typename tCube::CellType intersection (q0, q1);
00953         hashedset<typename tCube::CellType> faces;
00954         faces. add (intersection);
00955 
00956         // check all the faces of the cells
00957         int_t current = 0;
00958         int_t counter = 0;
00959         while (current < faces. size ())
00960         {
00961                 const typename tCube::CellType &face = faces [current ++];
00962                 if (ident. check (face))
00963                 {
00964                         if (bits)
00965                                 bits -> set (neighbor2bit (q0, face));
00966                         ++ counter;
00967                 }
00968                 else
00969                 {
00970                         for (int_t i = 0; i < boundarylength (face); ++ i)
00971                                 faces. add (boundarycell (face, i));
00972                 }
00973         }
00974         return (counter > 0);
00975 } /* intersection2l */
00976 
00979 template <class tCube, class tCubeSet1, class tCubeSet2>
00980 int_t getneighbors_scan (const tCube2l<tCube> &q2l, BitField *bits,
00981         const tCubeSet1 &theset, tCubeSet2 *neighbors, int_t limit)
00982 {
00983         // decompose the cube into its components
00984         const tCube &q0 = q2l. cube ();
00985         typename tCube2l<tCube>::LayerType l0 (q2l. layer ());
00986 
00987         // determine the set of cubes at layer 0
00988         const hashedset<tCube> &layer0 = tCube2l<tCube>::layer0 ();
00989 
00990         // prepare a counter for the number of neighbors
00991         int_t count = 0;
00992 
00993         // go through all the elements in the set
00994         for (int_t i = 0; i < theset. size (); ++ i)
00995         {
00996                 // take the cube from the set
00997                 const tCube2l<tCube> &q1l = theset [i];
00998 
00999                 // if this is the current cube then ignore it
01000                 if (q1l == q2l)
01001                         continue;
01002 
01003                 // decompose the cube into its components
01004                 const tCube &q1 = q1l. cube ();
01005                 typename tCube2l<tCube>::LayerType l1 (q1l. layer ());
01006 
01007                 // determine the number of this neighbor
01008                 int_t number = neighbor2bit (q0, q1);
01009 
01010                 // if not neighbor then ignore it
01011                 if (number < 0)
01012                         continue;
01013 
01014                 // if the cubes fully intersect then this is easy
01015                 if ((l0 == l1) ||
01016                         ((l0 == 0) && (l1 == 1) && (layer0. check (q0))) ||
01017                         ((l0 == 1) && (l1 == 0) && (layer0. check (q1))))
01018                 {
01019                         // set the appropriate bit in the bit field
01020                         if (bits)
01021                                 bits -> set (number);
01022                 }
01023                 // otherwise the correct intersection of the cubes
01024                 // must be determined at the boundary between the layers
01025                 else if (!intersection2l (q0, q1, bits))
01026                         continue;
01027 
01028                 // add the cube to the set of neighbors
01029                 if (neighbors)
01030                         neighbors -> add (q1l);
01031 
01032                 // increase the counter
01033                 ++ count;
01034 
01035                 // if this is enough then finish
01036                 if (limit && (count >= limit))
01037                         return count;
01038         }
01039 
01040         return count;
01041 } /* getneighbors_scan */
01042 
01046 template <class tCube, class tCubeSet1, class tCubeSet2>
01047 int_t getneighbors_generate (const tCube2l<tCube> &q2l, BitField *bits,
01048         const tCubeSet1 &theset, tCubeSet2 *neighbors, int_t limit)
01049 {
01050         // decompose the cube into its components
01051         const tCube &q0 = q2l. cube ();
01052         typename tCube2l<tCube>::LayerType l0 (q2l. layer ());
01053 
01054         // determine the upper bound for the number of neighbors
01055         int_t maxneighbors = getmaxneighbors (q0. dim ());
01056 
01057         // determine the set of cubes at layer 0
01058         const hashedset<tCube> &layer0 = tCube2l<tCube>::layer0 ();
01059 
01060         // determine the set of cubes at layer 1
01061         const hashedset<tCube> &layer1 = tCube2l<tCube>::layer1 ();
01062 
01063         // prepare a counter for the number of neighbors
01064         int_t count = 0;
01065 
01066         // go through all possible neighbor numbers
01067         for (int_t number = 0; number < maxneighbors; ++ number)
01068         {
01069                 // create a neighbor cube using the generic algorithm
01070                 tCube q1 = bit2neighbor (q0, number, true);
01071 
01072                 // determine the layer of the neighbor
01073                 int l1 = layer1. check (q1) ? 1 : 0;
01074 
01075                 // create the neighbor cube
01076                 tCube2l<tCube> q1l (q1, l1);
01077 
01078                 // if this cube is not in the set then skip it
01079                 if (!theset. check (q1l))
01080                         continue;
01081 
01082                 // if the cubes fully intersect then this is easy
01083                 if ((l0 == l1) ||
01084                         ((l0 == 0) && (l1 == 1) && (layer0. check (q0))) ||
01085                         ((l0 == 1) && (l1 == 0) && (layer0. check (q1))))
01086                 {
01087                         // set the appropriate bit in the bit field
01088                         if (bits)
01089                                 bits -> set (number);
01090                 }
01091                 // otherwise the correct intersection of the cubes
01092                 // must be determined at the boundary between the layers
01093                 else if (!intersection2l (q0, q1, bits))
01094                         continue;
01095 
01096                 // add the cube to the set of neighbors
01097                 if (neighbors)
01098                         neighbors -> add (q1l);
01099 
01100                 // increase the counter
01101                 ++ count;
01102 
01103                 // if this is enough then finish
01104                 if (limit && (count >= limit))
01105                         return count;
01106         }
01107 
01108         return count;
01109 } /* getneighbors_generate */
01110 
01116 template <class euclidom, class tCell, class tCube>
01117 int_t createimages (mvcellmap<tCell2l<tCell>,euclidom,tCube2l<tCube> > &m,
01118         const mvmap<tCube2l<tCube>,tCube2l<tCube> > &f1,
01119         const mvmap<tCube2l<tCube>,tCube2l<tCube> > &f2,
01120         const hashedset<tCube2l<tCube> > &dom1,
01121         const hashedset<tCube2l<tCube> > &dom2)
01122 {
01123         typedef typename tCube::CoordType coordType;
01124         int_t countimages = 0;
01125         coordType leftbound [tCell::MaxDim];
01126         coordType rightbound [tCell::MaxDim];
01127         coordType left [tCell::MaxDim];
01128         coordType right [tCell::MaxDim];
01129 
01130         // go through all the dimensions of the cellular complex separtely
01131         for (int d = 0; d <= m. dim (); ++ d)
01132         {
01133                 const hashedset<tCell2l<tCell> > &cset = m. get (d);
01134                 if (cset. empty ())
01135                         continue;
01136                 const int spacedim = cset [0]. spacedim ();
01137 
01138                 // go through the cells of the specified dimension
01139                 for (int_t i = 0; i < cset. size (); ++ i)
01140                 {
01141                         // remember the cell whose image is computed
01142                         const tCell2l<tCell> &thecell = cset [i];
01143 
01144                         // determine tha layer of the cell
01145                         const typename tCube2l<tCube>::LayerType layer =
01146                                 thecell. layer ();
01147 
01148                         // check if the layers are identified at the cell
01149                         bool idlayers = tCell2l<tCell>::identify ().
01150                                 check (thecell. cell ());
01151 
01152                         // get the coordinates of the corners of the cell
01153                         thecell. leftcoord (left);
01154                         thecell. rightcoord (right);
01155 
01156                         // compute the bounds for full cubes to get imgs of
01157                         for (int j = 0; j < spacedim; ++ j)
01158                         {
01159                                 // compensate for space wrapping
01160                                 if (right [j] < left [j])
01161                                         right [j] = left [j] + 1;
01162 
01163                                 // compute the bounds for full cubes
01164                                 leftbound [j] = static_cast<coordType>
01165                                         (left [j] - (left [j] == right [j]));
01166                                 rightbound [j] = static_cast<coordType>
01167                                         (right [j] +
01168                                         (left [j] == right [j]));
01169                         }
01170 
01171                         // go through the full cubes in the computed range
01172                         tRectangle<coordType> r (leftbound, rightbound,
01173                                 spacedim);
01174                         const coordType *c;
01175                         while ((c = r. get ()) != NULL)
01176                         {
01177                                 // determine the core cube
01178                                 if (!tCube::PointBase::check (c, spacedim))
01179                                         continue;
01180                                 tCube q0 (c, spacedim);
01181 
01182                                 // add the images of the 2-layer cube
01183                                 tCube2l<tCube> q (q0, layer);
01184                                 if (dom1. check (q))
01185                                         m. add (d, i, f1 (q));
01186                                 if (dom2. check (q))
01187                                         m. add (d, i, f2 (q));
01188 
01189                                 // determine if the cubes at the other
01190                                 // layer must also be considered
01191                                 typename tCube2l<tCube>::LayerType l = layer;
01192                                 if (idlayers && !layer &&
01193                                         tCube2l<tCube>::layer1 ().
01194                                         check (q0))
01195                                 {
01196                                         l = 1;
01197                                 }
01198                                 else if (idlayers && layer &&
01199                                         tCube2l<tCube>::layer0 ().
01200                                         check (q0))
01201                                 {
01202                                         l = 0;
01203                                 }
01204                                 if (l != layer)
01205                                 {
01206                                         tCube2l<tCube> ql (q0, l);
01207                                         if (dom1. check (ql))
01208                                                 m. add (d, i, f1 (ql));
01209                                         if (dom2. check (ql))
01210                                                 m. add (d, i, f2 (ql));
01211                                 }
01212                         }
01213                         countimages += m (thecell). size ();
01214                 }
01215         }
01216         return countimages;
01217 } /* createimages */
01218 
01219 
01220 // --------------------------------------------------
01221 // ----------------- standard types -----------------
01222 // --------------------------------------------------
01223 
01225 typedef tCube2l<tCubeBase<coordinate> > Cube2l;
01226 
01228 typedef tCell2l<tCellBase<coordinate> > CubicalCell2l;
01229 
01231 typedef mvmap<Cube2l,Cube2l> CombinatorialMultivaluedMap2l;
01232 
01234 typedef hashedset<Cube2l> SetOfCubes2l;
01235 
01237 typedef hashedset<CubicalCell2l> SetOfCubicalCells2l;
01238 
01240 typedef gcomplex<CubicalCell2l,integer> CubicalComplex2l;
01241 
01243 typedef mvcellmap<CubicalCell2l,integer,CubicalCell2l>
01244         CubicalMultivaluedMap2l;
01245 
01246 
01247 } // namespace homology
01248 } // namespace chomp
01249 
01250 #endif // _CHOMP_CUBES_TWOLAYER_H_
01251 
01253