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

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

Added original make3d

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