wicket 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +11 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +58 -0
- data/Rakefile +6 -0
- data/lib/wicket.rb +12 -0
- data/lib/wicket/command.rb +39 -0
- data/lib/wicket/commands/h.rb +29 -0
- data/lib/wicket/commands/l.rb +30 -0
- data/lib/wicket/commands/m.rb +30 -0
- data/lib/wicket/commands/v.rb +29 -0
- data/lib/wicket/commands/z.rb +22 -0
- data/lib/wicket/subpath.rb +42 -0
- data/lib/wicket/svg_path.rb +46 -0
- data/lib/wicket/version.rb +3 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/svg_path_spec.rb +127 -0
- data/wicket.gemspec +24 -0
- metadata +109 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4796455f861ca6470c2d70dc0df6ac3cbed39f56
|
4
|
+
data.tar.gz: d7c4009ad2d103dd4df905fd1e0272ed223c2ebb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fb8a84ca13e6a0b698f5b32ba78b059248fcdff3ef4a710fcb0efa10a50de352c7054104c1b0f8781ad95379d9e2417be3dd5e1bfa20678572a0f20caaa447a1
|
7
|
+
data.tar.gz: 95350c86b4d5525324a7b33c8d56c608246b905b89e106c688a3499c969b39ef64f228b77522fab1516719f27bd77b831e3222276d77bd4e10bce2e4629a7f88
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Ryan Urabe
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# Wicket
|
2
|
+
|
3
|
+
[](https://travis-ci.org/rurabe/wicket)[](https://codeclimate.com/github/rurabe/wicket)
|
4
|
+
|
5
|
+
Wicket is a pure Ruby library for the conversion of [SVG](http://en.wikipedia.org/wiki/Scalable_Vector_Graphics) path data into [Well Known Text (WKT)](http://en.wikipedia.org/wiki/Well-known_text). This is useful for cases when you have SVG input data, but want to store it in a spatial database that accepts WKT such as PostGIS.
|
6
|
+
|
7
|
+
Notable features include:
|
8
|
+
- Translating line paths into WKT Polygons or Multipolygons
|
9
|
+
- Accepting absolute or relative path commands
|
10
|
+
- Inversing Y axis measurements (SVG y coordinates decrease as you go up)
|
11
|
+
|
12
|
+
Future possible features could include:
|
13
|
+
- Translating curved paths
|
14
|
+
- Translating non closed paths into Linestrings and Multilines
|
15
|
+
- Specifying paths for polygons which are exlcusions from the area (donut holes)
|
16
|
+
- Translating WKT to SVG (although PostGIS already does this)
|
17
|
+
|
18
|
+
If you want to see these or any other features, feel free to make an issue or pull request.
|
19
|
+
|
20
|
+
Wicket is similar in concept to [SVG-to-WKT.js](https://github.com/davidmcclure/svg-to-wkt), although that project operates within the browser and focuses much more on the DOM elements. It also owes credit to [Savage](https://github.com/awebneck/savage) as a reference for the SVG parser. If you need to edit SVG paths, I would recommend checking it out.
|
21
|
+
|
22
|
+
## Installation
|
23
|
+
|
24
|
+
Add this line to your application's Gemfile:
|
25
|
+
|
26
|
+
gem 'wicket'
|
27
|
+
|
28
|
+
And then execute:
|
29
|
+
|
30
|
+
$ bundle
|
31
|
+
|
32
|
+
Or install it yourself as:
|
33
|
+
|
34
|
+
$ gem install wicket
|
35
|
+
|
36
|
+
## Usage
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
path = Wicket::SVGPath.new("M10 10H20l10 10H10z")
|
40
|
+
path.to_polygon
|
41
|
+
# => "POLYGON((10.0 -10.0,20.0 -10.0,30.0 -20.0,10.0 -20.0,10.0 -10.0))"
|
42
|
+
path.to_multipolygon
|
43
|
+
# => "MULTIPOLYGON(((10.0 -10.0,30.0 -10.0,40.0 -10.0,50.0 -20.0,40.0 -20.0,10.0 -10.0)))"
|
44
|
+
```
|
45
|
+
|
46
|
+
## Gotchas
|
47
|
+
|
48
|
+
- Wicket assumes that a move command (M or m) is part of the polygon edge. It just so happened that a lot of the data I was working with when creating this project was formatted that way. Eventually I believe this should not be the case and should be able to be toggled on as an option.
|
49
|
+
- Polygons are assumed to have no holes, thus everything inside the path is part of the polygon.
|
50
|
+
- Each polygon is represented by a subpath. A subpath continues until it is closed by a Z command or by moving or lineing to the starting coordinates. Multiple subpaths are represented as individual elements in `#to_multipolygon`, whereas only the first subpath is represented in `#to_polygon`. Make sure your data does not include multiple subpaths if using the `#to_polygon` method.
|
51
|
+
|
52
|
+
## Contributing
|
53
|
+
|
54
|
+
1. Fork it ( http://github.com/rurabe/wicket/fork )
|
55
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
56
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
57
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
58
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/wicket.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "wicket/version"
|
2
|
+
require "wicket/svg_path"
|
3
|
+
require "wicket/subpath"
|
4
|
+
require "wicket/command"
|
5
|
+
require "wicket/commands/m"
|
6
|
+
require "wicket/commands/l"
|
7
|
+
require "wicket/commands/z"
|
8
|
+
require "wicket/commands/h"
|
9
|
+
require "wicket/commands/v"
|
10
|
+
|
11
|
+
module Wicket
|
12
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Wicket
|
2
|
+
class Command
|
3
|
+
attr_reader :cursor_start
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def from_code(code,arg_string,subpath)
|
7
|
+
command_class = Commands.const_get(code.upcase) # get the class which handles this code
|
8
|
+
absolute = (code.upcase == code) # is it uppercase?
|
9
|
+
cursor_start = subpath.cursor_end # get the current position of the cursor
|
10
|
+
args = arg_string.to_s.scan(/(?:\-\s*)?\d+(?:\.\d+)?/).flatten # parse out the numerical arguments
|
11
|
+
if !args.empty?
|
12
|
+
args.each_slice(command_class.arg_count).map do |slice| # slice them according to the number the code takes
|
13
|
+
slice.map!{|arg| arg.gsub(/\s*/,'').to_f } # remove whitespace and turn into a float
|
14
|
+
command_class.new(absolute,cursor_start,*slice)
|
15
|
+
end
|
16
|
+
else
|
17
|
+
[command_class.new(absolute,cursor_start)]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def subpath=(subpath)
|
23
|
+
@subpath = subpath
|
24
|
+
end
|
25
|
+
|
26
|
+
def inspect
|
27
|
+
"#<#{self.class.to_s} #{coordinates.map{|k,v|[k,v].join("=")}.join(",")}#{" abs" if @absolute}>"
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_wkt
|
31
|
+
inverse_values.join(" ")
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def inverse_values
|
36
|
+
[cursor_end[:x], cursor_end[:y] * -1]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Wicket
|
2
|
+
module Commands
|
3
|
+
class H < Command
|
4
|
+
|
5
|
+
def self.arg_count
|
6
|
+
1
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(absolute,cursor_start,x)
|
10
|
+
@absolute = absolute
|
11
|
+
@cursor_start = cursor_start
|
12
|
+
@x = x
|
13
|
+
end
|
14
|
+
|
15
|
+
def coordinates
|
16
|
+
{:x => @x, :y => cursor_start[:y]}
|
17
|
+
end
|
18
|
+
|
19
|
+
def cursor_end
|
20
|
+
if @absolute
|
21
|
+
coordinates
|
22
|
+
else
|
23
|
+
{:x => (@cursor_start[:x] + @x), :y => @cursor_start[:y]}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Wicket
|
2
|
+
module Commands
|
3
|
+
class L < Command
|
4
|
+
|
5
|
+
def self.arg_count
|
6
|
+
2
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(absolute,cursor_start,x,y)
|
10
|
+
@absolute = absolute
|
11
|
+
@x = x
|
12
|
+
@y = y
|
13
|
+
@cursor_start = cursor_start
|
14
|
+
end
|
15
|
+
|
16
|
+
def coordinates
|
17
|
+
{:x => @x, :y => @y}
|
18
|
+
end
|
19
|
+
|
20
|
+
def cursor_end
|
21
|
+
if @absolute
|
22
|
+
coordinates
|
23
|
+
else
|
24
|
+
{:x => (@cursor_start[:x] + @x), :y => (@cursor_start[:y] + @y)}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Wicket
|
2
|
+
module Commands
|
3
|
+
class M < Command
|
4
|
+
|
5
|
+
def self.arg_count
|
6
|
+
2
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(absolute,cursor_start,x,y)
|
10
|
+
@absolute = absolute
|
11
|
+
@x = x
|
12
|
+
@y = y
|
13
|
+
@cursor_start = cursor_start
|
14
|
+
end
|
15
|
+
|
16
|
+
def coordinates
|
17
|
+
{:x => @x, :y => @y}
|
18
|
+
end
|
19
|
+
|
20
|
+
def cursor_end
|
21
|
+
if @absolute
|
22
|
+
coordinates
|
23
|
+
else
|
24
|
+
{:x => (@cursor_start[:x] + @x), :y => (@cursor_start[:y] + @y)}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Wicket
|
2
|
+
module Commands
|
3
|
+
class V < Command
|
4
|
+
|
5
|
+
def self.arg_count
|
6
|
+
1
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(absolute,cursor_start,y)
|
10
|
+
@absolute = absolute
|
11
|
+
@cursor_start = cursor_start
|
12
|
+
@y = y
|
13
|
+
end
|
14
|
+
|
15
|
+
def coordinates
|
16
|
+
{:x => cursor_start[:x], :y => @y}
|
17
|
+
end
|
18
|
+
|
19
|
+
def cursor_end
|
20
|
+
if @absolute
|
21
|
+
coordinates
|
22
|
+
else
|
23
|
+
{:x => @cursor_start[:x], :y => (@cursor_start[:y] + @y)}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Wicket
|
2
|
+
module Commands
|
3
|
+
class Z < Command
|
4
|
+
|
5
|
+
def self.arg_count
|
6
|
+
1
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(absolute,cursor_start)
|
10
|
+
@cursor_start = cursor_start
|
11
|
+
end
|
12
|
+
|
13
|
+
def coordinates
|
14
|
+
{}
|
15
|
+
end
|
16
|
+
|
17
|
+
def cursor_end
|
18
|
+
@subpath.first_command.cursor_end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Wicket
|
2
|
+
class Subpath
|
3
|
+
attr_reader :commands
|
4
|
+
def initialize
|
5
|
+
@commands = []
|
6
|
+
end
|
7
|
+
|
8
|
+
def add_command(*new_commands)
|
9
|
+
new_commands.each do |c|
|
10
|
+
c.subpath = self
|
11
|
+
@commands << c
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def cursor_end
|
16
|
+
return {:x => 0, :y => 0} unless last_command
|
17
|
+
last_command.cursor_end
|
18
|
+
end
|
19
|
+
|
20
|
+
def closed?
|
21
|
+
return false if @commands.empty?
|
22
|
+
if @commands.length > 1
|
23
|
+
first_command.cursor_end == last_command.cursor_end
|
24
|
+
else
|
25
|
+
first_command.cursor_start == first_command.cursor_end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_polygon
|
30
|
+
vertices = commands.map(&:to_wkt).join(",")
|
31
|
+
"((#{vertices}))"
|
32
|
+
end
|
33
|
+
|
34
|
+
def last_command
|
35
|
+
@commands.last
|
36
|
+
end
|
37
|
+
|
38
|
+
def first_command
|
39
|
+
@commands.first
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Wicket
|
2
|
+
class SVGPath
|
3
|
+
attr_reader :text
|
4
|
+
def initialize(text)
|
5
|
+
@text = text
|
6
|
+
@subpaths = []
|
7
|
+
parse
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_polygon
|
11
|
+
poly = @subpaths.first.to_polygon
|
12
|
+
"POLYGON#{poly}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_multipolygon
|
16
|
+
polys = @subpaths.map(&:to_polygon).join(",")
|
17
|
+
"MULTIPOLYGON(#{polys})"
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def parse
|
23
|
+
commands = @text.scan(/(?:([MmLlHhVvQqCcTtSsAaZz])([\d\.\,\-\s]+)*)/)
|
24
|
+
commands.each_with_index.inject(new_subpath) do |subpath,((code,arg_string),index)|
|
25
|
+
# pass the code and arguments for parsing into individual commands and add them to the subpath
|
26
|
+
subpath.add_command( *Command.from_code(code,arg_string,subpath) )
|
27
|
+
# if the path closes, provision a new subpath for future commands unless done
|
28
|
+
(subpath.closed? && (index + 1) < commands.length) ? new_subpath : subpath
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def new_subpath
|
33
|
+
Subpath.new.tap {|s| @subpaths << s }
|
34
|
+
end
|
35
|
+
|
36
|
+
def group_by_subpath(parsed_result)
|
37
|
+
parsed_result.each_with_object([]) do
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def parse_arg_string(arg_string)
|
42
|
+
matches = arg_string.scan(/(?:\-\s*)?\d+(?:\.\d+)?/)
|
43
|
+
matches.flatten.map!{|arg| arg.gsub(/\s*/,'').to_f }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
|
8
|
+
require 'wicket'
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
12
|
+
config.run_all_when_everything_filtered = true
|
13
|
+
config.filter_run :focus
|
14
|
+
|
15
|
+
# Run specs in random order to surface order dependencies. If you find an
|
16
|
+
# order dependency and want to debug it, you can fix the order by providing
|
17
|
+
# the seed, which is printed after each run.
|
18
|
+
# --seed 1234
|
19
|
+
config.order = 'random'
|
20
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Wicket
|
4
|
+
describe SVGPath do
|
5
|
+
let(:path){ SVGPath.new("M10 10 20 20") }
|
6
|
+
|
7
|
+
it "knows its text" do
|
8
|
+
expect(path.text).to eq("M10 10 20 20")
|
9
|
+
end
|
10
|
+
|
11
|
+
context "absolute h shortcuts" do
|
12
|
+
let(:path){ SVGPath.new("M10 10H20l10 10H10z") }
|
13
|
+
it "parses to polygon" do
|
14
|
+
expect(path.to_polygon).to eq("POLYGON((10.0 -10.0,20.0 -10.0,30.0 -20.0,10.0 -20.0,10.0 -10.0))")
|
15
|
+
end
|
16
|
+
|
17
|
+
it "parses to a multipolygon" do
|
18
|
+
expect(path.to_multipolygon).to eq("MULTIPOLYGON(((10.0 -10.0,20.0 -10.0,30.0 -20.0,10.0 -20.0,10.0 -10.0)))")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "relative h shortcuts" do
|
23
|
+
let(:path){ SVGPath.new("M10 10h20h10l10 10h-10z") }
|
24
|
+
it "parses to polygon" do
|
25
|
+
expect(path.to_polygon).to eq("POLYGON((10.0 -10.0,30.0 -10.0,40.0 -10.0,50.0 -20.0,40.0 -20.0,10.0 -10.0))")
|
26
|
+
end
|
27
|
+
|
28
|
+
it "parses to a multipolygon" do
|
29
|
+
expect(path.to_multipolygon).to eq("MULTIPOLYGON(((10.0 -10.0,30.0 -10.0,40.0 -10.0,50.0 -20.0,40.0 -20.0,10.0 -10.0)))")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "absolute h shortcuts" do
|
34
|
+
let(:path){ SVGPath.new("M10 10l20 20V50V80z") }
|
35
|
+
it "parses to polygon" do
|
36
|
+
expect(path.to_polygon).to eq("POLYGON((10.0 -10.0,30.0 -30.0,30.0 -50.0,30.0 -80.0,10.0 -10.0))")
|
37
|
+
end
|
38
|
+
|
39
|
+
it "parses to a multipolygon" do
|
40
|
+
expect(path.to_multipolygon).to eq("MULTIPOLYGON(((10.0 -10.0,30.0 -30.0,30.0 -50.0,30.0 -80.0,10.0 -10.0)))")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "relative h shortcuts" do
|
45
|
+
let(:path){ SVGPath.new("M10 10h20h10l10 10h-10z") }
|
46
|
+
it "parses to polygon" do
|
47
|
+
expect(path.to_polygon).to eq("POLYGON((10.0 -10.0,30.0 -10.0,40.0 -10.0,50.0 -20.0,40.0 -20.0,10.0 -10.0))")
|
48
|
+
end
|
49
|
+
|
50
|
+
it "parses to a multipolygon" do
|
51
|
+
expect(path.to_multipolygon).to eq("MULTIPOLYGON(((10.0 -10.0,30.0 -10.0,40.0 -10.0,50.0 -20.0,40.0 -20.0,10.0 -10.0)))")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "single subpath, manually closed, no explicit commands" do
|
56
|
+
let(:path){ SVGPath.new("M197.5977 356.0957 227.0786 325.3271 229.667 328.4067 200.8188 358.5156 197.5977 356.0957") }
|
57
|
+
|
58
|
+
it "parses to polygon" do
|
59
|
+
expect(path.to_polygon).to eq("POLYGON((197.5977 -356.0957,227.0786 -325.3271,229.667 -328.4067,200.8188 -358.5156,197.5977 -356.0957))")
|
60
|
+
end
|
61
|
+
|
62
|
+
it "parses to a multipolygon" do
|
63
|
+
expect(path.to_multipolygon).to eq("MULTIPOLYGON(((197.5977 -356.0957,227.0786 -325.3271,229.667 -328.4067,200.8188 -358.5156,197.5977 -356.0957)))")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "single subpath, z closed, no explicit commands" do
|
68
|
+
let(:path){ SVGPath.new("M227.1177 371.5405 247.7852 349.9634 250.373 353.0425 230.2959 374.0044 z") }
|
69
|
+
|
70
|
+
it "parses to polygon" do
|
71
|
+
expect(path.to_polygon).to eq("POLYGON((227.1177 -371.5405,247.7852 -349.9634,250.373 -353.0425,230.2959 -374.0044,227.1177 -371.5405))")
|
72
|
+
end
|
73
|
+
|
74
|
+
it "parses to a multipolygon" do
|
75
|
+
expect(path.to_multipolygon).to eq("MULTIPOLYGON(((227.1177 -371.5405,247.7852 -349.9634,250.373 -353.0425,230.2959 -374.0044,227.1177 -371.5405)))")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
context "single subpath, z closed, no explicit commands" do
|
81
|
+
let(:path){ SVGPath.new("M227.1177 371.5405 247.7852 349.9634 250.373 353.0425 230.2959 374.0044 z") }
|
82
|
+
|
83
|
+
it "parses to polygon" do
|
84
|
+
expect(path.to_polygon).to eq("POLYGON((227.1177 -371.5405,247.7852 -349.9634,250.373 -353.0425,230.2959 -374.0044,227.1177 -371.5405))")
|
85
|
+
end
|
86
|
+
|
87
|
+
it "parses to a multipolygon" do
|
88
|
+
expect(path.to_multipolygon).to eq("MULTIPOLYGON(((227.1177 -371.5405,247.7852 -349.9634,250.373 -353.0425,230.2959 -374.0044,227.1177 -371.5405)))")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context "single subpath, z closed, relative and absolute commands" do
|
93
|
+
let(:path){ SVGPath.new("M722.3984,688.502L710,693.5693l-1.8115-3.5811l12.3096-5.0313L732.3984,688.502z") }
|
94
|
+
|
95
|
+
it "parses to polygon" do
|
96
|
+
expect(path.to_polygon).to eq("POLYGON((722.3984 -688.502,710.0 -693.5693,708.1885 -689.9882,720.4981 -684.9569,732.3984 -688.502,722.3984 -688.502))")
|
97
|
+
end
|
98
|
+
|
99
|
+
it "parses to a multipolygon" do
|
100
|
+
expect(path.to_multipolygon).to eq("MULTIPOLYGON(((722.3984 -688.502,710.0 -693.5693,708.1885 -689.9882,720.4981 -684.9569,732.3984 -688.502,722.3984 -688.502)))")
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context "two subpaths, z closed, no explicit commands" do
|
105
|
+
let(:path){ SVGPath.new("M227.1177 371.5405 247.7852 349.9634 250.373 353.0425 230.2959 374.0044 z M197.5977 356.0957 227.0786 325.3271 229.667 328.4067 200.8188 358.5156 197.5977 356.0957") }
|
106
|
+
|
107
|
+
it "parses the first subpath to polygon" do
|
108
|
+
expect(path.to_polygon).to eq("POLYGON((227.1177 -371.5405,247.7852 -349.9634,250.373 -353.0425,230.2959 -374.0044,227.1177 -371.5405))")
|
109
|
+
end
|
110
|
+
|
111
|
+
it "parses both to a multipolygon" do
|
112
|
+
expect(path.to_multipolygon).to eq("MULTIPOLYGON(((227.1177 -371.5405,247.7852 -349.9634,250.373 -353.0425,230.2959 -374.0044,227.1177 -371.5405)),((197.5977 -356.0957,227.0786 -325.3271,229.667 -328.4067,200.8188 -358.5156,197.5977 -356.0957)))")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "the kitchen sink" do
|
117
|
+
let(:path){ SVGPath.new("M749.208,402.3311l14.8604,23.8335l-3.6279,1.7236l-14.4775-23.1108L749.208,402.3311z M775.3047,457.8872l0.0293,33.5894 l-3.9326,0.0044l-0.0225-32.6997L775.3047,457.8872z M764.0645,426.1665l11.2402,31.7207l-3.9268,0.894l-10.9434-30.8901 L764.0645,426.1665z") }
|
118
|
+
it "parses the first subpath to polygon" do
|
119
|
+
expect(path.to_polygon).to eq("POLYGON((227.1177 -371.5405,247.7852 -349.9634,250.373 -353.0425,230.2959 -374.0044,227.1177 -371.5405))")
|
120
|
+
end
|
121
|
+
|
122
|
+
it "parses both to a multipolygon" do
|
123
|
+
expect(path.to_multipolygon).to eq("MULTIPOLYGON(((227.1177 -371.5405,247.7852 -349.9634,250.373 -353.0425,230.2959 -374.0044,227.1177 -371.5405)),((197.5977 -356.0957,227.0786 -325.3271,229.667 -328.4067,200.8188 -358.5156,197.5977 -356.0957)))")
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
data/wicket.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'wicket/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "wicket"
|
8
|
+
spec.version = Wicket::VERSION
|
9
|
+
spec.authors = ["Ryan Urabe"]
|
10
|
+
spec.email = ["rurabe@gmail.com"]
|
11
|
+
spec.summary = "A tool to turn SVGs into WKT"
|
12
|
+
spec.description = "A tool to turn SVGs into WKT for use in GIS databases or whatever you want to do with it"
|
13
|
+
spec.homepage = "http://github.com/rurabe/wicket"
|
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
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wicket
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan Urabe
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-04-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: A tool to turn SVGs into WKT for use in GIS databases or whatever you
|
56
|
+
want to do with it
|
57
|
+
email:
|
58
|
+
- rurabe@gmail.com
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".gitignore"
|
64
|
+
- ".rspec"
|
65
|
+
- ".travis.yml"
|
66
|
+
- Gemfile
|
67
|
+
- LICENSE.txt
|
68
|
+
- README.md
|
69
|
+
- Rakefile
|
70
|
+
- lib/wicket.rb
|
71
|
+
- lib/wicket/command.rb
|
72
|
+
- lib/wicket/commands/h.rb
|
73
|
+
- lib/wicket/commands/l.rb
|
74
|
+
- lib/wicket/commands/m.rb
|
75
|
+
- lib/wicket/commands/v.rb
|
76
|
+
- lib/wicket/commands/z.rb
|
77
|
+
- lib/wicket/subpath.rb
|
78
|
+
- lib/wicket/svg_path.rb
|
79
|
+
- lib/wicket/version.rb
|
80
|
+
- spec/spec_helper.rb
|
81
|
+
- spec/svg_path_spec.rb
|
82
|
+
- wicket.gemspec
|
83
|
+
homepage: http://github.com/rurabe/wicket
|
84
|
+
licenses:
|
85
|
+
- MIT
|
86
|
+
metadata: {}
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
requirements: []
|
102
|
+
rubyforge_project:
|
103
|
+
rubygems_version: 2.2.2
|
104
|
+
signing_key:
|
105
|
+
specification_version: 4
|
106
|
+
summary: A tool to turn SVGs into WKT
|
107
|
+
test_files:
|
108
|
+
- spec/spec_helper.rb
|
109
|
+
- spec/svg_path_spec.rb
|