00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef __SGL_LINE_STRIPPER_HPP
00027 #define __SGL_LINE_STRIPPER_HPP
00028
00029 #include <sgldb.h>
00030 #include <deque>
00031 #include <list>
00032 #include <vector>
00033 #include <sglHashTable.hpp>
00034 #include <sglOStream.hpp>
00035
00036
00037 template <class T>
00038 class SGLDB_DLL_API sglLineStripper
00039 {
00040 public:
00041 sglLineStripper();
00042 ~sglLineStripper();
00043
00044 void addSegment(const T& end1, const T& end2);
00045
00046 void lineStripify();
00047
00048 void reset();
00049
00050 unsigned int getNumSegments() {return m_segment;}
00051
00052 unsigned int getNumStrips() {return m_strips.size();}
00053
00054 const deque<T>& getStrip(unsigned int indx) {return *(m_strips[indx]);}
00055
00056 private:
00057
00058 sglLineStripper(const sglLineStripper &);
00059 const sglLineStripper &operator=(const sglLineStripper &);
00060
00061
00062 class segment
00063 {
00064 public:
00065 segment(T end1, T end2, bool used) :
00066 m_end1(end1), m_end2(end2), m_used(used) {};
00067 ~segment() {};
00068 public:
00069 T m_end1;
00070 T m_end2;
00071 bool m_used;
00072 };
00073 class segmentEnd
00074 {
00075 public:
00076 T m_v;
00077
00078 typename list< segment >::iterator m_seg;
00079
00080 int hash(unsigned int hashsize)
00081 {
00082 int val = m_v.hash();
00083 val = val & 0x7fffffff;
00084 return val % hashsize;
00085 }
00086
00087 bool isEqual(segmentEnd *rhs)
00088 {
00089 return m_v == rhs->m_v && !(rhs->m_seg->m_used);
00090 }
00091 };
00092 friend class segmentEnd;
00093
00094 private:
00095 unsigned int m_num_segments;
00096 list<segment> m_segments;
00097 vector< deque<T>* > m_strips;
00098 unsigned int m_strip_len;
00099 };
00100
00101
00102
00103 template <class T>
00104 inline
00105 sglLineStripper<T>::sglLineStripper() :
00106 m_num_segments(0),
00107 m_strip_len(0)
00108 {
00109 }
00110
00111
00112
00113 template <class T>
00114 inline
00115 sglLineStripper<T>::~sglLineStripper()
00116 {
00117 reset();
00118 }
00119
00120
00121
00122 template <class T>
00123 inline
00124 void sglLineStripper<T>::reset()
00125 {
00126 while (!m_strips.empty())
00127 {
00128 deque<T>* strip = m_strips.back();
00129 delete strip;
00130 m_strips.pop_back();
00131 }
00132 if (!m_segments.empty())
00133 {
00134 m_segments.erase(m_segments.begin(), m_segments.end());
00135 }
00136 m_num_segments = 0;
00137 m_strip_len = 0;
00138 }
00139
00140
00141
00142 template <class T>
00143 inline
00144 void sglLineStripper<T>::addSegment(const T& end1, const T& end2)
00145 {
00146 m_segments.push_back(segment(end1, end2, false));
00147 ++m_num_segments;
00148 }
00149
00150
00151
00152 template <class T>
00153 inline
00154 void sglLineStripper<T>::lineStripify()
00155 {
00156 sglHashTable<segmentEnd> segHash(m_num_segments/2);
00157 segmentEnd* ends = new segmentEnd[m_num_segments*2];
00158 segmentEnd* nextEnd = ends;
00159 for (typename list<segment>::iterator ii = m_segments.begin();
00160 ii != m_segments.end(); ++ii)
00161 {
00162 nextEnd->m_v = ii->m_end1;
00163 nextEnd->m_seg = ii;
00164 segHash.add(nextEnd++);
00165 nextEnd->m_v = ii->m_end2;
00166 nextEnd->m_seg = ii;
00167 segHash.add(nextEnd++);
00168 }
00169
00170 segmentEnd* lastEnd = nextEnd;
00171 for (nextEnd = ends; nextEnd != lastEnd; ++nextEnd)
00172 {
00173 if (!(nextEnd->m_seg->m_used))
00174 {
00175 deque<T> *tmpList = new deque<T>();
00176 tmpList->push_back(nextEnd->m_seg->m_end1);
00177 tmpList->push_back(nextEnd->m_seg->m_end2);
00178 nextEnd->m_seg->m_used = true;
00179
00180 for(;;)
00181 {
00182 segmentEnd first;
00183 first.m_v = tmpList->front();
00184 first.m_seg = 0;
00185 segmentEnd* match = segHash.search(&first);
00186 if (match)
00187 {
00188 if (match->m_seg->m_end1 == first.m_v)
00189 tmpList->push_front(match->m_seg->m_end2);
00190 else
00191 tmpList->push_front(match->m_seg->m_end1);
00192 match->m_seg->m_used = true;
00193 }
00194 else
00195 {
00196 break;
00197 }
00198 }
00199 for(;;)
00200 {
00201 segmentEnd second;
00202 second.m_v = tmpList->back();
00203 second.m_seg = 0;
00204 segmentEnd* match = segHash.search(&second);
00205 if (match)
00206 {
00207 if (match->m_seg->m_end1 == second.m_v)
00208 tmpList->push_back(match->m_seg->m_end2);
00209 else
00210 tmpList->push_back(match->m_seg->m_end1);
00211 match->m_seg->m_used = true;
00212 }
00213 else
00214 {
00215 break;
00216 }
00217 }
00218
00219 m_strips.push_back(tmpList);
00220 m_strip_len += tmpList->size();
00221 }
00222 }
00223
00224 delete[] ends;
00225
00226 sglPrintInfo() << "sglLineStripper: Number of input segments = "
00227 << m_num_segments << endl;
00228 sglPrintInfo() << "sglLineStripper: Number of line strips = "
00229 << m_strips.size() << endl;
00230 sglPrintInfo() << "sglLineStripper: Avg. strip length = "
00231 << ((float) m_strip_len/(float) m_strips.size())
00232 << endl;
00233 sglPrintInfo() << "sglLineStripper: Total vertices to "
00234 "send to the pipe = " << m_strip_len << endl;
00235 }
00236
00237
00238 #endif