Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   Related Pages  

sglLineStripper.hpp

00001 /*****************************************************************************
00002  * SGL: A Scene Graph Library
00003  *
00004  * Copyright (C) 1997-2001  Scott McMillan   All Rights Reserved.
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Library General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Library General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Library General Public
00017  * License along with this library; if not, write to the Free
00018  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  *****************************************************************************
00020  *     File: sglLineStripper.hpp
00021  *   Author: Tom Stimson
00022  *  Created: 9 September 1999
00023  *  Summary: strip line segments together
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    // not implemented
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

Generated at Mon Jul 1 18:00:05 2002 for SGL by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001