Skip to content

V4.2.1 update #123

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions .github/workflows/ruby_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,21 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
# os: [ubuntu-latest, macos-latest]
os: [macos-latest]
# Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0'
ruby: ['2.7', '3.0', '3.1', '3.2', '3.3']
ruby: ['3.2', '3.3', '3.4']
include:
# - os: ubuntu-latest
# install_h3: git clone https://github.com/uber/h3.git && cd h3 && git checkout v4.2.1 && sudo apt install cmake make gcc libtool && mkdir build && cd build && cmake -DBUILD_SHARED_LIBS=true .. && cmake --build .
- os: macos-latest
install_h3: brew install h3
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- run: ${{ matrix.install_h3 }}
- run: bundle exec rake
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.7.2
3.4.2
44 changes: 35 additions & 9 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,46 +1,72 @@
PATH
remote: .
specs:
h3 (3.7.4)
h3 (4.0.0)
ffi (~> 1.9)
rgeo-geojson (~> 2.1)
zeitwerk (~> 2.5)

GEM
remote: https://rubygems.org/
specs:
diff-lcs (1.5.1)
coderay (1.1.3)
diff-lcs (1.6.1)
ffi (1.17.1)
ffi (1.17.1-aarch64-linux-gnu)
ffi (1.17.1-aarch64-linux-musl)
ffi (1.17.1-arm-linux-gnu)
ffi (1.17.1-arm-linux-musl)
ffi (1.17.1-arm64-darwin)
ffi (1.17.1-x86-linux-gnu)
ffi (1.17.1-x86-linux-musl)
ffi (1.17.1-x86_64-darwin)
ffi (1.17.1-x86_64-linux-gnu)
ffi (1.17.1-x86_64-linux-musl)
method_source (1.1.0)
multi_json (1.15.0)
pry (0.15.2)
coderay (~> 1.1)
method_source (~> 1.0)
rake (13.2.1)
rgeo (3.0.0)
rgeo (3.0.1)
rgeo-geojson (2.2.0)
multi_json (~> 1.15)
rgeo (>= 1.0.0)
rspec (3.13.0)
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
rspec-mocks (~> 3.13.0)
rspec-core (3.13.0)
rspec-core (3.13.3)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.0)
rspec-expectations (3.13.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.0)
rspec-mocks (3.13.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-support (3.13.1)
rspec-support (3.13.2)
yard (0.9.37)
zeitwerk (2.6.18)
zeitwerk (2.7.2)

PLATFORMS
aarch64-linux-gnu
aarch64-linux-musl
arm-linux-gnu
arm-linux-musl
arm64-darwin
ruby
x86-linux-gnu
x86-linux-musl
x86_64-darwin
x86_64-linux-gnu
x86_64-linux-musl

DEPENDENCIES
h3!
pry (~> 0.14)
rake (~> 13.0)
rspec (~> 3.8)
yard (~> 0.9)

BUNDLED WITH
2.2.22
2.6.7
23 changes: 0 additions & 23 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,27 +1,4 @@
require "rspec/core/rake_task"
RSpec::Core::RakeTask.new(:spec)

desc "Build H3 C library"
task :build do
unless File.exist?("ext/h3/src/Makefile")
`git submodule update --init --recursive`
print "Building h3..."
`cd ext/h3; make > /dev/null 2>&1`
puts " done."
end
end

desc "Remove compiled H3 library"
task :clean do
File.delete("ext/h3/src/Makefile") if File.exist?("ext/h3/src/Makefile")
FileUtils.remove_dir("ext/h3/src/bin") if Dir.exist?("ext/h3/src/bin")
FileUtils.remove_dir("ext/h3/src/generated") if Dir.exist?("ext/h3/src/generated")
FileUtils.remove_dir("ext/h3/src/lib") if Dir.exist?("ext/h3/src/lib")
end

task spec: :build

desc "Recompile the H3 C library"
task rebuild: %i[clean build]

task default: :spec
2 changes: 1 addition & 1 deletion ext/h3/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ make:
install:
: # do nothing, we'll load the lib directly
clean:
: # do nothing, cleanup happens when gem uninstalled
rm -rf build
2 changes: 0 additions & 2 deletions ext/h3/extconf.rb

This file was deleted.

1 change: 0 additions & 1 deletion ext/h3/src
Submodule src deleted from 26a640
3 changes: 2 additions & 1 deletion h3.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Gem::Specification.new do |spec|
spec.version = H3::VERSION
spec.licenses = ["MIT"]
spec.summary = "C Bindings for Uber's H3 library"

spec.homepage = "https://github.com/seanhandley/h3_ruby"
spec.authors = ["Sean Handley", "Xavier Noria", "Lachlan Laycock"]
spec.email = "sean.handley@gmail.com"
Expand All @@ -20,6 +21,6 @@ Gem::Specification.new do |spec|
spec.add_development_dependency "rake", "~> 13.0"
spec.add_development_dependency "rspec", "~> 3.8"
spec.add_development_dependency "yard", "~> 0.9"
spec.add_development_dependency "pry", "~> 0.14"

spec.extensions << "ext/h3/extconf.rb"
end
4 changes: 2 additions & 2 deletions lib/h3/bindings/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ module Bindings
# When extended, this module sets up FFI to use the H3 C library.
module Base
def self.extended(base)
lib_path = File.expand_path(__dir__ + "/../../../ext/h3/src/lib")
base.extend FFI::Library
base.extend Gem::Deprecate
base.include Structs
base.include Types
base.ffi_lib ["#{lib_path}/libh3.dylib", "#{lib_path}/libh3.so"]
base.ffi_lib ["libh3.dylib", "libh3.so"]
base.typedef :ulong_long, :h3_index
base.typedef :int, :k_distance
base.typedef :uint, :h3_error_code
end

def attach_predicate_function(name, *args)
Expand Down
39 changes: 39 additions & 0 deletions lib/h3/bindings/error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module H3
module Bindings
module Error
class FailedError < StandardError ; end
class DomainError < StandardError ; end
class LatLngDomainError < StandardError ; end
class ResolutionDomainError < StandardError ; end
class CellInvalidError < StandardError ; end
class DirectedEdgeInvalidError < StandardError ; end
class UndirectedEdgeInvalidError < StandardError ; end
class VertexInvalidError < StandardError ; end
class PentagonDistortionError < StandardError ; end
class DuplicateInputError < StandardError ; end
class NotNeighborsError < StandardError ; end
class ResolutionMismatchError < StandardError ; end
class MemoryAllocationError < StandardError ; end
class MemoryBoundsError < StandardError ; end

def self.raise_error(code)
case code
when 1 then raise FailedError
when 2 then raise DomainError
when 3 then raise LatLngDomainError
when 4 then raise ResolutionDomainError
when 5 then raise CellInvalidError
when 6 then raise DirectedEdgeInvalidError
when 7 then raise UndirectedEdgeInvalidError
when 8 then raise VertexInvalidError
when 9 then raise PentagonDistortionError
when 10 then raise DuplicateInputError
when 11 then raise NotNeighborsError
when 12 then raise ResolutionMismatchError
when 13 then raise MemoryAllocationError
when 14 then raise MemoryBoundsError
end
end
end
end
end
111 changes: 58 additions & 53 deletions lib/h3/bindings/private.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,58 +7,63 @@ module Bindings
module Private
extend H3::Bindings::Base

attach_function :compact, [H3IndexesIn, H3IndexesOut, :size_t], :bool
attach_function :destroy_linked_polygon, :destroyLinkedPolygon, [LinkedGeoPolygon], :void
attach_function :geo_to_h3, :geoToH3, [GeoCoord, Resolution], :h3_index
attach_function :get_pentagon_indexes, :getPentagonIndexes, [:int, H3IndexesOut], :void
attach_function :h3_faces, :h3GetFaces, %i[h3_index buffer_out], :void
attach_function :h3_indexes_from_unidirectional_edge,
:getH3IndexesFromUnidirectionalEdge,
[:h3_index, H3IndexesOut], :void
attach_function :h3_line, :h3Line, [:h3_index, :h3_index, H3IndexesOut], :int
attach_function :h3_unidirectional_edges_from_hexagon,
:getH3UnidirectionalEdgesFromHexagon,
[:h3_index, H3IndexesOut], :void
attach_function :h3_set_to_linked_geo,
:h3SetToLinkedGeo,
[H3IndexesIn, :size_t, LinkedGeoPolygon],
:void
attach_function :h3_to_children, :h3ToChildren, [:h3_index, Resolution, H3IndexesOut], :void
attach_function :h3_to_geo, :h3ToGeo, [:h3_index, GeoCoord], :void
attach_function :h3_to_string, :h3ToString, %i[h3_index buffer_out size_t], :void
attach_function :h3_to_geo_boundary,
:h3ToGeoBoundary,
[:h3_index, GeoBoundary],
:void
attach_function :h3_unidirectional_edge_boundary,
:getH3UnidirectionalEdgeBoundary,
[:h3_index, GeoBoundary], :void
attach_function :hex_range, :hexRange, [:h3_index, :k_distance, H3IndexesOut], :bool
attach_function :hex_range_distances,
:hexRangeDistances,
[:h3_index, :k_distance, H3IndexesOut, :buffer_out], :bool
attach_function :hex_ranges,
:hexRanges,
[H3IndexesIn, :size_t, :k_distance, H3IndexesOut],
:bool
attach_function :hex_ring, :hexRing, [:h3_index, :k_distance, H3IndexesOut], :bool
attach_function :k_ring, :kRing, [:h3_index, :k_distance, H3IndexesOut], :void
attach_function :k_ring_distances,
:kRingDistances,
[:h3_index, :k_distance, H3IndexesOut, :buffer_out],
:bool
attach_function :max_polyfill_size,
:maxPolyfillSize,
[GeoPolygon, Resolution],
:int
attach_function :max_uncompact_size, :maxUncompactSize, [H3IndexesIn, :size_t, Resolution], :int
attach_function :point_distance_rads, :pointDistRads, [GeoCoord, GeoCoord], :double
attach_function :point_distance_km, :pointDistKm, [GeoCoord, GeoCoord], :double
attach_function :point_distance_m, :pointDistM, [GeoCoord, GeoCoord], :double
attach_function :polyfill, [GeoPolygon, Resolution, H3IndexesOut], :void
attach_function :res_0_indexes, :getRes0Indexes, [H3IndexesOut], :void
attach_function :string_to_h3, :stringToH3, %i[string], :h3_index
attach_function :uncompact, [H3IndexesIn, :size_t, H3IndexesOut, :size_t, Resolution], :bool
def self.safe_call(out_type, method, *in_args)
out = FFI::MemoryPointer.new(out_type)
send(method, *in_args + [out]).tap do |code|
Error::raise_error(code) unless code.zero?
end
out.send("read_#{out_type}".to_sym)
end

# Hierarchy functions
attach_function :cellToParent, [:h3_index, Resolution, H3Index], :h3_error_code
attach_function :compactCells, [H3IndexesIn, H3IndexesOut, :int64], :h3_error_code
attach_function :h3_to_children, :cellToChildren, [:h3_index, Resolution, H3IndexesOut], :h3_error_code
attach_function :max_children, :cellToChildrenSize, [:h3_index, Resolution, :pointer], :h3_error_code
attach_function :max_uncompact_size, :uncompactCellsSize, [H3IndexesIn, :int64, Resolution, :pointer], :h3_error_code
attach_function :uncompactCells, [H3IndexesIn, :size_t, H3IndexesOut, :size_t, Resolution], :h3_error_code

# Indexing functions
attach_function :from_string, :stringToH3, %i[string pointer], :h3_error_code
attach_function :geo_to_h3, :latLngToCell, [LatLng, Resolution, :pointer], :h3_error_code
attach_function :h3_to_geo, :cellToLatLng, [:h3_index, LatLng], :h3_error_code
attach_function :h3_to_string, :h3ToString, %i[h3_index buffer_out size_t], :h3_error_code
attach_function :h3_to_geo_boundary, :cellToBoundary, [:h3_index, CellBoundary], :h3_error_code

# Traversal functions
attach_function :k_ring, :gridDisk, [:h3_index, :k_distance, H3IndexesOut], :h3_error_code
attach_function :k_ring_distances, :gridDiskDistances, [:h3_index, :k_distance, H3IndexesOut, :pointer], :h3_error_code
attach_function :hex_range, :gridDiskUnsafe, [:h3_index, :k_distance, H3IndexesOut], :h3_error_code
attach_function :hex_range_distances, :gridDiskDistancesUnsafe, [:h3_index, :k_distance, H3IndexesOut, :pointer], :h3_error_code
attach_function :hex_ranges, :gridDisksUnsafe, [H3IndexesIn, :size_t, :k_distance, H3IndexesOut], :h3_error_code
attach_function :hex_ring, :gridRingUnsafe, [:h3_index, :k_distance, H3IndexesOut], :h3_error_code
attach_function :h3_line, :gridPathCells, [:h3_index, :h3_index, H3IndexesOut], :h3_error_code
attach_function :max_kring_size, :maxGridDiskSize, [:k_distance, :pointer], :h3_error_code

# Directed edge functions (formerly unidirectional_edge)
attach_function :h3_indexes_from_unidirectional_edge, :directedEdgeToCells, [:h3_index, H3IndexesOut], :h3_error_code
attach_function :h3_unidirectional_edges_from_hexagon, :originToDirectedEdges, [:h3_index, H3IndexesOut], :h3_error_code
attach_function :h3_unidirectional_edge_boundary, :directedEdgeToBoundary, [:h3_index, CellBoundary], :h3_error_code

# Miscellaneous functions
attach_function :hexagon_count, :getNumCells, [Resolution, :pointer], :h3_error_code
attach_function :edge_length_km, :getHexagonEdgeLengthAvgKm, [Resolution, :pointer], :h3_error_code
attach_function :edge_length_m, :getHexagonEdgeLengthAvgM, [Resolution, :pointer], :h3_error_code
attach_function :h3_faces, :getIcosahedronFaces, %i[h3_index buffer_out], :h3_error_code
attach_function :max_face_count, :maxFaceCount, %i[h3_index pointer], :h3_error_code
attach_function :get_pentagon_indexes, :getPentagons, [:int, H3IndexesOut], :h3_error_code
attach_function :res_0_indexes, :getRes0Cells, [H3IndexesOut], :h3_error_code

# Distance functions
attach_function :point_distance_rads, :greatCircleDistanceRads, [LatLng, LatLng], :double
attach_function :point_distance_km, :greatCircleDistanceKm, [LatLng, LatLng], :double
attach_function :point_distance_m, :greatCircleDistanceM, [LatLng, LatLng], :double

# Region functions
attach_function :destroy_linked_polygon, :destroyLinkedMultiPolygon, [LinkedGeoPolygon], :void
attach_function :h3_set_to_linked_geo, :cellsToLinkedMultiPolygon, [H3IndexesIn, :size_t, LinkedGeoPolygon], :h3_error_code
attach_function :max_polyfill_size, :maxPolygonToCellsSize, [GeoPolygon, Resolution, :pointer], :h3_error_code
attach_function :polyfill, :polygonToCells, [GeoPolygon, Resolution, H3IndexesOut], :h3_error_code
end
end
end
end
8 changes: 4 additions & 4 deletions lib/h3/bindings/structs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ module Bindings
module Structs
extend FFI::Library

class GeoCoord < FFI::Struct
class LatLng < FFI::Struct
layout :lat, :double,
:lon, :double
end

class GeoBoundary < FFI::Struct
class CellBoundary < FFI::Struct
layout :num_verts, :int,
:verts, [GeoCoord, 10] # array of GeoCoord structs (must be fixed length)
:verts, [LatLng, 10] # array of GeoCoord structs (must be fixed length)
end

class GeoFence < FFI::Struct
Expand All @@ -34,7 +34,7 @@ class GeoMultiPolygon < FFI::Struct
end

class LinkedGeoCoord < FFI::Struct
layout :vertex, GeoCoord,
layout :vertex, LatLng,
:next, LinkedGeoCoord.ptr
end

Expand Down
19 changes: 18 additions & 1 deletion lib/h3/bindings/types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,29 @@ def to_native(value, _context)
private

def failure
raise ArgumentError,
raise Error::ResolutionDomainError,
"resolution must be between #{RES_RANGE.first} and #{RES_RANGE.last}"
end
end
end

class H3Index
extend FFI::DataConverter
native_type FFI::Type::POINTER

def initialize(value)
ptr.write(value)
end

def size
FFI.type_size(FFI::Type::ULONG_LONG)
end

def ptr
@ptr ||= FFI::MemoryPointer.new(:ulong_long)
end
end

class H3IndexesIn
extend FFI::DataConverter
native_type FFI::Type::POINTER
Expand Down
Loading