Merge branch 'master' into geometry_cleanup
This commit is contained in:
commit
726cea7ba4
16 changed files with 123 additions and 70 deletions
|
@ -41,8 +41,10 @@ def is_py3():
|
|||
|
||||
prefix = env['PREFIX']
|
||||
target_path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik')
|
||||
target_path_deprecated = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik2')
|
||||
|
||||
libraries = ['mapnik','png']
|
||||
libraries = ['mapnik']
|
||||
libraries.append('png')
|
||||
|
||||
if env['JPEG']:
|
||||
libraries.append('jpeg')
|
||||
|
@ -121,22 +123,24 @@ else:
|
|||
paths = '''
|
||||
"""Configuration paths of Mapnik fonts and input plugins (auto-generated by SCons)."""
|
||||
|
||||
import os
|
||||
from os.path import normpath,join,dirname
|
||||
|
||||
mapniklibpath = '%s'
|
||||
mapniklibpath = normpath(join(dirname(__file__),mapniklibpath))
|
||||
'''
|
||||
|
||||
paths += "inputpluginspath = os.path.normpath(mapniklibpath + '/input')\n"
|
||||
paths += "inputpluginspath = join(mapniklibpath,'input')\n"
|
||||
|
||||
if env['SYSTEM_FONTS']:
|
||||
paths += "fontscollectionpath = os.path.normpath('%s')" % env['SYSTEM_FONTS']
|
||||
paths += "fontscollectionpath = normpath('%s')\n" % env['SYSTEM_FONTS']
|
||||
else:
|
||||
paths += "fontscollectionpath = os.path.normpath(mapniklibpath + '/fonts')"
|
||||
paths += "fontscollectionpath = join(mapniklibpath,'fonts')\n"
|
||||
|
||||
paths += "__all__ = [mapniklibpath,inputpluginspath,fontscollectionpath]\n"
|
||||
|
||||
if not os.path.exists('mapnik'):
|
||||
os.mkdir('mapnik')
|
||||
file('mapnik/paths.py','w').write(paths % (env['MAPNIK_LIB_DIR']))
|
||||
file('mapnik/paths.py','w').write(paths % (os.path.relpath(env['MAPNIK_LIB_DIR'],target_path)))
|
||||
|
||||
# force open perms temporarily so that `sudo scons install`
|
||||
# does not later break simple non-install non-sudo rebuild
|
||||
|
@ -152,8 +156,7 @@ if 'install' in COMMAND_LINE_TARGETS:
|
|||
init_module = env.Install(target_path, init_files)
|
||||
env.Alias(target='install', source=init_module)
|
||||
# install mapnik2 module which redirects to mapnik and issues DeprecatedWarning
|
||||
path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik2')
|
||||
init_mapnik2 = env.Install(path, 'mapnik2/__init__.py')
|
||||
init_mapnik2 = env.Install(target_path_deprecated, 'mapnik2/__init__.py')
|
||||
env.Alias(target='install', source=init_mapnik2)
|
||||
|
||||
# fix perms and install the custom generated 'paths.py'
|
||||
|
@ -204,4 +207,5 @@ if 'uninstall' not in COMMAND_LINE_TARGETS:
|
|||
|
||||
|
||||
env['create_uninstall_target'](env, target_path)
|
||||
env['create_uninstall_target'](env, target_path_deprecated)
|
||||
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
mapniklibpath = '@PACKAGE_LIB_DIR@'
|
||||
inputpluginspath = mapniklibpath + '/input'
|
||||
fontscollectionpath = '@SYSTEM_FONTS_DIR@/truetype/ttf-dejavu'
|
|
@ -213,6 +213,12 @@ struct symbolizer_attributes : public boost::static_visitor<>
|
|||
|
||||
void operator () (building_symbolizer const& sym)
|
||||
{
|
||||
expression_ptr const& height_expr = sym.height();
|
||||
if (height_expr)
|
||||
{
|
||||
expression_attributes f_attr(names_);
|
||||
boost::apply_visitor(f_attr,*height_expr);
|
||||
}
|
||||
collect_metawriter(sym);
|
||||
}
|
||||
// TODO - support remaining syms
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
// mapnik
|
||||
#include <mapnik/color.hpp>
|
||||
#include <mapnik/symbolizer.hpp>
|
||||
#include <mapnik/filter_factory.hpp>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
@ -79,11 +80,10 @@ struct MAPNIK_DECL building_symbolizer : public symbolizer_base
|
|||
explicit building_symbolizer()
|
||||
: symbolizer_base(),
|
||||
fill_(color(128,128,128)),
|
||||
height_(0.0),
|
||||
opacity_(1.0)
|
||||
{}
|
||||
|
||||
building_symbolizer(color const& fill,double height)
|
||||
building_symbolizer(color const& fill, expression_ptr height)
|
||||
: symbolizer_base(),
|
||||
fill_(fill),
|
||||
height_(height),
|
||||
|
@ -97,11 +97,11 @@ struct MAPNIK_DECL building_symbolizer : public symbolizer_base
|
|||
{
|
||||
fill_ = fill;
|
||||
}
|
||||
double height() const
|
||||
expression_ptr height() const
|
||||
{
|
||||
return height_;
|
||||
}
|
||||
void set_height(double height)
|
||||
void set_height(expression_ptr height)
|
||||
{
|
||||
height_=height;
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ struct MAPNIK_DECL building_symbolizer : public symbolizer_base
|
|||
}
|
||||
private:
|
||||
color fill_;
|
||||
double height_;
|
||||
expression_ptr height_;
|
||||
double opacity_;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -489,10 +489,12 @@ void csv_datasource::parse_csv(T& stream,
|
|||
std::string::const_iterator str_beg = value.begin();
|
||||
std::string::const_iterator str_end = value.end();
|
||||
bool r = qi::phrase_parse(str_beg,str_end,
|
||||
(
|
||||
qi::lit("POINT") >> '(' >> double_[ref(x) = _1] >> double_[ref(y) = _1] >> ')'
|
||||
),
|
||||
ascii::space);
|
||||
(
|
||||
qi::lit("POINT") >> '('
|
||||
>> double_[ref(x) = _1]
|
||||
>> double_[ref(y) = _1] >> ')'
|
||||
),
|
||||
ascii::space);
|
||||
|
||||
if (r && (str_beg == str_end))
|
||||
{
|
||||
|
@ -615,28 +617,27 @@ void csv_datasource::parse_csv(T& stream,
|
|||
}
|
||||
}
|
||||
|
||||
// add all values as attributes
|
||||
// here we detect numbers and treat everything else as pure strings
|
||||
// this is intentional since boolean and null types are not common in csv editors
|
||||
if (value.empty())
|
||||
{
|
||||
UnicodeString ustr = tr.transcode(value.c_str());
|
||||
boost::put(*feature,fld_name,ustr);
|
||||
if (feature_count == 1)
|
||||
{
|
||||
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
|
||||
}
|
||||
}
|
||||
// only true strings are this long
|
||||
else if (value_length > 20)
|
||||
{
|
||||
UnicodeString ustr = tr.transcode(value.c_str());
|
||||
boost::put(*feature,fld_name,ustr);
|
||||
if (feature_count == 1)
|
||||
{
|
||||
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
|
||||
}
|
||||
// now, add all values as attributes
|
||||
/* First we detect likely strings, then try parsing likely numbers,
|
||||
finally falling back to string type
|
||||
* We intentionally do not try to detect boolean or null types
|
||||
since they are not common in csv
|
||||
* Likely strings are either empty values, very long values
|
||||
or value with leading zeros like 001 (which are not safe
|
||||
to assume are numbers)
|
||||
*/
|
||||
|
||||
bool has_dot = value.find(".") != std::string::npos;
|
||||
if (value.empty() ||
|
||||
(value_length > 20) ||
|
||||
(value_length > 1 && !has_dot && value[0] == '0'))
|
||||
{
|
||||
UnicodeString ustr = tr.transcode(value.c_str());
|
||||
boost::put(*feature,fld_name,ustr);
|
||||
if (feature_count == 1)
|
||||
{
|
||||
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
|
||||
}
|
||||
}
|
||||
else if ((value[0] >= '0' && value[0] <= '9') || value[0] == '-')
|
||||
{
|
||||
|
@ -646,12 +647,14 @@ void csv_datasource::parse_csv(T& stream,
|
|||
bool r = qi::phrase_parse(str_beg,str_end,qi::double_,ascii::space,float_val);
|
||||
if (r && (str_beg == str_end))
|
||||
{
|
||||
if (value.find(".") != std::string::npos)
|
||||
if (has_dot)
|
||||
{
|
||||
boost::put(*feature,fld_name,float_val);
|
||||
if (feature_count == 1)
|
||||
{
|
||||
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::Double));
|
||||
desc_.add_descriptor(
|
||||
mapnik::attribute_descriptor(
|
||||
fld_name,mapnik::Double));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -660,7 +663,9 @@ void csv_datasource::parse_csv(T& stream,
|
|||
boost::put(*feature,fld_name,val);
|
||||
if (feature_count == 1)
|
||||
{
|
||||
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::Integer));
|
||||
desc_.add_descriptor(
|
||||
mapnik::attribute_descriptor(
|
||||
fld_name,mapnik::Integer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -671,7 +676,9 @@ void csv_datasource::parse_csv(T& stream,
|
|||
boost::put(*feature,fld_name,ustr);
|
||||
if (feature_count == 1)
|
||||
{
|
||||
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
|
||||
desc_.add_descriptor(
|
||||
mapnik::attribute_descriptor(
|
||||
fld_name,mapnik::String));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -682,7 +689,9 @@ void csv_datasource::parse_csv(T& stream,
|
|||
boost::put(*feature,fld_name,ustr);
|
||||
if (feature_count == 1)
|
||||
{
|
||||
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
|
||||
desc_.add_descriptor(
|
||||
mapnik::attribute_descriptor(
|
||||
fld_name,mapnik::String));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <mapnik/agg_renderer.hpp>
|
||||
#include <mapnik/agg_rasterizer.hpp>
|
||||
#include <mapnik/segment.hpp>
|
||||
#include <mapnik/expression_evaluator.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
@ -66,7 +67,13 @@ void agg_renderer<T>::process(building_symbolizer const& sym,
|
|||
ras_ptr->reset();
|
||||
ras_ptr->gamma(agg::gamma_linear());
|
||||
|
||||
double height = sym.height() * scale_factor_;
|
||||
double height = 0.0;
|
||||
expression_ptr height_expr = sym.height();
|
||||
if (height_expr)
|
||||
{
|
||||
value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature), *height_expr);
|
||||
height = result.to_double() * scale_factor_;
|
||||
}
|
||||
|
||||
for (unsigned i=0;i<feature.num_geometries();++i)
|
||||
{
|
||||
|
|
|
@ -62,7 +62,7 @@ void agg_renderer<T>::process(polygon_symbolizer const& sym,
|
|||
renderer ren(renb);
|
||||
|
||||
ras_ptr->reset();
|
||||
ras_ptr->gamma(agg::gamma_linear(0.0, sym.get_gamma()));
|
||||
ras_ptr->gamma(agg::gamma_power(sym.get_gamma()));
|
||||
metawriter_with_properties writer = sym.get_metawriter();
|
||||
for (unsigned i=0;i<feature.num_geometries();++i)
|
||||
{
|
||||
|
|
|
@ -779,7 +779,13 @@ void cairo_renderer_base::process(building_symbolizer const& sym,
|
|||
cairo_context context(context_);
|
||||
|
||||
color const& fill = sym.get_fill();
|
||||
double height = 0.7071 * sym.height(); // height in meters
|
||||
double height = 0.0;
|
||||
expression_ptr height_expr = sym.height();
|
||||
if (height_expr)
|
||||
{
|
||||
value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature), *height_expr);
|
||||
height = 0.7071 * result.to_double();
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < feature.num_geometries(); ++i)
|
||||
{
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <mapnik/grid/grid_pixel.hpp>
|
||||
#include <mapnik/grid/grid.hpp>
|
||||
#include <mapnik/segment.hpp>
|
||||
#include <mapnik/expression_evaluator.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
@ -59,7 +60,13 @@ void grid_renderer<T>::process(building_symbolizer const& sym,
|
|||
|
||||
ras_ptr->reset();
|
||||
|
||||
double height = sym.height() * scale_factor_;
|
||||
double height = 0.0;
|
||||
expression_ptr height_expr = sym.height();
|
||||
if (height_expr)
|
||||
{
|
||||
value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature), *height_expr);
|
||||
height = result.to_double() * scale_factor_;
|
||||
}
|
||||
|
||||
for (unsigned i=0;i<feature.num_geometries();++i)
|
||||
{
|
||||
|
|
|
@ -1906,9 +1906,8 @@ void map_parser::parse_building_symbolizer( rule & rule, ptree const & sym )
|
|||
optional<double> opacity = get_opt_attr<double>(sym, "fill-opacity");
|
||||
if (opacity) building_sym.set_opacity(*opacity);
|
||||
// height
|
||||
// TODO - expression
|
||||
optional<double> height = get_opt_attr<double>(sym, "height");
|
||||
if (height) building_sym.set_height(*height);
|
||||
optional<std::string> height = get_opt_attr<std::string>(sym, "height");
|
||||
if (height) building_sym.set_height(parse_expression(*height, "utf8"));
|
||||
|
||||
parse_metawriter_in_symbolizer(building_sym, sym);
|
||||
rule.append(building_sym);
|
||||
|
|
|
@ -241,10 +241,9 @@ public:
|
|||
{
|
||||
set_attr( sym_node, "fill-opacity", sym.get_opacity() );
|
||||
}
|
||||
if ( sym.height() != dfl.height() || explicit_defaults_ )
|
||||
{
|
||||
set_attr( sym_node, "height", sym.height() );
|
||||
}
|
||||
|
||||
set_attr( sym_node, "height", to_expression_string(*sym.height()) );
|
||||
|
||||
add_metawriter_attributes(sym_node, sym);
|
||||
}
|
||||
|
||||
|
|
4
tests/data/csv/leading_zeros.csv
Normal file
4
tests/data/csv/leading_zeros.csv
Normal file
|
@ -0,0 +1,4 @@
|
|||
x,y,fips
|
||||
0,0,001
|
||||
0,0,003
|
||||
0,0,005
|
|
|
@ -7,25 +7,15 @@
|
|||
</Rule>
|
||||
</Style>
|
||||
|
||||
<!-- layer created by ogr like: ogr2ogr -t_srs EPSG:4326 -f SQLite ../sqlite/world.sqlite world_merc.shp -->
|
||||
<!-- here we read with the ogr plugin -->
|
||||
<Layer name="world_borders1" srs="+init=epsg:4326">
|
||||
<StyleName>world_borders_style1</StyleName>
|
||||
<Datasource>
|
||||
<Parameter name="type">ogr</Parameter>
|
||||
<Parameter name="file">../sqlite/world.sqlite</Parameter>
|
||||
<Parameter name="layer">world_merc</Parameter>
|
||||
</Datasource>
|
||||
</Layer>
|
||||
|
||||
<Style name="world_borders_style2">
|
||||
<Rule>
|
||||
<PolygonSymbolizer fill="yellow" gamma="0.5"/>
|
||||
</Rule>
|
||||
</Style>
|
||||
|
||||
<!-- here we read with native sqlite plugin -->
|
||||
<!-- layer created by ogr like: ogr2ogr -t_srs EPSG:4326 -f SQLite ../sqlite/world.sqlite world_merc.shp -->
|
||||
<Layer name="world_borders2" srs="+init=epsg:4326">
|
||||
<StyleName>world_borders_style1</StyleName>
|
||||
<StyleName>world_borders_style2</StyleName>
|
||||
<Datasource>
|
||||
<Parameter name="type">sqlite</Parameter>
|
||||
|
|
6
tests/data/svg/README.md
Normal file
6
tests/data/svg/README.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
Other good sources of svg for tests include:
|
||||
|
||||
* http://intertwingly.net/svg/
|
||||
* http://www.w3.org/Graphics/SVG/Test/20110816/
|
||||
* http://croczilla.com/bits_and_pieces/svg/samples/
|
||||
* http://www.w3schools.com/svg/svg_examples.asp
|
|
@ -227,6 +227,25 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
query.add_property_name('bogus')
|
||||
fs = ds.features(query)
|
||||
|
||||
def test_that_leading_zeros_mean_strings(**kwargs):
|
||||
ds = get_csv_ds('leading_zeros.csv')
|
||||
eq_(len(ds.fields()),3)
|
||||
eq_(ds.fields(),['x','y','fips'])
|
||||
eq_(ds.field_types(),['int','int','str'])
|
||||
fs = ds.featureset()
|
||||
feat = fs.next()
|
||||
eq_(feat['x'],0)
|
||||
eq_(feat['y'],0)
|
||||
eq_(feat['fips'],'001')
|
||||
feat = fs.next()
|
||||
eq_(feat['x'],0)
|
||||
eq_(feat['y'],0)
|
||||
eq_(feat['fips'],'003')
|
||||
feat = fs.next()
|
||||
eq_(feat['x'],0)
|
||||
eq_(feat['y'],0)
|
||||
eq_(feat['fips'],'005')
|
||||
|
||||
if __name__ == "__main__":
|
||||
setup()
|
||||
[eval(run)(visual=True) for run in dir() if 'test_' in run]
|
||||
|
|
|
@ -12,7 +12,7 @@ def usage():
|
|||
def main():
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "hvqp:", ["help", "prefix="])
|
||||
except getopt.GetoptError as err:
|
||||
except getopt.GetoptError,err:
|
||||
print(str(err))
|
||||
usage()
|
||||
sys.exit(2)
|
||||
|
|
Loading…
Reference in a new issue