Reduce merge conflicts with master

This commit is contained in:
Dane Springmeyer 2016-01-11 16:23:04 -08:00
commit 488af4055d
49 changed files with 2676 additions and 1663 deletions

View file

@ -83,7 +83,7 @@ script:
- if [[ ${COVERAGE} != true ]]; then
make bench;
fi
- if [[ ${TEST_RESULT} != 0 ]]; then exit $TEST_RESULT ; fi;
- if [[ ${TEST_RESULT:-0} != 0 ]]; then exit $TEST_RESULT ; fi;
- if [[ ${MASON_PUBLISH} == true ]]; then
./mason_latest.sh build;
./mason_latest.sh link;

View file

@ -294,6 +294,7 @@ opts.AddVariables(
# Note: setting DEBUG=True will override any custom OPTIMIZATION level
BoolVariable('DEBUG', 'Compile a debug version of Mapnik', 'False'),
BoolVariable('DEBUG_UNDEFINED', 'Compile a version of Mapnik using clang/llvm undefined behavior asserts', 'False'),
BoolVariable('DEBUG_SANITIZE', 'Compile a version of Mapnik using clang/llvm address sanitation', 'False'),
ListVariable('INPUT_PLUGINS','Input drivers to include',DEFAULT_PLUGINS,PLUGINS.keys()),
('WARNING_CXXFLAGS', 'Compiler flags you can set to reduce warning levels which are placed after -Wall.', ''),
@ -1799,6 +1800,11 @@ if not preconfigured:
if env['DEBUG_UNDEFINED']:
env.Append(CXXFLAGS = '-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -ftrapv -fwrapv')
if env['DEBUG_SANITIZE']:
env.Append(CXXFLAGS = ['-fsanitize=address'])
env.Append(LINKFLAGS = ['-fsanitize=address'])
# if requested, sort LIBPATH and CPPPATH one last time before saving...
if env['PRIORITIZE_LINKING']:
conf.prioritize_paths(silent=True)

View file

@ -90,16 +90,16 @@ struct evaluate
return geom.value<value_type,feature_type>(feature_);
}
value_type operator() (binary_node<tags::logical_and> const & x) const
value_type operator() (binary_node<tags::logical_and> const& x) const
{
return (util::apply_visitor(*this, x.left).to_bool())
&& (util::apply_visitor(*this, x.right).to_bool());
}
value_type operator() (binary_node<tags::logical_or> const & x) const
value_type operator() (binary_node<tags::logical_or> const& x) const
{
return (util::apply_visitor(*this,x.left).to_bool())
|| (util::apply_visitor(*this,x.right).to_bool());
return (util::apply_visitor(*this, x.left).to_bool())
|| (util::apply_visitor(*this, x.right).to_bool());
}
template <typename Tag>

View file

@ -41,7 +41,7 @@ struct geometry_envelope
{
return mapnik::util::apply_visitor(*this, geom);
}
void operator() (mapnik::geometry::geometry_empty const&) const {}
template <typename T>
@ -60,30 +60,36 @@ struct geometry_envelope
bool first = true;
for (auto const& pt : line)
{
if (first && !bbox.valid())
if (first && !bbox.valid())
{
bbox.init(pt.x, pt.y, pt.x, pt.y);
first = false;
}
else
else
{
bbox.expand_to_include(pt.x, pt.y);
}
}
}
template <typename T>
void operator() (mapnik::geometry::linear_ring<T> const& ring) const
{
(*this)(static_cast<mapnik::geometry::line_string<T> const&>(ring));
}
template <typename T>
void operator() (mapnik::geometry::polygon<T> const& poly) const
{
bool first = true;
for (auto const& pt : poly.exterior_ring)
{
if (first && !bbox.valid())
if (first && !bbox.valid())
{
bbox.init(pt.x, pt.y, pt.x, pt.y);
first = false;
}
else
else
{
bbox.expand_to_include(pt.x, pt.y);
}
@ -96,12 +102,12 @@ struct geometry_envelope
bool first = true;
for (auto const& pt : multi_point)
{
if (first && !bbox.valid())
if (first && !bbox.valid())
{
bbox.init(pt.x, pt.y, pt.x, pt.y);
first = false;
}
else
else
{
bbox.expand_to_include(pt.x, pt.y);
}
@ -140,7 +146,7 @@ struct geometry_envelope
template <typename T>
mapnik::box2d<double> envelope(T const& geom)
{
{
box2d<double> bbox;
detail::geometry_envelope op(bbox);
op(geom);
@ -149,4 +155,3 @@ mapnik::box2d<double> envelope(T const& geom)
} // end ns geometry
} // end ns mapnik

View file

@ -36,7 +36,7 @@ geometry_empty reproject_internal(geometry_empty const&, proj_transform const&,
}
template <typename T>
point<T> reproject_internal(point<T> const & p, proj_transform const& proj_trans, unsigned int & n_err)
point<T> reproject_internal(point<T> const& p, proj_transform const& proj_trans, unsigned int & n_err)
{
point<T> new_p(p);
if (!proj_trans.forward(new_p))
@ -47,7 +47,7 @@ point<T> reproject_internal(point<T> const & p, proj_transform const& proj_trans
}
template <typename T>
line_string<T> reproject_internal(line_string<T> const & ls, proj_transform const& proj_trans, unsigned int & n_err)
line_string<T> reproject_internal(line_string<T> const& ls, proj_transform const& proj_trans, unsigned int & n_err)
{
line_string<T> new_ls(ls);
unsigned int err = proj_trans.forward(new_ls);
@ -59,7 +59,7 @@ line_string<T> reproject_internal(line_string<T> const & ls, proj_transform cons
}
template <typename T>
polygon<T> reproject_internal(polygon<T> const & poly, proj_transform const& proj_trans, unsigned int & n_err)
polygon<T> reproject_internal(polygon<T> const& poly, proj_transform const& proj_trans, unsigned int & n_err)
{
polygon<T> new_poly;
linear_ring<T> new_ext(poly.exterior_ring);
@ -171,7 +171,8 @@ geometry_collection<T> reproject_internal(geometry_collection<T> const & c, proj
}
template <typename T>
struct geom_reproj_copy_visitor {
struct geom_reproj_copy_visitor
{
geom_reproj_copy_visitor(proj_transform const & proj_trans, unsigned int & n_err)
: proj_trans_(proj_trans),

View file

@ -1,82 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 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_GEOMETRY_UNIQUE_HPP
#define MAPNIK_GEOMETRY_UNIQUE_HPP
#include <mapnik/geometry.hpp>
#include <mapnik/geometry_adapters.hpp>
#include <boost/geometry/algorithms/unique.hpp>
#include <type_traits>
namespace mapnik { namespace geometry {
namespace detail {
struct geometry_unique
{
using result_type = void;
result_type operator() (geometry & geom) const
{
mapnik::util::apply_visitor(*this, geom);
}
result_type operator() (geometry_collection & collection) const
{
for (auto & geom : collection)
{
(*this)(geom);
}
}
result_type operator() (line_string & line) const
{
boost::geometry::unique(line);
}
result_type operator() (polygon & poly) const
{
boost::geometry::unique(poly);
}
template <typename T>
result_type operator() (T & geom) const
{
// no-op
}
};
}
template <typename GeomType>
inline void unique(GeomType & geom)
{
static_assert(!std::is_const<GeomType>::value,"mapnik::geometry::unique on const& is invalid");
detail::geometry_unique()(geom);
}
}}
#endif // MAPNIK_GEOMETRY_UNIQUE_HPP

View file

@ -23,16 +23,17 @@
#ifndef MAPNIK_IMAGE_FILITER_GRAMMAR_HPP
#define MAPNIK_IMAGE_FILITER_GRAMMAR_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/css_color_grammar.hpp>
#include <mapnik/color.hpp>
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/css_color_grammar.hpp>
#include <mapnik/color.hpp>
// stl
#include <cmath>

View file

@ -25,6 +25,7 @@
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/image.hpp>
#include <mapnik/pixel_types.hpp>
//stl

View file

@ -24,7 +24,9 @@
#define MAPNIK_IMAGE_SCALING_TRAITS_HPP
// mapnik
#include <mapnik/span_image_filter.h>
#include <mapnik/image.hpp>
#include <mapnik/image_scaling.hpp>
#include <mapnik/span_image_filter.hpp>
// agg
#include "agg_image_accessors.h"

View file

@ -23,6 +23,8 @@
#ifndef MAPNIK_IMAGE_UTIL_JPEG_HPP
#define MAPNIK_IMAGE_UTIL_JPEG_HPP
#include <mapnik/config.hpp>
// stl
#include <string>
#include <iostream>

View file

@ -23,6 +23,8 @@
#ifndef MAPNIK_IMAGE_UTIL_PNG_HPP
#define MAPNIK_IMAGE_UTIL_PNG_HPP
#include <mapnik/palette.hpp>
// stl
#include <string>
#include <iostream>

View file

@ -23,7 +23,7 @@
#ifndef MAPNIK_IMAGE_VIEW_NULL_HPP
#define MAPNIK_IMAGE_VIEW_NULL_HPP
#include <mapnik/image.hpp>
#include <mapnik/image_view.hpp>
//stl
#include <stdexcept>

View file

@ -63,10 +63,10 @@ struct set_position_impl
struct push_position_impl
{
using result_type = void;
template <typename T0,typename T1>
template <typename T0, typename T1>
result_type operator() (T0 & coords, T1 const& pos) const
{
if (pos) coords.push_back(*pos);
if (pos) coords.emplace_back(*pos);
}
};

View file

@ -28,8 +28,8 @@
#include <mapnik/util/singleton.hpp>
#include <mapnik/util/noncopyable.hpp>
// boost
#include <memory>
#include <string>
#include <unordered_map>
#include <boost/optional.hpp>

View file

@ -179,12 +179,7 @@ public:
"Values stored in quad-tree must be standard layout types to allow serialisation");
char header[16];
std::memset(header,0,16);
header[0]='m';
header[1]='a';
header[2]='p';
header[3]='n';
header[4]='i';
header[5]='k';
std::strcpy(header,"mapnik-index");
out.write(header,16);
write_node(out,root_);
}

View file

@ -26,6 +26,8 @@
#include "agg_span_image_filter_gray.h"
#include "agg_span_image_filter_rgba.h"
#include <boost/optional.hpp>
#include <limits>
namespace mapnik

View file

@ -79,8 +79,7 @@ struct path_attributes
even_odd_flag(false),
visibility_flag(true),
display_flag(true)
{
}
{}
// Copy constructor
path_attributes(path_attributes const& attr)

View file

@ -73,46 +73,29 @@ namespace mapnik { namespace svg {
>> *(-lit(',') >> coord [ line_to_(_1,_a) ] ); // *line_to
H = (lit('H')[_a = false] | lit('h')[_a = true])
>> +double_[ hline_to_(_1,_a) ] ; // +hline_to
>> (double_[ hline_to_(_1,_a) ] % -lit(',')) ; // +hline_to
V = (lit('V')[_a = false] | lit('v')[_a = true])
>> +double_ [ vline_to_(_1,_a) ]; // +vline_to
>> (double_ [ vline_to_(_1,_a) ] % -lit(',')); // +vline_to
L = (lit('L')[_a = false] | lit('l')[_a = true])
>> +coord [ line_to_(_1,_a) ]; // +line_to
>> (coord [ line_to_(_1,_a) ] % -lit(',')); // +line_to
C = (lit('C')[_a = false] | lit('c')[_a = true])
>> +(coord
>> -lit(',')
>> coord
>> -lit(',')
>> coord) [ curve4_(_1,_2,_3,_a) ]; // +curve4
>> ((coord >> -lit(',') >> coord >> -lit(',') >> coord) [ curve4_(_1,_2,_3,_a) ] % -lit(',')); // +curve4
S = (lit('S')[_a = false] | lit('s')[_a = true])
>> +(coord
>> -lit(',')
>> coord) [ curve4_smooth_(_1,_2,_a) ]; // +curve4_smooth (smooth curveto)
>> ((coord >> -lit(',') >> coord) [ curve4_smooth_(_1,_2,_a) ] % -lit(',')); // +curve4_smooth (smooth curveto)
Q = (lit('Q')[_a = false] | lit('q')[_a = true])
>> +(coord
>> -lit(',')
>> coord) [ curve3_(_1,_2,_a) ]; // +curve3 (quadratic-bezier-curveto)
>> ((coord >> -lit(',') >> coord) [ curve3_(_1,_2,_a) ] % -lit(',')); // +curve3 (quadratic-bezier-curveto)
T = (lit('T')[_a = false] | lit('t')[_a = true])
>> +(coord ) [ curve3_smooth_(_1,_a) ]; // +curve3_smooth (smooth-quadratic-bezier-curveto)
>> ((coord ) [ curve3_smooth_(_1,_a) ] % -lit(',')); // +curve3_smooth (smooth-quadratic-bezier-curveto)
A = (lit('A')[_a = false] | lit('a')[_a = true])
>> +(coord
>> -lit(',')
>> double_
>> -lit(',')
>> int_
>> -lit(',')
>> int_
>> -lit(',')
>> coord) [arc_to_(_1,_2,_3,_4,_5,_a)]; // arc_to;
>> ((coord >> -lit(',') >> double_ >> -lit(',')
>> int_ >> -lit(',') >> int_ >> -lit(',') >> coord) [arc_to_(_1,_2,_3,_4,_5,_a)] % -lit(',')); // arc_to;
Z = no_case[lit('z')] [close_()]; // close path

View file

@ -60,12 +60,10 @@
namespace mapnik {
namespace svg {
// Arbitrary linear gradient specified by two control points. Gradient
// value is taken as the normalised distance along the line segment
// represented by the two points.
/**
* Arbitrary linear gradient specified by two control points. Gradient
* value is taken as the normalised distance along the line segment
* represented by the two points.
*/
class linear_gradient_from_segment
{
public:
@ -105,14 +103,14 @@ template <typename VertexSource, typename AttributeSource, typename ScanlineRend
class svg_renderer_agg : util::noncopyable
{
public:
using curved_type = agg::conv_curve<VertexSource> ;
using curved_stroked_type = agg::conv_stroke<curved_type> ;
using curved_type = agg::conv_curve<VertexSource>;
using curved_stroked_type = agg::conv_stroke<curved_type>;
using curved_stroked_trans_type = agg::conv_transform<curved_stroked_type>;
using curved_trans_type = agg::conv_transform<curved_type> ;
using curved_trans_contour_type = agg::conv_contour<curved_trans_type> ;
using renderer_base = agg::renderer_base<PixelFormat> ;
using vertex_source_type = VertexSource ;
using attribute_source_type = AttributeSource ;
using curved_trans_type = agg::conv_transform<curved_type>;
using curved_trans_contour_type = agg::conv_contour<curved_trans_type>;
using renderer_base = agg::renderer_base<PixelFormat>;
using vertex_source_type = VertexSource;
using attribute_source_type = AttributeSource;
svg_renderer_agg(VertexSource & source, AttributeSource const& attributes)
: source_(source),
@ -191,11 +189,11 @@ public:
// scale everything up since agg turns things into integers a bit too soon
int scaleup=255;
radius*=scaleup;
x1*=scaleup;
y1*=scaleup;
x2*=scaleup;
y2*=scaleup;
radius *= scaleup;
x1 *= scaleup;
y1 *= scaleup;
x2 *= scaleup;
y2 *= scaleup;
transform.scale(scaleup,scaleup);
interpolator_type span_interpolator(transform);
@ -217,10 +215,10 @@ public:
color_func_type>;
// scale everything up since agg turns things into integers a bit too soon
int scaleup=255;
x1*=scaleup;
y1*=scaleup;
x2*=scaleup;
y2*=scaleup;
x1 *= scaleup;
y1 *= scaleup;
x2 *= scaleup;
y2 *= scaleup;
transform.scale(scaleup,scaleup);
@ -288,7 +286,8 @@ public:
if(attr.fill_gradient.get_gradient_type() != NO_GRADIENT)
{
render_gradient(ras, sl, ren, attr.fill_gradient, transform, attr.fill_opacity * attr.opacity * opacity, symbol_bbox, curved_trans, attr.index);
render_gradient(ras, sl, ren, attr.fill_gradient, transform,
attr.fill_opacity * attr.opacity * opacity, symbol_bbox, curved_trans, attr.index);
}
else
{
@ -324,7 +323,8 @@ public:
if(attr.stroke_gradient.get_gradient_type() != NO_GRADIENT)
{
render_gradient(ras, sl, ren, attr.stroke_gradient, transform, attr.stroke_opacity * attr.opacity * opacity, symbol_bbox, curved_trans, attr.index);
render_gradient(ras, sl, ren, attr.stroke_gradient, transform,
attr.stroke_opacity * attr.opacity * opacity, symbol_bbox, curved_trans, attr.index);
}
else
{

View file

@ -317,12 +317,8 @@ struct evaluate_expression_wrapper<mapnik::dash_array>
mapnik::value_type val = util::apply_visitor(mapnik::evaluate<T2,mapnik::value_type,T3>(feature,vars), expr);
if (val.is_null()) return dash_array();
dash_array dash;
std::vector<double> buf;
std::string str = val.to_string();
if (util::parse_dasharray(str,buf))
{
util::add_dashes(buf,dash);
}
util::parse_dasharray(str,dash);
return dash;
}
};

View file

@ -24,7 +24,12 @@
#define MAPNIK_SYMBOLIZER_DEFAULT_VALUES_HPP
#include <mapnik/symbolizer_keys.hpp>
#include <mapnik/symbolizer_enumerations.hpp>
#include <mapnik/image_compositing.hpp>
#include <mapnik/image_scaling.hpp>
#include <mapnik/simplify.hpp>
#include <mapnik/color.hpp>
#include <mapnik/value_types.hpp>
#include <type_traits>

View file

@ -404,9 +404,8 @@ struct set_symbolizer_property_impl<Symbolizer,dash_array,false>
boost::optional<std::string> str = node.get_opt_attr<std::string>(name);
if (str)
{
std::vector<double> buf;
dash_array dash;
if (util::parse_dasharray(*str,buf) && util::add_dashes(buf,dash))
if (util::parse_dasharray(*str,dash))
{
put(sym,key,dash);
}

View file

@ -23,32 +23,13 @@
#ifndef MAPNIK_UTIL_DASHARRAY_PARSER_HPP
#define MAPNIK_UTIL_DASHARRAY_PARSER_HPP
#include <mapnik/symbolizer_base.hpp>
#include <vector>
#include <string>
namespace mapnik { namespace util {
bool parse_dasharray(std::string const& value, std::vector<double>& dasharray);
inline bool add_dashes(std::vector<double> & buf, std::vector<std::pair<double,double> > & dash)
{
if (buf.empty()) return false;
size_t size = buf.size();
if (size % 2 == 1)
{
buf.insert(buf.end(),buf.begin(),buf.end());
}
std::vector<double>::const_iterator pos = buf.begin();
while (pos != buf.end())
{
if (*pos > 0.0 || *(pos+1) > 0.0) // avoid both dash and gap eq 0.0
{
dash.emplace_back(*pos,*(pos + 1));
}
pos +=2;
}
return !buf.empty();
}
bool parse_dasharray(std::string const& value, dash_array & dash);
}}

View file

@ -30,6 +30,7 @@
#include <mapnik/geom_util.hpp>
// stl
#include <type_traits>
#include <cstring>
using mapnik::box2d;
using mapnik::query;
@ -44,7 +45,6 @@ public:
static box2d<double> bounding_box( InputStream& in );
static void query_first_n(Filter const& filter, InputStream & in, std::vector<Value>& pos, std::size_t count);
private:
spatial_index();
~spatial_index();
spatial_index(spatial_index const&);
@ -53,12 +53,23 @@ private:
static void read_envelope(InputStream& in, box2d<double>& envelope);
static void query_node(Filter const& filter, InputStream& in, std::vector<Value> & results);
static void query_first_n_impl(Filter const& filter, InputStream& in, std::vector<Value> & results, std::size_t count);
static bool check_header(InputStream& in);
};
template <typename Value, typename Filter, typename InputStream>
bool spatial_index<Value, Filter, InputStream>::check_header(InputStream& in)
{
static_assert(std::is_standard_layout<Value>::value, "Values stored in quad-tree must be standard layout type");
char header[17]; // mapnik-index
std::memset(header, 0, 17);
in.read(header,16);
return (std::strncmp(header, "mapnik-index",12) == 0);
}
template <typename Value, typename Filter, typename InputStream>
box2d<double> spatial_index<Value, Filter, InputStream>::bounding_box(InputStream& in)
{
static_assert(std::is_standard_layout<Value>::value, "Values stored in quad-tree must be standard layout type");
if (!check_header(in)) throw std::runtime_error("Invalid index file");
in.seekg(16 + 4, std::ios::beg);
box2d<double> box;
read_envelope(in, box);
@ -69,7 +80,7 @@ box2d<double> spatial_index<Value, Filter, InputStream>::bounding_box(InputStrea
template <typename Value, typename Filter, typename InputStream>
void spatial_index<Value, Filter, InputStream>::query(Filter const& filter, InputStream& in, std::vector<Value>& results)
{
static_assert(std::is_standard_layout<Value>::value, "Values stored in quad-tree must be standard layout types");
if (!check_header(in)) throw std::runtime_error("Invalid index file");
in.seekg(16, std::ios::beg);
query_node(filter, in, results);
}
@ -104,7 +115,7 @@ void spatial_index<Value, Filter, InputStream>::query_node(Filter const& filter,
template <typename Value, typename Filter, typename InputStream>
void spatial_index<Value, Filter, InputStream>::query_first_n(Filter const& filter, InputStream& in, std::vector<Value>& results, std::size_t count)
{
static_assert(std::is_standard_layout<Value>::value, "Values stored in quad-tree must be standard layout types");
if (!check_header(in)) throw std::runtime_error("Invalid index file");
in.seekg(16, std::ios::beg);
query_first_n_impl(filter, in, results, count);
}

View file

@ -283,29 +283,20 @@ namespace detail {
template <typename T>
struct unwrapper
{
T const& operator() (T const& obj) const
{
return obj;
}
T& operator() (T & obj) const
{
return obj;
}
static T const& apply_const(T const& obj) {return obj;}
static T& apply(T & obj) {return obj;}
};
template <typename T>
struct unwrapper<recursive_wrapper<T>>
{
auto operator() (recursive_wrapper<T> const& obj) const
static auto apply_const(recursive_wrapper<T> const& obj)
-> typename recursive_wrapper<T>::type const&
{
return obj.get();
}
auto operator() (recursive_wrapper<T> & obj) const
-> typename recursive_wrapper<T>::type &
static auto apply(recursive_wrapper<T> & obj)
-> typename recursive_wrapper<T>::type&
{
return obj.get();
}
@ -314,8 +305,13 @@ struct unwrapper<recursive_wrapper<T>>
template <typename T>
struct unwrapper<std::reference_wrapper<T>>
{
auto operator() (std::reference_wrapper<T> const& obj) const
-> typename recursive_wrapper<T>::type const&
static auto apply_const(std::reference_wrapper<T> const& obj)
-> typename std::reference_wrapper<T>::type const&
{
return obj.get();
}
static auto apply(std::reference_wrapper<T> & obj)
-> typename std::reference_wrapper<T>::type&
{
return obj.get();
}
@ -332,7 +328,7 @@ struct dispatcher<F, V, R, T, Types...>
{
if (v.get_type_index() == sizeof...(Types))
{
return f(unwrapper<T>()(v. template get<T>()));
return f(unwrapper<T>::apply_const(v. template get<T>()));
}
else
{
@ -344,7 +340,7 @@ struct dispatcher<F, V, R, T, Types...>
{
if (v.get_type_index() == sizeof...(Types))
{
return f(unwrapper<T>()(v. template get<T>()));
return f(unwrapper<T>::apply(v. template get<T>()));
}
else
{
@ -380,8 +376,8 @@ struct binary_dispatcher_rhs<F, V, R, T0, T1, Types...>
{
if (rhs.get_type_index() == sizeof...(Types)) // call binary functor
{
return f(unwrapper<T0>()(lhs. template get<T0>()),
unwrapper<T1>()(rhs. template get<T1>()));
return f(unwrapper<T0>::apply_const(lhs. template get<T0>()),
unwrapper<T1>::apply_const(rhs. template get<T1>()));
}
else
{
@ -393,8 +389,8 @@ struct binary_dispatcher_rhs<F, V, R, T0, T1, Types...>
{
if (rhs.get_type_index() == sizeof...(Types)) // call binary functor
{
return f(unwrapper<T0>()(lhs. template get<T0>()),
unwrapper<T1>()(rhs. template get<T1>()));
return f(unwrapper<T0>::apply(lhs. template get<T0>()),
unwrapper<T1>::apply(rhs. template get<T1>()));
}
else
{
@ -430,7 +426,8 @@ struct binary_dispatcher_lhs<F, V, R, T0, T1, Types...>
{
if (lhs.get_type_index() == sizeof...(Types)) // call binary functor
{
return f(lhs. template get<T1>(), rhs. template get<T0>());
return f(unwrapper<T1>::apply_const(lhs. template get<T1>()),
unwrapper<T0>::apply_const(rhs. template get<T0>()));
}
else
{
@ -442,7 +439,8 @@ struct binary_dispatcher_lhs<F, V, R, T0, T1, Types...>
{
if (lhs.get_type_index() == sizeof...(Types)) // call binary functor
{
return f(lhs. template get<T1>(), rhs. template get<T0>());
return f(unwrapper<T1>::apply(lhs. template get<T1>()),
unwrapper<T0>::apply(rhs. template get<T0>()));
}
else
{
@ -480,7 +478,8 @@ struct binary_dispatcher<F, V, R, T, Types...>
{
if (v0.get_type_index() == v1.get_type_index())
{
return f(v0. template get<T>(), v1. template get<T>()); // call binary functor
return f(unwrapper<T>::apply_const(v0. template get<T>()),
unwrapper<T>::apply_const(v1. template get<T>())); // call binary functor
}
else
{
@ -500,7 +499,8 @@ struct binary_dispatcher<F, V, R, T, Types...>
{
if (v0.get_type_index() == v1.get_type_index())
{
return f(v0. template get<T>(), v1. template get<T>()); // call binary functor
return f(unwrapper<T>::apply(v0. template get<T>()),
unwrapper<T>::apply(v1. template get<T>())); // call binary functor
}
else
{

View file

@ -60,8 +60,7 @@ if env['PLUGIN_LINKING'] == 'shared':
SHLIBPREFIX='',
SHLIBSUFFIX='.input',
source=plugin_sources,
LIBS=libraries,
LINKFLAGS=env['CUSTOM_LDFLAGS'])
LIBS=libraries)
# if the plugin links to libmapnik ensure it is built first
Depends(TARGET, env.subst('../../../src/%s' % env['MAPNIK_LIB_NAME']))

View file

@ -63,12 +63,13 @@ shape_index_featureset<filterT>::shape_index_featureset(filterT const& filter,
if (index)
{
#if defined(MAPNIK_MEMORY_MAPPED_FILE)
mapnik::util::spatial_index<int, filterT,boost::interprocess::ibufferstream>::query(filter, index->file(), offsets_);
mapnik::util::spatial_index<mapnik::detail::node, filterT,boost::interprocess::ibufferstream>::query(filter, index->file(), offsets_);
#else
mapnik::util::spatial_index<int, filterT, std::ifstream>::query(filter, index->file(), offsets_);
mapnik::util::spatial_index<mapnik::detail::node, filterT, std::ifstream>::query(filter, index->file(), offsets_);
#endif
}
std::sort(offsets_.begin(), offsets_.end());
std::sort(offsets_.begin(), offsets_.end(), [](mapnik::detail::node const& n0, mapnik::detail::node const& n1)
{return n0.offset != n1.offset ? n0.offset < n1.offset : n0.start < n1.start;});
MAPNIK_LOG_DEBUG(shape) << "shape_index_featureset: Query size=" << offsets_.size();
itr_ = offsets_.begin();
}
@ -83,7 +84,15 @@ feature_ptr shape_index_featureset<filterT>::next()
while ( itr_ != offsets_.end())
{
shape_ptr_->move_to(*itr_++);
int offset = itr_->offset;
shape_ptr_->move_to(offset);
std::vector<std::pair<int,int>> parts;
while (itr_->offset == offset && itr_ != offsets_.end())
{
if (itr_->start!= -1) parts.emplace_back(itr_->start, itr_->end);
++itr_;
}
//std::cerr << "PARTS SIZE=" << parts.size() <<" offset=" << offset << std::endl;
mapnik::value_integer feature_id = shape_ptr_->id();
shape_file::record_type record(shape_ptr_->reclength_ * 2);
shape_ptr_->shp().read_record(record);
@ -124,7 +133,8 @@ feature_ptr shape_index_featureset<filterT>::next()
{
shape_io::read_bbox(record, feature_bbox_);
if (!filter_.pass(feature_bbox_)) continue;
feature->set_geometry(shape_io::read_polyline(record));
if (parts.size() < 2) feature->set_geometry(shape_io::read_polyline(record));
else feature->set_geometry(shape_io::read_polyline_parts(record, parts));
break;
}
case shape_io::shape_polygon:
@ -133,7 +143,8 @@ feature_ptr shape_index_featureset<filterT>::next()
{
shape_io::read_bbox(record, feature_bbox_);
if (!filter_.pass(feature_bbox_)) continue;
feature->set_geometry(shape_io::read_polygon(record));
if (parts.size() < 2) feature->set_geometry(shape_io::read_polygon(record));
else feature->set_geometry(shape_io::read_polygon_parts(record, parts));
break;
}
default :

View file

@ -45,6 +45,21 @@ using mapnik::box2d;
using mapnik::feature_ptr;
using mapnik::context_ptr;
namespace mapnik { namespace detail
{
struct node
{
node() = default;
node(int offset_, int start_, int end_)
: offset(offset_),
start(start_),
end(end_) {}
int offset;
int start;
int end;
};
}} // ns
template <typename filterT>
class shape_index_featureset : public Featureset
{
@ -63,8 +78,8 @@ private:
context_ptr ctx_;
std::unique_ptr<shape_io> shape_ptr_;
const std::unique_ptr<mapnik::transcoder> tr_;
std::vector<int> offsets_;
std::vector<int>::iterator itr_;
std::vector<mapnik::detail::node> offsets_;
std::vector<mapnik::detail::node>::iterator itr_;
std::vector<int> attr_ids_;
mapnik::value_integer row_limit_;
mutable int count_;

View file

@ -125,6 +125,7 @@ mapnik::geometry::geometry<double> shape_io::read_polyline(shape_file::record_ty
std::for_each(parts.begin(), parts.end(), [&](int & part) { part = record.read_ndr_integer();});
int start, end;
mapnik::geometry::multi_line_string<double> multi_line;
multi_line.reserve(num_parts);
for (int k = 0; k < num_parts; ++k)
{
start = parts[k];
@ -152,6 +153,34 @@ mapnik::geometry::geometry<double> shape_io::read_polyline(shape_file::record_ty
return geom;
}
mapnik::geometry::geometry<double> shape_io::read_polyline_parts(shape_file::record_type & record, std::vector<std::pair<int, int>> const& parts)
{
mapnik::geometry::geometry<double> geom; // default empty
int total_num_parts = record.read_ndr_integer();
int num_parts = parts.size();
mapnik::geometry::multi_line_string<double> multi_line;
multi_line.reserve(num_parts);
for (int k = 0; k < num_parts; ++k)
{
int start = parts[k].first;
int end = parts[k].second;
unsigned pos = 4 + 32 + 8 + 4 * total_num_parts + start * 16;
record.set_pos(pos);
mapnik::geometry::line_string<double> line;
line.reserve(end - start);
for (int j = start; j < end; ++j)
{
double x = record.read_double();
double y = record.read_double();
line.emplace_back(x, y);
}
multi_line.push_back(std::move(line));
}
geom = std::move(multi_line);
return geom;
}
mapnik::geometry::geometry<double> shape_io::read_polygon(shape_file::record_type & record)
{
@ -207,3 +236,53 @@ mapnik::geometry::geometry<double> shape_io::read_polygon(shape_file::record_typ
mapnik::geometry::correct(geom);
return geom;
}
mapnik::geometry::geometry<double> shape_io::read_polygon_parts(shape_file::record_type & record, std::vector<std::pair<int,int>> const& parts)
{
mapnik::geometry::geometry<double> geom; // default empty
int total_num_parts = record.read_ndr_integer();
mapnik::geometry::polygon<double> poly;
mapnik::geometry::multi_polygon<double> multi_poly;
int num_parts = parts.size();
for (int k = 0; k < num_parts; ++k)
{
int start = parts[k].first;
int end = parts[k].second;
unsigned pos = 4 + 32 + 8 + 4 * total_num_parts + start * 16;
record.set_pos(pos);
mapnik::geometry::linear_ring<double> ring;
ring.reserve(end - start);
for (int j = start; j < end; ++j)
{
double x = record.read_double();
double y = record.read_double();
ring.emplace_back(x, y);
}
if (k == 0)
{
poly.set_exterior_ring(std::move(ring));
}
else if (mapnik::util::is_clockwise(ring))
{
multi_poly.emplace_back(std::move(poly));
poly.interior_rings.clear();
poly.set_exterior_ring(std::move(ring));
}
else
{
poly.add_hole(std::move(ring));
}
}
if (multi_poly.size() > 0) // multi
{
multi_poly.emplace_back(std::move(poly));
geom = std::move(multi_poly);
}
else
{
geom = std::move(poly);
}
mapnik::geometry::correct(geom);
return geom;
}

View file

@ -80,6 +80,8 @@ public:
static void read_bbox(shape_file::record_type & record, mapnik::box2d<double> & bbox);
static mapnik::geometry::geometry<double> read_polyline(shape_file::record_type & record);
static mapnik::geometry::geometry<double> read_polygon(shape_file::record_type & record);
static mapnik::geometry::geometry<double> read_polyline_parts(shape_file::record_type & record,std::vector<std::pair<int,int>> const& parts);
static mapnik::geometry::geometry<double> read_polygon_parts(shape_file::record_type & record, std::vector<std::pair<int,int>> const& parts);
shapeType type_;
shape_file shp_;

View file

@ -105,6 +105,11 @@ struct shape_record
pos += n;
}
void set_pos(unsigned pos_)
{
pos = pos_;
}
int read_ndr_integer()
{
std::int32_t val;

View file

@ -0,0 +1,57 @@
$PSVersionTable
$PSVersionTable.PSVersion
$SystemManaged = Get-WmiObject -Class Win32_ComputerSystem | % {$_.AutomaticManagedPagefile}
$total_physicalmem = gwmi Win32_ComputerSystem | % {[Math]::round($_.TotalPhysicalMemory/1MB,0)}
$physical_mem = get-ciminstance -class 'cim_physicalmemory' | % { $_.Capacity/1024/1024}
$PF =gwmi Win32_PageFileUsage
$PageFileLocation = $PF.Name;
$PageFileSize = $PF.AllocatedBaseSize
Write-Host "physical memory : "$physical_mem
Write-Host "total physical memory : "$total_physicalmem
Write-Host "page file system managed : "$SystemManaged
Write-Host "page file location : "$PageFileLocation
Write-Host "page file size : "$PageFileSize
Write-Host "InitialSize : "${CurrentPageFile}.InitialSize
Write-Host "MaximumSize : "$CurrentPageFile.MaximumSize
if($env:APPVEYOR -eq "true"){
Write-Host !!!!!!! on AppVeyor: changing page file settings !!!!!!!!!!
#disable automatically managed page file settings
$c = Get-WmiObject Win32_computersystem -EnableAllPrivileges
if($c.AutomaticManagedPagefile){
Write-Host disabling managed page file settings
$c.AutomaticManagedPagefile = $false
$c.Put() | Out-Null
}
$new_page_size=18000
$CurrentPageFile = Get-WmiObject -Class Win32_PageFileSetting
if($CurrentPageFile.InitialSize -ne $new_page_size){
Write-Host "setting new page file size to $new_page_size"
$CurrentPageFile.InitialSize=$new_page_size
$CurrentPageFile.MaximumSize=$new_page_size
$CurrentPageFile.Put() | Out-Null
}
Write-Host "new ------------ "
Write-Host "system managed:" (Get-WmiObject -Class Win32_ComputerSystem | % {$_.AutomaticManagedPagefile})
Write-Host "page file size:" (gwmi Win32_PageFileUsage).AllocatedBaseSize
Write-Host "InitialSize: "${CurrentPageFile}.InitialSize
Write-Host "MaximumSize: "$CurrentPageFile.MaximumSize
} else {
Write-Host not on AppVeyor, leaving page file as is
}
#list drives
Get-WmiObject -Class Win32_LogicalDisk |
Where-Object {$_.DriveType -ne 5} |
Sort-Object -Property Name |
Select-Object Name, VolumeName, FileSystem, Description, VolumeDirty, `
@{"Label"="DiskSize(GB)";"Expression"={"{0:N}" -f ($_.Size/1GB) -as [float]}}, `
@{"Label"="FreeSpace(GB)";"Expression"={"{0:N}" -f ($_.FreeSpace/1GB) -as [float]}}, `
@{"Label"="%Free";"Expression"={"{0:N}" -f ($_.FreeSpace/$_.Size*100) -as [float]}} |
Format-Table -AutoSize

View file

@ -5,8 +5,9 @@ SET EL=0
ECHO =========== %~f0 ===========
ECHO NUMBER_OF_PROCESSORS^: %NUMBER_OF_PROCESSORS%
ECHO RAM [MB]^:
powershell "get-ciminstance -class 'cim_physicalmemory' | %% { $_.Capacity/1024/1024}"
powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted -Force
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
powershell .\scripts\appveyor-system-info.ps1
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
::only build on AppVeyor, if explicitly stated
@ -27,27 +28,6 @@ ECHO ========
SET PATH=C:\Python27;%PATH%
SET PATH=C:\Program Files\7-Zip;%PATH%
:: *nix style find command comes with git:
ECHO checking for unix style 'find'
find %USERPROFILE% -name "*.blabla"
IF %ERRORLEVEL% EQU 0 GOTO NIX_FIND_FOUND
IF DEFINED GIT_INSTALL_ROOT SET TEMP_GIT_DIR=%GIT_INSTALL_ROOT%&& GOTO TEST_FIND_AGAIN
IF EXIST "C:\Program Files (x86)\Git" SET TEMP_GIT_DIR=C:\Program Files (x86)\Git&& GOTO TEST_FIND_AGAIN
IF EXIST "C:\Program Files\Git" SET TEMP_GIT_DIR=C:\Program Files\Git&& GOTO TEST_FIND_AGAIN
:TEST_FIND_AGAIN
SET PATH=%TEMP_GIT_DIR%\bin;%PATH%
SET PATH=%TEMP_GIT_DIR%\usr\bin;%PATH%
ECHO %PATH%
::check again
find %USERPROFILE% -name "*.blabla"
IF %ERRORLEVEL% NEQ 0 (ECHO unix style find not found && GOTO ERROR)
:NIX_FIND_FOUND
ECHO find was found
::cloning mapnik-gyp
if EXIST mapnik-gyp ECHO mapnik-gyp already cloned && GOTO MAPNIK_GYP_ALREADY_HERE
CALL git clone https://github.com/mapnik/mapnik-gyp.git

View file

@ -8,14 +8,45 @@ SET APPVEYOR_REPO_COMMIT_MESSAGE=this is a [build appveyor] test
SET APPVEYOR=true
::comment this to get complete AppVeyor behaviour
SET LOCAL_BUILD_DONT_SKIP_TESTS=true
SET MAPNIK_GIT=3.0.5
SET BOOST_VERSION=59
SET FASTBUILD=1
FOR /F "tokens=1 usebackq" %%i in (`powershell .\scripts\parse-appveyor-yml.ps1`) DO SET BOOST_VERSION=%%i
ECHO BOOST_VERSION found in appveyor.yml^: %BOOST_VERSION%
IF "%BOOST_VERSION%"=="0" ECHO BOOST_VERSION not valid && SET ERRORLEVEL=1 && GOTO ERROR
:: OVERRIDE PARAMETERS >>>>>>>>
:NEXT-ARG
IF '%1'=='' GOTO ARGS-DONE
ECHO setting %1
SET %1
SHIFT
GOTO NEXT-ARG
:ARGS-DONE
::<<<<< OVERRIDE PARAMETERS
SET configuration=Release
SET msvs_toolset=14
SET platform=x64
SET APPVEYOR_BUILD_FOLDER=%CD%
IF NOT EXIST bindings\python git clone https://github.com/mapnik/python-mapnik.git bindings/python
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
CD bindings\python & IF %ERRORLEVEL% NEQ 0 GOTO ERROR
git fetch & IF %ERRORLEVEL% NEQ 0 GOTO ERROR
git pull & IF %ERRORLEVEL% NEQ 0 GOTO ERROR
CD ..\.. & IF %ERRORLEVEL% NEQ 0 GOTO ERROR
ECHO pulling test data
CALL git submodule update --init
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
ECHO pulling test data, DONE
SET TIME_START_LOCAL_BUILD=%TIME%
CALL scripts\build-appveyor.bat
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
@ -28,5 +59,7 @@ SET EL=%ERRORLEVEL%
:DONE
ECHO =========== DONE %~f0 ===========
ECHO build started^: %TIME_START_LOCAL_BUILD%
ECHO build finished^: %TIME%
EXIT /b %EL%

View file

@ -0,0 +1,7 @@
$ErrorActionPreference = 'Stop'
$boost_version='0'
Get-Content .\appveyor.yml |
foreach {
if ($_ -match "BOOST_VERSION: "){ $boost_version = $_.split()[-1] }
}
Write-Host $boost_version

9
scripts/time-header Executable file
View file

@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -eu
set -o pipefail
CXXFLAGS="$(./utils/mapnik-config/mapnik-config --cflags)"
CXX="$(./utils/mapnik-config/mapnik-config --cxx)"
echo "Time taken to compile '$(basename $1)':"
time ${CXX} $1 -I./test -I./deps/agg/include -Ideps -I./include $CXXFLAGS -o /tmp/header.out

View file

@ -36,7 +36,29 @@ namespace mapnik {
namespace util {
bool parse_dasharray(std::string const& value, std::vector<double>& dasharray)
namespace {
inline bool setup_dashes(std::vector<double> & buf, dash_array & dash)
{
if (buf.empty()) return false;
size_t size = buf.size();
if (size % 2 == 1)
{
buf.insert(buf.end(),buf.begin(),buf.end());
}
std::vector<double>::const_iterator pos = buf.begin();
while (pos != buf.end())
{
if (*pos > 0.0 || *(pos+1) > 0.0) // avoid both dash and gap eq 0.0
{
dash.emplace_back(*pos,*(pos + 1));
}
pos +=2;
}
return !buf.empty();
}
}
bool parse_dasharray(std::string const& value, dash_array & dash)
{
using namespace boost::spirit;
qi::double_type double_;
@ -49,18 +71,19 @@ bool parse_dasharray(std::string const& value, std::vector<double>& dasharray)
// dasharray ::= (length | percentage) (comma-wsp dasharray)?
// no support for 'percentage' as viewport is unknown at load_map
//
std::vector<double> buf;
auto first = value.begin();
auto last = value.end();
bool r = qi::phrase_parse(first, last,
(double_[boost::phoenix::push_back(boost::phoenix::ref(dasharray), _1)] %
(double_[boost::phoenix::push_back(boost::phoenix::ref(buf), _1)] %
no_skip[char_(", ")]
| lit("none")),
space);
if (first != last)
if (r && first == last)
{
return false;
return setup_dashes(buf, dash);
}
return r;
return false;
}
} // end namespace util

View file

@ -31,6 +31,7 @@ template MAPNIK_DECL mapnik::box2d<double> envelope(mapnik::base_symbolizer_help
template MAPNIK_DECL mapnik::box2d<double> envelope(geometry_empty const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(point<double> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(line_string<double> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(linear_ring<double> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(polygon<double> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(multi_point<double> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(multi_line_string<double> const& geom);
@ -40,6 +41,7 @@ template MAPNIK_DECL mapnik::box2d<double> envelope(geometry_collection<double>
template MAPNIK_DECL mapnik::box2d<double> envelope(geometry<std::int64_t> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(point<std::int64_t> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(line_string<std::int64_t> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(linear_ring<std::int64_t> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(polygon<std::int64_t> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(multi_point<std::int64_t> const& geom);
template MAPNIK_DECL mapnik::box2d<double> envelope(multi_line_string<std::int64_t> const& geom);

View file

@ -44,9 +44,9 @@ namespace mapnik { namespace svg {
svg_path_grammar<iterator_type,skip_type,PathType> g(p);
iterator_type first = wkt;
iterator_type last = wkt + std::strlen(wkt);
return qi::phrase_parse(first, last, g, skip_type());
bool status = qi::phrase_parse(first, last, g, skip_type());
return (status && (first == last));
}
template bool parse_path<svg_converter_type>(const char*, svg_converter_type&);
}}
}}

View file

@ -598,13 +598,9 @@ image_any tiff_reader<T>::read(unsigned x, unsigned y, unsigned width, unsigned
}
template <typename T>
void tiff_reader<T>::read_generic(std::size_t, std::size_t, image_rgba8& image)
void tiff_reader<T>::read_generic(std::size_t, std::size_t, image_rgba8&)
{
TIFF* tif = open(stream_);
if (tif)
{
throw std::runtime_error("tiff_reader: TODO - tiff is not stripped or tiled");
}
throw std::runtime_error("tiff_reader: TODO - tiff is not stripped or tiled");
}
template <typename T>

File diff suppressed because it is too large Load diff

@ -1 +1 @@
Subproject commit 972b039bfc5a5e189f68852c22df717a30c1adf7
Subproject commit af88691110b39c75f97140ab4b608b258e53ad51

View file

@ -68,6 +68,10 @@ mapnik::datasource_ptr get_csv_ds(std::string const& file_name, bool strict = tr
mapnik::parameters params;
params["type"] = std::string("csv");
params["file"] = file_name;
if (!base.empty())
{
params["base"] = base;
}
params["strict"] = mapnik::value_bool(strict);
auto ds = mapnik::datasource_cache::instance().create(params);
// require a non-null pointer returned
@ -80,7 +84,7 @@ int create_disk_index(std::string const& filename, bool silent = true)
std::string cmd;
if (std::getenv("DYLD_LIBRARY_PATH") != nullptr)
{
cmd += std::string("export DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " && ";
cmd += std::string("DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " ";
}
cmd += "mapnik-index " + filename;
if (silent)
@ -288,7 +292,7 @@ TEST_CASE("csv") {
INFO(ret_posix);
CHECK(mapnik::util::exists(filepath + ".index"));
}
auto ds = get_csv_ds(filepath,true,base);
auto ds = get_csv_ds(filename,true,base);
CHECK(ds->type() == mapnik::datasource::datasource_t::Vector);
auto fields = ds->get_descriptor().get_descriptors();
require_field_names(fields, {"Precinct", "Phone", "Address", "City", "geo_longitude", "geo_latitude", "geo_accuracy"});

View file

@ -66,7 +66,7 @@ int create_disk_index(std::string const& filename, bool silent = true)
std::string cmd;
if (std::getenv("DYLD_LIBRARY_PATH") != nullptr)
{
cmd += std::string("export DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " && ";
cmd += std::string("DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " ";
}
cmd += "mapnik-index " + filename;
if (silent)

View file

@ -35,263 +35,260 @@ clang++ -o test-postgis -g -I./test/ test/unit/run.cpp test/unit/datasource/post
#include <boost/optional/optional_io.hpp>
namespace postgistest {
int run(std::string const& command, bool okay_to_fail = false)
int run(std::string const& command, bool okay_to_fail = false)
{
std::string cmd;
if (std::getenv("DYLD_LIBRARY_PATH") != nullptr)
{
cmd += std::string("DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " && ";
}
cmd += command;
// silence output unless MAPNIK_TEST_DEBUG is defined
if (std::getenv("MAPNIK_TEST_DEBUG") == nullptr)
{
std::string cmd;
if (std::getenv("DYLD_LIBRARY_PATH") != nullptr)
{
cmd += std::string("export DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " && ";
}
cmd += command;
// silence output unless MAPNIK_TEST_DEBUG is defined
if (std::getenv("MAPNIK_TEST_DEBUG") == nullptr)
{
#ifndef _WINDOWS
cmd += " 2>/dev/null";
cmd += " 2>/dev/null";
#else
cmd += " 2> nul";
cmd += " 2> nul";
#endif
}
else
{
std::clog << "Running " << cmd << "\n";
}
bool worked = (std::system(cmd.c_str()) == 0);
if (okay_to_fail == true) return true;
return worked;
}
std::string dbname("mapnik-tmp-postgis-test-db");
TEST_CASE("postgis") {
SECTION("Postgis data initialization")
{
//don't add 'true' here, to get error message, when drop fails. If it works nothing is output
REQUIRE(run("dropdb --if-exists " + dbname));
REQUIRE(run("createdb -T template_postgis " + dbname));
//REQUIRE(run("createdb " + dbname));
// Breaks when raster support is missing (unfortunately this is common)
//REQUIRE(run("psql -c 'CREATE EXTENSION postgis;' " + dbname, true));
REQUIRE(run("psql -q -f ./test/data/sql/postgis-create-db-and-tables.sql " + dbname));
}
mapnik::parameters params;
params["type"] = "postgis";
params["dbname"] = dbname;
SECTION("Postgis should throw without 'table' parameter")
{
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
}
SECTION("Postgis should throw with 'max_async_connection' greater than 'max_size'")
{
params["table"] = "test";
params["max_async_connection"] = "2";
params["max_size"] = "1";
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
}
SECTION("Postgis should throw with invalid metadata query")
{
params["table"] = "does_not_exist";
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
}
SECTION("Postgis should throw with invalid key field")
{
params["table"] = "test_invalid_id";
params["key_field"] = "id";
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
}
SECTION("Postgis should throw with multicolumn primary key")
{
params["table"] = "test_invalid_multi_col_pk";
params["autodetect_key_field"] = "true";
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
}
SECTION("Postgis should throw without geom column")
{
params["table"] = "test_no_geom_col";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
CHECK_THROWS(all_features(ds));
}
SECTION("Postgis should throw with invalid credentials")
{
params["table"] = "test";
params["user"] = "not_a_valid_user";
params["password"] = "not_a_valid_pwd";
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
}
SECTION("Postgis initialize dataset with persist_connection, schema, extent, geometry field, autodectect key field, simplify_geometries, row_limit")
{
params["persist_connection"] = "false";
params["table"] = "public.test";
params["geometry_field"] = "geom";
params["autodetect_key_field"] = "true";
params["extent"] = "-1 -1, -1 2, 4 3, 3 -1, -1 -1";
params["simplify_geometries"] = "true";
params["row_limit"] = "1";
auto ds = mapnik::datasource_cache::instance().create(params);
}
SECTION("Postgis dataset geometry type")
{
params["table"] = "(SELECT * FROM test WHERE gid=1) as data";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::Point);
}
SECTION("Postgis query field names")
{
params["table"] = "test";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
REQUIRE(ds->type() == mapnik::datasource::datasource_t::Vector);
auto fields = ds->get_descriptor().get_descriptors();
require_field_names(fields, { "gid", "colbigint", "col_text", "col-char", "col+bool", "colnumeric", "colsmallint", "colfloat4", "colfloat8", "colcharacter" });
require_field_types(fields, { mapnik::Integer, mapnik::Integer, mapnik::String, mapnik::String, mapnik::Boolean, mapnik::Double, mapnik::Integer, mapnik::Double, mapnik::Double, mapnik::String });
}
SECTION("Postgis iterate features")
{
params["table"] = "test";
params["key_field"] = "gid";
params["max_async_connection"] = "2";
//params["cursor_size"] = "2";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
auto featureset = ds->features_at_point(mapnik::coord2d(1, 1));
mapnik::feature_ptr feature;
while ((bool(feature = featureset->next()))) {
REQUIRE(feature->get(2).to_string() == feature->get("col_text").to_string());
REQUIRE(feature->get(4).to_bool() == feature->get("col+bool").to_bool());
REQUIRE(feature->get(5).to_double() == feature->get("colnumeric").to_double());
REQUIRE(feature->get(5).to_string() == feature->get("colnumeric").to_string());
}
featureset = all_features(ds);
feature = featureset->next();
//deactivate char tests for now: not yet implemented.
//add at postgis_datasource.cpp:423
//case 18: // char
//REQUIRE("A" == feature->get("col-char").to_string());
feature = featureset->next();
//REQUIRE("B" == feature->get("col-char").to_string());
feature = featureset->next();
REQUIRE(false == feature->get("col+bool").to_bool());
}
SECTION("Postgis cursorresultest")
{
params["table"] = "(SELECT * FROM test) as data";
params["cursor_size"] = "2";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
auto featureset = all_features(ds);
CHECK(count_features(featureset) == 8);
featureset = all_features(ds);
mapnik::feature_ptr feature;
while (bool(feature = featureset->next())) {
CHECK(feature->size() == 10);
}
featureset = all_features(ds);
require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Point);
require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Point);
require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiPoint);
require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::LineString);
require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiLineString);
require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Polygon);
require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiPolygon);
require_geometry(featureset->next(), 3, mapnik::geometry::geometry_types::GeometryCollection);
}
SECTION("Postgis bbox query")
{
params["table"] = "(SELECT * FROM public.test) as data WHERE geom && !bbox!";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
mapnik::box2d<double> ext = ds->envelope();
CAPTURE(ext);
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
REQUIRE(ext.minx() == -2);
REQUIRE(ext.miny() == -2);
REQUIRE(ext.maxx() == 5);
REQUIRE(ext.maxy() == 4);
}
SECTION("Postgis query extent: full dataset")
{
//include schema to increase coverage
params["table"] = "(SELECT * FROM public.test) as data";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
mapnik::box2d<double> ext = ds->envelope();
CAPTURE(ext);
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
REQUIRE(ext.minx() == -2);
REQUIRE(ext.miny() == -2);
REQUIRE(ext.maxx() == 5);
REQUIRE(ext.maxy() == 4);
}
/* deactivated for merging: still investigating a proper fix
SECTION("Postgis query extent from subquery")
{
params["table"] = "(SELECT * FROM test where gid=4) as data";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
mapnik::box2d<double> ext = ds->envelope();
CAPTURE(ext);
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
REQUIRE(ext.minx() == 0);
REQUIRE(ext.miny() == 0);
REQUIRE(ext.maxx() == 1);
REQUIRE(ext.maxy() == 2);
}
*/
SECTION("Postgis query extent: from subquery with 'extent_from_subquery=true'")
{
params["table"] = "(SELECT * FROM test where gid=4) as data";
params["extent_from_subquery"] = "true";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
mapnik::box2d<double> ext = ds->envelope();
CAPTURE(ext);
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
REQUIRE(ext.minx() == 0);
REQUIRE(ext.miny() == 0);
REQUIRE(ext.maxx() == 1);
REQUIRE(ext.maxy() == 2);
}
/* deactivated for merging: still investigating a proper fix
SECTION("Postgis query extent: subset with 'extent_from_subquery=true' and 'scale_denominator'")
{
// !!!! postgis-vt-util::z() returns 'null' when 'scale_denominator > 600000000'
// https://github.com/mapbox/postgis-vt-util/blob/559f073877696a6bfea41baf3e1065f9cf4d18d1/postgis-vt-util.sql#L615-L617
params["table"] = "(SELECT * FROM test where gid=4 AND z(!scale_denominator!) BETWEEN 0 AND 22) as data";
params["extent_from_subquery"] = "true";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
mapnik::box2d<double> ext = ds->envelope();
CAPTURE(ext);
INFO("" << std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
REQUIRE(ext.minx() == 0);
REQUIRE(ext.miny() == 0);
REQUIRE(ext.maxx() == 1);
REQUIRE(ext.maxy() == 2);
}
*/
else
{
std::clog << "Running " << cmd << "\n";
}
bool worked = (std::system(cmd.c_str()) == 0);
if (okay_to_fail == true) return true;
return worked;
}
std::string dbname("mapnik-tmp-postgis-test-db");
TEST_CASE("postgis") {
SECTION("Postgis data initialization")
{
//don't add 'true' here, to get error message, when drop fails. If it works nothing is output
REQUIRE(run("dropdb --if-exists " + dbname));
REQUIRE(run("createdb -T template_postgis " + dbname));
//REQUIRE(run("createdb " + dbname));
// Breaks when raster support is missing (unfortunately this is common)
//REQUIRE(run("psql -c 'CREATE EXTENSION postgis;' " + dbname, true));
REQUIRE(run("psql -q -f ./test/data/sql/postgis-create-db-and-tables.sql " + dbname));
}
mapnik::parameters params;
params["type"] = "postgis";
params["dbname"] = dbname;
SECTION("Postgis should throw without 'table' parameter")
{
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
}
SECTION("Postgis should throw with 'max_async_connection' greater than 'max_size'")
{
params["table"] = "test";
params["max_async_connection"] = "2";
params["max_size"] = "1";
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
}
SECTION("Postgis should throw with invalid metadata query")
{
params["table"] = "does_not_exist";
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
}
SECTION("Postgis should throw with invalid key field")
{
params["table"] = "test_invalid_id";
params["key_field"] = "id";
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
}
SECTION("Postgis should throw with multicolumn primary key")
{
params["table"] = "test_invalid_multi_col_pk";
params["autodetect_key_field"] = "true";
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
}
SECTION("Postgis should throw without geom column")
{
params["table"] = "test_no_geom_col";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
CHECK_THROWS(all_features(ds));
}
SECTION("Postgis should throw with invalid credentials")
{
params["table"] = "test";
params["user"] = "not_a_valid_user";
params["password"] = "not_a_valid_pwd";
CHECK_THROWS(mapnik::datasource_cache::instance().create(params));
}
SECTION("Postgis initialize dataset with persist_connection, schema, extent, geometry field, autodectect key field, simplify_geometries, row_limit")
{
params["persist_connection"] = "false";
params["table"] = "public.test";
params["geometry_field"] = "geom";
params["autodetect_key_field"] = "true";
params["extent"] = "-1 -1, -1 2, 4 3, 3 -1, -1 -1";
params["simplify_geometries"] = "true";
params["row_limit"] = "1";
auto ds = mapnik::datasource_cache::instance().create(params);
}
SECTION("Postgis dataset geometry type")
{
params["table"] = "(SELECT * FROM test WHERE gid=1) as data";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
CHECK(ds->get_geometry_type() == mapnik::datasource_geometry_t::Point);
}
SECTION("Postgis query field names")
{
params["table"] = "test";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
REQUIRE(ds->type() == mapnik::datasource::datasource_t::Vector);
auto fields = ds->get_descriptor().get_descriptors();
require_field_names(fields, { "gid", "colbigint", "col_text", "col-char", "col+bool", "colnumeric", "colsmallint", "colfloat4", "colfloat8", "colcharacter" });
require_field_types(fields, { mapnik::Integer, mapnik::Integer, mapnik::String, mapnik::String, mapnik::Boolean, mapnik::Double, mapnik::Integer, mapnik::Double, mapnik::Double, mapnik::String });
}
SECTION("Postgis iterate features")
{
params["table"] = "test";
params["key_field"] = "gid";
params["max_async_connection"] = "2";
//params["cursor_size"] = "2";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
auto featureset = ds->features_at_point(mapnik::coord2d(1, 1));
mapnik::feature_ptr feature;
while ((bool(feature = featureset->next()))) {
REQUIRE(feature->get(2).to_string() == feature->get("col_text").to_string());
REQUIRE(feature->get(4).to_bool() == feature->get("col+bool").to_bool());
REQUIRE(feature->get(5).to_double() == feature->get("colnumeric").to_double());
REQUIRE(feature->get(5).to_string() == feature->get("colnumeric").to_string());
}
featureset = all_features(ds);
feature = featureset->next();
//deactivate char tests for now: not yet implemented.
//add at postgis_datasource.cpp:423
//case 18: // char
//REQUIRE("A" == feature->get("col-char").to_string());
feature = featureset->next();
//REQUIRE("B" == feature->get("col-char").to_string());
feature = featureset->next();
REQUIRE(false == feature->get("col+bool").to_bool());
}
SECTION("Postgis cursorresultest")
{
params["table"] = "(SELECT * FROM test) as data";
params["cursor_size"] = "2";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
auto featureset = all_features(ds);
CHECK(count_features(featureset) == 8);
featureset = all_features(ds);
mapnik::feature_ptr feature;
while (bool(feature = featureset->next())) {
CHECK(feature->size() == 10);
}
featureset = all_features(ds);
require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Point);
require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Point);
require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiPoint);
require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::LineString);
require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiLineString);
require_geometry(featureset->next(), 1, mapnik::geometry::geometry_types::Polygon);
require_geometry(featureset->next(), 2, mapnik::geometry::geometry_types::MultiPolygon);
require_geometry(featureset->next(), 3, mapnik::geometry::geometry_types::GeometryCollection);
}
SECTION("Postgis bbox query")
{
params["table"] = "(SELECT * FROM public.test) as data WHERE geom && !bbox!";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
mapnik::box2d<double> ext = ds->envelope();
CAPTURE(ext);
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
REQUIRE(ext.minx() == -2);
REQUIRE(ext.miny() == -2);
REQUIRE(ext.maxx() == 5);
REQUIRE(ext.maxy() == 4);
}
SECTION("Postgis query extent: full dataset")
{
//include schema to increase coverage
params["table"] = "(SELECT * FROM public.test) as data";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
mapnik::box2d<double> ext = ds->envelope();
CAPTURE(ext);
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
REQUIRE(ext.minx() == -2);
REQUIRE(ext.miny() == -2);
REQUIRE(ext.maxx() == 5);
REQUIRE(ext.maxy() == 4);
}
/* deactivated for merging: still investigating a proper fix
SECTION("Postgis query extent from subquery")
{
params["table"] = "(SELECT * FROM test where gid=4) as data";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
mapnik::box2d<double> ext = ds->envelope();
CAPTURE(ext);
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
REQUIRE(ext.minx() == 0);
REQUIRE(ext.miny() == 0);
REQUIRE(ext.maxx() == 1);
REQUIRE(ext.maxy() == 2);
}
*/
SECTION("Postgis query extent: from subquery with 'extent_from_subquery=true'")
{
params["table"] = "(SELECT * FROM test where gid=4) as data";
params["extent_from_subquery"] = "true";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
mapnik::box2d<double> ext = ds->envelope();
CAPTURE(ext);
INFO(std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
REQUIRE(ext.minx() == 0);
REQUIRE(ext.miny() == 0);
REQUIRE(ext.maxx() == 1);
REQUIRE(ext.maxy() == 2);
}
/* deactivated for merging: still investigating a proper fix
SECTION("Postgis query extent: subset with 'extent_from_subquery=true' and 'scale_denominator'")
{
// !!!! postgis-vt-util::z() returns 'null' when 'scale_denominator > 600000000'
// https://github.com/mapbox/postgis-vt-util/blob/559f073877696a6bfea41baf3e1065f9cf4d18d1/postgis-vt-util.sql#L615-L617
params["table"] = "(SELECT * FROM test where gid=4 AND z(!scale_denominator!) BETWEEN 0 AND 22) as data";
params["extent_from_subquery"] = "true";
auto ds = mapnik::datasource_cache::instance().create(params);
REQUIRE(ds != nullptr);
mapnik::box2d<double> ext = ds->envelope();
CAPTURE(ext);
INFO("" << std::setprecision(6) << std::fixed << ext.minx() << "/" << ext.miny() << " " << ext.maxx() << "/" << ext.maxy());
REQUIRE(ext.minx() == 0);
REQUIRE(ext.miny() == 0);
REQUIRE(ext.maxx() == 1);
REQUIRE(ext.maxy() == 2);
}
*/
}

View file

@ -58,14 +58,17 @@ std::size_t count_shapefile_features(std::string const& filename)
return feature_count;
}
int create_shapefile_index(std::string const& filename, bool silent = true)
int create_shapefile_index(std::string const& filename, bool index_parts, bool silent = true)
{
std::string cmd;
if (std::getenv("DYLD_LIBRARY_PATH") != nullptr)
{
cmd += std::string("export DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " && ";
cmd += std::string("DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " ";
}
cmd += "shapeindex " + filename;
cmd += "shapeindex";
if (index_parts) cmd+= " --index-parts ";
cmd += filename;
if (silent)
{
#ifndef _WINDOWS
@ -90,28 +93,31 @@ TEST_CASE("shapeindex")
{
if (boost::iends_with(path,".shp"))
{
std::string index_path = path.substr(0, path.rfind(".")) + ".index";
// remove *.index if present
if (mapnik::util::exists(index_path))
for (bool index_parts : {false, true} )
{
mapnik::util::remove(index_path);
}
// count features
std::size_t feature_count = count_shapefile_features(path);
// create *.index
create_shapefile_index(path);
if (feature_count == 0)
{
REQUIRE(!mapnik::util::exists(index_path)); // index won't be created if there's no features
}
// count features
std::size_t feature_count_indexed = count_shapefile_features(path);
// ensure number of features are the same
REQUIRE(feature_count == feature_count_indexed);
// remove *.index if present
if (mapnik::util::exists(index_path))
{
mapnik::util::remove(index_path);
std::string index_path = path.substr(0, path.rfind(".")) + ".index";
// remove *.index if present
if (mapnik::util::exists(index_path))
{
mapnik::util::remove(index_path);
}
// count features
std::size_t feature_count = count_shapefile_features(path);
// create *.index
create_shapefile_index(path, index_parts);
if (feature_count == 0)
{
REQUIRE(!mapnik::util::exists(index_path)); // index won't be created if there's no features
}
// count features
std::size_t feature_count_indexed = count_shapefile_features(path);
// ensure number of features are the same
REQUIRE(feature_count == feature_count_indexed);
// remove *.index if present
if (mapnik::util::exists(index_path))
{
mapnik::util::remove(index_path);
}
}
}
}

View file

@ -1,17 +1,73 @@
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
#include <string>
#include <mapnik/util/fs.hpp>
#include <mapnik/datasource_cache.hpp>
#include <boost/filesystem/convenience.hpp>
#include "cleanup.hpp" // run_cleanup()
std::string plugin_path;
inline void set_plugin_path(Catch::ConfigData&, std::string const& _plugin_path ) {
plugin_path = _plugin_path;
}
std::string working_dir;
inline void set_working_dir(Catch::ConfigData&, std::string const& _working_dir ) {
working_dir = _working_dir;
}
int main (int argc, char* const argv[])
{
mapnik::datasource_cache::instance().register_datasources("plugins/input/");
Catch::Session session;
int result = Catch::Session().run( argc, argv );
auto & cli = session.cli();
cli["-p"]["--plugins"]
.describe("path to mapnik plugins")
.bind(&set_plugin_path, "plugins");
cli["-C"]["--working-directory"]
.describe("change working directory")
.bind(&set_working_dir, "working directory");
int result = session.applyCommandLine(argc, argv);
if (!plugin_path.empty())
{
if (!mapnik::util::exists(plugin_path))
{
std::clog << "Could not find " << plugin_path << "\n";
return -1;
}
mapnik::datasource_cache::instance().register_datasources(plugin_path);
}
else
{
mapnik::datasource_cache::instance().register_datasources("plugins/input/");
}
if (!working_dir.empty())
{
if (!mapnik::util::exists(working_dir))
{
std::clog << "Could not find " << working_dir << "\n";
return -1;
}
boost::filesystem::current_path(working_dir);
}
if (result == 0)
{
result = session.run();
}
testing::run_cleanup();
return result;
}

View file

@ -150,7 +150,8 @@ result_list runner::test_all(report_type & report) const
result_list runner::test(std::vector<std::string> const & style_names, report_type & report) const
{
std::vector<runner::path_type> files(style_names.size());
std::vector<runner::path_type> files;
files.reserve(style_names.size());
std::transform(style_names.begin(), style_names.end(), std::back_inserter(files),
[&](runner::path_type const & name)
{

View file

@ -26,9 +26,10 @@
#include <string>
#include <mapnik/util/fs.hpp>
#include <mapnik/quad_tree.hpp>
#include <mapnik/geometry_envelope.hpp>
#include "shapefile.hpp"
#include "shape_io.hpp"
#include "shape_index_featureset.hpp"
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
#include <boost/algorithm/string.hpp>
@ -44,8 +45,9 @@ int main (int argc,char** argv)
namespace po = boost::program_options;
bool verbose=false;
unsigned int depth=DEFAULT_DEPTH;
double ratio=DEFAULT_RATIO;
bool index_parts = false;
unsigned int depth = DEFAULT_DEPTH;
double ratio = DEFAULT_RATIO;
std::vector<std::string> shape_files;
try
@ -54,6 +56,7 @@ int main (int argc,char** argv)
desc.add_options()
("help,h", "produce usage message")
("version,V","print version string")
("index-parts","index individual shape parts (default: no)")
("verbose,v","verbose output")
("depth,d", po::value<unsigned int>(), "max tree depth\n(default 8)")
("ratio,r",po::value<double>(),"split ratio (default 0.55)")
@ -81,6 +84,10 @@ int main (int argc,char** argv)
{
verbose = true;
}
if (vm.count("index-parts"))
{
index_parts = true;
}
if (vm.count("depth"))
{
depth = vm["depth"].as<unsigned int>();
@ -159,7 +166,7 @@ int main (int argc,char** argv)
int pos = 50;
shx.seek(pos * 2);
mapnik::quad_tree<int> tree(extent, depth, ratio);
mapnik::quad_tree<mapnik::detail::node> tree(extent, depth, ratio);
int count = 0;
if (shape_type != shape_io::shape_null)
@ -188,17 +195,56 @@ int main (int argc,char** argv)
double y=shp.read_double();
item_ext=box2d<double>(x,y,x,y);
}
else if (index_parts &&
(shape_type == shape_io::shape_polygon || shape_type == shape_io::shape_polygonm || shape_type == shape_io::shape_polygonz
|| shape_type == shape_io::shape_polyline || shape_type == shape_io::shape_polylinem || shape_type == shape_io::shape_polylinez))
{
shp.read_envelope(item_ext);
int num_parts = shp.read_ndr_integer();
int num_points = shp.read_ndr_integer();
std::vector<int> parts;
parts.resize(num_parts);
std::for_each(parts.begin(), parts.end(), [&](int & part) { part = shp.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];
mapnik::geometry::linear_ring<double> ring;
ring.reserve(end - start);
for (int j = start; j < end; ++j)
{
double x = shp.read_double();
double y = shp.read_double();
ring.emplace_back(x, y);
}
item_ext = mapnik::geometry::envelope(ring);
if (item_ext.valid())
{
if (verbose)
{
std::clog << "record number " << record_number << " box=" << item_ext << std::endl;
}
tree.insert(mapnik::detail::node(offset * 2, start, end),item_ext);
++count;
}
}
item_ext = mapnik::box2d<double>(); //invalid
}
else
{
shp.read_envelope(item_ext);
}
if (verbose)
{
std::clog << "record number " << record_number << " box=" << item_ext << std::endl;
}
if (item_ext.valid())
{
tree.insert(offset * 2,item_ext);
if (verbose)
{
std::clog << "record number " << record_number << " box=" << item_ext << std::endl;
}
tree.insert(mapnik::detail::node(offset * 2,-1,0),item_ext);
++count;
}
}