iiif-presentation 1.2.0 → 1.3.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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/iiif-presentation.gemspec +1 -0
- data/lib/iiif/v3/presentation/nav_place.rb +109 -0
- data/lib/iiif/v3/presentation.rb +1 -0
- data/spec/unit/iiif/v3/presentation/nav_place_spec.rb +80 -0
- metadata +20 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55260d04809482b5ebd267655c07543d4c97e2d5166bdca7b26eff5b22725fe6
|
4
|
+
data.tar.gz: 616cb247a11b55e56aac745508e5aa5000cae11c47b3e384d37ca2011b187c55
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e83acf715f8b6bf0513d1211ce5797237f28e9cead4c2cf3446b150ba496df81e16ba7b0d7ffae04aebe9cb40a4b84098c8d184e493f1259419cd0f9d99fae0b
|
7
|
+
data.tar.gz: 2221b5bcfc51cabfefc039584a58b93bd16fa95f7729e7921017bdac46b6d71e8cea6cbcc687e38f96a903386d4b7daf56d66693868e719b7cb6944ccc1067a3
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.3.0
|
data/iiif-presentation.gemspec
CHANGED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'geo/coord'
|
2
|
+
|
3
|
+
module IIIF
|
4
|
+
module V3
|
5
|
+
module Presentation
|
6
|
+
class NavPlace < IIIF::V3::AbstractResource
|
7
|
+
Rect = Struct.new(:coord1, :coord2)
|
8
|
+
|
9
|
+
COORD_REGEX = /(?<hemisphere>[NSEW]) (?<degrees>\d+)[°⁰*] ?(?<minutes>\d+)?[ʹ']? ?(?<seconds>\d+)?[ʺ"]?/
|
10
|
+
|
11
|
+
def initialize(coordinate_texts:, base_uri:)
|
12
|
+
@coordinate_texts = coordinate_texts
|
13
|
+
@base_uri = base_uri
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Boolean] indicates if coordinate_texts passed in are valid
|
17
|
+
def valid?
|
18
|
+
!(coordinates.nil? || coordinates.empty?)
|
19
|
+
end
|
20
|
+
|
21
|
+
def build
|
22
|
+
raise ArgumentError.new('invalid coordinates') unless valid?
|
23
|
+
|
24
|
+
{
|
25
|
+
id: "#{base_uri}/feature-collection/1",
|
26
|
+
type: 'FeatureCollection',
|
27
|
+
features: features
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader :coordinate_texts, :base_uri
|
34
|
+
|
35
|
+
def coordinates
|
36
|
+
@coordinates ||= coordinate_texts.map do |coordinate_text|
|
37
|
+
coordinate_parts = coordinate_text.split(%r{ ?--|/})
|
38
|
+
case coordinate_parts.length
|
39
|
+
when 2
|
40
|
+
coord_for(coordinate_parts[0], coordinate_parts[1])
|
41
|
+
when 4
|
42
|
+
rect_for(coordinate_parts)
|
43
|
+
end
|
44
|
+
end.compact
|
45
|
+
end
|
46
|
+
|
47
|
+
def coord_for(long_str, lat_str)
|
48
|
+
long_matcher = long_str.match(COORD_REGEX)
|
49
|
+
lat_matcher = lat_str.match(COORD_REGEX)
|
50
|
+
return unless long_matcher && lat_matcher
|
51
|
+
|
52
|
+
Geo::Coord.new(latd: lat_matcher[:degrees], latm: lat_matcher[:minutes], lats: lat_matcher[:seconds], lath: lat_matcher[:hemisphere],
|
53
|
+
lngd: long_matcher[:degrees], lngm: long_matcher[:minutes], lngs: long_matcher[:seconds], lngh: long_matcher[:hemisphere])
|
54
|
+
end
|
55
|
+
|
56
|
+
def rect_for(coordinate_parts)
|
57
|
+
coord1 = coord_for(coordinate_parts[0], coordinate_parts[2])
|
58
|
+
coord2 = coord_for(coordinate_parts[1], coordinate_parts[3])
|
59
|
+
return if coord1.nil? || coord2.nil?
|
60
|
+
|
61
|
+
Rect.new(coord1, coord2)
|
62
|
+
end
|
63
|
+
|
64
|
+
def features
|
65
|
+
coordinates.map.with_index(1) do |coordinate, index|
|
66
|
+
{
|
67
|
+
id: "#{base_uri}/iiif/feature/#{index}",
|
68
|
+
type: 'Feature',
|
69
|
+
properties: {},
|
70
|
+
geometry: coordinate.is_a?(Rect) ? polygon_geometry(coordinate) : point_geometry(coordinate)
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def point_geometry(coord)
|
76
|
+
{
|
77
|
+
type: 'Point',
|
78
|
+
coordinates: [format(coord.lng), format(coord.lat)]
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
def polygon_geometry(rect)
|
83
|
+
{
|
84
|
+
type: 'Polygon',
|
85
|
+
coordinates: [
|
86
|
+
[
|
87
|
+
[format(rect.coord1.lng), format(rect.coord1.lat)],
|
88
|
+
[format(rect.coord2.lng), format(rect.coord1.lat)],
|
89
|
+
[format(rect.coord2.lng), format(rect.coord2.lat)],
|
90
|
+
[format(rect.coord1.lng), format(rect.coord2.lat)],
|
91
|
+
[format(rect.coord1.lng), format(rect.coord1.lat)]
|
92
|
+
]
|
93
|
+
]
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
# @param [BigDecimal] coordinate value from geocoord gem
|
98
|
+
# @return [String] string formatted with max 6 digits after the decimal point
|
99
|
+
# The to_f ensures removal of scientific notation of BigDecimal before converting to a string.
|
100
|
+
# examples:
|
101
|
+
# input value is BigDecimal("-23.9") or "0.239e2", output value is "-23.9" as string
|
102
|
+
# input value is BigDecimal("23.9424213434") or "0.239424213434e2", output value is "23.942421" as string
|
103
|
+
def format(decimal)
|
104
|
+
decimal.truncate(6).to_f.to_s
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/lib/iiif/v3/presentation.rb
CHANGED
@@ -0,0 +1,80 @@
|
|
1
|
+
describe IIIF::V3::Presentation::NavPlace do
|
2
|
+
let(:subject) { described_class.new(coordinate_texts: coordinate_texts, base_uri: base_uri) }
|
3
|
+
let(:base_uri) { "https://purl.stanford.edu" }
|
4
|
+
let(:invalid_coordinates) { ["bogus", "stuff", "is", "here"] }
|
5
|
+
let(:valid_coordinates) do
|
6
|
+
["W 23°54'00\"--E 53°36'00\"/N 71°19'00\"--N 33°30'00\"",
|
7
|
+
'E 103°48ʹ/S 3°46ʹ).',
|
8
|
+
'X 103°48ʹ/Y 3°46ʹ).',
|
9
|
+
'In decimal degrees: (E 138.0--W 074.0/N 073.0--N 041.2).']
|
10
|
+
end
|
11
|
+
let(:nav_place) do
|
12
|
+
{ id: 'https://purl.stanford.edu/feature-collection/1',
|
13
|
+
type: 'FeatureCollection',
|
14
|
+
features: [{ id: 'https://purl.stanford.edu/iiif/feature/1',
|
15
|
+
type: 'Feature',
|
16
|
+
properties: {},
|
17
|
+
geometry: { type: 'Polygon',
|
18
|
+
coordinates: [[['-23.9', '71.316666'],
|
19
|
+
['53.6', '71.316666'],
|
20
|
+
['53.6', '33.5'],
|
21
|
+
['-23.9', '33.5'],
|
22
|
+
['-23.9', '71.316666']]] } },
|
23
|
+
{ id: 'https://purl.stanford.edu/iiif/feature/2',
|
24
|
+
type: 'Feature',
|
25
|
+
properties: {},
|
26
|
+
geometry: { type: 'Point', coordinates: ['103.8', '-3.766666'] } }] }
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#build' do
|
30
|
+
context 'when coordinates are valid' do
|
31
|
+
let(:coordinate_texts) { valid_coordinates }
|
32
|
+
|
33
|
+
it 'returns navPlace' do
|
34
|
+
expect(subject.build).to eq nav_place
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when coordinates are not present' do
|
39
|
+
let(:coordinate_texts) { [] }
|
40
|
+
|
41
|
+
it 'raises ArgumentError' do
|
42
|
+
expect { subject.build }.to raise_error(ArgumentError)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when coordinates are invalid' do
|
47
|
+
let(:coordinate_texts) { invalid_coordinates }
|
48
|
+
|
49
|
+
it 'raises ArgumentError' do
|
50
|
+
expect { subject.build }.to raise_error(ArgumentError)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#valid' do
|
56
|
+
context 'when coordinates are valid' do
|
57
|
+
let(:coordinate_texts) { valid_coordinates }
|
58
|
+
|
59
|
+
it 'returns true' do
|
60
|
+
expect(subject.valid?).to be true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when coordinates are not present' do
|
65
|
+
let(:coordinate_texts) { [] }
|
66
|
+
|
67
|
+
it 'returns false' do
|
68
|
+
expect(subject.valid?).to be false
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'when coordinates are invalid' do
|
73
|
+
let(:coordinate_texts) { invalid_coordinates }
|
74
|
+
|
75
|
+
it 'returns false' do
|
76
|
+
expect(subject.valid?).to be false
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: iiif-presentation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Stroop
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -150,6 +150,20 @@ dependencies:
|
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '2.7'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: geo_coord
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :runtime
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
153
167
|
description: API for working with IIIF Presentation manifests.
|
154
168
|
email:
|
155
169
|
- jpstroop@gmail.com
|
@@ -192,6 +206,7 @@ files:
|
|
192
206
|
- lib/iiif/v3/presentation/collection.rb
|
193
207
|
- lib/iiif/v3/presentation/image_resource.rb
|
194
208
|
- lib/iiif/v3/presentation/manifest.rb
|
209
|
+
- lib/iiif/v3/presentation/nav_place.rb
|
195
210
|
- lib/iiif/v3/presentation/range.rb
|
196
211
|
- lib/iiif/v3/presentation/resource.rb
|
197
212
|
- lib/iiif/v3/presentation/sequence.rb
|
@@ -238,6 +253,7 @@ files:
|
|
238
253
|
- spec/unit/iiif/v3/presentation/collection_spec.rb
|
239
254
|
- spec/unit/iiif/v3/presentation/image_resource_spec.rb
|
240
255
|
- spec/unit/iiif/v3/presentation/manifest_spec.rb
|
256
|
+
- spec/unit/iiif/v3/presentation/nav_place_spec.rb
|
241
257
|
- spec/unit/iiif/v3/presentation/range_spec.rb
|
242
258
|
- spec/unit/iiif/v3/presentation/resource_spec.rb
|
243
259
|
- spec/unit/iiif/v3/presentation/sequence_spec.rb
|
@@ -269,7 +285,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
269
285
|
- !ruby/object:Gem::Version
|
270
286
|
version: '0'
|
271
287
|
requirements: []
|
272
|
-
rubygems_version: 3.4.
|
288
|
+
rubygems_version: 3.4.21
|
273
289
|
signing_key:
|
274
290
|
specification_version: 4
|
275
291
|
summary: API for working with IIIF Presentation manifests.
|
@@ -316,6 +332,7 @@ test_files:
|
|
316
332
|
- spec/unit/iiif/v3/presentation/collection_spec.rb
|
317
333
|
- spec/unit/iiif/v3/presentation/image_resource_spec.rb
|
318
334
|
- spec/unit/iiif/v3/presentation/manifest_spec.rb
|
335
|
+
- spec/unit/iiif/v3/presentation/nav_place_spec.rb
|
319
336
|
- spec/unit/iiif/v3/presentation/range_spec.rb
|
320
337
|
- spec/unit/iiif/v3/presentation/resource_spec.rb
|
321
338
|
- spec/unit/iiif/v3/presentation/sequence_spec.rb
|