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

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

Added original make3d

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