root/trunk/include/mapnik/feature_style_processor.hpp @ 770

Revision 770, 9.7 kB (checked in by artem, 22 months ago)

+ applied patch avoid_extent from rcoup

Line 
1/*****************************************************************************
2 *
3 * This file is part of Mapnik (c++ mapping toolkit)
4 *
5 * Copyright (C) 2006 Artem Pavlenko
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 *
21 *****************************************************************************/
22
23//$Id$
24
25#ifndef FEATURE_STYLE_PROCESSOR_HPP
26#define FEATURE_STYLE_PROCESSOR_HPP
27
28// mapnik
29#include <mapnik/envelope.hpp>
30#include <mapnik/datasource.hpp>
31#include <mapnik/layer.hpp>
32#include <mapnik/map.hpp>
33#include <mapnik/attribute_collector.hpp>
34#include <mapnik/utils.hpp>
35#include <mapnik/projection.hpp>
36#include <mapnik/scale_denominator.hpp>
37// boost
38#include <boost/progress.hpp>
39//stl
40#include <vector>
41
42namespace mapnik
43{       
44   template <typename Processor>
45   class feature_style_processor 
46   {
47         struct symbol_dispatch : public boost::static_visitor<>
48         {
49               symbol_dispatch (Processor & output,
50                                Feature const& f, 
51                                proj_transform const& prj_trans)
52                  : output_(output),
53                    f_(f),
54                    prj_trans_(prj_trans)  {}
55           
56               template <typename T>
57               void operator () (T const& sym) const
58               {
59                  output_.process(sym,f_,prj_trans_);
60               }
61               
62               Processor & output_;
63               Feature const& f_;
64               proj_transform const& prj_trans_;
65         };
66      public:
67         feature_style_processor(Map const& m)
68            : m_(m) {}
69         
70         void apply()
71         {
72#ifdef MAPNIK_DEBUG           
73            boost::progress_timer t(std::clog); 
74#endif         
75            Processor & p = static_cast<Processor&>(*this);
76            p.start_map_processing(m_);
77                       
78            try
79            {
80               projection proj(m_.srs()); // map projection
81               double scale_denom = scale_denominator(m_,proj.is_geographic());
82#ifdef MAPNIK_DEBUG
83               std::clog << "scale denominator = " << scale_denom << "\n";
84#endif
85               std::vector<Layer>::const_iterator itr = m_.layers().begin();
86               std::vector<Layer>::const_iterator end = m_.layers().end();
87           
88               while (itr != end)
89               {
90                  if (itr->isVisible(scale_denom))
91                  {
92                     apply_to_layer(*itr, p, proj, scale_denom);
93                  }
94                  ++itr;
95               }
96            }
97            catch (proj_init_error& ex)
98            {
99               std::clog << "proj_init_error:" << ex.what() << "\n"; 
100            }
101           
102            p.end_map_processing(m_);
103         }     
104      private:
105         void apply_to_layer(Layer const& lay, Processor & p, 
106                             projection const& proj0,double scale_denom)
107         {
108            p.start_layer_processing(lay);
109            boost::shared_ptr<datasource> ds=lay.datasource();
110            if (ds)
111            {
112               Envelope<double> const& ext=m_.getCurrentExtent();
113               Envelope<double> bbox(ext);
114               projection proj1(lay.srs());
115               proj_transform prj_trans(proj0,proj1);
116               
117               if (proj0 != proj1) {
118                  Envelope<double> layer_ext = lay.envelope();
119                  double lx0 = layer_ext.minx();
120                  double ly0 = layer_ext.miny();
121                  double lz0 = 0.0;
122                  double lx1 = layer_ext.maxx();
123                  double ly1 = layer_ext.maxy();
124                  double lz1 = 0.0;
125                  // back project layers extent into main map projection
126                  prj_trans.backward(lx0,ly0,lz0);
127                  prj_trans.backward(lx1,ly1,lz1);
128                  // clip query bbox
129                  lx0 = std::max(ext.minx(),lx0);
130                  ly0 = std::max(ext.miny(),ly0);
131                  lx1 = std::min(ext.maxx(),lx1);
132                  ly1 = std::min(ext.maxy(),ly1);
133
134                  prj_trans.forward(lx0,ly0,lz0);
135                  prj_trans.forward(lx1,ly1,lz1);
136                  bbox = Envelope<double>(lx0,ly0,lx1,ly1);
137               }
138               double resolution = m_.getWidth()/bbox.width();
139               query q(bbox,resolution); //BBOX query
140               
141               std::vector<std::string> const& style_names = lay.styles();
142               std::vector<std::string>::const_iterator stylesIter = style_names.begin();
143               std::vector<std::string>::const_iterator stylesEnd = style_names.end(); 
144               for (;stylesIter != stylesEnd; ++stylesIter)
145               {
146                  std::set<std::string> names;
147                  attribute_collector<Feature> collector(names);
148                  std::vector<rule_type*> if_rules;
149                  std::vector<rule_type*> else_rules;
150                   
151                  bool active_rules=false;
152                 
153                  boost::optional<feature_type_style const&> style=m_.find_style(*stylesIter);
154                  if (!style) continue;
155                 
156                  const std::vector<rule_type>& rules=(*style).get_rules();
157                  std::vector<rule_type>::const_iterator ruleIter=rules.begin();
158                  std::vector<rule_type>::const_iterator ruleEnd=rules.end();
159                                       
160                  for (;ruleIter!=ruleEnd;++ruleIter)
161                  {
162                     if (ruleIter->active(scale_denom))
163                     {
164                        active_rules=true;
165                        ruleIter->accept(collector);
166
167                        if (ruleIter->has_else_filter())
168                        {
169                           else_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
170                        }
171                        else
172                        {
173                           if_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));               
174                        }
175                     }
176                  }
177                  std::set<std::string>::const_iterator namesIter=names.begin();
178                  std::set<std::string>::const_iterator namesEnd =names.end();
179                   
180                  // push all property names
181                  for (;namesIter!=namesEnd;++namesIter)
182                  {
183                     q.add_property_name(*namesIter);
184                  }
185                  if (active_rules)
186                  {
187                     featureset_ptr fs=ds->features(q);
188                     if (fs)
189                     {             
190                        feature_ptr feature;
191                        while ((feature = fs->next()))
192                        {                 
193                           bool do_else=true;               
194                           std::vector<rule_type*>::const_iterator itr=if_rules.begin();
195                           std::vector<rule_type*>::const_iterator end=if_rules.end();
196                           for (;itr != end;++itr)
197                           {
198                              filter_ptr const& filter=(*itr)->get_filter();   
199                              if (filter->pass(*feature))
200                              {   
201                                 do_else=false;
202                                 const symbolizers& symbols = (*itr)->get_symbolizers();
203                                 symbolizers::const_iterator symIter=symbols.begin();
204                                 symbolizers::const_iterator symEnd =symbols.end();
205                                 for (;symIter != symEnd;++symIter)
206                                 {   
207                                    boost::apply_visitor
208                                       (symbol_dispatch(p,*feature,prj_trans),*symIter);
209                                 }
210                              }                     
211                           }
212                           if (do_else)
213                           {
214                              //else filter
215                              std::vector<rule_type*>::const_iterator itr=
216                                 else_rules.begin();
217                              std::vector<rule_type*>::const_iterator end=
218                                 else_rules.end();
219                              for (;itr != end;++itr)
220                              {
221                                 const symbolizers& symbols = (*itr)->get_symbolizers();
222                                 symbolizers::const_iterator symIter= symbols.begin();
223                                 symbolizers::const_iterator symEnd = symbols.end();
224                                       
225                                 for (;symIter!=symEnd;++symIter)
226                                 {
227                                    boost::apply_visitor
228                                       (symbol_dispatch(p,*feature,prj_trans),*symIter);
229                                 }
230                              }
231                           }     
232                        }
233                     }
234                  }
235               }               
236            }
237            p.end_layer_processing(lay);
238         }     
239         Map const& m_;
240   };
241}
242
243#endif //FEATURE_STYLE_PROCESSOR_HPP
Note: See TracBrowser for help on using the browser.