brokjson 1.0.0

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.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/lib/brokjson.rb +173 -0
  3. data/test/test_brokjson.rb +79 -0
  4. metadata +46 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: '0013492d14661dd0d183aee536c4ff4c4f01d0b58d70edf201a3e157554bd6ef'
4
+ data.tar.gz: 2d13984d0c27917e8d09cd35c57f7eba92b300ffd798ef518950a1d39ac78dc0
5
+ SHA512:
6
+ metadata.gz: 66930a92352f886ca573458abee6a0917197722bfa638f51a09df02d546d0f1d5d22b0a4398d3411035394ad625bde1ade697e0489803482f643b25b065bfc67
7
+ data.tar.gz: 7307728c001fbf46d8a5a98bb667ea31c06050f0df49ffe98219146538a23645fe545d739ffd37074c03d0cc80546fe9b7f1f6f914bba8bb8532f079286ae19e
data/lib/brokjson.rb ADDED
@@ -0,0 +1,173 @@
1
+ class BrokJson
2
+ def self.geo2brok(geojson)
3
+ global_geometries = []
4
+ global_properties = []
5
+ global_foreign_members = []
6
+
7
+ geojson['features'].each do |feature|
8
+ next if feature['type'].downcase != 'feature'
9
+
10
+ return unless feature.key?('geometry')
11
+
12
+ # Add properties
13
+ props = []
14
+ if feature.key?('properties')
15
+ feature['properties'].each do |property_key, property_value|
16
+ # Add to list if item in list
17
+ global_properties << property_key unless global_properties.include? property_key
18
+
19
+ index = global_properties.find_index(property_key)
20
+
21
+ # Check if props are long enough
22
+ props = props + [nil] * (index + 1 - props.length) if props.length - 1 < index
23
+
24
+ # Add to props
25
+ props[index] = property_value
26
+ end
27
+ end
28
+
29
+ # Add foreign members
30
+ foreign_members = []
31
+ feature.each do |item_key, item_val|
32
+ next if ['type', 'properties', 'geometry'].include? item_key.downcase
33
+
34
+ global_foreign_members << item_key unless global_foreign_members.include? item_key
35
+
36
+ index = global_foreign_members.find_index(item_key)
37
+
38
+ foreign_members = foreign_members + [nil] * (index + 1 - foreign_members.length) if foreign_members.length - 1 < index
39
+
40
+ foreign_members[index] = item_val
41
+ end
42
+
43
+ coords = nil
44
+ if feature['geometry']['type'].downcase == 'geometrycollection'
45
+ # GeometryCollection detected!
46
+ coords = []
47
+
48
+ feature["geometry"]["geometries"].each do |geom|
49
+ # Now check if last item of geometries is same type. If not, add the type
50
+ if (coords.length == 0 || coords[-1]['type'].downcase != geom['type'].downcase)
51
+ # Add new geometry list
52
+ coords << { 'type' => geom['type'], 'features' => [] }
53
+ end
54
+
55
+ # Add feature to geometry list
56
+ coords[coords.length - 1]['features'] << [geom['coordinates']]
57
+ end
58
+ else
59
+ # Add Coords
60
+ coords = feature['geometry']['coordinates']
61
+ end
62
+
63
+ # Create feature-array
64
+ brok_feature = [coords]
65
+
66
+ # Add props
67
+ brok_feature << props if props.length > 0
68
+
69
+ # Add foreign members
70
+ if foreign_members.length > 0
71
+ brok_feature << nil if brok_feature.length < 2
72
+ brok_feature << foreign_members
73
+ end
74
+
75
+ # Now check if last item of geometries is same type. If not, add the type
76
+ if (global_geometries.length == 0 || global_geometries[-1]['type'].downcase != feature['geometry']['type'].downcase)
77
+ # Add new geometry list
78
+ global_geometries << { 'type' => feature['geometry']['type'], 'features' => [] }
79
+ end
80
+
81
+ # Add feature to geometry list
82
+ global_geometries[global_geometries.length - 1]['features'] << brok_feature
83
+ end
84
+
85
+ # Build BrokJSON
86
+ brok = {}
87
+
88
+ # Add global properties
89
+ brok['properties'] = global_properties if global_properties.length > 0
90
+
91
+ # Add foreign members
92
+ brok['foreignMembers'] = global_foreign_members if global_foreign_members.length > 0
93
+
94
+ # Add all unknown members
95
+ geojson.each do |member_key, member_val|
96
+ # Exclude List
97
+ next if ['type', 'features'].include? member_key
98
+
99
+ brok[member_key] = member_val
100
+ end
101
+
102
+ # Add geometry
103
+ brok['geometries'] = global_geometries if global_geometries.length > 0
104
+
105
+ return brok
106
+ end
107
+
108
+ def self.brok2geo(brok)
109
+ geo = {
110
+ 'type' => 'FeatureCollection'
111
+ }
112
+
113
+ # Look for custom properties on root
114
+ brok.each do |member_key, member_val|
115
+ geo[member_key] = member_val unless ['properties', 'geometries', 'foreignMembers'].include? member_key
116
+ end
117
+
118
+ geo['features'] = [] if brok['geometries'].length > 0
119
+
120
+ # Add geometries
121
+ brok['geometries'].each do |geometry_collection|
122
+ geometry_collection['features'].each do |feature|
123
+ # Create Feature
124
+ json_feature = { 'type' => 'Feature' }
125
+
126
+ # Check and add properties
127
+ properties = {}
128
+ if feature.length >= 2
129
+ (0..feature[1].length).each do |p|
130
+ prop = feature[1][p]
131
+
132
+ next if prop.nil?
133
+
134
+ properties[brok['properties'][p]] = prop
135
+ end
136
+ end
137
+
138
+ # Check and add foreign members
139
+ if feature.length >= 3
140
+ (0..feature[2].length).each do |m|
141
+ json_feature[brok['foreignMembers'][m]] = feature[2][m]
142
+ end
143
+ end
144
+
145
+ # Add props
146
+ json_feature['properties'] = properties if properties.length > 0
147
+
148
+ # Check if geometry collection
149
+ if geometry_collection['type'].downcase == 'geometryCollection'
150
+ new_coords = []
151
+ geometry_collection['features'].each do |coordinates|
152
+ coordinates[0].each do |geocol|
153
+ geocol['features'].each do |types|
154
+ coord = { 'type' => geocol['type'], 'coordinates' => types[0] }
155
+ new_coords << coord
156
+ end
157
+ end
158
+ end
159
+
160
+ # Add Geometry
161
+ json_feature['geometry'] = { 'type' => geometry_collection['type'], 'geometries' => new_coords }
162
+ else
163
+ # Normal Geometry
164
+ json_feature['geometry'] = { 'type' => geometry_collection['type'], 'coordinates' => feature[0] }
165
+ end
166
+
167
+ geo['features'] << json_feature
168
+ end
169
+ end
170
+
171
+ return geo
172
+ end
173
+ end
@@ -0,0 +1,79 @@
1
+ require 'test/unit'
2
+ require 'brokjson'
3
+
4
+ class BrokJsonTest < Test::Unit::TestCase
5
+ def test_can_convert_from_geojson_to_brokjson
6
+ assert_equal sample_brokjson, BrokJson.geo2brok(sample_geojson)
7
+ end
8
+
9
+ def test_can_convert_from_brokjson_to_geojson
10
+ assert_equal sample_geojson, BrokJson.brok2geo(sample_brokjson)
11
+ end
12
+
13
+ private
14
+
15
+ def sample_geojson
16
+ {
17
+ 'type' => 'FeatureCollection',
18
+ 'title' => 'Hello World',
19
+ 'features' => [
20
+ {
21
+ 'type' => 'Feature',
22
+ 'properties' => {
23
+ 'id' => 1,
24
+ 'title' => 'Datapoint 1',
25
+ 'value' => 343
26
+ },
27
+ 'geometry' => {
28
+ 'type' => 'Point',
29
+ 'coordinates' => [
30
+ 8.5402,
31
+ 47.3782
32
+ ]
33
+ }
34
+ },
35
+ {
36
+ 'type' => 'Feature',
37
+ 'properties' => {
38
+ 'id' => 1,
39
+ 'title' => 'Datapoint 2',
40
+ 'value' => 14
41
+ },
42
+ 'geometry' => {
43
+ 'type' => 'Point',
44
+ 'coordinates' => [
45
+ 8.5637,
46
+ 47.4504
47
+ ]
48
+ }
49
+ }
50
+ ]
51
+ }
52
+ end
53
+
54
+ def sample_brokjson
55
+ {
56
+ 'properties' => [
57
+ 'id',
58
+ 'title',
59
+ 'value'
60
+ ],
61
+ 'title' => 'Hello World',
62
+ 'geometries' => [
63
+ {
64
+ 'type' => 'Point',
65
+ 'features'=> [
66
+ [
67
+ [8.5402, 47.3782],
68
+ [1, 'Datapoint 1', 343]
69
+ ],
70
+ [
71
+ [8.5637, 47.4504],
72
+ [1, 'Datapoint 2', 14]
73
+ ]
74
+ ]
75
+ }
76
+ ]
77
+ }
78
+ end
79
+ end
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: brokjson
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Hazimi Asyraf
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-03-24 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: BrokJSON is a space-saving alternative to GeoJSON. Convert GeoJSON to
14
+ BrokJSON and vice versa
15
+ email: hazimi@hazimiasyraf.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/brokjson.rb
21
+ - test/test_brokjson.rb
22
+ homepage: https://github.com/jimmyasyraf/brokJSON_rb
23
+ licenses:
24
+ - MIT
25
+ metadata: {}
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - lib
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '2.6'
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ requirements: []
41
+ rubygems_version: 3.1.2
42
+ signing_key:
43
+ specification_version: 4
44
+ summary: BrokJSON is a space-saving alternative to GeoJSON
45
+ test_files:
46
+ - test/test_brokjson.rb