topojson-rails 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+
3
+ # Specify your gem's dependencies in gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Vlad Gorodetsky
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,27 @@
1
+ # topojson-rails
2
+
3
+ **TopoJSON** is an extension of GeoJSON that encodes topology. Rather than representing geometries discretely, geometries in TopoJSON files are stitched together from shared line segments called *arcs*. TopoJSON eliminates redundancy, offering much more compact representations of geometry than with GeoJSON; typical TopoJSON files are 80% smaller than their GeoJSON equivalents. In addition, TopoJSON facilitates applications that use topology, such as [topology-preserving shape simplification](http://bost.ocks.org/mike/simplify/), [automatic map coloring](http://bl.ocks.org/4188334), and [cartograms](http://prag.ma/code/d3-cartogram/).
4
+
5
+ Want to learn more? [See the wiki.](/mbostock/topojson/wiki)
6
+
7
+ ## Installation
8
+
9
+ Add the following to your gemfile:
10
+
11
+ gem 'topojson-rails'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Add the following directive to your JavaScript manifest file (application.js):
18
+
19
+ //= require topojson
20
+
21
+ ## Contributing
22
+
23
+ 1. Fork it
24
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
25
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
26
+ 4. Push to the branch (`git push origin my-new-feature`)
27
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,8 @@
1
+ require "topojson-rails/version"
2
+
3
+ module Topojson
4
+ module Rails
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ module Topojson
2
+ module Rails
3
+ VERSION = "0.0.8"
4
+ end
5
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'topojson-rails/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "topojson-rails"
8
+ gem.version = Topojson::Rails::VERSION
9
+ gem.authors = ["Vlad Gorodetsky"]
10
+ gem.email = ["v@gor.io"]
11
+ gem.description = %q{An extension of GeoJSON that encodes topology.}
12
+ gem.summary = %q{Gemified topojson.js asset for Rails}
13
+ gem.homepage = "http://github.com/bai/topojson-rails"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency "railties", ">= 3.0", "< 5.0"
21
+ end
@@ -0,0 +1,253 @@
1
+ topojson = (function() {
2
+
3
+ function merge(topology, arcs) {
4
+ var arcsByEnd = {},
5
+ fragmentByStart = {},
6
+ fragmentByEnd = {};
7
+
8
+ arcs.forEach(function(i) {
9
+ var e = ends(i);
10
+ (arcsByEnd[e[0]] || (arcsByEnd[e[0]] = [])).push(i);
11
+ (arcsByEnd[e[1]] || (arcsByEnd[e[1]] = [])).push(~i);
12
+ });
13
+
14
+ arcs.forEach(function(i) {
15
+ var e = ends(i),
16
+ start = e[0],
17
+ end = e[1],
18
+ f, g;
19
+
20
+ if (f = fragmentByEnd[start]) {
21
+ delete fragmentByEnd[f.end];
22
+ f.push(i);
23
+ f.end = end;
24
+ if (g = fragmentByStart[end]) {
25
+ delete fragmentByStart[g.start];
26
+ var fg = g === f ? f : f.concat(g);
27
+ fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg;
28
+ } else if (g = fragmentByEnd[end]) {
29
+ delete fragmentByStart[g.start];
30
+ delete fragmentByEnd[g.end];
31
+ var fg = f.concat(g.map(function(i) { return ~i; }).reverse());
32
+ fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.start] = fg;
33
+ } else {
34
+ fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
35
+ }
36
+ } else if (f = fragmentByStart[end]) {
37
+ delete fragmentByStart[f.start];
38
+ f.unshift(i);
39
+ f.start = start;
40
+ if (g = fragmentByEnd[start]) {
41
+ delete fragmentByEnd[g.end];
42
+ var gf = g === f ? f : g.concat(f);
43
+ fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf;
44
+ } else if (g = fragmentByStart[start]) {
45
+ delete fragmentByStart[g.start];
46
+ delete fragmentByEnd[g.end];
47
+ var gf = g.map(function(i) { return ~i; }).reverse().concat(f);
48
+ fragmentByStart[gf.start = g.end] = fragmentByEnd[gf.end = f.end] = gf;
49
+ } else {
50
+ fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
51
+ }
52
+ } else if (f = fragmentByStart[start]) {
53
+ delete fragmentByStart[f.start];
54
+ f.unshift(~i);
55
+ f.start = end;
56
+ if (g = fragmentByEnd[end]) {
57
+ delete fragmentByEnd[g.end];
58
+ var gf = g === f ? f : g.concat(f);
59
+ fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf;
60
+ } else if (g = fragmentByStart[end]) {
61
+ delete fragmentByStart[g.start];
62
+ delete fragmentByEnd[g.end];
63
+ var gf = g.map(function(i) { return ~i; }).reverse().concat(f);
64
+ fragmentByStart[gf.start = g.end] = fragmentByEnd[gf.end = f.end] = gf;
65
+ } else {
66
+ fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
67
+ }
68
+ } else if (f = fragmentByEnd[end]) {
69
+ delete fragmentByEnd[f.end];
70
+ f.push(~i);
71
+ f.end = start;
72
+ if (g = fragmentByEnd[start]) {
73
+ delete fragmentByStart[g.start];
74
+ var fg = g === f ? f : f.concat(g);
75
+ fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg;
76
+ } else if (g = fragmentByStart[start]) {
77
+ delete fragmentByStart[g.start];
78
+ delete fragmentByEnd[g.end];
79
+ var fg = f.concat(g.map(function(i) { return ~i; }).reverse());
80
+ fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.start] = fg;
81
+ } else {
82
+ fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
83
+ }
84
+ } else {
85
+ f = [i];
86
+ fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f;
87
+ }
88
+ });
89
+
90
+ function ends(i) {
91
+ var arc = topology.arcs[i], p0 = arc[0], p1 = [0, 0];
92
+ arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; });
93
+ return [p0, p1];
94
+ }
95
+
96
+ var fragments = [];
97
+ for (var k in fragmentByEnd) fragments.push(fragmentByEnd[k]);
98
+ return fragments;
99
+ }
100
+
101
+ function mesh(topology, o, filter) {
102
+ var arcs = [];
103
+
104
+ if (arguments.length > 1) {
105
+ var geomsByArc = [],
106
+ geom;
107
+
108
+ function arc(i) {
109
+ if (i < 0) i = ~i;
110
+ (geomsByArc[i] || (geomsByArc[i] = [])).push(geom);
111
+ }
112
+
113
+ function line(arcs) {
114
+ arcs.forEach(arc);
115
+ }
116
+
117
+ function polygon(arcs) {
118
+ arcs.forEach(line);
119
+ }
120
+
121
+ function geometry(o) {
122
+ geom = o;
123
+ geometryType[o.type](o.arcs);
124
+ }
125
+
126
+ var geometryType = {
127
+ LineString: line,
128
+ MultiLineString: polygon,
129
+ Polygon: polygon,
130
+ MultiPolygon: function(arcs) { arcs.forEach(polygon); }
131
+ };
132
+
133
+ o.type === "GeometryCollection"
134
+ ? o.geometries.forEach(geometry)
135
+ : geometry(o);
136
+
137
+ geomsByArc.forEach(arguments.length < 3
138
+ ? function(geoms, i) { arcs.push([i]); }
139
+ : function(geoms, i) { if (filter(geoms[0], geoms[geoms.length - 1])) arcs.push([i]); });
140
+ } else {
141
+ for (var i = 0, n = topology.arcs.length; i < n; ++i) arcs.push([i]);
142
+ }
143
+
144
+ return object(topology, {type: "MultiLineString", arcs: merge(topology, arcs)});
145
+ }
146
+
147
+ function object(topology, o) {
148
+ var tf = topology.transform,
149
+ kx = tf.scale[0],
150
+ ky = tf.scale[1],
151
+ dx = tf.translate[0],
152
+ dy = tf.translate[1],
153
+ arcs = topology.arcs;
154
+
155
+ function arc(i, points) {
156
+ if (points.length) points.pop();
157
+ for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length, x = 0, y = 0, p; k < n; ++k) points.push([
158
+ (x += (p = a[k])[0]) * kx + dx,
159
+ (y += p[1]) * ky + dy
160
+ ]);
161
+ if (i < 0) reverse(points, n);
162
+ }
163
+
164
+ function point(coordinates) {
165
+ return [coordinates[0] * kx + dx, coordinates[1] * ky + dy];
166
+ }
167
+
168
+ function line(arcs) {
169
+ var points = [];
170
+ for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points);
171
+ return points;
172
+ }
173
+
174
+ function polygon(arcs) {
175
+ return arcs.map(line);
176
+ }
177
+
178
+ function geometry(o) {
179
+ o = Object.create(o);
180
+ o.coordinates = geometryType[o.type](o);
181
+ return o;
182
+ }
183
+
184
+ var geometryType = {
185
+ Point: function(o) { return point(o.coordinates); },
186
+ MultiPoint: function(o) { return o.coordinates.map(point); },
187
+ LineString: function(o) { return line(o.arcs); },
188
+ MultiLineString: function(o) { return polygon(o.arcs); },
189
+ Polygon: function(o) { return polygon(o.arcs); },
190
+ MultiPolygon: function(o) { return o.arcs.map(polygon); }
191
+ };
192
+
193
+ return o.type === "GeometryCollection"
194
+ ? (o = Object.create(o), o.geometries = o.geometries.map(geometry), o)
195
+ : geometry(o);
196
+ }
197
+
198
+ function reverse(array, n) {
199
+ var t, j = array.length, i = j - n; while (i < --j) t = array[i], array[i++] = array[j], array[j] = t;
200
+ }
201
+
202
+ function bisect(a, x) {
203
+ var lo = 0, hi = a.length;
204
+ while (lo < hi) {
205
+ var mid = lo + hi >>> 1;
206
+ if (a[mid] < x) lo = mid + 1;
207
+ else hi = mid;
208
+ }
209
+ return lo;
210
+ }
211
+
212
+ function neighbors(topology, objects) {
213
+ var objectsByArc = [],
214
+ neighbors = objects.map(function() { return []; });
215
+
216
+ function line(arcs, i) {
217
+ arcs.forEach(function(a) {
218
+ if (a < 0) a = ~a;
219
+ var o = objectsByArc[a] || (objectsByArc[a] = []);
220
+ if (!o[i]) o.forEach(function(j) {
221
+ var n, k;
222
+ k = bisect(n = neighbors[i], j); if (n[k] !== j) n.splice(k, 0, j);
223
+ k = bisect(n = neighbors[j], i); if (n[k] !== i) n.splice(k, 0, i);
224
+ }), o[i] = i;
225
+ });
226
+ }
227
+
228
+ function polygon(arcs, i) {
229
+ arcs.forEach(function(arc) { line(arc, i); });
230
+ }
231
+
232
+ function geometry(o, i) {
233
+ geometryType[o.type](o.arcs, i);
234
+ }
235
+
236
+ var geometryType = {
237
+ LineString: line,
238
+ MultiLineString: polygon,
239
+ Polygon: polygon,
240
+ MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); }
241
+ };
242
+
243
+ objects.forEach(geometry);
244
+ return neighbors;
245
+ }
246
+
247
+ return {
248
+ version: "0.0.8",
249
+ mesh: mesh,
250
+ object: object,
251
+ neighbors: neighbors
252
+ };
253
+ })();
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: topojson-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.8
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Vlad Gorodetsky
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: railties
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '3.0'
22
+ - - <
23
+ - !ruby/object:Gem::Version
24
+ version: '5.0'
25
+ type: :runtime
26
+ prerelease: false
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '3.0'
33
+ - - <
34
+ - !ruby/object:Gem::Version
35
+ version: '5.0'
36
+ description: An extension of GeoJSON that encodes topology.
37
+ email:
38
+ - v@gor.io
39
+ executables: []
40
+ extensions: []
41
+ extra_rdoc_files: []
42
+ files:
43
+ - .gitignore
44
+ - Gemfile
45
+ - LICENSE
46
+ - README.md
47
+ - Rakefile
48
+ - lib/topojson-rails.rb
49
+ - lib/topojson-rails/version.rb
50
+ - topojson-rails.gemspec
51
+ - vendor/assets/javascripts/topojson.js
52
+ homepage: http://github.com/bai/topojson-rails
53
+ licenses: []
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubyforge_project:
72
+ rubygems_version: 1.8.24
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: Gemified topojson.js asset for Rails
76
+ test_files: []