Merge lp:~stellarium/stellarium/catalog-cleanup into lp:stellarium

Proposed by Alexander Wolf
Status: Merged
Merged at revision: 6355
Proposed branch: lp:~stellarium/stellarium/catalog-cleanup
Merge into: lp:stellarium
Diff against target: 1865 lines (+1725/-35)
4 files modified
src/core/modules/StarMgr.cpp (+1/-1)
stars/default/CMakeLists.txt (+1/-1)
stars/default/defaultStarsConfig.json (+33/-33)
util/MakeCombinedCatalogue.v2.C (+1690/-0)
To merge this branch: bzr merge lp:~stellarium/stellarium/catalog-cleanup
Reviewer Review Type Date Requested Status
treaves Approve
Review via email: mp+196293@code.launchpad.net

Description of the change

This branch contains re-packed stars catalogues without a many artifacts.

I prefer merge it by myself.

To post a comment you must log in.
Revision history for this message
treaves (treaves) wrote :

Looks O.K.

I t would be nice to wrap this in a gui at some point.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/core/modules/StarMgr.cpp'
2--- src/core/modules/StarMgr.cpp 2013-10-18 04:42:17 +0000
3+++ src/core/modules/StarMgr.cpp 2013-11-22 14:47:49 +0000
4@@ -68,7 +68,7 @@
5 // This number must be incremented each time the content or file format of the stars catalogs change
6 // It can also be incremented when the defaultStarsConfig.json file change.
7 // It should always matchs the version field of the defaultStarsConfig.json file
8-static const int StarCatalogFormatVersion = 4;
9+static const int StarCatalogFormatVersion = 5;
10
11 // Initialise statics
12 bool StarMgr::flagSciNames = true;
13
14=== modified file 'stars/default/CMakeLists.txt'
15--- stars/default/CMakeLists.txt 2013-05-08 15:48:03 +0000
16+++ stars/default/CMakeLists.txt 2013-11-22 14:47:49 +0000
17@@ -1,5 +1,5 @@
18
19 ########### install files ###############
20
21-INSTALL(FILES defaultStarsConfig.json name.fab stars_0_0v0_3.cat stars_1_0v0_3.cat stars_2_0v0_3.cat stars_3_1v0_2.cat stars_hip_cids_0v0_0.cat stars_hip_sp_0v0_0.cat gcvs_hip_part.dat DESTINATION share/${PACKAGE}/stars/default)
22+INSTALL(FILES defaultStarsConfig.json name.fab stars_0_0v0_4.cat stars_1_0v0_4.cat stars_2_0v0_4.cat stars_3_1v0_3.cat stars_hip_cids_0v0_0.cat stars_hip_sp_0v0_0.cat gcvs_hip_part.dat DESTINATION share/${PACKAGE}/stars/default)
23
24
25=== modified file 'stars/default/defaultStarsConfig.json'
26--- stars/default/defaultStarsConfig.json 2013-05-03 17:35:56 +0000
27+++ stars/default/defaultStarsConfig.json 2013-11-22 14:47:49 +0000
28@@ -1,93 +1,93 @@
29 {
30- "version": 4,
31+ "version": 5,
32 "hipSpectralFile": "stars_hip_sp_0v0_0.cat",
33 "hipComponentsIdsFile": "stars_hip_cids_0v0_0.cat",
34 "catalogs":
35 [
36 {
37 "id": "stars0",
38- "fileName": "stars_0_0v0_3.cat",
39+ "fileName": "stars_0_0v0_4.cat",
40 "count": 0.005,
41 "magRange": [-2, 6],
42 "sizeMb": 0.1,
43- "checksum": "89b6833280270f0846f2c7dae1e310e0",
44+ "checksum": "d18dafce604d850efeab79aa8402222c",
45 "checked": true
46 },
47 {
48 "id": "stars1",
49- "fileName": "stars_1_0v0_3.cat",
50+ "fileName": "stars_1_0v0_4.cat",
51 "count": 0.022,
52 "magRange": [6, 7.5],
53 "sizeMb": 0.6,
54- "checksum": "59eeeb88a0939930a7ae1042fb542bdd",
55+ "checksum": "cdf19a423ed3e129bb5cd6fa0d3a09e2",
56 "checked": true
57 },
58 {
59 "id": "stars2",
60- "fileName": "stars_2_0v0_3.cat",
61+ "fileName": "stars_2_0v0_4.cat",
62 "count": 0.15,
63 "magRange": [7.5, 9],
64 "sizeMb": 4.1,
65- "checksum": "43e4a39a7198761e675b0f490de8a9ae",
66+ "checksum": "5a4c185f79c31c13b0e27d761e407f97",
67 "checked": true
68 },
69 {
70 "id": "stars3",
71- "fileName": "stars_3_1v0_2.cat",
72+ "fileName": "stars_3_1v0_3.cat",
73 "count": 0.43,
74 "magRange": [9, 10.5],
75- "sizeMb": 4.2,
76- "checksum": "7bfebdea2d6fd7eae8958f36edd82a77",
77+ "sizeMb": 4.1,
78+ "checksum": "0b2481f67b0af30dbb027d62761cc061",
79 "checked": true
80 },
81 {
82 "id": "stars4",
83- "fileName": "stars_4_1v0_0.cat",
84+ "fileName": "stars_4_1v0_1.cat",
85 "count": 1.7,
86 "magRange": [10.5, 12],
87 "sizeMb": 17,
88- "url": "http://downloads.sourceforge.net/sourceforge/stellarium/stars_4_1v0_0.cat",
89- "checksum": "3abe460ce558418dbdab9a251c173cc4",
90+ "url": "http://downloads.sourceforge.net/sourceforge/stellarium/stars_4_1v0_1.cat",
91+ "checksum": "7a3b8b3471a755661b6d3686eb4c7cc2",
92 "checked": false
93 },
94 {
95 "id": "stars5",
96- "fileName": "stars_5_2v0_0.cat",
97- "count": 7.7,
98+ "fileName": "stars_5_2v0_1.cat",
99+ "count": 7.1,
100 "magRange": [12, 13.5],
101- "sizeMb": 44,
102- "url": "http://downloads.sourceforge.net/sourceforge/stellarium/stars_5_2v0_0.cat",
103- "checksum": "67278f69d584b95710eba3e322e22f2e",
104+ "sizeMb": 41,
105+ "url": "http://downloads.sourceforge.net/sourceforge/stellarium/stars_5_2v0_1.cat",
106+ "checksum": "50e798428d9402766805da5cf0e8e819",
107 "checked": false
108 },
109 {
110 "id": "stars6",
111- "fileName": "stars_6_2v0_0.cat",
112- "count": 26.6,
113+ "fileName": "stars_6_2v0_1.cat",
114+ "count": 24.7,
115 "magRange": [13.5, 15],
116- "sizeMb": 153,
117- "url": "http://downloads.sourceforge.net/sourceforge/stellarium/stars_6_2v0_0.cat",
118- "checksum": "2f9a908226a5b7732319b950729b658b",
119+ "sizeMb": 142,
120+ "url": "http://downloads.sourceforge.net/sourceforge/stellarium/stars_6_2v0_1.cat",
121+ "checksum": "3005959bf7baca36d266def2fecf36d3",
122 "checked": false
123 },
124 {
125 "id": "stars7",
126- "fileName": "stars_7_2v0_0.cat",
127- "count": 57.8,
128+ "fileName": "stars_7_2v0_1.cat",
129+ "count": 50.8,
130 "magRange": [15, 16.5],
131- "sizeMb": 333,
132- "url": "http://downloads.sourceforge.net/sourceforge/stellarium/stars_7_2v0_0.cat",
133- "checksum": "e05a444abb23232267b10567901b547b",
134+ "sizeMb": 292,
135+ "url": "http://downloads.sourceforge.net/sourceforge/stellarium/stars_7_2v0_1.cat",
136+ "checksum": "15f856fb4c7830a71cb8d60e1decc387",
137 "checked": false
138 },
139 {
140 "id": "stars8",
141- "fileName": "stars_8_2v0_0.cat",
142- "count": 116.9,
143+ "fileName": "stars_8_2v0_1.cat",
144+ "count": 92.3,
145 "magRange": [16.5, 18],
146- "sizeMb": 674,
147- "url": "http://downloads.sourceforge.net/sourceforge/stellarium/stars_8_2v0_0.cat",
148- "checksum": "b804136f5c5584e9508f21a1f7aa1a28",
149+ "sizeMb": 534,
150+ "url": "http://downloads.sourceforge.net/sourceforge/stellarium/stars_8_2v0_1.cat",
151+ "checksum": "9e2e362022824c60d7e4d94ef8c3af12",
152 "checked": false
153 }
154 ]
155
156=== removed file 'stars/default/stars_0_0v0_3.cat'
157Binary files stars/default/stars_0_0v0_3.cat 2013-05-03 17:35:56 +0000 and stars/default/stars_0_0v0_3.cat 1970-01-01 00:00:00 +0000 differ
158=== added file 'stars/default/stars_0_0v0_4.cat'
159Binary files stars/default/stars_0_0v0_4.cat 1970-01-01 00:00:00 +0000 and stars/default/stars_0_0v0_4.cat 2013-11-22 14:47:49 +0000 differ
160=== removed file 'stars/default/stars_1_0v0_3.cat'
161Binary files stars/default/stars_1_0v0_3.cat 2013-05-03 17:35:56 +0000 and stars/default/stars_1_0v0_3.cat 1970-01-01 00:00:00 +0000 differ
162=== added file 'stars/default/stars_1_0v0_4.cat'
163Binary files stars/default/stars_1_0v0_4.cat 1970-01-01 00:00:00 +0000 and stars/default/stars_1_0v0_4.cat 2013-11-22 14:47:49 +0000 differ
164=== removed file 'stars/default/stars_2_0v0_3.cat'
165Binary files stars/default/stars_2_0v0_3.cat 2013-05-03 17:35:56 +0000 and stars/default/stars_2_0v0_3.cat 1970-01-01 00:00:00 +0000 differ
166=== added file 'stars/default/stars_2_0v0_4.cat'
167Binary files stars/default/stars_2_0v0_4.cat 1970-01-01 00:00:00 +0000 and stars/default/stars_2_0v0_4.cat 2013-11-22 14:47:49 +0000 differ
168=== removed file 'stars/default/stars_3_1v0_2.cat'
169Binary files stars/default/stars_3_1v0_2.cat 2013-05-03 17:35:56 +0000 and stars/default/stars_3_1v0_2.cat 1970-01-01 00:00:00 +0000 differ
170=== added file 'stars/default/stars_3_1v0_3.cat'
171Binary files stars/default/stars_3_1v0_3.cat 1970-01-01 00:00:00 +0000 and stars/default/stars_3_1v0_3.cat 2013-11-22 14:47:49 +0000 differ
172=== added file 'util/MakeCombinedCatalogue.v2.C'
173--- util/MakeCombinedCatalogue.v2.C 1970-01-01 00:00:00 +0000
174+++ util/MakeCombinedCatalogue.v2.C 2013-11-22 14:47:49 +0000
175@@ -0,0 +1,1690 @@
176+// Author and Copyright: Johannes Gajdosik, 2006
177+// Modifications: Alexander Wolf, 2013
178+// License: GPL
179+// g++ -O2 MakeCombinedCatalogue.C -o MakeCombinedCatalogue
180+
181+
182+// change catalogue locations according to your needs:
183+
184+const char *nomad_names[]={
185+ "/storage/1T/nomad.sml/Nomad00.sml",
186+ "/storage/1T/nomad.sml/Nomad01.sml",
187+ "/storage/1T/nomad.sml/Nomad02.sml",
188+ "/storage/1T/nomad.sml/Nomad03.sml",
189+ "/storage/1T/nomad.sml/Nomad04.sml",
190+ "/storage/1T/nomad.sml/Nomad05.sml",
191+ "/storage/1T/nomad.sml/Nomad06.sml",
192+ "/storage/1T/nomad.sml/Nomad07.sml",
193+ "/storage/1T/nomad.sml/Nomad08.sml",
194+ "/storage/1T/nomad.sml/Nomad09.sml",
195+ "/storage/1T/nomad.sml/Nomad10.sml",
196+ "/storage/1T/nomad.sml/Nomad11.sml",
197+ "/storage/1T/nomad.sml/Nomad12.sml",
198+ "/storage/1T/nomad.sml/Nomad13.sml",
199+ "/storage/1T/nomad.sml/Nomad14.sml",
200+ "/storage/1T/nomad.sml/Nomad15.sml",
201+ "/storage/1T/nomad.sml/Nomad16.sml",
202+ 0
203+};
204+
205+
206+
207+#define NR_OF_HIP 120416
208+
209+#define MAX_HIP_LEVEL 2
210+#define MAX_TYC_LEVEL 4
211+#define MAX_LEVEL 9
212+
213+static
214+const char *output_file_names[MAX_LEVEL+1] = {
215+ "stars0.cat",
216+ "stars1.cat",
217+ "stars2.cat",
218+ "stars3.cat",
219+ "stars4.cat",
220+ "stars5.cat",
221+ "stars6.cat",
222+ "stars7.cat",
223+ "stars8.cat",
224+ "stars9.cat"
225+};
226+
227+static
228+const char *component_ids_filename = "stars_hip_component_ids.cat";
229+
230+static
231+const char *sp_filename = "stars_hip_sp.cat";
232+
233+static
234+const double level_mag_limit[MAX_LEVEL+1] = {
235+ 6,7.5,9,
236+ 10.5,12,
237+ 13.5,15,16.5,18,19.5
238+};
239+
240+
241+
242+
243+
244+
245+
246+
247+
248+/*
249+
250+Vector (simple 3d-Vector)
251+
252+Author and Copyright: Johannes Gajdosik, 2006
253+
254+License: GPL
255+
256+*/
257+
258+
259+#include <math.h>
260+
261+struct Vector {
262+ double x[3];
263+ inline double length(void) const;
264+ inline void normalize(void);
265+ const Vector &operator+=(const Vector &a) {
266+ x[0] += a.x[0];
267+ x[1] += a.x[1];
268+ x[2] += a.x[2];
269+ }
270+ const Vector &operator-=(const Vector &a) {
271+ x[0] -= a.x[0];
272+ x[1] -= a.x[1];
273+ x[2] -= a.x[2];
274+ }
275+};
276+
277+static inline
278+Vector operator^(const Vector &a,const Vector &b) {
279+ Vector c;
280+ c.x[0] = a.x[1]*b.x[2] - a.x[2]*b.x[1];
281+ c.x[1] = a.x[2]*b.x[0] - a.x[0]*b.x[2];
282+ c.x[2] = a.x[0]*b.x[1] - a.x[1]*b.x[0];
283+ return c;
284+}
285+
286+static inline
287+Vector operator-(const Vector &a,const Vector &b) {
288+ Vector c;
289+ c.x[0] = a.x[0]-b.x[0];
290+ c.x[1] = a.x[1]-b.x[1];
291+ c.x[2] = a.x[2]-b.x[2];
292+ return c;
293+}
294+
295+static inline
296+Vector operator+(const Vector &a,const Vector &b) {
297+ Vector c;
298+ c.x[0] = a.x[0]+b.x[0];
299+ c.x[1] = a.x[1]+b.x[1];
300+ c.x[2] = a.x[2]+b.x[2];
301+ return c;
302+}
303+
304+static inline
305+Vector operator*(double a,const Vector &b) {
306+ Vector c;
307+ c.x[0] = a*b.x[0];
308+ c.x[1] = a*b.x[1];
309+ c.x[2] = a*b.x[2];
310+ return c;
311+}
312+
313+static inline
314+Vector operator*(const Vector &b,double a) {
315+ Vector c;
316+ c.x[0] = a*b.x[0];
317+ c.x[1] = a*b.x[1];
318+ c.x[2] = a*b.x[2];
319+ return c;
320+}
321+
322+static inline
323+double operator*(const Vector &a,const Vector &b) {
324+ return a.x[0]*b.x[0]+a.x[1]*b.x[1]+a.x[2]*b.x[2];
325+}
326+
327+double Vector::length(void) const {
328+ return sqrt(x[0]*x[0]+x[1]*x[1]+x[2]*x[2]);
329+}
330+
331+void Vector::normalize(void) {
332+ const double l = 1.0/length();
333+ x[0] *= l;
334+ x[1] *= l;
335+ x[2] *= l;
336+}
337+
338+
339+
340+
341+void ChangeEpoch(double delta_years,
342+ double &ra,double &dec, // degrees
343+ double pm_ra,double pm_dec // mas/yr
344+ ) {
345+ ra *= (M_PI/180);
346+ dec *= (M_PI/180);
347+
348+ const double cdec = cos(dec);
349+ Vector x = {cos(ra)*cdec,sin(ra)*cdec,sin(dec)};
350+ const Vector north = {0.0,0.0,1.0};
351+
352+ Vector axis0 = north ^ x;
353+ axis0.normalize();
354+ const Vector axis1 = x ^ axis0;
355+
356+ const double f = delta_years*(0.001/3600)*(M_PI/180);
357+
358+ x += pm_ra*f*axis1 + pm_dec*f*axis0;
359+
360+ ra = atan2(x.x[1],x.x[0]);
361+ if (ra < 0.0) ra += 2*M_PI;
362+ dec = atan2(x.x[2],sqrt(x.x[0]*x.x[0]+x.x[1]*x.x[1]));
363+
364+ ra *= (180/M_PI);
365+ dec *= (180/M_PI);
366+}
367+
368+
369+
370+
371+
372+
373+//------------------------------------------------
374+
375+/*
376+
377+GeodesicGrid: a library for dividing the sphere into triangle zones
378+by subdividing the icosahedron
379+
380+Author and Copyright: Johannes Gajdosik, 2006
381+
382+This library requires a simple Vector library,
383+which may have different copyright and license.
384+
385+In the moment I choose to distribute the library under the GPL,
386+later I may choose to additionally distribute it under a more
387+relaxed license like the LGPL. If you want to have the library
388+under another license, please ask me.
389+
390+
391+
392+This library is free software; you can redistribute it and/or
393+modify it under the terms of the GNU General Public License
394+as published by the Free Software Foundation; either version 2
395+of the License, or (at your option) any later version.
396+
397+This library is distributed in the hope that it will be useful,
398+but WITHOUT ANY WARRANTY; without even the implied warranty of
399+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
400+GNU General Public License for more details.
401+
402+You should have received a copy of the GNU General Public License
403+along with this library; if not, write to the Free Software
404+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
405+
406+*/
407+
408+using namespace std;
409+
410+struct HalfSpace {
411+ // all x with x*n-d >= 0
412+ Vector n;
413+ double d;
414+ bool inside(const Vector &x) const {return (x*n>=d);}
415+};
416+
417+class GeodesicGrid {
418+ // Grid of triangles (zones) on the sphere with radius 1,
419+ // generated by subdividing the icosahedron.
420+ // level 0: just the icosahedron, 20 zones
421+ // level 1: 80 zones, level 2: 320 zones, ...
422+ // Each zone has a unique integer number in the range
423+ // [0,getNrOfZones()-1].
424+public:
425+ GeodesicGrid(int max_level);
426+ ~GeodesicGrid(void);
427+ int getMaxLevel(void) const {return max_level;}
428+ static int nrOfZones(int level)
429+ {return (20<<(level<<1));} // 20*4^level
430+ int getNrOfZones(void) const {return nrOfZones(max_level);}
431+ void getTriangleCorners(int lev, int index, Vector& c0, Vector& c1, Vector& c2) const;
432+ // Return the position of the 3 corners for the triangle at the given level and index
433+ int getPartnerTriangle(int lev, int index) const;
434+ // Return the index of the partner triangle with which to form a paralelogram
435+ typedef void (VisitFunc)(int lev,int index,
436+ const Vector &c0,
437+ const Vector &c1,
438+ const Vector &c2,
439+ void *context);
440+ void visitTriangles(int max_visit_level,
441+ VisitFunc *func,void *context) const;
442+
443+ int searchZone(const Vector &v,int search_level) const;
444+ // find the zone number in which a given point lies.
445+ // prerequisite: v*v==1
446+ // When the point lies on the border of two or more zones,
447+ // one such zone is returned (always the same one,
448+ // because the algorithm is deterministic).
449+
450+ void searchZones(const HalfSpace *half_spaces,int nr_of_half_spaces,
451+ int **inside,int **border,int max_search_level) const;
452+ // find all zones that lie fully(inside) or partly(border)
453+ // in the intersection of the given half spaces.
454+ // The result is accurate when (0,0,0) lies on the border of
455+ // each half space. If this is not the case,
456+ // the result may be inaccurate, because it is assumed, that
457+ // a zone lies in a half space when its 3 corners lie in
458+ // this half space.
459+ // inside[l] points to the begin of an integer array of size nrOfZones(l),
460+ // border[l] points to one after the end of the same integer array.
461+ // The array will be filled from the beginning with the inside zone numbers
462+ // and from the end with the border zone numbers of the given level l
463+ // for 0<=l<=getMaxLevel().
464+ // inside[l] will not contain zones that are already contained
465+ // in inside[l1] for some l1 < l.
466+ // In order to restrict search depth set max_search_level < max_level,
467+ // for full search depth set max_search_level = max_level,
468+
469+private:
470+ const Vector& getTriangleCorner(int lev, int index, int cornerNumber) const;
471+ void initTriangle(int lev,int index,
472+ const Vector &c0,
473+ const Vector &c1,
474+ const Vector &c2);
475+ void visitTriangles(int lev,int index,
476+ const Vector &c0,
477+ const Vector &c1,
478+ const Vector &c2,
479+ int max_visit_level,
480+ VisitFunc *func,
481+ void *context) const;
482+ void searchZones(int lev,int index,
483+ const HalfSpace *half_spaces,
484+ const int nr_of_half_spaces,
485+ const int *index_of_used_half_spaces,
486+ const int half_spaces_used,
487+ const bool *corner0_inside,
488+ const bool *corner1_inside,
489+ const bool *corner2_inside,
490+ int **inside,int **border,int max_search_level) const;
491+private:
492+ const int max_level;
493+ struct Triangle {
494+ Vector e0,e1,e2; // Seitenmittelpunkte
495+ };
496+ Triangle **triangles;
497+ // 20*(4^0+4^1+...+4^n)=20*(4*(4^n)-1)/3 triangles total
498+ // 2+10*4^n corners
499+};
500+
501+class GeodesicSearchResult {
502+public:
503+ GeodesicSearchResult(const GeodesicGrid &grid);
504+ ~GeodesicSearchResult(void);
505+ void search(const HalfSpace *half_spaces,
506+ const int nr_of_half_spaces,
507+ int max_search_level);
508+ void search(const Vector &e0,const Vector &e1,const Vector &e2,const Vector &e3,
509+ int max_search_level);
510+ void print(void) const;
511+private:
512+ friend class GeodesicSearchInsideIterator;
513+ friend class GeodesicSearchBorderIterator;
514+ const GeodesicGrid &grid;
515+ int **const zones;
516+ int **const inside;
517+ int **const border;
518+};
519+
520+class GeodesicSearchBorderIterator {
521+public:
522+ GeodesicSearchBorderIterator(const GeodesicSearchResult &r,int level)
523+ : r(r),level((level<0)?0:(level>r.grid.getMaxLevel())
524+ ?r.grid.getMaxLevel():level),
525+ end(r.zones[GeodesicSearchBorderIterator::level]+
526+ GeodesicGrid::nrOfZones(GeodesicSearchBorderIterator::level))
527+ {reset();}
528+ void reset(void) {index = r.border[level];}
529+ int next(void) // returns -1 when finished
530+ {if (index < end) {return *index++;} return -1;}
531+private:
532+ const GeodesicSearchResult &r;
533+ const int level;
534+ const int *const end;
535+ const int *index;
536+};
537+
538+
539+class GeodesicSearchInsideIterator {
540+public:
541+ GeodesicSearchInsideIterator(const GeodesicSearchResult &r,int level)
542+ : r(r),max_level((level<0)?0:(level>r.grid.getMaxLevel())
543+ ?r.grid.getMaxLevel():level)
544+ {reset();}
545+ void reset(void);
546+ int next(void); // returns -1 when finished
547+private:
548+ const GeodesicSearchResult &r;
549+ const int max_level;
550+ int level;
551+ int max_count;
552+ int *index_p;
553+ int *end_p;
554+ int index;
555+ int count;
556+};
557+
558+#include <stdlib.h>
559+#include <cassert>
560+#include <iostream>
561+
562+using namespace std;
563+
564+static const double icosahedron_G = 0.5*(1.0+sqrt(5.0));
565+static const double icosahedron_b = 1.0/sqrt(1.0+icosahedron_G*icosahedron_G);
566+static const double icosahedron_a = icosahedron_b*icosahedron_G;
567+
568+static const Vector icosahedron_corners[12] = {
569+ { icosahedron_a, -icosahedron_b, 0.0},
570+ { icosahedron_a, icosahedron_b, 0.0},
571+ {-icosahedron_a, icosahedron_b, 0.0},
572+ {-icosahedron_a, -icosahedron_b, 0.0},
573+ { 0.0, icosahedron_a, -icosahedron_b},
574+ { 0.0, icosahedron_a, icosahedron_b},
575+ { 0.0, -icosahedron_a, icosahedron_b},
576+ { 0.0, -icosahedron_a, -icosahedron_b},
577+ {-icosahedron_b, 0.0, icosahedron_a},
578+ { icosahedron_b, 0.0, icosahedron_a},
579+ { icosahedron_b, 0.0, -icosahedron_a},
580+ {-icosahedron_b, 0.0, -icosahedron_a}
581+};
582+
583+struct TopLevelTriangle {
584+ int corners[3]; // index der Ecken
585+};
586+
587+
588+static const TopLevelTriangle icosahedron_triangles[20] = {
589+ { 1, 0,10}, // 1
590+ { 0, 1, 9}, // 0
591+ { 0, 9, 6}, // 12
592+ { 9, 8, 6}, // 9
593+ { 0, 7,10}, // 16
594+ { 6, 7, 0}, // 6
595+ { 7, 6, 3}, // 7
596+ { 6, 8, 3}, // 14
597+ {11,10, 7}, // 11
598+ { 7, 3,11}, // 18
599+ { 3, 2,11}, // 3
600+ { 2, 3, 8}, // 2
601+ {10,11, 4}, // 10
602+ { 2, 4,11}, // 19
603+ { 5, 4, 2}, // 5
604+ { 2, 8, 5}, // 15
605+ { 4, 1,10}, // 17
606+ { 4, 5, 1}, // 4
607+ { 5, 9, 1}, // 13
608+ { 8, 9, 5} // 8
609+};
610+
611+
612+
613+GeodesicGrid::GeodesicGrid(const int lev)
614+ :max_level(lev<0?0:lev) {
615+ if (max_level > 0) {
616+ triangles = new Triangle*[max_level];
617+ int nr_of_triangles = 20;
618+ for (int i=0;i<max_level;i++) {
619+ triangles[i] = new Triangle[nr_of_triangles];
620+ nr_of_triangles *= 4;
621+ }
622+ for (int i=0;i<20;i++) {
623+ const int *const corners = icosahedron_triangles[i].corners;
624+ initTriangle(0,i,
625+ icosahedron_corners[corners[0]],
626+ icosahedron_corners[corners[1]],
627+ icosahedron_corners[corners[2]]);
628+ }
629+ } else {
630+ triangles = 0;
631+ }
632+}
633+
634+GeodesicGrid::~GeodesicGrid(void) {
635+ if (max_level > 0) {
636+ for (int i=max_level-1;i>=0;i--) delete[] triangles[i];
637+ delete triangles;
638+ }
639+}
640+
641+void GeodesicGrid::getTriangleCorners(int lev,int index,
642+ Vector &h0,
643+ Vector &h1,
644+ Vector &h2) const {
645+ if (lev <= 0) {
646+ const int *const corners = icosahedron_triangles[index].corners;
647+ h0 = icosahedron_corners[corners[0]];
648+ h1 = icosahedron_corners[corners[1]];
649+ h2 = icosahedron_corners[corners[2]];
650+ } else {
651+ lev--;
652+ const int i = index>>2;
653+ Triangle &t(triangles[lev][i]);
654+ switch (index&3) {
655+ case 0: {
656+ Vector c0,c1,c2;
657+ getTriangleCorners(lev,i,c0,c1,c2);
658+ h0 = c0;
659+ h1 = t.e2;
660+ h2 = t.e1;
661+ } break;
662+ case 1: {
663+ Vector c0,c1,c2;
664+ getTriangleCorners(lev,i,c0,c1,c2);
665+ h0 = t.e2;
666+ h1 = c1;
667+ h2 = t.e0;
668+ } break;
669+ case 2: {
670+ Vector c0,c1,c2;
671+ getTriangleCorners(lev,i,c0,c1,c2);
672+ h0 = t.e1;
673+ h1 = t.e0;
674+ h2 = c2;
675+ } break;
676+ case 3:
677+ h0 = t.e0;
678+ h1 = t.e1;
679+ h2 = t.e2;
680+ break;
681+ }
682+ }
683+}
684+
685+int GeodesicGrid::getPartnerTriangle(int lev, int index) const
686+{
687+ if (lev==0)
688+ {
689+ assert(index<20);
690+ return (index&1) ? index+1 : index-1;
691+ }
692+ switch(index&7)
693+ {
694+ case 2:
695+ case 6:
696+ return index+1;
697+ case 3:
698+ case 7:
699+ return index-1;
700+ case 0:
701+ return (lev==1) ? index+5 : (getPartnerTriangle(lev-1, index>>2)<<2)+1;
702+ case 1:
703+ return (lev==1) ? index+3 : (getPartnerTriangle(lev-1, index>>2)<<2)+0;
704+ case 4:
705+ return (lev==1) ? index-3 : (getPartnerTriangle(lev-1, index>>2)<<2)+1;
706+ case 5:
707+ return (lev==1) ? index-5 : (getPartnerTriangle(lev-1, index>>2)<<2)+0;
708+ default:
709+ assert(0);
710+ }
711+}
712+
713+void GeodesicGrid::initTriangle(int lev,int index,
714+ const Vector &c0,
715+ const Vector &c1,
716+ const Vector &c2) {
717+ Triangle &t(triangles[lev][index]);
718+ t.e0 = c1+c2;
719+ t.e0.normalize();
720+ t.e1 = c2+c0;
721+ t.e1.normalize();
722+ t.e2 = c0+c1;
723+ t.e2.normalize();
724+ lev++;
725+ if (lev < max_level) {
726+ index *= 4;
727+ initTriangle(lev,index+0,c0,t.e2,t.e1);
728+ initTriangle(lev,index+1,t.e2,c1,t.e0);
729+ initTriangle(lev,index+2,t.e1,t.e0,c2);
730+ initTriangle(lev,index+3,t.e0,t.e1,t.e2);
731+ }
732+}
733+
734+
735+void GeodesicGrid::visitTriangles(int max_visit_level,
736+ VisitFunc *func,
737+ void *context) const {
738+ if (func && max_visit_level >= 0) {
739+ if (max_visit_level > max_level) max_visit_level = max_level;
740+ for (int i=0;i<20;i++) {
741+ const int *const corners = icosahedron_triangles[i].corners;
742+ visitTriangles(0,i,
743+ icosahedron_corners[corners[0]],
744+ icosahedron_corners[corners[1]],
745+ icosahedron_corners[corners[2]],
746+ max_visit_level,func,context);
747+ }
748+ }
749+}
750+
751+void GeodesicGrid::visitTriangles(int lev,int index,
752+ const Vector &c0,
753+ const Vector &c1,
754+ const Vector &c2,
755+ int max_visit_level,
756+ VisitFunc *func,
757+ void *context) const {
758+ (*func)(lev,index,c0,c1,c2,context);
759+ Triangle &t(triangles[lev][index]);
760+ lev++;
761+ if (lev <= max_visit_level) {
762+ index *= 4;
763+ visitTriangles(lev,index+0,c0,t.e2,t.e1,max_visit_level,func,context);
764+ visitTriangles(lev,index+1,t.e2,c1,t.e0,max_visit_level,func,context);
765+ visitTriangles(lev,index+2,t.e1,t.e0,c2,max_visit_level,func,context);
766+ visitTriangles(lev,index+3,t.e0,t.e1,t.e2,max_visit_level,func,context);
767+ }
768+}
769+
770+
771+int GeodesicGrid::searchZone(const Vector &v,int search_level) const {
772+ for (int i=0;i<20;i++) {
773+ const int *const corners = icosahedron_triangles[i].corners;
774+ const Vector &c0(icosahedron_corners[corners[0]]);
775+ const Vector &c1(icosahedron_corners[corners[1]]);
776+ const Vector &c2(icosahedron_corners[corners[2]]);
777+ if (((c0^c1)*v >= 0.0) && ((c1^c2)*v >= 0.0) && ((c2^c0)*v >= 0.0)) {
778+ // v lies inside this icosahedron triangle
779+ for (int lev=0;lev<search_level;lev++) {
780+ Triangle &t(triangles[lev][i]);
781+ i <<= 2;
782+ if ((t.e1^t.e2)*v <= 0.0) {
783+ // i += 0;
784+ } else if ((t.e2^t.e0)*v <= 0.0) {
785+ i += 1;
786+ } else if ((t.e0^t.e1)*v <= 0.0) {
787+ i += 2;
788+ } else {
789+ i += 3;
790+ }
791+ }
792+ return i;
793+ }
794+ }
795+ cerr << "software error: not found" << endl;
796+ exit(-1);
797+ // shut up the compiler
798+ return -1;
799+}
800+
801+void GeodesicGrid::searchZones(const HalfSpace *half_spaces,
802+ const int nr_of_half_spaces,
803+ int **inside_list,int **border_list,
804+ int max_search_level) const {
805+ if (max_search_level < 0) max_search_level = 0;
806+ else if (max_search_level > max_level) max_search_level = max_level;
807+ int halfs_used[nr_of_half_spaces];
808+ for (int h=0;h<nr_of_half_spaces;h++) {halfs_used[h] = h;}
809+ bool corner_inside[12][nr_of_half_spaces];
810+ for (int h=0;h<nr_of_half_spaces;h++) {
811+ const HalfSpace &half_space(half_spaces[h]);
812+ for (int i=0;i<12;i++) {
813+ corner_inside[i][h] = half_space.inside(icosahedron_corners[i]);
814+ }
815+ }
816+ for (int i=0;i<20;i++) {
817+ searchZones(0,i,
818+ half_spaces,nr_of_half_spaces,halfs_used,nr_of_half_spaces,
819+ corner_inside[icosahedron_triangles[i].corners[0]],
820+ corner_inside[icosahedron_triangles[i].corners[1]],
821+ corner_inside[icosahedron_triangles[i].corners[2]],
822+ inside_list,border_list,max_search_level);
823+ }
824+}
825+
826+void GeodesicGrid::searchZones(int lev,int index,
827+ const HalfSpace *half_spaces,
828+ const int nr_of_half_spaces,
829+ const int *index_of_used_half_spaces,
830+ const int half_spaces_used,
831+ const bool *corner0_inside,
832+ const bool *corner1_inside,
833+ const bool *corner2_inside,
834+ int **inside_list,int **border_list,
835+ const int max_search_level) const {
836+ int halfs_used[half_spaces_used];
837+ int halfs_used_count = 0;
838+ for (int h=0;h<half_spaces_used;h++) {
839+ const int i = index_of_used_half_spaces[h];
840+ if (!corner0_inside[i] && !corner1_inside[i] && !corner2_inside[i]) {
841+ // totally outside this HalfSpace
842+ return;
843+ } else if (corner0_inside[i] && corner1_inside[i] && corner2_inside[i]) {
844+ // totally inside this HalfSpace
845+ } else {
846+ // on the border of this HalfSpace
847+ halfs_used[halfs_used_count++] = i;
848+ }
849+ }
850+ if (halfs_used_count == 0) {
851+ // this triangle(lev,index) lies inside all halfspaces
852+ **inside_list = index;
853+ (*inside_list)++;
854+ } else {
855+ (*border_list)--;
856+ **border_list = index;
857+ if (lev < max_search_level) {
858+ Triangle &t(triangles[lev][index]);
859+ lev++;
860+ index <<= 2;
861+ inside_list++;
862+ border_list++;
863+ bool edge0_inside[nr_of_half_spaces];
864+ bool edge1_inside[nr_of_half_spaces];
865+ bool edge2_inside[nr_of_half_spaces];
866+ for (int h=0;h<halfs_used_count;h++) {
867+ const int i = halfs_used[h];
868+ const HalfSpace &half_space(half_spaces[i]);
869+ edge0_inside[i] = half_space.inside(t.e0);
870+ edge1_inside[i] = half_space.inside(t.e1);
871+ edge2_inside[i] = half_space.inside(t.e2);
872+ }
873+ searchZones(lev,index+0,
874+ half_spaces,nr_of_half_spaces,halfs_used,halfs_used_count,
875+ corner0_inside,edge2_inside,edge1_inside,
876+ inside_list,border_list,max_search_level);
877+ searchZones(lev,index+1,
878+ half_spaces,nr_of_half_spaces,halfs_used,halfs_used_count,
879+ edge2_inside,corner1_inside,edge0_inside,
880+ inside_list,border_list,max_search_level);
881+ searchZones(lev,index+2,
882+ half_spaces,nr_of_half_spaces,halfs_used,halfs_used_count,
883+ edge1_inside,edge0_inside,corner2_inside,
884+ inside_list,border_list,max_search_level);
885+ searchZones(lev,index+3,
886+ half_spaces,nr_of_half_spaces,halfs_used,halfs_used_count,
887+ edge0_inside,edge1_inside,edge2_inside,
888+ inside_list,border_list,max_search_level);
889+ }
890+ }
891+}
892+
893+
894+
895+GeodesicSearchResult::GeodesicSearchResult(const GeodesicGrid &grid)
896+ :grid(grid),
897+ zones(new int*[grid.getMaxLevel()+1]),
898+ inside(new int*[grid.getMaxLevel()+1]),
899+ border(new int*[grid.getMaxLevel()+1]) {
900+ for (int i=0;i<=grid.getMaxLevel();i++) {
901+ zones[i] = new int[GeodesicGrid::nrOfZones(i)];
902+ }
903+}
904+
905+GeodesicSearchResult::~GeodesicSearchResult(void) {
906+ for (int i=grid.getMaxLevel();i>=0;i--) {
907+ delete zones[i];
908+ }
909+ delete border;
910+ delete inside;
911+ delete zones;
912+}
913+
914+void GeodesicSearchResult::search(const HalfSpace *half_spaces,
915+ const int nr_of_half_spaces,
916+ int max_search_level) {
917+ for (int i=grid.getMaxLevel();i>=0;i--) {
918+ inside[i] = zones[i];
919+ border[i] = zones[i]+GeodesicGrid::nrOfZones(i);
920+ }
921+ grid.searchZones(half_spaces,nr_of_half_spaces,inside,border,max_search_level);
922+}
923+
924+void GeodesicSearchResult::search(const Vector &e0,const Vector &e1,
925+ const Vector &e2,const Vector &e3,
926+ int max_search_level) {
927+ HalfSpace half_spaces[4];
928+ half_spaces[0].d = e0*((e1-e0)^(e2-e0));
929+ if (half_spaces[0].d > 0) {
930+ half_spaces[0].n = e0^e1;
931+ half_spaces[1].n = e1^e2;
932+ half_spaces[2].n = e2^e3;
933+ half_spaces[3].n = e3^e0;
934+ half_spaces[0].d = 0.0;
935+ half_spaces[1].d = 0.0;
936+ half_spaces[2].d = 0.0;
937+ half_spaces[3].d = 0.0;
938+ search(half_spaces,4,max_search_level);
939+ } else {
940+ half_spaces[0].n = (e1-e0)^(e2-e0);
941+ search(half_spaces,1,max_search_level);
942+ }
943+}
944+
945+
946+
947+void GeodesicSearchInsideIterator::reset(void) {
948+ level = 0;
949+ max_count = 1<<(max_level<<1); // 4^max_level
950+ index_p = r.zones[0];
951+ end_p = r.inside[0];
952+ index = (*index_p) * max_count;
953+ count = (index_p < end_p) ? 0 : max_count;
954+}
955+
956+int GeodesicSearchInsideIterator::next(void) {
957+ if (count < max_count) return index+(count++);
958+ index_p++;
959+ if (index_p < end_p) {
960+ index = (*index_p) * max_count;
961+ count = 1;
962+ return index;
963+ }
964+ while (level < max_level) {
965+ level++;
966+ max_count >>= 2;
967+ index_p = r.zones[level];
968+ end_p = r.inside[level];
969+ if (index_p < end_p) {
970+ index = (*index_p) * max_count;
971+ count = 1;
972+ return index;
973+ }
974+ }
975+ return -1;
976+}
977+
978+//------------------------------------------------
979+
980+
981+#include <stdio.h>
982+#include <stdlib.h>
983+#include <string.h>
984+#include <math.h>
985+
986+#include <map>
987+#include <list>
988+#include <string>
989+#include <iostream>
990+
991+using namespace std;
992+
993+
994+
995+static int restrict_output_level_min = 0;
996+static int restrict_output_level_max = MAX_LEVEL;
997+
998+
999+
1000+struct FaintStar { // 6 byte
1001+ int x0:18;
1002+ int x1:18;
1003+ unsigned int b_v:7;
1004+ unsigned int mag:5;
1005+ bool operator<(const FaintStar &s) const {return (mag < s.mag);}
1006+} __attribute__ ((__packed__)) ;
1007+
1008+
1009+struct TycStar { // 10 byte
1010+ int x0:20;
1011+ int x1:20;
1012+ int dx0:14;
1013+ int dx1:14;
1014+ unsigned int b_v:7;
1015+ unsigned int mag:5;
1016+ bool operator<(const TycStar &s) const {return (mag < s.mag);}
1017+} __attribute__ ((__packed__));
1018+
1019+
1020+struct HipStarCompressed {
1021+ int hip:24; // 17 bits needed
1022+ unsigned char comp_ids_int; // 5 bits needed
1023+ int x0; // 32 bits needed
1024+ int x1; // 32 bits needed
1025+ unsigned char b_v; // 8 bits needed
1026+ unsigned char mag; // 5 bits needed
1027+ unsigned short sp_int; // 14 bits needed
1028+ int dx0,dx1,plx;
1029+} __attribute__ ((__packed__));
1030+
1031+struct HipStar : public HipStarCompressed {
1032+ string component_ids,sp;
1033+ void setPlxSp(double plx,const string &sp) {
1034+ HipStar::plx = (int)floor(0.5+100.0*plx);
1035+ if (HipStar::plx < 0) HipStar::plx = 0;
1036+ HipStar::sp = sp;
1037+ }
1038+ bool operator<(const HipStar &s) const {return (mag < s.mag);}
1039+};
1040+
1041+
1042+
1043+struct ZoneData {
1044+ virtual ~ZoneData(void) {}
1045+ virtual int getArraySize(void) const = 0;
1046+ virtual HipStar *add(int level,
1047+ int tyc1,int tyc2,int tyc3,
1048+ int hip,const char *component_ids,
1049+ double x0,double x1,double dx0,double dx1,
1050+ double mag,double b_v,
1051+ double plx,const char *sp,
1052+ bool &does_not_fit) = 0;
1053+ void writeInfoToOutput(FILE *f) const;
1054+ virtual void writeStarsToOutput(FILE *f) = 0;
1055+ Vector center;
1056+ Vector axis0;
1057+ Vector axis1;
1058+};
1059+
1060+struct HipZoneData : public ZoneData {
1061+ list<HipStar> stars;
1062+ int getArraySize(void) const {return stars.size();}
1063+ HipStar *add(int level,
1064+ int tyc1,int tyc2,int tyc3,
1065+ int hip,const char *component_ids,
1066+ double x0,double x1,double dx0,double dx1,
1067+ double mag,double b_v,double plx,const char *sp,
1068+ bool &does_not_fit);
1069+ void writeStarsToOutput(FILE *f);
1070+};
1071+
1072+
1073+static list<HipStar*> hip_index[NR_OF_HIP+1];
1074+
1075+static void SqueezeHip(void) {
1076+ // build lookup maps
1077+ map<string,int> component_ids_map,sp_map;
1078+ for (int i=0;i<=NR_OF_HIP;i++) {
1079+ for (list<HipStar*>::const_iterator it(hip_index[i].begin());
1080+ it!=hip_index[i].end();it++) {
1081+ HipStar *h = *it;
1082+ component_ids_map[h->component_ids]++;
1083+ sp_map[h->sp]++;
1084+ }
1085+ }
1086+ int component_ids_size = 0;
1087+ for (map<string,int>::iterator it(component_ids_map.begin());
1088+ it!=component_ids_map.end();it++,component_ids_size++) {
1089+ it->second = component_ids_size;
1090+ }
1091+ if (component_ids_size >= 32) {
1092+ cerr << "SqueezeHip: too many component_ids: "
1093+ << component_ids_size << endl;
1094+ }
1095+ int sp_size = 0;
1096+ for (map<string,int>::iterator it(sp_map.begin());
1097+ it!=sp_map.end();it++,sp_size++) {
1098+ it->second = sp_size;
1099+ }
1100+ if (sp_size >= 16384) {
1101+ cerr << "SqueezeHip: too many sp: " << sp_size << endl;
1102+ }
1103+ // translate the strings for the hip stars into integers:
1104+ for (int i=0;i<=NR_OF_HIP;i++) {
1105+ for (list<HipStar*>::const_iterator it(hip_index[i].begin());
1106+ it!=hip_index[i].end();it++) {
1107+ HipStar *h = *it;
1108+ h->comp_ids_int = component_ids_map[h->component_ids];
1109+ h->sp_int = sp_map[h->sp];
1110+ }
1111+ }
1112+ // write output files for component_ids and sp
1113+ FILE *f = fopen(component_ids_filename,"wb");
1114+ if (f==0) {
1115+ cout << "fopen(" << component_ids_filename << ") failed" << endl;
1116+ exit(-1);
1117+ }
1118+ for (map<string,int>::const_iterator it(component_ids_map.begin());
1119+ it!=component_ids_map.end();it++,component_ids_size++) {
1120+ fprintf(f,"%s\n",it->first.c_str());
1121+ }
1122+ fclose(f);
1123+ f = fopen(sp_filename,"wb");
1124+ if (f==0) {
1125+ cout << "fopen(" << sp_filename << ") failed" << endl;
1126+ exit(-1);
1127+ }
1128+ for (map<string,int>::const_iterator it(sp_map.begin());
1129+ it!=sp_map.end();it++,sp_size++) {
1130+ fprintf(f,"%s\n",it->first.c_str());
1131+ }
1132+ fclose(f);
1133+}
1134+
1135+struct TycZoneData : public ZoneData {
1136+ list<TycStar> stars;
1137+ int getArraySize(void) const {return stars.size();}
1138+ HipStar *add(int level,
1139+ int tyc1,int tyc2,int tyc3,
1140+ int hip,const char *component_ids,
1141+ double x0,double x1,double dx0,double dx1,
1142+ double mag,double b_v,double plx,const char *sp,
1143+ bool &does_not_fit);
1144+ void writeStarsToOutput(FILE *f);
1145+};
1146+
1147+struct FaintZoneData : public ZoneData {
1148+ list<FaintStar> stars;
1149+ int getArraySize(void) const {return stars.size();}
1150+ HipStar *add(int level,
1151+ int tyc1,int tyc2,int tyc3,
1152+ int hip,const char *component_ids,
1153+ double x0,double x1,double dx0,double dx1,
1154+ double mag,double b_v,double plx,const char *sp,
1155+ bool &does_not_fit);
1156+ void writeStarsToOutput(FILE *f);
1157+};
1158+
1159+
1160+class Accumulator {
1161+public:
1162+ Accumulator(void);
1163+ ~Accumulator(void);
1164+ int addStar(int tyc1,int tyc2,int tyc3,int hip,const char *component_ids,
1165+ double ra, // degrees
1166+ double dec, // degrees
1167+ double pma,double pmd,
1168+ double mag,double b_v,
1169+ double plx,const char *sp);
1170+ void writeOutput(const char *fnames[]);
1171+private:
1172+ GeodesicGrid grid;
1173+ struct ZoneArray {
1174+ ZoneArray(int level,GeodesicGrid &grid)
1175+ : level(level),nr_of_zones(GeodesicGrid::nrOfZones(level)),grid(grid)
1176+ {scale = 0.0;nr_of_stars = 0;}
1177+ virtual ~ZoneArray(void) {}
1178+ virtual ZoneData *getZone(int index) const = 0;
1179+ virtual void writeHeaderToOutput(FILE *f) const = 0;
1180+ const int level;
1181+ const int nr_of_zones;
1182+ const GeodesicGrid &grid;
1183+ double scale;
1184+// int scale_int;
1185+ int nr_of_stars;
1186+ HipStar *addStar(int tyc1,int tyc2,int tyc3,
1187+ int hip,const char *component_ids,
1188+ double ra, // degrees
1189+ double dec, // degrees
1190+ double pma,double pmd,
1191+ double mag,double b_v,
1192+ double plx,const char *sp,
1193+ bool &does_not_fit);
1194+ void writeOutput(const char *fname);
1195+ };
1196+ struct HipZoneArray : public ZoneArray {
1197+ HipZoneArray(int level,GeodesicGrid &grid)
1198+ : ZoneArray(level,grid),zones(new HipZoneData[nr_of_zones]) {}
1199+ ~HipZoneArray(void) {delete[] zones;}
1200+ void writeHeaderToOutput(FILE *f) const;
1201+ HipZoneData *const zones;
1202+ ZoneData *getZone(int index) const {
1203+ if (index<0 || index>=nr_of_zones) {
1204+ cerr << "getZone: bad index" << endl;
1205+ exit(-1);
1206+ }
1207+ return zones+index;
1208+ }
1209+ };
1210+ struct TycZoneArray : public ZoneArray {
1211+ TycZoneArray(int level,GeodesicGrid &grid)
1212+ : ZoneArray(level,grid),zones(new TycZoneData[nr_of_zones]) {}
1213+ ~TycZoneArray(void) {delete[] zones;}
1214+ void writeHeaderToOutput(FILE *f) const;
1215+ TycZoneData *zones;
1216+ ZoneData *getZone(int index) const {
1217+ if (index<0 || index>=nr_of_zones) {
1218+ cerr << "getZone: bad index" << endl;
1219+ exit(-1);
1220+ }
1221+ return zones+index;
1222+ }
1223+ };
1224+ struct FaintZoneArray : public ZoneArray {
1225+ FaintZoneArray(int level,GeodesicGrid &grid)
1226+ : ZoneArray(level,grid),zones(new FaintZoneData[nr_of_zones]) {}
1227+ ~FaintZoneArray(void) {delete[] zones;}
1228+ void writeHeaderToOutput(FILE *f) const;
1229+ FaintZoneData *zones;
1230+ ZoneData *getZone(int index) const {
1231+ if (index<0 || index>=nr_of_zones) {
1232+ cerr << "getZone: bad index" << endl;
1233+ exit(-1);
1234+ }
1235+ return zones+index;
1236+ }
1237+ };
1238+ ZoneArray *zone_array[MAX_LEVEL+1];
1239+
1240+private:
1241+ static void initTriangleFunc(int lev,int index,
1242+ const Vector &c0,
1243+ const Vector &c1,
1244+ const Vector &c2,
1245+ void *user_data) {
1246+ reinterpret_cast<Accumulator*>(user_data)
1247+ ->initTriangle(lev,index,c0,c1,c2);
1248+ }
1249+ void initTriangle(int lev,int index,
1250+ const Vector &c0,
1251+ const Vector &c1,
1252+ const Vector &c2);
1253+};
1254+
1255+
1256+
1257+
1258+
1259+
1260+
1261+
1262+
1263+static
1264+void WriteByte(FILE *f,int x) {
1265+ unsigned char c = (unsigned int)x;
1266+ if (1!=fwrite(&c,1,1,f)) {
1267+ cerr << "WriteByte: fwrite failed" << endl;
1268+ exit(-1);
1269+ }
1270+}
1271+
1272+static
1273+void WriteInt(FILE *f,int x) {
1274+ if (4!=fwrite(&x,1,4,f)) {
1275+ cerr << "WriteInt: fwrite failed" << endl;
1276+ exit(-1);
1277+ }
1278+}
1279+
1280+//static
1281+//int DoubleToInt(double x) {
1282+// return (int)floor(0.5+x*0x7FFFFFFF);
1283+//}
1284+
1285+//static
1286+//double IntToDouble(int x) {
1287+// double rval = x;
1288+// rval /= 0x7FFFFFFF;
1289+// return rval;
1290+//}
1291+
1292+void ZoneData::writeInfoToOutput(FILE *f) const {
1293+// WriteInt(f,DoubleToInt(center.x[0]));
1294+// WriteInt(f,DoubleToInt(center.x[1]));
1295+// WriteInt(f,DoubleToInt(center.x[2]));
1296+ WriteInt(f,getArraySize());
1297+}
1298+
1299+void HipZoneData::writeStarsToOutput(FILE *f) {
1300+ stars.sort();
1301+ for (list<HipStar>::const_iterator it(stars.begin());
1302+ it!=stars.end();it++) {
1303+ if (sizeof(HipStarCompressed)!=
1304+ fwrite(&(*it),1,sizeof(HipStarCompressed),f)) {
1305+ cerr << "HipZoneData::writeStarsToOutput: fwrite failed" << endl;
1306+ exit(-1);
1307+ }
1308+ }
1309+}
1310+
1311+void TycZoneData::writeStarsToOutput(FILE *f) {
1312+ stars.sort();
1313+ for (list<TycStar>::const_iterator it(stars.begin());
1314+ it!=stars.end();it++) {
1315+ if (sizeof(TycStar)!=fwrite(&(*it),1,sizeof(TycStar),f)) {
1316+ cerr << "TycZoneData::writeStarsToOutput: fwrite failed" << endl;
1317+ exit(-1);
1318+ }
1319+ }
1320+}
1321+
1322+
1323+void FaintZoneData::writeStarsToOutput(FILE *f) {
1324+ stars.sort();
1325+ for (list<FaintStar>::const_iterator it(stars.begin());
1326+ it!=stars.end();it++) {
1327+ if (sizeof(FaintStar)!=fwrite(&(*it),1,sizeof(FaintStar),f)) {
1328+ cerr << "FaintZoneData::writeStarsToOutput: fwrite failed" << endl;
1329+ exit(-1);
1330+ }
1331+ }
1332+}
1333+
1334+
1335+
1336+
1337+
1338+
1339+
1340+
1341+
1342+
1343+
1344+
1345+
1346+
1347+
1348+
1349+
1350+
1351+
1352+Accumulator::Accumulator(void)
1353+ :grid(MAX_LEVEL) {
1354+ int l=0;
1355+ for (;l<=MAX_HIP_LEVEL;l++) {
1356+ zone_array[l] = new HipZoneArray(l,grid);
1357+ }
1358+ for (;l<=MAX_TYC_LEVEL;l++) {
1359+ zone_array[l] = new TycZoneArray(l,grid);
1360+ }
1361+ for (;l<=MAX_LEVEL;l++) {
1362+ zone_array[l] = new FaintZoneArray(l,grid);
1363+ }
1364+ grid.visitTriangles(MAX_LEVEL,initTriangleFunc,this);
1365+ for (int l=0;l<=MAX_LEVEL;l++) {
1366+// zone_array[l]->scale_int = DoubleToInt(zone_array[l]->scale);
1367+// while (IntToDouble(zone_array[l]->scale_int) > zone_array[l]->scale) {
1368+// zone_array[l]->scale_int--;
1369+// }
1370+// zone_array[l]->scale = IntToDouble(zone_array[l]->scale_int);
1371+ cout << "Accumulator::Accumulator: level " << zone_array[l]->level
1372+ << ", scale: " << zone_array[l]->scale << endl;
1373+ }
1374+}
1375+
1376+Accumulator::~Accumulator(void) {
1377+ for (int l=0;l<=MAX_LEVEL;l++) {
1378+ delete zone_array[l];
1379+ }
1380+}
1381+
1382+static const Vector north = {0.0,0.0,1.0};
1383+
1384+void Accumulator::initTriangle(int lev,int index,
1385+ const Vector &c0,
1386+ const Vector &c1,
1387+ const Vector &c2) {
1388+ ZoneData &z(*zone_array[lev]->getZone(index));
1389+ double &scale(zone_array[lev]->scale);
1390+ z.center = c0+c1+c2;
1391+ z.center.normalize();
1392+ z.axis0 = north ^ z.center;
1393+ z.axis0.normalize();
1394+ z.axis1 = z.center ^ z.axis0;
1395+
1396+ double mu0,mu1,f,h;
1397+
1398+ mu0 = (c0-z.center)*z.axis0;
1399+ mu1 = (c0-z.center)*z.axis1;
1400+ f = 1.0/sqrt(1.0-mu0*mu0-mu1*mu1);
1401+ h = fabs(mu0)*f;
1402+ if (scale < h) scale = h;
1403+ h = fabs(mu1)*f;
1404+ if (scale < h) scale = h;
1405+
1406+ mu0 = (c1-z.center)*z.axis0;
1407+ mu1 = (c1-z.center)*z.axis1;
1408+ f = 1.0/sqrt(1.0-mu0*mu0-mu1*mu1);
1409+ h = fabs(mu0)*f;
1410+ if (scale < h) scale = h;
1411+ h = fabs(mu1)*f;
1412+ if (scale < h) scale = h;
1413+
1414+ mu0 = (c2-z.center)*z.axis0;
1415+ mu1 = (c2-z.center)*z.axis1;
1416+ f = 1.0/sqrt(1.0-mu0*mu0-mu1*mu1);
1417+ h = fabs(mu0)*f;
1418+ if (scale < h) scale = h;
1419+ h = fabs(mu1)*f;
1420+ if (scale < h) scale = h;
1421+}
1422+
1423+static
1424+unsigned char BvToColorIndex(double b_v) {
1425+ b_v *= 1000.0;
1426+ if (b_v < -500) {
1427+ b_v = -500;
1428+ } else if (b_v > 3499) {
1429+ b_v = 3499;
1430+ }
1431+ return (unsigned int)floor(0.5+127.0*((500.0+b_v)/4000.0));
1432+}
1433+
1434+HipStar *FaintZoneData::add(int level,
1435+ int tyc1,int tyc2,int tyc3,
1436+ int hip,const char *component_ids,
1437+ double x0,double x1,double dx0,double dx1,
1438+ double mag,double b_v,double plx,const char *sp,
1439+ bool &does_not_fit) {
1440+ if (mag>=level_mag_limit[level]) {
1441+ cout << "too faint" << endl;
1442+ exit(-1);
1443+ }
1444+ FaintStar s;
1445+ s.x0 = ((int)floor(0.5+x0*((1<<17)-1))); // 18 bit signed
1446+ s.b_v = BvToColorIndex(b_v); // 0..127: 7 Bit unsigned
1447+ s.x1 = ((int)floor(0.5+x1*((1<<17)-1))); // 18 bit signed
1448+ s.mag = (unsigned int)floor(30*(mag-level_mag_limit[level-1])/
1449+ (level_mag_limit[level]-level_mag_limit[level-1]));
1450+ // steps(accuracy) of 0.05mag, 5 bit unsigned
1451+ stars.push_back(s);
1452+ does_not_fit = false;
1453+ return 0;
1454+}
1455+
1456+HipStar *TycZoneData::add(int level,
1457+ int tyc1,int tyc2,int tyc3,
1458+ int hip,const char *component_ids,
1459+ double x0,double x1,double dx0,double dx1,
1460+ double mag,double b_v,double plx,const char *sp,
1461+ bool &does_not_fit) {
1462+ TycStar s;
1463+ s.x0 = ((int)floor(0.5+x0*((1<<19)-1))); // 20 bit signed
1464+ s.b_v = BvToColorIndex(b_v); // 0..127: 7 Bit unsigned
1465+ s.x1 = ((int)floor(0.5+x1*((1<<19)-1))); // 20 bit signed
1466+ s.mag = (unsigned int)floor(30*(mag-level_mag_limit[level-1])/
1467+ (level_mag_limit[level]-level_mag_limit[level-1]));
1468+ // steps(accuracy) of 0.05mag, 5 bit unsigned
1469+ const int dx0_int = (int)floor(0.5+dx0*10.0); // 14 bit signed
1470+ const int dx1_int = (int)floor(0.5+dx1*10.0); // 14 bit signed
1471+ if (dx0_int >= 8192 || dx0_int<-8192 ||
1472+ dx1_int >= 8192 || dx1_int<-8192) {
1473+ // does not fit, must store in Hip format
1474+ does_not_fit = true;
1475+ return 0;
1476+ }
1477+ s.dx0 = dx0_int;
1478+ s.dx1 = dx1_int;
1479+ stars.push_back(s);
1480+ does_not_fit = false;
1481+ return 0;
1482+}
1483+
1484+
1485+HipStar *HipZoneData::add(int level,
1486+ int tyc1,int tyc2,int tyc3,
1487+ int hip,const char *component_ids,
1488+ double x0,double x1,double dx0,double dx1,
1489+ double mag,double b_v,double plx,const char *sp,
1490+ bool &does_not_fit) {
1491+ HipStar s;
1492+ s.x0 = ((int)floor(0.5+x0*((1<<31)-1))); // 32 bit signed
1493+ s.b_v = BvToColorIndex(b_v); // 0..127: 7 Bit unsigned
1494+ s.x1 = ((int)floor(0.5+x1*((1<<31)-1))); // 32 bit signed
1495+ const int mag_int = (int)floor(20*
1496+ (mag-((level==0)?-2.0:level_mag_limit[level-1])));
1497+ if (mag_int < 0 || mag_int > 255) {
1498+ cerr << "HipZoneData(" << level << ")::add: bad mag: " << mag << endl;
1499+ exit(-1);
1500+ }
1501+ s.mag = mag_int;
1502+ s.dx0 = (int)floor(0.5+dx0*10.0);
1503+ s.dx1 = (int)floor(0.5+dx1*10.0);
1504+ s.hip = hip;
1505+ s.component_ids = component_ids;
1506+ s.comp_ids_int = 0;
1507+ s.sp_int = 0;
1508+ s.plx = (int)floor(0.5+100.0*plx);
1509+ s.sp = sp;
1510+ stars.push_back(s);
1511+ does_not_fit = false;
1512+ return &(stars.back());
1513+}
1514+
1515+
1516+HipStar *Accumulator::ZoneArray::addStar(
1517+ int tyc1,int tyc2,int tyc3,int hip,const char *component_ids,
1518+ double ra,double dec,double pma,double pmd,
1519+ double mag,double b_v,double plx,const char *sp,
1520+ bool &does_not_fit) {
1521+ ra *= (M_PI/180.0);
1522+ dec *= (M_PI/180.0);
1523+ if (ra < 0 || ra >= 2*M_PI || dec < -0.5*M_PI || dec > 0.5*M_PI) {
1524+ cerr << "ZoneArray(l=" << level << ")::addStar: "
1525+ "bad ra/dec: " << ra << ',' << dec << endl;
1526+ exit (-1);
1527+ }
1528+ const double cdec = cos(dec);
1529+ Vector pos;
1530+ pos.x[0] = cos(ra)*cdec;
1531+ pos.x[1] = sin(ra)*cdec;
1532+ pos.x[2] = sin(dec);
1533+ const int zone = grid.searchZone(pos,level);
1534+
1535+ ZoneData &z(*getZone(zone));
1536+ const double mu0 = (pos-z.center) * z.axis0;
1537+ const double mu1 = (pos-z.center) * z.axis1;
1538+ const double d = 1.0 - mu0*mu0 - mu1*mu1;
1539+ const double sd = sqrt(d);
1540+ const double x0 = mu0/(sd*scale);
1541+ const double x1 = mu1/(sd*scale);
1542+ const double h = mu0*pma + mu1*pmd;
1543+ const double dx0 = (pma*d + mu0*h) / (sd*d);
1544+ const double dx1 = (pmd*d + mu1*h) / (sd*d);
1545+
1546+//cout << "Accumulator::ZoneArray(l=" << level << ")::addStar: " << zone << endl;
1547+ HipStar *rval = z.add(level,tyc1,tyc2,tyc3,hip,component_ids,
1548+ x0,x1,dx0,dx1,mag,b_v,plx,sp,does_not_fit);
1549+ if (!does_not_fit) nr_of_stars++;
1550+//cout << "Accumulator::ZoneArray(l=" << level << ")::addStar: 999";
1551+ return rval;
1552+}
1553+
1554+int Accumulator::addStar(int tyc1,int tyc2,int tyc3,int hip,const char *component_ids,
1555+ double ra,double dec,double pma,double pmd,
1556+ double mag,double b_v,double plx,const char *sp) {
1557+// const int packed_hip = PackHip(hip,component_ids);
1558+// const int packed_tyc = PackTyc(tyc1,tyc2,tyc3);
1559+
1560+ int l=0;
1561+ while (l<MAX_LEVEL && mag>=level_mag_limit[l]) l++;
1562+ if (hip>0 && l>MAX_HIP_LEVEL) l = MAX_HIP_LEVEL;
1563+// store the faint tyc2 stars as faint stars
1564+// else if (tyc1>0 && l>MAX_TYC_LEVEL) l = MAX_TYC_LEVEL;
1565+
1566+
1567+ if (restrict_output_level_max < l ||
1568+ restrict_output_level_min > l) {
1569+ // you may want to restrict the output
1570+ // in order to restrict the amount of main memory used.
1571+ // Calling the program twice may be faster than calling once
1572+ // without enough main memory (avoid swapping).
1573+ return 0;
1574+ }
1575+
1576+ bool does_not_fit;
1577+ HipStar *s = zone_array[l]->addStar(tyc1,tyc2,tyc3,hip,component_ids,
1578+ ra,dec,pma,pmd,
1579+ mag,b_v,plx,sp,does_not_fit);
1580+ if (does_not_fit) s = zone_array[MAX_HIP_LEVEL]
1581+ ->addStar(tyc1,tyc2,tyc3,hip,component_ids,
1582+ ra,dec,pma,pmd,
1583+ mag,b_v,plx,sp,does_not_fit);
1584+ if (s) hip_index[hip].push_back(s);
1585+ return 0;
1586+}
1587+
1588+
1589+
1590+
1591+
1592+
1593+
1594+
1595+
1596+
1597+
1598+
1599+
1600+
1601+#define FILE_MAGIC 0x835f040a
1602+
1603+void Accumulator::HipZoneArray::writeHeaderToOutput(FILE *f) const {
1604+ cout << "Accumulator::HipZoneArray(" << level << ")::writeHeaderToOutput: "
1605+ << nr_of_stars << endl;
1606+ WriteInt(f,FILE_MAGIC);
1607+ WriteInt(f,0); // type
1608+ WriteInt(f,0); // major version
1609+ WriteInt(f,4); // minor version
1610+ WriteInt(f,level);
1611+// WriteInt(f,scale_int);
1612+ if (level == 0) {
1613+ WriteInt(f,-2000); // min_mag
1614+ } else {
1615+ WriteInt(f,(int)floor(0.5+1000.0*level_mag_limit[level-1])); // min_mag
1616+ }
1617+ WriteInt(f,12800); // mag_range
1618+ WriteInt(f,256); // mag_steps
1619+}
1620+
1621+void Accumulator::TycZoneArray::writeHeaderToOutput(FILE *f) const {
1622+ cout << "Accumulator::TycZoneArray(" << level << ")::writeHeaderToOutput: "
1623+ << nr_of_stars << endl;
1624+ WriteInt(f,FILE_MAGIC);
1625+ WriteInt(f,1); // type
1626+ WriteInt(f,0); // major version
1627+ WriteInt(f,3); // minor version
1628+ WriteInt(f,level);
1629+// WriteInt(f,scale_int);
1630+ WriteInt(f,(int)floor(0.5+1000.0*level_mag_limit[level-1])); // min_mag
1631+ WriteInt(f,(int)floor(0.5+1000.0*(level_mag_limit[level]
1632+ -level_mag_limit[level-1]))); // mag_range
1633+ WriteInt(f,30); // mag_steps
1634+}
1635+
1636+void Accumulator::FaintZoneArray::writeHeaderToOutput(FILE *f) const {
1637+ cout << "Accumulator::FaintZoneArray(" << level << ")::writeHeaderToOutput: "
1638+ << nr_of_stars << endl;
1639+ WriteInt(f,FILE_MAGIC);
1640+ WriteInt(f,2); // type
1641+ WriteInt(f,0); // major version
1642+ WriteInt(f,1); // minor version
1643+ WriteInt(f,level);
1644+// WriteInt(f,scale_int);
1645+ WriteInt(f,(int)floor(0.5+1000.0*level_mag_limit[level-1])); // min_mag
1646+ WriteInt(f,(int)floor(0.5+1000.0*(level_mag_limit[level]
1647+ -level_mag_limit[level-1]))); // mag_range
1648+ WriteInt(f,30); // mag_steps
1649+}
1650+
1651+
1652+void Accumulator::ZoneArray::writeOutput(const char *fname) {
1653+ if (nr_of_stars <= 0) return;
1654+ FILE *f = fopen(fname,"wb");
1655+ if (f==0) {
1656+ cerr << "Accumulator::writeOutput(" << fname << "): "
1657+ "fopen failed" << endl;
1658+ return;
1659+ }
1660+ writeHeaderToOutput(f);
1661+ for (int zone=0;zone<nr_of_zones;zone++) {
1662+ getZone(zone)->writeInfoToOutput(f);
1663+ }
1664+ int permille = 0;
1665+ for (int zone=0;zone<nr_of_zones;zone++) {
1666+ getZone(zone)->writeStarsToOutput(f);
1667+ int p = (1000*zone)/nr_of_zones;
1668+ if (p != permille) {
1669+ permille = p;
1670+ cout << "\rAccumulator::writeOutput(" << fname << "): "
1671+ << permille << "permille written" << flush;
1672+ }
1673+ }
1674+ cout << endl;
1675+ fclose(f);
1676+}
1677+
1678+void Accumulator::writeOutput(const char *fnames[]) {
1679+ for (int l=0;l<=MAX_LEVEL;l++) {
1680+ zone_array[l]->writeOutput(fnames[l]);
1681+ }
1682+}
1683+
1684+
1685+
1686+
1687+
1688+
1689+
1690+
1691+
1692+
1693+
1694+
1695+
1696+
1697+
1698+int ReadHipTycFile(Accumulator &accu) {
1699+ int count = 0;
1700+ FILE *f;
1701+ const char *fname = "HipTyc";
1702+ f = fopen(fname,"r");
1703+ if (f == 0) {
1704+ fprintf(stderr,"Could not open file \"%s\".\n",fname);
1705+ exit(-1);
1706+ }
1707+
1708+ int hip,tyc1,tyc2,tyc3;
1709+ char cids[32];
1710+ char sp[256];
1711+ int mag,b_v,VarFlag;
1712+ double ra,dec,Plx,pm_ra,pm_dec;
1713+ while (14==fscanf(f,"%d%d%d%d%s%d%lf%lf%lf%lf%lf%d%d%s",
1714+ &hip,&tyc1,&tyc2,&tyc3,cids,&VarFlag,
1715+ &ra,&dec,&Plx,&pm_ra,&pm_dec,&mag,&b_v,sp)) {
1716+ if (b_v>-500 && b_v<3450) {
1717+ const int rc = accu.addStar(tyc1,tyc2,tyc3,hip,
1718+ cids[0]=='?'?"":cids,
1719+ ra, // degrees
1720+ dec, // degrees
1721+ pm_ra,pm_dec,0.001*mag,0.001*b_v,
1722+ Plx,sp[0]=='?'?"":sp);
1723+ if (rc < 0) {
1724+ // never mind: propably no magnitude for Hiparcos star
1725+// fprintf(stderr,"File \"%s\", record %d: Error 13 %d %d \"%s\"\n",
1726+// fname,count,rc,hip,sp);
1727+// exit(-1);
1728+ }
1729+ count++;
1730+ }
1731+ }
1732+ fclose(f);
1733+ return count;
1734+}
1735+
1736+
1737+const unsigned short int SHORT_ASTSRCBIT0 = 0x0001; // Astrometry source bit 0
1738+const unsigned short int SHORT_ASTSRCBIT1 = 0x0002; // Astrometry source bit 1
1739+const unsigned short int SHORT_ASTSRCBIT2 = 0x0004; // Astrometry source bit 2
1740+const unsigned short int SHORT_UBBIT = 0x0008;
1741+const unsigned short int SHORT_TMBIT = 0x0010;
1742+const unsigned short int SHORT_XRBIT = 0x0020;
1743+const unsigned short int SHORT_IUCBIT = 0x0040;
1744+const unsigned short int SHORT_ITYBIT = 0x0080;
1745+const unsigned short int SHORT_OMAGBIT = 0x0100;
1746+const unsigned short int SHORT_EMAGBIT = 0x0200;
1747+const unsigned short int SHORT_TMONLY = 0x0400;
1748+const unsigned short int SHORT_SPIKE = 0x0800;
1749+const unsigned short int SHORT_TYCONF = 0x1000;
1750+const unsigned short int SHORT_BSCONF = 0x2000;
1751+const unsigned short int SHORT_BSART = 0x4000;
1752+const unsigned short int SHORT_USEME = 0x8000;
1753+
1754+struct Short_NOMAD_Record {
1755+ int ra,spd,pm_ra,pm_spd;
1756+ short int b,v,r;
1757+ unsigned short int flags;
1758+};
1759+
1760+
1761+
1762+#define READ_SIZE 10000
1763+static Short_NOMAD_Record buff[READ_SIZE];
1764+
1765+void ReadNOMADFile(const char *fname,Accumulator &accu) {
1766+ int count;
1767+ FILE *f;
1768+ f = fopen(fname,"r");
1769+ if (f == 0) {
1770+ fprintf(stderr,"Could not open file \"%s\".\n",fname);
1771+ exit(-1);
1772+ }
1773+ int total = 0;
1774+ do {
1775+ count = fread(buff,sizeof(Short_NOMAD_Record),READ_SIZE,f);
1776+ total += count;
1777+ printf("\rfread(%s,...) returned %6d, total = %8d",
1778+ fname,count,total);
1779+ fflush(stdout);
1780+ int i;
1781+ for (i=0;i<count;i++) {
1782+ int mag = 30000;
1783+ int b_v;
1784+ if (buff[i].v >= 30000) {
1785+ if (buff[i].b >= 30000) {
1786+ if (buff[i].r >= 30000) {
1787+// cerr << "no magnitude at all" << endl;
1788+ } else {
1789+ mag = buff[i].r + 3499; // just an assumption
1790+ b_v = 3499;
1791+ }
1792+ } else {
1793+ mag = buff[i].b + 500; // just an assumption
1794+ b_v = -500;
1795+ }
1796+ } else {
1797+ mag = buff[i].v;
1798+ if (buff[i].b >= 30000) {
1799+ if (buff[i].r >= 30000) {
1800+ b_v = 0;
1801+ } else {
1802+ b_v = buff[i].v-buff[i].r; // desperate
1803+ }
1804+ } else {
1805+ b_v = buff[i].b-buff[i].v;
1806+ }
1807+ }
1808+
1809+ int nr_of_measurements = 0;
1810+ if (buff[i].b < 30000) nr_of_measurements++;
1811+ if (buff[i].v < 30000) nr_of_measurements++;
1812+ if (buff[i].r < 30000) nr_of_measurements++;
1813+
1814+ if (mag < 19500 && b_v>-500 && b_v<3450 &&
1815+ ((buff[i].flags&SHORT_USEME) ||
1816+ (
1817+ ((buff[i].flags&(SHORT_ASTSRCBIT0|SHORT_ASTSRCBIT1|SHORT_ASTSRCBIT2))!=1 ||
1818+ (((buff[i].flags&SHORT_UBBIT)==0)
1819+ &&
1820+ (mag>14000 || nr_of_measurements>1) &&
1821+ (mag>13000 || nr_of_measurements>2)
1822+ )) &&
1823+ ((buff[i].flags&SHORT_SPIKE)==0) &&
1824+ ((buff[i].flags&SHORT_BSART)==0) &&
1825+ ((buff[i].flags&SHORT_TMONLY)==0)))) {
1826+ if (accu.addStar(0,0,0,0,"",
1827+ buff[i].ra/(3600.0*1000.0), // degrees
1828+ (buff[i].spd-90*3600*1000)/(3600.0*1000.0), // degrees
1829+ 0.1*buff[i].pm_ra,0.1*buff[i].pm_spd,
1830+ 0.001*mag,0.001*b_v,
1831+ 0,"") < 0) {
1832+ fprintf(stderr,"File \"%s\", record %d: Error 16\n",fname,count);
1833+ exit(-1);
1834+ }
1835+ }
1836+ }
1837+ } while (count == READ_SIZE);
1838+ printf("\n");
1839+ fclose(f);
1840+}
1841+
1842+
1843+int main(int argc,char *argv[]) {
1844+ if (argc != 3 ||
1845+ 1 != sscanf(argv[1],"%d",&restrict_output_level_min) ||
1846+ 1 != sscanf(argv[2],"%d",&restrict_output_level_max)) {
1847+ cerr << "Usage: " << argv[0] << " level_min level_max" << endl
1848+ << " (like " << argv[0] << " 0 6)" << endl << endl;
1849+ return -1;
1850+ }
1851+
1852+ Accumulator accu;
1853+ int n=0;
1854+ n = ReadHipTycFile(accu);
1855+ printf("HipTyc: %d records processed.\n",n);
1856+ SqueezeHip();
1857+
1858+ for (int c=0;nomad_names[c];c++) {
1859+ ReadNOMADFile(nomad_names[c],accu);
1860+ }
1861+
1862+ accu.writeOutput(output_file_names);
1863+
1864+ return 0;
1865+}