mapnik/include/mapnik/grid/grid.hpp
2013-07-23 16:10:00 -04:00

238 lines
5.5 KiB
C++

/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_GRID_HPP
#define MAPNIK_GRID_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/grid/grid_view.hpp>
#include <mapnik/global.hpp>
#include <mapnik/value.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_factory.hpp>
#include <mapnik/util/conversions.hpp>
// boost
#include <boost/cstdint.hpp>
// stl
#include <map>
#include <set>
#include <cmath>
#include <string>
#include <cassert>
#include <vector>
namespace mapnik
{
template <typename T>
class MAPNIK_DECL hit_grid
{
public:
typedef T value_type;
typedef mapnik::ImageData<value_type> data_type;
typedef std::string lookup_type;
// mapping between pixel id and key
typedef std::map<value_type, lookup_type> feature_key_type;
typedef std::map<lookup_type, mapnik::feature_ptr> feature_type;
static const value_type base_mask;
private:
unsigned width_;
unsigned height_;
std::string key_;
data_type data_;
unsigned int resolution_;
std::string id_name_;
bool painted_;
std::set<std::string> names_;
feature_key_type f_keys_;
feature_type features_;
mapnik::context_ptr ctx_;
public:
hit_grid(int width, int height, std::string const& key, unsigned int resolution);
hit_grid(hit_grid<T> const& rhs);
~hit_grid() {}
void clear();
inline void painted(bool painted)
{
painted_ = painted;
}
inline bool painted() const
{
return painted_;
}
inline std::string const& key_name() const
{
return id_name_;
}
void add_feature(mapnik::feature_impl & feature);
inline void add_property_name(std::string const& name)
{
names_.insert(name);
}
inline std::set<std::string> const& property_names() const
{
return names_;
}
inline feature_type const& get_grid_features() const
{
return features_;
}
inline feature_key_type const& get_feature_keys() const
{
return f_keys_;
}
inline std::string const& get_key() const
{
return key_;
}
inline void set_key(std::string const& key)
{
key_ = key;
}
inline unsigned int get_resolution() const
{
return resolution_;
}
inline void set_resolution(unsigned int res)
{
resolution_ = res;
}
inline data_type const& data() const
{
return data_;
}
inline data_type& data()
{
return data_;
}
inline T const * raw_data() const
{
return data_.getData();
}
inline T* raw_data()
{
return data_.getData();
}
inline value_type const * getRow(unsigned row) const
{
return data_.getRow(row);
}
inline mapnik::grid_view get_view(unsigned x, unsigned y, unsigned w, unsigned h)
{
return mapnik::grid_view(x,y,w,h,
data_,key_,id_name_,resolution_,names_,f_keys_,features_);
}
private:
inline bool checkBounds(unsigned x, unsigned y) const
{
return (x < width_ && y < height_);
}
hit_grid& operator=(const hit_grid&);
public:
inline void setPixel(int x,int y,value_type feature_id)
{
if (checkBounds(x,y))
{
data_(x,y) = feature_id;
}
}
inline unsigned width() const
{
return width_;
}
inline unsigned height() const
{
return height_;
}
inline void set_rectangle(value_type id,image_data_32 const& data,int x0,int y0)
{
box2d<int> ext0(0,0,width_,height_);
box2d<int> ext1(x0,y0,x0+data.width(),y0+data.height());
if (ext0.intersects(ext1))
{
box2d<int> box = ext0.intersect(ext1);
for (int y = box.miny(); y < box.maxy(); ++y)
{
value_type* row_to = data_.getRow(y);
unsigned int const * row_from = data.getRow(y-y0);
for (int x = box.minx(); x < box.maxx(); ++x)
{
unsigned rgba = row_from[x-x0];
#ifdef MAPNIK_BIG_ENDIAN
unsigned a = rgba & 0xff;
#else
unsigned a = (rgba >> 24) & 0xff;
#endif
// if the pixel is more than a tenth
// opaque then burn in the feature id
if (a >= 25)
{
row_to[x] = id;
}
}
}
}
}
};
typedef hit_grid<mapnik::value_integer> grid;
}
#endif //MAPNIK_GRID_HPP