add 'maximum-extent' attribute to map and use this, if set, in place of calculated layer extents in zoom_all()

This commit is contained in:
Dane Springmeyer 2011-04-14 02:20:33 +00:00
parent 6549d090cc
commit 8998296f7b
4 changed files with 130 additions and 83 deletions

View file

@ -14,6 +14,11 @@ For a complete change history, see the SVN log.
Mapnik Trunk Mapnik Trunk
------------ ------------
- Added optional 'maximum-extent' parameter to map object. If set will be used, instead of combined
layer extents, for return value of map.zoom_all(). Useful in cases where the combined layer extents
cannot possibly be projected into the map srs or the user wishes to control map bounds without
modifying the extents of each layer.
- Support for NODATA values with grey and rgb images in GDAL plugin (#727) - Support for NODATA values with grey and rgb images in GDAL plugin (#727)
- Print warning if invalid XML property names are used (#110) - Print warning if invalid XML property names are used (#110)

View file

@ -503,6 +503,15 @@ void export_map()
"<mapnik._mapnik.layer object at 0x5fe130>\n" "<mapnik._mapnik.layer object at 0x5fe130>\n"
) )
.add_property("maximum_extent",make_function
(&Map::maximum_extent,return_value_policy<copy_const_reference>()),
&Map::set_maximum_extent,
"The maximum extent of the map.\n"
"\n"
"Usage:\n"
">>> m.maximum_extent = Box2d(-180,-90,180,90)\n"
)
.add_property("srs", .add_property("srs",
make_function(&Map::srs,return_value_policy<copy_const_reference>()), make_function(&Map::srs,return_value_policy<copy_const_reference>()),
&Map::set_srs, &Map::set_srs,

View file

@ -72,7 +72,7 @@ private:
static const unsigned MAX_MAPSIZE=MIN_MAPSIZE<<10; static const unsigned MAX_MAPSIZE=MIN_MAPSIZE<<10;
unsigned width_; unsigned width_;
unsigned height_; unsigned height_;
std::string srs_; std::string srs_;
int buffer_size_; int buffer_size_;
boost::optional<color> background_; boost::optional<color> background_;
boost::optional<std::string> background_image_; boost::optional<std::string> background_image_;
@ -81,7 +81,8 @@ private:
std::map<std::string,font_set> fontsets_; std::map<std::string,font_set> fontsets_;
std::vector<layer> layers_; std::vector<layer> layers_;
aspect_fix_mode aspectFixMode_; aspect_fix_mode aspectFixMode_;
box2d<double> currentExtent_; box2d<double> current_extent_;
boost::optional<box2d<double> > maximum_extent_;
parameters extra_attr_; parameters extra_attr_;
public: public:
@ -331,6 +332,15 @@ public:
*/ */
int buffer_size() const; int buffer_size() const;
/*! \brief Set the map maximum extent.
* @param box The bounding box for the maximum extent.
*/
void set_maximum_extent(box2d<double>const& box);
/*! \brief Get the map maximum extent as box2d<double>
*/
boost::optional<box2d<double> > const& maximum_extent() const;
/*! \brief Zoom the map at the current position. /*! \brief Zoom the map at the current position.
* @param factor The factor how much the map is zoomed in or out. * @param factor The factor how much the map is zoomed in or out.
*/ */

View file

@ -85,7 +85,8 @@ Map::Map(const Map& rhs)
metawriters_(rhs.metawriters_), metawriters_(rhs.metawriters_),
layers_(rhs.layers_), layers_(rhs.layers_),
aspectFixMode_(rhs.aspectFixMode_), aspectFixMode_(rhs.aspectFixMode_),
currentExtent_(rhs.currentExtent_), current_extent_(rhs.current_extent_),
maximum_extent_(rhs.maximum_extent_),
extra_attr_(rhs.extra_attr_) {} extra_attr_(rhs.extra_attr_) {}
Map& Map::operator=(const Map& rhs) Map& Map::operator=(const Map& rhs)
@ -101,6 +102,7 @@ Map& Map::operator=(const Map& rhs)
metawriters_ = rhs.metawriters_; metawriters_ = rhs.metawriters_;
layers_=rhs.layers_; layers_=rhs.layers_;
aspectFixMode_=rhs.aspectFixMode_; aspectFixMode_=rhs.aspectFixMode_;
maximum_extent_=rhs.maximum_extent_;
extra_attr_=rhs.extra_attr_; extra_attr_=rhs.extra_attr_;
return *this; return *this;
} }
@ -333,12 +335,22 @@ void Map::set_background_image(std::string const& image_filename)
background_image_ = image_filename; background_image_ = image_filename;
} }
void Map::set_maximum_extent(box2d<double> const& box)
{
maximum_extent_ = box;
}
boost::optional<box2d<double> > const& Map::maximum_extent() const
{
return maximum_extent_;
}
void Map::zoom(double factor) void Map::zoom(double factor)
{ {
coord2d center = currentExtent_.center(); coord2d center = current_extent_.center();
double w = factor * currentExtent_.width(); double w = factor * current_extent_.width();
double h = factor * currentExtent_.height(); double h = factor * current_extent_.height();
currentExtent_ = box2d<double>(center.x - 0.5 * w, current_extent_ = box2d<double>(center.x - 0.5 * w,
center.y - 0.5 * h, center.y - 0.5 * h,
center.x + 0.5 * w, center.x + 0.5 * w,
center.y + 0.5 * h); center.y + 0.5 * h);
@ -347,75 +359,86 @@ void Map::zoom(double factor)
void Map::zoom_all() void Map::zoom_all()
{ {
try if (maximum_extent_) {
{ zoom_to_box(*maximum_extent_);
projection proj0(srs_);
box2d<double> ext;
bool first = true;
std::vector<layer>::const_iterator itr = layers_.begin();
std::vector<layer>::const_iterator end = layers_.end();
while (itr != end)
{
if (itr->isActive())
{
std::string const& layer_srs = itr->srs();
projection proj1(layer_srs);
proj_transform prj_trans(proj0,proj1);
box2d<double> layerExt = itr->envelope();
double x0 = layerExt.minx();
double y0 = layerExt.miny();
double z0 = 0.0;
double x1 = layerExt.maxx();
double y1 = layerExt.maxy();
double z1 = 0.0;
prj_trans.backward(x0,y0,z0);
prj_trans.backward(x1,y1,z1);
box2d<double> layerExt2(x0,y0,x1,y1);
#ifdef MAPNIK_DEBUG
std::clog << " layer1 - > " << layerExt << "\n";
std::clog << " layer2 - > " << layerExt2 << "\n";
#endif
if (first)
{
ext = layerExt2;
first = false;
}
else
{
ext.expand_to_include(layerExt2);
}
}
++itr;
}
zoom_to_box(ext);
} }
catch (proj_init_error & ex) else
{ {
std::clog << "proj_init_error:" << ex.what() << '\n'; try
{
projection proj0(srs_);
box2d<double> ext;
bool success = false;
bool first = true;
std::vector<layer>::const_iterator itr = layers_.begin();
std::vector<layer>::const_iterator end = layers_.end();
while (itr != end)
{
if (itr->isActive())
{
std::string const& layer_srs = itr->srs();
projection proj1(layer_srs);
proj_transform prj_trans(proj0,proj1);
box2d<double> layer_ext = itr->envelope();
if (prj_trans.backward(layer_ext))
{
success = true;
#ifdef MAPNIK_DEBUG
std::clog << " layer " << itr->name() << " original ext: " << itr->envelope() << "\n";
std::clog << " layer " << itr->name() << " transformed to map srs: " << layer_ext << "\n";
#endif
if (first)
{
ext = layer_ext;
first = false;
}
else
{
ext.expand_to_include(layer_ext);
}
}
}
++itr;
}
if (success) {
zoom_to_box(ext);
} else {
std::ostringstream s;
s << "could not zoom to combined layer extents "
<< "using zoom_all because proj4 could not "
<< "back project any layer extents into the map srs "
<< "(set map 'maximum-extent' to override)";
throw std::runtime_error(s.str());
}
}
catch (proj_init_error & ex)
{
std::clog << "proj_init_error:" << ex.what() << "\n";
}
} }
} }
void Map::zoom_to_box(const box2d<double> &box) void Map::zoom_to_box(const box2d<double> &box)
{ {
currentExtent_=box; current_extent_=box;
fixAspectRatio(); fixAspectRatio();
} }
void Map::fixAspectRatio() void Map::fixAspectRatio()
{ {
double ratio1 = (double) width_ / (double) height_; double ratio1 = (double) width_ / (double) height_;
double ratio2 = currentExtent_.width() / currentExtent_.height(); double ratio2 = current_extent_.width() / current_extent_.height();
if (ratio1 == ratio2) return; if (ratio1 == ratio2) return;
switch(aspectFixMode_) switch(aspectFixMode_)
{ {
case ADJUST_BBOX_HEIGHT: case ADJUST_BBOX_HEIGHT:
currentExtent_.height(currentExtent_.width() / ratio1); current_extent_.height(current_extent_.width() / ratio1);
break; break;
case ADJUST_BBOX_WIDTH: case ADJUST_BBOX_WIDTH:
currentExtent_.width(currentExtent_.height() * ratio1); current_extent_.width(current_extent_.height() * ratio1);
break; break;
case ADJUST_CANVAS_HEIGHT: case ADJUST_CANVAS_HEIGHT:
height_ = int (width_ / ratio2 + 0.5); height_ = int (width_ / ratio2 + 0.5);
@ -425,15 +448,15 @@ void Map::fixAspectRatio()
break; break;
case GROW_BBOX: case GROW_BBOX:
if (ratio2 > ratio1) if (ratio2 > ratio1)
currentExtent_.height(currentExtent_.width() / ratio1); current_extent_.height(current_extent_.width() / ratio1);
else else
currentExtent_.width(currentExtent_.height() * ratio1); current_extent_.width(current_extent_.height() * ratio1);
break; break;
case SHRINK_BBOX: case SHRINK_BBOX:
if (ratio2 < ratio1) if (ratio2 < ratio1)
currentExtent_.height(currentExtent_.width() / ratio1); current_extent_.height(current_extent_.width() / ratio1);
else else
currentExtent_.width(currentExtent_.height() * ratio1); current_extent_.width(current_extent_.height() * ratio1);
break; break;
case GROW_CANVAS: case GROW_CANVAS:
if (ratio2 > ratio1) if (ratio2 > ratio1)
@ -449,24 +472,24 @@ void Map::fixAspectRatio()
break; break;
default: default:
if (ratio2 > ratio1) if (ratio2 > ratio1)
currentExtent_.height(currentExtent_.width() / ratio1); current_extent_.height(current_extent_.width() / ratio1);
else else
currentExtent_.width(currentExtent_.height() * ratio1); current_extent_.width(current_extent_.height() * ratio1);
break; break;
} }
} }
const box2d<double>& Map::get_current_extent() const const box2d<double>& Map::get_current_extent() const
{ {
return currentExtent_; return current_extent_;
} }
box2d<double> Map::get_buffered_extent() const box2d<double> Map::get_buffered_extent() const
{ {
double extra = 2.0 * scale() * buffer_size_; double extra = 2.0 * scale() * buffer_size_;
box2d<double> ext(currentExtent_); box2d<double> ext(current_extent_);
ext.width(currentExtent_.width() + extra); ext.width(current_extent_.width() + extra);
ext.height(currentExtent_.height() + extra); ext.height(current_extent_.height() + extra);
return ext; return ext;
} }
@ -474,12 +497,12 @@ void Map::pan(int x,int y)
{ {
int dx = x - int(0.5 * width_); int dx = x - int(0.5 * width_);
int dy = int(0.5 * height_) - y; int dy = int(0.5 * height_) - y;
double s = width_/currentExtent_.width(); double s = width_/current_extent_.width();
double minx = currentExtent_.minx() + dx/s; double minx = current_extent_.minx() + dx/s;
double maxx = currentExtent_.maxx() + dx/s; double maxx = current_extent_.maxx() + dx/s;
double miny = currentExtent_.miny() + dy/s; double miny = current_extent_.miny() + dy/s;
double maxy = currentExtent_.maxy() + dy/s; double maxy = current_extent_.maxy() + dy/s;
currentExtent_.init(minx,miny,maxx,maxy); current_extent_.init(minx,miny,maxx,maxy);
} }
void Map::pan_and_zoom(int x,int y,double factor) void Map::pan_and_zoom(int x,int y,double factor)
@ -491,8 +514,8 @@ void Map::pan_and_zoom(int x,int y,double factor)
double Map::scale() const double Map::scale() const
{ {
if (width_>0) if (width_>0)
return currentExtent_.width()/width_; return current_extent_.width()/width_;
return currentExtent_.width(); return current_extent_.width();
} }
double Map::scale_denominator() const double Map::scale_denominator() const
@ -503,7 +526,7 @@ double Map::scale_denominator() const
CoordTransform Map::view_transform() const CoordTransform Map::view_transform() const
{ {
return CoordTransform(width_,height_,currentExtent_); return CoordTransform(width_,height_,current_extent_);
} }
featureset_ptr Map::query_point(unsigned index, double x, double y) const featureset_ptr Map::query_point(unsigned index, double x, double y) const
@ -519,10 +542,10 @@ featureset_ptr Map::query_point(unsigned index, double x, double y) const
proj_transform prj_trans(source,dest); proj_transform prj_trans(source,dest);
prj_trans.backward(x,y,z); prj_trans.backward(x,y,z);
double minx = currentExtent_.minx(); double minx = current_extent_.minx();
double miny = currentExtent_.miny(); double miny = current_extent_.miny();
double maxx = currentExtent_.maxx(); double maxx = current_extent_.maxx();
double maxy = currentExtent_.maxy(); double maxy = current_extent_.maxy();
prj_trans.backward(minx,miny,z); prj_trans.backward(minx,miny,z);
prj_trans.backward(maxx,maxy,z); prj_trans.backward(maxx,maxy,z);
@ -564,10 +587,10 @@ featureset_ptr Map::query_map_point(unsigned index, double x, double y) const
double z = 0; double z = 0;
prj_trans.backward(x,y,z); prj_trans.backward(x,y,z);
double minx = currentExtent_.minx(); double minx = current_extent_.minx();
double miny = currentExtent_.miny(); double miny = current_extent_.miny();
double maxx = currentExtent_.maxx(); double maxx = current_extent_.maxx();
double maxy = currentExtent_.maxy(); double maxy = current_extent_.maxy();
prj_trans.backward(minx,miny,z); prj_trans.backward(minx,miny,z);
prj_trans.backward(maxx,maxy,z); prj_trans.backward(maxx,maxy,z);