tg_geometry 0.1.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 +7 -0
- data/CHANGELOG.md +103 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +385 -0
- data/Rakefile +129 -0
- data/benchmark/_support.rb +115 -0
- data/benchmark/batch_packed_vs_loop.rb +27 -0
- data/benchmark/falcon_concurrency.rb +25 -0
- data/benchmark/flat_vs_rtree.rb +27 -0
- data/benchmark/gvl_threshold.rb +41 -0
- data/benchmark/objectspace_memsize.rb +17 -0
- data/benchmark/parse_throughput.rb +38 -0
- data/benchmark/rss_stability.rb +70 -0
- data/docs/ACTIVE_RECORD.md +26 -0
- data/docs/ARCHITECTURE.md +130 -0
- data/docs/AUTO_STRATEGY.md +15 -0
- data/docs/BENCHMARKING.md +75 -0
- data/docs/CASUAL_EXAMPLE.md +618 -0
- data/docs/CONCURRENCY.md +65 -0
- data/docs/ERROR_HANDLING.md +55 -0
- data/docs/EXPANSION_E_TO_H_STATUS.md +51 -0
- data/docs/FORMAT_COVERAGE.md +23 -0
- data/docs/FULL_TG_API_COVERAGE.md +109 -0
- data/docs/LIMITATIONS.md +61 -0
- data/docs/LOW_LEVEL_GEOMETRY.md +121 -0
- data/docs/MEMORY_OWNERSHIP.md +94 -0
- data/docs/RACTOR.md +40 -0
- data/docs/REGISTRY.md +37 -0
- data/docs/RELEASE_CHECKLIST.md +39 -0
- data/ext/tg_geometry/extconf.rb +91 -0
- data/ext/tg_geometry/tg_geometry_ext.c +3054 -0
- data/ext/tg_geometry/tg_geometry_vendor_rtree.c +1 -0
- data/ext/tg_geometry/tg_geometry_vendor_tg.c +24 -0
- data/ext/tg_geometry/vendor/.vendored +16 -0
- data/ext/tg_geometry/vendor/rtree/LICENSE +20 -0
- data/ext/tg_geometry/vendor/rtree/README.md +202 -0
- data/ext/tg_geometry/vendor/rtree/VERSION +3 -0
- data/ext/tg_geometry/vendor/rtree/rtree.c +840 -0
- data/ext/tg_geometry/vendor/rtree/rtree.h +105 -0
- data/ext/tg_geometry/vendor/tg/LICENSE +19 -0
- data/ext/tg_geometry/vendor/tg/README.md +197 -0
- data/ext/tg_geometry/vendor/tg/VERSION +3 -0
- data/ext/tg_geometry/vendor/tg/tg.c +16010 -0
- data/ext/tg_geometry/vendor/tg/tg.h +359 -0
- data/lib/tg/geometry/active_record_source.rb +57 -0
- data/lib/tg/geometry/registry.rb +119 -0
- data/lib/tg/geometry/version.rb +7 -0
- data/lib/tg/geometry.rb +6 -0
- data/lib/tg_geometry.rb +3 -0
- data/script/vendor_libs.rb +264 -0
- data/spec/block_10_rtree_strategy_spec.rb +82 -0
- data/spec/block_11_rtree_order_spec.rb +53 -0
- data/spec/block_12_batch_packed_spec.rb +55 -0
- data/spec/block_13_error_hardening_spec.rb +65 -0
- data/spec/block_14_memory_gc_hardening_spec.rb +116 -0
- data/spec/block_1_skeleton_spec.rb +45 -0
- data/spec/block_20_concurrency_spec.rb +157 -0
- data/spec/block_20_fuzz_spec.rb +145 -0
- data/spec/block_2_vendor_spec.rb +79 -0
- data/spec/block_3_geom_parse_spec.rb +89 -0
- data/spec/block_4_geom_api_spec.rb +90 -0
- data/spec/block_5_rect_api_spec.rb +96 -0
- data/spec/block_6_index_build_spec.rb +111 -0
- data/spec/block_7_index_owned_geometry_spec.rb +143 -0
- data/spec/block_8_index_borrowed_geometry_spec.rb +106 -0
- data/spec/block_9_flat_query_spec.rb +65 -0
- data/spec/expansion_a_auto_strategy_spec.rb +14 -0
- data/spec/expansion_b_registry_spec.rb +47 -0
- data/spec/expansion_c_active_record_source_spec.rb +42 -0
- data/spec/expansion_d_format_coverage_spec.rb +30 -0
- data/spec/expansion_e_low_level_geometry_spec.rb +82 -0
- data/spec/expansion_i_ractor_spec.rb +25 -0
- data/spec/expansion_j_full_tg_api_coverage_spec.rb +114 -0
- data/spec/spec_helper.rb +15 -0
- metadata +157 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
RSpec.describe "Expansion Block J grouped TG API coverage" do
|
|
6
|
+
it "adds safe point and empty geometry constructors without public allocation" do
|
|
7
|
+
point = TG::Geometry.point_zm(1, 2, 3, 4)
|
|
8
|
+
|
|
9
|
+
expect(point).to be_a(TG::Geometry::Geom)
|
|
10
|
+
expect(point).to be_frozen
|
|
11
|
+
expect(point.type).to eq(:point)
|
|
12
|
+
expect(point.point).to eq([1.0, 2.0])
|
|
13
|
+
expect(point.dims).to eq(4)
|
|
14
|
+
expect(point.has_z?).to be(true)
|
|
15
|
+
expect(point.has_m?).to be(true)
|
|
16
|
+
expect(point.z).to eq(3.0)
|
|
17
|
+
expect(point.m).to eq(4.0)
|
|
18
|
+
expect(point.extra_coords).to eq([])
|
|
19
|
+
expect(point.to_wkt).to eq("POINT(1 2 3 4)")
|
|
20
|
+
|
|
21
|
+
expect(TG::Geometry.point(1, 2).dims).to eq(2)
|
|
22
|
+
expect(TG::Geometry.point_z(1, 2, 3).z).to eq(3.0)
|
|
23
|
+
expect(TG::Geometry.point_m(1, 2, 4).m).to eq(4.0)
|
|
24
|
+
|
|
25
|
+
expect(TG::Geometry.empty_point.to_wkt).to eq("POINT EMPTY")
|
|
26
|
+
expect(TG::Geometry.empty_linestring.to_wkt).to eq("LINESTRING EMPTY")
|
|
27
|
+
expect(TG::Geometry.empty_polygon.to_wkt).to eq("POLYGON EMPTY")
|
|
28
|
+
expect(TG::Geometry.empty_multipoint.to_wkt).to eq("MULTIPOINT EMPTY")
|
|
29
|
+
expect(TG::Geometry.empty_multilinestring.to_wkt).to eq("MULTILINESTRING EMPTY")
|
|
30
|
+
expect(TG::Geometry.empty_multipolygon.to_wkt).to eq("MULTIPOLYGON EMPTY")
|
|
31
|
+
expect(TG::Geometry.empty_geometrycollection.to_wkt).to eq("GEOMETRYCOLLECTION EMPTY")
|
|
32
|
+
|
|
33
|
+
expect { TG::Geometry.point(Float::NAN, 2) }.to raise_error(TG::Geometry::ArgumentError)
|
|
34
|
+
expect { TG::Geometry::Geom.allocate }.to raise_error(TypeError)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "exposes additional TG predicates without changing == semantics" do
|
|
38
|
+
square = TG::Geometry.parse_wkt("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))")
|
|
39
|
+
same_square = TG::Geometry.parse_wkt("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))")
|
|
40
|
+
inner = TG::Geometry.parse_wkt("POINT (5 5)")
|
|
41
|
+
boundary = TG::Geometry.parse_wkt("POINT (0 0)")
|
|
42
|
+
outside = TG::Geometry.parse_wkt("POINT (20 20)")
|
|
43
|
+
|
|
44
|
+
expect(square.equals?(same_square)).to be(true)
|
|
45
|
+
expect(square.covers?(boundary)).to be(true)
|
|
46
|
+
expect(square.contains?(boundary)).to be(false)
|
|
47
|
+
expect(inner.within?(square)).to be(true)
|
|
48
|
+
expect(boundary.covered_by?(square)).to be(true)
|
|
49
|
+
expect(square.disjoint?(outside)).to be(true)
|
|
50
|
+
expect(square.intersects_xy?(5, 5)).to be(true)
|
|
51
|
+
expect(square.intersects_rect?(TG::Geometry::Rect.new(9, 9, 11, 11))).to be(true)
|
|
52
|
+
expect(square.intersects_rect?(20, 20, 21, 21)).to be(false)
|
|
53
|
+
expect(square == same_square).to be(false)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "exposes collection accessors through borrowed immutable Geom wrappers" do
|
|
57
|
+
geom = TG::Geometry.parse_wkt(
|
|
58
|
+
"GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (0 0, 3 4), POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)))"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
expect(geom.type).to eq(:geometrycollection)
|
|
62
|
+
expect(geom.num_geometries).to eq(3)
|
|
63
|
+
expect(geom.geometries.map(&:type)).to eq(%i[point linestring polygon])
|
|
64
|
+
expect(geom.geometry_at(0).point).to eq([1.0, 2.0])
|
|
65
|
+
expect(geom.geometry_at(1).line.length).to eq(5.0)
|
|
66
|
+
expect(geom.geometry_at(2).polygon.exterior_ring.area).to eq(1.0)
|
|
67
|
+
|
|
68
|
+
child = geom.geometry_at(2)
|
|
69
|
+
index = TG::Geometry::Index.build([[:child, child]], via: :geom, strategy: :flat)
|
|
70
|
+
geom = nil
|
|
71
|
+
child = nil
|
|
72
|
+
GC.start
|
|
73
|
+
GC.compact if GC.respond_to?(:compact)
|
|
74
|
+
|
|
75
|
+
expect(index.find_covering(0.5, 0.5)).to eq(:child)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "exposes multipoint, multiline, and multipolygon child accessors" do
|
|
79
|
+
multipoint = TG::Geometry.parse_wkt("MULTIPOINT ((1 2), (3 4))")
|
|
80
|
+
multiline = TG::Geometry.parse_wkt("MULTILINESTRING ((0 0, 3 4), (10 10, 11 11))")
|
|
81
|
+
multipolygon = TG::Geometry.parse_wkt(
|
|
82
|
+
"MULTIPOLYGON (((0 0, 1 0, 1 1, 0 1, 0 0)), ((10 10, 11 10, 11 11, 10 11, 10 10)))"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
expect(multipoint.num_points).to eq(2)
|
|
86
|
+
expect(multipoint.points).to eq([[1.0, 2.0], [3.0, 4.0]])
|
|
87
|
+
expect(multiline.num_lines).to eq(2)
|
|
88
|
+
expect(multiline.lines.map(&:length)).to eq([5.0, Math.sqrt(2)])
|
|
89
|
+
expect(multipolygon.num_polygons).to eq(2)
|
|
90
|
+
expect(multipolygon.polygon_at(1).bbox.center).to eq([10.5, 10.5])
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "exposes value Segment wrappers from Line and Ring" do
|
|
94
|
+
line = TG::Geometry.parse_wkt("LINESTRING (0 0, 3 4, 6 4)").line
|
|
95
|
+
ring = TG::Geometry.parse_wkt("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))").polygon.exterior_ring
|
|
96
|
+
|
|
97
|
+
segment = line.segment_at(0)
|
|
98
|
+
other = line.segment_at(1)
|
|
99
|
+
|
|
100
|
+
expect(segment).to be_a(TG::Geometry::Segment)
|
|
101
|
+
expect(segment).to be_frozen
|
|
102
|
+
expect(segment.a).to eq([0.0, 0.0])
|
|
103
|
+
expect(segment.b).to eq([3.0, 4.0])
|
|
104
|
+
expect(segment.points).to eq([[0.0, 0.0], [3.0, 4.0]])
|
|
105
|
+
expect(segment.bbox.center).to eq([1.5, 2.0])
|
|
106
|
+
expect(segment.intersects?(segment)).to be(true)
|
|
107
|
+
expect(segment.intersects?(other)).to be(true)
|
|
108
|
+
expect(line.segments.size).to eq(2)
|
|
109
|
+
expect(ring.segments.size).to eq(4)
|
|
110
|
+
|
|
111
|
+
expect { TG::Geometry::Segment.allocate }.to raise_error(TypeError)
|
|
112
|
+
expect { line.segment_at(2) }.to raise_error(TG::Geometry::ArgumentError)
|
|
113
|
+
end
|
|
114
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rbconfig"
|
|
4
|
+
|
|
5
|
+
ROOT = File.expand_path("..", __dir__)
|
|
6
|
+
LIB_DIR = File.join(ROOT, "lib")
|
|
7
|
+
EXT_SO = File.join(LIB_DIR, "tg_geometry_ext_geometry_ext.#{RbConfig::CONFIG.fetch("DLEXT")}")
|
|
8
|
+
|
|
9
|
+
unless File.exist?(EXT_SO)
|
|
10
|
+
system(RbConfig.ruby, "-S", "rake", "compile:test", chdir: ROOT) or abort "failed to compile native extension"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
$LOAD_PATH.unshift(LIB_DIR) unless $LOAD_PATH.include?(LIB_DIR)
|
|
14
|
+
|
|
15
|
+
require "tg/geometry"
|
metadata
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: tg_geometry
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Roman Haydarov
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-05-25 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rake
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '13.0'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '13.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rspec
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '3.13'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '3.13'
|
|
41
|
+
description: Defines TG::Geometry with immutable Geom parsing and constructor wrappers,
|
|
42
|
+
expanded geometry predicates and accessors, Rect helpers, Hex/GeoBIN writers, raw
|
|
43
|
+
extra_json access, read-only borrowed Line/Ring/Polygon and GeometryCollection child
|
|
44
|
+
wrappers, value Segment wrappers, Registry reload sugar, optional ActiveRecord source
|
|
45
|
+
helpers, and an immutable geofencing-oriented Index with owned and borrowed geometry
|
|
46
|
+
ingestion, flat/rtree strategies, deterministic ordered id results, exact rtree
|
|
47
|
+
allocation accounting, and native-endian packed point batch queries over vendored
|
|
48
|
+
TG sources. Ractor support is not claimed.
|
|
49
|
+
email:
|
|
50
|
+
- romnhajdarov@gmail.com
|
|
51
|
+
executables: []
|
|
52
|
+
extensions:
|
|
53
|
+
- ext/tg_geometry/extconf.rb
|
|
54
|
+
extra_rdoc_files: []
|
|
55
|
+
files:
|
|
56
|
+
- CHANGELOG.md
|
|
57
|
+
- Gemfile
|
|
58
|
+
- LICENSE.txt
|
|
59
|
+
- README.md
|
|
60
|
+
- Rakefile
|
|
61
|
+
- benchmark/_support.rb
|
|
62
|
+
- benchmark/batch_packed_vs_loop.rb
|
|
63
|
+
- benchmark/falcon_concurrency.rb
|
|
64
|
+
- benchmark/flat_vs_rtree.rb
|
|
65
|
+
- benchmark/gvl_threshold.rb
|
|
66
|
+
- benchmark/objectspace_memsize.rb
|
|
67
|
+
- benchmark/parse_throughput.rb
|
|
68
|
+
- benchmark/rss_stability.rb
|
|
69
|
+
- docs/ACTIVE_RECORD.md
|
|
70
|
+
- docs/ARCHITECTURE.md
|
|
71
|
+
- docs/AUTO_STRATEGY.md
|
|
72
|
+
- docs/BENCHMARKING.md
|
|
73
|
+
- docs/CASUAL_EXAMPLE.md
|
|
74
|
+
- docs/CONCURRENCY.md
|
|
75
|
+
- docs/ERROR_HANDLING.md
|
|
76
|
+
- docs/EXPANSION_E_TO_H_STATUS.md
|
|
77
|
+
- docs/FORMAT_COVERAGE.md
|
|
78
|
+
- docs/FULL_TG_API_COVERAGE.md
|
|
79
|
+
- docs/LIMITATIONS.md
|
|
80
|
+
- docs/LOW_LEVEL_GEOMETRY.md
|
|
81
|
+
- docs/MEMORY_OWNERSHIP.md
|
|
82
|
+
- docs/RACTOR.md
|
|
83
|
+
- docs/REGISTRY.md
|
|
84
|
+
- docs/RELEASE_CHECKLIST.md
|
|
85
|
+
- ext/tg_geometry/extconf.rb
|
|
86
|
+
- ext/tg_geometry/tg_geometry_ext.c
|
|
87
|
+
- ext/tg_geometry/tg_geometry_vendor_rtree.c
|
|
88
|
+
- ext/tg_geometry/tg_geometry_vendor_tg.c
|
|
89
|
+
- ext/tg_geometry/vendor/.vendored
|
|
90
|
+
- ext/tg_geometry/vendor/rtree/LICENSE
|
|
91
|
+
- ext/tg_geometry/vendor/rtree/README.md
|
|
92
|
+
- ext/tg_geometry/vendor/rtree/VERSION
|
|
93
|
+
- ext/tg_geometry/vendor/rtree/rtree.c
|
|
94
|
+
- ext/tg_geometry/vendor/rtree/rtree.h
|
|
95
|
+
- ext/tg_geometry/vendor/tg/LICENSE
|
|
96
|
+
- ext/tg_geometry/vendor/tg/README.md
|
|
97
|
+
- ext/tg_geometry/vendor/tg/VERSION
|
|
98
|
+
- ext/tg_geometry/vendor/tg/tg.c
|
|
99
|
+
- ext/tg_geometry/vendor/tg/tg.h
|
|
100
|
+
- lib/tg/geometry.rb
|
|
101
|
+
- lib/tg/geometry/active_record_source.rb
|
|
102
|
+
- lib/tg/geometry/registry.rb
|
|
103
|
+
- lib/tg/geometry/version.rb
|
|
104
|
+
- lib/tg_geometry.rb
|
|
105
|
+
- script/vendor_libs.rb
|
|
106
|
+
- spec/block_10_rtree_strategy_spec.rb
|
|
107
|
+
- spec/block_11_rtree_order_spec.rb
|
|
108
|
+
- spec/block_12_batch_packed_spec.rb
|
|
109
|
+
- spec/block_13_error_hardening_spec.rb
|
|
110
|
+
- spec/block_14_memory_gc_hardening_spec.rb
|
|
111
|
+
- spec/block_1_skeleton_spec.rb
|
|
112
|
+
- spec/block_20_concurrency_spec.rb
|
|
113
|
+
- spec/block_20_fuzz_spec.rb
|
|
114
|
+
- spec/block_2_vendor_spec.rb
|
|
115
|
+
- spec/block_3_geom_parse_spec.rb
|
|
116
|
+
- spec/block_4_geom_api_spec.rb
|
|
117
|
+
- spec/block_5_rect_api_spec.rb
|
|
118
|
+
- spec/block_6_index_build_spec.rb
|
|
119
|
+
- spec/block_7_index_owned_geometry_spec.rb
|
|
120
|
+
- spec/block_8_index_borrowed_geometry_spec.rb
|
|
121
|
+
- spec/block_9_flat_query_spec.rb
|
|
122
|
+
- spec/expansion_a_auto_strategy_spec.rb
|
|
123
|
+
- spec/expansion_b_registry_spec.rb
|
|
124
|
+
- spec/expansion_c_active_record_source_spec.rb
|
|
125
|
+
- spec/expansion_d_format_coverage_spec.rb
|
|
126
|
+
- spec/expansion_e_low_level_geometry_spec.rb
|
|
127
|
+
- spec/expansion_i_ractor_spec.rb
|
|
128
|
+
- spec/expansion_j_full_tg_api_coverage_spec.rb
|
|
129
|
+
- spec/spec_helper.rb
|
|
130
|
+
homepage: https://github.com/roman-haidarov/tg_geometry
|
|
131
|
+
licenses:
|
|
132
|
+
- MIT
|
|
133
|
+
metadata:
|
|
134
|
+
homepage_uri: https://github.com/roman-haidarov/tg_geometry
|
|
135
|
+
source_code_uri: https://github.com/roman-haidarov/tg_geometry/tree/main
|
|
136
|
+
changelog_uri: https://github.com/roman-haidarov/tg_geometry/blob/main/CHANGELOG.md
|
|
137
|
+
post_install_message:
|
|
138
|
+
rdoc_options: []
|
|
139
|
+
require_paths:
|
|
140
|
+
- lib
|
|
141
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
142
|
+
requirements:
|
|
143
|
+
- - ">="
|
|
144
|
+
- !ruby/object:Gem::Version
|
|
145
|
+
version: '3.0'
|
|
146
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
|
+
requirements:
|
|
148
|
+
- - ">="
|
|
149
|
+
- !ruby/object:Gem::Version
|
|
150
|
+
version: '0'
|
|
151
|
+
requirements: []
|
|
152
|
+
rubygems_version: 3.3.27
|
|
153
|
+
signing_key:
|
|
154
|
+
specification_version: 4
|
|
155
|
+
summary: Native extension for TG::Geometry parsing, predicates, immutable indexes,
|
|
156
|
+
registries, low-level wrappers, and packed point batches
|
|
157
|
+
test_files: []
|