/home/andreas/src/svn/mapnik/include/mapnik/feature_style_processor.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 
00023 //$Id$
00024 
00025 #ifndef FEATURE_STYLE_PROCESSOR_HPP
00026 #define FEATURE_STYLE_PROCESSOR_HPP
00027 
00028 //stl
00029 #include <vector>
00030 // boost
00031 #include <boost/progress.hpp>
00032 // mapnik
00033 #include <mapnik/envelope.hpp>
00034 #include <mapnik/datasource.hpp>
00035 #include <mapnik/layer.hpp>
00036 #include <mapnik/map.hpp>
00037 #include <mapnik/attribute_collector.hpp>
00038 #include <mapnik/utils.hpp>
00039 #include <mapnik/projection.hpp>
00040 #include <mapnik/scale_denominator.hpp>
00041 
00042 namespace mapnik
00043 {       
00044    template <typename Processor>
00045    class feature_style_processor 
00046    {
00047          struct symbol_dispatch : public boost::static_visitor<>
00048          {
00049                symbol_dispatch (Processor & output,
00050                                 Feature const& f, 
00051                                 proj_transform const& prj_trans)
00052                   : output_(output),
00053                     f_(f),
00054                     prj_trans_(prj_trans)  {}
00055             
00056                template <typename T>
00057                void operator () (T const& sym) const
00058                {
00059                   output_.process(sym,f_,prj_trans_);
00060                }
00061             
00062                Processor & output_;
00063                Feature const& f_;
00064                proj_transform const& prj_trans_;
00065          };
00066       public:
00067          feature_style_processor(Map const& m)
00068             : m_(m) {}
00069         
00070          void apply()
00071          {
00072 #ifdef MAPNIK_DEBUG           
00073             boost::progress_timer t(std::clog);  
00074 #endif          
00075             Processor & p = static_cast<Processor&>(*this);
00076             p.start_map_processing(m_);
00077                        
00078             try
00079             {
00080                projection proj(m_.srs()); // map projection
00081                double scale_denom = scale_denominator(m_,proj.is_geographic());
00082 #ifdef MAPNIK_DEBUG
00083                std::clog << "scale denominator = " << scale_denom << "\n";
00084 #endif
00085                std::vector<Layer>::const_iterator itr = m_.layers().begin();
00086                std::vector<Layer>::const_iterator end = m_.layers().end();
00087             
00088                while (itr != end)
00089                {
00090                   if (itr->isVisible(scale_denom))
00091                   {
00092                      apply_to_layer(*itr, p, proj, scale_denom);
00093                   }
00094                   ++itr;
00095                }
00096             }
00097             catch (proj_init_error& ex)
00098             {
00099                std::clog << ex.what() << "\n"; 
00100             }
00101 
00102             p.end_map_processing(m_);
00103          }      
00104       private:
00105          void apply_to_layer(Layer const& lay, Processor & p, 
00106                              projection const& proj0,double scale_denom)
00107          {
00108             p.start_layer_processing(lay);
00109             boost::shared_ptr<datasource> ds=lay.datasource();
00110             if (ds)
00111             {
00112                Envelope<double> const& ext=m_.getCurrentExtent();
00113               
00114                projection proj1(lay.srs());
00115                proj_transform prj_trans(proj0,proj1);
00116                 
00117                double x0 = ext.minx();
00118                double y0 = ext.miny();
00119                double z0 = 0.0;
00120                double x1 = ext.maxx();
00121                double y1 = ext.maxy();
00122                double z1 = 0.0;
00123                prj_trans.forward(x0,y0,z0);
00124                prj_trans.forward(x1,y1,z1);
00125                Envelope<double> bbox(x0,y0,x1,y1);
00126 #ifdef MAPNIK_DEBUG
00127                std::clog << bbox << "\n";
00128 #endif                
00129                std::vector<std::string> const& style_names = lay.styles();
00130                std::vector<std::string>::const_iterator stylesIter = style_names.begin();
00131                std::vector<std::string>::const_iterator stylesEnd = style_names.end();
00132                 
00133                while (stylesIter != stylesEnd)
00134                {
00135                   std::set<std::string> names;
00136                   attribute_collector<Feature> collector(names);
00137                   std::vector<rule_type*> if_rules;
00138                   std::vector<rule_type*> else_rules;
00139                     
00140                   bool active_rules=false;
00141                     
00142                   feature_type_style const& style=m_.find_style(*stylesIter++);
00143                         
00144                   query q(bbox); //BBOX query
00145 
00146                   const std::vector<rule_type>& rules=style.get_rules();
00147                   std::vector<rule_type>::const_iterator ruleIter=rules.begin();
00148                   std::vector<rule_type>::const_iterator ruleEnd=rules.end();
00149                                         
00150                   while (ruleIter!=ruleEnd)
00151                   {
00152                      if (ruleIter->active(scale_denom))
00153                      {
00154                         active_rules=true;
00155                         ruleIter->accept(collector);
00156 
00157                         if (ruleIter->has_else_filter())
00158                         {
00159                            else_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
00160                         }
00161                         else
00162                         {
00163                            if_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));                
00164                         }
00165                      }
00166                      ++ruleIter;
00167                   }
00168                   std::set<std::string>::const_iterator namesIter=names.begin();
00169                   std::set<std::string>::const_iterator namesEnd =names.end();
00170                     
00171                   // push all property names
00172                   while (namesIter!=namesEnd)
00173                   {
00174                      q.add_property_name(*namesIter);
00175                      ++namesIter;
00176                   }
00177                   if (active_rules)
00178                   {
00179                      featureset_ptr fs=ds->features(q);
00180                      if (fs)
00181                      {              
00182                         feature_ptr feature;
00183                         while ((feature = fs->next()))
00184                         {                  
00185                            bool do_else=true;               
00186                            std::vector<rule_type*>::const_iterator itr=if_rules.begin();
00187                            std::vector<rule_type*>::const_iterator end=if_rules.end();
00188                            while (itr != end)
00189                            {
00190                               filter_ptr const& filter=(*itr)->get_filter();    
00191                               if (filter->pass(*feature))
00192                               {   
00193                                  do_else=false;
00194                                  const symbolizers& symbols = (*itr)->get_symbolizers();
00195                                  symbolizers::const_iterator symIter=symbols.begin();
00196                                  symbolizers::const_iterator symEnd =symbols.end();
00197                                  while (symIter != symEnd)
00198                                  {   
00199                                     boost::apply_visitor
00200                                        (symbol_dispatch(p,*feature,prj_trans),*symIter++);
00201                                  }
00202                               }                     
00203                               ++itr;
00204                            }
00205                            if (do_else)
00206                            {
00207                               //else filter
00208                               std::vector<rule_type*>::const_iterator itr=
00209                                  else_rules.begin();
00210                               std::vector<rule_type*>::const_iterator end=
00211                                  else_rules.end();
00212                               while (itr != end)
00213                               {
00214                                  const symbolizers& symbols = (*itr)->get_symbolizers();
00215                                  symbolizers::const_iterator symIter= symbols.begin();
00216                                  symbolizers::const_iterator symEnd = symbols.end();
00217                                         
00218                                  while (symIter!=symEnd)
00219                                  {
00220                                     boost::apply_visitor
00221                                        (symbol_dispatch(p,*feature,prj_trans),
00222                                         *symIter++);
00223                                  }
00224                                  ++itr;
00225                               }
00226                            }      
00227                         }
00228                      }
00229                   }
00230                }
00231                 
00232             }
00233             p.end_layer_processing(lay);
00234          }      
00235          Map const& m_;
00236    };
00237 }
00238 
00239 #endif //FEATURE_STYLE_PROCESSOR_HPP

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