00001
00002
00003
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #ifndef _CHOMP_CUBES_POINTSET_H_
00047 #define _CHOMP_CUBES_POINTSET_H_
00048
00049 #include "chomp/system/config.h"
00050 #include "chomp/system/textfile.h"
00051
00052 #include <iostream>
00053 #include <fstream>
00054 #include <ctime>
00055 #include <cstdlib>
00056 #include <cctype>
00057
00058 namespace chomp {
00059 namespace homology {
00060
00061
00063 typedef short int coordinate;
00064
00065
00066 class psethashstat;
00067
00068
00069 template <class coordtype>
00070 class tPointset;
00071
00072
00073 template <class coordtype>
00074 class tNeighbors;
00075
00076
00077 template <class coordtype>
00078 class tRectangle;
00079
00081 typedef tPointset<coordinate> pointset;
00082
00084 typedef tNeighbors<coordinate> neighbors;
00085
00087 typedef tRectangle<coordinate> rectangle;
00088
00089
00090
00091
00092
00093
00094
00095
00097 template <class coordtype>
00098 inline int thesame (const coordtype *c1, const coordtype *c2, int dim)
00099 {
00100 for (int i = 0; i < dim; ++ i)
00101 if (c1 [i] != c2 [i])
00102 return 0;
00103 return 1;
00104 }
00105
00107 template <class coordtype>
00108 inline void copycoord (coordtype *destination, const coordtype *source,
00109 int dim)
00110 {
00111 for (int i = 0; i < dim; ++ i)
00112 destination [i] = source [i];
00113 return;
00114 }
00115
00118 template <class coordtype>
00119 inline void wrapcoord (coordtype *destination, const coordtype *source,
00120 const coordtype *wrap, int dim)
00121 {
00122 if (!destination || !source)
00123 throw "Trying to wrap NULL coordinates.";
00124
00125 for (int i = 0; i < dim; ++ i)
00126 if (wrap [i])
00127 {
00128 destination [i] =
00129 (coordtype) (source [i] % wrap [i]);
00130 if (destination [i] < 0)
00131 destination [i] += wrap [i];
00132 }
00133 else
00134 destination [i] = source [i];
00135
00136 return;
00137 }
00138
00141 inline bool numberisprime (unsigned n)
00142 {
00143 if (n < 2)
00144 return false;
00145
00146 unsigned i = 2;
00147 while (i * i <= n)
00148 if (!(n % i ++))
00149 return false;
00150
00151 return true;
00152 }
00153
00156 inline unsigned ceilprimenumber (unsigned n)
00157 {
00158 while (!numberisprime (n))
00159 ++ n;
00160
00161 return n;
00162 }
00163
00165 template <class coordtype>
00166 int_t pointhashkey (const coordtype *c, int dim, int_t hashsize)
00167 {
00168 int_t key = 13;
00169 for (int i = 0; i < dim; ++ i)
00170 {
00171 key ^= static_cast<int_t> ((c [i] > 0) ? c [i] : -c [i]) <<
00172 ((i << 3) % 19);
00173 }
00174 if (key < 0)
00175 key = -(key + 1);
00176
00177
00178 return (key % hashsize);
00179
00180 }
00181
00183 template <class coordtype>
00184 int_t pointhashadd (const coordtype *c, int dim, int_t hashsize)
00185 {
00186 int_t add = 1313;
00187 for (int i = 0; i < dim; ++ i)
00188 add ^= static_cast<int_t> ((c [i] > 0) ? c [i] : -c [i]) <<
00189 (((i << 4) + 3) % 21);
00190 if (add < 0)
00191 add = -(add + 1);
00192
00193
00194 return (add % (hashsize - 1) + 1);
00195
00196 }
00197
00199 template <class coordtype>
00200 inline coordtype rounddown (double x)
00201 {
00202 if ((x >= 0) || ((double) (coordtype) x == x))
00203 return (coordtype) x;
00204 else
00205 return -(coordtype) (-x) - 1;
00206 }
00207
00211 template <class coordtype>
00212 inline void roundpoint (const double *p, coordtype *c, const double *grid,
00213 int dim)
00214 {
00215 if (grid)
00216 {
00217 for (int i = 0; i < dim; ++ i)
00218 c [i] = rounddown<coordtype> (p [i] / grid [i]);
00219 }
00220 else
00221 {
00222 for (int i = 0; i < dim; ++ i)
00223 c [i] = rounddown<coordtype> (p [i]);
00224 }
00225 return;
00226 }
00227
00230 template <class coordtype>
00231 inline void cubemiddle (coordtype *c, double *p, double *grid, int dim)
00232 {
00233 if (grid)
00234 {
00235 for (int i = 0; i < dim; ++ i)
00236 p [i] = (c [i] + 0.5) * grid [i];
00237 }
00238 else
00239 {
00240 for (int i = 0; i < dim; ++ i)
00241 p [i] = c [i] + 0.5;
00242 }
00243 return;
00244 }
00245
00247 template <class coordtype>
00248 inline coordtype *allocatepoint (int dim, char *errormessage = NULL)
00249 {
00250 coordtype *temp = new coordtype [dim];
00251 if (!temp)
00252 {
00253 throw (errormessage ? errormessage :
00254 "Can't allocate memory for a temporary point.");
00255 }
00256 return temp;
00257 }
00258
00259 #define INSIDE 1
00260 #define OUTSIDE 0
00261
00267 template <class coordtype>
00268 int countneighbors (const tPointset<coordtype> &p, const coordtype *c,
00269 int which = INSIDE, int maxcount = 0);
00270
00272 template <class coordtype>
00273 int countneighbors (const tPointset<coordtype> &p,
00274 const tPointset<coordtype> &q, const coordtype *c,
00275 int which = INSIDE, int maxcount = 0);
00276
00278 template <class coordtype>
00279 int attheborder (const tPointset<coordtype> &p, const coordtype *c);
00280
00285 template <class coordtype>
00286 int_t findboundarypoint (tPointset<coordtype> &p, int_t n,
00287 int direction = 1);
00288
00290 template <class coordtype>
00291 int_t findboundarypoint (tPointset<coordtype> &p,
00292 tPointset<coordtype> &q, int_t n, int direction = 1);
00293
00295 template <class coordtype>
00296 tPointset<coordtype> *computeboundary (tPointset<coordtype> &p);
00297
00300 template <class coordtype>
00301 void computeboundary (tPointset<coordtype> &p, tPointset<coordtype> &b);
00302
00305 template <class coordtype>
00306 void enhancepoint (tPointset<coordtype> &p, coordtype *c);
00307
00310 template <class coordtype>
00311 void enhancepoint (tPointset<coordtype> &p, int_t n);
00312
00315 template <class coordtype>
00316 void enhance (tPointset<coordtype> &p);
00317
00318
00324 template <class coordtype>
00325 int read (textfile &f, coordtype *c, int maxdim);
00326
00332 template <class coordtype>
00333 int read (std::istream &in, coordtype *c, int maxdim);
00334
00335
00336
00337
00338 template <class coordtype>
00339 int write (std::ostream &out, const coordtype *c, int dim,
00340 char parenthesis = 40, char closing = 0);
00341
00342 #define CELL 0
00343 #define CUBE 1
00344
00350 template <class coordtype>
00351 int readcubeorcell (std::istream &in, coordtype *left, coordtype *right,
00352 int maxdim, int *type = NULL);
00353
00354
00357 template <class coordtype>
00358 int_t read (textfile &f, tPointset<coordtype> &p,
00359 int_t first = 0, int_t howmany = -1,
00360 coordtype *wrap = NULL, int maxdim = 0, int quiet = 0,
00361 tPointset<coordtype> *notthese = NULL);
00362
00365 template <class coordtype>
00366 int_t read (std::istream &in, tPointset<coordtype> &p,
00367 int_t first = 0, int_t howmany = -1,
00368 coordtype *wrap = NULL, int maxdim = 0, int quiet = 0,
00369 tPointset<coordtype> *notthese = NULL);
00370
00373 template <class coordtype>
00374 int_t read (textfile &f, tPointset<coordtype> &p,
00375 coordtype *wrap, int maxdim,
00376 int quiet = 0, tPointset<coordtype> *notthese = NULL);
00377
00380 template <class coordtype>
00381 int_t read (std::istream &in, tPointset<coordtype> &p,
00382 coordtype *wrap, int maxdim,
00383 int quiet = 0, tPointset<coordtype> *notthese = NULL);
00384
00386 template <class coordtype>
00387 textfile &operator >> (textfile &f, tPointset<coordtype> &p);
00388
00390 template <class coordtype>
00391 std::istream &operator >> (std::istream &in, tPointset<coordtype> &p);
00392
00396 template <class coordtype>
00397 int_t write (std::ostream &out, tPointset<coordtype> &p,
00398 int_t first = 0, int_t howmany = -1, int quiet = 0);
00399
00401 template <class coordtype>
00402 std::ostream &operator << (std::ostream &out, tPointset<coordtype> &p);
00403
00404
00405
00406
00407
00408
00411 class psethashstat
00412 {
00413 public:
00415 psethashstat ();
00416
00418 std::time_t creationtime;
00419
00422 unsigned long hashhits;
00423
00426 unsigned long hashmisses;
00427
00430 unsigned long rehashcount;
00431
00432 };
00433
00434
00435
00436 inline psethashstat::psethashstat ()
00437 {
00438 std::time (&creationtime);
00439 hashhits = 0;
00440 hashmisses = 0;
00441 rehashcount = 0;
00442 return;
00443 }
00444
00445
00446
00449 inline std::ostream &operator << (std::ostream &out, const psethashstat &s)
00450 {
00451 if (!s. hashhits)
00452 return out;
00453 out << "hashing: " << s. hashhits << " hits, avg " <<
00454 ((s. hashhits + s. hashmisses) / s. hashhits) << "." <<
00455 ((s. hashhits + s. hashmisses) * 10 / s. hashhits) % 10 <<
00456 " attempts (" << s. rehashcount << " times rehashed)";
00457 return out;
00458 }
00459
00460
00461
00462
00463
00464
00466 template <class coordtype>
00467 class tPointset
00468 {
00469 public:
00470
00471
00472
00480 tPointset (int_t initialsize = 0, int bequiet = 1);
00481
00483 tPointset (const tPointset<coordtype> &p);
00484
00486 tPointset &operator = (const tPointset<coordtype> &p);
00487
00489 ~tPointset ();
00490
00491
00492
00493
00495 int dimension (int d);
00496
00498 int dimension () const;
00499
00501 static int defaultdimension (int d = 0);
00502
00504 double *gridsize (double *g = 0);
00505
00507 double *gridsize (double g);
00508
00510 double *gridsize (int direction, double g);
00511
00512
00513
00514 const coordtype *wrapspace (const coordtype *w = NULL);
00515
00516 const coordtype *wrapspace (coordtype w);
00517
00518 const coordtype *wrapspace (int direction, coordtype w);
00519
00520
00521
00522
00523
00524
00525
00526
00527 int check (int_t n) const;
00528 int check (const coordtype *c) const;
00529 int check (const double *c) const;
00530
00531
00532
00533 int_t getnumber (const coordtype *c) const;
00534 int_t getnumber (const double *c) const;
00535
00536
00537
00538
00539 coordtype *operator [] (int_t n) const;
00540 coordtype *getpoint (int_t n) const;
00541 coordtype *getpoint (coordtype *c) const;
00542 coordtype *getpoint (double *c) const;
00543 coordtype *getpoint (int_t n, double *c) const;
00544
00545
00546 int_t add (const coordtype *c);
00547 int_t add (double *c);
00548
00549 tPointset &add (const tPointset<coordtype> &p);
00550
00551
00552
00553
00554
00555 int remove (int_t n);
00556 int remove (const coordtype *c);
00557 int remove (const double *c);
00558
00559 int remove (const tPointset<coordtype> &p);
00560
00561
00562
00563
00565 int_t size () const;
00566
00568 bool empty () const;
00569
00574
00575
00576
00577 int quiet;
00578
00579
00580
00581 int_t gethashsize () const;
00582
00583
00584
00585
00586
00587 psethashstat *stat;
00588
00589
00590 coordtype *minimal, *maximal;
00591
00592
00593
00594
00595
00596 int wereremoved;
00597
00598
00599 protected:
00600
00601
00602
00603
00604 int dim;
00605
00606
00607 int_t npoints;
00608
00609
00610 int_t ntables;
00611
00612
00613 int tablepoints;
00614
00615
00616
00617 coordtype **tables;
00618
00619
00620 double *grid;
00621
00622
00623 coordtype *wrap;
00624
00625
00626
00627 coordtype *temp;
00628
00629
00630 static int defaultdim;
00631 static double *defaultgrid;
00632 static coordtype *defaultwrap;
00633
00634
00635 void initialize (int_t initialsize, int bequiet);
00636 void deallocate ();
00637
00638
00639
00640
00641
00642 int_t hashsize;
00643
00644
00645 int_t hashcleared;
00646
00647
00648 int_t *hashtable;
00649
00650
00651 unsigned initsize;
00652
00653
00654
00655
00656
00657 int_t hashfindpoint (const coordtype *c,
00658 int_t *addposition = NULL, int wrapped = 0) const;
00659
00660
00661
00662
00663 void rehash (int_t newsize = 0);
00664
00665 };
00666
00667
00668
00669 template <class coordtype>
00670 int tPointset<coordtype>::defaultdim = 0;
00671
00672 template <class coordtype>
00673 double *tPointset<coordtype>::defaultgrid = NULL;
00674
00675 template <class coordtype>
00676 coordtype *tPointset<coordtype>::defaultwrap = NULL;
00677
00678
00679
00680 template <class coordtype>
00681 inline int tPointset<coordtype>::defaultdimension (int d)
00682 {
00683
00684 if (d > 0)
00685 {
00686
00687 if (d > defaultdim)
00688 {
00689 if (defaultgrid)
00690 delete [] defaultgrid;
00691 defaultgrid = NULL;
00692 if (defaultwrap)
00693 delete [] defaultwrap;
00694 defaultwrap = NULL;
00695 }
00696
00697
00698 defaultdim = d;
00699 }
00700
00701
00702 return defaultdim;
00703 }
00704
00705 template <class coordtype>
00706 inline double *tPointset<coordtype>::gridsize (int direction, double g)
00707 {
00708
00709
00710 if ((direction < 0) || (direction >= dim) || !dim || (g <= 0))
00711 return grid;
00712
00713
00714 if (!grid)
00715 {
00716 grid = new double [dim];
00717 if (!grid)
00718 throw "Can't allocate memory for the grid.";
00719 for (int i = 0; i < dim; ++ i)
00720 grid [i] = 1.0;
00721 }
00722
00723
00724 if (dim != defaultdim)
00725 defaultdimension (dim);
00726
00727
00728 if (!defaultgrid)
00729 {
00730 defaultgrid = new double [dim];
00731 if (!defaultgrid)
00732 throw "Can't alloc mem for the default grid.";
00733 for (int i = 0; i < dim; ++ i)
00734 defaultgrid [i] = grid [i];
00735 }
00736
00737
00738 grid [direction] = g;
00739 defaultgrid [direction] = g;
00740
00741
00742 return grid;
00743 }
00744
00745 template <class coordtype>
00746 inline double *tPointset<coordtype>::gridsize (double g)
00747 {
00748
00749 for (int i = 0; i < dim; ++ i)
00750 gridsize (i, g);
00751
00752
00753 return grid;
00754 }
00755
00756 template <class coordtype>
00757 inline double *tPointset<coordtype>::gridsize (double *g)
00758 {
00759
00760 if (!g)
00761 return grid;
00762
00763
00764 for (int i = 0; i < dim; ++ i)
00765 gridsize (i, g [i]);
00766
00767
00768 return grid;
00769 }
00770
00771 template <class coordtype>
00772 inline const coordtype *tPointset<coordtype>::wrapspace
00773 (int direction, coordtype w)
00774 {
00775
00776
00777 if ((direction < 0) || (direction >= dim) || !dim || (w < 0))
00778 return wrap;
00779
00780
00781 if (!wrap)
00782 {
00783 wrap = new coordtype [dim];
00784 if (!wrap)
00785 throw "Can't alloc mem for the wrap table.";
00786 for (int i = 0; i < dim; ++ i)
00787 wrap [i] = 0;
00788 }
00789
00790
00791 if (dim != defaultdim)
00792 defaultdimension (dim);
00793
00794
00795 if (!defaultwrap)
00796 {
00797 defaultwrap = new coordtype [dim];
00798 if (!defaultwrap)
00799 throw "Can't alloc mem for the def. WrapTab.";
00800 for (int i = 0; i < dim; ++ i)
00801 defaultwrap [i] = wrap [i];
00802 }
00803
00804
00805 wrap [direction] = w;
00806 defaultwrap [direction] = w;
00807
00808
00809 return wrap;
00810 }
00811
00812 template <class coordtype>
00813 inline const coordtype *tPointset<coordtype>::wrapspace (coordtype w)
00814 {
00815
00816 for (int i = 0; i < dim; ++ i)
00817 wrapspace (i, w);
00818
00819
00820 return wrap;
00821 }
00822
00823 template <class coordtype>
00824 inline const coordtype *tPointset<coordtype>::wrapspace (const coordtype *w)
00825 {
00826
00827 if (!w)
00828 return wrap;
00829
00830
00831 for (int i = 0; i < dim; ++ i)
00832 wrapspace (i, w [i]);
00833
00834
00835 return wrap;
00836 }
00837
00838 template <class coordtype>
00839 inline int tPointset<coordtype>::dimension (int d)
00840 {
00841
00842 if (d > 0)
00843 defaultdimension (d);
00844
00845
00846 if (!npoints && (d > 0))
00847 {
00848
00849 if (d > dim)
00850 {
00851 if (grid)
00852 delete [] grid;
00853 grid = NULL;
00854 gridsize (defaultgrid);
00855 if (wrap)
00856 delete [] wrap;
00857 wrap = NULL;
00858 wrapspace (defaultwrap);
00859 if (temp)
00860 delete [] temp;
00861 temp = NULL;
00862 }
00863
00864
00865 dim = d;
00866 }
00867
00868
00869 return dim;
00870 }
00871
00872 template <class coordtype>
00873 inline int tPointset<coordtype>::dimension () const
00874 {
00875 return dim;
00876 }
00877
00878 template <class coordtype>
00879 inline int_t tPointset<coordtype>::size () const
00880 {
00881 return npoints;
00882 }
00883
00884 template <class coordtype>
00885 inline bool tPointset<coordtype>::empty () const
00886 {
00887 return !npoints;
00888 }
00889
00890
00891
00892
00893
00894
00895
00896 template <class coordtype>
00897 inline coordtype *tPointset<coordtype>::operator [] (int_t n) const
00898 {
00899 if ((n < 0) || (n >= npoints))
00900 return NULL;
00901
00902 return (tables [n / tablepoints] + (n % tablepoints) * dim);
00903 }
00904
00905 template <class coordtype>
00906 inline int_t tPointset<coordtype>::hashfindpoint (const coordtype *c,
00907 int_t *addpos, int wrapped) const
00908 {
00909
00910 if (!hashsize)
00911 return -1;
00912
00913
00914 if (!wrapped && wrap)
00915 {
00916 if (!temp)
00917 throw "Unable to wrap point's coordinates.";
00918 wrapcoord (temp, c, wrap, dim);
00919 c = temp;
00920 }
00921
00922
00923 int_t pos = pointhashkey (c, dim, hashsize);
00924 int_t add = 0;
00925
00926
00927 ++ (stat -> hashhits);
00928
00929
00930 int_t number;
00931 while ((number = hashtable [pos]) != -1)
00932 {
00933 if ((number >= 0) && thesame ((*this) [number], c, dim))
00934 return (pos);
00935 if (addpos && (*addpos < 0) && (number == -2))
00936 *addpos = pos;
00937 if (!add)
00938 add = pointhashadd (c, dim, hashsize);
00939 pos = (pos + add) % hashsize;
00940 ++ (stat -> hashmisses);
00941 }
00942
00943
00944 return (pos);
00945 }
00946
00947 template <class coordtype>
00948 inline void tPointset<coordtype>::rehash (int_t newsize)
00949 {
00950
00951 if (newsize)
00952 newsize = ceilprimenumber (newsize);
00953 else if (!npoints && initsize && !hashsize)
00954 newsize = ceilprimenumber (initsize);
00955
00956
00957 if (newsize <= npoints + npoints / 5)
00958 {
00959
00960 newsize = ceilprimenumber ((npoints << 1) + 131);
00961
00962
00963 int x = 0xFFFF;
00964 if ((x < 0) && (newsize >= 16384))
00965 throw "Pointset too large for a 16-bit prog.";
00966 }
00967
00968
00969 if (hashsize && !quiet)
00970 sout << "(Changing the hashing table from " << hashsize <<
00971 " to " << newsize << " at " << npoints << " points) ";
00972 else if (!quiet)
00973 sout << "(Using a hashing table for " << newsize << " ";
00974
00975
00976 hashsize = newsize;
00977 if (hashtable)
00978 delete [] hashtable;
00979 hashtable = new int_t [hashsize];
00980 if (!hashtable)
00981 throw "Can't allocate memory for a hashing table.";
00982 for (int_t i = 0; i < hashsize; ++ i)
00983 hashtable [i] = -1;
00984 hashcleared = 0;
00985
00986
00987 for (int_t j = 0; j < npoints; ++ j)
00988 {
00989 int_t n = hashfindpoint ((*this) [j], NULL, 1);
00990 if (hashtable [n] != -1)
00991 throw "A repeated point found in the hashing table.";
00992 hashtable [n] = j;
00993 }
00994
00995 ++ (stat -> rehashcount);
00996
00997 if (!quiet)
00998 sout << "points.)\n";
00999
01000 return;
01001 }
01002
01003 template <class coordtype>
01004 inline int_t tPointset<coordtype>::add (const coordtype *c)
01005 {
01006
01007 if (!c)
01008 return -1;
01009
01010
01011 if (!dim)
01012 throw "Trying to add a point of unknown dimension.";
01013
01014
01015 if (wrap)
01016 {
01017 if (!temp)
01018 temp = allocatepoint<coordtype> (dim);
01019 wrapcoord (temp, c, wrap, dim);
01020 c = temp;
01021 }
01022
01023
01024 if (hashsize - hashcleared <= npoints + npoints / 5)
01025 rehash ();
01026
01027
01028 int_t addpos = -1;
01029 int_t pos = hashfindpoint (c, &addpos, 1);
01030
01031
01032 if (hashtable [pos] >= 0)
01033 return hashtable [pos];
01034
01035
01036 if (minimal)
01037 {
01038 for (int i = 0; i < dim; ++ i)
01039 if (minimal [i] > c [i])
01040 minimal [i] = c [i];
01041 }
01042 else
01043 {
01044 minimal = allocatepoint<coordtype> (dim);
01045 copycoord (minimal, c, dim);
01046 }
01047
01048 if (maximal)
01049 {
01050 for (int i = 0; i < dim; ++ i)
01051 if (maximal [i] < c [i])
01052 maximal [i] = c [i];
01053 }
01054 else
01055 {
01056 maximal = allocatepoint<coordtype> (dim);
01057 copycoord (maximal, c, dim);
01058 }
01059
01060
01061 if (addpos >= 0)
01062 {
01063 pos = addpos;
01064 if (hashtable [pos] == -2)
01065 -- hashcleared;
01066 }
01067 hashtable [pos] = npoints;
01068
01069
01070
01071 int_t tablenumber = npoints / tablepoints;
01072
01073
01074 if (tablenumber >= ntables)
01075 {
01076 int_t moretables = (ntables << 1) + 13;
01077 coordtype **newtables = new coordtype * [moretables];
01078 if (!newtables)
01079 throw "Unable to alloc a table for tables.";
01080 for (int_t i = 0; i < moretables; ++ i)
01081 newtables [i] = (i < ntables) ? (tables [i]) :
01082 (coordtype *) NULL;
01083 if (tables)
01084 delete [] tables;
01085 tables = newtables;
01086 ntables = moretables;
01087 }
01088
01089
01090 if (tables [tablenumber] == NULL)
01091 {
01092 tables [tablenumber] = new coordtype [tablepoints * dim];
01093 if (!tables [tablenumber])
01094 throw "Unable to alloc a table for coords.";
01095 }
01096
01097
01098 copycoord (tables [tablenumber] +
01099 ((npoints % tablepoints) * dim), c, dim);
01100
01101
01102
01103 return (npoints ++);
01104 }
01105
01106 template <class coordtype>
01107 inline int_t tPointset<coordtype>::add (double *c)
01108 {
01109
01110 if (!c)
01111 return -1;
01112
01113 if (!dim)
01114 throw "Trying to add a point of unknown dimension.";
01115 if (!temp)
01116 temp = allocatepoint<coordtype> (dim);
01117 roundpoint (c, temp, grid, dim);
01118 return add (temp);
01119 }
01120
01121 template <class coordtype>
01122 inline tPointset<coordtype> &tPointset<coordtype>::add
01123 (const tPointset<coordtype> &p)
01124 {
01125 int_t size = p. size ();
01126 for (int_t i = 0; i < size; ++ i)
01127 this -> add (p [i]);
01128 return *this;
01129 }
01130
01131 template <class coordtype>
01132 inline void tPointset<coordtype>::initialize (int_t initialsize, int bequiet)
01133 {
01134
01135 quiet = bequiet;
01136
01137
01138 if (initialsize < 0)
01139 initialsize = 0;
01140
01141
01142 npoints = 0;
01143 ntables = 0;
01144 if (initialsize <= 0)
01145 tablepoints = 3000;
01146 else if (initialsize > 10000)
01147 tablepoints = 10000;
01148 else
01149 tablepoints = static_cast<int> (initialsize);
01150 tables = NULL;
01151
01152
01153 dim = 0;
01154 grid = NULL;
01155 wrap = NULL;
01156 temp = NULL;
01157 wereremoved = 0;
01158 dimension (defaultdimension ());
01159 gridsize (defaultgrid);
01160 wrapspace (defaultwrap);
01161
01162
01163 hashsize = 0;
01164 hashcleared = 0;
01165 hashtable = NULL;
01166 if (initialsize)
01167 initsize = initialsize + initialsize / 5 + 3;
01168 else
01169 initsize = 0;
01170
01171
01172 stat = new psethashstat;
01173 minimal = NULL;
01174 maximal = NULL;
01175
01176 return;
01177 }
01178
01179 template <class coordtype>
01180 inline tPointset<coordtype>::tPointset (int_t initialsize, int bequiet)
01181 {
01182 initialize (initialsize, bequiet);
01183 return;
01184 }
01185
01186 template <class coordtype>
01187 inline tPointset<coordtype>::tPointset (const tPointset<coordtype> &p)
01188 {
01189 initialize (p. size (), p. quiet);
01190 add (p);
01191 return;
01192 }
01193
01194 template <class coordtype>
01195 inline void tPointset<coordtype>::deallocate ()
01196 {
01197
01198 for (int_t i = 0; i < ntables; ++ i)
01199 {
01200 if (tables [i])
01201 delete [] (tables [i]);
01202 }
01203 if (tables)
01204 delete [] tables;
01205
01206
01207 if (grid)
01208 delete [] grid;
01209 if (wrap)
01210 delete [] wrap;
01211
01212
01213 if (temp)
01214 delete [] temp;
01215
01216
01217 if (minimal)
01218 delete [] minimal;
01219 if (maximal)
01220 delete [] maximal;
01221
01222
01223 if (hashtable)
01224 delete [] hashtable;
01225
01226 if (stat)
01227 delete stat;
01228
01229 return;
01230 }
01231
01232 template <class coordtype>
01233 inline tPointset<coordtype> &tPointset<coordtype>::operator =
01234 (const tPointset<coordtype> &p)
01235 {
01236 deallocate ();
01237 initialize (p. size (), p. quiet);
01238 add (p);
01239 return *this;
01240 }
01241
01242 template <class coordtype>
01243 inline tPointset<coordtype>::~tPointset<coordtype> ()
01244 {
01245 deallocate ();
01246 return;
01247 }
01248
01249 template <class coordtype>
01250 inline int_t tPointset<coordtype>::getnumber (const coordtype *c) const
01251 {
01252
01253 if (!c)
01254 return -1;
01255
01256
01257 int_t pos = hashfindpoint (c);
01258
01259
01260 return ((pos >= 0) ? hashtable [pos] : static_cast<int_t> (-1));
01261 }
01262
01263 template <class coordtype>
01264 inline int_t tPointset<coordtype>::getnumber (const double *c) const
01265 {
01266 if (!npoints)
01267 return -1;
01268 if (!temp)
01269 throw "Cannot round point's coordinates.";
01270 roundpoint (c, temp, grid, dim);
01271 int_t pos = hashfindpoint (temp);
01272 return ((pos >= 0) ? hashtable [pos] : static_cast<int_t> (-1));
01273 }
01274
01275 template <class coordtype>
01276 inline int tPointset<coordtype>::check (int_t n) const
01277 {
01278 return ((n >= 0) && (n < npoints));
01279 }
01280
01281 template <class coordtype>
01282 inline int tPointset<coordtype>::check (const coordtype *c) const
01283 {
01284 return (getnumber (c) != -1);
01285 }
01286
01287 template <class coordtype>
01288 inline int tPointset<coordtype>::check (const double *c) const
01289 {
01290 return (getnumber (c) != -1);
01291 }
01292
01293 template <class coordtype>
01294 inline coordtype *tPointset<coordtype>::getpoint (int_t n) const
01295 {
01296 return (*this) [n];
01297 }
01298
01299 template <class coordtype>
01300 inline coordtype *tPointset<coordtype>::getpoint (coordtype *c) const
01301 {
01302 return (*this) [getnumber (c)];
01303 }
01304
01305 template <class coordtype>
01306 inline coordtype *tPointset<coordtype>::getpoint (double *c) const
01307 {
01308 return (*this) [getnumber (c)];
01309 }
01310
01311 template <class coordtype>
01312 inline coordtype *tPointset<coordtype>::getpoint (int_t n, double *c) const
01313 {
01314 coordtype *coord = (*this) [n];
01315 if (coord && c)
01316 {
01317 for (int i = 0; i < dim; ++ i)
01318 c [i] = (grid ? grid [i] : 1.0) * (0.5 + coord [i]);
01319 }
01320
01321 return coord;
01322 }
01323
01324 template <class coordtype>
01325 inline int tPointset<coordtype>::remove (int_t n)
01326 {
01327 if ((n < 0) || (n >= npoints))
01328 return -1;
01329 wereremoved = 1;
01330
01331
01332 coordtype *coord = (*this) [n];
01333 int_t pos = hashfindpoint (coord);
01334
01335
01336 hashtable [pos] = -2;
01337
01338
01339 if (n != npoints - 1)
01340 {
01341 coordtype *lastcoord = (*this) [npoints - 1];
01342 int_t lastpos = hashfindpoint (lastcoord);
01343 hashtable [lastpos] = n;
01344 copycoord (coord, lastcoord, dim);
01345 }
01346
01347
01348 int_t tablenumber = npoints / tablepoints;
01349 if ((tablenumber + 2 < ntables) && tables [tablenumber + 2])
01350 {
01351 delete [] (tables [tablenumber + 2]);
01352 tables [tablenumber + 2] = NULL;
01353 }
01354
01355
01356 -- npoints;
01357
01358
01359 ++ hashcleared;
01360
01361
01362 if (hashcleared > npoints + 13)
01363 rehash (13);
01364
01365 return (0);
01366 }
01367
01368 template <class coordtype>
01369 inline int tPointset<coordtype>::remove (const coordtype *c)
01370 {
01371 return remove (getnumber (c));
01372 }
01373
01374 template <class coordtype>
01375 inline int tPointset<coordtype>::remove (const double *c)
01376 {
01377 return remove (getnumber (c));
01378 }
01379
01380 template <class coordtype>
01381 inline int tPointset<coordtype>::remove (const tPointset<coordtype> &p)
01382 {
01383 int_t size = p. size ();
01384 for (int_t i = 0; i < size; ++ i)
01385 remove (p [i]);
01386 return 0;
01387 }
01388
01389 template <class coordtype>
01390 inline int_t tPointset<coordtype>::gethashsize () const
01391 {
01392 return hashsize;
01393 }
01394
01395
01396
01397
01398
01399
01403 template <class coordtype>
01404 class tNeighbors
01405 {
01406 public:
01408 tNeighbors (const coordtype *_source = NULL, int _dim = 0,
01409 const coordtype *_wrap = NULL);
01410
01412 tNeighbors (const tNeighbors<coordtype> &r);
01413
01415 tNeighbors &operator = (const tNeighbors<coordtype> &r);
01416
01418 ~tNeighbors ();
01419
01422 coordtype *get ();
01423
01425 void reset ();
01426
01428 void set (coordtype *_source);
01429
01430 private:
01432 int dim;
01433
01435 const coordtype *source;
01436
01438 coordtype *neighbor;
01439
01441 signed char *counters;
01442
01444 const coordtype *wrap;
01445
01447 void initialize (const coordtype *_source = NULL,
01448 int _dim = 0, const coordtype *_wrap = NULL);
01449
01451 void deallocate ();
01452
01453 };
01454
01455
01456
01457 template <class coordtype>
01458 void tNeighbors<coordtype>::initialize (const coordtype *_source, int _dim,
01459 const coordtype *_wrap)
01460 {
01461 source = _source;
01462 wrap = _wrap;
01463 dim = _dim;
01464 if (dim <= 0)
01465 {
01466 dim = 0;
01467 neighbor = NULL;
01468 counters = NULL;
01469 return;
01470 }
01471 neighbor = new coordtype [dim];
01472 counters = new signed char [dim];
01473 if (!neighbor || !counters)
01474 throw "Can't allocate memory for neighbors.";
01475 reset ();
01476 return;
01477 }
01478
01479 template <class coordtype>
01480 tNeighbors<coordtype>::tNeighbors (const coordtype *_source, int _dim,
01481 const coordtype *_wrap)
01482 {
01483 initialize (_source, _dim, _wrap);
01484 return;
01485 }
01486
01487 template <class coordtype>
01488 tNeighbors<coordtype>::tNeighbors (const tNeighbors<coordtype> &n)
01489 {
01490 initialize (n. source, n. dim, n. wrap);
01491 return;
01492 }
01493
01494 template <class coordtype>
01495 tNeighbors<coordtype> &tNeighbors<coordtype>::operator =
01496 (const tNeighbors<coordtype> &n)
01497 {
01498 deallocate ();
01499 initialize (n. source, n. dim, n. wrap);
01500 return *this;
01501 }
01502
01503 template <class coordtype>
01504 void tNeighbors<coordtype>::deallocate ()
01505 {
01506 if (neighbor)
01507 delete [] neighbor;
01508 if (counters)
01509 delete [] counters;
01510 return;
01511 }
01512
01513 template <class coordtype>
01514 tNeighbors<coordtype>::~tNeighbors<coordtype> ()
01515 {
01516 deallocate ();
01517 return;
01518 }
01519
01520 template <class coordtype>
01521 void tNeighbors<coordtype>::reset ()
01522 {
01523 if (counters)
01524 {
01525 for (int i = 0; i < dim; ++ i)
01526 counters [i] = 0;
01527 }
01528 return;
01529 }
01530
01531 template <class coordtype>
01532 void tNeighbors<coordtype>::set (coordtype *_source)
01533 {
01534 source = _source;
01535 return;
01536 }
01537
01538 template <class coordtype>
01539 coordtype *tNeighbors<coordtype>::get ()
01540 {
01541
01542 if (!dim || !counters || !neighbor || !source)
01543 return NULL;
01544
01545
01546
01547 int cur = 0;
01548 while ((cur < dim) && (counters [cur] == -1))
01549 counters [cur ++] = 0;
01550 if (cur >= dim)
01551 return NULL;
01552 counters [cur] = counters [cur] ?
01553 (signed char) -1 : (signed char) 1;
01554
01555
01556 for (int i = 0; i < dim; ++ i)
01557 neighbor [i] = (coordtype) (source [i] + counters [i]);
01558
01559
01560 if (wrap)
01561 wrapcoord (neighbor, neighbor, wrap, dim);
01562
01563
01564 return neighbor;
01565
01566 }
01567
01568
01569
01570
01571
01572
01580 template <class coordtype>
01581 class tRectangle
01582 {
01583 public:
01585 tRectangle (const coordtype *_left = NULL,
01586 const coordtype *_right = NULL, int _dim = 0);
01587
01589 tRectangle (const tRectangle<coordtype> &r);
01590
01592 tRectangle &operator = (const tRectangle<coordtype> &r);
01593
01595 ~tRectangle ();
01596
01599 const coordtype *get ();
01600
01602 void reset ();
01603
01604 private:
01606 int dim;
01607
01609 const coordtype *left;
01610
01612 const coordtype *right;
01613
01615 coordtype *point;
01616
01618 int firstpoint;
01619
01621 void initialize (const coordtype *_left = NULL,
01622 const coordtype *_right = NULL, int _dim = 0);
01623
01625 void deallocate ();
01626
01627 };
01628
01629
01630
01631 template <class coordtype>
01632 void tRectangle<coordtype>::initialize (const coordtype *_left,
01633 const coordtype *_right, int _dim)
01634 {
01635 firstpoint = 0;
01636 left = _left;
01637 right = _right;
01638 dim = _dim;
01639 if (dim <= 0)
01640 {
01641 dim = 0;
01642 point = NULL;
01643 return;
01644 }
01645 point = new coordtype [dim];
01646 if (!point)
01647 throw "Can't allocate memory for a rectangle.";
01648 reset ();
01649
01650 return;
01651 }
01652
01653 template <class coordtype>
01654 tRectangle<coordtype>::tRectangle (const coordtype *_left, const coordtype *_right,
01655 int _dim)
01656 {
01657 initialize (_left, _right, _dim);
01658 return;
01659 }
01660
01661 template <class coordtype>
01662 tRectangle<coordtype>::tRectangle (const tRectangle<coordtype> &r)
01663 {
01664 initialize (r. left, r. right, r. dim);
01665 return;
01666 }
01667
01668 template <class coordtype>
01669 tRectangle<coordtype> &tRectangle<coordtype>::operator = (const tRectangle<coordtype> &r)
01670 {
01671 deallocate ();
01672 initialize (r. left, r. right, r. dim);
01673 return *this;
01674 }
01675
01676 template <class coordtype>
01677 void tRectangle<coordtype>::deallocate ()
01678 {
01679 if (point)
01680 delete [] point;
01681 return;
01682 }
01683
01684 template <class coordtype>
01685 tRectangle<coordtype>::~tRectangle<coordtype> ()
01686 {
01687 deallocate ();
01688 return;
01689 }
01690
01691 template <class coordtype>
01692 void tRectangle<coordtype>::reset ()
01693 {
01694 for (int i = 0; i < dim; ++ i)
01695 point [i] = left [i];
01696 firstpoint = 1;
01697 return;
01698 }
01699
01700 template <class coordtype>
01701 const coordtype *tRectangle<coordtype>::get ()
01702 {
01703
01704 if (firstpoint)
01705 {
01706 firstpoint = 0;
01707 for (int i = 0; i < dim; ++ i)
01708 if (left [i] >= right [i])
01709 return NULL;
01710 return point;
01711 }
01712
01713
01714 int cur = 0;
01715 while ((cur < dim) && (++ (point [cur]) >= right [cur]))
01716 {
01717 point [cur] = left [cur];
01718 ++ cur;
01719 }
01720
01721
01722 if (cur >= dim)
01723 {
01724 firstpoint = 1;
01725 return NULL;
01726 }
01727
01728
01729 return point;
01730
01731 }
01732
01733
01734
01735
01736
01737
01739 template <class coordtype>
01740 int countneighbors (const tPointset<coordtype> &p, const coordtype *c,
01741 int which, int maxcount)
01742 {
01743 if (p. empty ())
01744 {
01745 if (which == INSIDE)
01746 return 0;
01747 else
01748 return maxcount;
01749 }
01750
01751 int count = 0;
01752 tNeighbors<coordtype> neigh (c, p. dimension ());
01753 while ((c = neigh. get ()) != NULL)
01754 {
01755 if (which == INSIDE)
01756 {
01757 if (p. check (c))
01758 ++ count;
01759 }
01760 else if (which == OUTSIDE)
01761 {
01762 if (!p. check (c))
01763 ++ count;
01764 }
01765
01766 if (maxcount && (count >= maxcount))
01767 return count;
01768 }
01769
01770 return count;
01771 }
01772
01773 template <class coordtype>
01774 int countneighbors (const tPointset<coordtype> &p,
01775 const tPointset<coordtype> &q, coordtype *c,
01776 int which, int maxcount)
01777 {
01778 if ((q. empty ()) || (p. dimension () != q. dimension ()))
01779 return countneighbors (p, c, which, maxcount);
01780 else if (p. empty ())
01781 return countneighbors (q, c, which, maxcount);
01782
01783 int count = 0;
01784 tNeighbors<coordtype> neigh (c, p. dimension ());
01785 while ((c = neigh. get ()) != NULL)
01786 {
01787 if (which == INSIDE)
01788 {
01789 if (p. check (c) || q. check (c))
01790 ++ count;
01791 }
01792 else if (which == OUTSIDE)
01793 {
01794 if (!p. check (c) && !q. check (c))
01795 ++ count;
01796 }
01797
01798 if (maxcount && (count >= maxcount))
01799 return count;
01800 }
01801
01802 return count;
01803 }
01804
01805 template <class coordtype>
01806 int attheborder (const tPointset<coordtype> &p, const coordtype *c)
01807 {
01808 return (countneighbors (p, c, OUTSIDE, 1));
01809
01810 }
01811
01812 template <class coordtype>
01813 int_t findboundarypoint (tPointset<coordtype> &p, int_t n, int direction)
01814 {
01815 if (direction >= 0)
01816 {
01817 if (n >= p. size ())
01818 return -1;
01819 if (n < 0)
01820 n = 0;
01821 int_t size = p. size ();
01822 while (n < size)
01823 {
01824 if (attheborder (p, p [n]))
01825 return n;
01826 else
01827 ++ n;
01828 }
01829 return -1;
01830 }
01831 else
01832 {
01833 if (n < 0)
01834 return -1;
01835 if (n >= p. size ())
01836 n = p. size () - 1;
01837 while (n >= 0)
01838 {
01839 if (attheborder (p, p [n]))
01840 return n;
01841 else
01842 -- n;
01843 }
01844 return -1;
01845 }
01846 }
01847
01848 template <class coordtype>
01849 int_t findboundarypoint (tPointset<coordtype> &p, tPointset<coordtype> &q,
01850 int_t n, int direction)
01851 {
01852 if (direction >= 0)
01853 {
01854 if (n >= p. size ())
01855 return -1;
01856 if (n < 0)
01857 n = 0;
01858 while (n < p. size ())
01859 {
01860 if (countneighbors (p, q, p [n], OUTSIDE, 1))
01861 return n;
01862 else
01863 ++ n;
01864 }
01865 return -1;
01866 }
01867 else
01868 {
01869 if (n < 0)
01870 return -1;
01871 if (n >= p. size ())
01872 n = p. size () - 1;
01873 while (n >= 0)
01874 {
01875 if (countneighbors (p, q, p [n], OUTSIDE, 1))
01876 return n;
01877 else
01878 -- n;
01879 }
01880 return -1;
01881 }
01882 }
01883
01884 template <class coordtype>
01885 void computeboundary (const tPointset<coordtype> &p, tPointset<coordtype> &b)
01886 {
01887
01888 int_t size = p. size ();
01889 for (int_t i = 0; i < size; ++ i)
01890 {
01891 coordtype *c = p [i];
01892 if (attheborder (p, c))
01893 b. add (c);
01894 }
01895 return;
01896 }
01897
01898 template <class coordtype>
01899 tPointset<coordtype> *computeboundary (tPointset<coordtype> &p)
01900 {
01901
01902 tPointset<coordtype> *boundary = new tPointset<coordtype>;
01903
01904
01905 if (!boundary)
01906 return NULL;
01907
01908
01909 boundary -> dimension (p. dimension ());
01910 boundary -> gridsize (p. gridsize ());
01911 boundary -> wrapspace (p. wrapspace ());
01912
01913
01914 computeboundary (p, *boundary);
01915
01916 return boundary;
01917 }
01918
01919 template <class coordtype>
01920 void enhancepoint (tPointset<coordtype> &p, coordtype *c)
01921 {
01922 tNeighbors<coordtype> neigh (c, p. dimension ());
01923
01924 while ((c = neigh. get ()) != NULL)
01925 p. add (c);
01926
01927 return;
01928 }
01929
01930 template <class coordtype>
01931 void enhancepoint (tPointset<coordtype> &p, int_t n)
01932 {
01933 enhancepoint (p, p [n]);
01934
01935 return;
01936 }
01937
01938 template <class coordtype>
01939 void enhance (tPointset<coordtype> &p)
01940 {
01941 int_t size = p. size ();
01942 for (int_t i = 0; i < size; ++ i)
01943 enhancepoint (p, p [i]);
01944
01945 return;
01946 }
01947
01948 template <class coordtype>
01949 int read (textfile &f, coordtype *c, int maxdim)
01950 {
01951
01952
01953 int ready = 0;
01954 while (!ready)
01955 {
01956 switch (f. checkchar ())
01957 {
01958 case '(':
01959 case '[':
01960 case '{':
01961 case '"':
01962 case '\'':
01963 f. readchar ();
01964 ready = 1;
01965 break;
01966 case '+':
01967 case '-':
01968 break;
01969 case EOF:
01970 return 0;
01971 default:
01972 f. ignoreline ();
01973 break;
01974 }
01975 }
01976
01977
01978 int n = 0;
01979 while (1)
01980 {
01981
01982 c [n ++] = (coordtype) f. readnumber ();
01983
01984
01985
01986 switch (f. checkchar ())
01987 {
01988 case ')':
01989 case ']':
01990 case '}':
01991 case '"':
01992 case '\'':
01993 f. readchar ();
01994 return n;
01995 case ',':
01996 f. readchar ();
01997 break;
01998 case '-':
01999 case '+':
02000 break;
02001 default:
02002 if ((f. checkchar () < '0') ||
02003 (f. checkchar () > '9'))
02004 return n;
02005 }
02006
02007
02008 if (n >= maxdim)
02009 return n;
02010 }
02011 }
02012
02013 template <class coordtype>
02014 int read (std::istream &in, coordtype *c, int maxdim)
02015 {
02016 textfile f (in);
02017 return read (f, c, maxdim);
02018 }
02019
02027 template <class coordtype>
02028 inline int readcoordinates (std::istream &in, coordtype *coord, int maxdim,
02029 int closing)
02030 {
02031
02032 if (closing == EOF)
02033 closing = readparenthesis (in);
02034 if (closing == EOF)
02035 return -1;
02036
02037 int cur = 0;
02038
02039 ignorecomments (in);
02040 while ((in. peek () != closing) && (cur < maxdim))
02041 {
02042
02043 if (in. peek () == '+')
02044 in. get ();
02045
02046
02047 if ((in. peek () != '-') && !std::isdigit (in. peek ()))
02048 break;
02049
02050
02051 long number;
02052 in >> number;
02053
02054
02055
02056
02057 coord [cur] = (coordtype) number;
02058 if (coord [cur] != number)
02059 return -1;
02060
02061
02062 ++ cur;
02063 if (closing == '\n')
02064 {
02065 while ((in. peek () == ' ') ||
02066 (in. peek () == '\t') ||
02067 (in. peek () == '\r'))
02068 in. get ();
02069 }
02070 else
02071 ignorecomments (in);
02072
02073
02074 if (in. peek () == ',')
02075 {
02076 in. get ();
02077 ignorecomments (in);
02078 }
02079 }
02080
02081
02082
02083
02084
02085
02086 if (in. peek () == closing)
02087 in. get ();
02088 else if ((closing == '\n') && (in. peek () == EOF))
02089 ;
02090 else
02091 return -1;
02092
02093 return cur;
02094 }
02095
02096 template <class coordtype>
02097 inline int readcoordinates (std::istream &in, coordtype *coord, int maxdim)
02098 {
02099 return readcoordinates (in, coord, maxdim, EOF);
02100 }
02101
02102 template <class coordtype>
02103 int write (std::ostream &out, const coordtype *c, int dim, char parenthesis,
02104 char closing)
02105 {
02106
02107 if (parenthesis != 0)
02108 out << parenthesis;
02109
02110
02111 for (int i = 0; i < dim; ++ i)
02112 {
02113 if (i)
02114 out << ",";
02115 out << c [i];
02116 }
02117
02118
02119 if (closing)
02120 out << closing;
02121 else if (parenthesis)
02122 {
02123 int ch = closingparenthesis (parenthesis);
02124 if (ch == EOF)
02125 closing = parenthesis;
02126 else
02127 closing = (char) ch;
02128 out << closing;
02129 }
02130
02131 return dim;
02132 }
02133
02134 template <class coordtype>
02135 int readcubeorcell (std::istream &in, coordtype *left, coordtype *right,
02136 int maxdim, int *type)
02137 {
02138
02139 int closing;
02140 while ((closing = closingparenthesis (in. peek ())) == EOF)
02141 {
02142 ignoreline (in);
02143 ignorecomments (in);
02144 if (!in)
02145 return 0;
02146 }
02147
02148
02149 int dim = readcoordinates (in, left, maxdim);
02150
02151
02152 if (dim > 0)
02153 {
02154
02155 ignorecomments (in);
02156 if (((in. peek () != 'x') && (in. peek () != 'X')) ||
02157 (dim > 2))
02158 {
02159
02160 for (int i = 0; i < dim; ++ i)
02161 right [i] = (coordtype) (left [i] + 1);
02162 if (type)
02163 *type = CUBE;
02164 return dim;
02165 }
02166
02167
02168 right [0] = (dim < 2) ? left [0] : left [1];
02169 dim = 1;
02170 coordtype temp [2];
02171 while ((in. peek () == 'x') || (in. peek () == 'X'))
02172 {
02173 if (dim >= maxdim)
02174 throw "Too many intervals in a product.";
02175 in. get ();
02176 ignorecomments (in);
02177 int d = readcoordinates (in, temp, 2);
02178 if ((d <= 0) || !in)
02179 throw "Can't read a product of intervals.";
02180 left [dim] = temp [0];
02181 right [dim] = (d < 2) ? temp [0] : temp [1];
02182 ++ dim;
02183 ignorecomments (in);
02184 }
02185 if (type)
02186 *type = CELL;
02187 return dim;
02188 }
02189
02190
02191 else
02192 {
02193
02194 in. clear (in. rdstate () & ~std::ios::failbit);
02195 ignorecomments (in);
02196
02197
02198 int leftdim = readcoordinates (in, left, maxdim);
02199 ignorecomments (in);
02200 int rightdim = readcoordinates (in, right, maxdim);
02201 ignorecomments (in);
02202
02203
02204 if (!leftdim || !rightdim)
02205 throw "Can't read a cell.";
02206 else if (leftdim != rightdim)
02207 throw "Different dim of left & right point.";
02208 else
02209 dim = leftdim;
02210
02211
02212 if (in. get () != closing)
02213 throw "Can't read the closing bracket of a cell.";
02214 ignorecomments (in);
02215 if (type)
02216 *type = CELL;
02217 }
02218 return dim;
02219 }
02220
02221 template <class coordtype>
02222 int_t read (textfile &f, tPointset<coordtype> &p,
02223 int_t first, int_t howmany,
02224 coordtype *wrap, int maxdim, int quiet,
02225 tPointset<coordtype> *notthese)
02226 {
02227
02228 if (maxdim <= 0)
02229 {
02230 if (wrap)
02231 wrap = NULL;
02232 maxdim = 100;
02233 }
02234 coordtype *temp = allocatepoint<coordtype> (maxdim + 1);
02235
02236 int_t count = 0;
02237 int dim = p. empty () ? 0 : p. dimension ();
02238
02239 if (notthese && !notthese -> empty ())
02240 {
02241 if (!dim)
02242 dim = notthese -> dimension ();
02243 else if (dim != notthese -> dimension ())
02244 {
02245 if (!quiet)
02246 sout << "Error: Dimensions not the same.\n";
02247 return -1;
02248 }
02249 }
02250
02251 while (1)
02252 {
02253
02254 if ((howmany >= 0) && (count >= howmany))
02255 {
02256 delete [] temp;
02257 return count;
02258 }
02259
02260
02261
02262 while ((f. checkchar () != 40) && (f. checkchar () != 91) &&
02263 (f. checkchar () != 123) && (f. checkchar () != EOF))
02264 f. ignoreline ();
02265
02266
02267 if (f. checkchar () == EOF)
02268 {
02269 delete [] temp;
02270 return count;
02271 }
02272
02273
02274 int n = read (f, temp, maxdim + 1);
02275 if (n > maxdim)
02276 {
02277 if (!quiet)
02278 sout << "Line " << f. linenumber () <<
02279 ": The point has too many " <<
02280 "coordinates.\n";
02281 delete [] temp;
02282 return -1;
02283 }
02284
02285
02286
02287 if (!first && dim && n && (n != dim))
02288 {
02289 if (!quiet)
02290 sout << "Line " << f. linenumber () <<
02291 ": Incorrect point dimension.\n";
02292 delete [] temp;
02293 return -1;
02294 }
02295
02296
02297 if (!first && !dim)
02298 {
02299 dim = n;
02300 if (p. dimension () != dim)
02301 p. dimension (dim);
02302 }
02303
02304
02305 if (first)
02306 -- first;
02307 else
02308 {
02309 if (wrap)
02310 {
02311 p. wrapspace (wrap);
02312 wrap = NULL;
02313 }
02314 if (!notthese || !notthese -> check (temp))
02315 p. add (temp);
02316 ++ count;
02317 }
02318 }
02319 }
02320
02321 template <class coordtype>
02322 int_t read (std::istream &in, tPointset<coordtype> &p,
02323 int_t first, int_t howmany, coordtype *wrap, int maxdim,
02324 int quiet, tPointset<coordtype> *notthese)
02325 {
02326 textfile f (in);
02327 return read (f, p, first, howmany, wrap, maxdim, quiet, notthese);
02328 }
02329
02330 template <class coordtype>
02331 int_t read (textfile &f, tPointset<coordtype> &p,
02332 coordtype *wrap, int maxdim,
02333 int quiet, tPointset<coordtype> *notthese)
02334 {
02335 return read (f, p, 0, -1, wrap, maxdim, quiet, notthese);
02336 }
02337
02338 template <class coordtype>
02339 int_t read (std::istream &in, tPointset<coordtype> &p, coordtype *wrap,
02340 int maxdim, int quiet, tPointset<coordtype> *notthese)
02341 {
02342 textfile f (in);
02343 return read (f, p, wrap, maxdim, quiet, notthese);
02344 }
02345
02346 template <class coordtype>
02347 textfile &operator >> (textfile &f, tPointset<coordtype> &p)
02348 {
02349 read (f, p);
02350 return f;
02351 }
02352
02353 template <class coordtype>
02354 std::istream &operator >> (std::istream &in, tPointset<coordtype> &p)
02355 {
02356 textfile f (in);
02357 read (f, p);
02358 return in;
02359 }
02360
02361 template <class coordtype>
02362 int_t write (std::ostream &out, tPointset<coordtype> &p,
02363 int_t first, int_t howmany, int)
02364 {
02365 int_t count = 0;
02366 int dim = p. dimension ();
02367
02368
02369 out << "; The set contains " << p. size () << " points.\n";
02370 if (first)
02371 out << "; Not writing first " << first << " points.\n";
02372 if (howmany >= 0)
02373 out << "; Writing at most " << howmany << " points.\n";
02374
02375
02376 if (dim && p. gridsize ())
02377 {
02378 for (int i = 0; i < dim; ++ i)
02379 out << (i ? ", " : "; Grid size: ") <<
02380 p. gridsize () [i];
02381 out << '\n';
02382 }
02383
02384
02385 if (p. gethashsize ())
02386 out << "; Hashing table size: " <<
02387 p. gethashsize () << " entries.\n";
02388
02389 if (p. stat -> hashhits)
02390 out << "; Hashing statistics: " <<
02391 ((p. stat -> hashhits + p. stat -> hashmisses) /
02392 p. stat -> hashhits) << '.' <<
02393 ((p. stat -> hashhits + p. stat -> hashmisses) * 10 /
02394 p. stat -> hashhits) % 10 << " trials per point, " <<
02395 p. stat -> rehashcount << " times rehashed.\n";
02396
02397 if (p. minimal && p. maximal)
02398 {
02399 out << "; The coordinates " <<
02400 (p. wereremoved ? "varied" : "vary") << " from ";
02401 write (out, p. minimal, dim);
02402 out << " to ";
02403 write (out, p. maximal, dim);
02404 out << ".\n";
02405 }
02406
02407 std::time_t tm;
02408 std::time (&tm);
02409 out << "; Work time: " << (tm - p. stat -> creationtime) <<
02410 " seconds.\n";
02411
02412
02413 if (p. wereremoved)
02414 out << "; Warning: Points were removed, " <<
02415 "so their original order may be distorted.\n";
02416
02417
02418
02419 out << "dimension " << p. dimension () << '\n';
02420
02421
02422 int_t size = p. size ();
02423 for (int_t i = first; i < size; ++ i)
02424 {
02425 if ((howmany >= 0) && (count >= howmany))
02426 return count;
02427 write (out, p [i], dim);
02428 out << '\n';
02429 ++ count;
02430 }
02431
02432 return count;
02433 }
02434
02435 template <class coordtype>
02436 std::ostream &operator << (std::ostream &out, tPointset<coordtype> &p)
02437 {
02438 write (out, p);
02439 return out;
02440 }
02441
02442
02443 }
02444 }
02445
02446 #endif // _CHOMP_CUBES_POINTSET_H_
02447
02449