simple_mapnik 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e8d3175e317ae4772b41f5d8ac4f9a0781d4432a
4
+ data.tar.gz: 46eaac32355da4efb010299a5a99bd799a27f468
5
+ SHA512:
6
+ metadata.gz: 03a3e4d5bdbe20771aeddb586cdeb7604b89071be85d89a6266bd02be35887d0b6c9d76405235cb57d98ea664cf02df5e09c30e3141e981db0f504e42081e662
7
+ data.tar.gz: c1a9cedff9a7c3f7af5073246aac47ce058646e6b3b0730098ecc7385b99cf283437d653930b9a243c5810dc2d4add3e9a6acfd1900b1d5810840121decd8d8e
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ Gemfile.lock
2
+ /pkg
3
+ *.gem
4
+ *.dylib
5
+ *.so
6
+ .bundle/
7
+ .byebug_history
8
+ coverage
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,16 @@
1
+ Metrics/LineLength:
2
+ Max: 100
3
+
4
+ Style/ClassAndModuleCamelCase:
5
+ Exclude:
6
+ - 'lib/simple_mapnik.rb'
7
+
8
+ Style/Documentation:
9
+ Enabled: false
10
+
11
+ Style/RaiseArgs:
12
+ EnforcedStyle: compact
13
+
14
+ Lint/HandleExceptions:
15
+ Exclude:
16
+ - 'Rakefile'
data/.travis.yml ADDED
@@ -0,0 +1,24 @@
1
+ language: ruby
2
+ sudo: true
3
+ matrix:
4
+ include:
5
+ - os: linux
6
+ compiler: clang
7
+ env: MAPNIK_VERSION="2.3"
8
+ - os: linux
9
+ compiler: gcc
10
+ env: MAPNIK_VERSION="2.3"
11
+
12
+ before_install:
13
+ - sudo apt-add-repository --yes ppa:mapnik/nightly-${MAPNIK_VERSION}
14
+ - sudo apt-get update -y
15
+
16
+ install:
17
+ - sudo apt-get -y install wget build-essential make libmapnik=${MAPNIK_VERSION}* mapnik-utils=${MAPNIK_VERSION}* libmapnik-dev=${MAPNIK_VERSION}* mapnik-input-plugin*=${MAPNIK_VERSION}*
18
+
19
+ before_script:
20
+ - gem install bundler -v 1.12.3
21
+ - bundle install
22
+
23
+ script:
24
+ - rake spec
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Eliot Jordan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Scooter Wadsworth
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,58 @@
1
+ SimpleMapnik
2
+ ==========
3
+ [![Build Status](https://travis-ci.org/geoconcerns/simple_mapnik.svg)](https://travis-ci.org/geoconcerns/simple_mapnik)
4
+ [![Coverage Status](https://coveralls.io/repos/github/geoconcerns/simple_mapnik/badge.svg?branch=master)](https://coveralls.io/github/geoconcerns/simple_mapnik?branch=master)
5
+
6
+ Simple ruby access to the Mapnik library using [ruby-ffi](https://github.com/ffi/ffi) and [mapnik-c-api](https://github.com/springmeyer/mapnik-c-api). Adapted from [ffi-mapnik](https://github.com/scooterw/ffi-mapnik).
7
+
8
+ ## Prerequisites
9
+
10
+ SimpleMapnik requires that Mapnik 3.x or 2.x be installed at `/usr/local/lib/libmapnik.*`. In addition, a C++ compiler and build environment is needed for the c api extension.
11
+
12
+ On Mac OS X:
13
+
14
+ - https://github.com/mapnik/mapnik/wiki/MacInstallation or ```brew install mapnik```
15
+ - Build environment: [Xcode](https://developer.apple.com/xcode/)
16
+
17
+ On Linux:
18
+ - https://github.com/mapnik/mapnik/wiki/LinuxInstallation
19
+ - Build environment: [gcc](https://help.ubuntu.com/community/InstallingCompilers) or clang
20
+
21
+ ## Installation
22
+
23
+ Install from the latest tagged release:
24
+ ```
25
+ $ gem install simple_mapnik
26
+ ```
27
+
28
+ Or, add it to the Gemfile of an existing project:
29
+ ```
30
+ gem 'simple_mapnik'
31
+ ```
32
+
33
+ Then run:
34
+ ```
35
+ $ bundle install
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ Open an IRB session, or run `bin/mapnik_console`:
41
+
42
+ ```ruby
43
+ require './lib/simple_mapnik' # not necessary if using bin/mapnik_console
44
+
45
+ SimpleMapnik.register_datasources '/usr/local/lib/mapnik/input'
46
+
47
+ map = SimpleMapnik::Map.new 256, 256
48
+ map.load 'spec/fixtures/sample/stylesheet.xml'
49
+ map.zoom_all
50
+ map.to_file '~/Desktop/sample_output.png'
51
+ ```
52
+
53
+ ## Testing
54
+
55
+ ```
56
+ $ bundle install
57
+ $ rake spec
58
+ ```
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+ begin
3
+ require 'bundler/setup'
4
+ require 'bundler/gem_tasks'
5
+ rescue
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ begin
10
+ require 'rspec/core/rake_task'
11
+ require 'rubocop/rake_task'
12
+
13
+ RuboCop::RakeTask.new(:rubocop) do |task|
14
+ task.requires << 'rubocop-rspec'
15
+ task.fail_on_error = true
16
+ end
17
+ task spec: :rubocop do
18
+ RSpec::Core::RakeTask.new(:spec)
19
+ end
20
+ rescue LoadError
21
+ end
22
+
23
+ require './lib/simple_mapnik/api.rb'
24
+
25
+ task :install do
26
+ SimpleMapnik::Api.new.install
27
+ end
28
+
29
+ task default: :install
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'simple_mapnik'))
4
+ require 'irb'
5
+
6
+ IRB.start
data/coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ service_name: travis-ci
@@ -0,0 +1,75 @@
1
+ require 'open-uri'
2
+ require 'zip'
3
+
4
+ module SimpleMapnik
5
+ class Api
6
+ attr_accessor :output_dir
7
+ attr_writer :lib, :url, :src_directory_name
8
+
9
+ def initialize(output_dir = './')
10
+ @output_dir = output_dir
11
+ end
12
+
13
+ def check_and_install
14
+ lib_exist = File.exist? File.expand_path(File.join(output_dir, lib))
15
+ install unless lib_exist
16
+ end
17
+
18
+ def install
19
+ download
20
+ unzip
21
+ build
22
+ clean
23
+ end
24
+
25
+ def lib
26
+ @lib ||= "libmapnik_c.#{::FFI::Platform::LIBSUFFIX}"
27
+ end
28
+
29
+ def url
30
+ @url ||= 'https://github.com/geoconcerns/mapnik-c-api/archive/master.zip'
31
+ end
32
+
33
+ def src_directory_name
34
+ @src_directory_name ||= 'mapnik-c-api-master'
35
+ end
36
+
37
+ protected
38
+
39
+ def zip_path
40
+ File.expand_path(File.join(output_dir, 'mapnik_api.zip'))
41
+ end
42
+
43
+ def source_directory
44
+ File.expand_path(File.join(output_dir, src_directory_name))
45
+ end
46
+
47
+ def download
48
+ open(url) do |io|
49
+ IO.copy_stream(io, zip_path)
50
+ end
51
+ end
52
+
53
+ def unzip
54
+ Zip::File.open(zip_path) do |zip_file|
55
+ zip_file.each do |f|
56
+ f_path = File.join(output_dir, f.name)
57
+ FileUtils.mkdir_p(File.dirname(f_path))
58
+ zip_file.extract(f, f_path) unless File.exist?(f_path)
59
+ end
60
+ end
61
+ end
62
+
63
+ def build
64
+ path = source_directory
65
+ system("make -C #{path} && mv #{path}/$(ls #{path}/ | grep -E '(.dylib|.so)') #{output_dir}.")
66
+ end
67
+
68
+ def clean
69
+ [zip_path, source_directory].each do |item|
70
+ FileUtils.remove_dir(item) if Dir.exist?(item)
71
+ File.delete(item) if File.exist?(item)
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,23 @@
1
+ module SimpleMapnik
2
+ class Bounds
3
+ include SimpleMapnik::FFI
4
+
5
+ attr_accessor :x_min, :y_min, :x_max, :y_max, :ptr
6
+
7
+ def initialize(x_min, y_min, x_max, y_max)
8
+ @x_min = x_min
9
+ @y_min = y_min
10
+ @x_max = x_max
11
+ @y_max = y_max
12
+ ptr = mapnik_bbox x_min, y_min, x_max, y_max
13
+ @ptr = ::FFI::AutoPointer.new ptr, self.class.method(:release)
14
+ @ptr.autorelease = false
15
+ end
16
+
17
+ def self.release; end
18
+
19
+ def free
20
+ mapnik_bbox_free @ptr
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ module SimpleMapnik
2
+ class Coordinate
3
+ include SimpleMapnik::FFI
4
+
5
+ attr_accessor :x, :y, :ptr
6
+
7
+ def initialize(x, y)
8
+ @x = x
9
+ @y = y
10
+ coord_struct = MAPNIK_COORD_T.new
11
+ coord_struct[:x] = x
12
+ coord_struct[:y] = y
13
+ @ptr = coord_struct.to_ptr
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,47 @@
1
+ module SimpleMapnik
2
+ class Map
3
+ include SimpleMapnik::FFI
4
+
5
+ attr_accessor :width, :height, :ptr
6
+
7
+ def initialize(width, height)
8
+ @width = width
9
+ @height = height
10
+ ptr = mapnik_map width, height
11
+ @ptr = ::FFI::AutoPointer.new ptr, self.class.method(:release)
12
+ @ptr.autorelease = false
13
+ end
14
+
15
+ def self.release; end
16
+
17
+ def free
18
+ mapnik_map_free @ptr
19
+ end
20
+
21
+ def load(style)
22
+ style = File.expand_path style
23
+ mapnik_map_load @ptr, style
24
+ end
25
+
26
+ def zoom_all
27
+ mapnik_map_zoom_all @ptr
28
+ end
29
+
30
+ def zoom_to(bounds)
31
+ mapnik_map_zoom_to_box @ptr, bounds.ptr
32
+ end
33
+
34
+ def to_image
35
+ mapnik_map_render_to_image @ptr
36
+ end
37
+
38
+ def to_png
39
+ mapnik_image_to_png_blob to_image
40
+ end
41
+
42
+ def to_file(file)
43
+ file = File.expand_path file
44
+ mapnik_map_render_to_file @ptr, file
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module SimpleMapnik
2
+ VERSION = '0.0.1'.freeze
3
+ end
@@ -0,0 +1,79 @@
1
+ require 'ffi'
2
+
3
+ module SimpleMapnik
4
+ MAPNIK_BASE = File.join(File.dirname(__FILE__), 'simple_mapnik')
5
+
6
+ autoload :Map, File.join(MAPNIK_BASE, 'map')
7
+ autoload :Coordinate, File.join(MAPNIK_BASE, 'coordinate')
8
+ autoload :Bounds, File.join(MAPNIK_BASE, 'bounds')
9
+ autoload :Api, File.join(MAPNIK_BASE, 'api')
10
+
11
+ module FFI
12
+ def self.find_lib(lib)
13
+ File.expand_path File.join('.', "#{lib}.#{::FFI::Platform::LIBSUFFIX}")
14
+ end
15
+
16
+ def self.mapnik_c_api_path
17
+ find_lib 'libmapnik_c'
18
+ end
19
+
20
+ class MAPNIK_COORD_T < ::FFI::Struct
21
+ layout :x, :double,
22
+ :y, :double
23
+ end
24
+
25
+ MAPNIK_FUNCTIONS = {
26
+ mapnik_register_datasources: [[:string, :pointer], :int],
27
+ mapnik_register_fonts: [[:string, :pointer], :int],
28
+ mapnik_map: [[:uint, :uint], :pointer],
29
+ mapnik_map_free: [[:pointer], :void],
30
+ # mapnik_map_reset_last_error: [[:pointer], :void],
31
+ mapnik_map_get_srs: [[:pointer], :string],
32
+ mapnik_map_set_srs: [[:pointer, :string], :int],
33
+ mapnik_map_load: [[:pointer, :string], :int],
34
+ mapnik_map_zoom_all: [[:pointer], :int],
35
+ mapnik_map_render_to_file: [[:pointer, :string], :int],
36
+ mapnik_map_resize: [[:pointer, :uint, :uint], :void],
37
+ mapnik_map_set_buffer_size: [[:pointer, :int], :void],
38
+ mapnik_map_last_error: [[:pointer], :string],
39
+ mapnik_map_projection: [[:pointer], :pointer], # needs struct
40
+ mapnik_projection_free: [[:pointer], :void],
41
+ mapnik_projection_forward: [[:pointer, MAPNIK_COORD_T.by_value], :pointer],
42
+ mapnik_bbox: [[:double, :double, :double, :double], :pointer],
43
+ mapnik_bbox_free: [[:pointer], :void],
44
+ mapnik_map_zoom_to_box: [[:pointer, :pointer], :void],
45
+ mapnik_image_free: [[:pointer], :void],
46
+ mapnik_map_render_to_image: [[:pointer], :pointer],
47
+ mapnik_image_blob_free: [[:pointer], :void],
48
+ mapnik_image_to_png_blob: [[:pointer], :pointer]
49
+ }.freeze
50
+
51
+ extend ::FFI::Library
52
+
53
+ def self.attach_functions
54
+ ffi_lib mapnik_c_api_path
55
+
56
+ MAPNIK_FUNCTIONS.each do |func, params|
57
+ attach_function func, params.first, params.last
58
+ end
59
+ rescue LoadError, NoMethodError
60
+ raise LoadError.new('Could not load Mapnik library and / or C API')
61
+ end
62
+
63
+ attach_functions
64
+ end
65
+
66
+ class << self
67
+ def error_ptr
68
+ ::FFI::MemoryPointer.new :char, 65
69
+ end
70
+
71
+ def register_datasources(sources)
72
+ SimpleMapnik::FFI.mapnik_register_datasources sources, nil
73
+ end
74
+
75
+ def register_fonts(fonts)
76
+ SimpleMapnik::FFI.mapnik_register_fonts fonts, nil
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'simple_mapnik/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'simple_mapnik'
8
+ spec.version = SimpleMapnik::VERSION
9
+ spec.authors = ['Eliot Jordan']
10
+ spec.email = ['eliotj@princeton.edu']
11
+ spec.description = 'Simple FFI wrapper for Mapnik'
12
+ spec.summary = 'Simple access to Mapnik library from Ruby'
13
+ spec.homepage = 'https://github.com/geoconcerns/simple_mapnik'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+ spec.extensions = ['Rakefile']
21
+
22
+ spec.add_dependency 'ffi', '~> 1.9.0'
23
+ spec.add_dependency 'rubyzip', '~> 1.2.0'
24
+
25
+ spec.add_development_dependency 'rake'
26
+ spec.add_development_dependency 'rspec'
27
+ spec.add_development_dependency 'rubocop', '~> 0.39'
28
+ spec.add_development_dependency 'rubocop-rspec', '~> 1.4.1'
29
+ spec.add_development_dependency 'simplecov'
30
+ spec.add_development_dependency 'coveralls'
31
+ spec.add_development_dependency 'bundler', '~> 1.12'
32
+ end
@@ -0,0 +1,21 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <Map 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 +wktext +no_defs +over" background-color="steelblue">
3
+
4
+ <Style name="style">
5
+ <Rule>
6
+ <PolygonSymbolizer fill="white" />
7
+ <LineSymbolizer stroke="grey" stroke-width=".2" />
8
+ <TextSymbolizer face-name="Unifont" placement="point" fill="#444444" halo-fill="rgba(255, 255, 255, 0.75)" halo-radius="2" line-spacing="2" wrap-width="30" ><![CDATA[[doesnotexist]]]></TextSymbolizer>
9
+ </Rule>
10
+ </Style>
11
+
12
+ <Layer name="world" 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 +wktext +no_defs +over">
13
+ <StyleName>style</StyleName>
14
+ <Datasource>
15
+ <Parameter name="file">world_merc.shp</Parameter>
16
+ <Parameter name="encoding">iso-8859-1</Parameter>
17
+ <Parameter name="type">shape</Parameter>
18
+ </Datasource>
19
+ </Layer>
20
+
21
+ </Map>
@@ -0,0 +1,19 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <Map 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 +wktext +no_defs +over" background-color="steelblue">
3
+
4
+ <Style name="style">
5
+ <Rule>
6
+ <PolygonSymbolizer fill="white" />
7
+ <LineSymbolizer stroke="grey" stroke-width=".2" />
8
+ </Rule>
9
+ </Style>
10
+
11
+ <Layer name="world" 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 +wktext +no_defs +over">
12
+ <StyleName>style</StyleName>
13
+ <Datasource>
14
+ <Parameter name="file">world_merc.shp</Parameter>
15
+ <Parameter name="encoding">iso-8859-1</Parameter>
16
+ <Parameter name="type">shape</Parameter>
17
+ </Datasource>
18
+ </Layer>
19
+ </Map>
Binary file