/home/andreas/src/svn/mapnik/include/mapnik/vertex_vector.hpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * 
00003  * This file is part of Mapnik (c++ mapping toolkit)
00004  *
00005  * Copyright (C) 2006 Artem Pavlenko
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020  *
00021  *****************************************************************************/
00022 //  Credits:
00023 //  I gratefully acknowledge the inspiring work of Maxim Shemanarev (McSeem), 
00024 //  author of Anti-Grain Geometry (http://www.antigrain.com). I have used 
00025 //  the datastructure from AGG as a template for my own. 
00026 
00027 
00028 //$Id: vertex_vector.hpp 39 2005-04-10 20:39:53Z pavlenko $
00029 
00030 #ifndef VERTEX_VECTOR_HPP
00031 #define VERTEX_VECTOR_HPP
00032 // stl
00033 #include <vector>
00034 // boost
00035 #include <boost/utility.hpp>
00036 #include <boost/tuple/tuple.hpp>
00037 // mapnik
00038 #include <mapnik/vertex.hpp>
00039 #include <mapnik/ctrans.hpp>
00040 
00041 namespace mapnik
00042 {
00043     template <typename T>
00044     class vertex_vector : private boost::noncopyable
00045     {
00046         typedef typename T::type value_type;
00047         typedef vertex<value_type,2> vertex_type;
00048         enum block_e {
00049             block_shift = 8,
00050             block_size  = 1<<block_shift,
00051             block_mask  = block_size - 1,
00052             grow_by     = 256
00053         };
00054 
00055     private:
00056         unsigned num_blocks_;
00057         unsigned max_blocks_;
00058         value_type** vertexs_;
00059         unsigned char** commands_;
00060         unsigned pos_;
00061     public:
00062         
00063         vertex_vector() 
00064             : num_blocks_(0),
00065               max_blocks_(0),
00066               vertexs_(0),
00067               commands_(0),
00068               pos_(0) {}
00069 
00070         ~vertex_vector()
00071         {
00072             if ( num_blocks_ )
00073             {
00074                 value_type** vertexs=vertexs_ + num_blocks_ - 1;
00075                 while ( num_blocks_-- )
00076                 {
00077                     delete [] *vertexs;
00078                     --vertexs;
00079                 }
00080                 delete [] vertexs_;
00081             }
00082         }
00083         unsigned size() const 
00084         {
00085             return pos_;
00086         }
00087         
00088         void push_back (value_type x,value_type y,unsigned command)
00089         {
00090             unsigned block = pos_ >> block_shift;
00091             if (block >= num_blocks_)
00092             {
00093                 allocate_block(block);
00094             }
00095             value_type* vertex = vertexs_[block] + ((pos_ & block_mask) << 1);
00096             unsigned char* cmd= commands_[block] + (pos_ & block_mask);
00097             
00098             *cmd = static_cast<unsigned char>(command);
00099             *vertex++ = x;
00100             *vertex   = y;
00101             ++pos_;
00102         }
00103         unsigned get_vertex(unsigned pos,value_type* x,value_type* y) const
00104         {
00105             if (pos >= pos_) return SEG_END;
00106             unsigned block = pos >> block_shift;
00107             const value_type* vertex = vertexs_[block] + (( pos & block_mask) << 1);
00108             *x = (*vertex++);
00109             *y = (*vertex);
00110             return commands_[block] [pos & block_mask];
00111         }
00112                 
00113         void set_capacity(size_t)
00114         {
00115             //do nothing
00116         }
00117         
00118     private:
00119         void allocate_block(unsigned block)
00120         {
00121             if (block >= max_blocks_)
00122             {
00123                 value_type** new_vertexs = new value_type* [(max_blocks_ + grow_by) * 2];
00124                 unsigned char** new_commands = (unsigned char**)(new_vertexs + max_blocks_ + grow_by);
00125                 if (vertexs_)
00126                 {
00127                     std::memcpy(new_vertexs,vertexs_,max_blocks_ * sizeof(value_type*));
00128                     std::memcpy(new_commands,commands_,max_blocks_ * sizeof(unsigned char*));
00129                     delete [] vertexs_;
00130                 }
00131                 vertexs_ = new_vertexs;
00132                 commands_ = new_commands;
00133                 max_blocks_ += grow_by;
00134             }
00135             vertexs_[block] = new value_type [block_size * 2 + block_size / (sizeof(value_type))];
00136             commands_[block] = (unsigned char*)(vertexs_[block] + block_size*2);
00137             ++num_blocks_;
00138         }
00139     };
00140 
00141     template <typename T>
00142     struct vertex_vector2 : boost::noncopyable
00143     {
00144         typedef typename T::type value_type;
00145         typedef boost::tuple<value_type,value_type,char> vertex_type;
00146         typedef typename std::vector<vertex_type>::const_iterator const_iterator;
00147         vertex_vector2() {}
00148         unsigned size() const 
00149         {
00150             return cont_.size();
00151         }
00152 
00153         void push_back (value_type x,value_type y,unsigned command)
00154         {
00155             cont_.push_back(vertex_type(x,y,command));
00156         }
00157         unsigned get_vertex(unsigned pos,value_type* x,value_type* y) const
00158         {
00159             if (pos >= cont_.size()) return SEG_END;
00160             vertex_type const& c = cont_[pos];
00161             *x = boost::get<0>(c);
00162             *y = boost::get<1>(c);
00163             return boost::get<2>(c);
00164         }
00165         
00166         const_iterator begin() const
00167         {
00168             return cont_.begin();
00169         }
00170         
00171         const_iterator end() const
00172         {
00173             return cont_.end();
00174         }
00175 
00176         void set_capacity(size_t size)
00177         {
00178             cont_.reserve(size);
00179         }
00180     private:
00181         std::vector<vertex_type> cont_;
00182     };
00183 }
00184 
00185 #endif //VERTEX_VECTOR_HPP

Generated on Thu Jul 19 17:59:27 2007 for Mapnik by  doxygen 1.4.7