From b8de6e6f34fab39a6782487bf15062f10769c803 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Mar 2013 20:55:45 -0800 Subject: [PATCH 1/4] no need for an intermediate bbox for rasters --- src/agg/process_markers_symbolizer.cpp | 4 ++-- src/grid/process_markers_symbolizer.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/agg/process_markers_symbolizer.cpp b/src/agg/process_markers_symbolizer.cpp index d001fbbd7..95399857a 100644 --- a/src/agg/process_markers_symbolizer.cpp +++ b/src/agg/process_markers_symbolizer.cpp @@ -192,9 +192,9 @@ void agg_renderer::process(markers_symbolizer const& sym, } else // raster markers { - box2d const& bbox = (*mark)->bounding_box(); - setup_transform_scaling(tr, bbox.width(), bbox.height(), feature, sym); + setup_transform_scaling(tr, (*mark)->width(), (*mark)->height(), feature, sym); evaluate_transform(tr, feature, sym.get_image_transform()); + box2d const& bbox = (*mark)->bounding_box(); coord2d center = bbox.center(); agg::trans_affine_translation recenter(-center.x, -center.y); agg::trans_affine marker_trans = recenter * tr; diff --git a/src/grid/process_markers_symbolizer.cpp b/src/grid/process_markers_symbolizer.cpp index 256a8753f..94cd4cc1f 100644 --- a/src/grid/process_markers_symbolizer.cpp +++ b/src/grid/process_markers_symbolizer.cpp @@ -209,9 +209,9 @@ void grid_renderer::process(markers_symbolizer const& sym, } else // raster markers { - box2d const& bbox = (*mark)->bounding_box(); - setup_transform_scaling(tr, bbox.width(), bbox.height(), feature, sym); + setup_transform_scaling(tr, (*mark)->width(), (*mark)->height(), feature, sym); evaluate_transform(tr, feature, sym.get_image_transform()); + box2d const& bbox = (*mark)->bounding_box(); // - clamp sizes to > 4 pixels of interactivity coord2d center = bbox.center(); agg::trans_affine_translation recenter(-center.x, -center.y); From 210840721f02f6e51aa0ccbce411f3e6ba8c590f Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Mar 2013 21:03:41 -0800 Subject: [PATCH 2/4] set dimensions of svg --- src/marker_cache.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/marker_cache.cpp b/src/marker_cache.cpp index d483d7b47..970e310f3 100644 --- a/src/marker_cache.cpp +++ b/src/marker_cache.cpp @@ -181,6 +181,7 @@ boost::optional marker_cache::find(std::string const& uri, double lox,loy,hix,hiy; svg.bounding_rect(&lox, &loy, &hix, &hiy); marker_path->set_bounding_box(lox,loy,hix,hiy); + marker_path->set_dimensions(svg.width(),svg.height()); marker_ptr mark(boost::make_shared(marker_path)); result.reset(mark); if (update_cache) From a7af47b7305b7d41693980c8e12168e77c14d79b Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sun, 10 Mar 2013 12:56:31 -0700 Subject: [PATCH 3/4] enable snprintf for windows --- src/conversions.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/conversions.cpp b/src/conversions.cpp index efd51f58c..e09a80a7e 100644 --- a/src/conversions.cpp +++ b/src/conversions.cpp @@ -28,6 +28,10 @@ #include +#if _MSC_VER +#define snprintf _snprintf +#endif + #define BOOST_SPIRIT_AUTO(domain_, name, expr) \ typedef boost::proto::result_of:: \ deep_copy::type name##_expr_type; \ From 4bdc5cdc1043498e4b64856e891622c7176b7a56 Mon Sep 17 00:00:00 2001 From: artemp Date: Mon, 11 Mar 2013 09:33:07 +0000 Subject: [PATCH 4/4] + boost.geometry based polygon clipper (NOTE: subject polygons must be 'valid' as in OGC world) --- include/mapnik/polygon_clipper.hpp | 238 +++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 include/mapnik/polygon_clipper.hpp diff --git a/include/mapnik/polygon_clipper.hpp b/include/mapnik/polygon_clipper.hpp new file mode 100644 index 000000000..a5bd6697b --- /dev/null +++ b/include/mapnik/polygon_clipper.hpp @@ -0,0 +1,238 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2013 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MAPNIK_POLYGON_CLIPPER_HPP +#define MAPNIK_POLYGON_CLIPPER_HPP + +// stl +#include +#include + +// mapnik +#include +#include + +// boost +#include +#include +#include +#include +#include +#include +#include + +BOOST_GEOMETRY_REGISTER_POINT_2D(mapnik::coord2d, double, cs::cartesian, x, y) + +// register mapnik::box2d +namespace boost { namespace geometry { namespace traits +{ + +template<> struct tag > { typedef box_tag type; }; + +template<> struct point_type > { typedef mapnik::coord2d type; }; + +template <> +struct indexed_access, min_corner, 0> +{ + typedef coordinate_type::type ct; + static inline ct get(mapnik::box2d const& b) { return b.minx();} + static inline void set(mapnik::box2d &b, ct const& value) { b.set_minx(value); } +}; + +template <> +struct indexed_access, min_corner, 1> +{ + typedef coordinate_type::type ct; + static inline ct get(mapnik::box2d const& b) { return b.miny();} + static inline void set(mapnik::box2d &b, ct const& value) { b.set_miny(value); } +}; + +template <> +struct indexed_access, max_corner, 0> +{ + typedef coordinate_type::type ct; + static inline ct get(mapnik::box2d const& b) { return b.maxx();} + static inline void set(mapnik::box2d &b, ct const& value) { b.set_maxx(value); } +}; + +template <> +struct indexed_access, max_corner, 1> +{ + typedef coordinate_type::type ct; + static inline ct get(mapnik::box2d const& b) { return b.maxy();} + static inline void set(mapnik::box2d &b , ct const& value) { b.set_maxy(value); } +}; + +}}} + +namespace mapnik { + +using namespace boost::geometry; + +template +struct polygon_clipper +{ + typedef mapnik::coord2d point_2d; + typedef model::polygon polygon_2d; + typedef std::deque polygon_list; + + polygon_clipper(Geometry & geom) + : clip_box_(), + geom_(geom) + { + + } + + polygon_clipper( box2d const& clip_box,Geometry & geom) + : clip_box_(clip_box), + geom_(geom) + { + init(); + } + + void set_clip_box(box2d const& clip_box) + { + clip_box_ = clip_box; + init(); + } + + unsigned type() const + { + return geom_.type(); + } + + void rewind(unsigned path_id) + { + output_.rewind(path_id); + } + + unsigned vertex (double * x, double * y) + { + return output_.vertex(x,y); + } + +private: + + void init() + { + polygon_2d subject_poly; + double x,y; + double prev_x, prev_y; + geom_.rewind(0); + unsigned ring_count = 0; + while (true) + { + unsigned cmd = geom_.vertex(&x,&y); + if (cmd == SEG_END) break; + if (cmd == SEG_MOVETO) + { + prev_x = x; + prev_y = y; + if (ring_count == 0) + { + append(subject_poly, make(x,y)); + } + else + { + subject_poly.inners().push_back(polygon_2d::inner_container_type::value_type()); + append(subject_poly.inners().back(),make(x,y)); + } + ++ring_count; + } + else if (cmd == SEG_LINETO) + { + if (std::abs(x - prev_x) < 1e-12 && std::abs(y - prev_y) < 1e-12) + { + std::cerr << std::setprecision(12) << "coincident vertices:(" << prev_x << "," + << prev_y << ") , (" << x << "," << y << ")" << std::endl; + continue; + } + prev_x = x; + prev_x = y; + if (ring_count == 1) + { + append(subject_poly, make(x,y)); + } + else + { + append(subject_poly.inners().back(),make(x,y)); + } + } + } + + polygon_list clipped_polygons; + bool dissolved = false; + try + { + boost::geometry::intersection(clip_box_, subject_poly, clipped_polygons); + } + catch (boost::geometry::exception const& ex) + { + std::cerr << ex.what() << std::endl; + } + + unsigned count=0; + BOOST_FOREACH(polygon_2d const& poly, clipped_polygons) + { + bool move_to = true; + BOOST_FOREACH(point_2d const& c, boost::geometry::exterior_ring(poly)) + { + if (move_to) + { + move_to = false; + output_.move_to(c.x,c.y); + } + else + { + output_.line_to(c.x,c.y); + } + } + output_.close_path(); + // interior rings + BOOST_FOREACH(polygon_2d::inner_container_type::value_type const& ring, boost::geometry::interior_rings(poly)) + { + move_to = true; + BOOST_FOREACH(point_2d const& c, ring) + { + if (move_to) + { + move_to = false; + output_.move_to(c.x,c.y); + } + else + { + output_.line_to(c.x,c.y); + } + } + output_.close_path(); + } + } + } + + box2d clip_box_; + Geometry & geom_; + mapnik::geometry_type output_; + +}; + +} + +#endif //MAPNIK_POLYGON_CLIPPER_HPP