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.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +103 -0
  3. data/Gemfile +3 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +385 -0
  6. data/Rakefile +129 -0
  7. data/benchmark/_support.rb +115 -0
  8. data/benchmark/batch_packed_vs_loop.rb +27 -0
  9. data/benchmark/falcon_concurrency.rb +25 -0
  10. data/benchmark/flat_vs_rtree.rb +27 -0
  11. data/benchmark/gvl_threshold.rb +41 -0
  12. data/benchmark/objectspace_memsize.rb +17 -0
  13. data/benchmark/parse_throughput.rb +38 -0
  14. data/benchmark/rss_stability.rb +70 -0
  15. data/docs/ACTIVE_RECORD.md +26 -0
  16. data/docs/ARCHITECTURE.md +130 -0
  17. data/docs/AUTO_STRATEGY.md +15 -0
  18. data/docs/BENCHMARKING.md +75 -0
  19. data/docs/CASUAL_EXAMPLE.md +618 -0
  20. data/docs/CONCURRENCY.md +65 -0
  21. data/docs/ERROR_HANDLING.md +55 -0
  22. data/docs/EXPANSION_E_TO_H_STATUS.md +51 -0
  23. data/docs/FORMAT_COVERAGE.md +23 -0
  24. data/docs/FULL_TG_API_COVERAGE.md +109 -0
  25. data/docs/LIMITATIONS.md +61 -0
  26. data/docs/LOW_LEVEL_GEOMETRY.md +121 -0
  27. data/docs/MEMORY_OWNERSHIP.md +94 -0
  28. data/docs/RACTOR.md +40 -0
  29. data/docs/REGISTRY.md +37 -0
  30. data/docs/RELEASE_CHECKLIST.md +39 -0
  31. data/ext/tg_geometry/extconf.rb +91 -0
  32. data/ext/tg_geometry/tg_geometry_ext.c +3054 -0
  33. data/ext/tg_geometry/tg_geometry_vendor_rtree.c +1 -0
  34. data/ext/tg_geometry/tg_geometry_vendor_tg.c +24 -0
  35. data/ext/tg_geometry/vendor/.vendored +16 -0
  36. data/ext/tg_geometry/vendor/rtree/LICENSE +20 -0
  37. data/ext/tg_geometry/vendor/rtree/README.md +202 -0
  38. data/ext/tg_geometry/vendor/rtree/VERSION +3 -0
  39. data/ext/tg_geometry/vendor/rtree/rtree.c +840 -0
  40. data/ext/tg_geometry/vendor/rtree/rtree.h +105 -0
  41. data/ext/tg_geometry/vendor/tg/LICENSE +19 -0
  42. data/ext/tg_geometry/vendor/tg/README.md +197 -0
  43. data/ext/tg_geometry/vendor/tg/VERSION +3 -0
  44. data/ext/tg_geometry/vendor/tg/tg.c +16010 -0
  45. data/ext/tg_geometry/vendor/tg/tg.h +359 -0
  46. data/lib/tg/geometry/active_record_source.rb +57 -0
  47. data/lib/tg/geometry/registry.rb +119 -0
  48. data/lib/tg/geometry/version.rb +7 -0
  49. data/lib/tg/geometry.rb +6 -0
  50. data/lib/tg_geometry.rb +3 -0
  51. data/script/vendor_libs.rb +264 -0
  52. data/spec/block_10_rtree_strategy_spec.rb +82 -0
  53. data/spec/block_11_rtree_order_spec.rb +53 -0
  54. data/spec/block_12_batch_packed_spec.rb +55 -0
  55. data/spec/block_13_error_hardening_spec.rb +65 -0
  56. data/spec/block_14_memory_gc_hardening_spec.rb +116 -0
  57. data/spec/block_1_skeleton_spec.rb +45 -0
  58. data/spec/block_20_concurrency_spec.rb +157 -0
  59. data/spec/block_20_fuzz_spec.rb +145 -0
  60. data/spec/block_2_vendor_spec.rb +79 -0
  61. data/spec/block_3_geom_parse_spec.rb +89 -0
  62. data/spec/block_4_geom_api_spec.rb +90 -0
  63. data/spec/block_5_rect_api_spec.rb +96 -0
  64. data/spec/block_6_index_build_spec.rb +111 -0
  65. data/spec/block_7_index_owned_geometry_spec.rb +143 -0
  66. data/spec/block_8_index_borrowed_geometry_spec.rb +106 -0
  67. data/spec/block_9_flat_query_spec.rb +65 -0
  68. data/spec/expansion_a_auto_strategy_spec.rb +14 -0
  69. data/spec/expansion_b_registry_spec.rb +47 -0
  70. data/spec/expansion_c_active_record_source_spec.rb +42 -0
  71. data/spec/expansion_d_format_coverage_spec.rb +30 -0
  72. data/spec/expansion_e_low_level_geometry_spec.rb +82 -0
  73. data/spec/expansion_i_ractor_spec.rb +25 -0
  74. data/spec/expansion_j_full_tg_api_coverage_spec.rb +114 -0
  75. data/spec/spec_helper.rb +15 -0
  76. 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
@@ -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: []