source: proiecte/pmake3d/make3d_original/Make3dSingleImageStanford_version0.1/third_party/ann_1.1.1/ann2fig/ann2fig.cpp @ 37

Last change on this file since 37 was 37, checked in by (none), 14 years ago

Added original make3d

File size: 20.9 KB
Line 
1//----------------------------------------------------------------------
2// File:                        ann2fig.cpp
3// Programmer:          David Mount
4// Last modified:       05/03/05
5// Description:         convert ann dump file to fig file
6//----------------------------------------------------------------------
7// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and
8// David Mount.  All Rights Reserved.
9//
10// This software and related documentation is part of the Approximate
11// Nearest Neighbor Library (ANN).  This software is provided under
12// the provisions of the Lesser GNU Public License (LGPL).  See the
13// file ../ReadMe.txt for further information.
14//
15// The University of Maryland (U.M.) and the authors make no
16// representations about the suitability or fitness of this software for
17// any purpose.  It is provided "as is" without express or implied
18// warranty.
19//----------------------------------------------------------------------
20// History:
21//      Revision 0.1  03/04/98
22//              Initial release
23//      Revision 1.0  04/01/05
24//              Changed dump file suffix from .ann to .dmp.
25//      Revision 1.1  05/03/05
26//              Fixed usage output string.
27//----------------------------------------------------------------------
28//      This program inputs an ann dump file of a search structure
29//      perhaps along with point coordinates, and outputs a fig (Ver 3.1)
30//      file (see fig2dev (1)) displaying the tree.  The fig file may
31//      then be displayed using xfig, or converted to any of a number of
32//      other formats using fig2dev.
33//
34//      If the dimension is 2 then the entire tree is display.  If the
35//      dimension is larger than 2 then the user has the option of
36//      selecting which two dimensions will be displayed, and the slice
37//      value for each of the remaining dimensions.  All leaf cells
38//      intersecting the slice are shown along with the points in these
39//      cells. See the procedure getArgs() below for the command-line
40//      arguments.
41//----------------------------------------------------------------------
42
43#include <cstdio>                                               // C standard I/O
44#include <fstream>                                              // file I/O
45#include <string>                                               // string manipulation
46#include <ANN/ANNx.h>                                   // all ANN includes
47
48using namespace std;                                    // make std:: accessible
49
50//----------------------------------------------------------------------
51// Globals and their defaults
52//----------------------------------------------------------------------
53
54const int               STRING_LEN              = 500;  // string lengths
55const int               MAX_DIM                 = 1000; // maximum dimension
56const double    DEF_SLICE_VAL   = 0;    // default slice value
57const char              FIG_HEAD[]              = {"#FIG 3.1"}; // fig file header
58const char              DUMP_SUFFIX[]   = {".dmp"};     // suffix for dump file
59const char              FIG_SUFFIX[]    = {".fig"};     // suffix for fig file
60
61char                    file_name[STRING_LEN];  // (root) file name (say xxx)
62char                    infile_name[STRING_LEN];// input file name (xxx.dmp)
63char                    outfile_name[STRING_LEN];// output file name (xxx.fig)
64char                    caption[STRING_LEN];    // caption line (= command line)
65ofstream                ofile;                                  // output file stream
66ifstream                ifile;                                  // input file stream
67int                             dim_x = 0;                              // horizontal dimension
68int                             dim_y = 1;                              // vertical dimension
69double                  slice_val[MAX_DIM];             // array of slice values
70double                  u_per_in = 1200;                // fig units per inch (version 3.1)
71double                  in_size = 5;                    // size of figure (in inches)
72double                  in_low_x = 1;                   // fig upper left corner (in inches)
73double                  in_low_y = 1;                   // fig upper left corner (in inches)
74double                  u_size = 6000;                  // size of figure (in units)
75double                  u_low_x = 1200;                 // fig upper left corner (in units)
76double                  u_low_y = 1200;                 // fig upper left corner (in units)
77int                             pt_size = 10;                   // point size (in fig units)
78
79int                             dim;                                    // dimension
80int                             n_pts;                                  // number of points
81ANNpointArray   pts = NULL;                             // point array
82
83double                  scale;                                  // scale factor for transformation
84double                  offset_x;                               // offsets for transformation
85double                  offset_y;
86
87                                                                                // transformations
88#define TRANS_X(p)              (offset_x + scale*(p[dim_x]))
89#define TRANS_Y(p)              (offset_y - scale*(p[dim_y]))
90
91//----------------------------------------------------------------------
92//      Error handler
93//----------------------------------------------------------------------
94
95void Error(char *msg, ANNerr level)
96{
97        if (level == ANNabort) {
98                cerr << "ann2fig: ERROR------->" << msg << "<-------------ERROR\n";
99                exit(1);
100        }
101        else {
102                cerr << "ann2fig: WARNING----->" << msg << "<-------------WARNING\n";
103        }
104}
105
106//----------------------------------------------------------------------
107// set_slice_val - set all slice values to given value
108//----------------------------------------------------------------------
109
110void set_slice_val(double val)
111{
112        for (int i = 0; i < MAX_DIM; i++) {
113                slice_val[i] = val;
114        }
115}
116
117//----------------------------------------------------------------------
118// getArgs - get input arguments
119//
120//              Syntax:
121//              ann2fig [-upi scale] [-x low_x] [-y low_y]
122//                              [-sz size] [-dx dim_x] [-dy dim_y] [-sl dim value]*
123//                              [-ps pointsize]
124//                              file
125//             
126//              where:
127//                      -upi scale                      fig units per inch (default = 1200)
128//                      -x low_x                        x and y offset of upper left corner (inches)
129//                      -y low_y                        ...(default = 1)
130//                      -sz size                        maximum side length of figure (in inches)
131//                                                              ...(default = 5)
132//                      -dx dim_x                       horizontal dimension (default = 0)
133//                      -dy dim_y                       vertical dimension (default = 1)
134//                      -sv value                       default slice value (default = 0)
135//                      -sl dim value           each such pair defines the value along the
136//                                                              ...given dimension at which to slice.  This
137//                                                              ...may be supplied for all dimensions except
138//                                                              ...dim_x and dim_y.
139//                      -ps pointsize           size of points in fig units (def = 10)
140//                      file                            file (input=file.dmp, output=file.fig)
141//
142//----------------------------------------------------------------------
143
144void getArgs(int argc, char **argv)
145{
146        int i;
147        int sl_dim;                                                                     // temp slice dimension
148        double sl_val;                                                          // temp slice value
149
150        set_slice_val(DEF_SLICE_VAL);                           // set initial slice-values
151
152        if (argc <= 1) {
153                cerr << "Syntax:\n\
154        ann2fig [-upi scale] [-x low_x] [-y low_y]\n\
155                [-sz size] [-dx dim_x] [-dy dim_y] [-sl dim value]*\n\
156                file\n\
157        \n\
158        where:\n\
159            -upi scale          fig units per inch (default = 1200)\n\
160            -x low_x            x and y offset of upper left corner (inches)\n\
161            -y low_y            ...(default = 1)\n\
162            -sz size            maximum side length of figure (in inches)\n\
163                                ...(default = 5)\n\
164            -dx dim_x           horizontal dimension (default = 0)\n\
165            -dy dim_y           vertical dimension (default = 1)\n\
166            -sv value           default slice value (default = 0)\n\
167            -sl dim value       each such pair defines the value along the\n\
168                                ...given dimension at which to slice.  This\n\
169                                ...may be supplied for each dimension except\n\
170                                ...dim_x and dim_y.\n\
171            -ps pointsize       size of points in fig units (def = 10)\n\
172            file                file (input=file.dmp, output=file.fig)\n";
173                exit(0);
174        }
175
176        ANNbool fileSeen = ANNfalse;                            // file argument seen?
177
178        for (i = 1; i < argc; i++) {
179                if (!strcmp(argv[i], "-upi")) {                 // process -upi option
180                        sscanf(argv[++i], "%lf", &u_per_in);
181                }
182                else if (!strcmp(argv[i], "-x")) {              // process -x option
183                        sscanf(argv[++i], "%lf", &in_low_x);
184                }
185                else if (!strcmp(argv[i], "-y")) {              // process -y option
186                        sscanf(argv[++i], "%lf", &in_low_y);
187                }
188                else if (!strcmp(argv[i], "-sz")) {             // process -sz option
189                        sscanf(argv[++i], "%lf", &in_size);
190                }
191                else if (!strcmp(argv[i], "-dx")) {             // process -dx option
192                        sscanf(argv[++i], "%d", &dim_x);
193                }
194                else if (!strcmp(argv[i], "-dy")) {             // process -dy option
195                        sscanf(argv[++i], "%d", &dim_y);
196                }
197                else if (!strcmp(argv[i], "-sv")) {             // process -sv option
198                        sscanf(argv[++i], "%lf", &sl_val);
199                        set_slice_val(sl_val);                          // set slice values
200                }
201                else if (!strcmp(argv[i], "-sl")) {             // process -sl option
202                        sscanf(argv[++i], "%d", &sl_dim);
203                        if (sl_dim < 0 || sl_dim >= MAX_DIM) {
204                                Error("Slice dimension out of bounds", ANNabort);
205                        }
206                        sscanf(argv[++i], "%lf", &slice_val[sl_dim]);
207                }
208                if (!strcmp(argv[i], "-ps")) {                  // process -ps option
209                        sscanf(argv[++i], "%i", &pt_size);
210                }
211                else {                                                                  // must be file name
212                        fileSeen = ANNtrue;
213                        sscanf(argv[i], "%s", file_name);
214                        strcpy(infile_name, file_name);         // copy to input file name
215                strcat(infile_name, DUMP_SUFFIX);
216                strcpy(outfile_name, file_name);        // copy to output file name
217                strcat(outfile_name, FIG_SUFFIX);
218                }
219        }
220
221        if (!fileSeen) {                                                        // no file seen
222                Error("File argument is required", ANNabort);
223        }
224
225        ifile.open(infile_name, ios::in);                       // open for reading
226        if (!ifile) {
227                Error("Cannot open input file", ANNabort);
228        }
229        ofile.open(outfile_name, ios::out);                     // open for writing
230        if (!ofile) {
231                Error("Cannot open output file", ANNabort);
232        }
233
234        u_low_x = u_per_in * in_low_x;                          // convert inches to fig units
235        u_low_y = u_per_in * in_low_y;
236        u_size  = u_per_in * in_size;
237
238        strcpy(caption, argv[0]);                                       // copy command line to caption
239        for (i = 1; i < argc; i++) {
240                strcat(caption, " ");
241                strcat(caption, argv[i]);
242        }
243}
244
245//----------------------------------------------------------------------
246// Graphics utilities for fig output
247//
248//              writeHeader                             write header for fig file
249//              writePoint                              write a point
250//              writeBox                                write a box
251//              writeLine                               write a line
252//----------------------------------------------------------------------
253
254void writeHeader()
255{
256        ofile << FIG_HEAD << "\n"                                       // fig file header
257                 << "Portrait\n"
258                 << "Center\n"
259                 << "Inches\n"
260                 << (int) u_per_in << " 2\n";
261}
262
263void writePoint(ANNpoint p)                                             // write a single point
264{
265                                                                                                // filled black point object
266        ofile << "1 3 0 1 -1 7 0 0 0 0.000 1 0.0000 ";
267        int cent_x = (int) TRANS_X(p);                          // transform center coords
268        int cent_y = (int) TRANS_Y(p);
269        ofile << cent_x << " " << cent_y << " "         // write center, radius, bounds
270                 << pt_size << " " << pt_size << " "
271                 << cent_x << " " << cent_y << " "
272                 << cent_x + pt_size << " " << cent_y + pt_size << "\n";
273}
274
275void writeBox(const ANNorthRect &r)                             // write box
276{
277                                                                                                // unfilled box object
278        ofile << "2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5\n";
279
280        int p0_x = (int) TRANS_X(r.lo);                         // transform endpoints
281        int p0_y = (int) TRANS_Y(r.lo);
282        int p1_x = (int) TRANS_X(r.hi);
283        int p1_y = (int) TRANS_Y(r.hi);
284        ofile << "\t"
285                 << p0_x << " " << p0_y << " "                  // write vertices
286                 << p1_x << " " << p0_y << " "
287                 << p1_x << " " << p1_y << " "
288                 << p0_x << " " << p1_y << " "
289                 << p0_x << " " << p0_y << "\n";
290}
291
292void writeLine(ANNpoint p0, ANNpoint p1)                // write line
293{
294                                                                                                // unfilled line object
295        ofile << "2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2\n";
296
297        int p0_x = (int) TRANS_X(p0);                           // transform endpoints
298        int p0_y = (int) TRANS_Y(p0);
299        int p1_x = (int) TRANS_X(p1);
300        int p1_y = (int) TRANS_Y(p1);
301        ofile << "\t"
302                 << p0_x << " " << p0_y << " "                  // write vertices
303                 << p1_x << " " << p1_y << "\n";
304}
305
306void writeCaption(                                                              // write caption text
307        const ANNorthRect       &bnd_box,                               // bounding box
308        char                            *caption)                               // caption
309{
310        if (!strcmp(caption, "\0")) return;                     // null string?
311        int px = (int) TRANS_X(bnd_box.lo);                     // put .5 in. lower left
312        int py = (int) (TRANS_Y(bnd_box.lo) + 0.50 * u_per_in); 
313        ofile << "4 0 -1 0 0 0 20 0.0000 4 255 2000 ";
314        ofile << px << " " << py << " " << caption << "\\001\n";
315}
316
317//----------------------------------------------------------------------
318// overlap - test whether a box overlap slicing region
319//
320//              The slicing region is a 2-dimensional plane in space
321//              which contains points (x1, x2, ..., xn) satisfying the
322//              n-2 linear equalities:
323//
324//                                              xi == slice_val[i]              for i != dim_x, dim_y
325//
326//              This procedure returns true of the box defined by
327//              corner points box.lo and box.hi overlap this plane.
328//----------------------------------------------------------------------
329
330ANNbool overlap(const ANNorthRect &box)
331{
332        for (int i = 0; i < dim; i++) {
333                if (i != dim_x && i != dim_y &&
334                   (box.lo[i] > slice_val[i] || box.hi[i] < slice_val[i]))
335                        return ANNfalse;
336        }
337        return ANNtrue;
338}
339
340//----------------------------------------------------------------------
341// readTree, recReadTree - inputs tree and outputs figure
342//
343//              readTree procedure initializes things and then calls recReadTree
344//              which does all the work.
345//
346//              recReadTree reads in a node of the tree, makes any recursive
347//              calls as needed to input the children of this node (if internal)
348//              and maintains the bounding box.  Note that the bounding box
349//              is modified within this procedure, but it is the responsibility
350//              of the procedure that it be restored to its original value
351//              on return.
352//
353//              Recall that these are the formats.  The tree is given in
354//              preorder.
355//
356//              Leaf node:
357//                              leaf <n_pts> <bkt[0]> <bkt[1]> ... <bkt[n-1]>
358//              Splitting nodes:
359//                              split <cut_dim> <cut_val> <lo_bound> <hi_bound>
360//              Shrinking nodes:
361//                              shrink <n_bnds>
362//                                              <cut_dim> <cut_val> <side>
363//                                              <cut_dim> <cut_val> <side>
364//                                              ... (repeated n_bnds times)
365//
366//              On reading a leaf we determine whether we should output the
367//              cell's points (if dimension = 2 or this cell overlaps the
368//              slicing region).  For splitting nodes we check whether the
369//              current cell overlaps the slicing plane and whether the
370//              cutting dimension coincides with either the x or y drawing
371//              dimensions.  If so, we output the corresponding splitting
372//              segment.
373//----------------------------------------------------------------------
374
375void recReadTree(ANNorthRect &box)
376{
377        char tag[STRING_LEN];                                           // tag (leaf, split, shrink)
378        int n_pts;                                                                      // number of points in leaf
379        int idx;                                                                        // point index
380        int cd;                                                                         // cut dimension
381        ANNcoord cv;                                                            // cut value
382        ANNcoord lb;                                                            // low bound
383        ANNcoord hb;                                                            // high bound
384        int n_bnds;                                                                     // number of bounding sides
385        int sd;                                                                         // which side
386
387        ifile >> tag;                                                           // input node tag
388        if (strcmp(tag, "leaf") == 0) {                         // leaf node
389
390                ifile >> n_pts;                                                 // input number of points
391                                                                                                // check for overlap
392                if (dim == 2 || overlap(box)) { 
393                        for (int i = 0; i < n_pts; i++) {       // yes, write the points
394                                ifile >> idx;
395                                writePoint(pts[idx]);
396                        }
397                }
398                else {                                                                  // input but ignore points
399                        for (int i = 0; i < n_pts; i++) {
400                                ifile >> idx;
401                        }
402                }
403        }
404        else if (strcmp(tag, "split") == 0) {           // splitting node
405
406                ifile >> cd >> cv >> lb >> hb;
407                if (lb != box.lo[cd] || hb != box.hi[cd]) {
408                        Error("Bounding box coordinates are fishy", ANNwarn);
409                }
410
411                ANNcoord lv = box.lo[cd];                               // save bounds for cutting dim
412                ANNcoord hv = box.hi[cd];
413
414                //--------------------------------------------------------------
415                //      The following code is rather fragile so modify at your
416                //      own risk.  We first decrease the high-end of the bounding
417                //      box down to the cutting plane and then read the left subtree.
418                //      Then we increase the low-end of the bounding box up to the
419                //      cutting plane (thus collapsing the bounding box to a d-1
420                //      dimensional hyperrectangle).  Then we draw the projection of
421                //      its diagonal if it crosses the slicing plane.  This will have
422                //      the effect of drawing its intersection on the slicing plane.
423                //      Then we restore the high-end of the bounding box and read
424                //      the right subtree.  Finally we restore the low-end of the
425                //      bounding box, before returning.
426                //--------------------------------------------------------------
427                box.hi[cd] = cv;                                                // decrease high bounds
428                recReadTree(box);                                               // read left subtree
429                                                                                                // check for overlap
430                box.lo[cd] = cv;                                                // increase low bounds
431                if (dim == 2 || overlap(box)) {                 // check for overlap
432                        if (cd == dim_x || cd == dim_y) {       // cut through slice plane
433                                writeLine(box.lo, box.hi);              // draw cutting line
434                        }
435                }
436                box.hi[cd] = hv;                                                // restore high bounds
437
438                recReadTree(box);                                               // read right subtree
439                box.lo[cd] = lv;                                                // restore low bounds
440        }
441        else if (strcmp(tag, "shrink") == 0) {          // splitting node
442
443                ANNorthRect inner(dim, box);                    // copy bounding box
444                ifile >> n_bnds;                                                // number of bounding sides
445                for (int i = 0; i < n_bnds; i++) {
446                        ifile >> cd >> cv >> sd;                        // input bounding halfspace
447                        ANNorthHalfSpace hs(cd, cv, sd);        // create orthogonal halfspace
448                        hs.project(inner.lo);                           // intersect by projecting
449                        hs.project(inner.hi);
450                }
451                if (dim == 2 || overlap(inner)) {
452                        writeBox(inner);                                        // draw inner rectangle
453                }
454                recReadTree(inner);                                             // read inner subtree
455                recReadTree(box);                                               // read outer subtree
456        }
457        else {
458                Error("Illegal node type in dump file", ANNabort);
459        }
460}
461
462void readTree(ANNorthRect &bnd_box)
463{
464        writeHeader();                                                          // output header
465        writeBox(bnd_box);                                                      // draw bounding box
466        writeCaption(bnd_box, caption);                         // write caption
467        recReadTree(bnd_box);                                           // do it
468}
469
470//----------------------------------------------------------------------
471// readANN - read the ANN dump file
472//
473//              This procedure reads in the dump file.  See the format below.
474//              It first reads the header line with version number.  If the
475//              points section is present it reads them (otherwise just leaves
476//              points = NULL), and then it reads the tree section.  It inputs
477//              the bounding box and determines the parameters for transforming
478//              the image to figure units.  It then invokes the procedure
479//              readTree to do all the real work.
480//
481//              Dump File Format: <xxx> = coordinate value (ANNcoord)
482//
483//              #ANN <version number> <comments> [END_OF_LINE]
484//              points <dim> <n_pts>                    (point coordinates: this is optional)
485//              0 <xxx> <xxx> ... <xxx>                 (point indices and coordinates)
486//              1 <xxx> <xxx> ... <xxx>
487//                ...
488//              tree <dim> <n_pts> <bkt_size>
489//              <xxx> <xxx> ... <xxx>                   (lower end of bounding box)
490//              <xxx> <xxx> ... <xxx>                   (upper end of bounding box)
491//                              If the tree is null, then a single line "null" is
492//                              output.  Otherwise the nodes of the tree are printed
493//                              one per line in preorder.  Leaves and splitting nodes
494//                              have the following formats:
495//              Leaf node:
496//                              leaf <n_pts> <bkt[0]> <bkt[1]> ... <bkt[n-1]>
497//              Splitting nodes:
498//                              split <cut_dim> <cut_val> <lo_bound> <hi_bound>
499//              Shrinking nodes:
500//                              shrink <n_bnds>
501//                                              <cut_dim> <cut_val> <side>
502//                                              <cut_dim> <cut_val> <side>
503//                                              ... (repeated n_bnds times)
504//
505//              Note: Infinite lo_ and hi_bounds are printed as the special
506//                              values "-INF" and "+INF", respectively.  We do not
507//                              check for this, because the current version of ANN
508//                              starts with a finite bounding box if the tree is
509//                              nonempty.
510//----------------------------------------------------------------------
511
512void readANN()
513{
514        int j;
515        char str[STRING_LEN];                                           // storage for string
516    char version[STRING_LEN];                                   // storage for version
517        int  bkt_size;                                                          // bucket size
518
519        ifile >> str;                                                           // input header
520        if (strcmp(str, "#ANN") != 0) {                         // incorrect header
521                Error("Incorrect header for dump file", ANNabort);
522        }
523    ifile.getline(version, STRING_LEN);                 // get version (ignore)
524        ifile >> str;                                                           // get major heading
525        if (strcmp(str, "points") == 0) {                       // points section
526                ifile >> dim;                                                   // read dimension
527                ifile >> n_pts;                                                 // number of points
528                pts = annAllocPts(n_pts, dim);                  // allocate points
529                for (int i = 0; i < n_pts; i++) {               // input point coordinates
530                        int idx;                                                        // point index
531                        ifile >> idx;                                           // input point index
532                        if (idx < 0 || idx >= n_pts) {
533                                Error("Point index is out of range", ANNabort);
534                        }
535                        for (j = 0; j < dim; j++) {
536                                ifile >> pts[idx][j];                   // read point coordinates
537                        }
538                }
539                ifile >> str;                                                   // get next major heading
540        }
541        if (strcmp(str, "tree") == 0) {                         // tree section
542                ifile >> dim;                                                   // read dimension
543                if (dim_x > dim || dim_y > dim) {
544                        Error("Dimensions out of bounds", ANNabort);
545                }
546                ifile >> n_pts;                                                 // number of points
547                ifile >> bkt_size;                                              // bucket size (ignored)
548                                                                                                // read bounding box
549                ANNorthRect bnd_box(dim);                               // create bounding box
550                for (j = 0; j < dim; j++) {
551                        ifile >> bnd_box.lo[j];                         // read box low coordinates
552                }
553                for (j = 0; j < dim; j++) {
554                        ifile >> bnd_box.hi[j];                         // read box high coordinates
555                }
556                                                                                                // compute scaling factors
557                double box_len_x = bnd_box.hi[dim_x] - bnd_box.lo[dim_x];
558                double box_len_y = bnd_box.hi[dim_y] - bnd_box.lo[dim_y];
559                                                                                                // longer side determines scale
560                if (box_len_x > box_len_y) scale = u_size/box_len_x;
561                else                                       scale = u_size/box_len_y;
562                                                                                                // compute offsets
563                offset_x = u_low_x - scale*bnd_box.lo[dim_x];
564                offset_y = u_low_y + scale*bnd_box.hi[dim_y];
565                readTree(bnd_box);                                              // read the tree and process
566        }
567        else if (strcmp(str, "null") == 0) return;      // empty tree
568        else {
569                cerr << "Input string: " << str << "\n";
570                Error("Illegal ann format.  Expecting section heading", ANNabort);
571        }
572}
573
574//----------------------------------------------------------------------
575// Main program
576//
577// Gets the command-line arguments and invokes the main scanning
578// procedure.
579//----------------------------------------------------------------------
580
581main(int argc, char **argv)
582{
583        getArgs(argc, argv);                                            // get input arguments
584        readANN();                                                                      // read the dump file
585}
Note: See TracBrowser for help on using the repository browser.