diff --git a/bindings/python/mapnik_datasource.cpp b/bindings/python/mapnik_datasource.cpp index 5263a35b4..44f3ca17c 100644 --- a/bindings/python/mapnik_datasource.cpp +++ b/bindings/python/mapnik_datasource.cpp @@ -27,7 +27,6 @@ #include // mapnik #include -#include #include #include #include @@ -69,38 +68,11 @@ namespace } } -inline object pass_through(object const& o) { return o; } - -inline mapnik::feature_ptr next(mapnik::featureset_ptr const& itr) -{ - mapnik::feature_ptr f = itr->next(); - if (!f) - { - PyErr_SetString(PyExc_StopIteration, "No more features."); - boost::python::throw_error_already_set(); - } - return f; -} - void export_datasource() { using namespace boost::python; using mapnik::datasource; - using mapnik::Featureset; - using mapnik::Feature; - - class_, - boost::noncopyable>("Feature",no_init) - .def("id",&Feature::id) - .def("__str__",&Feature::to_string) - ; - - class_, - boost::noncopyable>("Datasource",no_init) - .def("next",next) - .def("__iter__",pass_through) - ; - + class_, boost::noncopyable>("Datasource",no_init) .def("envelope",&datasource::envelope) diff --git a/bindings/python/mapnik_feature.cpp b/bindings/python/mapnik_feature.cpp new file mode 100644 index 000000000..370e1846c --- /dev/null +++ b/bindings/python/mapnik_feature.cpp @@ -0,0 +1,39 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ +//$Id$ + +// boost +#include +// mapnik +#include + +void export_feature() +{ + using namespace boost::python; + using mapnik::Feature; + class_, + boost::noncopyable>("Feature",no_init) + .def("id",&Feature::id) + //.def("__iter__", range<>()) + .def("__str__",&Feature::to_string) + ; +} diff --git a/bindings/python/mapnik_featureset.cpp b/bindings/python/mapnik_featureset.cpp new file mode 100644 index 000000000..ddd330a9f --- /dev/null +++ b/bindings/python/mapnik_featureset.cpp @@ -0,0 +1,58 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ +//$Id$ + +// boost +#include +// mapnik +#include +#include + +namespace { + using namespace boost::python; + inline object pass_through(object const& o) { return o; } + + inline mapnik::feature_ptr next(mapnik::featureset_ptr const& itr) + { + mapnik::feature_ptr f = itr->next(); + if (!f) + { + PyErr_SetString(PyExc_StopIteration, "No more features."); + boost::python::throw_error_already_set(); + } + return f; + } +} + +void export_featureset() +{ + using namespace boost::python; + using mapnik::Feature; + using mapnik::Featureset; + + class_, + boost::noncopyable>("Featureset",no_init) + .def("next",next) + .def("__iter__",pass_through) + ; +} + diff --git a/bindings/python/mapnik_map.cpp b/bindings/python/mapnik_map.cpp index fe1a8eab3..a78c09015 100644 --- a/bindings/python/mapnik_map.cpp +++ b/bindings/python/mapnik_map.cpp @@ -110,6 +110,7 @@ void export_map() .def("pan_and_zoom",&Map::pan_and_zoom) .def("append_style",&Map::insert_style) .def("remove_style",&Map::remove_style) + .def("query_map_point",&Map::query_map_point) .add_property("layers",make_function (layers_nonconst,return_value_policy()), "Get the list of layers in this map.") diff --git a/bindings/python/mapnik_python.cpp b/bindings/python/mapnik_python.cpp index 72e026002..0c6b7c7dc 100644 --- a/bindings/python/mapnik_python.cpp +++ b/bindings/python/mapnik_python.cpp @@ -39,6 +39,8 @@ void export_filter(); void export_rule(); void export_style(); void export_stroke(); +void export_feature(); +void export_featureset(); void export_datasource(); void export_datasource_cache(); void export_point_symbolizer(); @@ -97,6 +99,8 @@ BOOST_PYTHON_MODULE(_mapnik) using mapnik::save_map; export_query(); + export_feature(); + export_featureset(); export_datasource(); export_parameters(); export_color(); @@ -124,6 +128,7 @@ BOOST_PYTHON_MODULE(_mapnik) def("render_to_file",&render_to_file); def("render_tile_to_file",&render_tile_to_file); + def("render",&render); def("render",&render2); def("load_map",&load_map,"load Map object from XML"); diff --git a/include/mapnik/feature.hpp b/include/mapnik/feature.hpp index 58d758141..b1e99234c 100644 --- a/include/mapnik/feature.hpp +++ b/include/mapnik/feature.hpp @@ -48,12 +48,14 @@ namespace mapnik { public: typedef T1 geometry_type; typedef T2 raster_type; + private: int id_; geometry_type geom_; raster_type raster_; std::map props_; public: + typedef std::map::iterator iterator; explicit feature(int id) : properties(props_), id_(id), @@ -70,7 +72,7 @@ namespace mapnik { { return id_; } - + void set_geometry(geometry_type& geom) { geom_=geom; @@ -94,7 +96,17 @@ namespace mapnik { { return props_; } - + + iterator begin() const + { + return props_.begin(); + } + + iterator end() const + { + return props_.end(); + } + std::string to_string() const { std::stringstream ss; diff --git a/include/mapnik/filter_featureset.hpp b/include/mapnik/filter_featureset.hpp new file mode 100644 index 000000000..8531eda9f --- /dev/null +++ b/include/mapnik/filter_featureset.hpp @@ -0,0 +1,52 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2006 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +//$Id$ + +#include + +namespace mapnik { + + template + class filter_featureset : public Featureset + { + typedef T filter_type; + + public: + filter_featureset(featureset_ptr fs, filter_type const& filter) + : fs_(fs), filter_(filter) {} + + feature_ptr next() + { + feature_ptr feature = fs_->next(); + while (feature && !filter_.pass(*feature)) + { + feature = fs_->next(); + } + return feature; + } + + private: + featureset_ptr fs_; + filter_type filter_; + }; +} diff --git a/include/mapnik/hit_test_filter.hpp b/include/mapnik/hit_test_filter.hpp new file mode 100644 index 000000000..cc4e64f81 --- /dev/null +++ b/include/mapnik/hit_test_filter.hpp @@ -0,0 +1,54 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2006 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +//$Id$ + +#ifndef HIT_TEST_FILTER_HPP +#define HIT_TEST_FILTER_HPP + +#include + +namespace mapnik { + class hit_test_filter + { + public: + hit_test_filter(double x, double y, double tol) + : x_(x), + y_(y), + tol_(tol) {} + + bool pass(Feature const& feature) + { + geometry_ptr geom = feature.get_geometry(); + if (geom && geom->hit_test(x_,y_,tol_)) + return true; + return false; + } + + private: + double x_; + double y_; + double tol_; + }; +} + +#endif // HIT_TEST_FILTER_HPP diff --git a/include/mapnik/map.hpp b/include/mapnik/map.hpp index 05084f11b..c84f65def 100644 --- a/include/mapnik/map.hpp +++ b/include/mapnik/map.hpp @@ -25,6 +25,7 @@ #define MAP_HPP #include +#include namespace mapnik { @@ -79,6 +80,7 @@ namespace mapnik const Envelope& getCurrentExtent() const; double scale() const; CoordTransform view_transform() const; + featureset_ptr query_map_point(unsigned index, double x, double y) const; ~Map(); private: void fixAspectRatio(); diff --git a/include/mapnik/memory_datasource.hpp b/include/mapnik/memory_datasource.hpp new file mode 100644 index 000000000..576f09b2a --- /dev/null +++ b/include/mapnik/memory_datasource.hpp @@ -0,0 +1,51 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2006 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +//$Id$ + +#ifndef MEMORY_DATASOURCE_HPP +#define MEMORY_DATASOURCE_HPP + +#include +#include + +namespace mapnik { + + class memory_datasource : public datasource + { + friend class memory_featureset; + public: + memory_datasource(); + virtual ~memory_datasource(); + void push(feature_ptr feature); + int type() const; + featureset_ptr features(const query& q) const; + featureset_ptr features_at_point(coord2d const& pt) const; + Envelope envelope() const; + layer_descriptor get_descriptor() const; + size_t size() const; + private: + std::vector features_; + }; +} + +#endif // MEMORY_DATASOURCE_HPP diff --git a/include/mapnik/memory_featureset.hpp b/include/mapnik/memory_featureset.hpp new file mode 100644 index 000000000..1673506b3 --- /dev/null +++ b/include/mapnik/memory_featureset.hpp @@ -0,0 +1,63 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2006 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +//$Id$ +#ifndef MEMORY_FEATURESET_HPP +#define MEMORY_FEATURESET_HPP + +#include +#include + +namespace mapnik { + + class memory_featureset : public Featureset, private boost::noncopyable + { + public: + memory_featureset(Envelope const& bbox, memory_datasource const& ds) + : bbox_(bbox), + pos_(ds.features_.begin()), + end_(ds.features_.end()) + {} + virtual ~memory_featureset() {} + + feature_ptr next() + { + while (pos_ != end_) + { + geometry_ptr geom = (*pos_)->get_geometry(); + if (geom && bbox_.intersects(geom->envelope())) + { + return *pos_++; + } + ++pos_; + } + return feature_ptr(); + } + + private: + Envelope const& bbox_; + std::vector::const_iterator pos_; + std::vector::const_iterator end_; + }; +} + +#endif // MEMORY_FEATURESET_HPP diff --git a/src/SConscript b/src/SConscript index d4c4a78ba..c20b17231 100644 --- a/src/SConscript +++ b/src/SConscript @@ -60,6 +60,7 @@ source = Split( proj_transform.cpp distance.cpp scale_denominator.cpp + memory_datasource.cpp """ ) source += Split( diff --git a/src/map.cpp b/src/map.cpp index cda87fe21..ff525880c 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include namespace mapnik @@ -305,6 +307,52 @@ namespace mapnik { return CoordTransform(width_,height_,currentExtent_); } - + + featureset_ptr Map::query_map_point(unsigned index, double x, double y) const + { + if ( index< layers_.size()) + { + mapnik::Layer const& layer = layers_[index]; + CoordTransform tr = view_transform(); + tr.backward(&x,&y); + + try + { + mapnik::projection dest(srs_); + mapnik::projection source(layer.srs()); + proj_transform prj_trans(source,dest); + double z; + prj_trans.backward(x,y,z); + + double minx = currentExtent_.minx(); + double miny = currentExtent_.miny(); + double maxx = currentExtent_.maxx(); + double maxy = currentExtent_.maxy(); + + prj_trans.backward(minx,miny,z); + prj_trans.backward(maxx,maxy,z); + double tol = (maxx - minx) / width_ * 3; + mapnik::datasource_ptr ds = layer.datasource(); + if (ds) + { +#ifdef MAPNIK_DEBUG + std::clog << " query at point tol = " << tol << " (" << x << "," << y << ")\n"; +#endif + + featureset_ptr fs(new filter_featureset(ds->features_at_point(mapnik::coord2d(x,y)), + hit_test_filter(x,y,tol))); + return fs; + } + } + catch (...) + { +#ifdef MAPNIK_DEBUG + std::clog << "exception caught in \"query_map_point\"\n"; +#endif + } + } + return featureset_ptr(); + } + Map::~Map() {} } diff --git a/src/memory_datasource.cpp b/src/memory_datasource.cpp new file mode 100644 index 000000000..9da51aa66 --- /dev/null +++ b/src/memory_datasource.cpp @@ -0,0 +1,95 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2006 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +//$Id$ +#include +#include + +namespace mapnik { + + struct accumulate_extent + { + accumulate_extent(Envelope & ext) + : ext_(ext),first_(true) {} + + void operator() (feature_ptr feat) + { + geometry_ptr geom = feat->get_geometry(); + if ( !geom ) return; + if ( first_ ) + { + first_ = false; + ext_ = geom->envelope(); + } + else + { + ext_.expand_to_include(geom->envelope()); + } + } + + Envelope & ext_; + bool first_; + }; + + memory_datasource::memory_datasource() + : datasource(parameters()) {} + memory_datasource::~memory_datasource() {} + + void memory_datasource::push(feature_ptr feature) + { + features_.push_back(feature); + } + + int memory_datasource::type() const + { + return datasource::Vector; + } + + featureset_ptr memory_datasource::features(const query& q) const + { + return featureset_ptr(new memory_featureset(q.get_bbox(),*this)); + } + + + featureset_ptr memory_datasource::features_at_point(coord2d const& pt) const + { + return featureset_ptr(); + } + + Envelope memory_datasource::envelope() const + { + Envelope ext; + accumulate_extent func(ext); + std::for_each(features_.begin(),features_.end(),func); + return ext; + } + + layer_descriptor memory_datasource::get_descriptor() const + { + return layer_descriptor("in-memory datasource"); + } + + size_t memory_datasource::size() const + { + return features_.size(); + } +}