source: proiecte/pmake3d/make3d_original/Make3dSingleImageStanford_version0.1/third_party/vrippack-0.31/src/vrip/OccGridRLE.cc @ 37

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

Added original make3d

File size: 32.4 KB
Line 
1/*
2
3Brian Curless
4
5Computer Graphics Laboratory
6Stanford University
7
8---------------------------------------------------------------------
9
10Copyright (1997) The Board of Trustees of the Leland Stanford Junior
11University. Except for commercial resale, lease, license or other
12commercial transactions, permission is hereby given to use, copy,
13modify this software for academic purposes only.  No part of this
14software or any derivatives thereof may be used in the production of
15computer models for resale or for use in a commercial
16product. STANFORD MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND
17CONCERNING THIS SOFTWARE.  No support is implied or provided.
18
19*/
20
21
22#include <limits.h>
23#include <stdio.h>
24#include <unistd.h>
25#include <assert.h>
26
27#ifdef linux
28#include <endian.h>
29#endif
30
31
32#include "OccGridRLE.h"
33
34// Lucas:
35// Should we recompact (copy twice) the RLE pointers after doing
36// a transpose?  It would have better memory coherence, but it also
37// costs a lot...  In my tests, it was faster to avoid recompacting.
38#define OCCGRIDRLE_RECOMPACT 0
39
40OccScanlineRLE::OccScanlineRLE()
41{
42    this->lengths = this->allocatedLengths = NULL;
43    this->elements = this->allocatedElements = NULL;
44}
45
46
47OccScanlineRLE::OccScanlineRLE(int dim)
48{
49    this->allocatedLengths = new RunLength[dim];
50    this->allocatedElements = new OccElement[dim];
51
52    this->lengths = this->allocatedLengths;
53    this->elements = this->allocatedElements;
54}
55
56
57OccScanlineRLE::~OccScanlineRLE()
58{
59    if (this->allocatedLengths != NULL) {
60        delete [] this->lengths;
61    }
62
63    if (this->allocatedElements != NULL) {
64        delete [] this->elements;
65    }
66}
67
68
69
70OccGridRLE::OccGridRLE()
71{
72    this->xdim = this->ydim = this->zdim = 0;
73    this->axis = Z_AXIS;
74    this->flip = FALSE;
75    this->origin[0] = 0;
76    this->origin[1] = 0;
77    this->origin[2] = 0;
78    this->resolution = 1.0;
79
80    this->rleScanline = new OccScanlineRLE;
81
82    this->defaultElement = new OccElement;
83    //this->defaultElement->value = 0;
84    this->defaultElement->value = USHRT_MAX;
85    this->defaultElement->totalWeight = 0;
86
87    this->emptyNoWeight.value = 0;
88    this->emptyNoWeight.totalWeight = 0;
89
90    this->fullNoWeight.value = USHRT_MAX;
91    this->fullNoWeight.totalWeight = 0;
92
93    this->lengthChunker = NULL;
94    this->elementChunker = NULL;
95    this->sliceOrigins = NULL;
96    this->lengthAddr = NULL;
97    this->elementAddr = NULL;
98    this->slice = NULL;
99    this->scanline = NULL;
100    this->transpXZslice = NULL;
101
102
103}
104
105
106OccGridRLE::OccGridRLE(int xd, int yd, int zd, int num)
107{
108    this->xdim = this->ydim = this->zdim = 0;
109    this->axis = Z_AXIS;
110    this->flip = FALSE;
111    this->origin[0] = 0;
112    this->origin[1] = 0;
113    this->origin[2] = 0;
114    this->resolution = 1.0;
115
116    this->rleScanline = new OccScanlineRLE;
117
118    this->defaultElement = new OccElement;
119    this->defaultElement->value = 0;
120    this->defaultElement->totalWeight = 0;
121
122    this->emptyNoWeight.value = 0;
123    this->emptyNoWeight.totalWeight = 0;
124
125    this->fullNoWeight.value = USHRT_MAX;
126    this->fullNoWeight.totalWeight = 0;
127
128    this->lengthChunker = NULL;
129    this->elementChunker = NULL;
130    this->sliceOrigins = NULL;
131    this->lengthAddr = NULL;
132    this->elementAddr = NULL;
133    this->slice = NULL;
134    this->scanline = NULL;
135    this->transpXZslice = NULL;
136
137    this->init(xd, yd, zd, num);
138}
139
140
141void
142OccGridRLE::init(int xd, int yd, int zd, int num)
143{
144    int size1, size2, size3, sliceSize;
145
146    this->xdim = xd;
147    this->ydim = yd;
148    this->zdim = zd;
149
150    int maxdim = MAX(this->xdim, MAX(this->ydim, this->zdim));
151    this->sliceOrigins = new vec3f[maxdim];
152    this->scanline = new OccElement[maxdim];
153
154    this->axis = Z_AXIS;
155    this->flip = FALSE;
156    this->origin[0] = 0;
157    this->origin[1] = 0;
158    this->origin[2] = 0;
159    this->resolution = 1.0;
160
161    size1 = xd*yd;
162    size2 = xd*zd;
163    size3 = yd*zd;
164
165    sliceSize = MAX(MAX(size1, size2), size3);
166    this->slice = new OccElement[sliceSize];
167
168    this->rleScanline = new OccScanlineRLE;
169
170    this->defaultElement = new OccElement;
171    this->defaultElement->value = USHRT_MAX;
172    this->defaultElement->totalWeight = 0;
173
174    this->emptyNoWeight.value = 0;
175    this->emptyNoWeight.totalWeight = 0;
176
177    this->fullNoWeight.value = USHRT_MAX;
178    this->fullNoWeight.totalWeight = 0;
179
180    this->lengthAddr = new RunLength*[sliceSize];
181    this->elementAddr = new OccElement*[sliceSize];
182   
183    if (this->lengthChunker == NULL)
184        this->lengthChunker = new ChunkAllocator(num);
185    else if (this->lengthChunker->chunkSize != num) {
186        delete this->lengthChunker;
187        this->lengthChunker = new ChunkAllocator(num);
188    } else {
189        this->lengthChunker->reset();
190    }
191   
192    if (this->elementChunker == NULL)
193        this->elementChunker = new ChunkAllocator(num);
194    else if (this->elementChunker->chunkSize != num) {
195        delete this->elementChunker;
196        this->elementChunker = new ChunkAllocator(num);
197    } else {
198        this->elementChunker->reset();
199    }
200   
201
202    // Compute the maximum bytes needed for a scanline
203    //  Fix this!!
204    if (sizeof(OccElement) >= 2*sizeof(ushort)) {
205        this->transpXZbytesPerScanline = 
206            this->xdim*sizeof(OccElement)+3*sizeof(ushort);
207    }
208    else {
209        this->transpXZbytesPerScanline = 
210            this->xdim/2*
211            (sizeof(OccElement)+2*sizeof(ushort)) + sizeof(ushort);
212    }
213
214    this->transpXZslice = new uchar[this->zdim*this->transpXZbytesPerScanline];
215
216    this->clear();
217}
218
219
220OccGridRLE::~OccGridRLE()
221{
222   this->freeSpace();
223}
224
225
226void
227OccGridRLE::freeSpace()
228{
229    if (this->sliceOrigins != NULL) {
230        delete [] this->sliceOrigins;
231    }
232    if (this->lengthAddr != NULL) {
233        delete [] this->lengthAddr;
234    }
235    if (this->elementAddr != NULL) {
236        delete [] this->elementAddr;
237    }
238    if (this->slice != NULL) {
239        delete [] this->slice;
240    }
241    if (this->scanline != NULL) {
242        delete [] this->scanline;
243    }
244    if (this->rleScanline != NULL) {
245        delete this->rleScanline;
246    }
247    if (this->defaultElement != NULL) {
248        delete this->defaultElement;
249    }
250    if (this->elementChunker != NULL) {
251        delete this->elementChunker;
252    }
253    if (this->lengthChunker != NULL) {
254        delete this->lengthChunker;
255    }
256    if (this->transpXZslice != NULL) {
257        delete [] this->transpXZslice;
258    }
259}
260
261
262void
263OccGridRLE::copyParams(OccGridRLE *other)
264{
265    this->xdim = other->xdim;
266    this->ydim = other->ydim;
267    this->zdim = other->zdim;
268    this->axis = other->axis;
269    this->flip = other->flip;
270    this->origin[0] = other->origin[0];
271    this->origin[1] = other->origin[1];
272    this->origin[2] = other->origin[2];
273}
274
275
276void
277OccGridRLE::allocNewRun(int y, int z)
278{
279    // Make room for contiguous runs and point the length and data
280    // pointers to the next place that length and data will be put
281
282    this->elementChunker->newChunkIfNeeded(sizeof(OccElement)*(this->xdim+1));
283    this->elementAddr[y + z*this->ydim] = 
284        (OccElement *)this->elementChunker->currentAddr;
285
286    this->lengthChunker->newChunkIfNeeded(sizeof(RunLength)*(this->xdim+1));
287    this->lengthAddr[y + z*this->ydim] = 
288        (RunLength *)this->lengthChunker->currentAddr;
289
290    setScanline(y, z);
291}
292
293
294void
295OccGridRLE::setScanline(int y, int z)
296{
297    currentLength = this->lengthAddr[y + z*this->ydim];
298    currentElem = this->elementAddr[y + z*this->ydim];
299}
300
301
302#if defined(linux) && BYTE_ORDER == LITTLE_ENDIAN
303
304static inline void
305swap_4(const void *p, size_t size)
306{
307    char t;
308    for (char *pc = (char *) p; pc < (char *) p + size; pc += 4)
309    {
310        t = pc[0]; pc[0] = pc[3]; pc[3] = t;
311        t = pc[1]; pc[1] = pc[2]; pc[2] = t;
312    }
313}
314
315static inline void
316swap_2(const void *p, size_t size)
317{
318    char t;
319    for (char *pc = (char *) p; pc < (char *) p + size; pc += 2)
320    {
321        t = pc[0]; pc[0] = pc[1]; pc[1] = t;
322    }
323}
324
325static inline void
326write_be_int(const void *p, size_t size, size_t nitems, FILE *fp)
327{
328    swap_4(p, size * nitems);
329    fwrite(p, size, nitems, fp);
330    swap_4(p, size * nitems);
331}
332
333static inline void
334write_be_float(const void *p, size_t size, size_t nitems, FILE *fp)
335{
336    swap_4(p, size * nitems);
337    fwrite(p, size, nitems, fp);
338    swap_4(p, size * nitems);
339}
340
341static inline void
342write_be_ushort(const void *p, size_t size, size_t nitems, FILE *fp)
343{
344    swap_2(p, size * nitems);
345    fwrite(p, size, nitems, fp);
346    swap_2(p, size * nitems);
347}
348
349static inline void
350read_be_int(void *p, size_t size, size_t nitems, FILE *fp)
351{
352    fread(p, size, nitems, fp);
353    swap_4(p, size * nitems);
354}
355
356static inline void
357read_be_float(void *p, size_t size, size_t nitems, FILE *fp)
358{
359    fread(p, size, nitems, fp);
360    swap_4(p, size * nitems);
361}
362
363static inline void
364read_be_ushort(void *p, size_t size, size_t nitems, FILE *fp)
365{
366    fread(p, size, nitems, fp);
367    swap_2(p, size * nitems);
368}
369
370#else
371
372static inline void
373write_be_int(const void *p, size_t size, size_t nitems, FILE *fp)
374{
375    fwrite(p, size, nitems, fp);
376}
377
378static inline void
379write_be_float(const void *p, size_t size, size_t nitems, FILE *fp)
380{
381    fwrite(p, size, nitems, fp);
382}
383
384static inline void
385write_be_ushort(const void *p, size_t size, size_t nitems, FILE *fp)
386{
387    fwrite(p, size, nitems, fp);
388}
389
390static inline void
391read_be_int(void *p, size_t size, size_t nitems, FILE *fp)
392{
393    fread(p, size, nitems, fp);
394}
395
396static inline void
397read_be_float(void *p, size_t size, size_t nitems, FILE *fp)
398{
399    fread(p, size, nitems, fp);
400}
401
402static inline void
403read_be_ushort(void *p, size_t size, size_t nitems, FILE *fp)
404{
405    fread(p, size, nitems, fp);
406}
407
408#endif
409
410int
411OccGridRLE::write(const char *filename)
412{
413    FILE *fp = fopen(filename, "wb");
414
415    if (fp == NULL)
416        return FALSE;
417
418    write_be_int(&this->xdim, sizeof(int), 1, fp);
419    write_be_int(&this->ydim, sizeof(int), 1, fp);
420    write_be_int(&this->zdim, sizeof(int), 1, fp);
421    write_be_int(&this->axis, sizeof(int), 1, fp);
422    write_be_int(&this->flip, sizeof(int), 1, fp);
423    write_be_float(&this->origin, sizeof(float), 3, fp);
424    write_be_float(&this->resolution, sizeof(float), 1, fp);
425   
426    int yy, zz, numRuns, numElems;
427
428    // First count bytes
429    int lengthByteCount = 0;
430    int elementByteCount = 0;
431    for (zz = 0; zz < this->zdim; zz++) {
432        for (yy = 0; yy < this->ydim; yy++) {
433            runStats(yy, zz, &numRuns, &numElems);
434            // Don't forget the END_OF_RUN
435            lengthByteCount = lengthByteCount + 
436                (numRuns + 1)*sizeof(RunLength);
437            elementByteCount = elementByteCount + 
438                (numElems)*sizeof(OccElement);
439        }
440    }
441
442    write_be_int(&lengthByteCount, sizeof(int), 1, fp);
443    write_be_int(&elementByteCount, sizeof(int), 1, fp);
444
445    int i;
446    RunLength length;
447    int runType;
448    OccElement *element;
449
450    for (zz = 0; zz < this->zdim; zz++) {
451        for (yy = 0; yy < this->ydim; yy++) {
452            setScanline(yy, zz);
453            while (TRUE) {
454                length = getNextLength();
455                write_be_ushort(&length, sizeof(RunLength), 1, fp);
456               
457                runType = getRunType(&length);
458
459                if (runType == OccGridRLE::END_OF_RUN)
460                    break;
461               
462                if (runType == OccGridRLE::CONSTANT_DATA) {
463                    element = getNextElement();
464                    write_be_ushort(element, sizeof(OccElement), 1, fp);
465                }
466                else {
467                    for (i=0; i<length; i++) {
468                        element = getNextElement();
469                        write_be_ushort(element, sizeof(OccElement), 1, fp);
470                    }
471                }
472            }
473        }
474    }
475
476    fclose(fp);
477
478    return TRUE;
479}
480
481
482int
483OccGridRLE::read(const char *filename)
484{
485    int size1, size2, size3, xd, yd, zd, sliceSize;
486
487    FILE *fp = fopen(filename, "rb");
488
489    if (fp == NULL)
490        return FALSE;
491
492    read_be_int(&xd, sizeof(int), 1, fp);
493    read_be_int(&yd, sizeof(int), 1, fp);
494    read_be_int(&zd, sizeof(int), 1, fp);
495
496    if (xd != this->xdim || yd != this->ydim || zd != this->zdim) {
497        size1 = xd*yd;
498        size2 = xd*zd;
499        size3 = yd*zd;
500       
501        sliceSize = MAX(MAX(size1, size2), size3);
502
503        if (this->slice != NULL)
504            delete [] this->slice;
505        this->slice = new OccElement[sliceSize];
506
507        if (this->lengthAddr != NULL)
508            delete [] this->lengthAddr;
509        this->lengthAddr = new RunLength*[sliceSize];
510
511        if (this->elementAddr != NULL)
512            delete [] this->elementAddr;
513        this->elementAddr = new OccElement*[sliceSize];
514
515        int maxdim = MAX(xd, MAX(yd, zd));
516
517        if (this->sliceOrigins != NULL)
518            delete [] this->sliceOrigins;
519        this->sliceOrigins = new vec3f[maxdim];
520
521        if (this->scanline != NULL)
522            delete [] this->scanline;
523        this->scanline = new OccElement[maxdim];
524
525        this->xdim = xd;
526        this->ydim = yd;
527        this->zdim = zd;
528
529        if (sizeof(OccElement) > 2*sizeof(ushort)) {
530            this->transpXZbytesPerScanline = 
531                this->xdim*sizeof(OccElement)+3*sizeof(ushort);
532        }
533        else {
534            this->transpXZbytesPerScanline = 
535                this->xdim/2*
536                (sizeof(OccElement)+2*sizeof(ushort)) + sizeof(ushort);
537        }
538
539        if (this->transpXZslice != NULL)
540            delete [] this->transpXZslice;
541        this->transpXZslice = new uchar
542            [this->zdim*this->transpXZbytesPerScanline];
543    }
544
545    read_be_int(&this->axis, sizeof(int), 1, fp);
546    read_be_int(&this->flip, sizeof(int), 1, fp);
547    read_be_float(&this->origin, sizeof(float), 3, fp);
548    read_be_float(&this->resolution, sizeof(float), 1, fp);
549
550    int lengthByteCount, elementByteCount;
551    read_be_int(&lengthByteCount, sizeof(int), 1, fp);
552    read_be_int(&elementByteCount, sizeof(int), 1, fp);
553
554    reset();
555
556    int i, yy, zz;
557    RunLength length;
558    int runType;
559    OccElement element;
560
561    for (zz = 0; zz < this->zdim; zz++) {
562        for (yy = 0; yy < this->ydim; yy++) {
563            allocNewRun(yy, zz);
564            while (TRUE) {
565                read_be_ushort(&length, sizeof(RunLength), 1, fp);
566                putNextLength(length);
567               
568                runType = getRunType(&length);
569
570                if (runType == OccGridRLE::END_OF_RUN)
571                    break;
572
573                if (runType == OccGridRLE::CONSTANT_DATA) {
574                    read_be_ushort(&element, sizeof(OccElement), 1, fp);
575                    putNextElement(&element);
576                }
577                else {
578                    for (i=0; i<length; i++) {
579                        read_be_ushort(&element, sizeof(OccElement), 1, fp);
580                        putNextElement(&element);
581                    }
582                }
583            }
584        }
585    }
586
587    fclose(fp);
588
589    return TRUE;
590}
591
592
593int
594OccGridRLE::writeDen(const char *)
595{
596
597/*
598    orig_min[0] = extr_min[0] = map_min[0] = 0;
599    orig_min[1] = extr_min[1] = map_min[1] = 0;
600    orig_min[2] = extr_min[2] = map_min[2] = 0;
601
602    orig_max[0] = extr_max[0] = map_max[0] = this->xdim - 1;
603    orig_max[1] = extr_max[1] = map_max[1] = this->ydim - 1;
604    orig_max[2] = extr_max[2] = map_max[2] = this->zdim - 1;
605
606    orig_len[0] = extr_len[0] = map_len[0] = this->xdim;
607    orig_len[1] = extr_len[1] = map_len[1] = this->ydim;
608    orig_len[2] = extr_len[2] = map_len[2] = this->zdim;
609
610    map_warps = 0;
611
612    map_length = (long)map_len[X] * (long)map_len[Y] * (long)map_len[Z];
613
614    map_address = (uchar *)(this->elems);
615
616    Store_Indexed_DEN_File(filename, sizeof(OccElement));
617*/
618   
619    // So much for error checking...
620    return TRUE;
621}
622
623
624void
625OccGridRLE::copy(OccGridRLE *other)
626{
627    OccScanlineRLE *rleScanline;
628
629    this->reset();
630    this->copyParams(other);
631
632    for (int zz = 0; zz < this->zdim; zz++) {
633        for (int yy = 0; yy < this->ydim; yy++) {
634            rleScanline = other->getRLEScanline(yy, zz);
635            this->copyScanline(rleScanline, yy, zz);
636        }
637    }
638
639}
640
641
642int
643OccGridRLE::transposeXZ(OccGridRLE *outGrid)
644{
645    int zz, yy;
646    OccScanlineRLE *rleScanlines;
647    OccElement *elementData;
648    RunLength *lengthData;
649    int *runTypes;
650
651    outGrid->reset();
652    outGrid->copyParams(this);
653       
654    SWAP_INT(outGrid->xdim, outGrid->zdim);
655    SWAP_FLOAT(outGrid->origin[0], outGrid->origin[2]);
656
657    // Set up the new scanlines
658    rleScanlines = new OccScanlineRLE[outGrid->zdim];
659
660
661/*
662    rleScanlines = new OccScanlineRLE[outGrid->zdim];
663    for (zz = 0; zz < outGrid->zdim; zz++) {
664        rleScanlines[zz].lengths = new RunLength[outGrid->xdim + 1];
665        rleScanlines[zz].elements = new OccElement[outGrid->xdim + 1];
666    }   
667    */   
668
669    lengthData = new RunLength[(outGrid->xdim+1)*outGrid->zdim];
670    elementData = new OccElement[(outGrid->xdim)*outGrid->zdim];
671    for (zz = 0; zz < outGrid->zdim; zz++) {
672        rleScanlines[zz].lengths = lengthData + zz*(outGrid->xdim + 1);
673        rleScanlines[zz].elements = elementData + zz*(outGrid->xdim);
674    }
675
676    // For bookeeping
677    runTypes = new int[outGrid->zdim];
678
679    // Rename the bookeeping
680    int *runOffset = runTypes;
681
682    // Loop over slices
683    for (yy = 0; yy < this->ydim; yy++) {
684
685        // Initialize scanlines and bookkeeping
686        for (zz = 0; zz < outGrid->zdim; zz++) {
687            rleScanlines[zz].reset();
688            runOffset[zz] = 0;
689        }
690       
691        int xx;
692        RunLength length;
693        int runType, i;
694        OccElement *element;
695
696
697        // Lay down first scanline
698
699        xx = 0;
700        setScanline(yy, 0);
701        while (TRUE) {
702            length = getNextLength();
703           
704            runType = getRunType(&length);
705           
706            if (runType == OccGridRLE::END_OF_RUN)
707                break;
708           
709            if (runType == OccGridRLE::CONSTANT_DATA) {
710                element = getNextElement();
711                for (i=0; i < length; i++, xx++) {
712                    rleScanlines[xx].putNextElement(element);
713                }
714            }
715            else {
716                for (i=0; i<length; i++, xx++) {
717                    element = getNextElement();
718                    rleScanlines[xx].putNextElement(element);
719                }
720            }           
721        }
722        assert(xx == this->xdim);
723
724
725        // Process the current and previous scanlines concurrently
726
727        int end1, end2, type1, type2;
728        RunLength length1, length2;
729        OccElement *elem1, *elem2;
730        OccScanlineRLE *lastScanline;
731
732        // Loop over scanlines
733
734        for (zz = 1; zz < this->zdim; zz++) {
735
736            // Load up previous scanline
737            lastScanline = getRLEScanline(yy, zz-1);
738            lastScanline->reset();
739
740            // Load up current scanline
741            setScanline(yy, zz);
742
743            // Initialize
744            xx = 0;
745            end1 = 0;
746            end2 = 0;
747
748            while (xx < this->xdim) {
749                // Load up new lengths and/or new element from prior scanline
750                if (xx == end1) {
751                    length1 = lastScanline->getNextLength();
752                    type1 = getRunType(&length1);
753                    end1 += length1;
754                    elem1 = lastScanline->getNextElement();
755                } else if (type1 == OccGridRLE::VARYING_DATA) {
756                    elem1 = lastScanline->getNextElement();
757                }
758
759                // Load up new lengths and/or new element from current scanline
760                if (xx == end2) {
761                    length2 = getNextLength();
762                    type2 = getRunType(&length2);
763                    end2 += length2;
764                    elem2 = getNextElement();
765                } else if (type2 == OccGridRLE::VARYING_DATA) {
766                    elem2 = getNextElement();
767                }
768
769                if (type1 == OccGridRLE::CONSTANT_DATA &&
770                    type2 == OccGridRLE::CONSTANT_DATA &&
771                    elem1->value == elem2->value &&
772                    elem2->totalWeight == elem2->totalWeight) {
773
774                    // If both are the same constant value, then skip to end
775                    // of one of them, whichever comes first
776                    xx = MIN(end1, end2);
777
778                } 
779                else if (type1 == OccGridRLE::VARYING_DATA &&
780                         type2 == OccGridRLE::VARYING_DATA) {
781
782                    // If both are varying values, then write the new value
783                    rleScanlines[xx].putNextElement(elem2);
784                    xx++;
785
786                } else {
787                    // Else, clean up old run by updating length
788                    length = zz - runOffset[xx];
789                    setRunType(&length, type1);
790                    rleScanlines[xx].putNextLength(length);
791
792                    // Prepare for new run
793                    runOffset[xx] = zz;
794                    rleScanlines[xx].putNextElement(elem2);
795                    xx++;
796                }
797            }
798        }
799
800
801        // One last run through to finish up lengths
802        zz = this->zdim;
803        lastScanline = getRLEScanline(yy, zz-1);
804        lastScanline->reset();
805        xx = 0;
806        end1 = 0;       
807        while (xx < this->xdim) {
808            if (xx == end1) {
809                length1 = lastScanline->getNextLength();
810                type1 = getRunType(&length1);
811                end1 += length1;
812                elem1 = lastScanline->getNextElement();
813            } else if (type1 == OccGridRLE::VARYING_DATA) {
814                elem1 = lastScanline->getNextElement();
815            }
816            length = zz - runOffset[xx];
817            setRunType(&length, type1);
818            rleScanlines[xx].putNextLength(length);
819            xx++;
820        }
821
822
823        // Write out the end-of-run flags and copy runs to output grid
824        for (zz = 0; zz < outGrid->zdim; zz++) {
825            rleScanlines[zz].putNextLength(OccGridRLE::END_OF_RUN);
826            outGrid->allocNewRun(yy, zz);
827            outGrid->copyScanline(&rleScanlines[zz], yy, zz);
828        }
829    }
830
831#if OCCGRIDRLE_RECOMPACT
832    // Re-compactify
833    this->copy(outGrid);
834
835    // Put into output
836    outGrid->copy(this);
837#endif //OCCGRIDRLE_RECOMPACT
838
839    // So that scanline deletion will not try to free these
840    for (zz = 0; zz < outGrid->zdim; zz++) {
841        rleScanlines[zz].lengths = NULL;
842        rleScanlines[zz].elements = NULL;
843    }
844
845    delete [] rleScanlines;
846    delete [] lengthData;
847    delete [] elementData;
848    delete [] runTypes;
849
850    return TRUE;
851}
852
853
854int
855OccGridRLE::transposeXY(OccGridRLE *outGrid)
856{
857    int zz, yy;
858    OccScanlineRLE *rleScanlines;
859    OccElement *elementData;
860    RunLength *lengthData;
861    int *runTypes;
862
863    outGrid->reset();
864    outGrid->copyParams(this);
865       
866    SWAP_INT(outGrid->xdim, outGrid->ydim);
867    SWAP_FLOAT(outGrid->origin[0], outGrid->origin[1]);
868
869    rleScanlines = new OccScanlineRLE[outGrid->ydim];
870    lengthData = new RunLength[(outGrid->xdim+1)*outGrid->ydim];
871    elementData = new OccElement[(outGrid->xdim)*outGrid->ydim];
872    for (yy = 0; yy < outGrid->ydim; yy++) {
873        rleScanlines[yy].lengths = lengthData + yy*(outGrid->xdim + 1);
874        rleScanlines[yy].elements = elementData + yy*(outGrid->xdim);
875    }
876    runTypes = new int[outGrid->ydim];
877
878    // Rename the bookeeping
879    int *runOffset = runTypes;
880
881    // Loop over slices
882    for (zz = 0; zz < this->zdim; zz++) {
883
884        // Initialize scanlines and bookkeeping
885        for (yy = 0; yy < outGrid->ydim; yy++) {
886            rleScanlines[yy].reset();
887            runOffset[yy] = 0;
888        }
889       
890        int xx;
891        RunLength length;
892        int runType, i;
893        OccElement *element;
894
895
896        // Lay down first scanline
897
898        xx = 0;
899        setScanline(0, zz);
900        while (TRUE) {
901            length = getNextLength();
902           
903            runType = getRunType(&length);
904           
905            if (runType == OccGridRLE::END_OF_RUN)
906                break;
907           
908            if (runType == OccGridRLE::CONSTANT_DATA) {
909                element = getNextElement();
910                for (i=0; i < length; i++, xx++) {
911                    rleScanlines[xx].putNextElement(element);
912                }
913            }
914            else {
915                for (i=0; i<length; i++, xx++) {
916                    element = getNextElement();
917                    rleScanlines[xx].putNextElement(element);
918                }
919            }           
920        }
921        assert(xx == this->xdim);
922
923
924        // Process the current and previous scanlines concurrently
925
926        int end1, end2, type1, type2;
927        RunLength length1, length2;
928        OccElement *elem1, *elem2;
929        OccScanlineRLE *lastScanline;
930
931        // Loop over scanlines
932
933        for (yy = 1; yy < this->ydim; yy++) {
934
935            // Load up previous scanline
936            lastScanline = getRLEScanline(yy-1, zz);
937            lastScanline->reset();
938
939            // Load up current scanline
940            setScanline(yy, zz);
941
942            // Initialize
943            xx = 0;
944            end1 = 0;
945            end2 = 0;
946
947            while (xx < this->xdim) {
948                // Load up new lengths and/or new element from prior scanline
949                if (xx == end1) {
950                    length1 = lastScanline->getNextLength();
951                    type1 = getRunType(&length1);
952                    end1 += length1;
953                    elem1 = lastScanline->getNextElement();
954                } else if (type1 == OccGridRLE::VARYING_DATA) {
955                    elem1 = lastScanline->getNextElement();
956                }
957
958                // Load up new lengths and/or new element from current scanline
959                if (xx == end2) {
960                    length2 = getNextLength();
961                    type2 = getRunType(&length2);
962                    end2 += length2;
963                    elem2 = getNextElement();
964                } else if (type2 == OccGridRLE::VARYING_DATA) {
965                    elem2 = getNextElement();
966                }
967
968                if (type1 == OccGridRLE::CONSTANT_DATA &&
969                    type2 == OccGridRLE::CONSTANT_DATA &&
970                    elem1->value == elem2->value &&
971                    elem2->totalWeight == elem2->totalWeight) {
972
973                    // If both are the same constant value, then skip to end
974                    // of one of them, whichever comes first
975                    xx = MIN(end1, end2);
976
977                } 
978                else if (type1 == OccGridRLE::VARYING_DATA &&
979                         type2 == OccGridRLE::VARYING_DATA) {
980
981                    // If both are varying values, then write the new value
982                    rleScanlines[xx].putNextElement(elem2);
983                    xx++;
984
985                } else {
986                    // Else, clean up old run by updating length
987                    length = yy - runOffset[xx];
988                    setRunType(&length, type1);
989                    rleScanlines[xx].putNextLength(length);
990
991                    // Prepare for new run
992                    runOffset[xx] = yy;
993                    rleScanlines[xx].putNextElement(elem2);
994                    xx++;
995                }
996            }
997        }
998
999
1000        // One last run through to finish up lengths
1001        yy = this->ydim;
1002        lastScanline = getRLEScanline(yy-1, zz);
1003        lastScanline->reset();
1004        xx = 0;
1005        end1 = 0;       
1006        while (xx < this->xdim) {
1007            if (xx == end1) {
1008                length1 = lastScanline->getNextLength();
1009                type1 = getRunType(&length1);
1010                end1 += length1;
1011                elem1 = lastScanline->getNextElement();
1012            } else if (type1 == OccGridRLE::VARYING_DATA) {
1013                elem1 = lastScanline->getNextElement();
1014            }
1015            length = yy - runOffset[xx];
1016            setRunType(&length, type1);
1017            rleScanlines[xx].putNextLength(length);
1018            xx++;
1019        }
1020
1021
1022        // Write out the end-of-run flags and copy runs to output grid
1023        for (yy = 0; yy < outGrid->ydim; yy++) {
1024            rleScanlines[yy].putNextLength(OccGridRLE::END_OF_RUN);
1025            outGrid->allocNewRun(yy, zz);
1026            outGrid->copyScanline(&rleScanlines[yy], yy, zz);
1027        }
1028    }
1029   
1030#if OCCGRIDRLE_RECOMPACT
1031    // Re-compactify
1032    this->copy(outGrid);
1033
1034    // Put into output
1035    outGrid->copy(this);
1036#endif //OCCGRIDRLE_RECOMPACT
1037
1038    // So that scanline deletion will not try to free these
1039    for (yy = 0; yy < outGrid->ydim; yy++) {
1040        rleScanlines[yy].lengths = NULL;
1041        rleScanlines[yy].elements = NULL;
1042    }
1043
1044    delete [] rleScanlines;
1045    delete [] lengthData;
1046    delete [] elementData;
1047    delete [] runTypes;
1048
1049    return TRUE;
1050}
1051
1052
1053int
1054OccGridRLE::transposeYZ(OccGridRLE *outGrid)
1055{
1056    int yy,zz;
1057    OccScanlineRLE *rleScanline;
1058
1059    outGrid->reset();
1060    outGrid->copyParams(this); 
1061    SWAP_INT(outGrid->ydim, outGrid->zdim);
1062    SWAP_FLOAT(outGrid->origin[1], outGrid->origin[2]);
1063
1064    for (zz = 0; zz < outGrid->zdim; zz++) {
1065        for (yy = 0; yy < outGrid->ydim; yy++) {
1066            rleScanline = this->getRLEScanline(zz, yy);
1067            outGrid->copyScanline(rleScanline, yy, zz);
1068        }
1069    }
1070
1071    if (outGrid->axis == Y_AXIS)
1072        outGrid->axis = Z_AXIS;
1073    else if (outGrid->axis == Z_AXIS)
1074        outGrid->axis = Y_AXIS;
1075
1076    return TRUE;
1077}
1078
1079
1080OccScanlineRLE *
1081OccGridRLE::getRLEScanline(int y, int z)
1082{
1083    setScanline(y, z);
1084    rleScanline->lengths = currentLength;
1085    rleScanline->elements = currentElem;
1086    rleScanline->reset();
1087    return rleScanline;
1088}
1089
1090
1091OccElement *
1092OccGridRLE::getScanline(int y, int z)
1093{
1094    int i;
1095    assert (y<=ydim);
1096    assert (z<=zdim);
1097    assert (y>=0);
1098    assert (z>=0);
1099    setScanline(y, z);
1100    //printf ("%d %d\n",y,z);
1101   
1102    OccElement *scanPtr = this->scanline;
1103
1104    RunLength length;
1105    int runType;
1106    OccElement *element;
1107
1108    int xx = 0;
1109    while (TRUE) {
1110        length = getNextLength();
1111        runType = getRunType(&length);
1112
1113        if (runType == OccGridRLE::END_OF_RUN)
1114            break;
1115
1116        if (runType == OccGridRLE::CONSTANT_DATA) {
1117            element = getNextElement();
1118            for (i=0; i<length; i++, scanPtr++, xx++) {
1119                scanPtr->value = element->value;
1120                scanPtr->totalWeight = element->totalWeight;
1121            }
1122        }
1123        else {
1124            for (i=0; i<length; i++, scanPtr++, xx++) {
1125                element = getNextElement();
1126                scanPtr->value = element->value;
1127                scanPtr->totalWeight = element->totalWeight;
1128            }
1129        }
1130    }
1131
1132    assert(xx == this->xdim);
1133
1134    return this->scanline;
1135}
1136
1137
1138void
1139OccGridRLE::copyScanline(OccScanlineRLE *rleScanline, int y, int z)
1140{
1141    int i;
1142    RunLength length;
1143    int runType;
1144    OccElement *element;
1145
1146    rleScanline->reset();
1147    allocNewRun(y,z);
1148
1149    while (TRUE) {
1150        length = rleScanline->getNextLength();
1151        putNextLength(length);
1152
1153        runType = getRunType(&length);
1154
1155        if (runType == OccGridRLE::END_OF_RUN)
1156            break;
1157
1158        if (runType == OccGridRLE::CONSTANT_DATA) {
1159            element = rleScanline->getNextElement();
1160            putNextElement(element);
1161        }
1162        else {
1163            for (i=0; i<length; i++) {
1164                element = rleScanline->getNextElement();
1165                putNextElement(element);
1166            }
1167        }
1168    }
1169}
1170
1171
1172void
1173OccGridRLE::putScanline(OccElement *line, int y, int z)
1174{
1175    OccElement *scan = line;
1176    ushort count;
1177
1178    int xoff = 0;
1179
1180    allocNewRun(y, z);
1181
1182    while (TRUE) {
1183        if (scan->totalWeight == emptyNoWeight.totalWeight
1184            && scan->value == emptyNoWeight.value) {
1185            count = 0;
1186            while(scan->totalWeight == emptyNoWeight.totalWeight
1187                  && scan->value == emptyNoWeight.value
1188                  && xoff < this->xdim) {
1189                scan++;
1190                count++;
1191                xoff++;
1192            }
1193            setRunType(&count, OccGridRLE::CONSTANT_DATA);
1194            putNextLength(count);
1195            putNextElement(&emptyNoWeight);
1196        }
1197        else if (scan->totalWeight == fullNoWeight.totalWeight
1198            && scan->value == fullNoWeight.value) {
1199            count = 0;
1200            while(scan->totalWeight == fullNoWeight.totalWeight
1201                  && scan->value == fullNoWeight.value
1202                  && xoff < this->xdim) {
1203                scan++;
1204                count++;
1205                xoff++;
1206            }
1207            setRunType(&count, OccGridRLE::CONSTANT_DATA);
1208            putNextLength(count);
1209            putNextElement(&fullNoWeight);
1210        }
1211        else {
1212            count = 0;
1213            while (!(scan->totalWeight == emptyNoWeight.totalWeight
1214                     && scan->value == emptyNoWeight.value) && 
1215                   !(scan->totalWeight == fullNoWeight.totalWeight
1216                     && scan->value == fullNoWeight.value) &&
1217                   xoff < this->xdim) {
1218                putNextElement(scan);
1219                scan++;
1220                count++;
1221                xoff++;         
1222            }
1223            setRunType(&count, OccGridRLE::VARYING_DATA);
1224            putNextLength(count);
1225        }
1226
1227        if (xoff == this->xdim) {
1228            setRunType(&count, OccGridRLE::END_OF_RUN);     
1229            putNextLength(count);
1230            break;
1231        }
1232    }
1233}
1234
1235
1236OccElement *
1237OccGridRLE::getSlice(const char *axis, int sliceNum, int *pxdim, int *pydim)
1238{
1239    OccElement *buf1, *buf2;
1240    int xx, yy, zz;
1241
1242    buf1 = slice;
1243    if (EQSTR(axis, "x")) {
1244        if (sliceNum < this->xdim) {
1245            for (yy = 0; yy < this->ydim; yy++) {
1246                for (zz = 0; zz <this->zdim; zz++, buf1++) {
1247                    buf2 = this->getElement(sliceNum, yy, zz);
1248                    buf1->value = buf2->value;
1249                    buf1->totalWeight = buf2->totalWeight;
1250                }
1251            }
1252        }
1253        *pxdim = this->zdim;
1254        *pydim = this->ydim;
1255    }
1256    else if (EQSTR(axis, "y")) {
1257        if (sliceNum < this->ydim) {
1258            for (zz = 0; zz < this->zdim; zz++) {
1259                buf2 = this->getScanline(sliceNum,zz);
1260                for (xx = 0; xx < this->xdim; xx++, buf1++, buf2++) {
1261                    buf1->value = buf2->value;
1262                    buf1->totalWeight = buf2->totalWeight;
1263                }
1264            }
1265        }
1266        *pxdim = this->xdim;
1267        *pydim = this->zdim;
1268    }
1269    else if (EQSTR(axis, "z")) {
1270        if (sliceNum < this->zdim) {
1271            for (yy = 0; yy < this->ydim; yy++) {
1272                buf2 = this->getScanline(yy, sliceNum);
1273                for (xx = 0; xx < this->xdim; xx++, buf1++, buf2++) {
1274                    buf1->value = buf2->value;
1275                    buf1->totalWeight = buf2->totalWeight;
1276                }
1277            }
1278        }
1279        *pxdim = this->xdim;
1280        *pydim = this->ydim;
1281    }
1282
1283    return this->slice;
1284}
1285
1286
1287void
1288OccGridRLE::clear()
1289{
1290    RunLength length, end;
1291   
1292    this->reset();
1293
1294    setRunType(&end, OccGridRLE::END_OF_RUN);
1295
1296    length = this->xdim;
1297    setRunType(&length, OccGridRLE::CONSTANT_DATA);
1298   
1299    for (int zz = 0; zz < this->zdim; zz++) {
1300        for (int yy = 0; yy < this->ydim; yy++) {
1301            allocNewRun(yy, zz);
1302            putNextLength(length);
1303            putNextElement(defaultElement);
1304            putNextLength(end);
1305        }
1306    }
1307}
1308
1309
1310void
1311OccGridRLE::reset()
1312{
1313    this->lengthChunker->reset();
1314    this->elementChunker->reset();
1315}
1316
1317
1318void
1319OccGridRLE::runStats(int yy, int zz, int *numRuns, int *numElems)
1320{
1321    int runType, runCount, elemCount;
1322    RunLength length;
1323
1324    setScanline(yy,zz);
1325
1326    runCount = 0;
1327    elemCount = 0;
1328    while (TRUE) {
1329        length = getNextLength();
1330        runType = getRunType(&length);
1331
1332        if (runType == OccGridRLE::END_OF_RUN)
1333            break;
1334
1335        elemCount += length;
1336        runCount++;
1337    }
1338
1339    *numRuns = runCount;
1340    *numElems = elemCount;
1341}
1342
1343
1344OccElement *
1345OccGridRLE::getElement(int xx, int yy, int zz)
1346{
1347    OccElement *element;
1348    RunLength length;
1349    int runType;
1350
1351    setScanline(yy, zz);
1352   
1353    int currentX = 0;
1354    while (TRUE) {
1355        length = getNextLength();
1356        runType = getRunType(&length);
1357
1358        assert(runType != OccGridRLE::END_OF_RUN);
1359
1360        if (runType == OccGridRLE::CONSTANT_DATA) {
1361            element = getNextElement();
1362            currentX += length;
1363            if (xx < currentX)
1364                break;
1365        }
1366        else {
1367            // Really inefficient!!
1368/*
1369            for (int i = 0; i < length; i++, currentX++) {
1370                element = getNextElement();
1371                if (xx == currentX)
1372                    break;
1373            }
1374*/
1375
1376            if (xx < currentX+length) {
1377                currentElem += (xx - currentX);
1378                element = getNextElement();
1379                break;
1380            } else {
1381                currentX += length;
1382                currentElem += length;
1383            }
1384        }
1385    }
1386    return element;
1387}
1388
1389OccElement OccGridRLE::voxRead(int x, int y, int z)
1390{
1391  assert(x>=0 && x<xdim && y>=0 && y<ydim && z>=0 && z<zdim);
1392  OccElement *line;
1393  line = getScanline(y,z);
1394
1395  return line[x];
1396 
1397}
1398
1399void OccGridRLE::voxWrite(int x, int y, int z, OccElement &el)
1400{
1401  assert(x>=0 && x<xdim && y>=0 && y<ydim && z>=0 && z<zdim);
1402 
1403  OccElement *line;
1404  line = getScanline(y,z);
1405  line[x]=el;
1406  putScanline(line,y,z);
1407}
1408
1409OccGrid *OccGridRLE::voxExpand()
1410{
1411  puts ("Expanding grid");
1412  printf("OccEl size %d\n",sizeof(OccElement));
1413  printf("About to use MB%d\n " ,(int)(sizeof(OccElement)*(double)xdim*(double)ydim*(double)zdim/(double)(1024*1024)));
1414  OccGrid *og=new OccGrid(xdim,ydim,zdim);
1415  for (int y=0;y<ydim;y++)
1416    for (int z=0;z<zdim; z++)
1417      {
1418        OccElement *line=getScanline(y,z);
1419        for  (int x=0;x<xdim;x++)
1420          {
1421            *(og->address(x,y,z))=line[x];
1422          }
1423      }
1424  puts ("Done expanding grid");
1425  return og;
1426}
1427
1428void OccGridRLE::voxRLE(OccGrid *og)
1429{
1430  puts ("Starting grid RLE");
1431   for (int y=0;y<ydim;y++)
1432    for (int z=0;z<zdim; z++)
1433      {
1434        OccElement *line=getScanline(y,z);
1435        for  (int x=0;x<xdim;x++)
1436          {
1437            line[x]=*(og->address(x,y,z));
1438          }
1439        putScanline(line,y,z);
1440      }
1441   puts ("Finished grid RLE");
1442}
Note: See TracBrowser for help on using the repository browser.