The Conley-Morse Graphs Software
psetjoin.cpp
Go to the documentation of this file.
1/// @addtogroup homology
2/// @{
3
4/////////////////////////////////////////////////////////////////////////////
5///
6/// @file psetjoin.cpp
7///
8/// A program for joining topologically disjoint sets of points (or cubes).
9///
10/// @author Pawel Pilarczyk
11///
12/////////////////////////////////////////////////////////////////////////////
13
14// Copyright (C) 1997-2020 by Pawel Pilarczyk.
15//
16// This file is part of my research software package. This is free software:
17// you can redistribute it and/or modify it under the terms of the GNU
18// General Public License as published by the Free Software Foundation,
19// either version 3 of the License, or (at your option) any later version.
20//
21// This software is distributed in the hope that it will be useful,
22// but WITHOUT ANY WARRANTY; without even the implied warranty of
23// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24// GNU General Public License for more details.
25//
26// You should have received a copy of the GNU General Public License
27// along with this software; see the file "license.txt". If not,
28// please, see <https://www.gnu.org/licenses/>.
29
30// Started on November 20, 2006. Last revision: August 23, 2010.
31
32
33#include "chomp/system/config.h"
34#include "chomp/system/textfile.h"
35#include "chomp/cubes/pointset.h"
36#include "chomp/struct/hashsets.h"
37#include "chomp/system/timeused.h"
38#include "chomp/system/arg.h"
39
40#include <exception>
41#include <new>
42#include <iostream>
43#include <iomanip>
44#include <fstream>
45#include <cstdlib>
46#include <ctime>
47#include <sstream>
48#include <vector>
49#include <algorithm>
50
51using namespace chomp::homology;
52
53
54// --------------------------------------------------
55// -------------------- OVERTURE --------------------
56// --------------------------------------------------
57
58const char *title = "\
59Join PointSets, ver. 0.02. Copyright (C) 1997-2020 by Pawel Pilarczyk.\n\
60This is free software. No warranty. Consult 'license.txt' for details.";
61
62const char *helpinfo ="\
63Call with: infile1.cub ... infileN.cub prefix.\n\
64The program reads the sets of points in the given files,\n\
65and joins these sets which are topologically disjoint, that is,\n\
66can be separted back by taking their connected components.\n\
67The resulting sets are written to prefix001.cub, prefix002.cub, etc.\n\
68Switches and additional arguments:\n\
69-d N - the minimal distance between the sets (default: 1),\n\
70-s N - don't join the largest N input sets,\n\
71-h - display this brief help information only and exit.\n\
72For more information ask the author at http://www.PawelPilarczyk.com/.";
73
74const int maxnames = 16000;
75
77{
78public:
79 const coordinate *operator [] (int i) {return (*p) [i];}
80
81 pointset *p;
82
83}; /* class pointsetptr */
84
85inline bool operator < (const pointsetptr &x, const pointsetptr &y)
86{
87 // ! REVERSE ORDER !
88 return (x. p -> size () > y. p -> size ());
89} /* operator < */
90
91
92// --------------------------------------------------
93// -------------------- PSETJOIN --------------------
94// --------------------------------------------------
95
96int psetbold (pointset &p, int howmany, bool debug = false)
97{
98 int_t cur = 0;
99 while (howmany --)
100 {
101 int_t maxpoint = p. size ();
102 if (debug)
103 sout << "\n" << howmany << " - " << maxpoint;
104 if (debug)
105 std::cout << "\n==========\n" << p << "\n==========\n";
106 while (cur < maxpoint)
107 {
108 // add the neighbors of this point
109 neighbors n (p [cur ++], p. dimension ());
110 const coordinate *c;
111 while ((c = n. get ()) != 0)
112 {
113 if (debug)
114 sout << "#";
115 if (debug)
116 {
117 for (int i = 0; i < p. dimension (); ++ i)
118 sout << (i ? " " : "(") << c [i];
119 sout << ")";
120 }
121 if (p. check (c))
122 {
123 if (debug)
124 sout << "&";
125 continue;
126 }
127 if (debug)
128 sout << "+";
129 if (countneighbors (p, c, INSIDE, 1))
130 p. add (c);
131 if (debug)
132 sout << "=";
133 }
134 }
135 }
136 return 0;
137} /* psetbold */
138
139bool disjoint (const pointset &p, const pointset &q)
140{
141 if (p. size () > q. size ())
142 return disjoint (q, p);
143 for (int_t i = 0; i < p. size (); ++ i)
144 {
145 if (q. check (p [i]))
146 return false;
147 }
148 return true;
149} /* disjoint */
150
151/// Joins the sets of cubes.
152/// Returns: 0 = Ok, -1 = Error.
153int joinsets (char *innames [], int nnames, char *prefix, int distance,
154 int firstset)
155{
156 // make sure that the value of "firstset" is correct
157 if (firstset < 0)
158 firstset = 0;
159 if (firstset >= nnames)
160 firstset = nnames - 1;
161
162 // read the sets of points
163 sout << "Reading " << nnames << " input files... ";
164 std::vector <pointsetptr> p (nnames);
165 int count = 0;
166 for (int i = 0; i < nnames; ++ i)
167 {
168 std::ifstream in (innames [i]);
169 if (!in)
170 fileerror (innames [i]);
171 p [i]. p = new pointset;
172 in >> *(p [i]. p);
173 count += p [i]. p -> size ();
174 }
175 sout << count << " points total read.\n";
176
177 // sort the sets according to the number of cubes
178 std::sort (p. begin (), p. end ());
179
180 // create neighborhoods of the sets of points
181 sout << "Enhancing the sets... ";
182 pointset **bold = new pointset * [nnames];
183 for (int i = firstset; i < nnames; ++ i)
184 {
185 bold [i] = new pointset;
186 bold [i] -> add (*(p [i]. p));
187 psetbold (*(bold [i]), distance);
188 }
189 sout << "Done.\n";
190
191 // join the sets which are disjoint
192 sout << "Joining the sets... ";
193 int nsets = nnames;
194 for (int i = firstset; i < nsets; ++ i)
195 {
196 for (int j = firstset; j < nsets; ++ j)
197 {
198 if ((i == j) || !disjoint (*(bold [i]), *(p [j]. p)))
199 continue;
200 bold [i] -> add (*(bold [j]));
201 delete bold [j];
202 p [i]. p -> add (*(p [j]. p));
203 delete p [j]. p;
204 -- nsets;
205 for (int k = j; k < nsets; ++ k)
206 {
207 bold [k] = bold [k + 1];
208 p [k]. p = p [k + 1]. p;
209 }
210 }
211 }
212 sout << "Done.\n";
213
214 // write the components to the output file
215 sout << "Writing " << nsets << " files... ";
216 for (int n = 0; n < nsets; ++ n)
217 {
218 // prepare a file name for this set
219 std::ostringstream s;
220 s << prefix;
221 for (int digit = 10000; digit > 1; digit /= 10)
222 if (((n + 1) < digit) && (nsets >= digit))
223 s << '0';
224 s << (n + 1) << ".cub";
225
226 // open a file to write the components to
227 std::ofstream out (s. str (). c_str ());
228 if (!out)
229 fileerror (s. str (). c_str (), "create");
230 out << *(p [n]. p);
231 delete (p [n]. p);
232 if (n >= firstset)
233 delete bold [n];
234 }
235 sout << "Done.\n";
236
237 return 0;
238} /* join sets */
239
240
241// --------------------------------------------------
242// ---------------------- MAIN ----------------------
243// --------------------------------------------------
244
245/// The main function of the program.
246/// Returns: 0 = Ok, -1 = Error, 1 = Help displayed, 2 = Wrong arguments.
247int main (int argc, char *argv [])
248{
249 char *filenames [maxnames];
250 int nnames = 0;
251 int distance = 1;
252 int firstset = 0;
253
254 arguments a;
255 arg (a, "d", distance);
256 arg (a, "s", firstset);
257 arg (a, NULL, filenames, nnames, maxnames);
258 arghelp (a);
259
260 argstreamprepare (a);
261 int argresult = a. analyze (argc, argv);
262 argstreamset ();
263
264 // show the program's title
265 if (argresult >= 0)
266 sout << title << '\n';
267
268 // if not enough file names, help should be displayed
269 if (nnames < 2)
270 argresult = 1;
271
272 // if something was incorrect, show an additional message and exit
273 if (argresult < 0)
274 {
275 sout << "Call with '--help' for help.\n";
276 return 2;
277 }
278
279 // if help requested or no filenames present, show help information
280 if (argresult > 0)
281 {
282 sout << helpinfo << '\n';
283 return 1;
284 }
285
286 // try running the main function and catch an error message if thrown
287 try
288 {
289 joinsets (filenames, nnames - 1, filenames [nnames - 1],
290 distance, firstset);
291 program_time = 1;
292 return 0;
293 }
294 catch (const char *msg)
295 {
296 sout << "ERROR: " << msg << '\n';
297 return -1;
298 }
299 catch (const std::exception &e)
300 {
301 sout << "ERROR: " << e. what () << '\n';
302 return -1;
303 }
304 catch (...)
305 {
306 sout << "ABORT: An unknown error occurred.\n";
307 return -1;
308 }
309} /* main */
310
311/// @}
312
const coordinate * operator[](int i)
Definition: psetjoin.cpp:79
pointset * p
Definition: psetjoin.cpp:81
int psetbold(pointset &p, int howmany, bool debug=false)
Definition: psetjoin.cpp:96
int main(int argc, char *argv[])
The main function of the program.
Definition: psetjoin.cpp:247
const int maxnames
Definition: psetjoin.cpp:74
const char * helpinfo
Definition: psetjoin.cpp:62
int joinsets(char *innames[], int nnames, char *prefix, int distance, int firstset)
Joins the sets of cubes.
Definition: psetjoin.cpp:153
bool operator<(const pointsetptr &x, const pointsetptr &y)
Definition: psetjoin.cpp:85
bool disjoint(const pointset &p, const pointset &q)
Definition: psetjoin.cpp:139
const char * title
Definition: psetjoin.cpp:58