Skip to content

Commit

Permalink
Merge pull request #821 from sul-dlss/move-nav-place-to-gem
Browse files Browse the repository at this point in the history
Use navPlace from iiif-presentation gem
  • Loading branch information
justinlittman authored Dec 1, 2023
2 parents 4b6473c + 85e6ffd commit 5222bae
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 103 deletions.
3 changes: 1 addition & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ gem 'cancancan' # authorization
gem 'config' # simple rails environment specific config
gem "cssbundling-rails", "~> 1.1"
gem 'faraday' # HTTP client
gem "geo_coord", require: "geo/coord"
gem 'honeybadger' # exception reporting
gem 'htmlentities'
gem "importmap-rails" # Use JavaScript with ESM import maps
Expand All @@ -32,7 +31,7 @@ gem 'whenever', require: false # cron jobs

# DLSS and its community
gem 'dor-rights-auth', '~> 1.6'
gem 'iiif-presentation', '~> 1.2'
gem 'iiif-presentation', '~> 1.3'
gem 'mods_display', '~> 1.4'

group :production do
Expand Down
8 changes: 4 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ GEM
edtf (3.1.1)
activesupport (>= 3.0, < 8.0)
erubi (1.12.0)
faraday (2.7.11)
faraday (2.7.12)
base64
faraday-net_http (>= 2.0, < 3.1)
ruby2_keywords (>= 0.0.4)
Expand All @@ -193,9 +193,10 @@ GEM
htmlentities (4.3.4)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
iiif-presentation (1.2.0)
iiif-presentation (1.3.0)
activesupport (>= 3.2.18)
faraday (~> 2.7)
geo_coord
json
importmap-rails (1.2.3)
actionpack (>= 6.0.0)
Expand Down Expand Up @@ -453,10 +454,9 @@ DEPENDENCIES
dlss-capistrano
dor-rights-auth (~> 1.6)
faraday
geo_coord
honeybadger
htmlentities
iiif-presentation (~> 1.2)
iiif-presentation (~> 1.3)
importmap-rails
jbuilder
jsonpath
Expand Down
104 changes: 7 additions & 97 deletions app/models/iiif3_presentation_manifest.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
require 'iiif/presentation'
require 'iiif/v3/presentation'
require 'geo/coord'

class Iiif3PresentationManifest < IiifPresentationManifest
delegate :reading_order, to: :content_metadata
Expand Down Expand Up @@ -347,103 +346,14 @@ def annotation_page_url(**kwargs)
end

def nav_place
@nav_place ||= NavPlace.new(public_xml_document:, purl_base_uri:).build
end

class NavPlace
Rect = Struct.new(:coord1, :coord2)

def initialize(public_xml_document:, purl_base_uri:)
@public_xml_document = public_xml_document
@purl_base_uri = purl_base_uri
end

def build
return if coordinates.blank?

{
id: "#{purl_base_uri}/feature-collection/1",
type: 'FeatureCollection',
features:
}
end

private

attr_reader :public_xml_document, :purl_base_uri

def coordinates
@coordinates ||= coordinate_texts.map do |coordinate_text|
coordinate_parts = coordinate_text.split(%r{ ?--|/})
case coordinate_parts.length
when 2
coord_for(coordinate_parts[0], coordinate_parts[1])
when 4
rect_for(coordinate_parts)
end
end.compact
end

def coordinate_texts
public_xml_document.xpath('//mods:subject/mods:cartographics/mods:coordinates', 'mods' => IiifPresentationManifest::MODS_SCHEMA).map(&:text)
end

COORD_REGEX = /(?<hemisphere>[NSEW]) (?<degrees>\d+)[°⁰*] ?(?<minutes>\d+)?[ʹ']? ?(?<seconds>\d+)?[ʺ"]?/

def coord_for(long_str, lat_str)
long_matcher = long_str.match(COORD_REGEX)
lat_matcher = lat_str.match(COORD_REGEX)
return unless long_matcher && lat_matcher

Geo::Coord.new(latd: lat_matcher[:degrees], latm: lat_matcher[:minutes], lats: lat_matcher[:seconds], lath: lat_matcher[:hemisphere],
lngd: long_matcher[:degrees], lngm: long_matcher[:minutes], lngs: long_matcher[:seconds], lngh: long_matcher[:hemisphere])
end

def rect_for(coordinate_parts)
coord1 = coord_for(coordinate_parts[0], coordinate_parts[2])
coord2 = coord_for(coordinate_parts[1], coordinate_parts[3])
return if coord1.nil? || coord2.nil?

Rect.new(coord1, coord2)
@nav_place ||= begin
nav_place = IIIF::V3::Presentation::NavPlace.new(coordinate_texts:, base_uri: purl_base_uri)
nav_place.valid? ? nav_place.build : nil # if coordinates are invalid, do nothing, else return navPlace element
end
end

def features
coordinates.map.with_index do |coordinate, index|
{
id: "#{purl_base_uri}/iiif/feature/#{index + 1}",
type: 'Feature',
properties: {},
geometry: coordinate.is_a?(Rect) ? polygon_geometry(coordinate) : point_geometry(coordinate)
}
end
end

def point_geometry(coord)
{
type: 'Point',
coordinates: [format(coord.lng), format(coord.lat)]
}
end

# rubocop:disable Metrics/AbcSize
def polygon_geometry(rect)
{
type: 'Polygon',
coordinates: [
[
[format(rect.coord1.lng), format(rect.coord1.lat)],
[format(rect.coord2.lng), format(rect.coord1.lat)],
[format(rect.coord2.lng), format(rect.coord2.lat)],
[format(rect.coord1.lng), format(rect.coord2.lat)],
[format(rect.coord1.lng), format(rect.coord1.lat)]
]
]
}
end
# rubocop:enable Metrics/AbcSize

def format(decimal)
decimal.truncate(6).to_s
end
def coordinate_texts
@coordinate_texts ||= public_xml_document.xpath('//mods:subject/mods:cartographics/mods:coordinates',
'mods' => IiifPresentationManifest::MODS_SCHEMA).map(&:text)
end
end

0 comments on commit 5222bae

Please sign in to comment.