Merge branch 'master' into conv_simplify
Conflicts: bindings/python/mapnik_line_symbolizer.cpp bindings/python/mapnik_polygon_symbolizer.cpp
1
.gitignore
vendored
|
@ -39,6 +39,7 @@ tests/data/sqlite/*index
|
|||
demo/c++/cairo-demo.pdf
|
||||
demo/c++/cairo-demo.png
|
||||
demo/c++/cairo-demo256.png
|
||||
demo/c++/cairo-demo.svg
|
||||
demo/c++/demo.tif
|
||||
demo/c++/demo.jpg
|
||||
demo/c++/demo.png
|
||||
|
|
158
CHANGELOG.md
|
@ -9,42 +9,76 @@ For a complete change history, see the git log.
|
|||
|
||||
## Mapnik 2.1.0
|
||||
|
||||
Not yet released
|
||||
Released Aug 23, 2012
|
||||
|
||||
(Packaged from a25aac8)
|
||||
|
||||
- Feature-level compositing (comp-op) for all symbolizers (except building) in AGG and Cairo renderers (#1409)
|
||||
|
||||
- Style-level compositing (comp-op) (#1409) and style-level opacity for AGG renderer (#314)
|
||||
|
||||
- New experimental framework for image manipulation called `image-filters` to allow things to be done across entire layer canvas like burring (#1412)
|
||||
|
||||
- Support for recoloring stroke, fill, and opacity of SVG files (#1410 / #659)
|
||||
|
||||
- Support for data-driven transform expressions (#664)
|
||||
|
||||
- New support for offsetting geometries / parallel lines in line_symbolizer (#927/#1269)
|
||||
|
||||
- New support for clipping geometries - now default enabled on all symbolizers (#1116)
|
||||
|
||||
- Framework for chainable geometry transformations (called `vertex_converters`) so that you can do things like clip, smooth, and offset at the same time (#927)
|
||||
|
||||
- WKT parsing now is more robust and supports multi-geometries (#745)
|
||||
|
||||
- New support for outputting WKT/WKB/GeoJSON/SVG from mapnik.Geometry objects (#1411)
|
||||
|
||||
- New experimental python datasource plugin (#1337)
|
||||
|
||||
- New experimental geojson datasource plugin using in-memory rtree indexing (#1413)
|
||||
|
||||
- Cairo rendering is now much more similiar to AGG rendering as cairo backend now supports `scale_factor` (#1280) and other fixed have landed (#1343, #1233, #1344, #1242, #687, #737, #1006, #1071)
|
||||
|
||||
- mapnik::Feature objects and datasource plugins now use a `Context` to store attribute schemas to reduce the memory footprint of features (#834)
|
||||
|
||||
- Added Stroke `miterlimit` (#786)
|
||||
|
||||
- Python: exposed Map `background_image` (and aliased `background` to `background_color`)
|
||||
|
||||
- Python: exposed BuildingSymbolizer
|
||||
|
||||
- Support in the CSV plugin for reading JSON encoded geometries (#1392)
|
||||
|
||||
- Increased grid encoding performance (#1315)
|
||||
|
||||
- Added support for overriding fill, stroke, and opacity for svg markers using marker properties
|
||||
|
||||
- Added support for setting opacity dynamically on images in polygon pattern and markers symbolizers
|
||||
|
||||
- Added support for filtering on a features geometry type, either `point`, `linestring`, 'polygon`,
|
||||
- Added support for filtering on a features geometry type, either `point`, `linestring`, `polygon`,
|
||||
or `collection` using the expression keyword of `[mapnik::geometry_type]` (#546)
|
||||
|
||||
- MarkersSymbolizer width and height moved to expressions (#1102)
|
||||
|
||||
- Added style-level 'opacity' (#314)
|
||||
|
||||
- PostGIS: Added 'simplify_geometries' option - will trigger ST_Simplify on geometries before returning to Mapnik (#1179)
|
||||
- PostGIS: Added `simplify_geometries` option - will trigger ST_Simplify on geometries before returning to Mapnik (#1179)
|
||||
|
||||
- Improved error feedback for invalid values passed to map.query_point
|
||||
|
||||
- Fixed rendering of thin svg lines (#1129)
|
||||
|
||||
- Improved logging/debugging system with release logs and file redirection (#937 and partially #986, #467)
|
||||
- Improved logging/debugging system with release logs and file redirection (https://github.com/mapnik/mapnik/wiki/Runtime-Logging) (#937 and partially #986, #467)
|
||||
|
||||
- GDAL: allow setting nodata value on the fly (will override value if nodata is set in data) (#1161)
|
||||
|
||||
- GDAL: respect nodata for paletted/colormapped images (#1160)
|
||||
|
||||
- PostGIS: Added a new option called 'autodetect_key_field' (by default false) that if true will
|
||||
trigger autodetection of a given tables' primary key allowing for feature.id() to represent
|
||||
globally unique ids. This option has no effect if the user has not manually supplied the 'key_field' option. (#804)
|
||||
- PostGIS: Added a new option called `autodetect_key_field` (by default false) that if true will
|
||||
trigger autodetection of the table primary key allowing for feature.id() to represent
|
||||
globally unique ids. This option has no effect if the user has not manually supplied the `key_field` option. (#804)
|
||||
|
||||
- Cairo: Add full rendering support for markers to match AGG renderer functionality (#1071)
|
||||
|
||||
- Fix Markers rendering so that ellipse height/width units are pixels (previously were unintentionally radii) (#1134)
|
||||
|
||||
- Added 'ignore-placement` attribute to markers-symbolizer (#1135)
|
||||
- Added `ignore-placement` attribute to markers-symbolizer (#1135)
|
||||
|
||||
- Removed PointDatasource - use more robust MemoryDatasource instead (#1032)
|
||||
|
||||
|
@ -108,7 +142,7 @@ Released April 10, 2012
|
|||
|
||||
- Fix Markers rendering so that ellipse height/width units are pixels (previously were unintentially radii) (#1134)
|
||||
|
||||
- Added 'ignore-placement` attribute to markers-symbolizer (#1135)
|
||||
- Added `ignore-placement` attribute to markers-symbolizer (#1135)
|
||||
|
||||
- Removed svn_revision info from mapnik-config and python bindings as git is now used
|
||||
|
||||
|
@ -158,13 +192,13 @@ Released September 26, 2011
|
|||
from a file that files directory is used. And a custom value can still be passed as an argument to
|
||||
load_map_from_string().
|
||||
|
||||
- Added python function 'render_grid' to allow conversion of grid buffer to python object containing list of grid
|
||||
- Added python function `render_grid` to allow conversion of grid buffer to python object containing list of grid
|
||||
pixels, list of keys, and a and dictionary of feature attributes.
|
||||
|
||||
- Added new rendering backend, grid_renderer, that collects the attributes of rendered features and
|
||||
burns their ids into a grid buffer.
|
||||
|
||||
- Added optional 'maximum-extent' parameter to map object. If set will be used, instead of combined
|
||||
- Added optional `maximum-extent` parameter to map object. If set will be used, instead of combined
|
||||
layer extents, for return value of map.zoom_all(). Useful in cases where the combined layer extents
|
||||
cannot possibly be projected into the map srs or the user wishes to control map bounds without
|
||||
modifying the extents of each layer.
|
||||
|
@ -177,9 +211,9 @@ Released September 26, 2011
|
|||
|
||||
- Added support for drawing only first matching rule using filter-mode="first" in Style (#706)
|
||||
|
||||
- Added support to PointSymbolizer ('ignore_placement') for skipping adding placed points to collision detector (#564)
|
||||
- Added support to PointSymbolizer (`ignore_placement`) for skipping adding placed points to collision detector (#564)
|
||||
|
||||
- Added ability to register fonts within XML using Map level 'font_directory' parameter (#168)
|
||||
- Added ability to register fonts within XML using Map level `font-directory` parameter (#168)
|
||||
|
||||
- TextSymbolizer: Change text_convert to text_transform to better match css naming (r2211)
|
||||
|
||||
|
@ -187,8 +221,8 @@ Released September 26, 2011
|
|||
|
||||
- Upgraded to the latest proj4 string literal for EPSG:4326 (WGS84) as global default projection (#333)
|
||||
|
||||
- Added 'mapnik_version_from_string()' function in python bindings to easily convert string representation
|
||||
of version number to the integer format used in 'mapnik/version.hpp'. e.g. '0.7.1' --> 701.
|
||||
- Added `mapnik_version_from_string()` function in python bindings to easily convert string representation
|
||||
of version number to the integer format used in `mapnik/version.hpp`. e.g. `0.7.1` --> `701`.
|
||||
|
||||
- Added xinclude (http://www.w3.org/TR/xinclude/) support to libxml2-based xml parser (oldtopos) (#567)
|
||||
|
||||
|
@ -196,7 +230,7 @@ Released September 26, 2011
|
|||
|
||||
- Added support for setting global alignment of polygon pattern fills (#203)
|
||||
|
||||
- Added support for choosing OGR layer by index number using 'layer_by_index' parameter (r1904)
|
||||
- Added support for choosing OGR layer by index number using `layer_by_index` parameter (r1904)
|
||||
|
||||
- Added support for fractional halo widths (using FT Stroker) (#93)
|
||||
|
||||
|
@ -258,7 +292,7 @@ Released Oct 18, 2011
|
|||
|
||||
- Various fixes to sqlite, ogr, and occi driver backported from trunk.
|
||||
|
||||
- Ensured that '\n' triggers linebreaks in text rendering (#584)
|
||||
- Ensured that `\n` triggers linebreaks in text rendering (#584)
|
||||
|
||||
- Support for boost filesystem v3
|
||||
|
||||
|
@ -277,13 +311,13 @@ Released March 23, 2010
|
|||
|
||||
- XML: Save map buffer_size when serializing map.
|
||||
|
||||
- SCons: Added new build options 'PRIORITIZE_LINKING' and 'LINK_PRIORITY'. The first is a boolean (default True)
|
||||
- SCons: Added new build options `PRIORITIZE_LINKING` and `LINK_PRIORITY`. The first is a boolean (default True)
|
||||
of whether to use the new sorting implementation that gives explcit preference to custom or local paths
|
||||
during compile and linking that will affect builds when duplicate libraries and include directories are on the
|
||||
system. LINK_PRIORITY defaults to prioritizing internal sources of the mapnik source folder, then local/user
|
||||
installed libraries over system libraries, but the option can be customized. Sorting not only ensures that
|
||||
compiling and linking will more likely match the desired libraries but also gives more likelyhood to avoid
|
||||
the scenario where libraries are linked that don't match the includes libmapnik compiled against.
|
||||
the scenario where libraries are linked that don`t match the includes libmapnik compiled against.
|
||||
|
||||
- XML: Fixed behavior of PolygonPatternSymbolizer and LinePatternSymbolizer whereby width, height,
|
||||
and type of images is actually allowed to be optionally ommitted ([#508](https://github.com/mapnik/mapnik/issues/508)). This was added in r1543 but
|
||||
|
@ -323,26 +357,26 @@ Released January, 19 2010
|
|||
|
||||
* Use the gdaladdo utility to add overviews to existing GDAL datasets
|
||||
|
||||
- PostGIS: Added an optional 'geometry_table' parameter. The 'geometry_table' used by Mapnik to look up
|
||||
metadata in the geometry_columns and calculate extents (when the 'geometry_field' and 'srid' parameters
|
||||
are not supplied). If 'geometry_table' is not specified Mapnik will attempt to determine the name of the
|
||||
table to query based on parsing the 'table' parameter, which may fail for complex queries with more than
|
||||
one 'from' keyword. Using this parameter should allow for existing metadata and table indexes to be used
|
||||
while opening the door to much more complicated subqueries being passed to the 'table' parameter without
|
||||
- PostGIS: Added an optional `geometry_table` parameter. The `geometry_table` used by Mapnik to look up
|
||||
metadata in the geometry_columns and calculate extents (when the `geometry_field` and `srid` parameters
|
||||
are not supplied). If `geometry_table` is not specified Mapnik will attempt to determine the name of the
|
||||
table to query based on parsing the `table` parameter, which may fail for complex queries with more than
|
||||
one `from` keyword. Using this parameter should allow for existing metadata and table indexes to be used
|
||||
while opening the door to much more complicated subqueries being passed to the `table` parameter without
|
||||
failing (#260, #426).
|
||||
|
||||
- PostGIS Plugin: Added optional 'geometry_field' and 'srid' parameters. If specified these will allow
|
||||
- PostGIS Plugin: Added optional `geometry_field` and `srid` parameters. If specified these will allow
|
||||
Mapnik to skip several queries to try to determine these values dynamically, and can be helpful to avoid
|
||||
possible query failures during metadata lookup with complex subqueries as discussed in #260 and #436, but
|
||||
also solvable by specifying the 'geometry_table' parameter. (r1300,#376)
|
||||
also solvable by specifying the `geometry_table` parameter. (r1300,#376)
|
||||
|
||||
- PostGIS: Added an optional 'extent_from_subquery' parameter that when true (while the 'extent' parameter is
|
||||
not provided and 'estimate_extent' is false) will direct Mapnik to calculate the extent upon the exact table
|
||||
or sql provided in the 'table' parameter. If a sub-select is used for the table parameter then this will,
|
||||
- PostGIS: Added an optional `extent_from_subquery` parameter that when true (while the `extent` parameter is
|
||||
not provided and `estimate_extent` is false) will direct Mapnik to calculate the extent upon the exact table
|
||||
or sql provided in the `table` parameter. If a sub-select is used for the table parameter then this will,
|
||||
in cases where the subquery limits results, provide a faster and more accurate layer extent. It will have
|
||||
no effect if the 'table' parameter is simply an existing table. This parameter is false by default. (#456)
|
||||
no effect if the `table` parameter is simply an existing table. This parameter is false by default. (#456)
|
||||
|
||||
- PostGIS Plugin: Added '!bbox!' token substitution ability in sql query string. This opens the door for various
|
||||
- PostGIS Plugin: Added `!bbox!` token substitution ability in sql query string. This opens the door for various
|
||||
complex queries that may aggregate geometries to be kept fast by allowing proper placement of the bbox
|
||||
query to be used by indexes. (#415)
|
||||
|
||||
|
@ -358,7 +392,7 @@ Released January, 19 2010
|
|||
(Select * from table where geom && !bbox!) as map
|
||||
</Parameter>
|
||||
|
||||
- PostGIS Plugin: Added 'scale_denominator' substitution ability in sql query string (#415/#465)
|
||||
- PostGIS Plugin: Added `scale_denominator` substitution ability in sql query string (#415/#465)
|
||||
|
||||
* Pass the scale_denominator token inside a subquery like: !scale_denominator!
|
||||
|
||||
|
@ -366,7 +400,7 @@ Released January, 19 2010
|
|||
|
||||
- PostGIS Plugin: Added support for quoted table names (r1454) (#393)
|
||||
|
||||
- PostGIS: Add a 'persist_connection' option (default true), that when false will release
|
||||
- PostGIS: Add a `persist_connection` option (default true), that when false will release
|
||||
the idle psql connection after datasource goes out of scope (r1337) (#433,#434)
|
||||
|
||||
- PostGIS: Added support for BigInt (int8) postgres type (384)
|
||||
|
@ -387,19 +421,19 @@ Released January, 19 2010
|
|||
|
||||
- PNG: Added support for semi-transparency in png256 output (#477,#202)
|
||||
|
||||
- PolygonSymbolizer: Added 'gamma' attribute to allow for dilation of polygon edges - a solution
|
||||
- PolygonSymbolizer: Added `gamma` attribute to allow for dilation of polygon edges - a solution
|
||||
to gap artifacts or "ghost lines" between adjacent polygons and allows for slight sharpening of
|
||||
the edges of non overlapping polygons. Accepts any values but 0-1 is the recommended range.
|
||||
|
||||
- TextSymbolizer: Large set of new attributes: 'text_transform', 'line_spacing', 'character_spacing',
|
||||
'wrap_character', 'wrap_before', 'horizontal_alignment', 'justify_alignment', and 'opacity'.
|
||||
- TextSymbolizer: Large set of new attributes: `text_transform`, `line_spacing`, `character_spacing`,
|
||||
`wrap_character`, `wrap_before`, `horizontal_alignment`, `justify_alignment`, and `opacity`.
|
||||
|
||||
* More details at changesets: r1254 and r1341
|
||||
|
||||
- SheildSymbolizer: Added special new attributes: 'unlock_image', 'VERTEX' placement, 'no_text' and many
|
||||
attributes previously only supported in the TextSymbolizer: 'allow_overlap', 'vertical_alignment',
|
||||
'horizontal_alignment', 'justify_alignment', 'wrap_width', 'wrap_character', 'wrap_before', 'text_transform',
|
||||
'line_spacing', 'character_spacing', and 'opacity'.
|
||||
- SheildSymbolizer: Added special new attributes: `unlock_image`, `VERTEX` placement, `no_text` and many
|
||||
attributes previously only supported in the TextSymbolizer: `allow_overlap`, `vertical_alignment`,
|
||||
`horizontal_alignment`, `justify_alignment`, `wrap_width`, `wrap_character`, `wrap_before`, `text_transform`,
|
||||
`line_spacing`, `character_spacing`, and `opacity`.
|
||||
|
||||
* More details at changeset r1341
|
||||
|
||||
|
@ -407,42 +441,42 @@ Released January, 19 2010
|
|||
|
||||
- XML: Fixed memory leak in libxml2 implementation (#473)
|
||||
|
||||
- XML: Added function to serialize map to string, called 'mapnik.save_map_to_string()' (#396)
|
||||
- XML: Added function to serialize map to string, called `mapnik.save_map_to_string()` (#396)
|
||||
|
||||
- XML: Added parameter to <Map> called 'minimum_version' to allow for enforcing the minimum Mapnik version
|
||||
- XML: Added parameter to <Map> called `minimum_version` to allow for enforcing the minimum Mapnik version
|
||||
needed for XML features used in the mapfiles. Uses Major.Minor.Point syntax, for example
|
||||
<Map minimum_version="0.6.1"> would throw an error if the user is running Mapnik less than 0.6.1.
|
||||
|
||||
- XML: Added support for relative paths when using entities and 'mapnik.load_map_from_string()' (#440)
|
||||
- XML: Added support for relative paths when using entities and `mapnik.load_map_from_string()` (#440)
|
||||
|
||||
- XML: Made width and height optional for symbolizers using images (r1543)
|
||||
|
||||
- XML: Ensured that default values for layers are not serialized in save_map() (r1366)
|
||||
|
||||
- XML: Added missing serialization of PointSymbolizer 'opacity' and 'allow_overlap' attributes (r1358)
|
||||
- XML: Added missing serialization of PointSymbolizer `opacity` and `allow_overlap` attributes (r1358)
|
||||
|
||||
- XML: Default text vertical_alignment now dependent on dy (#485, r1527)
|
||||
|
||||
- Python: Exposed ability to write to Cairo formats using 'mapnik.render_to_file()' and without pycairo (#381)
|
||||
- Python: Exposed ability to write to Cairo formats using `mapnik.render_to_file()` and without pycairo (#381)
|
||||
|
||||
- Python: Fixed potential crash if pycairo support is enabled but python-cairo module is missing (#392)
|
||||
|
||||
- Python: Added 'mapnik.has_pycairo()' function to test for pycairo support (r1278) (#284)
|
||||
- Python: Added `mapnik.has_pycairo()` function to test for pycairo support (r1278) (#284)
|
||||
|
||||
- Python: Added 'mapnik.register_plugins()' and 'mapnik.register_fonts()' functions (r1256)
|
||||
- Python: Added `mapnik.register_plugins()` and `mapnik.register_fonts()` functions (r1256)
|
||||
|
||||
- Python: Pickling support for point_symbolizer (r1295) (#345)
|
||||
|
||||
- Python: Ensured mapnik::config_errors now throw RuntimeError exception instead of UserWarning exception (#442)
|
||||
|
||||
- Filters: Added support for '!=' as an alias to '<>' for not-equals filters (avoids <>) (r1326) (#427)
|
||||
- Filters: Added support for `!=` as an alias to `<>` for not-equals filters (avoids <>) (r1326) (#427)
|
||||
|
||||
- SCons: Improved boost auto-detection (r1255,r1279)
|
||||
|
||||
- SCons: Fixed support for JOBS=N and FAST=True to enable faster compiling (r1440)
|
||||
|
||||
- SCons: Ensured that -h or --help will properly print help on custom Mapnik options before a user
|
||||
has been able to properly run 'configure'. (r1514)
|
||||
has been able to properly run `configure`. (r1514)
|
||||
|
||||
- SCons: Added ability to link to custom icu library name using ICU_LIB_NAME (r1414)
|
||||
|
||||
|
@ -457,7 +491,7 @@ Released July 14, 2009
|
|||
|
||||
(Packaged from r1247/353ff576c7)
|
||||
|
||||
- Plugins: expose list of registered plugins as a 'plugin_names()' method of DatasourceCache (r1180)
|
||||
- Plugins: expose list of registered plugins as a `plugin_names()` method of DatasourceCache (r1180)
|
||||
|
||||
- XML: Fixed serialization and parsing bugs related to handling of integers and Enums (#328,#353)
|
||||
|
||||
|
@ -497,13 +531,13 @@ Released July 14, 2009
|
|||
|
||||
- Python: Pickling support for raster_symbolizer (r1154) (#345)
|
||||
|
||||
- Python: Added 'mapnik.has_cairo()' function to test for cairo support (r1152) (#284)
|
||||
- Python: Added `mapnik.has_cairo()` function to test for cairo support (r1152) (#284)
|
||||
|
||||
- Python: Exposed dash_array get method (r1151) (#317)
|
||||
|
||||
- Python: Pickling support for Coord objects (#345)
|
||||
|
||||
- GDAL Plugin: Added an experimental option to open files in 'shared mode' (r1143)
|
||||
- GDAL Plugin: Added an experimental option to open files in `shared mode` (r1143)
|
||||
|
||||
- Python: Exposed RasterSymbolizer options in Python (r1139)
|
||||
|
||||
|
@ -515,13 +549,13 @@ Released July 14, 2009
|
|||
|
||||
- XML: Ensured relative paths in XML are interpreted relative to XML file location (r1124) (#326)
|
||||
|
||||
- XML: Added ability to serialize all default symbolizer values by passing third argument to save_map(m,'file.xml',True)(r1117) (#327)
|
||||
- XML: Added ability to serialize all default symbolizer values by passing third argument to save_map(m,`file.xml`,True)(r1117) (#327)
|
||||
|
||||
- Core: Added support for alpha transparency when writing to png256 (patch from Marcin Rudowski) (#202)
|
||||
|
||||
- SCons: Ensured ABI compatibility information is embedded in libmapnik.dylib on Mac OS X (#322)
|
||||
|
||||
- SCons: Ensured that the full 'install_name' path would be added to libmapnik.dylib on Mac OS X (#374)
|
||||
- SCons: Ensured that the full `install_name` path would be added to libmapnik.dylib on Mac OS X (#374)
|
||||
|
||||
- Tests: Added testing framework in Python using nose (r1101-r1105)
|
||||
|
||||
|
@ -546,7 +580,7 @@ Released April 1, 2009
|
|||
|
||||
- OGCServer Fixed axis-ordering for WMS 1.3.0 request (r1051) (#241)
|
||||
|
||||
- Plugins: Added option to all plugins to support using a 'base' path argument (r1042)
|
||||
- Plugins: Added option to all plugins to support using a `base` path argument (r1042)
|
||||
|
||||
- Symbolizers: RasterSymbolizer now support composing modes for hillshading (r1027)
|
||||
|
||||
|
@ -567,7 +601,7 @@ Released April 1, 2009
|
|||
- Plugins: PostGIS plugin now accepts multi-line queries (r862)
|
||||
|
||||
- Filter parsing: Allow numbers in the filter field name.
|
||||
This allows for shapefiles with columns like '1970'.
|
||||
This allows for shapefiles with columns like `1970`.
|
||||
|
||||
- Plugins: Added OGR driver for reading all OGR supported formats (kunitoki) (r836) (#170)
|
||||
|
||||
|
@ -589,7 +623,7 @@ Released April 1, 2009
|
|||
|
||||
- Core: Transformation is now skipped if srs values match exactly (r777)
|
||||
|
||||
- Symbolizers: 'min_distance' now honored for POINT placement using Text Symbolizer (r771)
|
||||
- Symbolizers: `min_distance` now honored for POINT placement using Text Symbolizer (r771)
|
||||
|
||||
- Plugins: PostGIS plugin now accepts a geometry_field,record_limit, cursor_size options (r769,r872)
|
||||
|
||||
|
|
15
SConstruct
|
@ -309,7 +309,9 @@ opts.AddVariables(
|
|||
PathVariable('ICU_LIBS','Search path for ICU include files','/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
|
||||
('ICU_LIB_NAME', 'The library name for icu (such as icuuc, sicuuc, or icucore)', 'icuuc'),
|
||||
PathVariable('PNG_INCLUDES', 'Search path for libpng include files', '/usr/include', PathVariable.PathAccept),
|
||||
PathVariable('PNG_LIBS','Search path for libpng include files','/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
|
||||
PathVariable('PNG_LIBS','Search path for libpng library files','/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
|
||||
PathVariable('LTDL_INCLUDES', 'Search path for libltdl (part of libtool) include files', '/usr/include', PathVariable.PathAccept),
|
||||
PathVariable('LTDL_LIBS','Search path for libltdl (ltdl.h) library files','/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
|
||||
BoolVariable('JPEG', 'Build Mapnik with JPEG read and write support', 'True'),
|
||||
PathVariable('JPEG_INCLUDES', 'Search path for libjpeg include files', '/usr/include', PathVariable.PathAccept),
|
||||
PathVariable('JPEG_LIBS', 'Search path for libjpeg library files', '/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept),
|
||||
|
@ -323,7 +325,7 @@ opts.AddVariables(
|
|||
|
||||
BoolVariable('RENDERING_STATS', 'Output rendering statistics during style processing', 'False'),
|
||||
|
||||
BoolVariable('SVG_RENDERER', 'build support for native svg renderer', 'False'),
|
||||
#BoolVariable('SVG_RENDERER', 'build support for native svg renderer', 'False'),
|
||||
|
||||
# Variables for optional dependencies
|
||||
('GEOS_CONFIG', 'The path to the geos-config executable.', 'geos-config'),
|
||||
|
@ -424,7 +426,7 @@ pickle_store = [# Scons internal variables
|
|||
'CAIROMM_LIBPATHS',
|
||||
'CAIROMM_LINKFLAGS',
|
||||
'CAIROMM_CPPPATHS',
|
||||
'SVG_RENDERER',
|
||||
#'SVG_RENDERER',
|
||||
'SQLITE_LINKFLAGS',
|
||||
'BOOST_LIB_VERSION_FROM_HEADER'
|
||||
]
|
||||
|
@ -1055,7 +1057,7 @@ if not preconfigured:
|
|||
|
||||
# Adding the required prerequisite library directories to the include path for
|
||||
# compiling and the library path for linking, respectively.
|
||||
for required in ('PNG', 'JPEG', 'TIFF','PROJ','ICU', 'SQLITE'):
|
||||
for required in ('PNG', 'JPEG', 'TIFF','PROJ','ICU', 'SQLITE', 'LTDL'):
|
||||
inc_path = env['%s_INCLUDES' % required]
|
||||
lib_path = env['%s_LIBS' % required]
|
||||
env.AppendUnique(CPPPATH = os.path.realpath(inc_path))
|
||||
|
@ -1442,7 +1444,7 @@ if not preconfigured:
|
|||
# fetch the mapnik version header in order to set the
|
||||
# ABI version used to build libmapnik.so on linux in src/build.py
|
||||
abi = conf.GetMapnikLibVersion()
|
||||
abi_fallback = "2.0.1-pre"
|
||||
abi_fallback = "2.2.0-pre"
|
||||
if not abi:
|
||||
color_print(1,'Problem encountered parsing mapnik version, falling back to %s' % abi_fallback)
|
||||
abi = abi_fallback
|
||||
|
@ -1738,7 +1740,8 @@ if not HELP_REQUESTED:
|
|||
# not ready for release
|
||||
SConscript('tests/cpp_tests/build.py')
|
||||
|
||||
# not ready for release
|
||||
# not currently maintained
|
||||
# https://github.com/mapnik/mapnik/issues/1438
|
||||
#if env['SVG_RENDERER']:
|
||||
# SConscript('tests/cpp_tests/svg_renderer_tests/build.py')
|
||||
|
||||
|
|
|
@ -664,6 +664,39 @@ class PythonDatasource(object):
|
|||
|
||||
return itertools.imap(make_it, features, itertools.count(1))
|
||||
|
||||
@classmethod
|
||||
def wkt_features(cls, keys, features):
|
||||
"""A convenience function to wrap an iterator yielding pairs of WKT format geometry and dictionaries of
|
||||
key-value pairs into mapnik features. Return this from PythonDatasource.features() passing it a sequence of keys
|
||||
to appear in the output and an iterator yielding features.
|
||||
|
||||
For example. One might have a features() method in a derived class like the following:
|
||||
|
||||
def features(self, query):
|
||||
# ... create WKT features feat1 and feat2
|
||||
|
||||
return mapnik.PythonDatasource.wkt_features(
|
||||
keys = ( 'name', 'author' ),
|
||||
features = [
|
||||
(feat1, { 'name': 'feat1', 'author': 'alice' }),
|
||||
(feat2, { 'name': 'feat2', 'author': 'bob' }),
|
||||
]
|
||||
)
|
||||
|
||||
"""
|
||||
ctx = Context()
|
||||
[ctx.push(x) for x in keys]
|
||||
|
||||
def make_it(feat, idx):
|
||||
f = Feature(ctx, idx)
|
||||
geom, attrs = feat
|
||||
f.add_geometries_from_wkt(geom)
|
||||
for k, v in attrs.iteritems():
|
||||
f[k] = v
|
||||
return f
|
||||
|
||||
return itertools.imap(make_it, features, itertools.count(1))
|
||||
|
||||
class _TextSymbolizer(TextSymbolizer,_injector):
|
||||
@property
|
||||
def text_size(self):
|
||||
|
@ -760,6 +793,18 @@ class _TextSymbolizer(TextSymbolizer,_injector):
|
|||
self.format.wrap_char = wrap_char
|
||||
|
||||
|
||||
@property
|
||||
def wrap_character(self):
|
||||
warnings.warn("'wrap_character' is deprecated, use format.wrap_character",
|
||||
DeprecationWarning, 2)
|
||||
return self.format.wrap_character
|
||||
|
||||
@wrap_char.setter
|
||||
def wrap_character(self, wrap_character):
|
||||
warnings.warn("'wrap_char' is deprecated, use format.wrap_character",
|
||||
DeprecationWarning, 2)
|
||||
self.format.wrap_character = wrap_character
|
||||
|
||||
|
||||
@property
|
||||
def wrap_before(self):
|
||||
|
|
50
bindings/python/mapnik_building_symbolizer.cpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2012 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
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <boost/python.hpp>
|
||||
#include <mapnik/building_symbolizer.hpp>
|
||||
|
||||
using namespace mapnik;
|
||||
using mapnik::building_symbolizer;
|
||||
using mapnik::color;
|
||||
|
||||
void export_building_symbolizer()
|
||||
{
|
||||
using namespace boost::python;
|
||||
|
||||
class_<building_symbolizer>("BuildingSymbolizer",
|
||||
init<>("Default BuildingSymbolizer"))
|
||||
.add_property("fill",make_function
|
||||
(&building_symbolizer::get_fill,
|
||||
return_value_policy<copy_const_reference>()),
|
||||
&building_symbolizer::set_fill)
|
||||
.add_property("fill_opacity",
|
||||
&building_symbolizer::get_opacity,
|
||||
&building_symbolizer::set_opacity)
|
||||
.add_property("height",
|
||||
make_function(&building_symbolizer::height,
|
||||
return_value_policy<copy_const_reference>()),
|
||||
&building_symbolizer::set_height,
|
||||
"Set/get the building height")
|
||||
;
|
||||
|
||||
}
|
|
@ -38,6 +38,7 @@
|
|||
#if BOOST_VERSION >= 104700
|
||||
#include <mapnik/util/geometry_to_wkb.hpp>
|
||||
#include <mapnik/util/geometry_to_wkt.hpp>
|
||||
#include <mapnik/util/geometry_to_svg.hpp>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
@ -224,6 +225,41 @@ std::string to_geojson( path_type const& geom)
|
|||
return json;
|
||||
}
|
||||
|
||||
std::string to_svg( geometry_type const& geom)
|
||||
{
|
||||
#if BOOST_VERSION >= 104700
|
||||
std::string svg; // Use Python String directly ?
|
||||
bool result = mapnik::util::to_svg(svg,geom);
|
||||
if (!result)
|
||||
{
|
||||
throw std::runtime_error("Generate WKT failed");
|
||||
}
|
||||
return svg;
|
||||
#else
|
||||
throw std::runtime_error("mapnik::to_wkt() requires at least boost 1.47 while your build was compiled against boost "
|
||||
+ boost_version());
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
// https://github.com/mapnik/mapnik/issues/1437
|
||||
std::string to_svg2( path_type const& geom)
|
||||
{
|
||||
#if BOOST_VERSION >= 104700
|
||||
std::string svg; // Use Python String directly ?
|
||||
bool result = mapnik::util::to_svg(svg,geom);
|
||||
if (!result)
|
||||
{
|
||||
throw std::runtime_error("Generate WKT failed");
|
||||
}
|
||||
return svg;
|
||||
#else
|
||||
throw std::runtime_error("mapnik::to_svg() requires at least boost 1.47 while your build was compiled against boost "
|
||||
+ boost_version());
|
||||
#endif
|
||||
}*/
|
||||
|
||||
|
||||
void export_geometry()
|
||||
{
|
||||
using namespace boost::python;
|
||||
|
@ -248,6 +284,7 @@ void export_geometry()
|
|||
.def("type",&geometry_type::type)
|
||||
.def("to_wkb",&to_wkb)
|
||||
.def("to_wkt",&to_wkt)
|
||||
.def("to_svg",&to_svg)
|
||||
// TODO add other geometry_type methods
|
||||
;
|
||||
|
||||
|
@ -259,6 +296,7 @@ void export_geometry()
|
|||
.def("add_wkb",add_wkb_impl)
|
||||
.def("add_geojson",add_geojson_impl)
|
||||
.def("to_wkt",&to_wkt2)
|
||||
//.def("to_svg",&to_svg2)
|
||||
.def("to_wkb",&to_wkb2)
|
||||
.def("from_wkt",from_wkt_impl)
|
||||
.def("from_wkb",from_wkb_impl)
|
||||
|
|
|
@ -161,7 +161,7 @@ void export_layer()
|
|||
.add_property("active",
|
||||
&layer::active,
|
||||
&layer::set_active,
|
||||
"Get/Set whether this layer is active and will be rendered.\n"
|
||||
"Get/Set whether this layer is active and will be rendered (same as status property).\n"
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
">>> from mapnik import Layer\n"
|
||||
|
@ -173,6 +173,21 @@ void export_layer()
|
|||
"False\n"
|
||||
)
|
||||
|
||||
.add_property("status",
|
||||
&layer::active,
|
||||
&layer::set_active,
|
||||
"Get/Set whether this layer is active and will be rendered.\n"
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
">>> from mapnik import Layer\n"
|
||||
">>> lyr = Layer('My Layer','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')\n"
|
||||
">>> lyr.status\n"
|
||||
"True # Active by default\n"
|
||||
">>> lyr.status = False # set False to disable layer rendering\n"
|
||||
">>> lyr.status\n"
|
||||
"False\n"
|
||||
)
|
||||
|
||||
.add_property("clear_label_cache",
|
||||
&layer::clear_label_cache,
|
||||
&layer::set_clear_label_cache,
|
||||
|
@ -304,6 +319,14 @@ void export_layer()
|
|||
">>> lyr.srs = '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over'\n"
|
||||
)
|
||||
|
||||
.add_property("group_by",
|
||||
make_function(&layer::group_by,return_value_policy<copy_const_reference>()),
|
||||
&layer::set_group_by,
|
||||
"Get/Set the optional layer group name.\n"
|
||||
"\n"
|
||||
"More details at https://github.com/mapnik/mapnik/wiki/Grouped-rendering:\n"
|
||||
)
|
||||
|
||||
.add_property("styles",
|
||||
make_function(_styles_,return_value_policy<reference_existing_object>()),
|
||||
"The styles list attached to this layer.\n"
|
||||
|
|
|
@ -62,5 +62,17 @@ void export_line_pattern_symbolizer()
|
|||
.add_property("filename",
|
||||
&get_filename,
|
||||
&set_filename)
|
||||
.add_property("comp_op",
|
||||
&line_pattern_symbolizer::comp_op,
|
||||
&line_pattern_symbolizer::set_comp_op,
|
||||
"Set/get the comp-op")
|
||||
.add_property("clip",
|
||||
&line_pattern_symbolizer::clip,
|
||||
&line_pattern_symbolizer::set_clip,
|
||||
"Set/get the line pattern geometry's clipping status")
|
||||
.add_property("smooth",
|
||||
&line_pattern_symbolizer::smooth,
|
||||
&line_pattern_symbolizer::set_smooth,
|
||||
"smooth value (0..1.0)")
|
||||
;
|
||||
}
|
||||
|
|
|
@ -48,17 +48,25 @@ void export_line_symbolizer()
|
|||
(&line_symbolizer::get_stroke,
|
||||
return_value_policy<reference_existing_object>()),
|
||||
&line_symbolizer::set_stroke)
|
||||
.add_property("smooth",
|
||||
&line_symbolizer::smooth,
|
||||
&line_symbolizer::set_smooth,
|
||||
"smooth value (0..1.0)")
|
||||
.add_property("simplify_tolerance",
|
||||
&line_symbolizer::simplify_tolerance,
|
||||
&line_symbolizer::set_simplify_tolerance,
|
||||
"simplfication tolerance measure")
|
||||
"simplification tolerance measure")
|
||||
.add_property("offset",
|
||||
&line_symbolizer::offset,
|
||||
&line_symbolizer::set_offset,
|
||||
"offset value")
|
||||
.add_property("comp_op",
|
||||
&line_symbolizer::comp_op,
|
||||
&line_symbolizer::set_comp_op,
|
||||
"Set/get the comp-op")
|
||||
.add_property("clip",
|
||||
&line_symbolizer::clip,
|
||||
&line_symbolizer::set_clip,
|
||||
"Set/get the line geometry's clipping status")
|
||||
.add_property("smooth",
|
||||
&line_symbolizer::smooth,
|
||||
&line_symbolizer::set_smooth,
|
||||
"smooth value (0..1.0)")
|
||||
;
|
||||
}
|
||||
|
|
|
@ -370,12 +370,30 @@ void export_map()
|
|||
.add_property("background",make_function
|
||||
(&Map::background,return_value_policy<copy_const_reference>()),
|
||||
&Map::set_background,
|
||||
"The background color of the map.\n"
|
||||
"The background color of the map (same as background_color property).\n"
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
">>> m.background = Color('steelblue')\n"
|
||||
)
|
||||
|
||||
.add_property("background_color",make_function
|
||||
(&Map::background,return_value_policy<copy_const_reference>()),
|
||||
&Map::set_background,
|
||||
"The background color of the map.\n"
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
">>> m.background_color = Color('steelblue')\n"
|
||||
)
|
||||
|
||||
.add_property("background_image",make_function
|
||||
(&Map::background_image,return_value_policy<copy_const_reference>()),
|
||||
&Map::set_background_image,
|
||||
"The optional background image of the map.\n"
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
">>> m.background_image = '/path/to/image.png'\n"
|
||||
)
|
||||
|
||||
.add_property("base",
|
||||
make_function(&Map::base_path,return_value_policy<copy_const_reference>()),
|
||||
&Map::set_base_path,
|
||||
|
|
|
@ -23,11 +23,13 @@
|
|||
#include <boost/python.hpp>
|
||||
|
||||
#include <mapnik/graphics.hpp>
|
||||
#include <mapnik/value_error.hpp>
|
||||
#include <mapnik/image_util.hpp>
|
||||
#include <mapnik/markers_symbolizer.hpp>
|
||||
#include <mapnik/parse_path.hpp>
|
||||
#include "mapnik_svg.hpp"
|
||||
#include "mapnik_enumeration.hpp"
|
||||
#include <mapnik/marker_cache.hpp> // for known_svg_prefix_
|
||||
|
||||
using mapnik::markers_symbolizer;
|
||||
using mapnik::symbolizer_with_image;
|
||||
|
@ -47,8 +49,27 @@ void set_filename(mapnik::markers_symbolizer & symbolizer, std::string const& fi
|
|||
symbolizer.set_filename(parse_path(file_expr));
|
||||
}
|
||||
|
||||
void set_marker_type(mapnik::markers_symbolizer & symbolizer, std::string const& marker_type)
|
||||
{
|
||||
std::string filename;
|
||||
if (marker_type == "ellipse")
|
||||
{
|
||||
filename = mapnik::marker_cache::known_svg_prefix_ + "ellipse";
|
||||
}
|
||||
else if (marker_type == "arrow")
|
||||
{
|
||||
filename = mapnik::marker_cache::known_svg_prefix_ + "arrow";
|
||||
}
|
||||
else
|
||||
{
|
||||
throw mapnik::value_error("Unknown marker-type: '" + marker_type + "'");
|
||||
}
|
||||
symbolizer.set_filename(parse_path(filename));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// https://github.com/mapnik/mapnik/issues/1367
|
||||
PyObject* get_fill_opacity_impl(markers_symbolizer & sym)
|
||||
{
|
||||
|
@ -74,6 +95,9 @@ void export_markers_symbolizer()
|
|||
.add_property("filename",
|
||||
&get_filename,
|
||||
&set_filename)
|
||||
.add_property("marker_type",
|
||||
&get_filename,
|
||||
&set_marker_type)
|
||||
.add_property("allow_overlap",
|
||||
&markers_symbolizer::get_allow_overlap,
|
||||
&markers_symbolizer::set_allow_overlap)
|
||||
|
@ -119,5 +143,17 @@ void export_markers_symbolizer()
|
|||
&markers_symbolizer::get_marker_placement,
|
||||
&markers_symbolizer::set_marker_placement,
|
||||
"Set/get the marker placement")
|
||||
.add_property("comp_op",
|
||||
&markers_symbolizer::comp_op,
|
||||
&markers_symbolizer::set_comp_op,
|
||||
"Set/get the marker comp-op")
|
||||
.add_property("clip",
|
||||
&markers_symbolizer::clip,
|
||||
&markers_symbolizer::set_clip,
|
||||
"Set/get the marker geometry's clipping status")
|
||||
.add_property("smooth",
|
||||
&markers_symbolizer::smooth,
|
||||
&markers_symbolizer::set_smooth,
|
||||
"Set/get the marker geometry's smooth value")
|
||||
;
|
||||
}
|
||||
|
|
|
@ -81,5 +81,9 @@ void export_point_symbolizer()
|
|||
.add_property("transform",
|
||||
mapnik::get_svg_transform<point_symbolizer>,
|
||||
mapnik::set_svg_transform<point_symbolizer>)
|
||||
.add_property("comp_op",
|
||||
&point_symbolizer::comp_op,
|
||||
&point_symbolizer::set_comp_op,
|
||||
"Set/get the comp-op")
|
||||
;
|
||||
}
|
||||
|
|
|
@ -70,6 +70,9 @@ void export_polygon_pattern_symbolizer()
|
|||
.add_property("filename",
|
||||
&get_filename,
|
||||
&set_filename)
|
||||
.add_property("opacity",
|
||||
&polygon_pattern_symbolizer::get_opacity,
|
||||
&polygon_pattern_symbolizer::set_opacity)
|
||||
.add_property("gamma",
|
||||
&polygon_pattern_symbolizer::get_gamma,
|
||||
&polygon_pattern_symbolizer::set_gamma)
|
||||
|
@ -77,5 +80,17 @@ void export_polygon_pattern_symbolizer()
|
|||
&polygon_pattern_symbolizer::get_gamma_method,
|
||||
&polygon_pattern_symbolizer::set_gamma_method,
|
||||
"Set/get the gamma correction method of the polygon")
|
||||
.add_property("comp_op",
|
||||
&polygon_pattern_symbolizer::comp_op,
|
||||
&polygon_pattern_symbolizer::set_comp_op,
|
||||
"Set/get the pattern comp-op")
|
||||
.add_property("clip",
|
||||
&polygon_pattern_symbolizer::clip,
|
||||
&polygon_pattern_symbolizer::set_clip,
|
||||
"Set/get the pattern geometry's clipping status")
|
||||
.add_property("smooth",
|
||||
&polygon_pattern_symbolizer::smooth,
|
||||
&polygon_pattern_symbolizer::set_smooth,
|
||||
"Set/get the pattern geometry's smooth value")
|
||||
;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#include <boost/python.hpp>
|
||||
#include "mapnik_enumeration.hpp"
|
||||
#include <mapnik/polygon_symbolizer.hpp>
|
||||
|
||||
using namespace mapnik;
|
||||
|
@ -49,10 +48,18 @@ void export_polygon_symbolizer()
|
|||
&polygon_symbolizer::get_gamma_method,
|
||||
&polygon_symbolizer::set_gamma_method,
|
||||
"gamma correction method")
|
||||
.add_property("comp_op",
|
||||
&polygon_symbolizer::comp_op,
|
||||
&polygon_symbolizer::set_comp_op,
|
||||
"Set/get the polygon comp-op")
|
||||
.add_property("clip",
|
||||
&polygon_symbolizer::clip,
|
||||
&polygon_symbolizer::set_clip,
|
||||
"Set/get the polygon geometry's clipping status")
|
||||
.add_property("smooth",
|
||||
&polygon_symbolizer::smooth,
|
||||
&polygon_symbolizer::set_smooth,
|
||||
"smooth value (0..1.0)")
|
||||
"Set/get the polygon geometry's smooth value")
|
||||
.add_property("simplify_tolerance",
|
||||
&polygon_symbolizer::simplify_tolerance,
|
||||
&polygon_symbolizer::set_simplify_tolerance,
|
||||
|
|
|
@ -57,6 +57,7 @@ void export_point_symbolizer();
|
|||
void export_line_symbolizer();
|
||||
void export_line_pattern_symbolizer();
|
||||
void export_polygon_symbolizer();
|
||||
void export_building_symbolizer();
|
||||
void export_polygon_pattern_symbolizer();
|
||||
void export_raster_symbolizer();
|
||||
void export_text_placement();
|
||||
|
@ -395,6 +396,7 @@ BOOST_PYTHON_MODULE(_mapnik)
|
|||
export_line_symbolizer();
|
||||
export_line_pattern_symbolizer();
|
||||
export_polygon_symbolizer();
|
||||
export_building_symbolizer();
|
||||
export_polygon_pattern_symbolizer();
|
||||
export_raster_symbolizer();
|
||||
export_text_placement();
|
||||
|
@ -617,6 +619,7 @@ BOOST_PYTHON_MODULE(_mapnik)
|
|||
python_optional<mapnik::stroke>();
|
||||
python_optional<mapnik::color>();
|
||||
python_optional<mapnik::box2d<double> >();
|
||||
python_optional<mapnik::composite_mode_e>();
|
||||
python_optional<mapnik::datasource::geometry_t>();
|
||||
python_optional<std::string>();
|
||||
python_optional<unsigned>();
|
||||
|
|
|
@ -39,18 +39,13 @@ void export_raster_symbolizer()
|
|||
.add_property("mode",
|
||||
make_function(&raster_symbolizer::get_mode,return_value_policy<copy_const_reference>()),
|
||||
&raster_symbolizer::set_mode,
|
||||
"Get/Set merging mode.\n"
|
||||
"Possible values are:\n"
|
||||
"normal, grain_merge, grain_merge2, multiply,\n"
|
||||
"multiply2, divide, divide2, screen, and hard_light\n"
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
"\n"
|
||||
">>> from mapnik import RasterSymbolizer\n"
|
||||
">>> r = RasterSymbolizer()\n"
|
||||
">>> r.mode = 'grain_merge2'\n"
|
||||
"Get/Set merging mode. (deprecated, use comp_op instead)\n"
|
||||
)
|
||||
.add_property("comp_op",
|
||||
&raster_symbolizer::comp_op,
|
||||
&raster_symbolizer::set_comp_op,
|
||||
"Set/get the raster comp-op"
|
||||
)
|
||||
|
||||
.add_property("scaling",
|
||||
&raster_symbolizer::get_scaling_method,
|
||||
&raster_symbolizer::set_scaling_method,
|
||||
|
|
|
@ -205,5 +205,13 @@ void export_shield_symbolizer()
|
|||
.add_property("transform",
|
||||
mapnik::get_svg_transform<shield_symbolizer>,
|
||||
mapnik::set_svg_transform<shield_symbolizer>)
|
||||
.add_property("comp_op",
|
||||
&shield_symbolizer::comp_op,
|
||||
&shield_symbolizer::set_comp_op,
|
||||
"Set/get the comp-op")
|
||||
.add_property("clip",
|
||||
&shield_symbolizer::clip,
|
||||
&shield_symbolizer::set_clip,
|
||||
"Set/get the shield geometry's clipping status")
|
||||
;
|
||||
}
|
||||
|
|
|
@ -32,10 +32,9 @@ using namespace mapnik;
|
|||
namespace {
|
||||
using namespace boost::python;
|
||||
|
||||
list get_dashes_list(const stroke& stroke)
|
||||
list get_dashes_list(stroke const& stroke)
|
||||
{
|
||||
list l;
|
||||
|
||||
if (stroke.has_dash()) {
|
||||
mapnik::dash_array const& dash = stroke.get_dash_array();
|
||||
mapnik::dash_array::const_iterator iter = dash.begin();
|
||||
|
@ -44,9 +43,23 @@ list get_dashes_list(const stroke& stroke)
|
|||
l.append(make_tuple(iter->first, iter->second));
|
||||
}
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
void set_dasharray(stroke & stroke, list const& l)
|
||||
{
|
||||
for (int i=0; i<len(l); ++i)
|
||||
{
|
||||
boost::python::tuple dash = extract<boost::python::tuple>(l[i]);
|
||||
if (len(dash) == 2)
|
||||
{
|
||||
double d1 = extract<double>(dash[0]);
|
||||
double d2 = extract<double>(dash[1]);
|
||||
stroke.add_dash(d1,d2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void export_stroke ()
|
||||
|
@ -101,18 +114,37 @@ void export_stroke ()
|
|||
.add_property("line_cap",
|
||||
&stroke::get_line_cap,
|
||||
&stroke::set_line_cap,
|
||||
"Gets or sets the line cap of this stroke.\n")
|
||||
"Gets or sets the line cap of this stroke. (alias of linecap)\n")
|
||||
.add_property("linecap",
|
||||
&stroke::get_line_cap,
|
||||
&stroke::set_line_cap,
|
||||
"Gets or sets the linecap of this stroke.\n")
|
||||
.add_property("line_join",
|
||||
&stroke::get_line_join,
|
||||
&stroke::set_line_join,
|
||||
"Returns the line join mode of this stroke.\n")
|
||||
// todo consider providing a single get/set property
|
||||
"Returns the line join mode of this stroke. (alias of linejoin)\n")
|
||||
.add_property("linejoin",
|
||||
&stroke::get_line_join,
|
||||
&stroke::set_line_join,
|
||||
"Returns the linejoin mode of this stroke.\n")
|
||||
.add_property("miterlimit",
|
||||
&stroke::get_miterlimit,
|
||||
&stroke::set_miterlimit,
|
||||
"Returns the miterlimit mode of this stroke.\n")
|
||||
.def("add_dash",&stroke::add_dash,
|
||||
(arg("length"),arg("gap")),
|
||||
"Adds a dash segment to the dash patterns of this stroke.\n")
|
||||
.def("get_dashes", get_dashes_list,
|
||||
"Returns the list of dash segments for this stroke.\n")
|
||||
.add_property("dasharray",
|
||||
get_dashes_list,
|
||||
set_dasharray,
|
||||
"Gets or sets dasharray string of this stroke. (alternate property to add_dash/get_dashes)\n")
|
||||
.add_property("dash_offset",
|
||||
&stroke::dash_offset,
|
||||
&stroke::set_dash_offset,
|
||||
"Gets or sets dash offset of this stroke. (alias of dashoffet)\n")
|
||||
.add_property("dashoffset",
|
||||
&stroke::dash_offset,
|
||||
&stroke::set_dash_offset,
|
||||
"Gets or sets dash offset of this stroke.\n")
|
||||
|
|
|
@ -25,13 +25,40 @@
|
|||
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/value_error.hpp>
|
||||
#include "mapnik_enumeration.hpp"
|
||||
#include <mapnik/feature_type_style.hpp>
|
||||
#include <mapnik/image_filter_grammar.hpp> // image_filter_grammar
|
||||
#include <mapnik/image_filter_types.hpp> // generate_image_filters
|
||||
|
||||
using mapnik::feature_type_style;
|
||||
using mapnik::rules;
|
||||
using mapnik::rule;
|
||||
|
||||
std::string get_image_filters(feature_type_style & style)
|
||||
{
|
||||
std::string filters_str;
|
||||
std::back_insert_iterator<std::string> sink(filters_str);
|
||||
generate_image_filters(sink, style.image_filters());
|
||||
return filters_str;
|
||||
}
|
||||
|
||||
void set_image_filters(feature_type_style & style, std::string const& filters)
|
||||
{
|
||||
std::string::const_iterator itr = filters.begin();
|
||||
std::string::const_iterator end = filters.end();
|
||||
mapnik::image_filter_grammar<std::string::const_iterator,
|
||||
std::vector<mapnik::filter::filter_type> > filter_grammar;
|
||||
bool result = boost::spirit::qi::phrase_parse(itr,end,
|
||||
filter_grammar,
|
||||
boost::spirit::qi::ascii::space,
|
||||
style.image_filters());
|
||||
if (!result || itr!=end)
|
||||
{
|
||||
throw mapnik::value_error("failed to parse image-filters: '" + std::string(itr,end) + "'");
|
||||
}
|
||||
}
|
||||
|
||||
void export_style()
|
||||
{
|
||||
using namespace boost::python;
|
||||
|
@ -61,6 +88,18 @@ void export_style()
|
|||
&feature_type_style::get_filter_mode,
|
||||
&feature_type_style::set_filter_mode,
|
||||
"Set/get the filter mode of the style")
|
||||
.add_property("opacity",
|
||||
&feature_type_style::get_opacity,
|
||||
&feature_type_style::set_opacity,
|
||||
"Set/get the opacity of the style")
|
||||
.add_property("comp_op",
|
||||
&feature_type_style::comp_op,
|
||||
&feature_type_style::set_comp_op,
|
||||
"Set/get the comp-op (composite operation) of the style")
|
||||
.add_property("image_filters",
|
||||
get_image_filters,
|
||||
set_image_filters,
|
||||
"Set/get the comp-op (composite operation) of the style")
|
||||
;
|
||||
|
||||
}
|
||||
|
|
|
@ -354,6 +354,14 @@ void export_text_placement()
|
|||
make_function(&get_properties, return_value_policy<reference_existing_object>()),
|
||||
&set_properties,
|
||||
"Shortcut for placements.defaults")
|
||||
.add_property("comp_op",
|
||||
&text_symbolizer::comp_op,
|
||||
&text_symbolizer::set_comp_op,
|
||||
"Set/get the comp-op")
|
||||
.add_property("clip",
|
||||
&text_symbolizer::clip,
|
||||
&text_symbolizer::set_clip,
|
||||
"Set/get the text geometry's clipping status")
|
||||
;
|
||||
|
||||
|
||||
|
@ -390,8 +398,10 @@ void export_text_placement()
|
|||
set_old_style expression is just a compatibility wrapper and doesn't need to be exposed in python. */
|
||||
;
|
||||
|
||||
class_<char_properties>
|
||||
|
||||
class_with_converter<char_properties>
|
||||
("CharProperties")
|
||||
.def_readwrite_convert("text_transform", &char_properties::text_transform)
|
||||
.def(init<char_properties const&>()) //Copy constructor
|
||||
.def_readwrite("face_name", &char_properties::face_name)
|
||||
.def_readwrite("fontset", &char_properties::fontset)
|
||||
|
@ -400,8 +410,8 @@ void export_text_placement()
|
|||
.def_readwrite("line_spacing", &char_properties::line_spacing)
|
||||
.def_readwrite("text_opacity", &char_properties::text_opacity)
|
||||
.def_readwrite("wrap_char", &char_properties::wrap_char)
|
||||
.def_readwrite("wrap_character", &char_properties::wrap_char)
|
||||
.def_readwrite("wrap_before", &char_properties::wrap_before)
|
||||
.def_readwrite("text_transform", &char_properties::text_transform)
|
||||
.def_readwrite("fill", &char_properties::fill)
|
||||
.def_readwrite("halo_fill", &char_properties::halo_fill)
|
||||
.def_readwrite("halo_radius", &char_properties::halo_radius)
|
||||
|
@ -488,6 +498,7 @@ void export_text_placement()
|
|||
.def_readwrite_convert("line_spacing", &formatting::format_node::line_spacing)
|
||||
.def_readwrite_convert("text_opacity", &formatting::format_node::text_opacity)
|
||||
.def_readwrite_convert("wrap_char", &formatting::format_node::wrap_char)
|
||||
.def_readwrite_convert("wrap_character", &formatting::format_node::wrap_char)
|
||||
.def_readwrite_convert("wrap_before", &formatting::format_node::wrap_before)
|
||||
.def_readwrite_convert("text_transform", &formatting::format_node::text_transform)
|
||||
.def_readwrite_convert("fill", &formatting::format_node::fill)
|
||||
|
@ -527,6 +538,7 @@ void export_text_placement()
|
|||
.def_readwrite("line_spacing", &formatting::expression_format::line_spacing)
|
||||
.def_readwrite("text_opacity", &formatting::expression_format::text_opacity)
|
||||
.def_readwrite("wrap_char", &formatting::expression_format::wrap_char)
|
||||
.def_readwrite("wrap_character", &formatting::expression_format::wrap_char)
|
||||
.def_readwrite("wrap_before", &formatting::expression_format::wrap_before)
|
||||
.def_readwrite("fill", &formatting::expression_format::fill)
|
||||
.def_readwrite("halo_fill", &formatting::expression_format::halo_fill)
|
||||
|
|
|
@ -34,11 +34,11 @@ namespace mapnik
|
|||
struct MAPNIK_DECL building_symbolizer : public symbolizer_base
|
||||
{
|
||||
building_symbolizer();
|
||||
building_symbolizer(color const& fill, expression_ptr height);
|
||||
building_symbolizer(color const& fill, expression_ptr const& height);
|
||||
color const& get_fill() const;
|
||||
void set_fill(color const& fill);
|
||||
expression_ptr height() const;
|
||||
void set_height(expression_ptr height);
|
||||
expression_ptr const& height() const;
|
||||
void set_height(expression_ptr const& height);
|
||||
void set_opacity(double opacity);
|
||||
double get_opacity() const;
|
||||
|
||||
|
|
|
@ -276,10 +276,10 @@ bool middle_point(PathType & path, double & x, double & y)
|
|||
template <typename PathType>
|
||||
bool centroid(PathType & path, double & x, double & y)
|
||||
{
|
||||
double x0 = 0;
|
||||
double y0 = 0;
|
||||
double x1 = 0;
|
||||
double y1 = 0;
|
||||
double x0 = 0.0;
|
||||
double y0 = 0.0;
|
||||
double x1 = 0.0;
|
||||
double y1 = 0.0;
|
||||
double start_x;
|
||||
double start_y;
|
||||
|
||||
|
@ -290,9 +290,9 @@ bool centroid(PathType & path, double & x, double & y)
|
|||
start_x = x0;
|
||||
start_y = y0;
|
||||
|
||||
double atmp = 0;
|
||||
double xtmp = 0;
|
||||
double ytmp = 0;
|
||||
double atmp = 0.0;
|
||||
double xtmp = 0.0;
|
||||
double ytmp = 0.0;
|
||||
unsigned count = 1;
|
||||
while (SEG_END != (command = path.vertex(&x1, &y1)))
|
||||
{
|
||||
|
@ -310,10 +310,9 @@ bool centroid(PathType & path, double & x, double & y)
|
|||
++count;
|
||||
}
|
||||
|
||||
if (count == 1)
|
||||
{
|
||||
x = start_x;
|
||||
y = start_y;
|
||||
if (count <= 2) {
|
||||
x = (start_x + x0) * 0.5;
|
||||
y = (start_y + y0) * 0.5;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -368,14 +367,15 @@ bool hit_test(PathType & path, double x, double y, double tol)
|
|||
}
|
||||
|
||||
template <typename PathType>
|
||||
void interior_position(PathType & path, double & x, double & y)
|
||||
bool interior_position(PathType & path, double & x, double & y)
|
||||
{
|
||||
// start with the centroid
|
||||
label::centroid(path, x,y);
|
||||
if (!label::centroid(path, x,y))
|
||||
return false;
|
||||
|
||||
// if we are not a polygon, or the default is within the polygon we are done
|
||||
if (hit_test(path,x,y,0.001))
|
||||
return;
|
||||
return true;
|
||||
|
||||
// otherwise we find a horizontal line across the polygon and then return the
|
||||
// center of the widest intersection between the polygon and the line.
|
||||
|
@ -422,7 +422,7 @@ void interior_position(PathType & path, double & x, double & y)
|
|||
}
|
||||
// no intersections we just return the default
|
||||
if (intersections.empty())
|
||||
return;
|
||||
return true;
|
||||
x0=intersections[0];
|
||||
double max_width = 0;
|
||||
for (unsigned ii = 1; ii < intersections.size(); ++ii)
|
||||
|
@ -437,6 +437,7 @@ void interior_position(PathType & path, double & x, double & y)
|
|||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
// mapnik
|
||||
#include <mapnik/vertex_vector.hpp>
|
||||
#include <mapnik/geom_util.hpp>
|
||||
#include <mapnik/box2d.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
// mapnik
|
||||
#include <mapnik/markers_symbolizer.hpp>
|
||||
#include <mapnik/markers_placement.hpp>
|
||||
#include <mapnik/geometry.hpp>
|
||||
#include <mapnik/geom_util.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_renderer_scanline.h"
|
||||
|
@ -78,15 +80,17 @@ struct raster_markers_rasterizer_dispatch_grid
|
|||
box2d<double> bbox_(0,0, src_.width(),src_.height());
|
||||
if (placement_method != MARKER_LINE_PLACEMENT)
|
||||
{
|
||||
double x,y;
|
||||
path.rewind(0);
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
if (placement_method == MARKER_INTERIOR_PLACEMENT)
|
||||
{
|
||||
label::interior_position(path, x, y);
|
||||
if (!label::interior_position(path, x, y))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
label::centroid(path, x, y);
|
||||
if (!label::centroid(path, x, y))
|
||||
return;
|
||||
}
|
||||
agg::trans_affine matrix = marker_trans_;
|
||||
matrix.translate(x,y);
|
||||
|
@ -207,15 +211,17 @@ struct vector_markers_rasterizer_dispatch_grid
|
|||
marker_placement_e placement_method = sym_.get_marker_placement();
|
||||
if (placement_method != MARKER_LINE_PLACEMENT)
|
||||
{
|
||||
double x,y;
|
||||
path.rewind(0);
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
if (placement_method == MARKER_INTERIOR_PLACEMENT)
|
||||
{
|
||||
label::interior_position(path, x, y);
|
||||
if (!label::interior_position(path, x, y))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
label::centroid(path, x, y);
|
||||
if (!label::centroid(path, x, y))
|
||||
return;
|
||||
}
|
||||
agg::trans_affine matrix = marker_trans_;
|
||||
matrix.translate(x,y);
|
||||
|
|
48
include/mapnik/image_filter_grammar.hpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2012 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_IMAGE_FILITER_GRAMMAR_HPP
|
||||
#define MAPNIK_IMAGE_FILITER_GRAMMAR_HPP
|
||||
|
||||
// boost
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
|
||||
// stl
|
||||
#include <vector>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
||||
template <typename Iterator, typename ContType>
|
||||
struct image_filter_grammar :
|
||||
qi::grammar<Iterator, ContType(), qi::ascii::space_type>
|
||||
{
|
||||
image_filter_grammar();
|
||||
qi::rule<Iterator, ContType(), qi::ascii::space_type> start;
|
||||
qi::rule<Iterator, ContType(), qi::locals<int,int>, qi::ascii::space_type> filter;
|
||||
qi::uint_parser< unsigned, 10, 1, 3 > radius_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MAPNIK_IMAGE_FILITER_PARSER_HPP
|
|
@ -1,97 +0,0 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2012 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_IMAGE_FILITER_PARSER_HPP
|
||||
#define MAPNIK_IMAGE_FILITER_PARSER_HPP
|
||||
|
||||
#include <mapnik/image_filter.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/phoenix.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace phoenix = boost::phoenix;
|
||||
|
||||
template <typename Iterator, typename ContType>
|
||||
struct image_filter_grammar :
|
||||
qi::grammar<Iterator, ContType(), qi::ascii::space_type>
|
||||
{
|
||||
image_filter_grammar()
|
||||
: image_filter_grammar::base_type(start)
|
||||
{
|
||||
using qi::lit;
|
||||
using qi::_val;
|
||||
using qi::_1;
|
||||
using qi::_a;
|
||||
using qi::_b;
|
||||
using qi::eps;
|
||||
using qi::char_;
|
||||
using phoenix::push_back;
|
||||
using phoenix::construct;
|
||||
|
||||
#if BOOST_VERSION >= 104700
|
||||
using qi::no_skip;
|
||||
start = -(filter % no_skip[*char_(", ")])
|
||||
;
|
||||
#else
|
||||
start = -(filter)
|
||||
;
|
||||
#endif
|
||||
|
||||
filter =
|
||||
lit("emboss")[push_back(_val,construct<mapnik::filter::emboss>())]
|
||||
|
|
||||
lit("blur")[push_back(_val,construct<mapnik::filter::blur>())]
|
||||
|
|
||||
lit("gray")[push_back(_val,construct<mapnik::filter::gray>())]
|
||||
|
|
||||
lit("edge-detect")[push_back(_val,construct<mapnik::filter::edge_detect>())]
|
||||
|
|
||||
lit("sobel")[push_back(_val,construct<mapnik::filter::sobel>())]
|
||||
|
|
||||
lit("sharpen")[push_back(_val,construct<mapnik::filter::sharpen>())]
|
||||
|
|
||||
lit("x-gradient")[push_back(_val,construct<mapnik::filter::x_gradient>())]
|
||||
|
|
||||
lit("y-gradient")[push_back(_val,construct<mapnik::filter::y_gradient>())]
|
||||
|
|
||||
(lit("agg-stack-blur")[_a = 1, _b = 1]
|
||||
>> -( lit('(') >> radius_[_a = _1]
|
||||
>> lit(',')
|
||||
>> radius_[_b = _1]
|
||||
>> lit(')'))
|
||||
[push_back(_val,construct<mapnik::filter::agg_stack_blur>(_a,_b))])
|
||||
|
|
||||
lit("invert")[push_back(_val,construct<mapnik::filter::invert>())]
|
||||
;
|
||||
}
|
||||
//
|
||||
qi::rule<Iterator, ContType(), qi::ascii::space_type> start;
|
||||
qi::rule<Iterator, ContType(), qi::locals<int,int>, qi::ascii::space_type> filter;
|
||||
qi::uint_parser< unsigned, 10, 1, 3 > radius_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MAPNIK_IMAGE_FILITER_PARSER_HPP
|
|
@ -171,7 +171,7 @@ public:
|
|||
/*!
|
||||
* @return The field rendering of this layer is grouped by.
|
||||
*/
|
||||
std::string group_by() const;
|
||||
std::string const& group_by() const;
|
||||
|
||||
/*!
|
||||
* @brief Attach a datasource for this layer.
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#define MAPNIK_MARKER_HELPERS_HPP
|
||||
|
||||
#include <mapnik/color.hpp>
|
||||
#include <mapnik/geometry.hpp>
|
||||
#include <mapnik/geom_util.hpp>
|
||||
#include <mapnik/markers_symbolizer.hpp>
|
||||
#include <mapnik/expression_evaluator.hpp>
|
||||
#include <mapnik/svg/svg_path_attributes.hpp>
|
||||
|
@ -87,15 +89,17 @@ struct vector_markers_rasterizer_dispatch
|
|||
|
||||
if (placement_method != MARKER_LINE_PLACEMENT)
|
||||
{
|
||||
double x,y;
|
||||
path.rewind(0);
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
if (placement_method == MARKER_INTERIOR_PLACEMENT)
|
||||
{
|
||||
label::interior_position(path, x, y);
|
||||
if (!label::interior_position(path, x, y))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
label::centroid(path, x, y);
|
||||
if (!label::centroid(path, x, y))
|
||||
return;
|
||||
}
|
||||
agg::trans_affine matrix = marker_trans_;
|
||||
matrix.translate(x,y);
|
||||
|
@ -117,7 +121,9 @@ struct vector_markers_rasterizer_dispatch
|
|||
sym_.get_spacing() * scale_factor_,
|
||||
sym_.get_max_error(),
|
||||
sym_.get_allow_overlap());
|
||||
double x, y, angle;
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
double angle = 0;
|
||||
while (placement.get_point(x, y, angle))
|
||||
{
|
||||
agg::trans_affine matrix = marker_trans_;
|
||||
|
@ -179,15 +185,17 @@ struct raster_markers_rasterizer_dispatch
|
|||
|
||||
if (placement_method != MARKER_LINE_PLACEMENT)
|
||||
{
|
||||
double x,y;
|
||||
path.rewind(0);
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
if (placement_method == MARKER_INTERIOR_PLACEMENT)
|
||||
{
|
||||
label::interior_position(path, x, y);
|
||||
if (!label::interior_position(path, x, y))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
label::centroid(path, x, y);
|
||||
if (!label::centroid(path, x, y))
|
||||
return;
|
||||
}
|
||||
agg::trans_affine matrix = marker_trans_;
|
||||
matrix.translate(x,y);
|
||||
|
|
|
@ -32,6 +32,9 @@
|
|||
#include <mapnik/image_compositing.hpp>
|
||||
#include <mapnik/image_scaling.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
struct MAPNIK_DECL raster_symbolizer : public symbolizer_base
|
||||
|
@ -66,15 +69,22 @@ struct MAPNIK_DECL raster_symbolizer : public symbolizer_base
|
|||
mode_ = mode;
|
||||
if (mode == "normal")
|
||||
{
|
||||
MAPNIK_LOG_ERROR(raster_symbolizer) << "converting 'mode=normal' to 'comp-op:src_over'";
|
||||
this->set_comp_op(src_over);
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::optional<composite_mode_e> comp_op = comp_op_from_string(mode);
|
||||
std::string mode2 = boost::algorithm::replace_last_copy(mode,"2","");
|
||||
boost::optional<composite_mode_e> comp_op = comp_op_from_string(mode2);
|
||||
if (comp_op)
|
||||
{
|
||||
MAPNIK_LOG_ERROR(raster_symbolizer) << "converting 'mode:" << mode << "' to 'comp-op:" + *comp_op_to_string(*comp_op) + "'";
|
||||
this->set_comp_op(*comp_op);
|
||||
}
|
||||
else
|
||||
MAPNIK_LOG_ERROR(raster_symbolizer) << "could not convert mode into comp-op";
|
||||
{
|
||||
MAPNIK_LOG_ERROR(raster_symbolizer) << "could not convert mode '" << mode << "' into comp-op, defaulting to 'comp-op:src-over'";
|
||||
}
|
||||
}
|
||||
}
|
||||
scaling_method_e get_scaling_method() const
|
||||
|
|
|
@ -75,8 +75,8 @@ private:
|
|||
class MAPNIK_DECL symbolizer_with_image
|
||||
{
|
||||
public:
|
||||
path_expression_ptr get_filename() const;
|
||||
void set_filename(path_expression_ptr filename);
|
||||
path_expression_ptr const& get_filename() const;
|
||||
void set_filename(path_expression_ptr const& filename);
|
||||
void set_opacity(float opacity);
|
||||
float get_opacity() const;
|
||||
void set_image_transform(transform_type const& tr);
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
// fusion
|
||||
#include <boost/fusion/include/at.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
|
||||
// stl
|
||||
#include <vector>
|
||||
|
||||
|
@ -83,16 +87,36 @@ struct scale_node
|
|||
|
||||
struct rotate_node
|
||||
{
|
||||
typedef boost::fusion::vector2<expr_node, expr_node> coords_type;
|
||||
|
||||
expr_node angle_;
|
||||
expr_node cx_;
|
||||
expr_node cy_;
|
||||
|
||||
explicit rotate_node(expr_node const& angle)
|
||||
: angle_(angle) {}
|
||||
|
||||
rotate_node(expr_node const& angle,
|
||||
expr_node const& cx, expr_node const& cy)
|
||||
: angle_(angle), cx_(cx), cy_(cy) {}
|
||||
|
||||
rotate_node(expr_node const& angle,
|
||||
boost::optional<expr_node> const& cx,
|
||||
boost::optional<expr_node> const& cy)
|
||||
: angle_(angle)
|
||||
, cx_(cx ? *cx : value_null())
|
||||
, cy_(cy ? *cy : value_null()) {}
|
||||
|
||||
rotate_node(expr_node const& angle,
|
||||
boost::optional<coords_type> const& center)
|
||||
: angle_(angle)
|
||||
{
|
||||
if (center)
|
||||
{
|
||||
cx_ = boost::fusion::at_c<0>(*center);
|
||||
cy_ = boost::fusion::at_c<1>(*center);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct skewX_node
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include <mapnik/transform_expression.hpp>
|
||||
|
||||
// spirit
|
||||
#include <boost/spirit/home/phoenix/object/construct.hpp>
|
||||
#include <boost/spirit/home/qi.hpp>
|
||||
|
||||
namespace mapnik {
|
||||
|
@ -40,20 +39,22 @@ namespace mapnik {
|
|||
: qi::grammar<Iterator, transform_list(), space_type>
|
||||
{
|
||||
explicit transform_expression_grammar(expression_grammar<Iterator> const& g);
|
||||
typedef qi::locals<expr_node, boost::optional<expr_node>,
|
||||
boost::optional<expr_node>
|
||||
> rotate_locals;
|
||||
|
||||
typedef qi::rule<Iterator, transform_node(), space_type> node_rule;
|
||||
typedef qi::rule<Iterator, transform_list(), space_type> list_rule;
|
||||
|
||||
// rules
|
||||
typename expression_grammar<Iterator>::rule_type expr;
|
||||
qi::rule<Iterator, std::string(), space_type> attr;
|
||||
qi::rule<Iterator, expr_node(), space_type> atom;
|
||||
qi::rule<Iterator, expr_node(), space_type> expr;
|
||||
qi::rule<Iterator, expr_node(), space_type> sep_atom;
|
||||
qi::rule<Iterator, expr_node(), space_type> sep_expr;
|
||||
qi::rule<Iterator, transform_list(), space_type> start;
|
||||
qi::rule<Iterator, transform_node(), space_type> transform_;
|
||||
qi::rule<Iterator, transform_node(), space_type> matrix;
|
||||
qi::rule<Iterator, transform_node(), space_type> translate;
|
||||
qi::rule<Iterator, transform_node(), space_type> scale;
|
||||
qi::rule<Iterator, transform_node(), space_type, rotate_locals> rotate;
|
||||
qi::rule<Iterator, transform_node(), space_type> rotate;
|
||||
qi::rule<Iterator, transform_node(), space_type> skewX;
|
||||
qi::rule<Iterator, transform_node(), space_type> skewY;
|
||||
};
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace mapnik { namespace util {
|
|||
namespace karma = boost::spirit::karma;
|
||||
namespace phoenix = boost::phoenix;
|
||||
|
||||
namespace detail {
|
||||
namespace svg_detail {
|
||||
struct get_type
|
||||
{
|
||||
template <typename T>
|
||||
|
@ -133,10 +133,10 @@ namespace mapnik { namespace util {
|
|||
karma::rule<OutputIterator, karma::locals<unsigned>, geometry_type const& ()> svg_path;
|
||||
|
||||
// phoenix functions
|
||||
phoenix::function<detail::get_type > _type;
|
||||
phoenix::function<detail::get_first> _first;
|
||||
phoenix::function<svg_detail::get_type > _type;
|
||||
phoenix::function<svg_detail::get_first> _first;
|
||||
//
|
||||
karma::real_generator<double, detail::coordinate_policy<double> > coord_type;
|
||||
karma::real_generator<double, svg_detail::coordinate_policy<double> > coord_type;
|
||||
|
||||
};
|
||||
|
||||
|
|
64
include/mapnik/util/geometry_to_svg.hpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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_TO_SVG_HPP
|
||||
#define MAPNIK_GEOMETRY_TO_SVG_HPP
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/global.hpp>
|
||||
#include <mapnik/geometry.hpp>
|
||||
#include <mapnik/util/vertex_iterator.hpp>
|
||||
#include <mapnik/util/geometry_svg_generator.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/spirit/include/karma.hpp>
|
||||
|
||||
namespace mapnik { namespace util {
|
||||
|
||||
namespace karma = boost::spirit::karma;
|
||||
|
||||
bool to_svg(std::string & svg, mapnik::geometry_type const& geom)
|
||||
{
|
||||
typedef std::back_insert_iterator<std::string> sink_type;
|
||||
sink_type sink(svg);
|
||||
svg_generator<sink_type> generator;
|
||||
bool result = karma::generate(sink, generator, geom);
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO
|
||||
// https://github.com/mapnik/mapnik/issues/1437
|
||||
/*
|
||||
bool to_svg(std::string & svg, mapnik::geometry_container const& geom)
|
||||
{
|
||||
typedef std::back_insert_iterator<std::string> sink_type;
|
||||
sink_type sink(svg);
|
||||
svg_multi_generator<sink_type> generator;
|
||||
bool result = karma::generate(sink, generator, geom);
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
|
||||
}}
|
||||
|
||||
|
||||
#endif // MAPNIK_GEOMETRY_TO_SVG_HPP
|
|
@ -56,7 +56,7 @@ namespace mapnik { namespace util {
|
|||
namespace karma = boost::spirit::karma;
|
||||
namespace phoenix = boost::phoenix;
|
||||
|
||||
namespace {
|
||||
namespace detail {
|
||||
|
||||
struct get_type
|
||||
{
|
||||
|
@ -130,10 +130,10 @@ struct wkt_generator :
|
|||
karma::rule<OutputIterator, geometry_type::value_type (unsigned& )> polygon_coord;
|
||||
|
||||
// phoenix functions
|
||||
phoenix::function<get_type > _type;
|
||||
phoenix::function<get_first> _first;
|
||||
phoenix::function<detail::get_type > _type;
|
||||
phoenix::function<detail::get_first> _first;
|
||||
//
|
||||
karma::real_generator<double, wkt_coordinate_policy<double> > coord_type;
|
||||
karma::real_generator<double, detail::wkt_coordinate_policy<double> > coord_type;
|
||||
};
|
||||
|
||||
|
||||
|
@ -150,9 +150,9 @@ struct wkt_multi_generator :
|
|||
karma::rule<OutputIterator, geometry_container const& ()> multi_geometry;
|
||||
wkt_generator<OutputIterator> path;
|
||||
// phoenix
|
||||
phoenix::function<multi_geometry_> is_multi;
|
||||
phoenix::function<multi_geometry_type> _multi_type;
|
||||
phoenix::function<get_type > _type;
|
||||
phoenix::function<detail::multi_geometry_> is_multi;
|
||||
phoenix::function<detail::multi_geometry_type> _multi_type;
|
||||
phoenix::function<detail::get_type > _type;
|
||||
//
|
||||
karma::symbols<unsigned, char const*> geometry_types;
|
||||
};
|
||||
|
|
|
@ -26,9 +26,10 @@
|
|||
#define MAPNIK_VERSION_IS_RELEASE 0
|
||||
|
||||
#define MAPNIK_MAJOR_VERSION 2
|
||||
#define MAPNIK_MINOR_VERSION 1
|
||||
#define MAPNIK_MINOR_VERSION 2
|
||||
#define MAPNIK_PATCH_VERSION 0
|
||||
|
||||
// translates to 200200
|
||||
#define MAPNIK_VERSION (MAPNIK_MAJOR_VERSION*100000) + (MAPNIK_MINOR_VERSION*100) + (MAPNIK_PATCH_VERSION)
|
||||
|
||||
#ifndef MAPNIK_STRINGIFY
|
||||
|
@ -37,12 +38,12 @@
|
|||
#endif
|
||||
|
||||
#if MAPNIK_VERSION_IS_RELEASE
|
||||
# define MAPNIK_VERSION_STRING MAPNIK_STRINGIFY(MAPNIK_MAJOR_VERSION) "." \
|
||||
#define MAPNIK_VERSION_STRING MAPNIK_STRINGIFY(MAPNIK_MAJOR_VERSION) "." \
|
||||
MAPNIK_STRINGIFY(MAPNIK_MINOR_VERSION) "." \
|
||||
MAPNIK_STRINGIFY(MAPNIK_PATCH_VERSION)
|
||||
|
||||
#else
|
||||
# define MAPNIK_VERSION_STRING MAPNIK_STRINGIFY(MAPNIK_MAJOR_VERSION) "." \
|
||||
#define MAPNIK_VERSION_STRING MAPNIK_STRINGIFY(MAPNIK_MAJOR_VERSION) "." \
|
||||
MAPNIK_STRINGIFY(MAPNIK_MINOR_VERSION) "." \
|
||||
MAPNIK_STRINGIFY(MAPNIK_PATCH_VERSION) "-pre"
|
||||
#endif
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
// mapnik
|
||||
#include <mapnik/config.hpp>
|
||||
#include <mapnik/geometry.hpp>
|
||||
#include <mapnik/wkt/wkt_grammar.hpp>
|
||||
// boost
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/ptr_container/ptr_vector.hpp>
|
||||
|
@ -37,10 +38,6 @@
|
|||
|
||||
namespace mapnik {
|
||||
|
||||
namespace wkt {
|
||||
template <typename Iterator> struct wkt_collection_grammar;
|
||||
}
|
||||
|
||||
MAPNIK_DECL bool from_wkt(std::string const& wkt, boost::ptr_vector<geometry_type> & paths);
|
||||
|
||||
#if BOOST_VERSION >= 104700
|
||||
|
|
|
@ -97,6 +97,8 @@ namespace mapnik { namespace wkt {
|
|||
: wkt_grammar::base_type(geometry_tagged_text)
|
||||
{
|
||||
using qi::no_case;
|
||||
using qi::_1;
|
||||
using qi::_2;
|
||||
using boost::phoenix::push_back;
|
||||
|
||||
geometry_tagged_text = point_tagged_text
|
||||
|
|
|
@ -22,17 +22,19 @@
|
|||
|
||||
#ifndef MAPNIK_XML_TREE_H
|
||||
#define MAPNIK_XML_TREE_H
|
||||
//mapnik
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/xml_node.hpp>
|
||||
#include <mapnik/expression_grammar.hpp>
|
||||
#include <mapnik/path_expression_grammar.hpp>
|
||||
#include <mapnik/transform_expression_grammar.hpp>
|
||||
#include <mapnik/image_filter_grammar.hpp>
|
||||
#include <mapnik/image_filter.hpp>
|
||||
#include <mapnik/css_color_grammar.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include <mapnik/css_color_grammar.hpp>
|
||||
|
||||
//stl
|
||||
#include <string>
|
||||
|
||||
|
@ -56,6 +58,8 @@ public:
|
|||
mapnik::expression_grammar<std::string::const_iterator> expr_grammar;
|
||||
path_expression_grammar<std::string::const_iterator> path_expr_grammar;
|
||||
transform_expression_grammar<std::string::const_iterator> transform_expr_grammar;
|
||||
image_filter_grammar<std::string::const_iterator,std::vector<filter::filter_type> > image_filters_grammar;
|
||||
|
||||
};
|
||||
|
||||
} //ns mapnik
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#include "csv_datasource.hpp"
|
||||
#include "csv_utils.hpp"
|
||||
|
||||
// boost
|
||||
#include <boost/make_shared.hpp>
|
||||
|
@ -36,6 +37,7 @@
|
|||
#include <mapnik/geometry.hpp>
|
||||
#include <mapnik/memory_featureset.hpp>
|
||||
#include <mapnik/wkt/wkt_factory.hpp>
|
||||
#include <mapnik/json/geometry_parser.hpp>
|
||||
#include <mapnik/util/geometry_to_ds_type.hpp>
|
||||
#include <mapnik/util/conversions.hpp>
|
||||
#include <mapnik/boolean.hpp>
|
||||
|
@ -82,7 +84,7 @@ csv_datasource::csv_datasource(parameters const& params, bool bind)
|
|||
- build up csv line-by-line iterator
|
||||
- creates opportunity to filter attributes by map query
|
||||
speed:
|
||||
- add properties for wkt/lon/lat at parse time
|
||||
- add properties for wkt/json/lon/lat at parse time
|
||||
- add ability to pass 'filter' keyword to drop attributes at layer init
|
||||
- create quad tree on the fly for small/med size files
|
||||
- memory map large files for reading
|
||||
|
@ -264,7 +266,7 @@ void csv_datasource::parse_csv(T& stream,
|
|||
// grammer = boost::escaped_list_separator<char>('\\', ',', '\"');
|
||||
grammer = boost::escaped_list_separator<char>(esc, sep, quo);
|
||||
}
|
||||
catch(const std::exception & ex)
|
||||
catch(std::exception const& ex)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "CSV Plugin: " << ex.what();
|
||||
|
@ -275,9 +277,11 @@ void csv_datasource::parse_csv(T& stream,
|
|||
|
||||
int line_number(1);
|
||||
bool has_wkt_field = false;
|
||||
bool has_json_field = false;
|
||||
bool has_lat_field = false;
|
||||
bool has_lon_field = false;
|
||||
unsigned wkt_idx(0);
|
||||
unsigned json_idx(0);
|
||||
unsigned lat_idx(0);
|
||||
unsigned lon_idx(0);
|
||||
|
||||
|
@ -296,6 +300,11 @@ void csv_datasource::parse_csv(T& stream,
|
|||
wkt_idx = idx;
|
||||
has_wkt_field = true;
|
||||
}
|
||||
if (lower_val == "geojson")
|
||||
{
|
||||
json_idx = idx;
|
||||
has_json_field = true;
|
||||
}
|
||||
if (lower_val == "x"
|
||||
|| lower_val == "lon"
|
||||
|| lower_val == "lng"
|
||||
|
@ -369,6 +378,11 @@ void csv_datasource::parse_csv(T& stream,
|
|||
wkt_idx = idx;
|
||||
has_wkt_field = true;
|
||||
}
|
||||
if (lower_val == "geojson")
|
||||
{
|
||||
json_idx = idx;
|
||||
has_json_field = true;
|
||||
}
|
||||
if (lower_val == "x"
|
||||
|| lower_val == "lon"
|
||||
|| lower_val == "lng"
|
||||
|
@ -401,10 +415,10 @@ void csv_datasource::parse_csv(T& stream,
|
|||
}
|
||||
}
|
||||
|
||||
if (!has_wkt_field && (!has_lon_field || !has_lat_field) )
|
||||
if (!has_wkt_field && !has_json_field && (!has_lon_field || !has_lat_field) )
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "CSV Plugin: could not detect column headers with the name of wkt, x/y, or latitude/longitude - this is required for reading geometry data";
|
||||
s << "CSV Plugin: could not detect column headers with the name of wkt, geojson, x/y, or latitude/longitude - this is required for reading geometry data";
|
||||
throw mapnik::datasource_exception(s.str());
|
||||
}
|
||||
|
||||
|
@ -418,6 +432,8 @@ void csv_datasource::parse_csv(T& stream,
|
|||
}
|
||||
|
||||
mapnik::transcoder tr(desc_.get_encoding());
|
||||
mapnik::wkt_parser parse_wkt;
|
||||
mapnik::json::geometry_parser<std::string::const_iterator> parse_json;
|
||||
|
||||
while (std::getline(stream,csv_line,newline))
|
||||
{
|
||||
|
@ -444,19 +460,39 @@ void csv_datasource::parse_csv(T& stream,
|
|||
|
||||
try
|
||||
{
|
||||
// special handling for varieties of quoting that we will enounter with json
|
||||
// TODO - test with custom "quo" option
|
||||
if (has_json_field && (quo == "\"") && (std::count(csv_line.begin(), csv_line.end(), '"') >= 6))
|
||||
{
|
||||
csv_utils::fix_json_quoting(csv_line);
|
||||
}
|
||||
|
||||
Tokenizer tok(csv_line, grammer);
|
||||
Tokenizer::iterator beg = tok.begin();
|
||||
|
||||
// early return for strict mode
|
||||
if (strict_)
|
||||
unsigned num_fields = std::distance(beg,tok.end());
|
||||
if (num_fields > num_headers)
|
||||
{
|
||||
unsigned num_fields = std::distance(beg,tok.end());
|
||||
if (num_fields != num_headers)
|
||||
std::ostringstream s;
|
||||
s << "CSV Plugin: # of columns("
|
||||
<< num_fields << ") > # of headers("
|
||||
<< num_headers << ") parsed for row " << line_number << "\n";
|
||||
throw mapnik::datasource_exception(s.str());
|
||||
}
|
||||
else if (num_fields < num_headers)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "CSV Plugin: # of headers("
|
||||
<< num_headers << ") > # of columns("
|
||||
<< num_fields << ") parsed for row " << line_number << "\n";
|
||||
if (strict_)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "CSV Plugin: # of headers != # of values parsed for row " << line_number << "\n";
|
||||
throw mapnik::datasource_exception(s.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
MAPNIK_LOG_WARN(csv) << s.str();
|
||||
}
|
||||
}
|
||||
|
||||
mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx_,feature_count));
|
||||
|
@ -465,22 +501,24 @@ void csv_datasource::parse_csv(T& stream,
|
|||
bool parsed_x = false;
|
||||
bool parsed_y = false;
|
||||
bool parsed_wkt = false;
|
||||
bool null_geom = false;
|
||||
bool parsed_json = false;
|
||||
std::vector<std::string> collected;
|
||||
|
||||
for (unsigned i = 0; i < num_headers; ++i)
|
||||
{
|
||||
std::string fld_name(headers_.at(i));
|
||||
collected.push_back(fld_name);
|
||||
std::string value;
|
||||
if (beg == tok.end())
|
||||
if (beg == tok.end()) // there are more headers than column values for this row
|
||||
{
|
||||
// add an empty string here to represent a missing value
|
||||
// not using null type here since nulls are not a csv thing
|
||||
feature->put(fld_name,tr.transcode(value.c_str()));
|
||||
null_geom = true;
|
||||
if (feature_count == 1)
|
||||
{
|
||||
desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
|
||||
}
|
||||
// continue here instead of break so that all missing values are
|
||||
// encoded consistenly as empty strings
|
||||
continue;
|
||||
}
|
||||
else
|
||||
|
@ -499,77 +537,67 @@ void csv_datasource::parse_csv(T& stream,
|
|||
// skip empty geoms
|
||||
if (value.empty())
|
||||
{
|
||||
null_geom = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// optimize simple "POINT (x y)"
|
||||
// using this shaved 2 seconds off csv that took 8 seconds total to parse
|
||||
if (value.find("POINT") == 0)
|
||||
if (parse_wkt.parse(value, feature->paths()))
|
||||
{
|
||||
using boost::phoenix::ref;
|
||||
using boost::spirit::qi::_1;
|
||||
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);
|
||||
|
||||
if (r && (str_beg == str_end))
|
||||
{
|
||||
mapnik::geometry_type * pt = new mapnik::geometry_type(mapnik::Point);
|
||||
pt->move_to(x,y);
|
||||
feature->add_geometry(pt);
|
||||
parsed_wkt = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "CSV Plugin: expected well known text geometry: could not parse row "
|
||||
<< line_number
|
||||
<< ",column "
|
||||
<< i << " - found: '"
|
||||
<< value << "'";
|
||||
if (strict_)
|
||||
{
|
||||
throw mapnik::datasource_exception(s.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
MAPNIK_LOG_ERROR(csv) << s.str();
|
||||
}
|
||||
}
|
||||
parsed_wkt = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mapnik::from_wkt(value, feature->paths()))
|
||||
std::ostringstream s;
|
||||
s << "CSV Plugin: expected well known text geometry: could not parse row "
|
||||
<< line_number
|
||||
<< ",column "
|
||||
<< i << " - found: '"
|
||||
<< value << "'";
|
||||
if (strict_)
|
||||
{
|
||||
parsed_wkt = true;
|
||||
throw mapnik::datasource_exception(s.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "CSV Plugin: expected well known text geometry: could not parse row "
|
||||
<< line_number
|
||||
<< ",column "
|
||||
<< i << " - found: '"
|
||||
<< value << "'";
|
||||
if (strict_)
|
||||
{
|
||||
throw mapnik::datasource_exception(s.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
MAPNIK_LOG_ERROR(csv) << s.str();
|
||||
}
|
||||
MAPNIK_LOG_ERROR(csv) << s.str();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO - support both wkt/geojson columns
|
||||
// at once to create multi-geoms?
|
||||
// parse as geojson
|
||||
else if (has_json_field)
|
||||
{
|
||||
if (i == json_idx)
|
||||
{
|
||||
// skip empty geoms
|
||||
if (value.empty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (parse_json.parse(value.begin(),value.end(), feature->paths()))
|
||||
{
|
||||
parsed_json = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "CSV Plugin: expected geojson geometry: could not parse row "
|
||||
<< line_number
|
||||
<< ",column "
|
||||
<< i << " - found: '"
|
||||
<< value << "'";
|
||||
if (strict_)
|
||||
{
|
||||
throw mapnik::datasource_exception(s.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
MAPNIK_LOG_ERROR(csv) << s.str();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// longitude
|
||||
|
@ -578,7 +606,6 @@ void csv_datasource::parse_csv(T& stream,
|
|||
// skip empty geoms
|
||||
if (value.empty())
|
||||
{
|
||||
null_geom = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -610,7 +637,6 @@ void csv_datasource::parse_csv(T& stream,
|
|||
// skip empty geoms
|
||||
if (value.empty())
|
||||
{
|
||||
null_geom = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -713,26 +739,10 @@ void csv_datasource::parse_csv(T& stream,
|
|||
}
|
||||
}
|
||||
|
||||
if (null_geom)
|
||||
bool null_geom = true;
|
||||
if (has_wkt_field || has_json_field)
|
||||
{
|
||||
++line_number;
|
||||
std::ostringstream s;
|
||||
s << "CSV Plugin: null geometry encountered for line "
|
||||
<< line_number;
|
||||
if (strict_)
|
||||
{
|
||||
throw mapnik::datasource_exception(s.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
MAPNIK_LOG_ERROR(csv) << s.str();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_wkt_field)
|
||||
{
|
||||
if (parsed_wkt)
|
||||
if (parsed_wkt || parsed_json)
|
||||
{
|
||||
if (!extent_initialized)
|
||||
{
|
||||
|
@ -745,11 +755,12 @@ void csv_datasource::parse_csv(T& stream,
|
|||
}
|
||||
features_.push_back(feature);
|
||||
++feature_count;
|
||||
null_geom = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "CSV Plugin: could not read WKT geometry "
|
||||
s << "CSV Plugin: could not read WKT or GeoJSON geometry "
|
||||
<< "for line " << line_number << " - found " << headers_.size()
|
||||
<< " with values like: " << csv_line << "\n";
|
||||
if (strict_)
|
||||
|
@ -763,7 +774,7 @@ void csv_datasource::parse_csv(T& stream,
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (has_lat_field || has_lon_field)
|
||||
{
|
||||
if (parsed_x && parsed_y)
|
||||
{
|
||||
|
@ -772,33 +783,31 @@ void csv_datasource::parse_csv(T& stream,
|
|||
feature->add_geometry(pt);
|
||||
features_.push_back(feature);
|
||||
++feature_count;
|
||||
|
||||
null_geom = false;
|
||||
if (!extent_initialized)
|
||||
{
|
||||
extent_initialized = true;
|
||||
extent_ = feature->envelope();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
extent_.expand_to_include(feature->envelope());
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (parsed_x || parsed_y)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "CSV Plugin: does your csv have valid headers?\n";
|
||||
if (!parsed_x)
|
||||
{
|
||||
s << "CSV Plugin: does your csv have valid headers?\n"
|
||||
<< "Could not detect or parse any rows named 'x' or 'longitude' "
|
||||
s << "Could not detect or parse any rows named 'x' or 'longitude' "
|
||||
<< "for line " << line_number << " but found " << headers_.size()
|
||||
<< " with values like: " << csv_line << "\n"
|
||||
<< "for: " << boost::algorithm::join(collected, ",") << "\n";
|
||||
}
|
||||
if (!parsed_y)
|
||||
{
|
||||
s << "CSV Plugin: does your csv have valid headers?\n"
|
||||
<< "Could not detect or parse any rows named 'y' or 'latitude' "
|
||||
s << "Could not detect or parse any rows named 'y' or 'latitude' "
|
||||
<< "for line " << line_number << " but found " << headers_.size()
|
||||
<< " with values like: " << csv_line << "\n"
|
||||
<< "for: " << boost::algorithm::join(collected, ",") << "\n";
|
||||
|
@ -814,9 +823,26 @@ void csv_datasource::parse_csv(T& stream,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null_geom)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "CSV Plugin: could not detect and parse valid lat/lon fields or wkt/json geometry for line "
|
||||
<< line_number;
|
||||
if (strict_)
|
||||
{
|
||||
throw mapnik::datasource_exception(s.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
MAPNIK_LOG_ERROR(csv) << s.str();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
++line_number;
|
||||
}
|
||||
catch(const mapnik::datasource_exception & ex )
|
||||
catch(mapnik::datasource_exception const& ex )
|
||||
{
|
||||
if (strict_)
|
||||
{
|
||||
|
@ -827,7 +853,7 @@ void csv_datasource::parse_csv(T& stream,
|
|||
MAPNIK_LOG_ERROR(csv) << ex.what();
|
||||
}
|
||||
}
|
||||
catch(const std::exception & ex)
|
||||
catch(std::exception const& ex)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "CSV Plugin: unexpected error parsing line: " << line_number
|
||||
|
|
86
plugins/input/csv/csv_utils.hpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2012 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_CSV_UTILS_DATASOURCE_HPP
|
||||
#define MAPNIK_CSV_UTILS_DATASOURCE_HPP
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
namespace csv_utils
|
||||
{
|
||||
static void fix_json_quoting(std::string & csv_line)
|
||||
{
|
||||
std::string wrapping_char;
|
||||
std::string::size_type j_idx = std::string::npos;
|
||||
std::string::size_type post_idx = std::string::npos;
|
||||
std::string::size_type j_idx_double = csv_line.find("\"{");
|
||||
std::string::size_type j_idx_single = csv_line.find("'{");
|
||||
if (j_idx_double != std::string::npos)
|
||||
{
|
||||
wrapping_char = "\"";
|
||||
j_idx = j_idx_double;
|
||||
post_idx = csv_line.find("}\"");
|
||||
|
||||
}
|
||||
else if (j_idx_single != std::string::npos)
|
||||
{
|
||||
wrapping_char = "'";
|
||||
j_idx = j_idx_single;
|
||||
post_idx = csv_line.find("}'");
|
||||
}
|
||||
// we are positive it is valid json
|
||||
if (!wrapping_char.empty())
|
||||
{
|
||||
// grab the json chunk
|
||||
std::string json_chunk = csv_line.substr(j_idx,post_idx+wrapping_char.size());
|
||||
bool does_not_have_escaped_double_quotes = (json_chunk.find("\\\"") == std::string::npos);
|
||||
// ignore properly escaped quotes like \" which need no special handling
|
||||
if (does_not_have_escaped_double_quotes)
|
||||
{
|
||||
std::string pre_json = csv_line.substr(0,j_idx);
|
||||
std::string post_json = csv_line.substr(post_idx+wrapping_char.size());
|
||||
// handle "" in a string wrapped in "
|
||||
// http://tools.ietf.org/html/rfc4180#section-2 item 7.
|
||||
// e.g. "{""type"":""Point"",""coordinates"":[30.0,10.0]}"
|
||||
if (json_chunk.find("\"\"") != std::string::npos)
|
||||
{
|
||||
boost::algorithm::replace_all(json_chunk,"\"\"","\\\"");
|
||||
csv_line = pre_json + json_chunk + post_json;
|
||||
}
|
||||
// handle " in a string wrapped in '
|
||||
// e.g. '{"type":"Point","coordinates":[30.0,10.0]}'
|
||||
else
|
||||
{
|
||||
// escape " because we cannot exchange for single quotes
|
||||
// https://github.com/mapnik/mapnik/issues/1408
|
||||
boost::algorithm::replace_all(json_chunk,"\"","\\\"");
|
||||
boost::algorithm::replace_all(json_chunk,"'","\"");
|
||||
csv_line = pre_json + json_chunk + post_json;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MAPNIK_CSV_UTILS_DATASOURCE_HPP
|
|
@ -21,7 +21,11 @@ plugin_sources = Split(
|
|||
boost_system = 'boost_system%s' % env['BOOST_APPEND']
|
||||
libraries = ['mapnik',env['BOOST_PYTHON_LIB'],boost_system,env['ICU_LIB_NAME']]
|
||||
|
||||
python_link_flag = ''
|
||||
# NOTE: explicit linking to libpython is uneeded on most linux version if the
|
||||
# python plugin is used by a app in python using mapnik's python bindings
|
||||
# we explicitly link to libpython here so that this plugin
|
||||
# can be used from a pure C++ calling application or a different binding language
|
||||
python_link_flag = '-lpython%s' % env['PYTHON_VERSION']
|
||||
|
||||
if env['PLATFORM'] == 'Darwin':
|
||||
if env['PYTHON_DYNAMIC_LOOKUP']:
|
||||
|
@ -37,8 +41,6 @@ if env['PLATFORM'] == 'Darwin':
|
|||
python_link_flag = '-F/System/Library/Frameworks/ -framework Python -Z'
|
||||
else:
|
||||
python_link_flag = '-F/ -framework Python'
|
||||
else:
|
||||
python_link_flag = '-lpython%s' % env['PYTHON_VERSION']
|
||||
|
||||
if env['CUSTOM_LDFLAGS']:
|
||||
linkflags = '%s %s' % (env['CUSTOM_LDFLAGS'], python_link_flag)
|
||||
|
|
|
@ -129,8 +129,9 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
|
|||
eGeomType type = feature.paths()[0].type();
|
||||
if (type == Polygon)
|
||||
converter.template set<clip_poly_tag>();
|
||||
else if (type == LineString)
|
||||
converter.template set<clip_line_tag>();
|
||||
// line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
|
||||
//else if (type == LineString)
|
||||
// converter.template set<clip_line_tag>();
|
||||
// don't clip if type==Point
|
||||
}
|
||||
converter.template set<transform_tag>(); //always transform
|
||||
|
@ -164,8 +165,9 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
|
|||
eGeomType type = feature.paths()[0].type();
|
||||
if (type == Polygon)
|
||||
converter.template set<clip_poly_tag>();
|
||||
else if (type == LineString)
|
||||
converter.template set<clip_line_tag>();
|
||||
// line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
|
||||
//else if (type == LineString)
|
||||
// converter.template set<clip_line_tag>();
|
||||
// don't clip if type==Point
|
||||
}
|
||||
converter.template set<transform_tag>(); //always transform
|
||||
|
@ -198,8 +200,9 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
|
|||
eGeomType type = feature.paths()[0].type();
|
||||
if (type == Polygon)
|
||||
converter.template set<clip_poly_tag>();
|
||||
else if (type == LineString)
|
||||
converter.template set<clip_line_tag>();
|
||||
// line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
|
||||
//else if (type == LineString)
|
||||
// converter.template set<clip_line_tag>();
|
||||
// don't clip if type==Point
|
||||
}
|
||||
converter.template set<transform_tag>(); //always transform
|
||||
|
|
|
@ -77,9 +77,15 @@ void agg_renderer<T>::process(point_symbolizer const& sym,
|
|||
double y;
|
||||
double z=0;
|
||||
if (sym.get_point_placement() == CENTROID_POINT_PLACEMENT)
|
||||
label::centroid(geom, x, y);
|
||||
{
|
||||
if (!label::centroid(geom, x, y))
|
||||
return;
|
||||
}
|
||||
else
|
||||
label::interior_position(geom ,x, y);
|
||||
{
|
||||
if (!label::interior_position(geom ,x, y))
|
||||
return;
|
||||
}
|
||||
|
||||
prj_trans.backward(x,y,z);
|
||||
t_.forward(&x,&y);
|
||||
|
|
|
@ -144,7 +144,7 @@ void agg_renderer<T>::process(polygon_pattern_symbolizer const& sym,
|
|||
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||
converter(query_extent_,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_);
|
||||
|
||||
if (sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||
converter.set<transform_tag>(); //always transform
|
||||
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
|
||||
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
||||
|
|
|
@ -56,7 +56,7 @@ void agg_renderer<T>::process(polygon_symbolizer const& sym,
|
|||
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||
converter(query_extent_,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_);
|
||||
|
||||
if (sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||
converter.set<transform_tag>(); //always transform
|
||||
converter.set<affine_transform_tag>();
|
||||
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
|
||||
|
|
42
src/build.py
|
@ -104,6 +104,7 @@ source = Split(
|
|||
css_color_grammar.cpp
|
||||
conversions.cpp
|
||||
image_compositing.cpp
|
||||
image_filter_grammar.cpp
|
||||
image_scaling.cpp
|
||||
box2d.cpp
|
||||
building_symbolizer.cpp
|
||||
|
@ -280,26 +281,27 @@ source += Split(
|
|||
grid/process_text_symbolizer.cpp
|
||||
""")
|
||||
|
||||
if env['SVG_RENDERER']: # svg backend
|
||||
source += Split(
|
||||
"""
|
||||
svg/svg_renderer.cpp
|
||||
svg/svg_generator.cpp
|
||||
svg/svg_output_attributes.cpp
|
||||
svg/process_symbolizers.cpp
|
||||
svg/process_building_symbolizer.cpp
|
||||
svg/process_line_pattern_symbolizer.cpp
|
||||
svg/process_line_symbolizer.cpp
|
||||
svg/process_markers_symbolizer.cpp
|
||||
svg/process_point_symbolizer.cpp
|
||||
svg/process_polygon_pattern_symbolizer.cpp
|
||||
svg/process_polygon_symbolizer.cpp
|
||||
svg/process_raster_symbolizer.cpp
|
||||
svg/process_shield_symbolizer.cpp
|
||||
svg/process_text_symbolizer.cpp
|
||||
""")
|
||||
lib_env.Append(CXXFLAGS = '-DSVG_RENDERER')
|
||||
libmapnik_cxxflags.append('-DSVG_RENDERER')
|
||||
# https://github.com/mapnik/mapnik/issues/1438
|
||||
#if env['SVG_RENDERER']: # svg backend
|
||||
# source += Split(
|
||||
# """
|
||||
# svg/svg_renderer.cpp
|
||||
# svg/svg_generator.cpp
|
||||
# svg/svg_output_attributes.cpp
|
||||
# svg/process_symbolizers.cpp
|
||||
# svg/process_building_symbolizer.cpp
|
||||
# svg/process_line_pattern_symbolizer.cpp
|
||||
# svg/process_line_symbolizer.cpp
|
||||
# svg/process_markers_symbolizer.cpp
|
||||
# svg/process_point_symbolizer.cpp
|
||||
# svg/process_polygon_pattern_symbolizer.cpp
|
||||
# svg/process_polygon_symbolizer.cpp
|
||||
# svg/process_raster_symbolizer.cpp
|
||||
# svg/process_shield_symbolizer.cpp
|
||||
# svg/process_text_symbolizer.cpp
|
||||
# """)
|
||||
# lib_env.Append(CXXFLAGS = '-DSVG_RENDERER')
|
||||
# libmapnik_cxxflags.append('-DSVG_RENDERER')
|
||||
|
||||
if env['XMLPARSER'] == 'libxml2' and env['HAS_LIBXML2']:
|
||||
source += Split(
|
||||
|
|
|
@ -32,7 +32,7 @@ building_symbolizer::building_symbolizer()
|
|||
opacity_(1.0)
|
||||
{}
|
||||
|
||||
building_symbolizer::building_symbolizer(color const& fill, expression_ptr height)
|
||||
building_symbolizer::building_symbolizer(color const& fill, expression_ptr const& height)
|
||||
: symbolizer_base(),
|
||||
fill_(fill),
|
||||
height_(height),
|
||||
|
@ -47,12 +47,12 @@ void building_symbolizer::set_fill(color const& fill)
|
|||
{
|
||||
fill_ = fill;
|
||||
}
|
||||
expression_ptr building_symbolizer::height() const
|
||||
expression_ptr const& building_symbolizer::height() const
|
||||
{
|
||||
return height_;
|
||||
}
|
||||
|
||||
void building_symbolizer::set_height(expression_ptr height)
|
||||
void building_symbolizer::set_height(expression_ptr const& height)
|
||||
{
|
||||
height_=height;
|
||||
}
|
||||
|
|
|
@ -870,7 +870,7 @@ void cairo_renderer_base::process(polygon_symbolizer const& sym,
|
|||
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||
converter(query_extent_,context,sym,t_,prj_trans,tr,1.0);
|
||||
|
||||
if (sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||
converter.set<transform_tag>(); //always transform
|
||||
converter.set<affine_transform_tag>();
|
||||
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
|
||||
|
@ -1205,9 +1205,15 @@ void cairo_renderer_base::process(point_symbolizer const& sym,
|
|||
double z = 0;
|
||||
|
||||
if (sym.get_point_placement() == CENTROID_POINT_PLACEMENT)
|
||||
label::centroid(geom, x, y);
|
||||
{
|
||||
if (!label::centroid(geom, x, y))
|
||||
return;
|
||||
}
|
||||
else
|
||||
label::interior_position(geom, x, y);
|
||||
{
|
||||
if (!label::interior_position(geom ,x, y))
|
||||
return;
|
||||
}
|
||||
|
||||
prj_trans.backward(x, y, z);
|
||||
t_.forward(&x, &y);
|
||||
|
@ -1387,7 +1393,7 @@ void cairo_renderer_base::process(polygon_pattern_symbolizer const& sym,
|
|||
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||
converter(query_extent_,context,sym,t_,prj_trans,tr, scale_factor_);
|
||||
|
||||
if (sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||
converter.set<transform_tag>(); //always transform
|
||||
converter.set<affine_transform_tag>();
|
||||
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
|
||||
|
@ -1493,15 +1499,17 @@ struct markers_dispatch
|
|||
|
||||
if (placement_method != MARKER_LINE_PLACEMENT)
|
||||
{
|
||||
double x,y;
|
||||
path.rewind(0);
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
if (placement_method == MARKER_INTERIOR_PLACEMENT)
|
||||
{
|
||||
label::interior_position(path, x, y);
|
||||
if (!label::interior_position(path, x, y))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
label::centroid(path, x, y);
|
||||
if (!label::centroid(path, x, y))
|
||||
return;
|
||||
}
|
||||
coord2d center = bbox_.center();
|
||||
agg::trans_affine matrix = agg::trans_affine_translation(-center.x, -center.y);
|
||||
|
@ -1574,15 +1582,17 @@ struct markers_dispatch_2
|
|||
|
||||
if (placement_method != MARKER_LINE_PLACEMENT)
|
||||
{
|
||||
double x,y;
|
||||
path.rewind(0);
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
if (placement_method == MARKER_INTERIOR_PLACEMENT)
|
||||
{
|
||||
label::interior_position(path, x, y);
|
||||
if (!label::interior_position(path, x, y))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
label::centroid(path, x, y);
|
||||
if (!label::centroid(path, x, y))
|
||||
return;
|
||||
}
|
||||
coord2d center = bbox_.center();
|
||||
agg::trans_affine matrix = agg::trans_affine_translation(-center.x, -center.y);
|
||||
|
@ -1692,8 +1702,9 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
|
|||
eGeomType type = feature.paths()[0].type();
|
||||
if (type == Polygon)
|
||||
converter.set<clip_poly_tag>();
|
||||
else if (type == LineString)
|
||||
converter.set<clip_line_tag>();
|
||||
// line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
|
||||
//else if (type == LineString)
|
||||
// converter.template set<clip_line_tag>();
|
||||
// don't clip if type==Point
|
||||
}
|
||||
converter.set<transform_tag>(); //always transform
|
||||
|
@ -1719,8 +1730,9 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
|
|||
eGeomType type = feature.paths()[0].type();
|
||||
if (type == Polygon)
|
||||
converter.set<clip_poly_tag>();
|
||||
else if (type == LineString)
|
||||
converter.set<clip_line_tag>();
|
||||
// line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
|
||||
//else if (type == LineString)
|
||||
// converter.template set<clip_line_tag>();
|
||||
// don't clip if type==Point
|
||||
}
|
||||
converter.set<transform_tag>(); //always transform
|
||||
|
@ -1751,8 +1763,9 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
|
|||
eGeomType type = feature.paths()[0].type();
|
||||
if (type == Polygon)
|
||||
converter.set<clip_poly_tag>();
|
||||
else if (type == LineString)
|
||||
converter.set<clip_line_tag>();
|
||||
// line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
|
||||
//else if (type == LineString)
|
||||
// converter.template set<clip_line_tag>();
|
||||
// don't clip if type==Point
|
||||
}
|
||||
converter.set<transform_tag>(); //always transform
|
||||
|
|
|
@ -25,11 +25,10 @@ config_error::config_error(std::string const& what, unsigned line_number, std::s
|
|||
char const* config_error::what() const throw()
|
||||
{
|
||||
std::stringstream s;
|
||||
s << file_;
|
||||
if (line_number_ > 0) s << " line " << line_number_;
|
||||
if (!node_name_.empty()) s << " in node "<< node_name_;
|
||||
if (line_number_ > 0 || !file_.empty()) s << ": ";
|
||||
s << what_;
|
||||
if (!node_name_.empty()) s << " in " << node_name_;
|
||||
if (line_number_ > 0) s << " at line " << line_number_;
|
||||
if (!file_.empty()) s << " of '" << file_ << "'";
|
||||
msg_ = s.str(); //Avoid returning pointer to dead object
|
||||
return msg_.c_str();
|
||||
}
|
||||
|
|
|
@ -156,8 +156,9 @@ void grid_renderer<T>::process(markers_symbolizer const& sym,
|
|||
eGeomType type = feature.paths()[0].type();
|
||||
if (type == Polygon)
|
||||
converter.template set<clip_poly_tag>();
|
||||
else if (type == LineString)
|
||||
converter.template set<clip_line_tag>();
|
||||
// line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
|
||||
//else if (type == LineString)
|
||||
// converter.template set<clip_line_tag>();
|
||||
// don't clip if type==Point
|
||||
}
|
||||
converter.template set<transform_tag>(); //always transform
|
||||
|
@ -200,8 +201,9 @@ void grid_renderer<T>::process(markers_symbolizer const& sym,
|
|||
eGeomType type = feature.paths()[0].type();
|
||||
if (type == Polygon)
|
||||
converter.template set<clip_poly_tag>();
|
||||
else if (type == LineString)
|
||||
converter.template set<clip_line_tag>();
|
||||
// line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
|
||||
//else if (type == LineString)
|
||||
// converter.template set<clip_line_tag>();
|
||||
// don't clip if type==Point
|
||||
}
|
||||
converter.template set<transform_tag>(); //always transform
|
||||
|
@ -247,8 +249,9 @@ void grid_renderer<T>::process(markers_symbolizer const& sym,
|
|||
eGeomType type = feature.paths()[0].type();
|
||||
if (type == Polygon)
|
||||
converter.template set<clip_poly_tag>();
|
||||
else if (type == LineString)
|
||||
converter.template set<clip_line_tag>();
|
||||
// line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
|
||||
//else if (type == LineString)
|
||||
// converter.template set<clip_line_tag>();
|
||||
// don't clip if type==Point
|
||||
}
|
||||
converter.template set<transform_tag>(); //always transform
|
||||
|
|
|
@ -81,9 +81,15 @@ void grid_renderer<T>::process(point_symbolizer const& sym,
|
|||
double y;
|
||||
double z=0;
|
||||
if (sym.get_point_placement() == CENTROID_POINT_PLACEMENT)
|
||||
label::centroid(geom, x, y);
|
||||
{
|
||||
if (!label::centroid(geom, x, y))
|
||||
return;
|
||||
}
|
||||
else
|
||||
label::interior_position(geom, x, y);
|
||||
{
|
||||
if (!label::interior_position(geom ,x, y))
|
||||
return;
|
||||
}
|
||||
|
||||
prj_trans.backward(x,y,z);
|
||||
t_.forward(&x,&y);
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
// boost
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/grid/grid_rasterizer.hpp>
|
||||
#include <mapnik/grid/grid_renderer.hpp>
|
||||
|
@ -27,6 +30,7 @@
|
|||
#include <mapnik/grid/grid_pixel.hpp>
|
||||
#include <mapnik/grid/grid.hpp>
|
||||
#include <mapnik/polygon_pattern_symbolizer.hpp>
|
||||
#include <mapnik/vertex_converters.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_rasterizer_scanline_aa.h"
|
||||
|
@ -44,10 +48,32 @@ void grid_renderer<T>::process(polygon_pattern_symbolizer const& sym,
|
|||
mapnik::feature_impl & feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
typedef coord_transform<CoordTransform,geometry_type> path_type;
|
||||
ras_ptr->reset();
|
||||
|
||||
agg::trans_affine tr;
|
||||
evaluate_transform(tr, feature, sym.get_transform());
|
||||
|
||||
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag> conv_types;
|
||||
vertex_converter<box2d<double>, grid_rasterizer, polygon_pattern_symbolizer,
|
||||
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||
converter(query_extent_,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_);
|
||||
|
||||
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||
converter.set<transform_tag>(); //always transform
|
||||
converter.set<affine_transform_tag>();
|
||||
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
||||
|
||||
|
||||
BOOST_FOREACH( geometry_type & geom, feature.paths())
|
||||
{
|
||||
if (geom.size() > 2)
|
||||
{
|
||||
converter.apply(geom);
|
||||
}
|
||||
}
|
||||
|
||||
typedef agg::renderer_base<mapnik::pixfmt_gray32> ren_base;
|
||||
typedef agg::renderer_scanline_bin_solid<ren_base> renderer;
|
||||
agg::scanline_bin sl;
|
||||
|
||||
grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_);
|
||||
mapnik::pixfmt_gray32 pixf(buf);
|
||||
|
@ -55,20 +81,9 @@ void grid_renderer<T>::process(polygon_pattern_symbolizer const& sym,
|
|||
ren_base renb(pixf);
|
||||
renderer ren(renb);
|
||||
|
||||
ras_ptr->reset();
|
||||
|
||||
for (unsigned i=0;i<feature.num_geometries();++i)
|
||||
{
|
||||
geometry_type & geom = feature.get_geometry(i);
|
||||
if (geom.size() > 2)
|
||||
{
|
||||
path_type path(t_,geom,prj_trans);
|
||||
ras_ptr->add_path(path);
|
||||
}
|
||||
}
|
||||
|
||||
// render id
|
||||
ren.color(mapnik::gray32(feature.id()));
|
||||
agg::scanline_bin sl;
|
||||
agg::render_scanlines(*ras_ptr, sl, ren);
|
||||
|
||||
// add feature properties to grid cache
|
||||
|
|
|
@ -50,17 +50,15 @@ void grid_renderer<T>::process(polygon_symbolizer const& sym,
|
|||
{
|
||||
ras_ptr->reset();
|
||||
|
||||
box2d<double> inflated_extent = query_extent_ * 1.0;
|
||||
|
||||
agg::trans_affine tr;
|
||||
evaluate_transform(tr, feature, sym.get_transform());
|
||||
|
||||
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,simplify_tag,smooth_tag> conv_types;
|
||||
vertex_converter<box2d<double>, grid_rasterizer, polygon_symbolizer,
|
||||
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||
converter(inflated_extent,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_);
|
||||
converter(query_extent_,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_);
|
||||
|
||||
if (sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||
converter.set<transform_tag>(); //always transform
|
||||
converter.set<affine_transform_tag>();
|
||||
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
|
||||
|
|
91
src/image_filter_grammar.cpp
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2012 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
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/image_filter_grammar.hpp>
|
||||
#include <mapnik/image_filter.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/version.hpp>
|
||||
|
||||
// spirit
|
||||
#include <boost/spirit/include/phoenix.hpp>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace phoenix = boost::phoenix;
|
||||
|
||||
template <typename Iterator, typename ContType>
|
||||
image_filter_grammar<Iterator,ContType>::image_filter_grammar()
|
||||
: image_filter_grammar::base_type(start)
|
||||
{
|
||||
using qi::lit;
|
||||
using qi::_val;
|
||||
using qi::_1;
|
||||
using qi::_a;
|
||||
using qi::_b;
|
||||
using qi::eps;
|
||||
using qi::char_;
|
||||
using phoenix::push_back;
|
||||
using phoenix::construct;
|
||||
|
||||
#if BOOST_VERSION >= 104700
|
||||
using qi::no_skip;
|
||||
start = -(filter % no_skip[*char_(", ")])
|
||||
;
|
||||
#else
|
||||
start = -(filter)
|
||||
;
|
||||
#endif
|
||||
|
||||
filter =
|
||||
lit("emboss")[push_back(_val,construct<mapnik::filter::emboss>())]
|
||||
|
|
||||
lit("blur")[push_back(_val,construct<mapnik::filter::blur>())]
|
||||
|
|
||||
lit("gray")[push_back(_val,construct<mapnik::filter::gray>())]
|
||||
|
|
||||
lit("edge-detect")[push_back(_val,construct<mapnik::filter::edge_detect>())]
|
||||
|
|
||||
lit("sobel")[push_back(_val,construct<mapnik::filter::sobel>())]
|
||||
|
|
||||
lit("sharpen")[push_back(_val,construct<mapnik::filter::sharpen>())]
|
||||
|
|
||||
lit("x-gradient")[push_back(_val,construct<mapnik::filter::x_gradient>())]
|
||||
|
|
||||
lit("y-gradient")[push_back(_val,construct<mapnik::filter::y_gradient>())]
|
||||
|
|
||||
(lit("agg-stack-blur")[_a = 1, _b = 1]
|
||||
>> -( lit('(') >> radius_[_a = _1]
|
||||
>> lit(',')
|
||||
>> radius_[_b = _1]
|
||||
>> lit(')'))
|
||||
[push_back(_val,construct<mapnik::filter::agg_stack_blur>(_a,_b))])
|
||||
|
|
||||
lit("invert")[push_back(_val,construct<mapnik::filter::invert>())]
|
||||
;
|
||||
}
|
||||
|
||||
template struct mapnik::image_filter_grammar<std::string::const_iterator,std::vector<mapnik::filter::filter_type> >;
|
||||
|
||||
}
|
|
@ -237,7 +237,7 @@ void layer::set_group_by(std::string column)
|
|||
group_by_ = column;
|
||||
}
|
||||
|
||||
std::string layer::group_by() const
|
||||
std::string const& layer::group_by() const
|
||||
{
|
||||
return group_by_;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include <mapnik/color_factory.hpp>
|
||||
#include <mapnik/symbolizer.hpp>
|
||||
#include <mapnik/feature_type_style.hpp>
|
||||
#include <mapnik/image_filter_parser.hpp>
|
||||
#include <mapnik/layer.hpp>
|
||||
#include <mapnik/datasource_cache.hpp>
|
||||
#include <mapnik/font_engine_freetype.hpp>
|
||||
|
@ -117,6 +116,7 @@ private:
|
|||
|
||||
|
||||
std::string ensure_relative_to_xml(boost::optional<std::string> opt_path);
|
||||
void ensure_exists(std::string const& file_path);
|
||||
boost::optional<color> get_opt_color_attr(boost::property_tree::ptree const& node,
|
||||
std::string const& name);
|
||||
|
||||
|
@ -427,19 +427,14 @@ void map_parser::parse_style(Map & map, xml_node const& sty)
|
|||
}
|
||||
|
||||
// image filters
|
||||
mapnik::image_filter_grammar<std::string::const_iterator,
|
||||
std::vector<mapnik::filter::filter_type> > filter_grammar;
|
||||
|
||||
optional<std::string> filters = sty.get_opt_attr<std::string>("image-filters");
|
||||
if (filters)
|
||||
{
|
||||
std::string filter_mode = *filters;
|
||||
std::string::const_iterator itr = filter_mode.begin();
|
||||
std::string::const_iterator end = filter_mode.end();
|
||||
|
||||
|
||||
bool result = boost::spirit::qi::phrase_parse(itr,end,
|
||||
filter_grammar,
|
||||
sty.get_tree().image_filters_grammar,
|
||||
boost::spirit::qi::ascii::space,
|
||||
style.image_filters());
|
||||
if (!result || itr!=end)
|
||||
|
@ -459,7 +454,7 @@ void map_parser::parse_style(Map & map, xml_node const& sty)
|
|||
std::string::const_iterator itr = filter_mode.begin();
|
||||
std::string::const_iterator end = filter_mode.end();
|
||||
bool result = boost::spirit::qi::phrase_parse(itr,end,
|
||||
filter_grammar,
|
||||
sty.get_tree().image_filters_grammar,
|
||||
boost::spirit::qi::ascii::space,
|
||||
style.direct_image_filters());
|
||||
if (!result || itr!=end)
|
||||
|
@ -921,11 +916,12 @@ void map_parser::parse_point_symbolizer(rule & rule, xml_node const & sym)
|
|||
}
|
||||
|
||||
*file = ensure_relative_to_xml(file);
|
||||
|
||||
std::string filename = *file;
|
||||
ensure_exists(filename);
|
||||
path_expression_ptr expr(boost::make_shared<path_expression>());
|
||||
if (!parse_path_from_string(expr, *file, sym.get_tree().path_expr_grammar))
|
||||
if (!parse_path_from_string(expr, filename, sym.get_tree().path_expr_grammar))
|
||||
{
|
||||
throw mapnik::config_error("Failed to parse path_expression '" + *file + "'");
|
||||
throw mapnik::config_error("Failed to parse path_expression '" + filename + "'");
|
||||
}
|
||||
|
||||
symbol.set_filename(expr);
|
||||
|
@ -946,7 +942,7 @@ void map_parser::parse_point_symbolizer(rule & rule, xml_node const & sym)
|
|||
}
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in PointSymbolizer", sym);
|
||||
ex.append_context(sym);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -977,8 +973,9 @@ void map_parser::parse_markers_symbolizer(rule & rule, xml_node const& node)
|
|||
optional<std::string> marker_type = node.get_opt_attr<std::string>("marker-type");
|
||||
if (marker_type)
|
||||
{
|
||||
// TODO - before Mapnik 2.1 release change this from WARN TO ERROR
|
||||
MAPNIK_LOG_WARN(markers_symbolizer) << "'marker-type' is deprecated and will be removed in Mapnik 3.x, use file='shape://<type>' to specify known svg shapes";
|
||||
// TODO - revisit whether to officially deprecate marker-type
|
||||
// https://github.com/mapnik/mapnik/issues/1427
|
||||
//MAPNIK_LOG_WARN(markers_symbolizer) << "'marker-type' is deprecated and will be removed in Mapnik 3.x, use file='shape://<type>' to specify known svg shapes";
|
||||
// back compatibility with Mapnik 2.0.0
|
||||
if (!marker_type->empty() && filename.empty())
|
||||
{
|
||||
|
@ -997,6 +994,7 @@ void map_parser::parse_markers_symbolizer(rule & rule, xml_node const& node)
|
|||
|
||||
if (!filename.empty())
|
||||
{
|
||||
ensure_exists(filename);
|
||||
path_expression_ptr expr(boost::make_shared<path_expression>());
|
||||
if (!parse_path_from_string(expr, filename, node.get_tree().path_expr_grammar))
|
||||
{
|
||||
|
@ -1053,7 +1051,7 @@ void map_parser::parse_markers_symbolizer(rule & rule, xml_node const& node)
|
|||
}
|
||||
catch (config_error const& ex)
|
||||
{
|
||||
ex.append_context("in MarkersSymbolizer", node);
|
||||
ex.append_context(node);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -1080,6 +1078,7 @@ void map_parser::parse_line_pattern_symbolizer(rule & rule, xml_node const & sym
|
|||
}
|
||||
|
||||
file = ensure_relative_to_xml(file);
|
||||
ensure_exists(file);
|
||||
path_expression_ptr expr(boost::make_shared<path_expression>());
|
||||
if (!parse_path_from_string(expr, file, sym.get_tree().path_expr_grammar))
|
||||
{
|
||||
|
@ -1092,7 +1091,7 @@ void map_parser::parse_line_pattern_symbolizer(rule & rule, xml_node const & sym
|
|||
}
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in LinePatternSymbolizer", sym);
|
||||
ex.append_context(sym);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -1121,7 +1120,7 @@ void map_parser::parse_polygon_pattern_symbolizer(rule & rule,
|
|||
}
|
||||
|
||||
file = ensure_relative_to_xml(file);
|
||||
|
||||
ensure_exists(file);
|
||||
path_expression_ptr expr(boost::make_shared<path_expression>());
|
||||
if (!parse_path_from_string(expr, file, sym.get_tree().path_expr_grammar))
|
||||
{
|
||||
|
@ -1150,7 +1149,7 @@ void map_parser::parse_polygon_pattern_symbolizer(rule & rule,
|
|||
}
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in PolygonPatternSymbolizer", sym);
|
||||
ex.append_context(sym);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -1179,7 +1178,7 @@ void map_parser::parse_text_symbolizer(rule & rule, xml_node const& sym)
|
|||
}
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in TextSymbolizer", sym);
|
||||
ex.append_context(sym);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -1273,6 +1272,7 @@ void map_parser::parse_shield_symbolizer(rule & rule, xml_node const& sym)
|
|||
}
|
||||
|
||||
file = ensure_relative_to_xml(file);
|
||||
ensure_exists(file);
|
||||
path_expression_ptr expr(boost::make_shared<path_expression>());
|
||||
if (!parse_path_from_string(expr, file, sym.get_tree().path_expr_grammar))
|
||||
{
|
||||
|
@ -1284,7 +1284,7 @@ void map_parser::parse_shield_symbolizer(rule & rule, xml_node const& sym)
|
|||
}
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in ShieldSymbolizer", sym);
|
||||
ex.append_context(sym);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -1393,7 +1393,7 @@ void map_parser::parse_line_symbolizer(rule & rule, xml_node const & sym)
|
|||
}
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in LineSymbolizer", sym);
|
||||
ex.append_context(sym);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -1422,7 +1422,7 @@ void map_parser::parse_polygon_symbolizer(rule & rule, xml_node const & sym)
|
|||
}
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in PolygonSymbolizer", sym);
|
||||
ex.append_context(sym);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -1448,7 +1448,7 @@ void map_parser::parse_building_symbolizer(rule & rule, xml_node const & sym)
|
|||
}
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in BuildingSymbolizer", sym);
|
||||
ex.append_context(sym);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -1526,7 +1526,7 @@ void map_parser::parse_raster_symbolizer(rule & rule, xml_node const & sym)
|
|||
}
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in RasterSymbolizer", sym);
|
||||
ex.append_context(sym);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -1612,7 +1612,7 @@ void map_parser::parse_raster_colorizer(raster_colorizer_ptr const& rc,
|
|||
}
|
||||
catch (const config_error & ex)
|
||||
{
|
||||
ex.append_context("in RasterColorizer", node);
|
||||
ex.append_context(node);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -1654,20 +1654,34 @@ std::string map_parser::ensure_relative_to_xml(boost::optional<std::string> opt_
|
|||
return *opt_path;
|
||||
}
|
||||
|
||||
void map_parser::ensure_exists(std::string const& file_path)
|
||||
{
|
||||
if (marker_cache::is_uri(file_path))
|
||||
return;
|
||||
// validate that the filename exists if it is not a dynamic PathExpression
|
||||
if (!boost::algorithm::find_first(file_path,"[") && !boost::algorithm::find_first(file_path,"]"))
|
||||
{
|
||||
if (!boost::filesystem::exists(file_path))
|
||||
{
|
||||
throw mapnik::config_error("point-file could not be found: '" + file_path + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void map_parser::find_unused_nodes(xml_node const& root)
|
||||
{
|
||||
std::stringstream error_message;
|
||||
find_unused_nodes_recursive(root, error_message);
|
||||
if (!error_message.str().empty())
|
||||
{
|
||||
std::string msg("The following nodes or attributes were not processed while parsing the xml file:" + error_message.str());
|
||||
std::string msg("Unable to process some data while parsing '" + filename_ + "':" + error_message.str());
|
||||
if (strict_)
|
||||
{
|
||||
throw config_error(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
MAPNIK_LOG_ERROR(load_map) << "map_parser: " << msg;
|
||||
MAPNIK_LOG_ERROR(load_map) << msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1679,7 +1693,7 @@ void map_parser::find_unused_nodes_recursive(xml_node const& node, std::stringst
|
|||
if (node.is_text()) {
|
||||
error_message << "\n* text '" << node.text() << "'";
|
||||
} else {
|
||||
error_message << "\n* node '" << node.name() << "' in line " << node.line();
|
||||
error_message << "\n* node '" << node.name() << "' at line " << node.line();
|
||||
}
|
||||
return; //All attributes and children are automatically unprocessed, too.
|
||||
}
|
||||
|
@ -1692,7 +1706,7 @@ void map_parser::find_unused_nodes_recursive(xml_node const& node, std::stringst
|
|||
{
|
||||
error_message << "\n* attribute '" << aitr->first <<
|
||||
"' with value '" << aitr->second.value <<
|
||||
"' in line " << node.line();
|
||||
"' at line " << node.line();
|
||||
}
|
||||
}
|
||||
xml_node::const_iterator itr = node.begin();
|
||||
|
|
|
@ -132,7 +132,7 @@ void placement_finder<DetectorT>::find_point_placements(T & shape_path)
|
|||
double total_distance = get_total_distance<T>(shape_path);
|
||||
shape_path.rewind(0);
|
||||
|
||||
if (distance == 0) //Point data, not a line
|
||||
if (total_distance == 0) //Point data, not a line
|
||||
{
|
||||
double x, y;
|
||||
shape_path.vertex(&x,&y);
|
||||
|
|
|
@ -67,10 +67,28 @@ string_info &processed_text::get_string_info()
|
|||
{
|
||||
if (!p.fontset.get_name().empty())
|
||||
{
|
||||
throw config_error("Unable to find specified font set '" + p.fontset.get_name() + "'");
|
||||
} else if (!p.face_name.empty()) {
|
||||
if (p.fontset.size())
|
||||
{
|
||||
if (!p.face_name.empty())
|
||||
{
|
||||
throw config_error("Unable to find specified font face '" + p.face_name + "' in font set: '" + p.fontset.get_name() + "'");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw config_error("No valid font face could be loaded for font set: '" + p.fontset.get_name() + "'");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw config_error("Font set '" + p.fontset.get_name() + "' does not contain any Font face-name entries");
|
||||
}
|
||||
}
|
||||
else if (!p.face_name.empty())
|
||||
{
|
||||
throw config_error("Unable to find specified font face '" + p.face_name + "'");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
throw config_error("Both font set and face name are empty!");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,12 +151,12 @@ symbolizer_with_image::symbolizer_with_image( symbolizer_with_image const& rhs)
|
|||
{
|
||||
}
|
||||
|
||||
path_expression_ptr symbolizer_with_image::get_filename() const
|
||||
path_expression_ptr const& symbolizer_with_image::get_filename() const
|
||||
{
|
||||
return image_filename_;
|
||||
}
|
||||
|
||||
void symbolizer_with_image::set_filename(path_expression_ptr image_filename)
|
||||
void symbolizer_with_image::set_filename(path_expression_ptr const& image_filename)
|
||||
{
|
||||
image_filename_ = image_filename;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
#include <mapnik/symbolizer_helpers.hpp>
|
||||
#include <mapnik/label_collision_detector.hpp>
|
||||
#include <mapnik/placement_finder.hpp>
|
||||
#include <mapnik/geom_util.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_conv_clip_polyline.h"
|
||||
|
||||
namespace mapnik {
|
||||
|
@ -233,25 +236,31 @@ void text_symbolizer_helper<FaceManagerT, DetectorT>::initialize_points()
|
|||
}
|
||||
else
|
||||
{
|
||||
// https://github.com/mapnik/mapnik/issues/1423
|
||||
bool success = false;
|
||||
// https://github.com/mapnik/mapnik/issues/1350
|
||||
if (geom.type() == LineString)
|
||||
{
|
||||
label::middle_point(geom, label_x,label_y);
|
||||
success = label::middle_point(geom, label_x,label_y);
|
||||
}
|
||||
else if (how_placed == POINT_PLACEMENT)
|
||||
{
|
||||
label::centroid(geom, label_x, label_y);
|
||||
success = label::centroid(geom, label_x, label_y);
|
||||
}
|
||||
else if (how_placed == INTERIOR_PLACEMENT)
|
||||
{
|
||||
label::interior_position(geom, label_x, label_y);
|
||||
success = label::interior_position(geom, label_x, label_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
MAPNIK_LOG_ERROR(symbolizer_helpers) << "ERROR: Unknown placement type in initialize_points()";
|
||||
}
|
||||
prj_trans_.backward(label_x, label_y, z);
|
||||
t_.forward(&label_x, &label_y);
|
||||
points_.push_back(std::make_pair(label_x, label_y));
|
||||
if (success)
|
||||
{
|
||||
prj_trans_.backward(label_x, label_y, z);
|
||||
t_.forward(&label_x, &label_y);
|
||||
points_.push_back(std::make_pair(label_x, label_y));
|
||||
}
|
||||
}
|
||||
}
|
||||
point_itr_ = points_.begin();
|
||||
|
|
|
@ -94,6 +94,11 @@ void text_symbolizer_properties::from_xml(xml_node const &sym, fontset_map const
|
|||
if (label_position_tolerance_) label_position_tolerance = *label_position_tolerance_;
|
||||
optional<unsigned> spacing_ = sym.get_opt_attr<unsigned>("spacing");
|
||||
if (spacing_) label_spacing = *spacing_;
|
||||
else {
|
||||
// https://github.com/mapnik/mapnik/issues/1427
|
||||
spacing_ = sym.get_opt_attr<unsigned>("label-spacing");
|
||||
if (spacing_) label_spacing = *spacing_;
|
||||
}
|
||||
optional<unsigned> minimum_distance_ = sym.get_opt_attr<unsigned>("minimum-distance");
|
||||
if (minimum_distance_) minimum_distance = *minimum_distance_;
|
||||
optional<unsigned> min_padding_ = sym.get_opt_attr<unsigned>("minimum-padding");
|
||||
|
|
|
@ -19,12 +19,16 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/transform_expression_grammar.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/version.hpp>
|
||||
|
||||
// spirit
|
||||
#include <boost/spirit/home/phoenix/object/construct.hpp>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
@ -39,8 +43,17 @@ transform_expression_grammar<Iterator>::transform_expression_grammar(expression_
|
|||
using qi::_c; using qi::_3; using qi::_6;
|
||||
using qi::_val;
|
||||
using qi::char_;
|
||||
using qi::double_;
|
||||
using qi::lit;
|
||||
using qi::no_case;
|
||||
|
||||
// [http://www.w3.org/TR/SVG/coords.html#TransformAttribute]
|
||||
|
||||
// The value of the ‘transform’ attribute is a <transform-list>, which
|
||||
// is defined as a list of transform definitions, which are applied in
|
||||
// the order provided. The individual transform definitions are
|
||||
// separated by whitespace and/or a comma.
|
||||
|
||||
#if BOOST_VERSION > 104200
|
||||
using qi::no_skip;
|
||||
start = transform_ % no_skip[char_(", ")] ;
|
||||
|
@ -51,48 +64,71 @@ transform_expression_grammar<Iterator>::transform_expression_grammar(expression_
|
|||
|
||||
transform_ = matrix | translate | scale | rotate | skewX | skewY ;
|
||||
|
||||
// matrix(<a> <b> <c> <d> <e> <f>)
|
||||
matrix = no_case[lit("matrix")]
|
||||
>> (lit('(')
|
||||
>> expr >> -lit(',')
|
||||
>> expr >> -lit(',')
|
||||
>> expr >> -lit(',')
|
||||
>> expr >> -lit(',')
|
||||
>> expr >> -lit(',')
|
||||
>> expr >> lit(')'))
|
||||
>> ( atom >> sep_atom >> sep_atom >> sep_atom >> sep_atom
|
||||
>> sep_atom >> lit(')')
|
||||
| expr >> sep_expr >> sep_expr >> sep_expr >> sep_expr
|
||||
>> sep_expr >> lit(')')
|
||||
))
|
||||
[ _val = construct<matrix_node>(_1,_2,_3,_4,_5,_6) ];
|
||||
|
||||
// translate(<tx> [<ty>])
|
||||
translate = no_case[lit("translate")]
|
||||
>> (lit('(')
|
||||
>> expr >> -lit(',')
|
||||
>> -expr >> lit(')'))
|
||||
[ _val = construct<translate_node>(_1,_2) ];
|
||||
>> lit('(')
|
||||
>> ( ( atom >> -sep_atom >> lit(')') )
|
||||
[ _val = construct<translate_node>(_1,_2) ]
|
||||
| ( expr >> -sep_expr >> lit(')') )
|
||||
[ _val = construct<translate_node>(_1,_2) ]
|
||||
);
|
||||
|
||||
// scale(<sx> [<sy>])
|
||||
scale = no_case[lit("scale")]
|
||||
>> (lit('(')
|
||||
>> expr >> -lit(',')
|
||||
>> -expr >> lit(')'))
|
||||
[ _val = construct<scale_node>(_1,_2) ];
|
||||
>> lit('(')
|
||||
>> ( ( atom >> -sep_atom >> lit(')') )
|
||||
[ _val = construct<scale_node>(_1,_2) ]
|
||||
| ( expr >> -sep_expr >> lit(')') )
|
||||
[ _val = construct<scale_node>(_1,_2) ]
|
||||
);
|
||||
|
||||
// rotate(<rotate-angle> [<cx> <cy>])
|
||||
rotate = no_case[lit("rotate")]
|
||||
>> lit('(')
|
||||
>> expr[_a = _1] >> -lit(',')
|
||||
>> -(expr [_b = _1] >> -lit(',') >> expr[_c = _1])
|
||||
>> lit(')')
|
||||
[ _val = construct<rotate_node>(_a,_b,_c) ];
|
||||
>> ( ( atom >> -( sep_atom >> sep_atom ) >> lit(')') )
|
||||
[ _val = construct<rotate_node>(_1,_2) ]
|
||||
| ( expr >> -( sep_expr >> sep_expr ) >> lit(')') )
|
||||
[ _val = construct<rotate_node>(_1,_2) ]
|
||||
);
|
||||
|
||||
// skewX(<skew-angle>)
|
||||
skewX = no_case[lit("skewX")]
|
||||
>> lit('(')
|
||||
>> expr [ _val = construct<skewX_node>(_1) ]
|
||||
>> lit(')');
|
||||
|
||||
// skewY(<skew-angle>)
|
||||
skewY = no_case[lit("skewY")]
|
||||
>> lit('(')
|
||||
>> expr [ _val = construct<skewY_node>(_1) ]
|
||||
>> lit(')');
|
||||
|
||||
// number or attribute
|
||||
atom = double_ [ _val = _1 ]
|
||||
| attr [ _val = construct<mapnik::attribute>(_1) ];
|
||||
|
||||
// Individual arguments in lists consiting solely of numbers and/or
|
||||
// attributes are separated by whitespace and/or a comma.
|
||||
sep_atom = -lit(',') >> atom [ _val = _1 ];
|
||||
|
||||
// Individual arguments in lists containing one or more compound
|
||||
// expressions are separated by a comma.
|
||||
sep_expr = lit(',') >> expr [ _val = _1 ];
|
||||
|
||||
attr = g.attr.alias();
|
||||
expr = g.expr.alias();
|
||||
}
|
||||
|
||||
template struct mapnik::transform_expression_grammar<std::string::const_iterator>;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
namespace mapnik { namespace util {
|
||||
|
||||
boost::tuple<unsigned,bool> multi_geometry_type::operator() (geometry_container const& geom) const
|
||||
boost::tuple<unsigned,bool> detail::multi_geometry_type::operator() (geometry_container const& geom) const
|
||||
{
|
||||
unsigned type = 0u;
|
||||
bool collection = false;
|
||||
|
|
|
@ -173,7 +173,8 @@ xml_tree::xml_tree(std::string const& encoding)
|
|||
color_grammar(),
|
||||
expr_grammar(tr_),
|
||||
path_expr_grammar(),
|
||||
transform_expr_grammar(expr_grammar)
|
||||
transform_expr_grammar(expr_grammar),
|
||||
image_filters_grammar()
|
||||
{
|
||||
node_.set_processed(true); //root node is always processed
|
||||
}
|
||||
|
|
|
@ -6,16 +6,18 @@ Import ('env')
|
|||
|
||||
test_env = env.Clone()
|
||||
|
||||
headers = env['CPPPATH']
|
||||
|
||||
libraries = copy(env['LIBMAPNIK_LIBS'])
|
||||
libraries.append('mapnik')
|
||||
libraries.append('sqlite3')
|
||||
|
||||
test_env.Append(CXXFLAGS='-g')
|
||||
test_env['LIBS'] = copy(env['LIBMAPNIK_LIBS'])
|
||||
test_env.AppendUnique(LIBS='mapnik')
|
||||
test_env.AppendUnique(LIBS='sqlite3')
|
||||
test_env.AppendUnique(CXXFLAGS='-g')
|
||||
|
||||
for cpp_test in glob.glob('*_test.cpp'):
|
||||
test_program = test_env.Program(cpp_test.replace('.cpp','-bin'), [cpp_test], CPPPATH=headers, LIBS=libraries, LINKFLAGS=env['CUSTOM_LDFLAGS'])
|
||||
test_env_local = test_env.Clone()
|
||||
name = cpp_test.replace('.cpp','-bin')
|
||||
source_files = [cpp_test]
|
||||
if 'csv_parse' in cpp_test:
|
||||
source_files += glob.glob('../../plugins/input/csv/' + '*.cpp')
|
||||
test_program = test_env_local.Program(name, source=source_files, LINKFLAGS=env['CUSTOM_LDFLAGS'])
|
||||
Depends(test_program, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME']))
|
||||
# build locally if installing
|
||||
if 'install' in COMMAND_LINE_TARGETS:
|
||||
|
|
30
tests/cpp_tests/csv_parse_test.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#include <boost/version.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
#include "plugins/input/csv/csv_datasource.hpp"
|
||||
#include <mapnik/params.hpp>
|
||||
|
||||
|
||||
int main( int, char*[] )
|
||||
{
|
||||
// test of directly instanciating a datasource
|
||||
try {
|
||||
mapnik::parameters params;
|
||||
params["type"]="csv";
|
||||
params["file"]="./tests/data/csv/wkt.csv";
|
||||
csv_datasource ds(params);
|
||||
BOOST_TEST(true);
|
||||
} catch (std::exception const& ex) {
|
||||
BOOST_TEST(false);
|
||||
std::clog << "threw: " << ex.what() << "\n";
|
||||
}
|
||||
|
||||
if (!::boost::detail::test_errors()) {
|
||||
std::clog << "C++ CSV parse: \x1b[1;32m✓ \x1b[0m\n";
|
||||
#if BOOST_VERSION >= 104600
|
||||
::boost::detail::report_errors_remind().called_report_errors_function = true;
|
||||
#endif
|
||||
} else {
|
||||
return ::boost::report_errors();
|
||||
}
|
||||
}
|
42
tests/cpp_tests/label_algo_test.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include <boost/version.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
#include <mapnik/geometry.hpp>
|
||||
#include <mapnik/geom_util.hpp>
|
||||
|
||||
|
||||
int main( int, char*[] )
|
||||
{
|
||||
// reused these for simplicity
|
||||
double x,y;
|
||||
|
||||
// single point
|
||||
mapnik::geometry_type pt(mapnik::Point);
|
||||
pt.move_to(10,10);
|
||||
BOOST_TEST( mapnik::label::centroid(pt, x, y) );
|
||||
BOOST_TEST( x == 10 );
|
||||
BOOST_TEST( y == 10 );
|
||||
|
||||
// two points
|
||||
pt.move_to(20,20);
|
||||
BOOST_TEST( mapnik::label::centroid(pt, x, y) );
|
||||
BOOST_TEST_EQ( x, 15 );
|
||||
BOOST_TEST_EQ( y, 15 );
|
||||
|
||||
// line with two verticies
|
||||
mapnik::geometry_type line(mapnik::LineString);
|
||||
line.move_to(0,0);
|
||||
line.move_to(50,50);
|
||||
BOOST_TEST( mapnik::label::centroid(line, x, y) );
|
||||
BOOST_TEST( x == 25 );
|
||||
BOOST_TEST( y == 25 );
|
||||
|
||||
if (!::boost::detail::test_errors()) {
|
||||
std::clog << "C++ label algorithms: \x1b[1;32m✓ \x1b[0m\n";
|
||||
#if BOOST_VERSION >= 104600
|
||||
::boost::detail::report_errors_remind().called_report_errors_function = true;
|
||||
#endif
|
||||
} else {
|
||||
return ::boost::report_errors();
|
||||
}
|
||||
}
|
2
tests/data/csv/fails/more_column_values_than_headers.csv
Normal file
|
@ -0,0 +1,2 @@
|
|||
x,y,one,two
|
||||
0,0,one,two,three
|
|
10
tests/data/csv/geojson_2x_double_quote_filebakery_style.csv
Normal file
|
@ -0,0 +1,10 @@
|
|||
type,GeoJSON
|
||||
point, "{""type"":""Point"",""coordinates"":[30.0,10.0]}"
|
||||
linestring, "{""type"":""LineString"",""coordinates"":[[30.0,10.0],[10.0,30.0],[40.0,40.0]]}"
|
||||
polygon, "{""type"":""Polygon"",""coordinates"":[[[30.0,10.0],[10.0,20.0],[20.0,40.0],[40.0,40.0],[30.0,10.0]]]}"
|
||||
polygon, "{""type"":""Polygon"",""coordinates"":[[[35.0,10.0],[10.0,20.0],[15.0,40.0],[45.0,45.0],[35.0,10.0]],[[20.0,30.0],[35.0,35.0],[30.0,20.0],[20.0,30.0]]]}"
|
||||
multipoint, "{""type"":""MultiPoint"",""coordinates"":[[10.0,40.0],[40.0,30.0],[20.0,20.0],[30.0,10.0]]}"
|
||||
multilinestring, "{""type"":""MultiLineString"",""coordinates"":[[[10.0,10.0],[20.0,20.0],[10.0,40.0]],[[40.0,40.0],[30.0,30.0],[40.0,20.0],[30.0,10.0]]]}"
|
||||
multipolygon, "{""type"":""MultiPolygon"",""coordinates"":[[[[30.0,20.0],[10.0,40.0],[45.0,40.0],[30.0,20.0]]],[[[15.0,5.0],[40.0,10.0],[10.0,20.0],[5.0,10.0],[15.0,5.0]]]]}"
|
||||
multipolygon, "{""type"":""MultiPolygon"",""coordinates"":[[[[40.0,40.0],[20.0,45.0],[45.0,30.0],[40.0,40.0]]],[[[20.0,35.0],[45.0,20.0],[30.0,5.0],[10.0,10.0],[10.0,30.0],[20.0,35.0]],[[30.0,20.0],[20.0,25.0],[20.0,15.0],[30.0,20.0]]]]}"
|
||||
collection, "{""type"":""GeometryCollection"",""geometries"":[{""type"":""Polygon"",""coordinates"":[[[1.0,1.0],[2.0,1.0],[2.0,2.0],[1.0,2.0],[1.0,1.0]]]},{""type"":""Point"",""coordinates"":[2.0,3.0]},{""type"":""LineString"",""coordinates"":[[2.0,3.0],[3.0,4.0]]}]}"
|
|
10
tests/data/csv/geojson_double_quote_escape.csv
Normal file
|
@ -0,0 +1,10 @@
|
|||
type,GeoJSON
|
||||
point, "{\"type\":\"Point\",\"coordinates\":[30.0,10.0]}"
|
||||
linestring, "{\"type\":\"LineString\",\"coordinates\":[[30.0,10.0],[10.0,30.0],[40.0,40.0]]}"
|
||||
polygon, "{\"type\":\"Polygon\",\"coordinates\":[[[30.0,10.0],[10.0,20.0],[20.0,40.0],[40.0,40.0],[30.0,10.0]]]}"
|
||||
polygon, "{\"type\":\"Polygon\",\"coordinates\":[[[35.0,10.0],[10.0,20.0],[15.0,40.0],[45.0,45.0],[35.0,10.0]],[[20.0,30.0],[35.0,35.0],[30.0,20.0],[20.0,30.0]]]}"
|
||||
multipoint, "{\"type\":\"MultiPoint\",\"coordinates\":[[10.0,40.0],[40.0,30.0],[20.0,20.0],[30.0,10.0]]}"
|
||||
multilinestring, "{\"type\":\"MultiLineString\",\"coordinates\":[[[10.0,10.0],[20.0,20.0],[10.0,40.0]],[[40.0,40.0],[30.0,30.0],[40.0,20.0],[30.0,10.0]]]}"
|
||||
multipolygon, "{\"type\":\"MultiPolygon\",\"coordinates\":[[[[30.0,20.0],[10.0,40.0],[45.0,40.0],[30.0,20.0]]],[[[15.0,5.0],[40.0,10.0],[10.0,20.0],[5.0,10.0],[15.0,5.0]]]]}"
|
||||
multipolygon, "{\"type\":\"MultiPolygon\",\"coordinates\":[[[[40.0,40.0],[20.0,45.0],[45.0,30.0],[40.0,40.0]]],[[[20.0,35.0],[45.0,20.0],[30.0,5.0],[10.0,10.0],[10.0,30.0],[20.0,35.0]],[[30.0,20.0],[20.0,25.0],[20.0,15.0],[30.0,20.0]]]]}"
|
||||
collection, "{\"type\":\"GeometryCollection\",\"geometries\":[{\"type\":\"Polygon\",\"coordinates\":[[[1.0,1.0],[2.0,1.0],[2.0,2.0],[1.0,2.0],[1.0,1.0]]]},{\"type\":\"Point\",\"coordinates\":[2.0,3.0]},{\"type\":\"LineString\",\"coordinates\":[[2.0,3.0],[3.0,4.0]]}]}"
|
Can't render this file because it contains an unexpected character in line 2 and column 21.
|
10
tests/data/csv/geojson_single_quote.csv
Normal file
|
@ -0,0 +1,10 @@
|
|||
type,GeoJSON
|
||||
point, '{"type":"Point","coordinates":[30.0,10.0]}'
|
||||
linestring, '{"type":"LineString","coordinates":[[30.0,10.0],[10.0,30.0],[40.0,40.0]]}'
|
||||
polygon, '{"type":"Polygon","coordinates":[[[30.0,10.0],[10.0,20.0],[20.0,40.0],[40.0,40.0],[30.0,10.0]]]}'
|
||||
polygon, '{"type":"Polygon","coordinates":[[[35.0,10.0],[10.0,20.0],[15.0,40.0],[45.0,45.0],[35.0,10.0]],[[20.0,30.0],[35.0,35.0],[30.0,20.0],[20.0,30.0]]]}'
|
||||
multipoint, '{"type":"MultiPoint","coordinates":[[10.0,40.0],[40.0,30.0],[20.0,20.0],[30.0,10.0]]}'
|
||||
multilinestring, '{"type":"MultiLineString","coordinates":[[[10.0,10.0],[20.0,20.0],[10.0,40.0]],[[40.0,40.0],[30.0,30.0],[40.0,20.0],[30.0,10.0]]]}'
|
||||
multipolygon, '{"type":"MultiPolygon","coordinates":[[[[30.0,20.0],[10.0,40.0],[45.0,40.0],[30.0,20.0]]],[[[15.0,5.0],[40.0,10.0],[10.0,20.0],[5.0,10.0],[15.0,5.0]]]]}'
|
||||
multipolygon, '{"type":"MultiPolygon","coordinates":[[[[40.0,40.0],[20.0,45.0],[45.0,30.0],[40.0,40.0]]],[[[20.0,35.0],[45.0,20.0],[30.0,5.0],[10.0,10.0],[10.0,30.0],[20.0,35.0]],[[30.0,20.0],[20.0,25.0],[20.0,15.0],[30.0,20.0]]]]}'
|
||||
collection, '{"type":"GeometryCollection","geometries":[{"type":"Polygon","coordinates":[[[1.0,1.0],[2.0,1.0],[2.0,2.0],[1.0,2.0],[1.0,1.0]]]},{"type":"Point","coordinates":[2.0,3.0]},{"type":"LineString","coordinates":[[2.0,3.0],[3.0,4.0]]}]}'
|
Can't render this file because it contains an unexpected character in line 2 and column 20.
|
2
tests/data/csv/more_headers_than_column_values.csv
Normal file
|
@ -0,0 +1,2 @@
|
|||
x,y,one,two,three
|
||||
0,0
|
|
|
@ -3,15 +3,15 @@
|
|||
<Style name="test 1">
|
||||
<Rule>
|
||||
<Filter>[foo]='bar'</Filter>
|
||||
<PointSymbolizer file="../data/images/foobar.png"/>
|
||||
<PointSymbolizer file="../data/images/dummy.png"/>
|
||||
</Rule>
|
||||
<Rule>
|
||||
<ElseFilter/>
|
||||
<PointSymbolizer file="../data/images/else.png"/>
|
||||
<PointSymbolizer file="../data/images/dummy.png"/>
|
||||
</Rule>
|
||||
<Rule>
|
||||
<AlsoFilter/>
|
||||
<PointSymbolizer file="../data/images/also.png"/>
|
||||
<PointSymbolizer file="../data/images/dummy.png"/>
|
||||
</Rule>
|
||||
</Style>
|
||||
</Map>
|
||||
|
|
20
tests/data/good_maps/path_expression.xml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<Map>
|
||||
<Style name="test">
|
||||
<Rule>
|
||||
<Filter>[filename]='dummy.png'</Filter>
|
||||
<PointSymbolizer file="../../[path1]/[path2]/[filename]"/>
|
||||
</Rule>
|
||||
</Style>
|
||||
|
||||
<Layer name="layer">
|
||||
<StyleName>test</StyleName>
|
||||
<Datasource>
|
||||
<Parameter name="inline">
|
||||
x,y,path1,path2,filename
|
||||
0,0,data,images,dummy.png
|
||||
1,1,data,images,dummy.png
|
||||
</Parameter>
|
||||
<Parameter name="type">csv</Parameter>
|
||||
</Datasource>
|
||||
</Layer>
|
||||
</Map>
|
|
@ -32,11 +32,6 @@
|
|||
<TextSymbolizer size="10" dy="20" face-name="DejaVu Sans Book" halo-radius="1">[name] + ' (jpg)'</TextSymbolizer>
|
||||
<PointSymbolizer file="../images/dummy.jpg"/>
|
||||
</Rule>
|
||||
<Rule>
|
||||
<ElseFilter/>
|
||||
<TextSymbolizer size="10" dy="20" face-name="DejaVu Sans Book" halo-radius="1">[name]</TextSymbolizer>
|
||||
<PointSymbolizer file="../images/bogus_will_fail.png"/>
|
||||
</Rule>
|
||||
</Style>
|
||||
|
||||
<Layer name="point" srs="+init=epsg:4326">
|
||||
|
|
152
tests/python_tests/box2d_test.py
Normal file
|
@ -0,0 +1,152 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
from nose.tools import *
|
||||
import mapnik
|
||||
|
||||
|
||||
def test_coord_init():
|
||||
c = mapnik.Coord(100, 100)
|
||||
|
||||
eq_(c.x, 100)
|
||||
eq_(c.y, 100)
|
||||
|
||||
def test_coord_multiplication():
|
||||
c = mapnik.Coord(100, 100)
|
||||
c *= 2
|
||||
|
||||
eq_(c.x, 200)
|
||||
eq_(c.y, 200)
|
||||
|
||||
def test_envelope_init():
|
||||
e = mapnik.Box2d(100, 100, 200, 200)
|
||||
|
||||
assert_true(e.contains(100, 100))
|
||||
assert_true(e.contains(100, 200))
|
||||
assert_true(e.contains(200, 200))
|
||||
assert_true(e.contains(200, 100))
|
||||
|
||||
assert_true(e.contains(e.center()))
|
||||
|
||||
assert_false(e.contains(99.9, 99.9))
|
||||
assert_false(e.contains(99.9, 200.1))
|
||||
assert_false(e.contains(200.1, 200.1))
|
||||
assert_false(e.contains(200.1, 99.9))
|
||||
|
||||
eq_(e.width(), 100)
|
||||
eq_(e.height(), 100)
|
||||
|
||||
eq_(e.minx, 100)
|
||||
eq_(e.miny, 100)
|
||||
|
||||
eq_(e.maxx, 200)
|
||||
eq_(e.maxy, 200)
|
||||
|
||||
eq_(e[0],100)
|
||||
eq_(e[1],100)
|
||||
eq_(e[2],200)
|
||||
eq_(e[3],200)
|
||||
eq_(e[0],e[-4])
|
||||
eq_(e[1],e[-3])
|
||||
eq_(e[2],e[-2])
|
||||
eq_(e[3],e[-1])
|
||||
|
||||
c = e.center()
|
||||
|
||||
eq_(c.x, 150)
|
||||
eq_(c.y, 150)
|
||||
|
||||
def test_envelope_static_init():
|
||||
e = mapnik.Box2d.from_string('100 100 200 200')
|
||||
e2 = mapnik.Box2d.from_string('100,100,200,200')
|
||||
e3 = mapnik.Box2d.from_string('100 , 100 , 200 , 200')
|
||||
eq_(e,e2)
|
||||
eq_(e,e3)
|
||||
|
||||
assert_true(e.contains(100, 100))
|
||||
assert_true(e.contains(100, 200))
|
||||
assert_true(e.contains(200, 200))
|
||||
assert_true(e.contains(200, 100))
|
||||
|
||||
assert_true(e.contains(e.center()))
|
||||
|
||||
assert_false(e.contains(99.9, 99.9))
|
||||
assert_false(e.contains(99.9, 200.1))
|
||||
assert_false(e.contains(200.1, 200.1))
|
||||
assert_false(e.contains(200.1, 99.9))
|
||||
|
||||
eq_(e.width(), 100)
|
||||
eq_(e.height(), 100)
|
||||
|
||||
eq_(e.minx, 100)
|
||||
eq_(e.miny, 100)
|
||||
|
||||
eq_(e.maxx, 200)
|
||||
eq_(e.maxy, 200)
|
||||
|
||||
eq_(e[0],100)
|
||||
eq_(e[1],100)
|
||||
eq_(e[2],200)
|
||||
eq_(e[3],200)
|
||||
eq_(e[0],e[-4])
|
||||
eq_(e[1],e[-3])
|
||||
eq_(e[2],e[-2])
|
||||
eq_(e[3],e[-1])
|
||||
|
||||
c = e.center()
|
||||
|
||||
eq_(c.x, 150)
|
||||
eq_(c.y, 150)
|
||||
|
||||
def test_envelope_multiplication():
|
||||
e = mapnik.Box2d(100, 100, 200, 200)
|
||||
e *= 2
|
||||
|
||||
assert_true(e.contains(50, 50))
|
||||
assert_true(e.contains(50, 250))
|
||||
assert_true(e.contains(250, 250))
|
||||
assert_true(e.contains(250, 50))
|
||||
|
||||
assert_false(e.contains(49.9, 49.9))
|
||||
assert_false(e.contains(49.9, 250.1))
|
||||
assert_false(e.contains(250.1, 250.1))
|
||||
assert_false(e.contains(250.1, 49.9))
|
||||
|
||||
assert_true(e.contains(e.center()))
|
||||
|
||||
eq_(e.width(), 200)
|
||||
eq_(e.height(), 200)
|
||||
|
||||
eq_(e.minx, 50)
|
||||
eq_(e.miny, 50)
|
||||
|
||||
eq_(e.maxx, 250)
|
||||
eq_(e.maxy, 250)
|
||||
|
||||
c = e.center()
|
||||
|
||||
eq_(c.x, 150)
|
||||
eq_(c.y, 150)
|
||||
|
||||
def test_envelope_clipping():
|
||||
e1 = mapnik.Box2d(-180,-90,180,90)
|
||||
e2 = mapnik.Box2d(-120,40,-110,48)
|
||||
e1.clip(e2)
|
||||
eq_(e1,e2)
|
||||
|
||||
# madagascar in merc
|
||||
e1 = mapnik.Box2d(4772116.5490, -2744395.0631, 5765186.4203, -1609458.0673)
|
||||
e2 = mapnik.Box2d(5124338.3753, -2240522.1727, 5207501.8621, -2130452.8520)
|
||||
e1.clip(e2)
|
||||
eq_(e1,e2)
|
||||
|
||||
# nz in lon/lat
|
||||
e1 = mapnik.Box2d(163.8062, -47.1897, 179.3628, -33.9069)
|
||||
e2 = mapnik.Box2d(173.7378, -39.6395, 174.4849, -38.9252)
|
||||
e1.clip(e2)
|
||||
eq_(e1,e2)
|
||||
|
||||
if __name__ == "__main__":
|
||||
setup()
|
||||
[eval(run)() for run in dir() if 'test_' in run]
|
|
@ -141,7 +141,6 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
eq_(ds.fields(),['type','WKT'])
|
||||
eq_(ds.field_types(),['str','str'])
|
||||
fs = ds.all_features()
|
||||
#import pdb;pdb.set_trace()
|
||||
eq_(len(fs[0].geometries()),1)
|
||||
eq_(fs[0].geometries()[0].type(),mapnik.DataGeometryType.Point)
|
||||
eq_(len(fs[1].geometries()),1)
|
||||
|
@ -150,9 +149,6 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
eq_(fs[2].geometries()[0].type(),mapnik.DataGeometryType.Polygon)
|
||||
eq_(len(fs[3].geometries()),1) # one geometry, two parts
|
||||
eq_(fs[3].geometries()[0].type(),mapnik.DataGeometryType.Polygon)
|
||||
# tests assuming we want to flatten geometries
|
||||
# ideally we should not have to:
|
||||
# https://github.com/mapnik/mapnik/issues?labels=multigeom+robustness&sort=created&direction=desc&state=open&page=1
|
||||
eq_(len(fs[4].geometries()),4)
|
||||
eq_(fs[4].geometries()[0].type(),mapnik.DataGeometryType.Point)
|
||||
eq_(len(fs[5].geometries()),2)
|
||||
|
@ -363,6 +359,64 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
feat = fs.next()
|
||||
eq_(feat['Name'],u"Winthrop, WA")
|
||||
|
||||
def validate_geojson_datasource(ds):
|
||||
eq_(len(ds.fields()),2)
|
||||
eq_(ds.fields(),['type','GeoJSON'])
|
||||
eq_(ds.field_types(),['str','str'])
|
||||
fs = ds.all_features()
|
||||
eq_(len(fs[0].geometries()),1)
|
||||
eq_(fs[0].geometries()[0].type(),mapnik.DataGeometryType.Point)
|
||||
eq_(len(fs[1].geometries()),1)
|
||||
eq_(fs[1].geometries()[0].type(),mapnik.DataGeometryType.LineString)
|
||||
eq_(len(fs[2].geometries()),1)
|
||||
eq_(fs[2].geometries()[0].type(),mapnik.DataGeometryType.Polygon)
|
||||
eq_(len(fs[3].geometries()),1) # one geometry, two parts
|
||||
eq_(fs[3].geometries()[0].type(),mapnik.DataGeometryType.Polygon)
|
||||
eq_(len(fs[4].geometries()),4)
|
||||
eq_(fs[4].geometries()[0].type(),mapnik.DataGeometryType.Point)
|
||||
eq_(len(fs[5].geometries()),2)
|
||||
eq_(fs[5].geometries()[0].type(),mapnik.DataGeometryType.LineString)
|
||||
eq_(len(fs[6].geometries()),2)
|
||||
eq_(fs[6].geometries()[0].type(),mapnik.DataGeometryType.Polygon)
|
||||
eq_(len(fs[7].geometries()),2)
|
||||
eq_(fs[7].geometries()[0].type(),mapnik.DataGeometryType.Polygon)
|
||||
desc = ds.describe()
|
||||
eq_(desc['geometry_type'],mapnik.DataGeometryType.Collection)
|
||||
eq_(desc['name'],'csv')
|
||||
eq_(desc['type'],mapnik.DataType.Vector)
|
||||
eq_(desc['encoding'],'utf-8')
|
||||
|
||||
def test_json_field1(**kwargs):
|
||||
ds = get_csv_ds('geojson_double_quote_escape.csv')
|
||||
validate_geojson_datasource(ds)
|
||||
|
||||
def test_json_field2(**kwargs):
|
||||
ds = get_csv_ds('geojson_single_quote.csv')
|
||||
validate_geojson_datasource(ds)
|
||||
|
||||
def test_json_field3(**kwargs):
|
||||
ds = get_csv_ds('geojson_2x_double_quote_filebakery_style.csv')
|
||||
validate_geojson_datasource(ds)
|
||||
|
||||
def test_that_blank_undelimited_rows_are_still_parsed(**kwargs):
|
||||
ds = get_csv_ds('more_headers_than_column_values.csv')
|
||||
eq_(len(ds.fields()),5)
|
||||
eq_(ds.fields(),['x','y','one', 'two','three'])
|
||||
eq_(ds.field_types(),['int','int','str','str','str'])
|
||||
fs = ds.featureset()
|
||||
feat = fs.next()
|
||||
eq_(feat['x'],0)
|
||||
eq_(feat['y'],0)
|
||||
eq_(feat['one'],'')
|
||||
eq_(feat['two'],'')
|
||||
eq_(feat['three'],'')
|
||||
desc = ds.describe()
|
||||
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
|
||||
|
||||
@raises(RuntimeError)
|
||||
def test_that_fewer_headers_than_rows_throws(**kwargs):
|
||||
# this has invalid header # so throw
|
||||
ds = get_csv_ds('more_column_values_than_headers.csv')
|
||||
|
||||
if __name__ == "__main__":
|
||||
setup()
|
||||
|
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 123 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 48 KiB |
27
tests/python_tests/layer_test.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from nose.tools import *
|
||||
import mapnik
|
||||
|
||||
# Map initialization
|
||||
def test_layer_init():
|
||||
l = mapnik.Layer('test')
|
||||
eq_(l.name,'test')
|
||||
eq_(l.srs,'+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')
|
||||
eq_(l.envelope(),mapnik.Box2d())
|
||||
eq_(l.clear_label_cache,False)
|
||||
eq_(l.cache_features,False)
|
||||
eq_(l.visible(1),True)
|
||||
eq_(l.active,True)
|
||||
eq_(l.datasource,None)
|
||||
eq_(l.queryable,False)
|
||||
eq_(l.minzoom,0.0)
|
||||
eq_(l.maxzoom > 1e+6,True)
|
||||
eq_(l.group_by,"")
|
||||
eq_(l.maximum_extent,None)
|
||||
eq_(l.buffer_size,0.0)
|
||||
eq_(len(l.styles),0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
[eval(run)() for run in dir() if 'test_' in run]
|
|
@ -29,77 +29,78 @@ def test_map_query_throw3():
|
|||
m = mapnik.Map(256,256)
|
||||
m.query_point(0,0,0)
|
||||
|
||||
# map has never been zoomed (even with data)
|
||||
@raises(RuntimeError)
|
||||
def test_map_query_throw4():
|
||||
m = mapnik.Map(256,256)
|
||||
mapnik.load_map(m,'../data/good_maps/agg_poly_gamma_map.xml')
|
||||
m.query_point(0,0,0)
|
||||
|
||||
# invalid coords in general (do not intersect)
|
||||
@raises(RuntimeError)
|
||||
def test_map_query_throw5():
|
||||
m = mapnik.Map(256,256)
|
||||
mapnik.load_map(m,'../data/good_maps/agg_poly_gamma_map.xml')
|
||||
m.zoom_all()
|
||||
m.query_point(0,9999999999999999,9999999999999999)
|
||||
|
||||
# invalid coords for back projecting
|
||||
@raises(RuntimeError)
|
||||
def test_map_query_throw6():
|
||||
m = mapnik.Map(256,256)
|
||||
mapnik.load_map(m,'../data/good_maps/merc2wgs84_reprojection.xml')
|
||||
wgs84_bounds = mapnik.Box2d(-180,-90,180,90)
|
||||
m.maximum_extent = wgs84_bounds
|
||||
m.zoom_all()
|
||||
m.query_point(0,-180,-90)
|
||||
|
||||
def test_map_query_works1():
|
||||
m = mapnik.Map(256,256)
|
||||
mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml')
|
||||
merc_bounds = mapnik.Box2d(-20037508.34,-20037508.34,20037508.34,20037508.34)
|
||||
m.maximum_extent = merc_bounds
|
||||
m.zoom_all()
|
||||
fs = m.query_point(0,-11012435.5376, 4599674.6134) # somewhere in kansas
|
||||
feat = fs.next()
|
||||
eq_(feat.attributes['NAME_FORMA'],u'United States of America')
|
||||
|
||||
def test_map_query_works2():
|
||||
m = mapnik.Map(256,256)
|
||||
mapnik.load_map(m,'../data/good_maps/merc2wgs84_reprojection.xml')
|
||||
wgs84_bounds = mapnik.Box2d(-179.999999975,-85.0511287776,179.999999975,85.0511287776)
|
||||
m.maximum_extent = wgs84_bounds
|
||||
# caution - will go square due to evil aspect_fix_mode backhandedness
|
||||
m.zoom_all()
|
||||
#mapnik.render_to_file(m,'works2.png')
|
||||
# valid that aspec_fix_mode modified the bbox
|
||||
eq_(m.envelope(),mapnik.Box2d(-179.999999975,-179.999999975,179.999999975,179.999999975))
|
||||
fs = m.query_point(0,-98.9264, 38.1432) # somewhere in kansas
|
||||
feat = fs.next()
|
||||
eq_(feat.attributes['NAME'],u'United States')
|
||||
|
||||
def test_map_query_in_pixels_works1():
|
||||
m = mapnik.Map(256,256)
|
||||
mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml')
|
||||
merc_bounds = mapnik.Box2d(-20037508.34,-20037508.34,20037508.34,20037508.34)
|
||||
m.maximum_extent = merc_bounds
|
||||
m.zoom_all()
|
||||
fs = m.query_map_point(0,55,100) # somewhere in middle of us
|
||||
feat = fs.next()
|
||||
eq_(feat.attributes['NAME_FORMA'],u'United States of America')
|
||||
|
||||
def test_map_query_in_pixels_works2():
|
||||
m = mapnik.Map(256,256)
|
||||
mapnik.load_map(m,'../data/good_maps/merc2wgs84_reprojection.xml')
|
||||
wgs84_bounds = mapnik.Box2d(-179.999999975,-85.0511287776,179.999999975,85.0511287776)
|
||||
m.maximum_extent = wgs84_bounds
|
||||
# caution - will go square due to evil aspect_fix_mode backhandedness
|
||||
m.zoom_all()
|
||||
# valid that aspec_fix_mode modified the bbox
|
||||
eq_(m.envelope(),mapnik.Box2d(-179.999999975,-179.999999975,179.999999975,179.999999975))
|
||||
fs = m.query_map_point(0,55,100) # somewhere in middle of us
|
||||
feat = fs.next()
|
||||
eq_(feat.attributes['NAME'],u'United States')
|
||||
if 'shape' in mapnik.DatasourceCache.instance().plugin_names():
|
||||
# map has never been zoomed (even with data)
|
||||
@raises(RuntimeError)
|
||||
def test_map_query_throw4():
|
||||
m = mapnik.Map(256,256)
|
||||
mapnik.load_map(m,'../data/good_maps/agg_poly_gamma_map.xml')
|
||||
m.query_point(0,0,0)
|
||||
|
||||
# invalid coords in general (do not intersect)
|
||||
@raises(RuntimeError)
|
||||
def test_map_query_throw5():
|
||||
m = mapnik.Map(256,256)
|
||||
mapnik.load_map(m,'../data/good_maps/agg_poly_gamma_map.xml')
|
||||
m.zoom_all()
|
||||
m.query_point(0,9999999999999999,9999999999999999)
|
||||
|
||||
# invalid coords for back projecting
|
||||
@raises(RuntimeError)
|
||||
def test_map_query_throw6():
|
||||
m = mapnik.Map(256,256)
|
||||
mapnik.load_map(m,'../data/good_maps/merc2wgs84_reprojection.xml')
|
||||
wgs84_bounds = mapnik.Box2d(-180,-90,180,90)
|
||||
m.maximum_extent = wgs84_bounds
|
||||
m.zoom_all()
|
||||
m.query_point(0,-180,-90)
|
||||
|
||||
def test_map_query_works1():
|
||||
m = mapnik.Map(256,256)
|
||||
mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml')
|
||||
merc_bounds = mapnik.Box2d(-20037508.34,-20037508.34,20037508.34,20037508.34)
|
||||
m.maximum_extent = merc_bounds
|
||||
m.zoom_all()
|
||||
fs = m.query_point(0,-11012435.5376, 4599674.6134) # somewhere in kansas
|
||||
feat = fs.next()
|
||||
eq_(feat.attributes['NAME_FORMA'],u'United States of America')
|
||||
|
||||
def test_map_query_works2():
|
||||
m = mapnik.Map(256,256)
|
||||
mapnik.load_map(m,'../data/good_maps/merc2wgs84_reprojection.xml')
|
||||
wgs84_bounds = mapnik.Box2d(-179.999999975,-85.0511287776,179.999999975,85.0511287776)
|
||||
m.maximum_extent = wgs84_bounds
|
||||
# caution - will go square due to evil aspect_fix_mode backhandedness
|
||||
m.zoom_all()
|
||||
#mapnik.render_to_file(m,'works2.png')
|
||||
# valid that aspec_fix_mode modified the bbox
|
||||
eq_(m.envelope(),mapnik.Box2d(-179.999999975,-179.999999975,179.999999975,179.999999975))
|
||||
fs = m.query_point(0,-98.9264, 38.1432) # somewhere in kansas
|
||||
feat = fs.next()
|
||||
eq_(feat.attributes['NAME'],u'United States')
|
||||
|
||||
def test_map_query_in_pixels_works1():
|
||||
m = mapnik.Map(256,256)
|
||||
mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml')
|
||||
merc_bounds = mapnik.Box2d(-20037508.34,-20037508.34,20037508.34,20037508.34)
|
||||
m.maximum_extent = merc_bounds
|
||||
m.zoom_all()
|
||||
fs = m.query_map_point(0,55,100) # somewhere in middle of us
|
||||
feat = fs.next()
|
||||
eq_(feat.attributes['NAME_FORMA'],u'United States of America')
|
||||
|
||||
def test_map_query_in_pixels_works2():
|
||||
m = mapnik.Map(256,256)
|
||||
mapnik.load_map(m,'../data/good_maps/merc2wgs84_reprojection.xml')
|
||||
wgs84_bounds = mapnik.Box2d(-179.999999975,-85.0511287776,179.999999975,85.0511287776)
|
||||
m.maximum_extent = wgs84_bounds
|
||||
# caution - will go square due to evil aspect_fix_mode backhandedness
|
||||
m.zoom_all()
|
||||
# valid that aspec_fix_mode modified the bbox
|
||||
eq_(m.envelope(),mapnik.Box2d(-179.999999975,-179.999999975,179.999999975,179.999999975))
|
||||
fs = m.query_map_point(0,55,100) # somewhere in middle of us
|
||||
feat = fs.next()
|
||||
eq_(feat.attributes['NAME'],u'United States')
|
||||
|
||||
if __name__ == "__main__":
|
||||
setup()
|
||||
|
|
|
@ -14,12 +14,42 @@ def setup():
|
|||
# from another directory we need to chdir()
|
||||
os.chdir(execution_path('.'))
|
||||
|
||||
# Tests that exercise the functionality of Mapnik classes.
|
||||
def test_line_pattern():
|
||||
s = mapnik.LinePatternSymbolizer(mapnik.PathExpression('../data/images/dummy.png'))
|
||||
eq_(s.filename, '../data/images/dummy.png')
|
||||
eq_(s.smooth,0.0)
|
||||
eq_(s.transform,'')
|
||||
eq_(s.comp_op,mapnik.CompositeOp.src_over)
|
||||
eq_(s.clip,True)
|
||||
|
||||
# LineSymbolizer initialization
|
||||
def test_line_symbolizer_init():
|
||||
def test_line_symbolizer():
|
||||
s = mapnik.LineSymbolizer()
|
||||
eq_(s.rasterizer, mapnik.line_rasterizer.FULL)
|
||||
eq_(s.smooth,0.0)
|
||||
eq_(s.comp_op,mapnik.CompositeOp.src_over)
|
||||
eq_(s.clip,True)
|
||||
eq_(s.stroke.width, 1)
|
||||
eq_(s.stroke.opacity, 1)
|
||||
eq_(s.stroke.color, mapnik.Color('black'))
|
||||
eq_(s.stroke.line_cap, mapnik.line_cap.BUTT_CAP)
|
||||
eq_(s.stroke.line_join, mapnik.line_join.MITER_JOIN)
|
||||
|
||||
l = mapnik.LineSymbolizer(mapnik.Color('blue'), 5.0)
|
||||
|
||||
eq_(l.stroke.width, 5)
|
||||
eq_(l.stroke.opacity, 1)
|
||||
eq_(l.stroke.color, mapnik.Color('blue'))
|
||||
eq_(l.stroke.line_cap, mapnik.line_cap.BUTT_CAP)
|
||||
eq_(l.stroke.line_join, mapnik.line_join.MITER_JOIN)
|
||||
|
||||
s = mapnik.Stroke(mapnik.Color('blue'), 5.0)
|
||||
l = mapnik.LineSymbolizer(s)
|
||||
|
||||
eq_(l.stroke.width, 5)
|
||||
eq_(l.stroke.opacity, 1)
|
||||
eq_(l.stroke.color, mapnik.Color('blue'))
|
||||
eq_(l.stroke.line_cap, mapnik.line_cap.BUTT_CAP)
|
||||
eq_(l.stroke.line_join, mapnik.line_join.MITER_JOIN)
|
||||
|
||||
def test_line_symbolizer_stroke_reference():
|
||||
l = mapnik.LineSymbolizer(mapnik.Color('green'),0.1)
|
||||
|
@ -30,9 +60,54 @@ def test_line_symbolizer_stroke_reference():
|
|||
eq_(l.stroke.opacity,1.0)
|
||||
assert_almost_equal(l.stroke.width,0.1)
|
||||
|
||||
# ShieldSymbolizer initialization
|
||||
def test_shieldsymbolizer_init():
|
||||
# https://github.com/mapnik/mapnik/issues/1427
|
||||
def test_stroke_dash_api():
|
||||
stroke = mapnik.Stroke()
|
||||
dashes = [(1.0,1.0)]
|
||||
stroke.dasharray = dashes
|
||||
eq_(stroke.dasharray, dashes)
|
||||
stroke.add_dash(.1,.1)
|
||||
dashes.append((.1,.1))
|
||||
eq_(stroke.dasharray, dashes)
|
||||
|
||||
|
||||
def test_text_symbolizer():
|
||||
s = mapnik.TextSymbolizer()
|
||||
eq_(s.comp_op,mapnik.CompositeOp.src_over)
|
||||
eq_(s.clip,True)
|
||||
|
||||
# https://github.com/mapnik/mapnik/issues/1420
|
||||
eq_(s.text_transform, mapnik.text_transform.NONE)
|
||||
|
||||
# https://github.com/mapnik/mapnik/issues/1427
|
||||
eq_(s.wrap_char,ord(' '))
|
||||
eq_(s.wrap_character,ord(' '))
|
||||
s.wrap_char = ord('\n')
|
||||
eq_(s.wrap_char,ord('\n'))
|
||||
eq_(s.wrap_character,ord('\n'))
|
||||
eq_(s.format.wrap_character,ord('\n'))
|
||||
s.wrap_character = ord('\r')
|
||||
eq_(s.wrap_char,ord('\r'))
|
||||
eq_(s.wrap_character,ord('\r'))
|
||||
eq_(s.format.wrap_character,ord('\r'))
|
||||
s.format.wrap_character = ord(' ')
|
||||
eq_(s.wrap_char,ord(' '))
|
||||
eq_(s.wrap_character,ord(' '))
|
||||
eq_(s.format.wrap_character,ord(' '))
|
||||
|
||||
# old args required method
|
||||
ts = mapnik.TextSymbolizer(mapnik.Expression('[Field_Name]'), 'Font Name', 8, mapnik.Color('black'))
|
||||
# eq_(str(ts.name), str(mapnik2.Expression('[Field_Name]'))) name field is no longer supported
|
||||
eq_(ts.format.face_name, 'Font Name')
|
||||
eq_(ts.format.text_size, 8)
|
||||
eq_(ts.format.fill, mapnik.Color('black'))
|
||||
eq_(ts.properties.label_placement, mapnik.label_placement.POINT_PLACEMENT)
|
||||
eq_(ts.properties.horizontal_alignment, mapnik.horizontal_alignment.AUTO)
|
||||
|
||||
def test_shield_symbolizer_init():
|
||||
s = mapnik.ShieldSymbolizer(mapnik.Expression('[Field Name]'), 'DejaVu Sans Bold', 6, mapnik.Color('#000000'), mapnik.PathExpression('../data/images/dummy.png'))
|
||||
eq_(s.comp_op,mapnik.CompositeOp.src_over)
|
||||
eq_(s.clip,True)
|
||||
eq_(s.displacement, (0.0,0.0))
|
||||
eq_(s.allow_overlap, False)
|
||||
eq_(s.avoid_edges, False)
|
||||
|
@ -89,34 +164,31 @@ def test_shieldsymbolizer_init():
|
|||
#def test_shieldsymbolizer_missing_image():
|
||||
# s = mapnik.ShieldSymbolizer(mapnik.Expression('[Field Name]'), 'DejaVu Sans Bold', 6, mapnik.Color('#000000'), mapnik.PathExpression('../#data/images/broken.png'))
|
||||
|
||||
# ShieldSymbolizer modification
|
||||
def test_shieldsymbolizer_modify():
|
||||
def test_shield_symbolizer_modify():
|
||||
s = mapnik.ShieldSymbolizer(mapnik.Expression('[Field Name]'), 'DejaVu Sans Bold', 6, mapnik.Color('#000000'), mapnik.PathExpression('../data/images/dummy.png'))
|
||||
# transform expression
|
||||
s.transform = "rotate(30+[a]) scale(2*[sx] [sy])"
|
||||
eq_(s.transform, "rotate((30+[a])) scale(2*[sx], [sy])")
|
||||
def check_transform(expr, expect_str=None):
|
||||
s.transform = expr
|
||||
eq_(s.transform, expr if expect_str is None else expect_str)
|
||||
check_transform("matrix(1 2 3 4 5 6)", "matrix(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)")
|
||||
check_transform("matrix(1, 2, 3, 4, 5, 6 +7)", "matrix(1, 2, 3, 4, 5, (6+7))")
|
||||
check_transform("rotate([a])")
|
||||
check_transform("rotate([a] -2)", "rotate(([a]-2))")
|
||||
check_transform("rotate([a] -2 -3)", "rotate([a], -2.0, -3.0)")
|
||||
check_transform("rotate([a] -2 -3 -4)", "rotate(((([a]-2)-3)-4))")
|
||||
check_transform("rotate([a] -2, 3, 4)", "rotate(([a]-2), 3, 4)")
|
||||
check_transform("translate([tx]) rotate([a])")
|
||||
check_transform("scale([sx], [sy]/2)")
|
||||
# TODO check expected failures
|
||||
|
||||
def test_polygonsymbolizer_init():
|
||||
p = mapnik.PolygonSymbolizer()
|
||||
|
||||
eq_(p.fill, mapnik.Color('gray'))
|
||||
eq_(p.fill_opacity, 1)
|
||||
eq_(p.placement, mapnik.point_placement.CENTROID)
|
||||
|
||||
p = mapnik.PolygonSymbolizer(mapnik.Color('blue'))
|
||||
p.placement = mapnik.point_placement.INTERIOR
|
||||
|
||||
eq_(p.fill, mapnik.Color('blue'))
|
||||
eq_(p.fill_opacity, 1)
|
||||
eq_(p.placement, mapnik.point_placement.INTERIOR)
|
||||
|
||||
# PointSymbolizer initialization
|
||||
def test_pointsymbolizer_init():
|
||||
def test_point_symbolizer():
|
||||
p = mapnik.PointSymbolizer()
|
||||
eq_(p.allow_overlap, False)
|
||||
eq_(p.opacity,1)
|
||||
eq_(p.filename,'')
|
||||
eq_(p.transform,'')
|
||||
eq_(p.opacity,1.0)
|
||||
eq_(p.allow_overlap,False)
|
||||
eq_(p.ignore_placement,False)
|
||||
eq_(p.comp_op,mapnik.CompositeOp.src_over)
|
||||
eq_(p.placement, mapnik.point_placement.CENTROID)
|
||||
|
||||
p = mapnik.PointSymbolizer(mapnik.PathExpression("../data/images/dummy.png"))
|
||||
|
@ -130,9 +202,7 @@ def test_pointsymbolizer_init():
|
|||
eq_(p.ignore_placement,True)
|
||||
eq_(p.placement, mapnik.point_placement.INTERIOR)
|
||||
|
||||
|
||||
# MarkersSymbolizer initialization
|
||||
def test_markersymbolizer_init():
|
||||
def test_markers_symbolizer():
|
||||
p = mapnik.MarkersSymbolizer()
|
||||
eq_(p.allow_overlap, False)
|
||||
eq_(p.opacity,1.0)
|
||||
|
@ -145,6 +215,10 @@ def test_markersymbolizer_init():
|
|||
eq_(p.max_error,0.2)
|
||||
eq_(p.width,None)
|
||||
eq_(p.height,None)
|
||||
eq_(p.transform,'')
|
||||
eq_(p.clip,True)
|
||||
eq_(p.comp_op,mapnik.CompositeOp.src_over)
|
||||
|
||||
|
||||
p.width = mapnik.Expression('12')
|
||||
p.height = mapnik.Expression('12')
|
||||
|
@ -170,6 +244,12 @@ def test_markersymbolizer_init():
|
|||
eq_(p.opacity, 0.5)
|
||||
eq_(p.fill_opacity, 0.5)
|
||||
|
||||
#https://github.com/mapnik/mapnik/issues/1285
|
||||
#https://github.com/mapnik/mapnik/issues/1427
|
||||
p.marker_type = 'arrow'
|
||||
eq_(p.marker_type,'shape://arrow')
|
||||
eq_(p.filename,'shape://arrow')
|
||||
|
||||
|
||||
# PointSymbolizer missing image file
|
||||
# images paths are now PathExpressions are evaluated at runtime
|
||||
|
@ -178,10 +258,11 @@ def test_markersymbolizer_init():
|
|||
#def test_pointsymbolizer_missing_image():
|
||||
# p = mapnik.PointSymbolizer(mapnik.PathExpression("../data/images/broken.png"))
|
||||
|
||||
# PolygonSymbolizer initialization
|
||||
def test_polygonsymbolizer_init():
|
||||
def test_polygon_symbolizer():
|
||||
p = mapnik.PolygonSymbolizer()
|
||||
|
||||
eq_(p.smooth,0.0)
|
||||
eq_(p.comp_op,mapnik.CompositeOp.src_over)
|
||||
eq_(p.clip,True)
|
||||
eq_(p.fill, mapnik.Color('gray'))
|
||||
eq_(p.fill_opacity, 1)
|
||||
|
||||
|
@ -190,7 +271,13 @@ def test_polygonsymbolizer_init():
|
|||
eq_(p.fill, mapnik.Color('blue'))
|
||||
eq_(p.fill_opacity, 1)
|
||||
|
||||
# Stroke initialization
|
||||
def test_building_symbolizer_init():
|
||||
p = mapnik.BuildingSymbolizer()
|
||||
|
||||
eq_(p.fill, mapnik.Color('gray'))
|
||||
eq_(p.fill_opacity, 1)
|
||||
eq_(p.height,None)
|
||||
|
||||
def test_stroke_init():
|
||||
s = mapnik.Stroke()
|
||||
|
||||
|
@ -211,7 +298,6 @@ def test_stroke_init():
|
|||
eq_(s.line_cap, mapnik.line_cap.BUTT_CAP)
|
||||
eq_(s.line_join, mapnik.line_join.MITER_JOIN)
|
||||
|
||||
# Stroke dashes
|
||||
def test_stroke_dash_arrays():
|
||||
s = mapnik.Stroke()
|
||||
s.add_dash(1,2)
|
||||
|
@ -220,58 +306,6 @@ def test_stroke_dash_arrays():
|
|||
|
||||
eq_(s.get_dashes(), [(1,2),(3,4),(5,6)])
|
||||
|
||||
# LineSymbolizer initialization
|
||||
def test_linesymbolizer_init():
|
||||
l = mapnik.LineSymbolizer()
|
||||
|
||||
eq_(l.stroke.width, 1)
|
||||
eq_(l.stroke.opacity, 1)
|
||||
eq_(l.stroke.color, mapnik.Color('black'))
|
||||
eq_(l.stroke.line_cap, mapnik.line_cap.BUTT_CAP)
|
||||
eq_(l.stroke.line_join, mapnik.line_join.MITER_JOIN)
|
||||
|
||||
l = mapnik.LineSymbolizer(mapnik.Color('blue'), 5.0)
|
||||
|
||||
eq_(l.stroke.width, 5)
|
||||
eq_(l.stroke.opacity, 1)
|
||||
eq_(l.stroke.color, mapnik.Color('blue'))
|
||||
eq_(l.stroke.line_cap, mapnik.line_cap.BUTT_CAP)
|
||||
eq_(l.stroke.line_join, mapnik.line_join.MITER_JOIN)
|
||||
|
||||
s = mapnik.Stroke(mapnik.Color('blue'), 5.0)
|
||||
l = mapnik.LineSymbolizer(s)
|
||||
|
||||
eq_(l.stroke.width, 5)
|
||||
eq_(l.stroke.opacity, 1)
|
||||
eq_(l.stroke.color, mapnik.Color('blue'))
|
||||
eq_(l.stroke.line_cap, mapnik.line_cap.BUTT_CAP)
|
||||
eq_(l.stroke.line_join, mapnik.line_join.MITER_JOIN)
|
||||
|
||||
# TextSymbolizer initialization
|
||||
def test_textsymbolizer_init():
|
||||
ts = mapnik.TextSymbolizer(mapnik.Expression('[Field_Name]'), 'Font Name', 8, mapnik.Color('black'))
|
||||
|
||||
# eq_(str(ts.name), str(mapnik2.Expression('[Field_Name]'))) name field is no longer supported
|
||||
eq_(ts.format.face_name, 'Font Name')
|
||||
eq_(ts.format.text_size, 8)
|
||||
eq_(ts.format.fill, mapnik.Color('black'))
|
||||
eq_(ts.properties.label_placement, mapnik.label_placement.POINT_PLACEMENT)
|
||||
eq_(ts.properties.horizontal_alignment, mapnik.horizontal_alignment.AUTO)
|
||||
|
||||
# Map initialization
|
||||
def test_layer_init():
|
||||
l = mapnik.Layer('test')
|
||||
eq_(l.name,'test')
|
||||
eq_(l.envelope(),mapnik.Box2d())
|
||||
eq_(l.clear_label_cache,False)
|
||||
eq_(l.cache_features,False)
|
||||
eq_(l.visible(1),True)
|
||||
eq_(l.active,True)
|
||||
eq_(l.datasource,None)
|
||||
eq_(l.queryable,False)
|
||||
eq_(l.srs,'+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')
|
||||
|
||||
# Map initialization
|
||||
def test_map_init():
|
||||
m = mapnik.Map(256, 256)
|
||||
|
||||
|
@ -387,7 +421,6 @@ def test_color_init():
|
|||
|
||||
eq_(c.to_hex_string(), '#004080c0')
|
||||
|
||||
# Color equality
|
||||
def test_color_equality():
|
||||
|
||||
c1 = mapnik.Color('blue')
|
||||
|
@ -442,7 +475,6 @@ def test_color_equality():
|
|||
eq_(c2, mapnik.Color('lime'))
|
||||
eq_(c3, mapnik.Color(0,0,255,128))
|
||||
|
||||
# Rule initialization
|
||||
def test_rule_init():
|
||||
min_scale = 5
|
||||
max_scale = 10
|
||||
|
@ -499,153 +531,6 @@ def test_rule_init():
|
|||
eq_(r.has_else(), False)
|
||||
eq_(r.has_also(), False)
|
||||
|
||||
# Coordinate initialization
|
||||
def test_coord_init():
|
||||
c = mapnik.Coord(100, 100)
|
||||
|
||||
eq_(c.x, 100)
|
||||
eq_(c.y, 100)
|
||||
|
||||
# Coordinate multiplication
|
||||
def test_coord_multiplication():
|
||||
c = mapnik.Coord(100, 100)
|
||||
c *= 2
|
||||
|
||||
eq_(c.x, 200)
|
||||
eq_(c.y, 200)
|
||||
|
||||
# Box2d initialization
|
||||
def test_envelope_init():
|
||||
e = mapnik.Box2d(100, 100, 200, 200)
|
||||
|
||||
assert_true(e.contains(100, 100))
|
||||
assert_true(e.contains(100, 200))
|
||||
assert_true(e.contains(200, 200))
|
||||
assert_true(e.contains(200, 100))
|
||||
|
||||
assert_true(e.contains(e.center()))
|
||||
|
||||
assert_false(e.contains(99.9, 99.9))
|
||||
assert_false(e.contains(99.9, 200.1))
|
||||
assert_false(e.contains(200.1, 200.1))
|
||||
assert_false(e.contains(200.1, 99.9))
|
||||
|
||||
eq_(e.width(), 100)
|
||||
eq_(e.height(), 100)
|
||||
|
||||
eq_(e.minx, 100)
|
||||
eq_(e.miny, 100)
|
||||
|
||||
eq_(e.maxx, 200)
|
||||
eq_(e.maxy, 200)
|
||||
|
||||
eq_(e[0],100)
|
||||
eq_(e[1],100)
|
||||
eq_(e[2],200)
|
||||
eq_(e[3],200)
|
||||
eq_(e[0],e[-4])
|
||||
eq_(e[1],e[-3])
|
||||
eq_(e[2],e[-2])
|
||||
eq_(e[3],e[-1])
|
||||
|
||||
c = e.center()
|
||||
|
||||
eq_(c.x, 150)
|
||||
eq_(c.y, 150)
|
||||
|
||||
# Box2d static initialization
|
||||
def test_envelope_static_init():
|
||||
e = mapnik.Box2d.from_string('100 100 200 200')
|
||||
e2 = mapnik.Box2d.from_string('100,100,200,200')
|
||||
e3 = mapnik.Box2d.from_string('100 , 100 , 200 , 200')
|
||||
eq_(e,e2)
|
||||
eq_(e,e3)
|
||||
|
||||
assert_true(e.contains(100, 100))
|
||||
assert_true(e.contains(100, 200))
|
||||
assert_true(e.contains(200, 200))
|
||||
assert_true(e.contains(200, 100))
|
||||
|
||||
assert_true(e.contains(e.center()))
|
||||
|
||||
assert_false(e.contains(99.9, 99.9))
|
||||
assert_false(e.contains(99.9, 200.1))
|
||||
assert_false(e.contains(200.1, 200.1))
|
||||
assert_false(e.contains(200.1, 99.9))
|
||||
|
||||
eq_(e.width(), 100)
|
||||
eq_(e.height(), 100)
|
||||
|
||||
eq_(e.minx, 100)
|
||||
eq_(e.miny, 100)
|
||||
|
||||
eq_(e.maxx, 200)
|
||||
eq_(e.maxy, 200)
|
||||
|
||||
eq_(e[0],100)
|
||||
eq_(e[1],100)
|
||||
eq_(e[2],200)
|
||||
eq_(e[3],200)
|
||||
eq_(e[0],e[-4])
|
||||
eq_(e[1],e[-3])
|
||||
eq_(e[2],e[-2])
|
||||
eq_(e[3],e[-1])
|
||||
|
||||
c = e.center()
|
||||
|
||||
eq_(c.x, 150)
|
||||
eq_(c.y, 150)
|
||||
|
||||
# Box2d multiplication
|
||||
def test_envelope_multiplication():
|
||||
e = mapnik.Box2d(100, 100, 200, 200)
|
||||
e *= 2
|
||||
|
||||
assert_true(e.contains(50, 50))
|
||||
assert_true(e.contains(50, 250))
|
||||
assert_true(e.contains(250, 250))
|
||||
assert_true(e.contains(250, 50))
|
||||
|
||||
assert_false(e.contains(49.9, 49.9))
|
||||
assert_false(e.contains(49.9, 250.1))
|
||||
assert_false(e.contains(250.1, 250.1))
|
||||
assert_false(e.contains(250.1, 49.9))
|
||||
|
||||
assert_true(e.contains(e.center()))
|
||||
|
||||
eq_(e.width(), 200)
|
||||
eq_(e.height(), 200)
|
||||
|
||||
eq_(e.minx, 50)
|
||||
eq_(e.miny, 50)
|
||||
|
||||
eq_(e.maxx, 250)
|
||||
eq_(e.maxy, 250)
|
||||
|
||||
c = e.center()
|
||||
|
||||
eq_(c.x, 150)
|
||||
eq_(c.y, 150)
|
||||
|
||||
# Box2d clipping
|
||||
def test_envelope_clipping():
|
||||
e1 = mapnik.Box2d(-180,-90,180,90)
|
||||
e2 = mapnik.Box2d(-120,40,-110,48)
|
||||
e1.clip(e2)
|
||||
eq_(e1,e2)
|
||||
|
||||
# madagascar in merc
|
||||
e1 = mapnik.Box2d(4772116.5490, -2744395.0631, 5765186.4203, -1609458.0673)
|
||||
e2 = mapnik.Box2d(5124338.3753, -2240522.1727, 5207501.8621, -2130452.8520)
|
||||
e1.clip(e2)
|
||||
eq_(e1,e2)
|
||||
|
||||
# nz in lon/lat
|
||||
e1 = mapnik.Box2d(163.8062, -47.1897, 179.3628, -33.9069)
|
||||
e2 = mapnik.Box2d(173.7378, -39.6395, 174.4849, -38.9252)
|
||||
e1.clip(e2)
|
||||
eq_(e1,e2)
|
||||
|
||||
if __name__ == "__main__":
|
||||
setup()
|
||||
[eval(run)() for run in dir() if 'test_' in run]
|
||||
|
|
|
@ -28,6 +28,7 @@ if 'ogr' in mapnik.DatasourceCache.instance().plugin_names():
|
|||
def test_shapefile_properties():
|
||||
# NOTE: encoding is latin1 but gdal >= 1.9 should now expose utf8 encoded features
|
||||
# See SHAPE_ENCODING for overriding: http://gdal.org/ogr/drv_shapefile.html
|
||||
# So: failure for the NOM_FR field is expected for older gdal
|
||||
ds = mapnik.Ogr(file='../../demo/data/boundaries.shp',layer_by_index=0)
|
||||
f = ds.features_at_point(ds.envelope().center()).features[0]
|
||||
eq_(ds.geometry_type(),mapnik.DataGeometryType.Polygon)
|
||||
|
|
|
@ -8,13 +8,6 @@ import sys
|
|||
from utilities import execution_path
|
||||
from nose.tools import *
|
||||
|
||||
try:
|
||||
from shapely.geometry import Point
|
||||
have_shapely = True
|
||||
except ImportError:
|
||||
print('Shapely is required for python data source test.')
|
||||
have_shapely = False
|
||||
|
||||
def setup():
|
||||
# All of the paths used are relative, if we run the tests
|
||||
# from another directory we need to chdir()
|
||||
|
@ -27,18 +20,14 @@ class PointDatasource(mapnik.PythonDatasource):
|
|||
)
|
||||
|
||||
def features(self, query):
|
||||
return mapnik.PythonDatasource.wkb_features(
|
||||
return mapnik.PythonDatasource.wkt_features(
|
||||
keys = ('label',),
|
||||
features = (
|
||||
( Point(5,6).wkb, { 'label': 'foo-bar'} ),
|
||||
( Point(60,50).wkb, { 'label': 'buzz-quux'} ),
|
||||
( 'POINT (5 6)', { 'label': 'foo-bar'} ),
|
||||
( 'POINT (60 50)', { 'label': 'buzz-quux'} ),
|
||||
)
|
||||
)
|
||||
|
||||
def box2d_to_shapely(box):
|
||||
import shapely.geometry
|
||||
return shapely.geometry.box(box.minx, box.miny, box.maxx, box.maxy)
|
||||
|
||||
class ConcentricCircles(object):
|
||||
def __init__(self, centre, bounds, step=1):
|
||||
self.centre = centre
|
||||
|
@ -53,20 +42,31 @@ class ConcentricCircles(object):
|
|||
bounds = self.container.bounds
|
||||
step = self.container.step
|
||||
|
||||
if centre.within(bounds):
|
||||
self.radius = step
|
||||
else:
|
||||
self.radius = math.ceil(centre.distance(bounds) / float(step)) * step
|
||||
self.radius = step
|
||||
|
||||
def next(self):
|
||||
circle = self.container.centre.buffer(self.radius)
|
||||
self.radius += self.container.step
|
||||
points = []
|
||||
for alpha in xrange(0, 361, 5):
|
||||
x = math.sin(math.radians(alpha)) * self.radius + self.container.centre[0]
|
||||
y = math.cos(math.radians(alpha)) * self.radius + self.container.centre[1]
|
||||
points.append('%s %s' % (x,y))
|
||||
circle = 'POLYGON ((' + ','.join(points) + '))'
|
||||
|
||||
# has the circle grown so large that the boundary is entirely within it?
|
||||
if circle.contains(self.container.bounds):
|
||||
tl = (self.container.bounds.maxx, self.container.bounds.maxy)
|
||||
tr = (self.container.bounds.maxx, self.container.bounds.maxy)
|
||||
bl = (self.container.bounds.minx, self.container.bounds.miny)
|
||||
br = (self.container.bounds.minx, self.container.bounds.miny)
|
||||
def within_circle(p):
|
||||
delta_x = p[0] - self.container.centre[0]
|
||||
delta_y = p[0] - self.container.centre[0]
|
||||
return delta_x*delta_x + delta_y*delta_y < self.radius*self.radius
|
||||
|
||||
if all(within_circle(p) for p in (tl,tr,bl,br)):
|
||||
raise StopIteration()
|
||||
|
||||
return ( circle.wkb, { } )
|
||||
self.radius += self.container.step
|
||||
return ( circle, { } )
|
||||
|
||||
def __iter__(self):
|
||||
return ConcentricCircles.Iterator(self)
|
||||
|
@ -87,16 +87,14 @@ class CirclesDatasource(mapnik.PythonDatasource):
|
|||
self.step = step
|
||||
|
||||
def features(self, query):
|
||||
# Get the query bounding-box as a shapely bounding box
|
||||
bounding_box = box2d_to_shapely(query.bbox)
|
||||
centre = Point(self.centre_x, self.centre_y)
|
||||
centre = (self.centre_x, self.centre_y)
|
||||
|
||||
return mapnik.PythonDatasource.wkb_features(
|
||||
return mapnik.PythonDatasource.wkt_features(
|
||||
keys = (),
|
||||
features = ConcentricCircles(centre, bounding_box, self.step)
|
||||
features = ConcentricCircles(centre, query.bbox, self.step)
|
||||
)
|
||||
|
||||
if 'python' in mapnik.DatasourceCache.instance().plugin_names() and have_shapely:
|
||||
if 'python' in mapnik.DatasourceCache.instance().plugin_names():
|
||||
# make sure we can load from ourself as a module
|
||||
sys.path.append(execution_path('.'))
|
||||
|
||||
|
@ -129,7 +127,7 @@ if 'python' in mapnik.DatasourceCache.instance().plugin_names() and have_shapely
|
|||
|
||||
def test_python_point_rendering():
|
||||
m = mapnik.Map(512,512)
|
||||
mapnik.load_map(m,'../data/good_maps/python_point_datasource.xml')
|
||||
mapnik.load_map(m,'../data/python_plugin/python_point_datasource.xml')
|
||||
m.zoom_all()
|
||||
im = mapnik.Image(512,512)
|
||||
mapnik.render(m,im)
|
||||
|
@ -142,7 +140,7 @@ if 'python' in mapnik.DatasourceCache.instance().plugin_names() and have_shapely
|
|||
|
||||
def test_python_circle_rendering():
|
||||
m = mapnik.Map(512,512)
|
||||
mapnik.load_map(m,'../data/good_maps/python_circle_datasource.xml')
|
||||
mapnik.load_map(m,'../data/python_plugin/python_circle_datasource.xml')
|
||||
m.zoom_all()
|
||||
im = mapnik.Image(512,512)
|
||||
mapnik.render(m,im)
|
||||
|
|
|
@ -9,79 +9,80 @@ def setup():
|
|||
# from another directory we need to chdir()
|
||||
os.chdir(execution_path('.'))
|
||||
|
||||
@raises(RuntimeError)
|
||||
def test_zoom_all_will_fail():
|
||||
m = mapnik.Map(512,512)
|
||||
mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml')
|
||||
m.zoom_all()
|
||||
|
||||
def test_zoom_all_will_work_with_max_extent():
|
||||
m = mapnik.Map(512,512)
|
||||
mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml')
|
||||
merc_bounds = mapnik.Box2d(-20037508.34,-20037508.34,20037508.34,20037508.34)
|
||||
m.maximum_extent = merc_bounds
|
||||
m.zoom_all()
|
||||
eq_(m.envelope(),merc_bounds)
|
||||
|
||||
m = mapnik.Map(512,512)
|
||||
mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml')
|
||||
merc_bounds = mapnik.Box2d(-20037508.34,-20037508.34,20037508.34,20037508.34)
|
||||
m.zoom_to_box(merc_bounds)
|
||||
eq_(m.envelope(),merc_bounds)
|
||||
if 'shape' in mapnik.DatasourceCache.instance().plugin_names():
|
||||
@raises(RuntimeError)
|
||||
def test_zoom_all_will_fail():
|
||||
m = mapnik.Map(512,512)
|
||||
mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml')
|
||||
m.zoom_all()
|
||||
|
||||
def test_zoom_all_will_work_with_max_extent():
|
||||
m = mapnik.Map(512,512)
|
||||
mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml')
|
||||
merc_bounds = mapnik.Box2d(-20037508.34,-20037508.34,20037508.34,20037508.34)
|
||||
m.maximum_extent = merc_bounds
|
||||
m.zoom_all()
|
||||
eq_(m.envelope(),merc_bounds)
|
||||
|
||||
def test_visual_zoom_all_rendering1():
|
||||
m = mapnik.Map(512,512)
|
||||
mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml')
|
||||
merc_bounds = mapnik.Box2d(-20037508.34,-20037508.34,20037508.34,20037508.34)
|
||||
m.maximum_extent = merc_bounds
|
||||
m.zoom_all()
|
||||
im = mapnik.Image(512,512)
|
||||
mapnik.render(m,im)
|
||||
actual = '/tmp/mapnik-wgs842merc-reprojection-render.png'
|
||||
expected = 'images/support/mapnik-wgs842merc-reprojection-render.png'
|
||||
im.save(actual)
|
||||
expected_im = mapnik.Image.open(expected)
|
||||
eq_(im.tostring(),expected_im.tostring(), 'failed comparing actual (%s) and expected (%s)' % (actual,'tests/python_tests/'+ expected))
|
||||
|
||||
def test_visual_zoom_all_rendering2():
|
||||
m = mapnik.Map(512,512)
|
||||
mapnik.load_map(m,'../data/good_maps/merc2wgs84_reprojection.xml')
|
||||
m.zoom_all()
|
||||
im = mapnik.Image(512,512)
|
||||
mapnik.render(m,im)
|
||||
actual = '/tmp/mapnik-merc2wgs84-reprojection-render.png'
|
||||
expected = 'images/support/mapnik-merc2wgs84-reprojection-render.png'
|
||||
im.save(actual)
|
||||
expected_im = mapnik.Image.open(expected)
|
||||
eq_(im.tostring(),expected_im.tostring(), 'failed comparing actual (%s) and expected (%s)' % (actual,'tests/python_tests/'+ expected))
|
||||
|
||||
# maximum-extent read from map.xml
|
||||
def test_visual_zoom_all_rendering3():
|
||||
m = mapnik.Map(512,512)
|
||||
mapnik.load_map(m,'../data/good_maps/bounds_clipping.xml')
|
||||
m.zoom_all()
|
||||
im = mapnik.Image(512,512)
|
||||
mapnik.render(m,im)
|
||||
actual = '/tmp/mapnik-merc2merc-reprojection-render1.png'
|
||||
expected = 'images/support/mapnik-merc2merc-reprojection-render1.png'
|
||||
im.save(actual)
|
||||
expected_im = mapnik.Image.open(expected)
|
||||
eq_(im.tostring(),expected_im.tostring(), 'failed comparing actual (%s) and expected (%s)' % (actual,'tests/python_tests/'+ expected))
|
||||
|
||||
# no maximum-extent
|
||||
def test_visual_zoom_all_rendering4():
|
||||
m = mapnik.Map(512,512)
|
||||
mapnik.load_map(m,'../data/good_maps/bounds_clipping.xml')
|
||||
m.maximum_extent = None
|
||||
m.zoom_all()
|
||||
im = mapnik.Image(512,512)
|
||||
mapnik.render(m,im)
|
||||
actual = '/tmp/mapnik-merc2merc-reprojection-render2.png'
|
||||
expected = 'images/support/mapnik-merc2merc-reprojection-render2.png'
|
||||
im.save(actual)
|
||||
expected_im = mapnik.Image.open(expected)
|
||||
eq_(im.tostring(),expected_im.tostring(), 'failed comparing actual (%s) and expected (%s)' % (actual,'tests/python_tests/'+ expected))
|
||||
m = mapnik.Map(512,512)
|
||||
mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml')
|
||||
merc_bounds = mapnik.Box2d(-20037508.34,-20037508.34,20037508.34,20037508.34)
|
||||
m.zoom_to_box(merc_bounds)
|
||||
eq_(m.envelope(),merc_bounds)
|
||||
|
||||
|
||||
def test_visual_zoom_all_rendering1():
|
||||
m = mapnik.Map(512,512)
|
||||
mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml')
|
||||
merc_bounds = mapnik.Box2d(-20037508.34,-20037508.34,20037508.34,20037508.34)
|
||||
m.maximum_extent = merc_bounds
|
||||
m.zoom_all()
|
||||
im = mapnik.Image(512,512)
|
||||
mapnik.render(m,im)
|
||||
actual = '/tmp/mapnik-wgs842merc-reprojection-render.png'
|
||||
expected = 'images/support/mapnik-wgs842merc-reprojection-render.png'
|
||||
im.save(actual)
|
||||
expected_im = mapnik.Image.open(expected)
|
||||
eq_(im.tostring(),expected_im.tostring(), 'failed comparing actual (%s) and expected (%s)' % (actual,'tests/python_tests/'+ expected))
|
||||
|
||||
def test_visual_zoom_all_rendering2():
|
||||
m = mapnik.Map(512,512)
|
||||
mapnik.load_map(m,'../data/good_maps/merc2wgs84_reprojection.xml')
|
||||
m.zoom_all()
|
||||
im = mapnik.Image(512,512)
|
||||
mapnik.render(m,im)
|
||||
actual = '/tmp/mapnik-merc2wgs84-reprojection-render.png'
|
||||
expected = 'images/support/mapnik-merc2wgs84-reprojection-render.png'
|
||||
im.save(actual)
|
||||
expected_im = mapnik.Image.open(expected)
|
||||
eq_(im.tostring(),expected_im.tostring(), 'failed comparing actual (%s) and expected (%s)' % (actual,'tests/python_tests/'+ expected))
|
||||
|
||||
# maximum-extent read from map.xml
|
||||
def test_visual_zoom_all_rendering3():
|
||||
m = mapnik.Map(512,512)
|
||||
mapnik.load_map(m,'../data/good_maps/bounds_clipping.xml')
|
||||
m.zoom_all()
|
||||
im = mapnik.Image(512,512)
|
||||
mapnik.render(m,im)
|
||||
actual = '/tmp/mapnik-merc2merc-reprojection-render1.png'
|
||||
expected = 'images/support/mapnik-merc2merc-reprojection-render1.png'
|
||||
im.save(actual)
|
||||
expected_im = mapnik.Image.open(expected)
|
||||
eq_(im.tostring(),expected_im.tostring(), 'failed comparing actual (%s) and expected (%s)' % (actual,'tests/python_tests/'+ expected))
|
||||
|
||||
# no maximum-extent
|
||||
def test_visual_zoom_all_rendering4():
|
||||
m = mapnik.Map(512,512)
|
||||
mapnik.load_map(m,'../data/good_maps/bounds_clipping.xml')
|
||||
m.maximum_extent = None
|
||||
m.zoom_all()
|
||||
im = mapnik.Image(512,512)
|
||||
mapnik.render(m,im)
|
||||
actual = '/tmp/mapnik-merc2merc-reprojection-render2.png'
|
||||
expected = 'images/support/mapnik-merc2merc-reprojection-render2.png'
|
||||
im.save(actual)
|
||||
expected_im = mapnik.Image.open(expected)
|
||||
eq_(im.tostring(),expected_im.tostring(), 'failed comparing actual (%s) and expected (%s)' % (actual,'tests/python_tests/'+ expected))
|
||||
|
||||
if __name__ == "__main__":
|
||||
setup()
|
||||
|
|
17
tests/python_tests/style_test.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
from nose.tools import *
|
||||
import mapnik
|
||||
|
||||
def test_style_init():
|
||||
s = mapnik.Style()
|
||||
eq_(s.filter_mode,mapnik.filter_mode.ALL)
|
||||
eq_(len(s.rules),0)
|
||||
eq_(s.opacity,1)
|
||||
eq_(s.comp_op,None)
|
||||
eq_(s.image_filters,"")
|
||||
|
||||
if __name__ == "__main__":
|
||||
[eval(run)() for run in dir() if 'test_' in run]
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
@ -5,8 +5,8 @@
|
|||
<Layer name="layer" srs="+proj=latlong +datum=WGS84">
|
||||
<StyleName>My Style</StyleName>
|
||||
<Datasource>
|
||||
<Parameter name="type">shape</Parameter>
|
||||
<Parameter name="file">../data/points.shp</Parameter>
|
||||
<Parameter name="type">osm</Parameter>
|
||||
<Parameter name="file">../data/points.osm</Parameter>
|
||||
</Datasource>
|
||||
</Layer>
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<Layer name="layer" srs="+proj=latlong +datum=WGS84">
|
||||
<StyleName>My Style</StyleName>
|
||||
<Datasource>
|
||||
<Parameter name="type">shape</Parameter>
|
||||
<Parameter name="file">../data/points.shp</Parameter>
|
||||
<Parameter name="type">osms</Parameter>
|
||||
<Parameter name="file">../data/points.osm</Parameter>
|
||||
</Datasource>
|
||||
</Layer>
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<Layer name="layer" srs="+proj=latlong +datum=WGS84">
|
||||
<StyleName>My Style</StyleName>
|
||||
<Datasource>
|
||||
<Parameter name="type">shape</Parameter>
|
||||
<Parameter name="file">../data/points.shp</Parameter>
|
||||
<Parameter name="type">osm</Parameter>
|
||||
<Parameter name="file">../data/points.osm</Parameter>
|
||||
</Datasource>
|
||||
</Layer>
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<Layer name="layer" srs="+proj=latlong +datum=WGS84">
|
||||
<StyleName>My Style</StyleName>
|
||||
<Datasource>
|
||||
<Parameter name="type">shape</Parameter>
|
||||
<Parameter name="file">../data/points.shp</Parameter>
|
||||
<Parameter name="type">osm</Parameter>
|
||||
<Parameter name="file">../data/points.osm</Parameter>
|
||||
</Datasource>
|
||||
</Layer>
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<Layer name="layer" srs="+proj=latlong +datum=WGS84">
|
||||
<StyleName>My Style</StyleName>
|
||||
<Datasource>
|
||||
<Parameter name="type">shape</Parameter>
|
||||
<Parameter name="file">../data/points.shp</Parameter>
|
||||
<Parameter name="type">osm</Parameter>
|
||||
<Parameter name="file">../data/points.osm</Parameter>
|
||||
</Datasource>
|
||||
</Layer>
|
||||
|
||||
|
|