rgeo 1.1.2 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +144 -0
  3. data/ext/geos_c_impl/analysis.c +78 -0
  4. data/ext/geos_c_impl/analysis.h +42 -0
  5. data/ext/geos_c_impl/errors.c +35 -0
  6. data/ext/geos_c_impl/errors.h +22 -0
  7. data/ext/geos_c_impl/extconf.rb +6 -3
  8. data/ext/geos_c_impl/factory.c +14 -5
  9. data/ext/geos_c_impl/factory.h +5 -1
  10. data/ext/geos_c_impl/geometry.c +20 -2
  11. data/ext/geos_c_impl/geometry_collection.c +0 -17
  12. data/ext/geos_c_impl/main.c +5 -2
  13. data/ext/geos_c_impl/preface.h +3 -0
  14. data/lib/rgeo.rb +11 -13
  15. data/lib/rgeo/cartesian.rb +13 -23
  16. data/lib/rgeo/cartesian/analysis.rb +44 -20
  17. data/lib/rgeo/cartesian/bounding_box.rb +83 -79
  18. data/lib/rgeo/cartesian/calculations.rb +40 -38
  19. data/lib/rgeo/cartesian/factory.rb +134 -169
  20. data/lib/rgeo/cartesian/feature_classes.rb +2 -18
  21. data/lib/rgeo/cartesian/feature_methods.rb +37 -39
  22. data/lib/rgeo/cartesian/interface.rb +11 -9
  23. data/lib/rgeo/coord_sys.rb +9 -8
  24. data/lib/rgeo/coord_sys/cs/entities.rb +345 -303
  25. data/lib/rgeo/coord_sys/cs/factories.rb +30 -28
  26. data/lib/rgeo/coord_sys/cs/wkt_parser.rb +128 -126
  27. data/lib/rgeo/coord_sys/srs_database/{interface.rb → entry.rb} +26 -32
  28. data/lib/rgeo/coord_sys/srs_database/sr_org.rb +19 -17
  29. data/lib/rgeo/coord_sys/srs_database/url_reader.rb +21 -19
  30. data/lib/rgeo/error.rb +7 -1
  31. data/lib/rgeo/feature.rb +40 -51
  32. data/lib/rgeo/feature/curve.rb +2 -0
  33. data/lib/rgeo/feature/factory.rb +15 -13
  34. data/lib/rgeo/feature/factory_generator.rb +7 -5
  35. data/lib/rgeo/feature/geometry.rb +31 -29
  36. data/lib/rgeo/feature/geometry_collection.rb +6 -4
  37. data/lib/rgeo/feature/line.rb +2 -0
  38. data/lib/rgeo/feature/line_string.rb +3 -1
  39. data/lib/rgeo/feature/linear_ring.rb +12 -0
  40. data/lib/rgeo/feature/multi_curve.rb +2 -0
  41. data/lib/rgeo/feature/multi_line_string.rb +2 -0
  42. data/lib/rgeo/feature/multi_point.rb +2 -0
  43. data/lib/rgeo/feature/multi_polygon.rb +2 -0
  44. data/lib/rgeo/feature/multi_surface.rb +2 -0
  45. data/lib/rgeo/feature/point.rb +2 -0
  46. data/lib/rgeo/feature/polygon.rb +3 -1
  47. data/lib/rgeo/feature/surface.rb +2 -0
  48. data/lib/rgeo/feature/types.rb +107 -103
  49. data/lib/rgeo/geographic.rb +27 -37
  50. data/lib/rgeo/geographic/factory.rb +154 -199
  51. data/lib/rgeo/geographic/interface.rb +141 -137
  52. data/lib/rgeo/geographic/proj4_projector.rb +28 -23
  53. data/lib/rgeo/geographic/projected_feature_classes.rb +2 -18
  54. data/lib/rgeo/geographic/projected_feature_methods.rb +64 -54
  55. data/lib/rgeo/geographic/projected_window.rb +4 -2
  56. data/lib/rgeo/geographic/simple_mercator_projector.rb +41 -39
  57. data/lib/rgeo/geographic/spherical_feature_classes.rb +3 -18
  58. data/lib/rgeo/geographic/spherical_feature_methods.rb +90 -67
  59. data/lib/rgeo/geographic/spherical_math.rb +81 -87
  60. data/lib/rgeo/geos.rb +40 -53
  61. data/lib/rgeo/geos/capi_factory.rb +111 -136
  62. data/lib/rgeo/geos/capi_feature_classes.rb +22 -36
  63. data/lib/rgeo/geos/ffi_factory.rb +276 -297
  64. data/lib/rgeo/geos/ffi_feature_classes.rb +2 -20
  65. data/lib/rgeo/geos/ffi_feature_methods.rb +177 -169
  66. data/lib/rgeo/geos/interface.rb +25 -23
  67. data/lib/rgeo/geos/utils.rb +47 -39
  68. data/lib/rgeo/geos/zm_factory.rb +171 -185
  69. data/lib/rgeo/geos/zm_feature_classes.rb +2 -20
  70. data/lib/rgeo/geos/zm_feature_methods.rb +76 -72
  71. data/lib/rgeo/impl_helper.rb +8 -18
  72. data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +84 -75
  73. data/lib/rgeo/impl_helper/basic_geometry_methods.rb +21 -23
  74. data/lib/rgeo/impl_helper/basic_line_string_methods.rb +95 -48
  75. data/lib/rgeo/impl_helper/basic_point_methods.rb +29 -25
  76. data/lib/rgeo/impl_helper/basic_polygon_methods.rb +68 -27
  77. data/lib/rgeo/impl_helper/math.rb +2 -0
  78. data/lib/rgeo/impl_helper/utils.rb +9 -15
  79. data/lib/rgeo/version.rb +3 -1
  80. data/lib/rgeo/wkrep.rb +24 -34
  81. data/lib/rgeo/wkrep/wkb_generator.rb +87 -84
  82. data/lib/rgeo/wkrep/wkb_parser.rb +93 -93
  83. data/lib/rgeo/wkrep/wkt_generator.rb +67 -63
  84. data/lib/rgeo/wkrep/wkt_parser.rb +172 -168
  85. metadata +30 -36
  86. data/lib/rgeo/feature/mixins.rb +0 -143
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # -----------------------------------------------------------------------------
2
4
  #
3
5
  # Core calculations on the sphere
@@ -21,11 +23,11 @@ module RGeo
21
23
  # of rotation.
22
24
 
23
25
  class PointXYZ # :nodoc:
24
- def initialize(x_, y_, z_)
25
- r_ = ::Math.sqrt(x_ * x_ + y_ * y_ + z_ * z_)
26
- @x = (x_ / r_).to_f
27
- @y = (y_ / r_).to_f
28
- @z = (z_ / r_).to_f
26
+ def initialize(x, y, z)
27
+ r = Math.sqrt(x * x + y * y + z * z)
28
+ @x = (x / r).to_f
29
+ @y = (y / r).to_f
30
+ @z = (z / r).to_f
29
31
  raise "Not a number" if @x.nan? || @y.nan? || @z.nan?
30
32
  end
31
33
 
@@ -37,90 +39,82 @@ module RGeo
37
39
  attr_reader :y
38
40
  attr_reader :z
39
41
 
40
- def eql?(rhs_)
41
- rhs_.is_a?(PointXYZ) && @x == rhs_.x && @y == rhs_.y && @z == rhs_.z
42
+ def eql?(rhs)
43
+ rhs.is_a?(PointXYZ) && @x == rhs.x && @y == rhs.y && @z == rhs.z
42
44
  end
43
45
  alias == eql?
44
46
 
45
47
  def latlon
46
- lat_rad_ = ::Math.asin(@z)
47
- lon_rad_ = begin
48
- ::Math.atan2(@y, @x)
49
- rescue
50
- 0.0
51
- end
52
- rpd_ = ImplHelper::Math::RADIANS_PER_DEGREE
53
- [lat_rad_ / rpd_, lon_rad_ / rpd_]
48
+ lat_rad = Math.asin(@z)
49
+ lon_rad = Math.atan2(@y, @x)
50
+ rpd = ImplHelper::Math::RADIANS_PER_DEGREE
51
+ [lat_rad / rpd, lon_rad / rpd]
54
52
  end
55
53
 
56
54
  def lonlat
57
- lat_rad_ = ::Math.asin(@z)
58
- lon_rad_ = begin
59
- ::Math.atan2(@y, @x)
60
- rescue
61
- 0.0
62
- end
63
- rpd_ = ImplHelper::Math::RADIANS_PER_DEGREE
64
- [lon_rad_ / rpd_, lat_rad_ / rpd_]
65
- end
66
-
67
- def *(rhs_)
68
- val_ = @x * rhs_.x + @y * rhs_.y + @z * rhs_.z
69
- val_ = 1.0 if val_ > 1.0
70
- val_ = -1.0 if val_ < -1.0
71
- val_
72
- end
73
-
74
- def %(rhs_)
75
- rx_ = rhs_.x
76
- ry_ = rhs_.y
77
- rz_ = rhs_.z
55
+ lat_rad = Math.asin(@z)
56
+ lon_rad = Math.atan2(@y, @x)
57
+ rpd = ImplHelper::Math::RADIANS_PER_DEGREE
58
+ [lon_rad / rpd, lat_rad / rpd]
59
+ end
60
+
61
+ def *(rhs)
62
+ val = @x * rhs.x + @y * rhs.y + @z * rhs.z
63
+ val = 1.0 if val > 1.0
64
+ val = -1.0 if val < -1.0
65
+ val
66
+ end
67
+
68
+ def %(rhs)
69
+ rx = rhs.x
70
+ ry = rhs.y
71
+ rz = rhs.z
78
72
  begin
79
- PointXYZ.new(@y * rz_ - @z * ry_, @z * rx_ - @x * rz_, @x * ry_ - @y * rx_)
80
- rescue
73
+ PointXYZ.new(@y * rz - @z * ry, @z * rx - @x * rz, @x * ry - @y * rx)
74
+ rescue StandardError
81
75
  nil
82
76
  end
83
77
  end
84
78
 
85
- def dist_to_point(rhs_)
86
- rx_ = rhs_.x
87
- ry_ = rhs_.y
88
- rz_ = rhs_.z
89
- dot_ = @x * rx_ + @y * ry_ + @z * rz_
90
- if dot_ > -0.8 && dot_ < 0.8
91
- ::Math.acos(dot_)
79
+ def dist_to_point(rhs)
80
+ rx = rhs.x
81
+ ry = rhs.y
82
+ rz = rhs.z
83
+ dot = @x * rx + @y * ry + @z * rz
84
+ if dot > -0.8 && dot < 0.8
85
+ Math.acos(dot)
92
86
  else
93
- x_ = @y * rz_ - @z * ry_
94
- y_ = @z * rx_ - @x * rz_
95
- z_ = @x * ry_ - @y * rx_
96
- as_ = ::Math.asin(::Math.sqrt(x_ * x_ + y_ * y_ + z_ * z_))
97
- dot_ > 0.0 ? as_ : ::Math::PI - as_
87
+ x = @y * rz - @z * ry
88
+ y = @z * rx - @x * rz
89
+ z = @x * ry - @y * rx
90
+ as = Math.asin(Math.sqrt(x * x + y * y + z * z))
91
+ dot > 0.0 ? as : Math::PI - as
98
92
  end
99
93
  end
100
94
 
101
95
  # Creates some point that is perpendicular to this point
102
96
 
103
97
  def create_perpendicular
104
- p1dot_ = self * P1
105
- p2dot_ = self * P2
106
- p1dot_ = -p1dot_ if p1dot_ < 0
107
- p2dot_ = -p2dot_ if p2dot_ < 0
108
- p1dot_ < p2dot_ ? (self % P1) : (self % P2)
98
+ p1dot = self * P1
99
+ p2dot = self * P2
100
+ p1dot = -p1dot if p1dot < 0
101
+ p2dot = -p2dot if p2dot < 0
102
+ p1dot < p2dot ? (self % P1) : (self % P2)
109
103
  end
110
104
 
111
- def self.from_latlon(lat_, lon_)
112
- rpd_ = ImplHelper::Math::RADIANS_PER_DEGREE
113
- lat_rad_ = rpd_ * lat_
114
- lon_rad_ = rpd_ * lon_
115
- z_ = ::Math.sin(lat_rad_)
116
- r_ = ::Math.cos(lat_rad_)
117
- x_ = ::Math.cos(lon_rad_) * r_
118
- y_ = ::Math.sin(lon_rad_) * r_
119
- new(x_, y_, z_)
105
+ def self.from_latlon(lat, lon)
106
+ rpd = ImplHelper::Math::RADIANS_PER_DEGREE
107
+ lat_rad = rpd * lat
108
+ lon_rad = rpd * lon
109
+ z = Math.sin(lat_rad)
110
+ r = Math.cos(lat_rad)
111
+ x = Math.cos(lon_rad) * r
112
+ y = Math.sin(lon_rad) * r
113
+ new(x, y, z)
120
114
  end
121
115
 
122
- def self.weighted_combination(p1_, w1_, p2_, w2_)
123
- new(p1_.x * w1_ + p2_.x * w2_, p1_.y * w1_ + p2_.y * w2_, p1_.z * w1_ + p2_.z * w2_)
116
+ def self.weighted_combination(p1, w1, p2, w2)
117
+ new(p1.x * w1 + p2.x * w2, p1.y * w1 + p2.y * w2, p1.z * w1 + p2.z * w2)
124
118
  end
125
119
 
126
120
  P1 = new(1, 0, 0)
@@ -130,9 +124,9 @@ module RGeo
130
124
  # Represents a finite arc on the sphere.
131
125
 
132
126
  class ArcXYZ # :nodoc:
133
- def initialize(start_, end_)
134
- @s = start_
135
- @e = end_
127
+ def initialize(start, stop)
128
+ @s = start
129
+ @e = stop
136
130
  @axis = false
137
131
  end
138
132
 
@@ -143,14 +137,14 @@ module RGeo
143
137
  "#{@s} - #{@e}"
144
138
  end
145
139
 
146
- def eql?(rhs_)
147
- rhs_.is_a?(ArcXYZ) && @s == rhs_.s && @e == rhs_.e
140
+ def eql?(rhs)
141
+ rhs.is_a?(ArcXYZ) && @s == rhs.s && @e == rhs.e
148
142
  end
149
143
  alias == eql?
150
144
 
151
145
  def degenerate?
152
- axis_ = axis
153
- axis_.x == 0 && axis_.y == 0 && axis_.z == 0
146
+ my_axis = axis
147
+ my_axis.x == 0 && my_axis.y == 0 && my_axis.z == 0
154
148
  end
155
149
 
156
150
  def axis
@@ -158,22 +152,22 @@ module RGeo
158
152
  @axis
159
153
  end
160
154
 
161
- def contains_point?(obj_)
162
- axis_ = axis
163
- saxis_ = ArcXYZ.new(@s, obj_).axis
164
- eaxis_ = ArcXYZ.new(obj_, @e).axis
165
- !saxis_ || !eaxis_ || obj_ * axis_ == 0.0 && saxis_ * axis_ > 0 && eaxis_ * axis_ > 0
155
+ def contains_point?(obj)
156
+ my_axis = axis
157
+ s_axis = ArcXYZ.new(@s, obj).axis
158
+ e_axis = ArcXYZ.new(obj, @e).axis
159
+ !s_axis || !e_axis || obj * my_axis == 0.0 && s_axis * my_axis > 0 && e_axis * my_axis > 0
166
160
  end
167
161
 
168
- def intersects_arc?(obj_)
169
- my_axis_ = axis
170
- dot1_ = my_axis_ * obj_.s
171
- dot2_ = my_axis_ * obj_.e
172
- if dot1_ >= 0.0 && dot2_ <= 0.0 || dot1_ <= 0.0 && dot2_ >= 0.0
173
- ob_axis_ = obj_.axis
174
- dot1_ = ob_axis_ * @s
175
- dot2_ = ob_axis_ * @e
176
- dot1_ >= 0.0 && dot2_ <= 0.0 || dot1_ <= 0.0 && dot2_ >= 0.0
162
+ def intersects_arc?(obj)
163
+ my_axis = axis
164
+ dot1 = my_axis * obj.s
165
+ dot2 = my_axis * obj.e
166
+ if dot1 >= 0.0 && dot2 <= 0.0 || dot1 <= 0.0 && dot2 >= 0.0
167
+ ob_axis = obj.axis
168
+ dot1 = ob_axis * @s
169
+ dot2 = ob_axis * @e
170
+ dot1 >= 0.0 && dot2 <= 0.0 || dot1 <= 0.0 && dot2 >= 0.0
177
171
  else
178
172
  false
179
173
  end
@@ -1,52 +1,44 @@
1
- # -----------------------------------------------------------------------------
1
+ # frozen_string_literal: true
2
+
3
+ # The Geos module provides general tools for creating and manipulating
4
+ # a GEOS-backed implementation of the SFS. This is a full implementation
5
+ # of the SFS using a Cartesian coordinate system. It uses the GEOS C++
6
+ # library to perform most operations, and hence is available only if
7
+ # GEOS version 3.2 or later is installed and accessible when the rgeo
8
+ # gem is installed. RGeo feature calls are translated into appropriate
9
+ # GEOS calls and directed to the library's C api. RGeo also corrects a
10
+ # few cases of missing or non-standard behavior in GEOS.
2
11
  #
3
- # GEOS wrapper for RGeo
12
+ # This module also provides a namespace for the implementation classes
13
+ # themselves; however, those classes are meant to be opaque and are
14
+ # therefore not documented.
4
15
  #
5
- # -----------------------------------------------------------------------------
6
-
7
- module RGeo
8
- # The Geos module provides general tools for creating and manipulating
9
- # a GEOS-backed implementation of the SFS. This is a full implementation
10
- # of the SFS using a Cartesian coordinate system. It uses the GEOS C++
11
- # library to perform most operations, and hence is available only if
12
- # GEOS version 3.2 or later is installed and accessible when the rgeo
13
- # gem is installed. RGeo feature calls are translated into appropriate
14
- # GEOS calls and directed to the library's C api. RGeo also corrects a
15
- # few cases of missing or non-standard behavior in GEOS.
16
- #
17
- # This module also provides a namespace for the implementation classes
18
- # themselves; however, those classes are meant to be opaque and are
19
- # therefore not documented.
20
- #
21
- # To use the Geos implementation, first obtain a factory using the
22
- # RGeo::Geos.factory method. You may then call any of the standard
23
- # factory methods on the resulting object.
24
-
25
- module Geos
26
- end
27
- end
16
+ # To use the Geos implementation, first obtain a factory using the
17
+ # RGeo::Geos.factory method. You may then call any of the standard
18
+ # factory methods on the resulting object.
28
19
 
29
20
  # :stopdoc:
30
21
 
31
22
  module RGeo
32
23
  module Geos
33
- # Implementation files
34
- require "rgeo/geos/utils"
35
- require "rgeo/geos/interface"
24
+ require_relative "geos/utils"
25
+ require_relative "geos/interface"
36
26
  begin
37
- require "rgeo/geos/geos_c_impl"
38
- rescue ::LoadError; end
27
+ require_relative "geos/geos_c_impl"
28
+ rescue LoadError
29
+ # continue
30
+ end
39
31
  CAPI_SUPPORTED = RGeo::Geos.const_defined?(:CAPIGeometryMethods)
40
32
  if CAPI_SUPPORTED
41
- require "rgeo/geos/capi_feature_classes"
42
- require "rgeo/geos/capi_factory"
33
+ require_relative "geos/capi_feature_classes"
34
+ require_relative "geos/capi_factory"
43
35
  end
44
- require "rgeo/geos/ffi_feature_methods"
45
- require "rgeo/geos/ffi_feature_classes"
46
- require "rgeo/geos/ffi_factory"
47
- require "rgeo/geos/zm_feature_methods"
48
- require "rgeo/geos/zm_feature_classes"
49
- require "rgeo/geos/zm_factory"
36
+ require_relative "geos/ffi_feature_methods"
37
+ require_relative "geos/ffi_feature_classes"
38
+ require_relative "geos/ffi_factory"
39
+ require_relative "geos/zm_feature_methods"
40
+ require_relative "geos/zm_feature_classes"
41
+ require_relative "geos/zm_factory"
50
42
 
51
43
  # Determine ffi support.
52
44
  begin
@@ -56,12 +48,12 @@ module RGeo
56
48
  raise "Problem loading FFI" unless ::FFI::AutoPointer
57
49
  FFI_SUPPORTED = true
58
50
  FFI_SUPPORT_EXCEPTION = nil
59
- rescue ::LoadError => ex_
51
+ rescue LoadError => ex
60
52
  FFI_SUPPORTED = false
61
- FFI_SUPPORT_EXCEPTION = ex_
62
- rescue => ex_
53
+ FFI_SUPPORT_EXCEPTION = ex
54
+ rescue StandardError => ex
63
55
  FFI_SUPPORTED = false
64
- FFI_SUPPORT_EXCEPTION = ex_
56
+ FFI_SUPPORT_EXCEPTION = ex
65
57
  end
66
58
 
67
59
  # Default preferred native interface
@@ -71,18 +63,13 @@ module RGeo
71
63
  self.preferred_native_interface = :ffi
72
64
  end
73
65
 
74
- # There is some trouble with END_CAP in GEOS
75
- # In docs CAP_ROUND = 1, but it's work properly with 0
76
- CAP_ROUND = 0
77
- CAP_FLAT = 1
78
- CAP_SQUARE = 2
79
-
80
- JOIN_ROUND = 0
81
- JOIN_MITRE = 1
82
- JOIN_BEVEL = 2
66
+ CAP_ROUND = 1
67
+ CAP_FLAT = 2
68
+ CAP_SQUARE = 3
83
69
 
84
- # Init internal utilities
85
- Utils._init
70
+ JOIN_ROUND = 1
71
+ JOIN_MITRE = 2
72
+ JOIN_BEVEL = 3
86
73
  end
87
74
  end
88
75
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # -----------------------------------------------------------------------------
2
4
  #
3
5
  # GEOS factory implementation
@@ -10,6 +12,7 @@ module RGeo
10
12
 
11
13
  class CAPIFactory
12
14
  include Feature::Factory::Instance
15
+ include ImplHelper::Utils
13
16
 
14
17
  class << self
15
18
  # Create a new factory. Returns nil if the GEOS CAPI implementation
@@ -19,17 +22,17 @@ module RGeo
19
22
 
20
23
  def create(opts_ = {})
21
24
  # Make sure GEOS is available
22
- return nil unless respond_to?(:_create)
25
+ return unless respond_to?(:_create)
23
26
 
24
27
  # Get flags to pass to the C extension
25
- flags_ = 0
26
- flags_ |= 1 if opts_[:uses_lenient_assertions] || opts_[:lenient_multi_polygon_assertions] || opts_[:uses_lenient_multi_polygon_assertions]
27
- flags_ |= 2 if opts_[:has_z_coordinate]
28
- flags_ |= 4 if opts_[:has_m_coordinate]
29
- if flags_ & 6 == 6
28
+ flags = 0
29
+ flags |= 1 if opts_[:uses_lenient_assertions] || opts_[:lenient_multi_polygon_assertions] || opts_[:uses_lenient_multi_polygon_assertions]
30
+ flags |= 2 if opts_[:has_z_coordinate]
31
+ flags |= 4 if opts_[:has_m_coordinate]
32
+ if flags & 6 == 6
30
33
  raise Error::UnsupportedOperation, "GEOS cannot support both Z and M coordinates at the same time."
31
34
  end
32
- flags_ |= 8 unless opts_[:auto_prepare] == :disabled
35
+ flags |= 8 unless opts_[:auto_prepare] == :disabled
33
36
 
34
37
  # Buffer resolution
35
38
  buffer_resolution_ = opts_[:buffer_resolution].to_i
@@ -40,7 +43,7 @@ module RGeo
40
43
  case wkt_generator_
41
44
  when :geos
42
45
  wkt_generator_ = nil
43
- when ::Hash
46
+ when Hash
44
47
  wkt_generator_ = WKRep::WKTGenerator.new(wkt_generator_)
45
48
  else
46
49
  wkt_generator_ = WKRep::WKTGenerator.new(convert_case: :upper)
@@ -49,7 +52,7 @@ module RGeo
49
52
  case wkb_generator_
50
53
  when :geos
51
54
  wkb_generator_ = nil
52
- when ::Hash
55
+ when Hash
53
56
  wkb_generator_ = WKRep::WKBGenerator.new(wkb_generator_)
54
57
  else
55
58
  wkb_generator_ = WKRep::WKBGenerator.new
@@ -59,19 +62,15 @@ module RGeo
59
62
  srid_ = opts_[:srid]
60
63
  proj4_ = opts_[:proj4]
61
64
  if proj4_ && CoordSys.check!(:proj4)
62
- if proj4_.is_a?(::String) || proj4_.is_a?(::Hash)
65
+ if proj4_.is_a?(String) || proj4_.is_a?(Hash)
63
66
  proj4_ = CoordSys::Proj4.create(proj4_)
64
67
  end
65
68
  else
66
69
  proj4_ = nil
67
70
  end
68
71
  coord_sys_ = opts_[:coord_sys]
69
- if coord_sys_.is_a?(::String)
70
- coord_sys_ = begin
71
- CoordSys::CS.create_from_wkt(coord_sys_)
72
- rescue
73
- nil
74
- end
72
+ if coord_sys_.is_a?(String)
73
+ coord_sys_ = CoordSys::CS.create_from_wkt(coord_sys_)
75
74
  end
76
75
  if (!proj4_ || !coord_sys_) && srid_ && (db_ = opts_[:srs_database])
77
76
  entry_ = db_.get(srid_.to_i)
@@ -83,7 +82,7 @@ module RGeo
83
82
  srid_ ||= coord_sys_.authority_code if coord_sys_
84
83
 
85
84
  # Create the factory and set instance variables
86
- result_ = _create(flags_, srid_.to_i, buffer_resolution_,
85
+ result = _create(flags, srid_.to_i, buffer_resolution_,
87
86
  wkt_generator_, wkb_generator_, proj4_, coord_sys_)
88
87
 
89
88
  # Interpret parser options
@@ -91,24 +90,24 @@ module RGeo
91
90
  case wkt_parser_
92
91
  when :geos
93
92
  wkt_parser_ = nil
94
- when ::Hash
95
- wkt_parser_ = WKRep::WKTParser.new(result_, wkt_parser_)
93
+ when Hash
94
+ wkt_parser_ = WKRep::WKTParser.new(result, wkt_parser_)
96
95
  else
97
- wkt_parser_ = WKRep::WKTParser.new(result_)
96
+ wkt_parser_ = WKRep::WKTParser.new(result)
98
97
  end
99
98
  wkb_parser_ = opts_[:wkb_parser]
100
99
  case wkb_parser_
101
100
  when :geos
102
101
  wkb_parser_ = nil
103
- when ::Hash
104
- wkb_parser_ = WKRep::WKBParser.new(result_, wkb_parser_)
102
+ when Hash
103
+ wkb_parser_ = WKRep::WKBParser.new(result, wkb_parser_)
105
104
  else
106
- wkb_parser_ = WKRep::WKBParser.new(result_)
105
+ wkb_parser_ = WKRep::WKBParser.new(result)
107
106
  end
108
- result_._set_wkrep_parsers(wkt_parser_, wkb_parser_)
107
+ result._set_wkrep_parsers(wkt_parser_, wkb_parser_)
109
108
 
110
109
  # Return the result
111
- result_
110
+ result
112
111
  end
113
112
  alias new create
114
113
  end
@@ -142,10 +141,10 @@ module RGeo
142
141
  "hasm" => (_flags & 0x4 != 0),
143
142
  "srid" => _srid,
144
143
  "bufr" => _buffer_resolution,
145
- "wktg" => _wkt_generator ? _wkt_generator._properties : {},
146
- "wkbg" => _wkb_generator ? _wkb_generator._properties : {},
147
- "wktp" => _wkt_parser ? _wkt_parser._properties : {},
148
- "wkbp" => _wkb_parser ? _wkb_parser._properties : {},
144
+ "wktg" => _wkt_generator ? _wkt_generator.properties : {},
145
+ "wkbg" => _wkb_generator ? _wkb_generator.properties : {},
146
+ "wktp" => _wkt_parser ? _wkt_parser.properties : {},
147
+ "wkbp" => _wkb_parser ? _wkb_parser.properties : {},
149
148
  "lmpa" => (_flags & 0x1 != 0),
150
149
  "apre" => ((_flags & 0x8) >> 3)
151
150
  }
@@ -170,20 +169,22 @@ module RGeo
170
169
  else
171
170
  coord_sys_ = nil
172
171
  end
173
- initialize_copy(CAPIFactory.create(
174
- has_z_coordinate: data_["hasz"],
175
- has_m_coordinate: data_["hasm"],
176
- srid: data_["srid"],
177
- buffer_resolution: data_["bufr"],
178
- wkt_generator: ImplHelper::Utils.symbolize_hash(data_["wktg"]),
179
- wkb_generator: ImplHelper::Utils.symbolize_hash(data_["wkbg"]),
180
- wkt_parser: ImplHelper::Utils.symbolize_hash(data_["wktp"]),
181
- wkb_parser: ImplHelper::Utils.symbolize_hash(data_["wkbp"]),
182
- uses_lenient_multi_polygon_assertions: data_["lmpa"],
183
- auto_prepare: (data_["apre"] == 0 ? :disabled : :simple),
184
- proj4: proj4_,
185
- coord_sys: coord_sys_
186
- ))
172
+ initialize_copy(
173
+ CAPIFactory.create(
174
+ has_z_coordinate: data_["hasz"],
175
+ has_m_coordinate: data_["hasm"],
176
+ srid: data_["srid"],
177
+ buffer_resolution: data_["bufr"],
178
+ wkt_generator: symbolize_hash(data_["wktg"]),
179
+ wkb_generator: symbolize_hash(data_["wkbg"]),
180
+ wkt_parser: symbolize_hash(data_["wktp"]),
181
+ wkb_parser: symbolize_hash(data_["wkbp"]),
182
+ uses_lenient_multi_polygon_assertions: data_["lmpa"],
183
+ auto_prepare: (data_["apre"] == 0 ? :disabled : :simple),
184
+ proj4: proj4_,
185
+ coord_sys: coord_sys_
186
+ )
187
+ )
187
188
  end
188
189
 
189
190
  # Psych support
@@ -194,10 +195,10 @@ module RGeo
194
195
  coder_["srid"] = _srid
195
196
  coder_["buffer_resolution"] = _buffer_resolution
196
197
  coder_["lenient_multi_polygon_assertions"] = (_flags & 0x1 != 0)
197
- coder_["wkt_generator"] = _wkt_generator ? _wkt_generator._properties : {}
198
- coder_["wkb_generator"] = _wkb_generator ? _wkb_generator._properties : {}
199
- coder_["wkt_parser"] = _wkt_parser ? _wkt_parser._properties : {}
200
- coder_["wkb_parser"] = _wkb_parser ? _wkb_parser._properties : {}
198
+ coder_["wkt_generator"] = _wkt_generator ? _wkt_generator.properties : {}
199
+ coder_["wkb_generator"] = _wkb_generator ? _wkb_generator.properties : {}
200
+ coder_["wkt_parser"] = _wkt_parser ? _wkt_parser.properties : {}
201
+ coder_["wkb_parser"] = _wkb_parser ? _wkb_parser.properties : {}
201
202
  coder_["auto_prepare"] = ((_flags & 0x8) == 0 ? "disabled" : "simple")
202
203
  if (proj4_ = _proj4)
203
204
  str_ = proj4_.original_str || proj4_.canonical_str
@@ -211,7 +212,7 @@ module RGeo
211
212
  def init_with(coder_) # :nodoc:
212
213
  if (proj4_data_ = coder_["proj4"])
213
214
  CoordSys.check!(:proj4)
214
- if proj4_data_.is_a?(::Hash)
215
+ if proj4_data_.is_a?(Hash)
215
216
  proj4_ = CoordSys::Proj4.create(proj4_data_["proj4"], radians: proj4_data_["radians"])
216
217
  else
217
218
  proj4_ = CoordSys::Proj4.create(proj4_data_.to_s)
@@ -224,20 +225,22 @@ module RGeo
224
225
  else
225
226
  coord_sys_ = nil
226
227
  end
227
- initialize_copy(CAPIFactory.create(
228
- has_z_coordinate: coder_["has_z_coordinate"],
229
- has_m_coordinate: coder_["has_m_coordinate"],
230
- srid: coder_["srid"],
231
- buffer_resolution: coder_["buffer_resolution"],
232
- wkt_generator: ImplHelper::Utils.symbolize_hash(coder_["wkt_generator"]),
233
- wkb_generator: ImplHelper::Utils.symbolize_hash(coder_["wkb_generator"]),
234
- wkt_parser: ImplHelper::Utils.symbolize_hash(coder_["wkt_parser"]),
235
- wkb_parser: ImplHelper::Utils.symbolize_hash(coder_["wkb_parser"]),
236
- auto_prepare: coder_["auto_prepare"] == "disabled" ? :disabled : :simple,
237
- uses_lenient_multi_polygon_assertions: coder_["lenient_multi_polygon_assertions"],
238
- proj4: proj4_,
239
- coord_sys: coord_sys_
240
- ))
228
+ initialize_copy(
229
+ CAPIFactory.create(
230
+ has_z_coordinate: coder_["has_z_coordinate"],
231
+ has_m_coordinate: coder_["has_m_coordinate"],
232
+ srid: coder_["srid"],
233
+ buffer_resolution: coder_["buffer_resolution"],
234
+ wkt_generator: symbolize_hash(coder_["wkt_generator"]),
235
+ wkb_generator: symbolize_hash(coder_["wkb_generator"]),
236
+ wkt_parser: symbolize_hash(coder_["wkt_parser"]),
237
+ wkb_parser: symbolize_hash(coder_["wkb_parser"]),
238
+ auto_prepare: coder_["auto_prepare"] == "disabled" ? :disabled : :simple,
239
+ uses_lenient_multi_polygon_assertions: coder_["lenient_multi_polygon_assertions"],
240
+ proj4: proj4_,
241
+ coord_sys: coord_sys_
242
+ )
243
+ )
241
244
  end
242
245
 
243
246
  # Returns the SRID of geometries created by this factory.
@@ -294,7 +297,11 @@ module RGeo
294
297
  if (wkb_parser_ = _wkb_parser)
295
298
  wkb_parser_.parse(str_)
296
299
  else
297
- _parse_wkb_impl(str_)
300
+ if str_[0] == "\x00" || str_[0] == "\x01"
301
+ _parse_wkb_impl(str_)
302
+ else
303
+ _parse_wkb_impl([str_].pack('H*'))
304
+ end
298
305
  end
299
306
  end
300
307
 
@@ -302,99 +309,67 @@ module RGeo
302
309
 
303
310
  def point(x_, y_, *extra_)
304
311
  if extra_.length > (_flags & 6 == 0 ? 0 : 1)
305
- nil
312
+ raise(RGeo::Error::InvalidGeometry, "Parse error")
306
313
  else
307
- begin
308
- CAPIPointImpl.create(self, x_, y_, extra_[0].to_f)
309
- rescue
310
- nil
311
- end
314
+ CAPIPointImpl.create(self, x_, y_, extra_[0].to_f)
312
315
  end
313
316
  end
314
317
 
315
318
  # See RGeo::Feature::Factory#line_string
316
319
 
317
320
  def line_string(points_)
318
- points_ = points_.to_a unless points_.is_a?(::Array)
319
- begin
320
- CAPILineStringImpl.create(self, points_)
321
- rescue
322
- nil
323
- end
321
+ points_ = points_.to_a unless points_.is_a?(Array)
322
+ CAPILineStringImpl.create(self, points_) ||
323
+ raise(RGeo::Error::InvalidGeometry, "Parse error")
324
324
  end
325
325
 
326
326
  # See RGeo::Feature::Factory#line
327
327
 
328
328
  def line(start_, end_)
329
329
  CAPILineImpl.create(self, start_, end_)
330
- rescue
331
- nil
332
330
  end
333
331
 
334
332
  # See RGeo::Feature::Factory#linear_ring
335
333
 
336
334
  def linear_ring(points_)
337
- points_ = points_.to_a unless points_.is_a?(::Array)
338
- begin
339
- CAPILinearRingImpl.create(self, points_)
340
- rescue
341
- nil
342
- end
335
+ points_ = points_.to_a unless points_.is_a?(Array)
336
+ CAPILinearRingImpl.create(self, points_)
343
337
  end
344
338
 
345
339
  # See RGeo::Feature::Factory#polygon
346
340
 
347
341
  def polygon(outer_ring_, inner_rings_ = nil)
348
- inner_rings_ = inner_rings_.to_a unless inner_rings_.is_a?(::Array)
349
- begin
350
- CAPIPolygonImpl.create(self, outer_ring_, inner_rings_)
351
- rescue
352
- nil
353
- end
342
+ inner_rings_ = inner_rings_.to_a unless inner_rings_.is_a?(Array)
343
+ CAPIPolygonImpl.create(self, outer_ring_, inner_rings_)
354
344
  end
355
345
 
356
346
  # See RGeo::Feature::Factory#collection
357
347
 
358
348
  def collection(elems_)
359
- elems_ = elems_.to_a unless elems_.is_a?(::Array)
360
- begin
361
- CAPIGeometryCollectionImpl.create(self, elems_)
362
- rescue
363
- nil
364
- end
349
+ elems_ = elems_.to_a unless elems_.is_a?(Array)
350
+ CAPIGeometryCollectionImpl.create(self, elems_)
365
351
  end
366
352
 
367
353
  # See RGeo::Feature::Factory#multi_point
368
354
 
369
355
  def multi_point(elems_)
370
- elems_ = elems_.to_a unless elems_.is_a?(::Array)
371
- begin
372
- CAPIMultiPointImpl.create(self, elems_)
373
- rescue
374
- nil
375
- end
356
+ elems_ = elems_.to_a unless elems_.is_a?(Array)
357
+ CAPIMultiPointImpl.create(self, elems_)
376
358
  end
377
359
 
378
360
  # See RGeo::Feature::Factory#multi_line_string
379
361
 
380
362
  def multi_line_string(elems_)
381
- elems_ = elems_.to_a unless elems_.is_a?(::Array)
382
- begin
383
- CAPIMultiLineStringImpl.create(self, elems_)
384
- rescue
385
- nil
386
- end
363
+ elems_ = elems_.to_a unless elems_.is_a?(Array)
364
+ CAPIMultiLineStringImpl.create(self, elems_)
387
365
  end
388
366
 
389
367
  # See RGeo::Feature::Factory#multi_polygon
390
368
 
391
369
  def multi_polygon(elems_)
392
- elems_ = elems_.to_a unless elems_.is_a?(::Array)
393
- begin
394
- CAPIMultiPolygonImpl.create(self, elems_)
395
- rescue
396
- nil
397
- end
370
+ elems_ = elems_.to_a unless elems_.is_a?(Array)
371
+ CAPIMultiPolygonImpl.create(self, elems_) ||
372
+ raise(RGeo::Error::InvalidGeometry, "Parse error")
398
373
  end
399
374
 
400
375
  # See RGeo::Feature::Factory#proj4
@@ -411,38 +386,38 @@ module RGeo
411
386
 
412
387
  # See RGeo::Feature::Factory#override_cast
413
388
 
414
- def override_cast(original_, ntype_, flags_)
415
- return nil unless Geos.supported?
416
- keep_subtype_ = flags_[:keep_subtype]
417
- # force_new_ = flags_[:force_new]
418
- project_ = flags_[:project]
419
- type_ = original_.geometry_type
420
- ntype_ = type_ if keep_subtype_ && type_.include?(ntype_)
421
- case original_
389
+ def override_cast(original, ntype, flags)
390
+ return unless Geos.supported?
391
+ keep_subtype = flags[:keep_subtype]
392
+ # force_new_ = flags[:force_new]
393
+ project = flags[:project]
394
+ type = original.geometry_type
395
+ ntype = type if keep_subtype && type.include?(ntype)
396
+ case original
422
397
  when CAPIGeometryMethods
423
398
  # Optimization if we're just changing factories, but the
424
399
  # factories are zm-compatible and proj4-compatible.
425
- if original_.factory != self && ntype_ == type_ &&
426
- original_.factory._flags & 0x6 == _flags & 0x6 &&
427
- (!project_ || original_.factory.proj4 == _proj4)
428
- result_ = original_.dup
429
- result_._set_factory(self)
430
- return result_
400
+ if original.factory != self && ntype == type &&
401
+ original.factory._flags & 0x6 == _flags & 0x6 &&
402
+ (!project || original.factory.proj4 == _proj4)
403
+ result = original.dup
404
+ result.factory = self
405
+ return result
431
406
  end
432
407
  # LineString conversion optimization.
433
- if (original_.factory != self || ntype_ != type_) &&
434
- original_.factory._flags & 0x6 == _flags & 0x6 &&
435
- (!project_ || original_.factory.proj4 == _proj4) &&
436
- type_.subtype_of?(Feature::LineString) && ntype_.subtype_of?(Feature::LineString)
437
- return IMPL_CLASSES[ntype_]._copy_from(self, original_)
408
+ if (original.factory != self || ntype != type) &&
409
+ original.factory._flags & 0x6 == _flags & 0x6 &&
410
+ (!project || original.factory.proj4 == _proj4) &&
411
+ type.subtype_of?(Feature::LineString) && ntype.subtype_of?(Feature::LineString)
412
+ return IMPL_CLASSES[ntype]._copy_from(self, original)
438
413
  end
439
414
  when ZMGeometryMethods
440
415
  # Optimization for just removing a coordinate from an otherwise
441
416
  # compatible factory
442
- if _flags & 0x6 == 0x2 && self == original_.factory.z_factory
443
- return Feature.cast(original_.z_geometry, ntype_, flags_)
444
- elsif _flags & 0x6 == 0x4 && self == original_.factory.m_factory
445
- return Feature.cast(original_.m_geometry, ntype_, flags_)
417
+ if _flags & 0x6 == 0x2 && self == original.factory.z_factory
418
+ return Feature.cast(original.z_geometry, ntype, flags)
419
+ elsif _flags & 0x6 == 0x4 && self == original.factory.m_factory
420
+ return Feature.cast(original.m_geometry, ntype, flags)
446
421
  end
447
422
  end
448
423
  false