source: GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h @ 2116

Revision 2116, 17.6 KB checked in by mattausch, 17 years ago (diff)

implemented hashpvs

Line 
1#ifndef __VERBOSEPVS_H
2#define __VERBOSEPVS_H
3
4#include <vector>
5#include "common.h"
6#include <math.h>
7#include "PvsBase.h"
8
9
10using namespace std;
11
12namespace GtpVisibilityPreprocessor {
13
14
15template<typename T, typename S>
16class PvsIterator
17{
18public:
19        PvsIterator<T, S>(){}
20        PvsIterator<T, S>(const typename vector<PvsEntry<T, S> >::const_iterator &itCurrent,
21                                          const typename vector<PvsEntry<T, S> >::const_iterator &itEnd):
22        mItCurrent(itCurrent), mItEnd(itEnd)
23        {
24        }
25
26        bool HasMoreEntries() const
27        {
28                return (mItCurrent != mItEnd);
29        }
30
31        const PvsEntry<T, S> &Next()
32        {
33                return *(mItCurrent ++);
34        }
35
36private:
37        typename vector<PvsEntry<T, S> >::const_iterator mItCurrent;
38        typename vector<PvsEntry<T, S> >::const_iterator mItEnd;
39};
40
41
42/** Template class representing the Potentially Visible Set (PVS)
43        mainly from a view cell, but also e.g., from objects.
44*/
45template<typename T, typename S>
46class VerbosePvs
47{
48        template<typename T, typename S> friend class PvsIterator;
49
50public:
51
52        VerbosePvs(): mSamples(0), mEntries(), mLastSorted(0), mQueriesSinceSort(0) {}
53
54        /** creates pvs and initializes it with the given entries.
55        Assumes that entries are sorted-
56        */
57        VerbosePvs(const vector<PvsEntry<T, S> > &samples);
58        virtual ~VerbosePvs() {};
59
60        /** Compresses PVS lossless or lossy.
61        */
62        int Compress()
63        {
64                return 0;
65        }
66       
67        int GetSize() const
68        {
69                return (int)mEntries.size();
70        }
71       
72        bool Empty() const
73        {
74                return mEntries.empty();
75        }
76
77        void Reserve(const int n)
78        {
79                mEntries.reserve(n);
80        }
81
82        /** Normalize the visibility of entries in order to get
83        comparable results.
84        */
85        void NormalizeMaximum();
86
87        /** Merges pvs of a into this pvs.
88        Warning: very slow!
89        */
90        void MergeInPlace(const VerbosePvs<T, S> &a);
91
92        /** Difference of pvs to pvs b.
93        @returns number of different entries.
94        */
95        int Diff(const VerbosePvs<T, S> &b);
96
97        /** Finds sample in PVS.
98                @param checkDirty if dirty part of the pvs should be checked for entry
99                (warning: linear runtime in dirty part)
100                @returns iterator on the sample if found, else the place where
101                it would be added in the sorted vector.
102        */
103        bool Find(T sample,
104                          typename vector<PvsEntry<T, S> >::iterator &it,
105                          const bool checkDirty = true);
106
107        bool GetSampleContribution(T sample, const float pdf, float &contribution);
108
109        /** Adds sample to PVS.
110                @returns contribution of sample (0 or 1)
111        */
112        float AddSample(T sample, const float pdf);
113
114        /** Adds sample to PVS without checking for presence of the sample
115                warning: pvs remains unsorted!
116        */
117        void AddSampleDirty(T sample, const float pdf);
118
119        /** Adds sample dirty (on the end of the vector) but
120                first checks if sample is already in clean part of the pvs.
121        */
122        bool AddSampleDirtyCheck(T sample, const float pdf);
123
124        /** Sort pvs entries - this should always be called after a
125                sequence of AddSampleDirty calls
126        */
127        void Sort();
128
129        /** Sort pvs entries assume that the pvs contains unique entries
130        */
131        void SimpleSort();
132
133        /** Adds sample to PVS.
134                @returns PvsData
135        */
136        typename std::vector<PvsEntry<T, S> >::iterator
137                AddSample2(T sample, const float pdf);
138
139        /** Subtracts one pvs from another one.
140                WARNING: could contains bugs
141                @returns new pvs size
142        */
143        int SubtractPvs(const VerbosePvs<T, S> &pvs);
144
145        /** Returns PVS data, i.e., how often it was seen from the view cell,
146                and the object itsef.
147        */
148        void GetData(const int index, T &entry, S &data);
149
150        /** Collects the PVS entries and returns them in the vector.
151        */
152        void CollectEntries(std::vector<T> &entries);
153
154        /** Removes sample from PVS if reference count is zero.
155        @param visibleSamples number of references to be removed
156        */
157        bool RemoveSample(T sample, const float pdf);
158
159        /** Compute continuous PVS difference
160        */
161        void ComputeContinuousPvsDifference(VerbosePvs<T, S> &pvs,
162                                                                                float &pvsReduction,
163                                                                                float &pvsEnlargement);
164
165        /** Clears the pvs.
166        */
167        void Clear(const bool trim = true);
168
169        void Trim();
170
171        static int GetEntrySizeByte();
172        static float GetEntrySize();
173
174        /** Compute continuous PVS difference
175        */
176        float GetPvsHomogenity(VerbosePvs<T, S> &pvs);
177
178        static void Merge(VerbosePvs<T, S> &mergedPvs,
179                                          const VerbosePvs<T, S> &a,
180                                          const VerbosePvs<T, S> &b);
181
182        int GetSamples() const
183        {
184                return mSamples;
185        }
186
187        bool IsDirty() const
188        {
189                return mLastSorted < mEntries.size();
190        }
191
192        bool RequiresResort() const
193        {
194                // the last part should not be more than log of the sorted part. this
195                // way we can achieve logarithmic behaviour for insertion and find
196                const int n = mEntries.size();
197                const int dirtySize = n - mLastSorted;
198
199                const double LOG2E = 1.442695040f;
200
201                const float logN = log((float)max(1, n))/LOG2E;
202                const float logS = log((float)max(1, mLastSorted))/LOG2E;
203                const float logD = log((float)max(1, dirtySize))/LOG2E;
204
205                if (8*(n + 2*dirtySize*logD) <
206                        mQueriesSinceSort*((mLastSorted*logS + dirtySize*dirtySize/2)/n - logN))
207                {
208                                //              cout<<"Q="<<mQueriesSinceSort<<" N="<<n<<" D="<<dirtySize<<endl;
209                        return true;
210                }
211               
212                return false;
213        }
214
215        bool RequiresResortLog() const
216        {
217                // the last part should not be more than log of the sorted part. this
218                // way we can achieve logarithmic behaviour for insertion and find
219                const int dirtySize = (int)mEntries.size() - mLastSorted;
220                return dirtySize > 4 * (int)(log((double)mEntries.size()) / log(2.0));
221        }
222
223        int GetLastSorted() const
224        {
225                return mLastSorted;
226        }
227
228        typename PvsIterator<T, S> GetIterator() const;
229
230protected:
231
232        static void Merge(VerbosePvs<T, S> &mergedPvs,
233                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &aBegin,
234                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &aEnd,
235                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &bBegin,
236                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &bEnd,
237                                          const int aSamples,
238                                          const int bSamples);
239
240        //////////////////////////////
241
242        /// vector of PVS entries
243        vector<PvsEntry<T, S> > mEntries;
244
245        /// Number of samples used to create the PVS
246        int mSamples;
247
248        /// Last sorted entry in the pvs (important for find and merge)
249        int mLastSorted;
250
251        int mQueriesSinceSort;
252};
253
254
255template <typename T, typename S>
256VerbosePvs<T, S>::VerbosePvs(const vector<PvsEntry<T, S> > &samples)
257{
258        mEntries.reserve(samples.size());
259        mEntries = samples;
260        mLastSorted = 0;
261        mSamples = samples.size();
262}
263
264
265template <typename T, typename S>
266void VerbosePvs<T, S>::Sort()
267{
268        vector<PvsEntry<T, S> >::iterator it = mEntries.begin() + mLastSorted;
269        vector<PvsEntry<T, S> >::iterator it_end = mEntries.end();
270
271        // throw out double entries
272        std::vector<PvsEntry<T, S> >::iterator newEnd = unique(it, it_end);
273        sort(it, newEnd);
274       
275        // now merge sorted ranges
276        ObjectPvs newPvs;
277        Merge(newPvs,
278                  mEntries.begin(),
279                  it,
280                  it,
281                  newEnd,
282                  mSamples,
283                  0);
284       
285        mEntries = newPvs.mEntries;
286        mLastSorted = (int)mEntries.size();
287        mQueriesSinceSort = 0;
288}
289
290template <typename T, typename S>
291void VerbosePvs<T, S>::SimpleSort()
292{
293        //  sort(mEntries.begin(), mEntries.end());
294        vector<PvsEntry<T, S> >::iterator it = mEntries.begin() + mLastSorted;
295
296        sort(it, mEntries.end());
297        inplace_merge(mEntries.begin(), it, mEntries.end());
298 
299        mLastSorted = (int)mEntries.size();
300        mQueriesSinceSort = 0;
301}
302
303
304/**
305   Compute continuous PVS difference of 'b' with respect to the base PVS (*this).
306   Provides separatelly PVS reduction from PVS enlargement.
307
308*/
309template <typename T, typename S>
310void
311VerbosePvs<T, S>::ComputeContinuousPvsDifference(VerbosePvs<T, S> &b,
312                                                                                  float &pvsReduction,
313                                                                                  float &pvsEnlargement)
314{
315        pvsReduction = 0.0f;
316        pvsEnlargement = 0.0f;
317
318        // Uses sum of log differences, which corresponds to entropy
319        vector<PvsEntry<T, S> >::iterator it;
320
321        for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
322        {
323                float bSumPdf = (*it).mData.mSumPdf;
324                float aSumPdf = 0.0f;
325
326                vector<PvsEntry<T, S> >::iterator oit;
327                const bool entryFound = Find((*it).mObject, oit);               
328
329                if (entryFound)
330                {
331                        aSumPdf = (*it).mData.mSumPdf;
332
333                        // mark this entry as processed to avoid double counting
334                        (*it).mData.mSumPdf = -aSumPdf;
335                }
336
337#if 0
338                const float diff = bSumPdf - aSumPdf;
339
340                if (diff > 0.0f)
341                {
342                        pvsEnlargement += diff;
343                }
344                else
345                {
346                        pvsReduction += -diff;
347                }
348#else
349                if (!entryFound)
350                {
351                        pvsEnlargement += 1.0f;
352                }
353#endif
354        }
355
356        for (it = mEntries.begin(); it != mEntries.end(); ++ it)
357        {
358                float aSumPdf = (*it).mData.mSumPdf;
359                float bSumPdf = 0.0f;
360                if (aSumPdf < 0.0f)
361                {
362                        // this entry was already accounted for!
363                        // just revert it back
364                        (*it).mData.mSumPdf = -aSumPdf;
365                }
366                else
367                {
368                        vector<PvsEntry<T, S> >::iterator oit;
369               
370                        const bool entryFound = b.Find((*it).mObject, oit);
371                                               
372                        if (entryFound) {
373                                bSumPdf = (*oit).mData.mSumPdf;
374                        }
375#if 0
376                        const float diff = bSumPdf - aSumPdf;
377
378                        if (diff > 0.0f) {
379                                pvsEnlargement += diff;
380                        } else {
381                                pvsReduction += -diff;
382                        }
383
384#else
385                        if (!entryFound)
386                                pvsReduction += 1.0f;
387#endif
388                }
389        }
390}
391
392
393template <typename T, typename S>
394int VerbosePvs<T, S>::Diff(const VerbosePvs<T, S> &b)
395{
396        int dif = 0;
397
398        std::vector<PvsEntry<T, S> >::const_iterator it;
399
400        for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
401        {
402                vector<PvsEntry<T, S> >::iterator bit;
403                const bool entryFound = Find((*it).first, bit);
404
405                if (!entryFound) ++ dif;
406        }
407
408        return dif;
409}
410
411
412template <typename T, typename S>
413void VerbosePvs<T, S>::MergeInPlace(const VerbosePvs<T, S> &a)
414{
415        // early exit
416        if (a.Empty())
417        {
418                return;
419        }
420        else if (Empty())
421        {
422                mEntries.reserve(a.GetSize());
423                mEntries = a.mEntries;
424                mSamples = a.mSamples;
425                return;
426        }
427
428        ObjectPvs interPvs;
429       
430        Merge(interPvs, *this, a);
431       
432        mEntries.reserve(interPvs.GetSize());
433        mEntries = interPvs.mEntries;
434        mSamples = interPvs.mSamples;
435}
436
437
438template <typename T, typename S>
439void VerbosePvs<T, S>::Merge(VerbosePvs<T, S> &mergedPvs,
440                                                         const VerbosePvs<T, S> &a,
441                                                         const VerbosePvs<T, S> &b)
442{
443        std::vector<PvsEntry<T, S> >::const_iterator ait =
444                a.mEntries.begin(), ait_end = a.mEntries.end();
445        std::vector<PvsEntry<T, S> >::const_iterator bit =
446                b.mEntries.begin(), bit_end = b.mEntries.end();
447       
448        Merge(mergedPvs,
449                  ait, ait_end,
450                  bit, bit_end,
451                  a.mSamples,
452                  b.mSamples);
453}
454
455
456template <typename T, typename S>
457void VerbosePvs<T, S>::Merge(VerbosePvs<T, S> &mergedPvs,
458                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &aBegin,
459                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &aEnd,
460                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &bBegin,
461                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &bEnd,
462                                          const int aSamples,
463                                          const int bSamples)
464{
465        std::vector<PvsEntry<T, S> >::const_iterator ait = aBegin;
466        std::vector<PvsEntry<T, S> >::const_iterator bit = bBegin;
467       
468        for (; (ait != aEnd); ++ ait)
469        {
470                Intersectable *aObj = (*ait).mObject;
471                Intersectable *bObj = NULL;
472                //Intersectable *bObjOld = NULL;
473       
474                const PvsEntry<T, S> &aEntry = (*ait);
475
476                for (; (bit != bEnd) && ((*bit).mObject <= (*ait).mObject); ++ bit)
477                {
478                        bObj = (*bit).mObject;
479
480                        // object found => add up probabilities
481                        if (bObj == aEntry.mObject)
482                        {
483                                PvsData newData(aEntry.mData.mSumPdf + (*bit).mData.mSumPdf);
484                                PvsEntry<T, S> entry(bObj, newData);
485                                mergedPvs.mEntries.push_back(entry);
486                        }
487                        else
488                        {
489                                mergedPvs.mEntries.push_back(*bit);
490                        }
491                }
492
493                // only push back if objects different
494                // (equal case is handled by second loop)
495                if (aObj != bObj)
496                {
497                        mergedPvs.mEntries.push_back(*ait);
498                }
499        }
500
501        // add the rest
502        for (; (bit != bEnd); ++ bit)
503        {
504                mergedPvs.mEntries.push_back(*bit);
505        }
506
507        mergedPvs.mSamples = aSamples + bSamples;
508}
509
510
511template <typename T, typename S> void VerbosePvs<T, S>::Clear(const bool trim = true)
512{
513        mEntries.clear();
514        mSamples = 0;
515        mLastSorted = 0;
516
517        if (trim)
518        {
519                vector<PvsEntry<T,S> >().swap(mEntries);
520        }
521}
522
523
524template <typename T, typename S> void VerbosePvs<T, S>::Trim()
525{
526        vector<PvsEntry<T,S> >(mEntries).swap(mEntries);
527}
528
529
530template <typename T, typename S>
531bool VerbosePvs<T, S>::Find(T sample,
532                                         typename vector<PvsEntry<T, S> >::iterator &it,
533                                         const bool checkDirty)
534{
535        bool found = false;
536       
537        PvsEntry<T, S> dummy(sample, PvsData());
538
539        // only check clean part
540        vector<PvsEntry<T, S> >::iterator sorted_end = mEntries.begin() + mLastSorted;
541        mQueriesSinceSort++;
542
543        // binary search
544        it = lower_bound(mEntries.begin(), sorted_end, dummy);
545
546        if ((it != mEntries.end()) && ((*it).mObject == sample))
547                found = true;
548
549        // sample not found yet => search further in the unsorted part
550        if (!found && checkDirty)
551        {
552                vector<PvsEntry<T, S> >::iterator dit, dit_end = mEntries.end();
553
554        for (dit = sorted_end; (dit != dit_end) && ((*dit).mObject != sample); ++ dit);
555       
556                if (dit != dit_end)
557                {
558                        found = true;
559                        it = dit;
560                }
561        }
562
563        return found;
564}
565
566
567template <typename T, typename S>
568void VerbosePvs<T, S>::GetData(const int index, T &entry, S &data)
569{
570        std::vector<PvsEntry<T, S> >::iterator i = mEntries.begin();
571        for (int k = 0; k != index && i != mEntries.end(); ++ i, ++ k);
572
573        entry = (*i).first;
574        data = (*i).second;
575}
576
577
578template <typename T, typename S>
579float VerbosePvs<T, S>::AddSample(T sample, const float pdf)
580{
581        ++ mSamples;
582       
583        vector<PvsEntry<T, S> >::iterator it;
584        const bool entryFound = Find(sample, it);               
585
586        if (entryFound)
587        {       
588                S &data = (*it).mData;
589                data.mSumPdf += pdf;
590                return data.mSumPdf;
591        }
592        else
593        {
594                PvsEntry<T, S> entry(sample, pdf);
595                mEntries.insert(it, entry);
596                ++ mLastSorted;
597                return pdf;
598        }
599}
600
601
602template <typename T, typename S>
603void VerbosePvs<T, S>::AddSampleDirty(T sample, const float pdf)
604{
605        ++ mSamples;
606        mEntries.push_back(PvsEntry<T, S>(sample, pdf));
607}
608                                         
609
610template <typename T, typename S>
611typename vector< PvsEntry<T, S> >::iterator VerbosePvs<T, S>::AddSample2(T sample,
612                                                                                                                                  const float pdf)
613{
614        ++ mSamples;
615       
616        vector<PvsEntry<T, S> >::iterator it;
617        const bool entryFound = Find(sample, it);
618
619        if (entryFound)
620        {
621                S &data = (*it).second;
622                data->mSumPdf += pdf;
623        }
624        else
625        {
626                PvsEntry<T, S> entry(sample, pdf);
627                mEntries.insert(it, entry);
628                ++ mLastSorted;
629        }
630
631        return it;
632}
633
634
635template <typename T, typename S>
636bool VerbosePvs<T, S>::AddSampleDirtyCheck(T sample,
637                                                                        const float pdf)
638                                                                        //,float &contribution)
639{
640        ++ mSamples;
641
642        vector<PvsEntry<T, S> >::iterator it;
643        const bool entryFound = Find(sample, it);
644
645        if (entryFound)
646        {
647                S &data = (*it).mData;
648         
649                data.mSumPdf += pdf;
650                //contribution = pdf / data.mSumPdf;
651
652        return false;
653        }
654        else
655        {
656                AddSampleDirty(sample, pdf);
657                //contribution = 1.0f;
658               
659                return true;
660        }
661}
662
663
664template <typename T, typename S>
665bool VerbosePvs<T, S>::GetSampleContribution(T sample,
666                                                                          const float pdf,
667                                                                          float &contribution)
668{
669        vector<PvsEntry<T, S> >::iterator it;
670        const bool entryFound = Find(sample, it);
671
672        if (entryFound) 
673        {
674                S &data = (*it).mData;
675                contribution = pdf / (data.mSumPdf + pdf);
676                return false;
677        }
678        else
679        {
680                contribution = 1.0f;
681                return true;
682        }
683}
684
685
686template <typename T, typename S>
687bool VerbosePvs<T, S>::RemoveSample(T sample, const float pdf)
688{
689        -- mSamples;
690       
691        vector<PvsEntry<T, S> >::iterator it;
692        const bool entryFound = Find(sample, it);
693
694        if (!entryFound)
695                return false;
696
697        S &data = (*it).mData;
698
699        data.mSumPdf -= pdf;
700
701        if (data.mSumPdf <= 0.0f)
702        {
703                mEntries.erase(it);
704                -- mLastSorted; // wrong if sample was in tail!!
705        }
706
707        return true;
708}
709
710
711template <typename T, typename S>
712int VerbosePvs<T, S>::SubtractPvs(const VerbosePvs<T, S> &pvs)
713{
714        const int samples = mSamples - pvs.mSamples;
715
716        std::vector<PvsEntry<T, S> >::
717                const_iterator it, it_end = pvs.mEntries.end();
718
719        // output PVS of view cell
720        for (it = pvs.mEntries.begin(); it != it_end; ++ it)
721                RemoveSample((*it).mObject, (*it).mData.mSumPdf);
722
723        mSamples = samples;
724
725        return GetSize();
726}
727
728
729template <typename T, typename S>
730void VerbosePvs<T, S>::CollectEntries(std::vector<T> &entries)
731{
732        std::vector<PvsEntry<T, S> >::
733                const_iterator it, it_end = mEntries.end();
734
735        // output PVS of view cell
736        for (it = mEntries.begin(); it != it_end; ++ it)
737                entries.push_back((*it)->first);
738}
739
740
741template <typename T, typename S>
742void VerbosePvs<T, S>::NormalizeMaximum()
743{
744        std::vector<PvsEntry<T, S> >::
745                const_iterator it, it_end = mEntries.end();
746
747        float maxPdfSum = -1.0f;
748
749        // output PVS of view cell
750        for (it = mEntries.begin(); it != it_end; ++ it) {
751                float sum = (*it)->second.sumPdf;
752                if (sum > maxSum)
753                        maxSum = sum;
754        }
755
756        maxSum = 1.0f / maxSum;
757
758        for (it = mEntries.begin(); it != it_end; ++ it) {
759                (*it)->second.sumPdf *= maxSum;
760        }
761}
762
763
764template <typename T, typename S>
765float VerbosePvs<T, S>::GetEntrySize()
766{
767        return (float)(sizeof(T) + sizeof(S)) / float(1024 * 1024);
768}
769
770
771template <typename T, typename S>
772int VerbosePvs<T, S>::GetEntrySizeByte()
773{
774        return sizeof(T) + sizeof(S);
775}
776
777
778template <typename T, typename S>
779float VerbosePvs<T, S>::GetPvsHomogenity(VerbosePvs<T, S> &pvs)
780{
781        float pvsReduction, pvsEnlargement;
782
783        ComputeContinuousPvsDifference(pvs,     pvsReduction, pvsEnlargement);
784        return pvsReduction + pvsEnlargement;
785}
786
787
788template <typename T, typename S>
789typename PvsIterator<T, S> VerbosePvs<T, S>::GetIterator() const
790{
791        PvsIterator<T, S> pit(mEntries.begin(), mEntries.end());
792        return pit;
793}
794
795}
796
797#endif
798
Note: See TracBrowser for help on using the repository browser.