1. Changed internal geometry representation (explicit support for multi geometries)

(FIXME : label_spacing is still, too slow!!) 
2. Re-use some agg objects.
3. placement_finder cleanups! 
4. Added support for 'building_symbolizer' - extruded polygons
This commit is contained in:
Artem Pavlenko 2007-09-16 11:23:51 +00:00
parent d38dedad68
commit 8e071f84c7
36 changed files with 1534 additions and 1292 deletions

View file

@ -52,10 +52,11 @@ opts.Add(PathOption('GIGABASE_LIBS', 'Search path for Gigabase library files', '
opts.Add(PathOption('PYTHON','Python executable', sys.executable)) opts.Add(PathOption('PYTHON','Python executable', sys.executable))
opts.Add(ListOption('INPUT_PLUGINS','Input drivers to include','all',['postgis','shape','raster','gdal','gigabase'])) opts.Add(ListOption('INPUT_PLUGINS','Input drivers to include','all',['postgis','shape','raster','gdal','gigabase']))
opts.Add(ListOption('BINDINGS','Language bindings to build','all',['python'])) opts.Add(ListOption('BINDINGS','Language bindings to build','all',['python']))
opts.Add('DEBUG', 'Compile a debug version of mapnik', '') opts.Add(BoolOption('DEBUG', 'Compile a debug version of mapnik', 'False'))
opts.Add('DESTDIR', 'The root directory to install into. Useful mainly for binary package building', '/') opts.Add('DESTDIR', 'The root directory to install into. Useful mainly for binary package building', '/')
opts.Add('BIDI', 'BIDI support', '') opts.Add(BoolOption('BIDI', 'BIDI support', 'False'))
opts.Add(EnumOption('THREADING','Set threading support','multi', ['multi','single'])) opts.Add(EnumOption('THREADING','Set threading support','multi', ['multi','single']))
opts.Add(EnumOption('XMLPARSER','Set xml parser ','tinyxml', ['tinyxml','spirit']))
env = Environment(ENV=os.environ, options=opts) env = Environment(ENV=os.environ, options=opts)
@ -99,9 +100,12 @@ if env['BIDI']:
if env['FRIBIDI_INCLUDES'] not in env['CPPPATH']: if env['FRIBIDI_INCLUDES'] not in env['CPPPATH']:
env['CPPPATH'].append(env['FRIBIDI_INCLUDES']) env['CPPPATH'].append(env['FRIBIDI_INCLUDES'])
if env['FRIBIDI_LIBS'] not in env['LIBPATH']: if env['FRIBIDI_LIBS'] not in env['LIBPATH']:
env['CPPPATH'].append(env['FRIBIDI_LIBS']) env['LIBPATH'].append(env['FRIBIDI_LIBS'])
env['LIBS'].append('fribidi') env['LIBS'].append('fribidi')
if env['XMLPARSER'] == 'tinyxml':
env.Append(CXXFLAGS = '-DBOOST_PROPERTY_TREE_XML_PARSER_TINYXML -DTIXML_USE_STL')
C_LIBSHEADERS = [ C_LIBSHEADERS = [
['m', 'math.h', True], ['m', 'math.h', True],
['ltdl', 'ltdl.h', True], ['ltdl', 'ltdl.h', True],
@ -122,7 +126,7 @@ if env['BIDI'] : C_LIBSHEADERS.append(['fribidi','fribidi/fribidi.h',True])
BOOST_LIBSHEADERS = [ BOOST_LIBSHEADERS = [
['thread', 'boost/thread/mutex.hpp', True], ['thread', 'boost/thread/mutex.hpp', True],
# ['system', 'boost/system/system_error.hpp', True], # uncomment this on Darwin + boost_1_35 ['system', 'boost/system/system_error.hpp', True], # uncomment this on Darwin + boost_1_35
['filesystem', 'boost/filesystem/operations.hpp', True], ['filesystem', 'boost/filesystem/operations.hpp', True],
['regex', 'boost/regex.hpp', True], ['regex', 'boost/regex.hpp', True],
['program_options', 'boost/program_options.hpp', False] ['program_options', 'boost/program_options.hpp', False]
@ -221,9 +225,9 @@ if env['PLATFORM'] == 'Darwin': pthread = ''
else: pthread = '-pthread' else: pthread = '-pthread'
if env['DEBUG']: if env['DEBUG']:
env.Append(CXXFLAGS = '-ansi -Wall %s -ftemplate-depth-100 -O0 -fno-inline -g -DDEBUG -DMAPNIK_DEBUG -D%s -DBOOST_PROPERTY_TREE_XML_PARSER_TINYXML -DTIXML_USE_STL' % (pthread, env['PLATFORM'].upper())) env.Append(CXXFLAGS = '-ansi -Wall %s -ftemplate-depth-100 -O0 -fno-inline -g -DDEBUG -DMAPNIK_DEBUG -D%s ' % (pthread, env['PLATFORM'].upper()))
else: else:
env.Append(CXXFLAGS = '-ansi -Wall %s -ftemplate-depth-100 -O3 -finline-functions -Wno-inline -DNDEBUG -D%s -DBOOST_PROPERTY_TREE_XML_PARSER_TINYXML -DTIXML_USE_STL' % (pthread,env['PLATFORM'].upper())) env.Append(CXXFLAGS = '-ansi -Wall %s -ftemplate-depth-100 -O2 -finline-functions -Wno-inline -DNDEBUG -D%s' % (pthread,env['PLATFORM'].upper()))
# Install some free default fonts # Install some free default fonts

View file

@ -33,10 +33,10 @@
// Provides faster access for massive pixel operations, // Provides faster access for massive pixel operations,
// such as blur, image filtering: // such as blur, image filtering:
// #define AGG_RENDERING_BUFFER row_ptr_cache<int8u> #define AGG_RENDERING_BUFFER row_ptr_cache<int8u>
// //
// Provides cheaper creation and destruction (no mem allocs): // Provides cheaper creation and destruction (no mem allocs):
#define AGG_RENDERING_BUFFER row_accessor<int8u> // #define AGG_RENDERING_BUFFER row_accessor<int8u>
// //
// You can still use both of them simultaneouslyin your applications // You can still use both of them simultaneouslyin your applications
// This #define is used only for default rendering_buffer type, // This #define is used only for default rendering_buffer type,

View file

@ -290,8 +290,8 @@ namespace agg
#ifdef AGG_RENDERING_BUFFER #ifdef AGG_RENDERING_BUFFER
typedef AGG_RENDERING_BUFFER rendering_buffer; typedef AGG_RENDERING_BUFFER rendering_buffer;
#else #else
// typedef row_ptr_cache<int8u> rendering_buffer; typedef row_ptr_cache<int8u> rendering_buffer;
typedef row_accessor<int8u> rendering_buffer; //typedef row_accessor<int8u> rendering_buffer;
#endif #endif
} }

View file

@ -53,10 +53,10 @@ class _Envelope(Envelope,_injector):
(self.minx,self.miny,self.maxx,self.maxy) (self.minx,self.miny,self.maxx,self.maxy)
class _Projection(Projection,_injector): class _Projection(Projection,_injector):
def forward(self,pt): def forward(self,obj):
return forward_(pt,self) return forward_(obj,self)
def inverse(self,pt): def inverse(self,obj):
return inverse_(pt,self) return inverse_(obj,self)
class _Datasource(Datasource,_injector): class _Datasource(Datasource,_injector):
def describe(self): def describe(self):

View file

@ -26,7 +26,7 @@
#include <mapnik/projection.hpp> #include <mapnik/projection.hpp>
namespace { namespace {
mapnik::coord2d forward(mapnik::coord2d const& pt, mapnik::coord2d forward_pt(mapnik::coord2d const& pt,
mapnik::projection const& prj) mapnik::projection const& prj)
{ {
double x = pt.x; double x = pt.x;
@ -35,7 +35,7 @@ namespace {
return mapnik::coord2d(x,y); return mapnik::coord2d(x,y);
} }
mapnik::coord2d inverse(mapnik::coord2d const& pt, mapnik::coord2d inverse_pt(mapnik::coord2d const& pt,
mapnik::projection const& prj) mapnik::projection const& prj)
{ {
double x = pt.x; double x = pt.x;
@ -44,6 +44,30 @@ namespace {
return mapnik::coord2d(x,y); return mapnik::coord2d(x,y);
} }
mapnik::Envelope<double> forward_env(mapnik::Envelope<double> const & box,
mapnik::projection const& prj)
{
double minx = box.minx();
double miny = box.miny();
double maxx = box.maxx();
double maxy = box.maxy();
prj.forward(minx,miny);
prj.forward(maxx,maxy);
return mapnik::Envelope<double>(minx,miny,maxx,maxy);
}
mapnik::Envelope<double> inverse_env(mapnik::Envelope<double> const & box,
mapnik::projection const& prj)
{
double minx = box.minx();
double miny = box.miny();
double maxx = box.maxx();
double maxy = box.maxy();
prj.inverse(minx,miny);
prj.inverse(maxx,maxy);
return mapnik::Envelope<double>(minx,miny,maxx,maxy);
}
} }
void export_projection () void export_projection ()
@ -57,7 +81,9 @@ void export_projection ()
.add_property ("geographic",&projection::is_geographic) .add_property ("geographic",&projection::is_geographic)
; ;
def("forward_",&forward); def("forward_",&forward_pt);
def("inverse_",&inverse); def("inverse_",&inverse_pt);
def("forward_",&forward_env);
def("inverse_",&inverse_env);
} }

View file

@ -171,10 +171,10 @@ void MapWidget::mousePressEvent(QMouseEvent* e)
} }
} }
geometry_ptr geom = feat->get_geometry(); if (feat->num_geometries() > 0)
if (geom)
{ {
(*feat)["mapnik:geometry"] = geom->type(); mapnik::geometry2d & geom = feat->get_geometry(0);
(*feat)["mapnik:geometry"] = geom.type();
data->push(feat); data->push(feat);
} }
} }

View file

@ -163,7 +163,7 @@ struct symbolizer_icon : public boost::static_visitor<QIcon>
{ {
QPixmap pix(16,16); QPixmap pix(16,16);
QPainter painter(&pix); QPainter painter(&pix);
mapnik::Color fill = sym.get_fill(); mapnik::Color const& fill = sym.get_fill();
QBrush brush(QColor(fill.red(),fill.green(),fill.blue(),fill.alpha())); QBrush brush(QColor(fill.red(),fill.green(),fill.blue(),fill.alpha()));
painter.fillRect(0, 0, 16, 16, brush); painter.fillRect(0, 0, 16, 16, brush);
return QIcon(pix); return QIcon(pix);
@ -180,6 +180,21 @@ struct symbolizer_icon : public boost::static_visitor<QIcon>
} }
return QIcon(); return QIcon();
} }
QIcon operator() (mapnik::line_symbolizer const& sym) const
{
QPixmap pix(48,16);
pix.fill();
QPainter painter(&pix);
mapnik::stroke const& strk = sym.get_stroke();
mapnik::Color const& col = strk.get_color();
QPen pen(QColor(col.red(),col.green(),col.blue(),col.alpha()));
pen.setWidth(strk.get_width());
painter.setPen(pen);
painter.drawLine(0,7,47,7);
//painter.drawLine(7,15,12,0);
//painter.drawLine(12,0,8,15);
return QIcon(pix);
}
template <typename T> template <typename T>
QIcon operator() (T const& ) const QIcon operator() (T const& ) const

View file

@ -7,10 +7,10 @@ TEMPLATE = app
INCLUDEPATH += /usr/local/include INCLUDEPATH += /usr/local/include
INCLUDEPATH += /opt/boost_1_35/include/boost-1_35 INCLUDEPATH += /opt/boost_1_35/include/boost-1_35
INCLUDEPATH += /usr/local/include/freetype2 INCLUDEPATH += /usr/local/include/freetype2
INCLUDEPATH += /Users/artem/projects/mapnik/agg/include
INCLUDEPATH += . INCLUDEPATH += .
QMAKE_CXXFLAGS +=' -DDARWIN'
unix:LIBS = -L/usr/local/lib -lmapnik -lfreetype unix:LIBS = -L/usr/local/lib -lmapnik -lfreetype
# Input # Input

View file

@ -35,6 +35,10 @@
#include <mapnik/label_collision_detector.hpp> #include <mapnik/label_collision_detector.hpp>
#include <mapnik/placement_finder.hpp> #include <mapnik/placement_finder.hpp>
#include <mapnik/map.hpp> #include <mapnik/map.hpp>
// agg
#include "agg_rendering_buffer.h"
#include "agg_pixfmt_rgba.h"
#include "agg_rasterizer_scanline_aa.h"
namespace mapnik { namespace mapnik {
template <typename T> template <typename T>
@ -71,12 +75,20 @@ namespace mapnik {
void process(text_symbolizer const& sym, void process(text_symbolizer const& sym,
Feature const& feature, Feature const& feature,
proj_transform const& prj_trans); proj_transform const& prj_trans);
void process(building_symbolizer const& sym,
Feature const& feature,
proj_transform const& prj_trans);
private: private:
T & pixmap_; T & pixmap_;
unsigned width_;
unsigned height_;
agg::row_ptr_cache<agg::int8u> buf_;
agg::pixfmt_rgba32 pixf_;
CoordTransform t_; CoordTransform t_;
face_manager<freetype_engine> font_manager_; face_manager<freetype_engine> font_manager_;
label_collision_detector4 detector_; label_collision_detector4 detector_;
placement_finder<label_collision_detector4> finder_; placement_finder<label_collision_detector4> finder_;
agg::rasterizer_scanline_aa<> ras_;
}; };
} }

View file

@ -30,111 +30,147 @@
#include <mapnik/proj_transform.hpp> #include <mapnik/proj_transform.hpp>
namespace mapnik { namespace mapnik {
typedef coord_array<coord2d> CoordinateArray; typedef coord_array<coord2d> CoordinateArray;
template <typename Transform,typename Geometry> template <typename Transform,typename Geometry>
struct MAPNIK_DECL coord_transform struct MAPNIK_DECL coord_transform
{ {
coord_transform(Transform const& t, Geometry& geom) coord_transform(Transform const& t, Geometry& geom)
: t_(t), geom_(geom) {} : t_(t), geom_(geom) {}
unsigned vertex(double *x , double *y) const unsigned vertex(double *x , double *y) const
{ {
unsigned command = geom_.vertex(x,y); unsigned command = geom_.vertex(x,y);
t_.forward(x,y); t_.forward(x,y);
return command; return command;
} }
void rewind (unsigned pos) void rewind (unsigned pos)
{ {
geom_.rewind(pos); geom_.rewind(pos);
} }
private: private:
Transform const& t_; Transform const& t_;
Geometry& geom_; Geometry& geom_;
}; };
template <typename Transform,typename Geometry> template <typename Transform,typename Geometry>
struct MAPNIK_DECL coord_transform2 struct MAPNIK_DECL coord_transform2
{ {
coord_transform2(Transform const& t, coord_transform2(Transform const& t,
Geometry& geom, Geometry const& geom,
proj_transform const& prj_trans) proj_transform const& prj_trans)
: t_(t), : t_(t),
geom_(geom), geom_(geom),
prj_trans_(prj_trans) {} prj_trans_(prj_trans) {}
unsigned vertex(double * x , double * y) const unsigned vertex(double * x , double * y) const
{ {
unsigned command = geom_.vertex(x,y); unsigned command = geom_.vertex(x,y);
double z=0; double z=0;
prj_trans_.backward(*x,*y,z); prj_trans_.backward(*x,*y,z);
t_.forward(x,y); t_.forward(x,y);
return command; return command;
} }
void rewind (unsigned pos) void rewind (unsigned pos)
{ {
geom_.rewind(pos); geom_.rewind(pos);
} }
private: private:
Transform const& t_; Transform const& t_;
Geometry& geom_; Geometry const& geom_;
proj_transform const& prj_trans_; proj_transform const& prj_trans_;
}; };
template <typename Transform,typename Geometry>
struct MAPNIK_DECL coord_transform3
{
coord_transform3(Transform const& t,
Geometry const& geom,
proj_transform const& prj_trans,
int dx, int dy)
: t_(t),
geom_(geom),
prj_trans_(prj_trans),
dx_(dx), dy_(dy) {}
class CoordTransform unsigned vertex(double * x , double * y) const
{ {
private: unsigned command = geom_.vertex(x,y);
int width; double z=0;
int height; prj_trans_.backward(*x,*y,z);
double scale_; t_.forward(x,y);
Envelope<double> extent_; *x+=dx_;
double offset_x_,offset_y_; *y+=dy_;
public: return command;
CoordTransform(int width,int height,const Envelope<double>& extent, }
double offset_x = 0, double offset_y = 0)
void rewind (unsigned pos)
{
geom_.rewind(pos);
}
private:
Transform const& t_;
Geometry const& geom_;
proj_transform const& prj_trans_;
int dx_;
int dy_;
};
class CoordTransform
{
private:
int width;
int height;
double scale_;
Envelope<double> extent_;
double offset_x_;
double offset_y_;
public:
CoordTransform(int width,int height,const Envelope<double>& extent,
double offset_x = 0, double offset_y = 0)
:width(width),height(height),extent_(extent),offset_x_(offset_x),offset_y_(offset_y) :width(width),height(height),extent_(extent),offset_x_(offset_x),offset_y_(offset_y)
{ {
double sx=((double)width)/extent_.width(); double sx=((double)width)/extent_.width();
double sy=((double)height)/extent_.height(); double sy=((double)height)/extent_.height();
scale_=std::min(sx,sy); scale_=std::min(sx,sy);
} }
inline double scale() const inline double scale() const
{ {
return scale_; return scale_;
} }
inline void forward(double * x, double * y) const inline void forward(double * x, double * y) const
{ {
*x = (*x - extent_.minx()) * scale_ - offset_x_; *x = (*x - extent_.minx()) * scale_ - offset_x_;
*y = (extent_.maxy() - *y) * scale_ - offset_y_; *y = (extent_.maxy() - *y) * scale_ - offset_y_;
} }
inline void backward(double * x, double * y) const inline void backward(double * x, double * y) const
{ {
*x = extent_.minx() + (*x + offset_x_)/scale_; *x = extent_.minx() + (*x + offset_x_)/scale_;
*y = extent_.maxy() - (*y + offset_y_)/scale_; *y = extent_.maxy() - (*y + offset_y_)/scale_;
} }
inline coord2d& forward(coord2d& c) const inline coord2d& forward(coord2d& c) const
{ {
forward(&c.x,&c.y); forward(&c.x,&c.y);
return c; return c;
} }
inline coord2d& backward(coord2d& c) const inline coord2d& backward(coord2d& c) const
{ {
backward(&c.x,&c.y); backward(&c.x,&c.y);
return c; return c;
} }
inline Envelope<double> forward(const Envelope<double>& e) const inline Envelope<double> forward(const Envelope<double>& e) const
{ {
double x0 = e.minx(); double x0 = e.minx();
double y0 = e.miny(); double y0 = e.miny();
double x1 = e.maxx(); double x1 = e.maxx();
@ -142,10 +178,10 @@ namespace mapnik {
forward(&x0,&y0); forward(&x0,&y0);
forward(&x1,&y1); forward(&x1,&y1);
return Envelope<double>(x0,y0,x1,y1); return Envelope<double>(x0,y0,x1,y1);
} }
inline Envelope<double> backward(const Envelope<double>& e) const inline Envelope<double> backward(const Envelope<double>& e) const
{ {
double x0 = e.minx(); double x0 = e.minx();
double y0 = e.miny(); double y0 = e.miny();
double x1 = e.maxx(); double x1 = e.maxx();
@ -153,26 +189,26 @@ namespace mapnik {
backward(&x0,&y0); backward(&x0,&y0);
backward(&x1,&y1); backward(&x1,&y1);
return Envelope<double>(x0,y0,x1,y1); return Envelope<double>(x0,y0,x1,y1);
} }
inline CoordinateArray& forward(CoordinateArray& coords) const inline CoordinateArray& forward(CoordinateArray& coords) const
{ {
for (unsigned i=0;i<coords.size();++i) for (unsigned i=0;i<coords.size();++i)
{ {
forward(coords[i]); forward(coords[i]);
} }
return coords; return coords;
} }
inline CoordinateArray& backward(CoordinateArray& coords) const inline CoordinateArray& backward(CoordinateArray& coords) const
{ {
for (unsigned i=0;i<coords.size();++i) for (unsigned i=0;i<coords.size();++i)
{ {
backward(coords[i]); backward(coords[i]);
} }
return coords; return coords;
} }
}; };
} }
#endif //CTRANS_HPP #endif //CTRANS_HPP

View file

@ -36,100 +36,111 @@
#include <mapnik/raster.hpp> #include <mapnik/raster.hpp>
namespace mapnik { namespace mapnik {
typedef boost::shared_ptr<raster> raster_ptr; typedef boost::shared_ptr<raster> raster_ptr;
typedef boost::associative_property_map< typedef boost::associative_property_map<
std::map<std::string,value std::map<std::string,value
> > properties; > > properties;
template <typename T1,typename T2> template <typename T1,typename T2>
struct feature : public properties, struct feature : public properties,
private boost::noncopyable private boost::noncopyable
{ {
public: public:
typedef T1 geometry_type; typedef T1 geometry_type;
typedef T2 raster_type; typedef T2 raster_type;
typedef std::map<std::string,value>::value_type value_type; typedef std::map<std::string,value>::value_type value_type;
typedef std::map<std::string,value>::size_type size_type; typedef std::map<std::string,value>::size_type size_type;
private: private:
int id_; int id_;
geometry_type geom_; boost::ptr_vector<geometry_type> geom_cont_;
raster_type raster_; raster_type raster_;
std::map<std::string,value> props_; std::map<std::string,value> props_;
public: public:
typedef std::map<std::string,value>::iterator iterator; typedef std::map<std::string,value>::iterator iterator;
explicit feature(int id) explicit feature(int id)
: properties(props_), : properties(props_),
id_(id), id_(id),
geom_(), geom_cont_(),
raster_() {} raster_() {}
feature(int id,const geometry_type& geom) //feature(int id,const geometry_type& geom)
: properties(props_), // : properties(props_),
id_(id), // id_(id),
geom_(geom), // geom_(geom),
raster_() {} // raster_() {}
int id() const int id() const
{ {
return id_; return id_;
} }
void set_geometry(geometry_type& geom) void add_geometry(geometry_type * geom)
{ {
geom_=geom; geom_cont_.push_back(geom);
} }
geometry_type const& get_geometry() const unsigned num_geometries() const
{ {
return geom_; return geom_cont_.size();
} }
const raster_type& get_raster() const geometry_type const& get_geometry(unsigned index) const
{ {
return geom_cont_[index];
}
geometry_type& get_geometry(unsigned index)
{
return geom_cont_[index];
}
const raster_type& get_raster() const
{
return raster_; return raster_;
} }
void set_raster(raster_type const& raster)
{ void set_raster(raster_type const& raster)
{
raster_=raster; raster_=raster;
} }
std::map<std::string,value> const& props() const std::map<std::string,value> const& props() const
{ {
return props_; return props_;
} }
iterator begin() const iterator begin() const
{ {
return props_.begin(); return props_.begin();
} }
iterator end() const iterator end() const
{ {
return props_.end(); return props_.end();
} }
std::string to_string() const std::string to_string() const
{ {
std::stringstream ss; std::stringstream ss;
ss << "feature (" << std::endl; ss << "feature (" << std::endl;
for (std::map<std::string,value>::const_iterator itr=props_.begin(); for (std::map<std::string,value>::const_iterator itr=props_.begin();
itr != props_.end();++itr) itr != props_.end();++itr)
{ {
ss << " " << itr->first << ":" << itr->second << std::endl; ss << " " << itr->first << ":" << itr->second << std::endl;
} }
ss << ")" << std::endl; ss << ")" << std::endl;
return ss.str(); return ss.str();
} }
}; };
typedef feature<geometry_ptr,raster_ptr> Feature; typedef feature<geometry2d,raster_ptr> Feature;
inline std::ostream& operator<< (std::ostream & out,Feature const& f) inline std::ostream& operator<< (std::ostream & out,Feature const& f)
{ {
out << f.to_string(); out << f.to_string();
return out; return out;
} }
} }
#endif //FEATURE_HPP #endif //FEATURE_HPP

View file

@ -29,6 +29,7 @@
// boost // boost
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
// mapnik // mapnik
#include <mapnik/vertex_vector.hpp> #include <mapnik/vertex_vector.hpp>
#include <mapnik/ctrans.hpp> #include <mapnik/ctrans.hpp>
@ -76,8 +77,8 @@ namespace mapnik {
virtual void move_to(value_type x,value_type y)=0; virtual void move_to(value_type x,value_type y)=0;
virtual void line_to(value_type x,value_type y)=0; virtual void line_to(value_type x,value_type y)=0;
virtual unsigned num_points() const = 0; virtual unsigned num_points() const = 0;
virtual unsigned vertex(double* x, double* y)=0; virtual unsigned vertex(double* x, double* y) const=0;
virtual void rewind(unsigned )=0; virtual void rewind(unsigned) const=0;
virtual void set_capacity(size_t size)=0; virtual void set_capacity(size_t size)=0;
virtual ~geometry() {} virtual ~geometry() {}
}; };
@ -117,14 +118,14 @@ namespace mapnik {
return 1; return 1;
} }
unsigned vertex(double* x, double* y) unsigned vertex(double* x, double* y) const
{ {
*x = pt_.x; *x = pt_.x;
*y = pt_.y; *y = pt_.y;
return SEG_LINETO; return SEG_LINETO;
} }
void rewind(unsigned ) {} void rewind(unsigned ) const {}
bool hit_test(value_type x,value_type y, double tol) const bool hit_test(value_type x,value_type y, double tol) const
{ {
@ -209,12 +210,12 @@ namespace mapnik {
return cont_.size(); return cont_.size();
} }
unsigned vertex(double* x, double* y) unsigned vertex(double* x, double* y) const
{ {
return cont_.get_vertex(itr_++,x,y); return cont_.get_vertex(itr_++,x,y);
} }
void rewind(unsigned ) void rewind(unsigned ) const
{ {
itr_=0; itr_=0;
} }
@ -318,12 +319,12 @@ namespace mapnik {
return cont_.size(); return cont_.size();
} }
unsigned vertex(double* x, double* y) unsigned vertex(double* x, double* y) const
{ {
return cont_.get_vertex(itr_++,x,y); return cont_.get_vertex(itr_++,x,y);
} }
void rewind(unsigned ) void rewind(unsigned ) const
{ {
itr_=0; itr_=0;
} }
@ -344,8 +345,9 @@ namespace mapnik {
typedef line_string<vertex2d,vertex_vector2> line_string_impl; typedef line_string<vertex2d,vertex_vector2> line_string_impl;
typedef polygon<vertex2d,vertex_vector2> polygon_impl; typedef polygon<vertex2d,vertex_vector2> polygon_impl;
typedef geometry<vertex2d> geometry_type; typedef geometry<vertex2d> geometry2d;
typedef boost::shared_ptr<geometry_type> geometry_ptr; typedef boost::shared_ptr<geometry2d> geometry_ptr;
typedef boost::ptr_vector<geometry2d> geometry_containter;
} }
#endif //GEOMETRY_HPP #endif //GEOMETRY_HPP

View file

@ -38,10 +38,13 @@ namespace mapnik {
bool pass(Feature const& feature) bool pass(Feature const& feature)
{ {
geometry_ptr geom = feature.get_geometry(); for (unsigned i=0;i<feature.num_geometries();++i)
if (geom && geom->hit_test(x_,y_,tol_)) {
return true; geometry2d const& geom = feature.get_geometry(i);
return false; if (geom.hit_test(x_,y_,tol_))
return true;
}
return false;
} }
private: private:

View file

@ -41,6 +41,7 @@ namespace mapnik {
feature_ptr next() feature_ptr next()
{ {
/*
while (pos_ != end_) while (pos_ != end_)
{ {
geometry_ptr geom = (*pos_)->get_geometry(); geometry_ptr geom = (*pos_)->get_geometry();
@ -50,6 +51,7 @@ namespace mapnik {
} }
++pos_; ++pos_;
} }
*/
return feature_ptr(); return feature_ptr();
} }

View file

@ -36,25 +36,18 @@
namespace mapnik namespace mapnik
{ {
typedef text_path placement_element;
struct placement_element struct placement : boost::noncopyable
{ {
double starting_x; typedef coord_transform2<CoordTransform,geometry2d> path_type;
double starting_y;
text_path path;
};
struct placement
{
typedef coord_transform2<CoordTransform,geometry_type> path_type;
template <typename SymbolizerT> template <typename SymbolizerT>
placement(string_info *info_, placement(string_info *info_,
CoordTransform *ctrans_, CoordTransform *ctrans_,
const proj_transform *proj_trans_, const proj_transform *proj_trans_,
geometry_ptr geom_, geometry2d const& geom_,
SymbolizerT sym); SymbolizerT const& sym);
~placement(); ~placement();
@ -69,7 +62,7 @@ namespace mapnik
CoordTransform *ctrans; CoordTransform *ctrans;
const proj_transform *proj_trans; const proj_transform *proj_trans;
geometry_ptr geom; geometry2d const& geom;
path_type shape_path; path_type shape_path;
double total_distance_; //cache for distance double total_distance_; //cache for distance
@ -80,10 +73,7 @@ namespace mapnik
std::queue< Envelope<double> > envelopes; std::queue< Envelope<double> > envelopes;
//output //output
std::vector<placement_element> placements; boost::ptr_vector<placement_element> placements;
// caching output
placement_element current_placement;
int wrap_width; int wrap_width;
int text_ratio; int text_ratio;

View file

@ -59,6 +59,37 @@ namespace mapnik
Color fill_; Color fill_;
float opacity_; float opacity_;
}; };
struct MAPNIK_DECL building_symbolizer
{
explicit building_symbolizer()
: fill_(Color(128,128,128)),
opacity_(1.0) {}
building_symbolizer(Color const& fill)
: fill_(fill),
opacity_(1.0) {}
Color const& get_fill() const
{
return fill_;
}
void set_fill(Color const& fill)
{
fill_ = fill;
}
void set_opacity(float opacity)
{
opacity_ = opacity;
}
float get_opacity() const
{
return opacity_;
}
private:
Color fill_;
float opacity_;
};
} }
#endif // POLYGON_SYMBOLIZER_HPP #endif // POLYGON_SYMBOLIZER_HPP

View file

@ -88,6 +88,12 @@ namespace mapnik
return (&lhs == &rhs); return (&lhs == &rhs);
} }
inline bool operator==(building_symbolizer const& lhs,
building_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
typedef boost::variant<point_symbolizer, typedef boost::variant<point_symbolizer,
line_symbolizer, line_symbolizer,
line_pattern_symbolizer, line_pattern_symbolizer,
@ -95,7 +101,8 @@ namespace mapnik
polygon_pattern_symbolizer, polygon_pattern_symbolizer,
raster_symbolizer, raster_symbolizer,
shield_symbolizer, shield_symbolizer,
text_symbolizer> symbolizer; text_symbolizer,
building_symbolizer> symbolizer;
typedef std::vector<symbolizer> symbolizers; typedef std::vector<symbolizer> symbolizers;

View file

@ -30,131 +30,134 @@
namespace mapnik namespace mapnik
{ {
struct character_info struct character_info
{ {
int character; int character;
double width, height; double width, height;
character_info() : character(0), width(0), height(0) {} character_info() : character(0), width(0), height(0) {}
character_info(int c_, double width_, double height_) : character(c_), width(width_), height(height_) {} character_info(int c_, double width_, double height_) : character(c_), width(width_), height(height_) {}
~character_info() {} ~character_info() {}
character_info(const character_info &ci) character_info(const character_info &ci)
: character(ci.character), width(ci.width), height(ci.height) : character(ci.character), width(ci.width), height(ci.height)
{ {
} }
}; };
class string_info : private boost::noncopyable class string_info : private boost::noncopyable
{ {
protected: protected:
typedef boost::ptr_vector<character_info> characters_t;
std::wstring string_;
characters_t characters_;
double width_;
double height_;
public:
string_info(std::wstring string)
: string_(string),
width_(0),
height_(0) {}
typedef boost::ptr_vector<character_info> characters_t; void add_info(int c, double width, double height)
{
characters_.push_back(new character_info(c, width, height));
}
std::wstring string_; unsigned num_characters()
characters_t characters_; {
return characters_.size();
}
double width_; character_info at(unsigned i)
double height_; {
public: return characters_[i];
string_info(std::wstring string) }
: string_(string),
width_(0),
height_(0) {}
void add_info(int c, double width, double height) character_info operator[](unsigned i)
{ {
characters_.push_back(new character_info(c, width, height)); return at(i);
} }
unsigned num_characters() void set_dimensions(double width, double height)
{ {
return characters_.size(); width_ = width;
} height_ = height;
}
character_info at(unsigned i) std::pair<double, double> get_dimensions()
{ {
return characters_[i]; return std::pair<double, double>(width_, height_);
} }
character_info operator[](unsigned i) std::wstring get_string() {
{ return string_;
return at(i); }
} };
void set_dimensions(double width, double height) struct text_path : boost::noncopyable
{ {
width_ = width; struct character_node
height_ = height; {
} int c;
double x, y, angle;
std::pair<double, double> get_dimensions() character_node(int c_, double x_, double y_, double angle_)
{ : c(c_), x(x_), y(y_), angle(angle_) {}
return std::pair<double, double>(width_, height_); ~character_node() {}
}
std::wstring get_string() { void vertex(int *c_, double *x_, double *y_, double *angle_)
return string_; {
} *c_ = c;
}; *x_ = x;
*y_ = y;
*angle_ = angle;
}
};
struct text_path typedef std::vector<character_node> character_nodes_t;
{ double starting_x;
struct character_node double starting_y;
{ character_nodes_t nodes_;
int c; int itr_;
double x, y, angle;
character_node(int c_, double x_, double y_, double angle_) : c(c_), x(x_), y(y_), angle(angle_) {} std::pair<unsigned,unsigned> string_dimensions;
~character_node() {}
void vertex(int *c_, double *x_, double *y_, double *angle_) text_path()
{ : starting_x(0),
*c_ = c; starting_y(0),
*x_ = x; itr_(0) {}
*y_ = y;
*angle_ = angle;
}
};
typedef std::vector<character_node> character_nodes_t; //text_path(text_path const& other) :
// itr_(0),
// nodes_(other.nodes_),
// string_dimensions(other.string_dimensions)
//{}
character_nodes_t nodes_; ~text_path() {}
int itr_;
std::pair<unsigned,unsigned> string_dimensions; void add_node(int c, double x, double y, double angle)
{
text_path() : itr_(0) {}
text_path(const text_path & other) : itr_(0)
{
nodes_ = other.nodes_;
string_dimensions = other.string_dimensions;
}
~text_path() {}
void add_node(int c, double x, double y, double angle)
{
nodes_.push_back(character_node(c, x, y, angle)); nodes_.push_back(character_node(c, x, y, angle));
} }
void vertex(int *c, double *x, double *y, double *angle) void vertex(int *c, double *x, double *y, double *angle)
{ {
nodes_[itr_++].vertex(c, x, y, angle); nodes_[itr_++].vertex(c, x, y, angle);
} }
int num_nodes() int num_nodes()
{ {
return nodes_.size(); return nodes_.size();
} }
void clear() void clear()
{ {
nodes_.clear(); nodes_.clear();
} }
}; };
} }
#endif #endif

View file

@ -27,17 +27,17 @@
#include <mapnik/geometry.hpp> #include <mapnik/geometry.hpp>
#include <mapnik/ctrans.hpp> #include <mapnik/ctrans.hpp>
#include <mapnik/feature.hpp>
namespace mapnik namespace mapnik
{ {
class MAPNIK_DECL geometry_utils class MAPNIK_DECL geometry_utils
{ {
public: public:
static geometry_ptr from_wkb(const char* wkb, unsigned size); static void from_wkb(Feature & feature,const char* wkb, unsigned size);
private: private:
geometry_utils(); geometry_utils();
geometry_utils(geometry_utils const&); geometry_utils(geometry_utils const&);
geometry_utils& operator=(const geometry_utils&); geometry_utils& operator=(const geometry_utils&);
}; };
} }
#endif //WKB_HPP #endif //WKB_HPP

View file

@ -34,6 +34,8 @@ gdal_src = Split(
libraries = ['gdal' ] libraries = ['gdal' ]
if env['PLATFORM'] == 'Darwin': if env['PLATFORM'] == 'Darwin':
libraries.append('mapnik') libraries.append('mapnik')
libraries.append('iconv')
if env['BIDI'] : libraries.append('fribidi')
gdal_inputdriver = env.SharedLibrary('gdal', source=gdal_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries) gdal_inputdriver = env.SharedLibrary('gdal', source=gdal_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries)

View file

@ -33,7 +33,7 @@ using boost::bad_lexical_cast;
using boost::trim; using boost::trim;
using std::string; using std::string;
using mapnik::Feature; using mapnik::Feature;
using mapnik::geometry_ptr; using mapnik::geometry2d;
using mapnik::byte; using mapnik::byte;
using mapnik::geometry_utils; using mapnik::geometry_utils;
@ -53,58 +53,53 @@ feature_ptr postgis_featureset::next()
feature_ptr feature(new Feature(count_)); feature_ptr feature(new Feature(count_));
int size=rs_->getFieldLength(0); int size=rs_->getFieldLength(0);
const char *data = rs_->getValue(0); const char *data = rs_->getValue(0);
geometry_ptr geom = geometry_utils::from_wkb(data,size); geometry_utils::from_wkb(*feature,data,size);
totalGeomSize_+=size; totalGeomSize_+=size;
if (geom) for (unsigned pos=1;pos<num_attrs_+1;++pos)
{ {
feature->set_geometry(geom); std::string name = rs_->getFieldName(pos);
const char* buf=rs_->getValue(pos);
int oid = rs_->getTypeOID(pos);
for (unsigned pos=1;pos<num_attrs_+1;++pos) if (oid==23) //int4
{ {
std::string name = rs_->getFieldName(pos); int val = int4net(buf);
const char* buf=rs_->getValue(pos); boost::put(*feature,name,val);
int oid = rs_->getTypeOID(pos); }
else if (oid==21) //int2
if (oid==23) //int4 {
{ int val = int2net(buf);
int val = int4net(buf); boost::put(*feature,name,val);
boost::put(*feature,name,val); }
} else if (oid == 700) // float4
else if (oid==21) //int2 {
{ float val;
int val = int2net(buf); float4net(val,buf);
boost::put(*feature,name,val); boost::put(*feature,name,val);
} }
else if (oid == 700) // float4 else if (oid == 701) // float8
{ {
float val; double val;
float4net(val,buf); float8net(val,buf);
boost::put(*feature,name,val); boost::put(*feature,name,val);
} }
else if (oid == 701) // float8 else if (oid==25 || oid==1042 || oid==1043) // text or bpchar or varchar
{ {
double val; std::string str(buf);
float8net(val,buf); trim(str);
boost::put(*feature,name,val); std::wstring wstr = tr_->transcode(str);
} boost::put(*feature,name,wstr);
else if (oid==25 || oid==1042 || oid==1043) // text or bpchar or varchar }
{ else
std::string str(buf); {
trim(str);
std::wstring wstr = tr_->transcode(str);
boost::put(*feature,name,wstr);
}
else
{
#ifdef MAPNIK_DEBUG #ifdef MAPNIK_DEBUG
std::clog << "uknown OID = " << oid << " FIXME \n"; std::clog << "uknown OID = " << oid << " FIXME \n";
#endif #endif
//boost::put(*feature,name,0); //boost::put(*feature,name,0);
} }
}
++count_;
} }
++count_;
return feature; return feature;
} }
else else

View file

@ -35,6 +35,7 @@ raster_src = Split(
libraries = [] libraries = []
if env['PLATFORM'] == 'Darwin': if env['PLATFORM'] == 'Darwin':
libraries.append('mapnik') libraries.append('mapnik')
if env['BIDI'] : libraries.append('fribidi')
raster_inputdriver = env.SharedLibrary('raster', source=raster_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries) raster_inputdriver = env.SharedLibrary('raster', source=raster_src, SHLIBPREFIX='', SHLIBSUFFIX='.input', LIBS=libraries)

View file

@ -41,6 +41,8 @@ libraries = []
if env['PLATFORM'] == 'Darwin': if env['PLATFORM'] == 'Darwin':
libraries.append('mapnik') libraries.append('mapnik')
libraries.append('iconv') libraries.append('iconv')
if env['BIDI'] : libraries.append('fribidi')
shape_inputdriver = env.SharedLibrary('shape', SHLIBSUFFIX='.input', source=shape_src, SHLIBPREFIX='', LIBS = libraries) shape_inputdriver = env.SharedLibrary('shape', SHLIBSUFFIX='.input', source=shape_src, SHLIBPREFIX='', LIBS = libraries)

View file

@ -40,8 +40,8 @@ using mapnik::attribute_descriptor;
shape_datasource::shape_datasource(const parameters &params) shape_datasource::shape_datasource(const parameters &params)
: datasource (params), : datasource (params),
shape_name_(*params_.get<std::string>("file","")),
type_(datasource::Vector), type_(datasource::Vector),
shape_name_(*params_.get<std::string>("file","")),
file_length_(0), file_length_(0),
indexed_(false), indexed_(false),
desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8")) desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8"))

View file

@ -1,3 +1,4 @@
/***************************************************************************** /*****************************************************************************
* *
* This file is part of Mapnik (c++ mapping toolkit) * This file is part of Mapnik (c++ mapping toolkit)
@ -59,7 +60,7 @@ template <typename filterT>
feature_ptr shape_featureset<filterT>::next() feature_ptr shape_featureset<filterT>::next()
{ {
using mapnik::point_impl; using mapnik::point_impl;
std::streampos pos=shape_.shp().pos(); std::streampos pos=shape_.shp().pos();
if (pos < std::streampos(file_length_ * 2)) if (pos < std::streampos(file_length_ * 2))
@ -71,9 +72,9 @@ feature_ptr shape_featureset<filterT>::next()
{ {
double x=shape_.shp().read_double(); double x=shape_.shp().read_double();
double y=shape_.shp().read_double(); double y=shape_.shp().read_double();
geometry_ptr point(new point_impl); geometry2d * point = new point_impl;
point->move_to(x,y); point->move_to(x,y);
feature->set_geometry(point); feature->add_geometry(point);
++count_; ++count_;
} }
else if (type == shape_io::shape_pointm) else if (type == shape_io::shape_pointm)
@ -81,9 +82,9 @@ feature_ptr shape_featureset<filterT>::next()
double x=shape_.shp().read_double(); double x=shape_.shp().read_double();
double y=shape_.shp().read_double(); double y=shape_.shp().read_double();
shape_.shp().read_double();//m shape_.shp().read_double();//m
geometry_ptr point(new point_impl); geometry2d * point = new point_impl;
point->move_to(x,y); point->move_to(x,y);
feature->set_geometry(point); feature->add_geometry(point);
++count_; ++count_;
} }
else if (type == shape_io::shape_pointz) else if (type == shape_io::shape_pointz)
@ -92,9 +93,9 @@ feature_ptr shape_featureset<filterT>::next()
double y=shape_.shp().read_double(); double y=shape_.shp().read_double();
shape_.shp().read_double();//z shape_.shp().read_double();//z
shape_.shp().read_double();//m shape_.shp().read_double();//m
geometry_ptr point(new point_impl); geometry2d * point=new point_impl;
point->move_to(x,y); point->move_to(x,y);
feature->set_geometry(point); feature->add_geometry(point);
++count_; ++count_;
} }
else else
@ -119,43 +120,43 @@ feature_ptr shape_featureset<filterT>::next()
case shape_io::shape_polyline: case shape_io::shape_polyline:
{ {
geometry_ptr line = shape_.read_polyline(); geometry2d * line = shape_.read_polyline();
feature->set_geometry(line); feature->add_geometry(line);
++count_; ++count_;
break; break;
} }
case shape_io::shape_polylinem: case shape_io::shape_polylinem:
{ {
geometry_ptr line = shape_.read_polylinem(); geometry2d * line = shape_.read_polylinem();
feature->set_geometry(line); feature->add_geometry(line);
++count_; ++count_;
break; break;
} }
case shape_io::shape_polylinez: case shape_io::shape_polylinez:
{ {
geometry_ptr line = shape_.read_polylinez(); geometry2d * line = shape_.read_polylinez();
feature->set_geometry(line); feature->add_geometry(line);
++count_; ++count_;
break; break;
} }
case shape_io::shape_polygon: case shape_io::shape_polygon:
{ {
geometry_ptr poly = shape_.read_polygon(); geometry2d * poly = shape_.read_polygon();
feature->set_geometry(poly); feature->add_geometry(poly);
++count_; ++count_;
break; break;
} }
case shape_io::shape_polygonm: case shape_io::shape_polygonm:
{ {
geometry_ptr poly = shape_.read_polygonm(); geometry2d * poly = shape_.read_polygonm();
feature->set_geometry(poly); feature->add_geometry(poly);
++count_; ++count_;
break; break;
} }
case shape_io::shape_polygonz: case shape_io::shape_polygonz:
{ {
geometry_ptr poly = shape_.read_polygonz(); geometry2d * poly = shape_.read_polygonz();
feature->set_geometry(poly); feature->add_geometry(poly);
++count_; ++count_;
break; break;
} }

View file

@ -85,9 +85,9 @@ feature_ptr shape_index_featureset<filterT>::next()
{ {
double x=shape_.shp().read_double(); double x=shape_.shp().read_double();
double y=shape_.shp().read_double(); double y=shape_.shp().read_double();
geometry_ptr point(new point_impl); geometry2d * point = new point_impl;
point->move_to(x,y); point->move_to(x,y);
feature->set_geometry(point); feature->add_geometry(point);
++count_; ++count_;
} }
else if (type == shape_io::shape_pointm) else if (type == shape_io::shape_pointm)
@ -95,9 +95,9 @@ feature_ptr shape_index_featureset<filterT>::next()
double x=shape_.shp().read_double(); double x=shape_.shp().read_double();
double y=shape_.shp().read_double(); double y=shape_.shp().read_double();
shape_.shp().read_double();// m shape_.shp().read_double();// m
geometry_ptr point(new point_impl); geometry2d * point = new point_impl;
point->move_to(x,y); point->move_to(x,y);
feature->set_geometry(point); feature->add_geometry(point);
++count_; ++count_;
} }
else if (type == shape_io::shape_pointz) else if (type == shape_io::shape_pointz)
@ -106,9 +106,9 @@ feature_ptr shape_index_featureset<filterT>::next()
double y=shape_.shp().read_double(); double y=shape_.shp().read_double();
shape_.shp().read_double();// z shape_.shp().read_double();// z
shape_.shp().read_double();// m shape_.shp().read_double();// m
geometry_ptr point(new point_impl); geometry2d * point = new point_impl;
point->move_to(x,y); point->move_to(x,y);
feature->set_geometry(point); feature->add_geometry(point);
++count_; ++count_;
} }
else else
@ -122,49 +122,49 @@ feature_ptr shape_index_featureset<filterT>::next()
switch (type) switch (type)
{ {
case shape_io::shape_polyline: case shape_io::shape_polyline:
{ {
geometry_ptr line = shape_.read_polyline(); geometry2d * line = shape_.read_polyline();
feature->set_geometry(line); feature->add_geometry(line);
++count_; ++count_;
break; break;
} }
case shape_io::shape_polylinem: case shape_io::shape_polylinem:
{ {
geometry_ptr line = shape_.read_polylinem(); geometry2d * line = shape_.read_polylinem();
feature->set_geometry(line); feature->add_geometry(line);
++count_; ++count_;
break; break;
} }
case shape_io::shape_polylinez: case shape_io::shape_polylinez:
{ {
geometry_ptr line = shape_.read_polylinez(); geometry2d * line = shape_.read_polylinez();
feature->set_geometry(line); feature->add_geometry(line);
++count_; ++count_;
break; break;
} }
case shape_io::shape_polygon: case shape_io::shape_polygon:
{ {
geometry_ptr poly = shape_.read_polygon(); geometry2d * poly = shape_.read_polygon();
feature->set_geometry(poly); feature->add_geometry(poly);
++count_;
break;
}
case shape_io::shape_polygonm:
{
geometry2d * poly = shape_.read_polygonm();
feature->add_geometry(poly);
++count_; ++count_;
break; break;
} }
case shape_io::shape_polygonm: case shape_io::shape_polygonz:
{ {
geometry_ptr poly = shape_.read_polygonm(); geometry2d * poly = shape_.read_polygonz();
feature->set_geometry(poly); feature->add_geometry(poly);
++count_; ++count_;
break; break;
} }
case shape_io::shape_polygonz:
{
geometry_ptr poly = shape_.read_polygonz();
feature->set_geometry(poly);
++count_;
break;
}
} }
} }
if (attr_ids_.size()) if (attr_ids_.size())

View file

@ -31,395 +31,395 @@ const std::string shape_io::SHP = ".shp";
const std::string shape_io::DBF = ".dbf"; const std::string shape_io::DBF = ".dbf";
shape_io::shape_io(const std::string& shape_name) shape_io::shape_io(const std::string& shape_name)
: type_(shape_null), : type_(shape_null),
reclength_(0), reclength_(0),
id_(0) id_(0)
{ {
bool ok = (shp_.open(shape_name + SHP) && bool ok = (shp_.open(shape_name + SHP) &&
dbf_.open(shape_name + DBF)); dbf_.open(shape_name + DBF));
if (!ok) if (!ok)
{ {
throw datasource_exception("cannot read shape file"); throw datasource_exception("cannot read shape file");
} }
} }
shape_io::~shape_io() shape_io::~shape_io()
{ {
shp_.close(); shp_.close();
dbf_.close(); dbf_.close();
} }
void shape_io::move_to (int pos) void shape_io::move_to (int pos)
{ {
shp_.seek(pos); shp_.seek(pos);
id_ = shp_.read_xdr_integer(); id_ = shp_.read_xdr_integer();
reclength_ = shp_.read_xdr_integer(); reclength_ = shp_.read_xdr_integer();
type_ = shp_.read_ndr_integer(); type_ = shp_.read_ndr_integer();
if (type_ != shape_point && type_ != shape_pointm && type_ != shape_pointz) if (type_ != shape_point && type_ != shape_pointm && type_ != shape_pointz)
{ {
shp_.read_envelope(cur_extent_); shp_.read_envelope(cur_extent_);
} }
} }
int shape_io::type() const int shape_io::type() const
{ {
return type_; return type_;
} }
const Envelope<double>& shape_io::current_extent() const const Envelope<double>& shape_io::current_extent() const
{ {
return cur_extent_; return cur_extent_;
} }
shape_file& shape_io::shp() shape_file& shape_io::shp()
{ {
return shp_; return shp_;
} }
shape_file& shape_io::shx() shape_file& shape_io::shx()
{ {
return shx_; return shx_;
} }
dbf_file& shape_io::dbf() dbf_file& shape_io::dbf()
{ {
return dbf_; return dbf_;
} }
geometry_ptr shape_io::read_polyline() geometry2d * shape_io::read_polyline()
{ {
using mapnik::line_string_impl; using mapnik::line_string_impl;
shape_record record(reclength_*2-36); shape_record record(reclength_*2-36);
shp_.read_record(record); shp_.read_record(record);
int num_parts=record.read_ndr_integer(); int num_parts=record.read_ndr_integer();
int num_points=record.read_ndr_integer(); int num_points=record.read_ndr_integer();
geometry_ptr line(new line_string_impl); geometry2d * line = new line_string_impl;
line->set_capacity(num_points + num_parts); line->set_capacity(num_points + num_parts);
if (num_parts == 1) if (num_parts == 1)
{ {
line->set_capacity(num_points + 1); line->set_capacity(num_points + 1);
record.skip(4); record.skip(4);
double x=record.read_double(); double x=record.read_double();
double y=record.read_double(); double y=record.read_double();
line->move_to(x,y); line->move_to(x,y);
for (int i=1;i<num_points;++i) for (int i=1;i<num_points;++i)
{ {
x=record.read_double(); x=record.read_double();
y=record.read_double(); y=record.read_double();
line->line_to(x,y); line->line_to(x,y);
} }
} }
else else
{ {
std::vector<int> parts(num_parts); std::vector<int> parts(num_parts);
for (int i=0;i<num_parts;++i) for (int i=0;i<num_parts;++i)
{ {
parts[i]=record.read_ndr_integer(); parts[i]=record.read_ndr_integer();
} }
int start,end; int start,end;
for (int k=0;k<num_parts;++k) for (int k=0;k<num_parts;++k)
{ {
start=parts[k]; start=parts[k];
if (k==num_parts-1) if (k==num_parts-1)
end=num_points;
else
end=parts[k+1];
double x=record.read_double();
double y=record.read_double();
line->move_to(x,y);
for (int j=start+1;j<end;++j)
{
x=record.read_double();
y=record.read_double();
line->line_to(x,y);
}
}
}
return line;
}
geometry_ptr shape_io::read_polylinem()
{
using mapnik::line_string_impl;
shape_record record(reclength_*2-36);
shp_.read_record(record);
int num_parts=record.read_ndr_integer();
int num_points=record.read_ndr_integer();
geometry_ptr line(new line_string_impl);
line->set_capacity(num_points + num_parts);
if (num_parts == 1)
{
record.skip(4);
double x=record.read_double();
double y=record.read_double();
line->move_to(x,y);
for (int i=1;i<num_points;++i)
{
x=record.read_double();
y=record.read_double();
line->line_to(x,y);
}
}
else
{
std::vector<int> parts(num_parts);
for (int i=0;i<num_parts;++i)
{
parts[i]=record.read_ndr_integer();
}
int start,end;
for (int k=0;k<num_parts;++k)
{
start=parts[k];
if (k==num_parts-1)
end=num_points;
else
end=parts[k+1];
double x=record.read_double();
double y=record.read_double();
line->move_to(x,y);
for (int j=start+1;j<end;++j)
{
x=record.read_double();
y=record.read_double();
line->line_to(x,y);
}
}
}
// m-range
//double m0=record.read_double();
//double m1=record.read_double();
//for (int i=0;i<num_points;++i)
//{
// double m=record.read_double();
//}
return line;
}
geometry_ptr shape_io::read_polylinez()
{
using mapnik::line_string_impl;
shape_record record(reclength_*2-36);
shp_.read_record(record);
int num_parts=record.read_ndr_integer();
int num_points=record.read_ndr_integer();
geometry_ptr line(new line_string_impl);
line->set_capacity(num_points + num_parts);
if (num_parts == 1)
{
record.skip(4);
double x=record.read_double();
double y=record.read_double();
line->move_to(x,y);
for (int i=1;i<num_points;++i)
{
x=record.read_double();
y=record.read_double();
line->line_to(x,y);
}
}
else
{
std::vector<int> parts(num_parts);
for (int i=0;i<num_parts;++i)
{
parts[i]=record.read_ndr_integer();
}
int start,end;
for (int k=0;k<num_parts;++k)
{
start=parts[k];
if (k==num_parts-1)
end=num_points;
else
end=parts[k+1];
double x=record.read_double();
double y=record.read_double();
line->move_to(x,y);
for (int j=start+1;j<end;++j)
{
x=record.read_double();
y=record.read_double();
line->line_to(x,y);
}
}
}
// z-range
//double z0=record.read_double();
//double z1=record.read_double();
//for (int i=0;i<num_points;++i)
// {
// double z=record.read_double();
// }
// m-range
//double m0=record.read_double();
//double m1=record.read_double();
//for (int i=0;i<num_points;++i)
//{
// double m=record.read_double();
//}
return line;
}
geometry_ptr shape_io::read_polygon()
{
using mapnik::polygon_impl;
shape_record record(reclength_*2-36);
shp_.read_record(record);
int num_parts=record.read_ndr_integer();
int num_points=record.read_ndr_integer();
std::vector<int> parts(num_parts);
geometry_ptr poly(new polygon_impl);
poly->set_capacity(num_points + num_parts);
for (int i=0;i<num_parts;++i)
{
parts[i]=record.read_ndr_integer();
}
for (int k=0;k<num_parts;k++)
{
int start=parts[k];
int end;
if (k==num_parts-1)
{
end=num_points; end=num_points;
} else
else
{
end=parts[k+1]; end=parts[k+1];
}
double x=record.read_double();
double y=record.read_double();
poly->move_to(x,y);
for (int j=start+1;j<end;j++) double x=record.read_double();
{ double y=record.read_double();
x=record.read_double(); line->move_to(x,y);
y=record.read_double();
poly->line_to(x,y); for (int j=start+1;j<end;++j)
} {
} x=record.read_double();
return poly; y=record.read_double();
line->line_to(x,y);
}
}
}
return line;
} }
geometry_ptr shape_io::read_polygonm() geometry2d * shape_io::read_polylinem()
{ {
using mapnik::polygon_impl; using mapnik::line_string_impl;
shape_record record(reclength_*2-36); shape_record record(reclength_*2-36);
shp_.read_record(record); shp_.read_record(record);
int num_parts=record.read_ndr_integer(); int num_parts=record.read_ndr_integer();
int num_points=record.read_ndr_integer(); int num_points=record.read_ndr_integer();
std::vector<int> parts(num_parts); geometry2d * line = new line_string_impl;
geometry_ptr poly(new polygon_impl); line->set_capacity(num_points + num_parts);
poly->set_capacity(num_points + num_parts); if (num_parts == 1)
for (int i=0;i<num_parts;++i) {
{ record.skip(4);
parts[i]=record.read_ndr_integer(); double x=record.read_double();
} double y=record.read_double();
line->move_to(x,y);
for (int i=1;i<num_points;++i)
{
x=record.read_double();
y=record.read_double();
line->line_to(x,y);
}
}
else
{
std::vector<int> parts(num_parts);
for (int i=0;i<num_parts;++i)
{
parts[i]=record.read_ndr_integer();
}
for (int k=0;k<num_parts;k++) int start,end;
{ for (int k=0;k<num_parts;++k)
int start=parts[k]; {
int end; start=parts[k];
if (k==num_parts-1) if (k==num_parts-1)
{
end=num_points; end=num_points;
} else
else
{
end=parts[k+1]; end=parts[k+1];
}
double x=record.read_double();
double y=record.read_double();
poly->move_to(x,y);
for (int j=start+1;j<end;j++) double x=record.read_double();
{ double y=record.read_double();
x=record.read_double(); line->move_to(x,y);
y=record.read_double();
poly->line_to(x,y);
}
}
// m-range
//double m0=record.read_double();
//double m1=record.read_double();
//for (int i=0;i<num_points;++i) for (int j=start+1;j<end;++j)
//{ {
// double m=record.read_double(); x=record.read_double();
//} y=record.read_double();
return poly; line->line_to(x,y);
}
}
}
// m-range
//double m0=record.read_double();
//double m1=record.read_double();
//for (int i=0;i<num_points;++i)
//{
// double m=record.read_double();
//}
return line;
} }
geometry_ptr shape_io::read_polygonz() geometry2d * shape_io::read_polylinez()
{ {
using mapnik::polygon_impl; using mapnik::line_string_impl;
shape_record record(reclength_*2-36); shape_record record(reclength_*2-36);
shp_.read_record(record); shp_.read_record(record);
int num_parts=record.read_ndr_integer(); int num_parts=record.read_ndr_integer();
int num_points=record.read_ndr_integer(); int num_points=record.read_ndr_integer();
std::vector<int> parts(num_parts); geometry2d * line = new line_string_impl;
geometry_ptr poly(new polygon_impl); line->set_capacity(num_points + num_parts);
poly->set_capacity(num_points + num_parts); if (num_parts == 1)
for (int i=0;i<num_parts;++i) {
{ record.skip(4);
parts[i]=record.read_ndr_integer(); double x=record.read_double();
} double y=record.read_double();
line->move_to(x,y);
for (int i=1;i<num_points;++i)
{
x=record.read_double();
y=record.read_double();
line->line_to(x,y);
}
}
else
{
std::vector<int> parts(num_parts);
for (int i=0;i<num_parts;++i)
{
parts[i]=record.read_ndr_integer();
}
for (int k=0;k<num_parts;k++) int start,end;
{ for (int k=0;k<num_parts;++k)
int start=parts[k]; {
int end; start=parts[k];
if (k==num_parts-1) if (k==num_parts-1)
{
end=num_points; end=num_points;
} else
else
{
end=parts[k+1]; end=parts[k+1];
}
double x=record.read_double();
double y=record.read_double();
poly->move_to(x,y);
for (int j=start+1;j<end;j++) double x=record.read_double();
{ double y=record.read_double();
x=record.read_double(); line->move_to(x,y);
y=record.read_double();
poly->line_to(x,y);
}
}
// z-range
//double z0=record.read_double();
//double z1=record.read_double();
//for (int i=0;i<num_points;++i)
//{
// double z=record.read_double();
//}
// m-range for (int j=start+1;j<end;++j)
//double m0=record.read_double(); {
//double m1=record.read_double(); x=record.read_double();
y=record.read_double();
line->line_to(x,y);
}
}
}
// z-range
//double z0=record.read_double();
//double z1=record.read_double();
//for (int i=0;i<num_points;++i)
// {
// double z=record.read_double();
// }
//for (int i=0;i<num_points;++i) // m-range
//{ //double m0=record.read_double();
// double m=record.read_double(); //double m1=record.read_double();
//}
return poly; //for (int i=0;i<num_points;++i)
//{
// double m=record.read_double();
//}
return line;
}
geometry2d * shape_io::read_polygon()
{
using mapnik::polygon_impl;
shape_record record(reclength_*2-36);
shp_.read_record(record);
int num_parts=record.read_ndr_integer();
int num_points=record.read_ndr_integer();
std::vector<int> parts(num_parts);
geometry2d * poly = new polygon_impl;
poly->set_capacity(num_points + num_parts);
for (int i=0;i<num_parts;++i)
{
parts[i]=record.read_ndr_integer();
}
for (int k=0;k<num_parts;k++)
{
int start=parts[k];
int end;
if (k==num_parts-1)
{
end=num_points;
}
else
{
end=parts[k+1];
}
double x=record.read_double();
double y=record.read_double();
poly->move_to(x,y);
for (int j=start+1;j<end;j++)
{
x=record.read_double();
y=record.read_double();
poly->line_to(x,y);
}
}
return poly;
}
geometry2d * shape_io::read_polygonm()
{
using mapnik::polygon_impl;
shape_record record(reclength_*2-36);
shp_.read_record(record);
int num_parts=record.read_ndr_integer();
int num_points=record.read_ndr_integer();
std::vector<int> parts(num_parts);
geometry2d * poly = new polygon_impl;
poly->set_capacity(num_points + num_parts);
for (int i=0;i<num_parts;++i)
{
parts[i]=record.read_ndr_integer();
}
for (int k=0;k<num_parts;k++)
{
int start=parts[k];
int end;
if (k==num_parts-1)
{
end=num_points;
}
else
{
end=parts[k+1];
}
double x=record.read_double();
double y=record.read_double();
poly->move_to(x,y);
for (int j=start+1;j<end;j++)
{
x=record.read_double();
y=record.read_double();
poly->line_to(x,y);
}
}
// m-range
//double m0=record.read_double();
//double m1=record.read_double();
//for (int i=0;i<num_points;++i)
//{
// double m=record.read_double();
//}
return poly;
}
geometry2d * shape_io::read_polygonz()
{
using mapnik::polygon_impl;
shape_record record(reclength_*2-36);
shp_.read_record(record);
int num_parts=record.read_ndr_integer();
int num_points=record.read_ndr_integer();
std::vector<int> parts(num_parts);
geometry2d * poly=new polygon_impl;
poly->set_capacity(num_points + num_parts);
for (int i=0;i<num_parts;++i)
{
parts[i]=record.read_ndr_integer();
}
for (int k=0;k<num_parts;k++)
{
int start=parts[k];
int end;
if (k==num_parts-1)
{
end=num_points;
}
else
{
end=parts[k+1];
}
double x=record.read_double();
double y=record.read_double();
poly->move_to(x,y);
for (int j=start+1;j<end;j++)
{
x=record.read_double();
y=record.read_double();
poly->line_to(x,y);
}
}
// z-range
//double z0=record.read_double();
//double z1=record.read_double();
//for (int i=0;i<num_points;++i)
//{
// double z=record.read_double();
//}
// m-range
//double m0=record.read_double();
//double m1=record.read_double();
//for (int i=0;i<num_points;++i)
//{
// double m=record.read_double();
//}
return poly;
} }

View file

@ -27,7 +27,7 @@
#include "shapefile.hpp" #include "shapefile.hpp"
#include "shp_index.hpp" #include "shp_index.hpp"
using mapnik::geometry_ptr; using mapnik::geometry2d;
struct shape_io struct shape_io
{ {
@ -62,25 +62,24 @@ public:
shape_multipatch = 31 shape_multipatch = 31
}; };
shape_io(const std::string& shape_name); shape_io(const std::string& shape_name);
~shape_io(); ~shape_io();
shape_file& shp(); shape_file& shp();
shape_file& shx(); shape_file& shx();
dbf_file& dbf(); dbf_file& dbf();
void move_to(int id); void move_to(int id);
int type() const; int type() const;
const Envelope<double>& current_extent() const; const Envelope<double>& current_extent() const;
geometry2d * read_polyline();
geometry_ptr read_polyline(); geometry2d * read_polylinem();
geometry_ptr read_polylinem(); geometry2d * read_polylinez();
geometry_ptr read_polylinez(); geometry2d * read_polygon();
geometry_ptr read_polygon(); geometry2d * read_polygonm();
geometry_ptr read_polygonm(); geometry2d * read_polygonz();
geometry_ptr read_polygonz(); private:
private: //void read_record(const shape_record& record);
//void read_record(const shape_record& record); // no copying
// no copying shape_io(const shape_io&);
shape_io(const shape_io&); shape_io& operator=(const shape_io&);
shape_io& operator=(const shape_io&);
}; };
#endif //SHAPE_IO_HH #endif //SHAPE_IO_HH

View file

@ -25,14 +25,16 @@
#include <iostream> #include <iostream>
// boost // boost
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/tuple/tuple.hpp>
// agg // agg
#include "agg_basics.h" #include "agg_basics.h"
#include "agg_rendering_buffer.h" //#include "agg_rendering_buffer.h"
#include "agg_rasterizer_scanline_aa.h" //#include "agg_rasterizer_scanline_aa.h"
#include "agg_scanline_p.h" #include "agg_scanline_p.h"
#include "agg_scanline_u.h" #include "agg_scanline_u.h"
#include "agg_renderer_scanline.h" #include "agg_renderer_scanline.h"
#include "agg_pixfmt_rgba.h" //#include "agg_pixfmt_rgba.h"
#include "agg_path_storage.h" #include "agg_path_storage.h"
#include "agg_span_allocator.h" #include "agg_span_allocator.h"
#include "agg_span_pattern_rgba.h" #include "agg_span_pattern_rgba.h"
@ -93,6 +95,10 @@ namespace mapnik
agg_renderer<T>::agg_renderer(Map const& m, T & pixmap, unsigned offset_x, unsigned offset_y) agg_renderer<T>::agg_renderer(Map const& m, T & pixmap, unsigned offset_x, unsigned offset_y)
: feature_style_processor<agg_renderer>(m), : feature_style_processor<agg_renderer>(m),
pixmap_(pixmap), pixmap_(pixmap),
width_(pixmap_.width()),
height_(pixmap_.height()),
buf_(pixmap_.raw_data(),width_,height_, width_ * 4),
pixf_(buf_),
t_(m.getWidth(),m.getHeight(),m.getCurrentExtent(),offset_x,offset_y), t_(m.getWidth(),m.getHeight(),m.getCurrentExtent(),offset_x,offset_y),
detector_(Envelope<double>(-64 ,-64, m.getWidth() + 64 ,m.getHeight() + 64)), detector_(Envelope<double>(-64 ,-64, m.getWidth() + 64 ,m.getHeight() + 64)),
finder_(detector_,Envelope<double>(0 ,0, m.getWidth(), m.getHeight())) finder_(detector_,Envelope<double>(0 ,0, m.getWidth(), m.getHeight()))
@ -111,6 +117,7 @@ namespace mapnik
std::clog << "start map processing bbox=" std::clog << "start map processing bbox="
<< map.getCurrentExtent() << "\n"; << map.getCurrentExtent() << "\n";
#endif #endif
ras_.clip_box(0,0,width_,height_);
} }
template <typename T> template <typename T>
@ -147,33 +154,141 @@ namespace mapnik
Feature const& feature, Feature const& feature,
proj_transform const& prj_trans) proj_transform const& prj_trans)
{ {
typedef coord_transform2<CoordTransform,geometry_type> path_type; typedef coord_transform2<CoordTransform,geometry2d> path_type;
typedef agg::renderer_base<agg::pixfmt_rgba32> ren_base; typedef agg::renderer_base<agg::pixfmt_rgba32> ren_base;
typedef agg::renderer_scanline_aa_solid<ren_base> renderer; typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
Color const& fill_ = sym.get_fill(); Color const& fill_ = sym.get_fill();
ras_.reset();
geometry_ptr const& geom=feature.get_geometry(); agg::scanline_u8 sl;
if (geom && geom->num_points() > 2) ren_base renb(pixf_);
unsigned r=fill_.red();
unsigned g=fill_.green();
unsigned b=fill_.blue();
renderer ren(renb);
for (unsigned i=0;i<feature.num_geometries();++i)
{ {
unsigned width = pixmap_.width(); geometry2d const& geom=feature.get_geometry(i);
unsigned height = pixmap_.height(); if (geom.num_points() > 2)
path_type path(t_,*geom,prj_trans); {
agg::row_accessor<agg::int8u> buf(pixmap_.raw_data(),width,height,width * 4); path_type path(t_,geom,prj_trans);
agg::pixfmt_rgba32 pixf(buf); ras_.add_path(path);
ren_base renb(pixf); }
}
ren.color(agg::rgba8(r, g, b, int(255 * sym.get_opacity())));
agg::render_scanlines(ras_, sl, ren);
}
unsigned r=fill_.red(); typedef boost::tuple<double,double,double,double> segment_t;
unsigned g=fill_.green(); bool y_order(segment_t const& first,segment_t const& second)
unsigned b=fill_.blue(); {
renderer ren(renb); double miny0 = std::min(first.get<1>(),first.get<3>());
double miny1 = std::min(second.get<1>(),second.get<3>());
return miny0 > miny1;
}
agg::rasterizer_scanline_aa<> ras; template <typename T>
agg::scanline_u8 sl; void agg_renderer<T>::process(building_symbolizer const& sym,
ras.clip_box(0,0,width,height); Feature const& feature,
ras.add_path(path); proj_transform const& prj_trans)
ren.color(agg::rgba8(r, g, b, int(255 * sym.get_opacity()))); {
agg::render_scanlines(ras, sl, ren); typedef coord_transform2<CoordTransform,geometry2d> path_type;
typedef coord_transform3<CoordTransform,geometry2d> path_type_roof;
typedef agg::renderer_base<agg::pixfmt_rgba32> ren_base;
typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
ren_base renb(pixf_);
Color const& fill_ = sym.get_fill();
unsigned r=fill_.red();
unsigned g=fill_.green();
unsigned b=fill_.blue();
renderer ren(renb);
agg::scanline_u8 sl;
ras_.reset();
int height = 60 << 8;
for (unsigned i=0;i<feature.num_geometries();++i)
{
geometry2d const& geom = feature.get_geometry(i);
if (geom.num_points() > 2)
{
boost::scoped_ptr<geometry2d> frame(new line_string_impl);
boost::scoped_ptr<geometry2d> roof(new polygon_impl);
std::deque<segment_t> face_segments;
double x0,y0;
for (unsigned j=0;j<geom.num_points();++j)
{
double x,y;
unsigned cm = geom.vertex(&x,&y);
if (cm == SEG_MOVETO)
{
frame->move_to(x,y);
}
else if (cm == SEG_LINETO)
{
frame->line_to(x,y);
}
if (j!=0)
{
face_segments.push_back(segment_t(x0,y0,x,y));
}
x0 = x;
y0 = y;
}
std::sort(face_segments.begin(),face_segments.end(), y_order);
std::deque<segment_t>::const_iterator itr=face_segments.begin();
for (;itr!=face_segments.end();++itr)
{
boost::scoped_ptr<geometry2d> faces(new polygon_impl);
faces->move_to(itr->get<0>(),itr->get<1>());
faces->line_to(itr->get<2>(),itr->get<3>());
faces->line_to(itr->get<2>(),itr->get<3>() + height);
faces->line_to(itr->get<0>(),itr->get<1>() + height);
path_type faces_path (t_,*faces,prj_trans);
ras_.add_path(faces_path);
ren.color(agg::rgba8(int(r*0.7), int(g*0.7), int(b*0.7), int(255 * sym.get_opacity())));
agg::render_scanlines(ras_, sl, ren);
ras_.reset();
frame->move_to(itr->get<0>(),itr->get<1>());
frame->line_to(itr->get<0>(),itr->get<1>()+height);
}
geom.rewind(0);
for (unsigned j=0;j<geom.num_points();++j)
{
double x,y;
unsigned cm = geom.vertex(&x,&y);
if (cm == SEG_MOVETO)
{
frame->move_to(x,y+height);
roof->move_to(x,y+height);
}
else if (cm == SEG_LINETO)
{
frame->line_to(x,y+height);
roof->line_to(x,y+height);
}
}
path_type path(t_,*frame,prj_trans);
agg::conv_stroke<path_type> stroke(path);
ras_.add_path(stroke);
ren.color(agg::rgba8(128, 128, 128, int(255 * sym.get_opacity())));
agg::render_scanlines(ras_, sl, ren);
ras_.reset();
path_type roof_path (t_,*roof,prj_trans);
ras_.add_path(roof_path);
ren.color(agg::rgba8(r, g, b, int(255 * sym.get_opacity())));
agg::render_scanlines(ras_, sl, ren);
}
} }
} }
@ -183,117 +298,95 @@ namespace mapnik
proj_transform const& prj_trans) proj_transform const& prj_trans)
{ {
typedef agg::renderer_base<agg::pixfmt_rgba32> ren_base; typedef agg::renderer_base<agg::pixfmt_rgba32> ren_base;
typedef coord_transform2<CoordTransform,geometry_type> path_type; typedef coord_transform2<CoordTransform,geometry2d> path_type;
typedef agg::renderer_outline_aa<ren_base> renderer_oaa; typedef agg::renderer_outline_aa<ren_base> renderer_oaa;
typedef agg::rasterizer_outline_aa<renderer_oaa> rasterizer_outline_aa; typedef agg::rasterizer_outline_aa<renderer_oaa> rasterizer_outline_aa;
typedef agg::renderer_scanline_aa_solid<ren_base> renderer; typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
geometry_ptr const& geom=feature.get_geometry(); ren_base renb(pixf_);
if (geom && geom->num_points() > 1) mapnik::stroke const& stroke_ = sym.get_stroke();
Color const& col = stroke_.get_color();
unsigned r=col.red();
unsigned g=col.green();
unsigned b=col.blue();
renderer ren(renb);
ras_.reset();
agg::scanline_p8 sl;
for (unsigned i=0;i<feature.num_geometries();++i)
{ {
path_type path(t_,*geom,prj_trans); geometry2d const& geom = feature.get_geometry(i);
agg::row_accessor<agg::int8u> buf(pixmap_.raw_data(), if (geom.num_points() > 1)
pixmap_.width(),
pixmap_.height(),
pixmap_.width()*4);
agg::pixfmt_rgba32 pixf(buf);
ren_base renb(pixf);
mapnik::stroke const& stroke_ = sym.get_stroke();
Color const& col = stroke_.get_color();
unsigned r=col.red();
unsigned g=col.green();
unsigned b=col.blue();
if (stroke_.has_dash())
{ {
renderer ren(renb); path_type path(t_,geom,prj_trans);
agg::rasterizer_scanline_aa<> ras;
agg::scanline_u8 sl; if (stroke_.has_dash())
agg::conv_dash<path_type> dash(path);
dash_array const& d = stroke_.get_dash_array();
dash_array::const_iterator itr = d.begin();
dash_array::const_iterator end = d.end();
while (itr != end)
{ {
dash.add_dash(itr->first, itr->second); agg::conv_dash<path_type> dash(path);
++itr; dash_array const& d = stroke_.get_dash_array();
dash_array::const_iterator itr = d.begin();
dash_array::const_iterator end = d.end();
for (;itr != end;++itr)
{
dash.add_dash(itr->first, itr->second);
}
agg::conv_stroke<agg::conv_dash<path_type > > stroke(dash);
line_join_e join=stroke_.get_line_join();
if ( join == MITER_JOIN)
stroke.generator().line_join(agg::miter_join);
else if( join == MITER_REVERT_JOIN)
stroke.generator().line_join(agg::miter_join);
else if( join == ROUND_JOIN)
stroke.generator().line_join(agg::round_join);
else
stroke.generator().line_join(agg::bevel_join);
line_cap_e cap=stroke_.get_line_cap();
if (cap == BUTT_CAP)
stroke.generator().line_cap(agg::butt_cap);
else if (cap == SQUARE_CAP)
stroke.generator().line_cap(agg::square_cap);
else
stroke.generator().line_cap(agg::round_cap);
stroke.generator().miter_limit(4.0);
stroke.generator().width(stroke_.get_width());
ras_.add_path(stroke);
} }
agg::conv_stroke<agg::conv_dash<path_type > > stroke(dash);
line_join_e join=stroke_.get_line_join();
if ( join == MITER_JOIN)
stroke.generator().line_join(agg::miter_join);
else if( join == MITER_REVERT_JOIN)
stroke.generator().line_join(agg::miter_join);
else if( join == ROUND_JOIN)
stroke.generator().line_join(agg::round_join);
else else
stroke.generator().line_join(agg::bevel_join); {
agg::conv_stroke<path_type> stroke(path);
line_cap_e cap=stroke_.get_line_cap(); line_join_e join=stroke_.get_line_join();
if (cap == BUTT_CAP) if ( join == MITER_JOIN)
stroke.generator().line_cap(agg::butt_cap); stroke.generator().line_join(agg::miter_join);
else if (cap == SQUARE_CAP) else if( join == MITER_REVERT_JOIN)
stroke.generator().line_cap(agg::square_cap); stroke.generator().line_join(agg::miter_join);
else else if( join == ROUND_JOIN)
stroke.generator().line_cap(agg::round_cap); stroke.generator().line_join(agg::round_join);
else
stroke.generator().line_join(agg::bevel_join);
stroke.generator().miter_limit(4.0); line_cap_e cap=stroke_.get_line_cap();
stroke.generator().width(stroke_.get_width()); if (cap == BUTT_CAP)
stroke.generator().line_cap(agg::butt_cap);
else if (cap == SQUARE_CAP)
stroke.generator().line_cap(agg::square_cap);
else
stroke.generator().line_cap(agg::round_cap);
ras.clip_box(0,0,pixmap_.width(),pixmap_.height()); stroke.generator().miter_limit(4.0);
ras.add_path(stroke); stroke.generator().width(stroke_.get_width());
ren.color(agg::rgba8(r, g, b, int(255*stroke_.get_opacity()))); ras_.add_path(stroke);
agg::render_scanlines(ras, sl, ren); }
}
//else if (stroke_.get_width() <= 1.0)
//{
// agg::line_profile_aa prof;
// prof.width(stroke_.get_width());
// renderer_oaa ren_oaa(renb, prof);
// rasterizer_outline_aa ras_oaa(ren_oaa);
// ren_oaa.color(agg::rgba8(r, g, b, int(255*stroke_.get_opacity())));
// ren_oaa.clip_box(0,0,pixmap_.width(),pixmap_.height());
// ras_oaa.add_path(path);
// }
else
{
renderer ren(renb);
agg::rasterizer_scanline_aa<> ras;
agg::scanline_p8 sl;
agg::conv_stroke<path_type> stroke(path);
line_join_e join=stroke_.get_line_join();
if ( join == MITER_JOIN)
stroke.generator().line_join(agg::miter_join);
else if( join == MITER_REVERT_JOIN)
stroke.generator().line_join(agg::miter_join);
else if( join == ROUND_JOIN)
stroke.generator().line_join(agg::round_join);
else
stroke.generator().line_join(agg::bevel_join);
line_cap_e cap=stroke_.get_line_cap();
if (cap == BUTT_CAP)
stroke.generator().line_cap(agg::butt_cap);
else if (cap == SQUARE_CAP)
stroke.generator().line_cap(agg::square_cap);
else
stroke.generator().line_cap(agg::round_cap);
stroke.generator().miter_limit(4.0);
stroke.generator().width(stroke_.get_width());
ras.clip_box(0,0,pixmap_.width(),pixmap_.height());
ras.add_path(stroke);
ren.color(agg::rgba8(r, g, b, int(255*stroke_.get_opacity())));
agg::render_scanlines(ras, sl, ren);
} }
} }
ren.color(agg::rgba8(r, g, b, int(255*stroke_.get_opacity())));
agg::render_scanlines(ras_, sl, ren);
} }
template <typename T> template <typename T>
@ -301,16 +394,17 @@ namespace mapnik
Feature const& feature, Feature const& feature,
proj_transform const& prj_trans) proj_transform const& prj_trans)
{ {
geometry_ptr const& geom=feature.get_geometry(); double x;
if (geom) double y;
double z=0;
boost::shared_ptr<ImageData32> const& data = sym.get_data();
if ( data )
{ {
double x; for (unsigned i=0;i<feature.num_geometries();++i)
double y;
double z=0;
boost::shared_ptr<ImageData32> const& data = sym.get_data();
if ( data )
{ {
geom->label_position(&x,&y); geometry2d const& geom = feature.get_geometry(i);
geom.label_position(&x,&y);
prj_trans.backward(x,y,z); prj_trans.backward(x,y,z);
t_.forward(&x,&y); t_.forward(&x,&y);
int w = data->width(); int w = data->width();
@ -336,45 +430,46 @@ namespace mapnik
Feature const& feature, Feature const& feature,
proj_transform const& prj_trans) proj_transform const& prj_trans)
{ {
geometry_ptr const& geom=feature.get_geometry(); std::wstring text = feature[sym.get_name()].to_unicode();
if (geom && geom->num_points() > 0) boost::shared_ptr<ImageData32> const& data = sym.get_background_image();
if (text.length() > 0 && data)
{ {
std::wstring text = feature[sym.get_name()].to_unicode(); face_ptr face = font_manager_.get_face(sym.get_face_name());
boost::shared_ptr<ImageData32> const& data = sym.get_background_image(); if (face)
if (text.length() > 0 && data)
{ {
face_ptr face = font_manager_.get_face(sym.get_face_name()); text_renderer<mapnik::Image32> ren(pixmap_,face);
if (face) ren.set_pixel_size(sym.get_text_size());
ren.set_fill(sym.get_fill());
string_info info(text);
ren.get_string_info(&info);
unsigned num_geom = feature.num_geometries();
for (unsigned i=0;i<num_geom;++i)
{ {
text_renderer<mapnik::Image32> ren(pixmap_,face); geometry2d const& geom = feature.get_geometry(i);
ren.set_pixel_size(sym.get_text_size()); if (geom.num_points() > 0) // don't bother with empty geometries
ren.set_fill(sym.get_fill());
string_info info(text);
ren.get_string_info(&info);
placement text_placement(&info, &t_, &prj_trans, geom, sym);
text_placement.avoid_edges = sym.get_avoid_edges();
finder_.find_placements(&text_placement);
for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii)
{ {
int w = data->width(); placement text_placement(&info, &t_, &prj_trans, geom, sym);
int h = data->height(); text_placement.avoid_edges = sym.get_avoid_edges();
double x = text_placement.placements[ii].starting_x; finder_.find_placements(&text_placement);
double y = text_placement.placements[ii].starting_y;
int px=int(x - (w/2)); for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii)
int py=int(y - (h/2)); {
int w = data->width();
int h = data->height();
pixmap_.set_rectangle_alpha(px,py,*data); double x = text_placement.placements[ii].starting_x;
double y = text_placement.placements[ii].starting_y;
Envelope<double> dim = ren.prepare_glyphs(&text_placement.placements[ii].path); int px=int(x - (w/2));
int py=int(y - (h/2));
ren.render(x,y); pixmap_.set_rectangle_alpha(px,py,*data);
Envelope<double> dim = ren.prepare_glyphs(&text_placement.placements[ii]);
ren.render(x,y);
}
} }
} }
} }
@ -386,29 +481,29 @@ namespace mapnik
Feature const& feature, Feature const& feature,
proj_transform const& prj_trans) proj_transform const& prj_trans)
{ {
typedef coord_transform2<CoordTransform,geometry_type> path_type; typedef coord_transform2<CoordTransform,geometry2d> path_type;
typedef agg::line_image_pattern<agg::pattern_filter_bilinear_rgba8> pattern_type; typedef agg::line_image_pattern<agg::pattern_filter_bilinear_rgba8> pattern_type;
typedef agg::renderer_base<agg::pixfmt_rgba32> renderer_base; typedef agg::renderer_base<agg::pixfmt_rgba32> renderer_base;
typedef agg::renderer_outline_image<renderer_base, pattern_type> renderer_type; typedef agg::renderer_outline_image<renderer_base, pattern_type> renderer_type;
typedef agg::rasterizer_outline_aa<renderer_type> rasterizer_type; typedef agg::rasterizer_outline_aa<renderer_type> rasterizer_type;
geometry_ptr const& geom=feature.get_geometry(); ImageData32 const& pat = sym.get_pattern();
if (geom && geom->num_points() > 1) renderer_base ren_base(pixf_);
agg::pattern_filter_bilinear_rgba8 filter;
pattern_source source(pat);
pattern_type pattern (filter,source);
renderer_type ren(ren_base, pattern);
ren.clip_box(0,0,width_,height_);
rasterizer_type ras(ren);
for (unsigned i=0;i<feature.num_geometries();++i)
{ {
unsigned width = pixmap_.width(); geometry2d const& geom = feature.get_geometry(i);
unsigned height = pixmap_.height(); if (geom.num_points() > 1)
ImageData32 const& pat = sym.get_pattern(); {
path_type path(t_,*geom,prj_trans); path_type path(t_,geom,prj_trans);
agg::row_accessor<agg::int8u> buf(pixmap_.raw_data(), width, height,width*4); ras.add_path(path);
agg::pixfmt_rgba32 pixf(buf); }
renderer_base ren_base(pixf);
agg::pattern_filter_bilinear_rgba8 filter;
pattern_source source(pat);
pattern_type pattern (filter,source);
renderer_type ren(ren_base, pattern);
ren.clip_box(0,0,width,height);
rasterizer_type ras(ren);
ras.add_path(path);
} }
} }
@ -417,11 +512,13 @@ namespace mapnik
Feature const& feature, Feature const& feature,
proj_transform const& prj_trans) proj_transform const& prj_trans)
{ {
typedef coord_transform2<CoordTransform,geometry_type> path_type; typedef coord_transform2<CoordTransform,geometry2d> path_type;
typedef agg::renderer_base<agg::pixfmt_rgba32> ren_base; typedef agg::renderer_base<agg::pixfmt_rgba32> ren_base;
typedef agg::wrap_mode_repeat wrap_x_type; typedef agg::wrap_mode_repeat wrap_x_type;
typedef agg::wrap_mode_repeat wrap_y_type; typedef agg::wrap_mode_repeat wrap_y_type;
typedef agg::image_accessor_wrap<agg::pixfmt_rgba32, typedef agg::pixfmt_alpha_blend_rgba<agg::blender_rgba32,
agg::row_accessor<agg::int8u>, agg::pixel32_type> rendering_buffer;
typedef agg::image_accessor_wrap<rendering_buffer,
wrap_x_type, wrap_x_type,
wrap_y_type> img_source_type; wrap_y_type> img_source_type;
@ -430,42 +527,41 @@ namespace mapnik
typedef agg::renderer_scanline_aa<ren_base, typedef agg::renderer_scanline_aa<ren_base,
agg::span_allocator<agg::rgba8>, agg::span_allocator<agg::rgba8>,
span_gen_type> renderer_type; span_gen_type> renderer_type;
geometry_ptr const& geom=feature.get_geometry();
if (geom && geom->num_points() > 2) ras_.reset();
ren_base renb(pixf_);
agg::scanline_u8 sl;
ImageData32 const& pattern = sym.get_pattern();
unsigned w=pattern.width();
unsigned h=pattern.height();
agg::row_accessor<agg::int8u> pattern_rbuf((agg::int8u*)pattern.getBytes(),w,h,w*4);
agg::span_allocator<agg::rgba8> sa;
agg::pixfmt_alpha_blend_rgba<agg::blender_rgba32,
agg::row_accessor<agg::int8u>, agg::pixel32_type> pixf_pattern(pattern_rbuf);
img_source_type img_src(pixf_pattern);
double x0=0,y0=0;
unsigned num_geometries = feature.num_geometries();
if (num_geometries>0)
{ {
ImageData32 const& pattern = sym.get_pattern(); path_type path(t_,feature.get_geometry(0),prj_trans);
unsigned width = pixmap_.width();
unsigned height = pixmap_.height();
path_type path(t_,*geom,prj_trans);
agg::row_accessor<agg::int8u> buf(pixmap_.raw_data(),width,height,width * 4);
agg::pixfmt_rgba32 pixf(buf);
ren_base renb(pixf);
unsigned w=pattern.width();
unsigned h=pattern.height();
agg::row_accessor<agg::int8u> pattern_rbuf((agg::int8u*)pattern.getBytes(),w,h,w*4);
double x0,y0;
path.vertex(&x0,&y0); path.vertex(&x0,&y0);
path.rewind(0);
unsigned offset_x = unsigned(width - x0);
unsigned offset_y = unsigned(height - y0);
agg::span_allocator<agg::rgba8> sa;
agg::pixfmt_rgba32 pixf_pattern(pattern_rbuf);
img_source_type img_src(pixf_pattern);
span_gen_type sg(img_src, offset_x, offset_y);
renderer_type rp(renb,sa, sg);
agg::rasterizer_scanline_aa<> ras;
agg::scanline_u8 sl;
ras.clip_box(0,0,width,height);
ras.add_path(path);
agg::render_scanlines(ras, sl, rp);
} }
unsigned offset_x = unsigned(width_-x0);
unsigned offset_y = unsigned(height_-y0);
span_gen_type sg(img_src, offset_x, offset_y);
renderer_type rp(renb,sa, sg);
for (unsigned i=0;i<num_geometries;++i)
{
geometry2d const& geom = feature.get_geometry(i);
if (geom.num_points() > 2)
{
path_type path(t_,geom,prj_trans);
ras_.add_path(path);
}
}
agg::render_scanlines(ras_, sl, rp);
} }
template <typename T> template <typename T>
@ -480,7 +576,7 @@ namespace mapnik
if (raster) if (raster)
{ {
Envelope<double> ext=t_.forward(raster->ext_); Envelope<double> ext=t_.forward(raster->ext_);
ImageData32 target((int)(ext.width() + 0.5),(int)(ext.height() + 0.5)); ImageData32 target(int(ext.width() + 0.5),int(ext.height() + 0.5));
scale_image<ImageData32>(target,raster->data_); scale_image<ImageData32>(target,raster->data_);
pixmap_.set_rectangle(int(ext.minx()),int(ext.miny()),target); pixmap_.set_rectangle(int(ext.minx()),int(ext.miny()),target);
} }
@ -491,41 +587,41 @@ namespace mapnik
Feature const& feature, Feature const& feature,
proj_transform const& prj_trans) proj_transform const& prj_trans)
{ {
geometry_ptr const& geom=feature.get_geometry();
if (geom && geom->num_points() > 0) std::wstring text = feature[sym.get_name()].to_unicode();
if ( text.length() > 0 )
{ {
std::wstring text = feature[sym.get_name()].to_unicode(); Color const& fill = sym.get_fill();
if ( text.length() > 0 ) face_ptr face = font_manager_.get_face(sym.get_face_name());
if (face)
{ {
Color const& fill = sym.get_fill(); text_renderer<mapnik::Image32> ren(pixmap_,face);
face_ptr face = font_manager_.get_face(sym.get_face_name()); ren.set_pixel_size(sym.get_text_size());
if (face) ren.set_fill(fill);
ren.set_halo_fill(sym.get_halo_fill());
ren.set_halo_radius(sym.get_halo_radius());
string_info info(text);
ren.get_string_info(&info);
unsigned num_geom = feature.num_geometries();
for (unsigned i=0;i<num_geom;++i)
{ {
text_renderer<mapnik::Image32> ren(pixmap_,face); geometry2d const& geom = feature.get_geometry(i);
ren.set_pixel_size(sym.get_text_size()); if (geom.num_points() > 0) // don't bother with empty geometries
ren.set_fill(fill);
ren.set_halo_fill(sym.get_halo_fill());
ren.set_halo_radius(sym.get_halo_radius());
string_info info(text);
ren.get_string_info(&info);
placement text_placement(&info, &t_, &prj_trans, geom, sym);
finder_.find_placements(&text_placement);
for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii)
{ {
double x = text_placement.placements[ii].starting_x; placement text_placement(&info, &t_, &prj_trans, geom, sym);
double y = text_placement.placements[ii].starting_y; finder_.find_placements(&text_placement);
Envelope<double> dim = ren.prepare_glyphs(&text_placement.placements[ii].path); for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii)
ren.render(x,y); {
double x = text_placement.placements[ii].starting_x;
double y = text_placement.placements[ii].starting_y;
Envelope<double> dim = ren.prepare_glyphs(&text_placement.placements[ii]);
ren.render(x,y);
}
} }
} }
} }
} }
} }
template class agg_renderer<Image32>; template class agg_renderer<Image32>;
} }

View file

@ -167,7 +167,7 @@ namespace mapnik
} }
template <typename T> template <typename T>
bool Envelope<T>::intersects(T x,T y) const inline bool Envelope<T>::intersects(T x,T y) const
{ {
return !(x>maxx_ || x<minx_ || y>maxy_ || y<miny_); return !(x>maxx_ || x<minx_ || y>maxy_ || y<miny_);
} }

View file

@ -441,6 +441,40 @@ namespace mapnik
} }
rule.append(poly_sym); rule.append(poly_sym);
} }
else if ( sym.first == "BuildingSymbolizer")
{
building_symbolizer building_sym;
ptree::const_iterator cssIter = sym.second.begin();
ptree::const_iterator endCss = sym.second.end();
for(; cssIter != endCss; ++cssIter)
{
ptree::value_type const& css = * cssIter;
std::string css_name =
css.second.get<std::string>("<xmlattr>.name");
std::string data = css.second.data();
if (css_name == "fill")
{
Color c = color_factory::from_string(css.second.data().c_str());
building_sym.set_fill(c);
}
else if (css_name == "fill-opacity")
{
try
{
float opacity = lexical_cast<float>(data);
building_sym.set_opacity(opacity);
}
catch (bad_lexical_cast & ex)
{
std::clog << ex.what() << "\n";
}
}
}
rule.append(building_sym);
}
else if ( sym.first == "RasterSymbolizer") else if ( sym.first == "RasterSymbolizer")
{ {
rule.append(raster_symbolizer()); rule.append(raster_symbolizer());

View file

@ -267,7 +267,7 @@ namespace mapnik
} }
catch (proj_init_error & ex) catch (proj_init_error & ex)
{ {
std::clog << ex.what() << '\n'; std::clog << "proj_init_error:" << ex.what() << '\n';
} }
} }

View file

@ -33,17 +33,19 @@ namespace mapnik {
void operator() (feature_ptr feat) void operator() (feature_ptr feat)
{ {
geometry_ptr geom = feat->get_geometry(); for (unsigned i=0;i<feat->num_geometries();++i)
if ( !geom ) return; {
if ( first_ ) geometry2d & geom = feat->get_geometry(i);
{ if ( first_ )
first_ = false; {
ext_ = geom->envelope(); first_ = false;
} ext_ = geom.envelope();
else }
{ else
ext_.expand_to_include(geom->envelope()); {
} ext_.expand_to_include(geom.envelope());
}
}
} }
Envelope<double> & ext_; Envelope<double> & ext_;

View file

@ -49,15 +49,15 @@ namespace mapnik
{ {
template<> template<>
placement::placement(string_info *info_, placement::placement(string_info *info_,
CoordTransform *ctrans_, CoordTransform *ctrans_,
const proj_transform *proj_trans_, const proj_transform *proj_trans_,
geometry_ptr geom_, geometry2d const& geom_,
shield_symbolizer sym) shield_symbolizer const& sym)
: info(info_), : info(info_),
ctrans(ctrans_), ctrans(ctrans_),
proj_trans(proj_trans_), proj_trans(proj_trans_),
geom(geom_), geom(geom_),
shape_path(*ctrans_, *geom_, *proj_trans_), shape_path(*ctrans_, geom_, *proj_trans_),
total_distance_(-1.0), total_distance_(-1.0),
displacement_(sym.get_displacement()), displacement_(sym.get_displacement()),
label_placement(sym.get_label_placement()), label_placement(sym.get_label_placement()),
@ -77,15 +77,15 @@ namespace mapnik
template<> template<>
placement::placement(string_info *info_, placement::placement(string_info *info_,
CoordTransform *ctrans_, CoordTransform *ctrans_,
const proj_transform *proj_trans_, const proj_transform *proj_trans_,
geometry_ptr geom_, geometry2d const& geom_,
text_symbolizer sym) text_symbolizer const& sym)
: info(info_), : info(info_),
ctrans(ctrans_), ctrans(ctrans_),
proj_trans(proj_trans_), proj_trans(proj_trans_),
geom(geom_), geom(geom_),
shape_path(*ctrans_, *geom_, *proj_trans_), shape_path(*ctrans_, geom_, *proj_trans_),
total_distance_(-1.0), total_distance_(-1.0),
displacement_(sym.get_displacement()), displacement_(sym.get_displacement()),
label_placement(sym.get_label_placement()), label_placement(sym.get_label_placement()),
@ -109,7 +109,7 @@ namespace mapnik
unsigned placement::path_size() const unsigned placement::path_size() const
{ {
return geom->num_points(); return geom.num_points();
} }
std::pair<double, double> placement::get_position_at_distance(double target_distance) std::pair<double, double> placement::get_position_at_distance(double target_distance)
@ -122,7 +122,7 @@ namespace mapnik
shape_path.rewind(0); shape_path.rewind(0);
shape_path.vertex(&new_x,&new_y); shape_path.vertex(&new_x,&new_y);
unsigned num_points = geom->num_points(); unsigned num_points = geom.num_points();
for (unsigned i = 1; i < num_points; ++i) for (unsigned i = 1; i < num_points; ++i)
{ {
double dx, dy; double dx, dy;
@ -162,7 +162,7 @@ namespace mapnik
total_distance_ = 0.0; total_distance_ = 0.0;
unsigned num_points = geom->num_points(); unsigned num_points = geom.num_points();
for (unsigned i = 1; i < num_points ; ++i) for (unsigned i = 1; i < num_points ; ++i)
{ {
double dx, dy; double dx, dy;
@ -328,7 +328,8 @@ namespace mapnik
int orientation = 0; int orientation = 0;
double displacement = boost::tuples::get<1>(p->displacement_); // displace by dy double displacement = boost::tuples::get<1>(p->displacement_); // displace by dy
p->current_placement.path.clear(); //p->current_placement.clear(); //TODO !!
std::auto_ptr<placement_element> current_placement(new placement_element);
double x, y; double x, y;
x = y = 0.0; x = y = 0.0;
@ -344,7 +345,7 @@ namespace mapnik
p->shape_path.vertex(&new_x,&new_y); p->shape_path.vertex(&new_x,&new_y);
old_x = new_x; old_x = new_x;
old_y = new_y; old_y = new_y;
unsigned num_points = p->geom->num_points(); unsigned num_points = p->geom.num_points();
for (unsigned i = 1; i < num_points; ++i) for (unsigned i = 1; i < num_points; ++i)
{ {
double dx, dy; double dx, dy;
@ -365,8 +366,8 @@ namespace mapnik
if (distance > target_distance) if (distance > target_distance)
{ {
// this segment is greater that the target starting distance so start here // this segment is greater that the target starting distance so start here
p->current_placement.starting_x = new_x - dx*(distance - target_distance)/segment_length; current_placement->starting_x = new_x - dx*(distance - target_distance)/segment_length;
p->current_placement.starting_y = new_y - dy*(distance - target_distance)/segment_length; current_placement->starting_y = new_y - dy*(distance - target_distance)/segment_length;
// angle text starts at and orientation // angle text starts at and orientation
angle = atan2(-dy, dx); angle = atan2(-dy, dx);
@ -403,7 +404,7 @@ namespace mapnik
cur_node++; cur_node++;
if (cur_node >= p->geom->num_points()) { if (cur_node >= p->geom.num_points()) {
return false; return false;
} }
@ -491,13 +492,14 @@ namespace mapnik
} }
p->current_placement.path.add_node(c,render_x - p->current_placement.starting_x, current_placement->add_node(c,render_x - current_placement->starting_x,
-render_y + p->current_placement.starting_y, -render_y + current_placement->starting_y,
render_angle); render_angle);
x += next_char_x; x += next_char_x;
y -= next_char_y; y -= next_char_y;
} }
p->placements.push_back(p->current_placement);
p->placements.push_back(current_placement.release());
return true; return true;
} }
@ -507,7 +509,8 @@ namespace mapnik
{ {
double x, y; double x, y;
p->current_placement.path.clear(); //p->current_placement.clear(); // TODO
std::auto_ptr<placement_element> current_placement(new placement_element);
std::pair<double, double> string_dimensions = p->info->get_dimensions(); std::pair<double, double> string_dimensions = p->info->get_dimensions();
double string_width = string_dimensions.first; double string_width = string_dimensions.first;
@ -538,7 +541,7 @@ namespace mapnik
double word_height = 0; double word_height = 0;
for (unsigned int ii = 0; ii < p->info->num_characters(); ii++) for (unsigned int ii = 0; ii < p->info->num_characters(); ii++)
{ {
character_info ci;; character_info ci;
ci = p->info->at(ii); ci = p->info->at(ii);
unsigned c = ci.character; unsigned c = ci.character;
@ -581,25 +584,25 @@ namespace mapnik
p->info->set_dimensions(string_width, string_height); p->info->set_dimensions(string_width, string_height);
if (p->geom->type() == LineString) if (p->geom.type() == LineString)
{ {
std::pair<double, double> starting_pos = p->get_position_at_distance(target_distance); std::pair<double, double> starting_pos = p->get_position_at_distance(target_distance);
p->current_placement.starting_x = starting_pos.first; current_placement->starting_x = starting_pos.first;
p->current_placement.starting_y = starting_pos.second; current_placement->starting_y = starting_pos.second;
} }
else else
{ {
p->geom->label_position(&p->current_placement.starting_x, &p->current_placement.starting_y); p->geom.label_position(&current_placement->starting_x, &current_placement->starting_y);
// TODO: // TODO:
// We would only want label position in final 'paper' coords. // We would only want label position in final 'paper' coords.
// Move view and proj transforms to e.g. label_position(x,y,proj_trans,ctrans)? // Move view and proj transforms to e.g. label_position(x,y,proj_trans,ctrans)?
double z=0; double z=0;
p->proj_trans->backward(p->current_placement.starting_x, p->current_placement.starting_y, z); p->proj_trans->backward(current_placement->starting_x,current_placement->starting_y, z);
p->ctrans->forward(&p->current_placement.starting_x, &p->current_placement.starting_y); p->ctrans->forward(&current_placement->starting_x, &current_placement->starting_y);
// apply displacement ( in pixels ) // apply displacement ( in pixels )
p->current_placement.starting_x += boost::tuples::get<0>(p->displacement_); current_placement->starting_x += boost::tuples::get<0>(p->displacement_);
p->current_placement.starting_y += boost::tuples::get<1>(p->displacement_); current_placement->starting_y += boost::tuples::get<1>(p->displacement_);
} }
double line_height = 0; double line_height = 0;
@ -627,22 +630,22 @@ namespace mapnik
} }
else else
{ {
p->current_placement.path.add_node(c, x, y, 0.0); current_placement->add_node(c, x, y, 0.0);
Envelope<double> e; Envelope<double> e;
if (p->has_dimensions) if (p->has_dimensions)
{ {
e.init(p->current_placement.starting_x - (p->dimensions.first/2.0), e.init(current_placement->starting_x - (p->dimensions.first/2.0),
p->current_placement.starting_y - (p->dimensions.second/2.0), current_placement->starting_y - (p->dimensions.second/2.0),
p->current_placement.starting_x + (p->dimensions.first/2.0), current_placement->starting_x + (p->dimensions.first/2.0),
p->current_placement.starting_y + (p->dimensions.second/2.0)); current_placement->starting_y + (p->dimensions.second/2.0));
} }
else else
{ {
e.init(p->current_placement.starting_x + x, e.init(current_placement->starting_x + x,
p->current_placement.starting_y - y, current_placement->starting_y - y,
p->current_placement.starting_x + x + ci.width, current_placement->starting_x + x + ci.width,
p->current_placement.starting_y - y - ci.height); current_placement->starting_y - y - ci.height);
} }
if (!detector_.has_placement(e, p->info->get_string(), p->minimum_distance)) if (!detector_.has_placement(e, p->info->get_string(), p->minimum_distance))
@ -660,7 +663,7 @@ namespace mapnik
x += ci.width; x += ci.width;
line_height = line_height > ci.height ? line_height : ci.height; line_height = line_height > ci.height ? line_height : ci.height;
} }
p->placements.push_back(p->current_placement); p->placements.push_back(current_placement.release());
return true; return true;
} }

View file

@ -24,24 +24,25 @@
#include <mapnik/wkb.hpp> #include <mapnik/wkb.hpp>
#include <mapnik/geom_util.hpp> #include <mapnik/geom_util.hpp>
#include <mapnik/feature.hpp>
namespace mapnik namespace mapnik
{ {
struct wkb_reader struct wkb_reader
{ {
private: private:
enum wkbByteOrder { enum wkbByteOrder {
wkbXDR=0, wkbXDR=0,
wkbNDR=1 wkbNDR=1
}; };
const char* wkb_; const char* wkb_;
unsigned size_; unsigned size_;
unsigned pos_; unsigned pos_;
wkbByteOrder byteOrder_; wkbByteOrder byteOrder_;
bool needSwap_; bool needSwap_;
public: public:
enum wkbGeometryType { enum wkbGeometryType {
wkbPoint=1, wkbPoint=1,
wkbLineString=2, wkbLineString=2,
wkbPolygon=3, wkbPolygon=3,
@ -49,14 +50,14 @@ namespace mapnik
wkbMultiLineString=5, wkbMultiLineString=5,
wkbMultiPolygon=6, wkbMultiPolygon=6,
wkbGeometryCollection=7 wkbGeometryCollection=7
}; };
wkb_reader(const char* wkb,unsigned size) wkb_reader(const char* wkb,unsigned size)
: wkb_(wkb), : wkb_(wkb),
size_(size), size_(size),
pos_(0), pos_(0),
byteOrder_((wkbByteOrder)wkb_[0]) byteOrder_((wkbByteOrder)wkb_[0])
{ {
++pos_; ++pos_;
#ifndef WORDS_BIGENDIAN #ifndef WORDS_BIGENDIAN
@ -64,138 +65,132 @@ namespace mapnik
#else #else
needSwap_=byteOrder_?wkbNDR:wkbXDR; needSwap_=byteOrder_?wkbNDR:wkbXDR;
#endif #endif
} }
~wkb_reader() {} ~wkb_reader() {}
geometry_ptr read() void read(Feature & feature)
{ {
geometry_ptr geom;
int type=read_integer(); int type=read_integer();
switch (type) switch (type)
{ {
case wkbPoint: case wkbPoint:
geom = read_point(); read_point(feature);
break; break;
case wkbLineString: case wkbLineString:
geom = read_linestring(); read_linestring(feature);
break; break;
case wkbPolygon: case wkbPolygon:
geom = read_polygon(); read_polygon(feature);
break; break;
case wkbMultiPoint: case wkbMultiPoint:
geom = read_multipoint(); read_multipoint(feature);
break; break;
case wkbMultiLineString: case wkbMultiLineString:
geom = read_multilinestring(); read_multilinestring(feature);
break; break;
case wkbMultiPolygon: case wkbMultiPolygon:
geom=read_multipolygon(); read_multipolygon(feature);
break; break;
case wkbGeometryCollection: case wkbGeometryCollection:
break; break;
default: default:
break; break;
} }
return geom; }
}
private: private:
wkb_reader(const wkb_reader&); wkb_reader(const wkb_reader&);
wkb_reader& operator=(const wkb_reader&); wkb_reader& operator=(const wkb_reader&);
int read_integer() int read_integer()
{ {
int n; int n;
if (!needSwap_) if (!needSwap_)
{ {
memcpy(&n,wkb_+pos_,4); memcpy(&n,wkb_+pos_,4);
} }
else else
{ {
const char* b=wkb_+pos_; const char* b=wkb_+pos_;
n = b[3]&0xff | (b[2]&0xff)<<8 | (b[1]&0xff)<<16 | (b[0]&0xff)<<24; n = b[3]&0xff | (b[2]&0xff)<<8 | (b[1]&0xff)<<16 | (b[0]&0xff)<<24;
} }
pos_+=4; pos_+=4;
return n; return n;
} }
double read_double() double read_double()
{ {
double d; double d;
if (!needSwap_) if (!needSwap_)
{ {
memcpy(&d,wkb_+pos_,8); memcpy(&d,wkb_+pos_,8);
} }
else else
{ {
// we rely on the fact that "long long" is in C standard, // we rely on the fact that "long long" is in C standard,
// but not in C++ yet // but not in C++ yet
// this is not quite portable // this is not quite portable
const char* b= wkb_+pos_; const char* b= wkb_+pos_;
long long n = (long long)b[7]&0xff | long long n = (long long)b[7]&0xff |
((long long)b[6]&0xff)<<8 | ((long long)b[6]&0xff)<<8 |
((long long)b[5]&0xff)<<16 | ((long long)b[5]&0xff)<<16 |
((long long)b[4]&0xff)<<24 | ((long long)b[4]&0xff)<<24 |
((long long)b[3]&0xff)<<32 | ((long long)b[3]&0xff)<<32 |
((long long)b[2]&0xff)<<40 | ((long long)b[2]&0xff)<<40 |
((long long)b[1]&0xff)<<48 | ((long long)b[1]&0xff)<<48 |
((long long)b[0]&0xff)<<56; ((long long)b[0]&0xff)<<56;
memcpy(&d,&n,8); memcpy(&d,&n,8);
} }
pos_+=8; pos_+=8;
return d; return d;
} }
void read_coords(CoordinateArray& ar) void read_coords(CoordinateArray& ar)
{ {
int size=sizeof(coord<double,2>)*ar.size(); int size=sizeof(coord<double,2>)*ar.size();
if (!needSwap_) if (!needSwap_)
{ {
std::memcpy(&ar[0],wkb_+pos_,size); std::memcpy(&ar[0],wkb_+pos_,size);
} }
else else
{ {
for (unsigned i=0;i<ar.size();++i) for (unsigned i=0;i<ar.size();++i)
{ {
ar[i].x=read_double(); ar[i].x=read_double();
ar[i].y=read_double(); ar[i].y=read_double();
} }
} }
pos_+=size; pos_+=size;
} }
geometry_ptr read_point() void read_point(Feature & feature)
{ {
geometry_ptr pt(new point<vertex2d>); geometry2d * pt = new point<vertex2d>;
double x = read_double(); double x = read_double();
double y = read_double(); double y = read_double();
pt->move_to(x,y); pt->move_to(x,y);
return pt; feature.add_geometry(pt);
} }
geometry_ptr read_multipoint() void read_multipoint(Feature & feature)
{ {
geometry_ptr pt(new point<vertex2d>);
int num_points = read_integer(); int num_points = read_integer();
for (int i=0;i<num_points;++i) for (int i=0;i<num_points;++i)
{ {
pos_+=5; pos_+=5;
double x = read_double(); read_point(feature);
double y = read_double();
pt->move_to(x,y);
} }
return pt; }
}
geometry_ptr read_linestring() void read_linestring(Feature & feature)
{ {
geometry_ptr line(new line_string<vertex2d>); geometry2d * line = new line_string<vertex2d>;
int num_points=read_integer(); int num_points=read_integer();
CoordinateArray ar(num_points); CoordinateArray ar(num_points);
read_coords(ar); read_coords(ar);
@ -203,85 +198,55 @@ namespace mapnik
line->move_to(ar[0].x,ar[0].y); line->move_to(ar[0].x,ar[0].y);
for (int i=1;i<num_points;++i) for (int i=1;i<num_points;++i)
{ {
line->line_to(ar[i].x,ar[i].y); line->line_to(ar[i].x,ar[i].y);
} }
return line; feature.add_geometry(line);
} }
geometry_ptr read_multilinestring() void read_multilinestring(Feature & feature)
{ {
geometry_ptr line(new line_string<vertex2d>);
int num_lines=read_integer(); int num_lines=read_integer();
for (int i=0;i<num_lines;++i) for (int i=0;i<num_lines;++i)
{ {
pos_+=5; pos_+=5;
read_linestring(feature);
int num_points=read_integer();
CoordinateArray ar(num_points);
read_coords(ar);
line->move_to(ar[0].x,ar[0].y);
for (int i=1;i<num_points;++i)
{
line->line_to(ar[i].x,ar[i].y);
}
} }
return line; }
}
geometry_ptr read_polygon()
{
geometry_ptr poly(new polygon<vertex2d>);
void read_polygon(Feature & feature)
{
geometry2d * poly = new polygon<vertex2d>;
int num_rings=read_integer(); int num_rings=read_integer();
for (int i=0;i<num_rings;++i) for (int i=0;i<num_rings;++i)
{ {
int num_points=read_integer(); int num_points=read_integer();
CoordinateArray ar(num_points); CoordinateArray ar(num_points);
read_coords(ar); read_coords(ar);
poly->move_to(ar[0].x,ar[0].y); poly->move_to(ar[0].x,ar[0].y);
for (int j=1;j<num_points;++j)
{
poly->line_to(ar[j].x,ar[j].y);
}
poly->line_to(ar[0].x,ar[0].y);
for (int j=1;j<num_points;++j)
{
poly->line_to(ar[j].x,ar[j].y);
}
poly->line_to(ar[0].x,ar[0].y);
} }
return poly; feature.add_geometry(poly);
} }
geometry_ptr read_multipolygon()
{
geometry_ptr poly(new polygon<vertex2d>);
void read_multipolygon(Feature & feature)
{
int num_polys=read_integer(); int num_polys=read_integer();
for (int i=0;i<num_polys;++i) for (int i=0;i<num_polys;++i)
{ {
pos_+=5; pos_+=5;
int num_rings=read_integer(); read_polygon(feature);
for (int i=0;i<num_rings;++i)
{
int num_points=read_integer();
CoordinateArray ar(num_points);
read_coords(ar);
poly->move_to(ar[0].x,ar[0].y);
for (int j=1;j<num_points;++j)
{
poly->line_to(ar[j].x,ar[j].y);
}
poly->line_to(ar[0].x,ar[0].y);
}
} }
return poly; }
} };
};
geometry_ptr geometry_utils::from_wkb(const char* wkb, unsigned size) void geometry_utils::from_wkb(Feature & feature,const char* wkb, unsigned size)
{ {
wkb_reader reader(wkb,size); wkb_reader reader(wkb,size);
return reader.read(); return reader.read(feature);
} }
} }