rgeo 1.1.2 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +144 -0
- data/ext/geos_c_impl/analysis.c +78 -0
- data/ext/geos_c_impl/analysis.h +42 -0
- data/ext/geos_c_impl/errors.c +35 -0
- data/ext/geos_c_impl/errors.h +22 -0
- data/ext/geos_c_impl/extconf.rb +6 -3
- data/ext/geos_c_impl/factory.c +14 -5
- data/ext/geos_c_impl/factory.h +5 -1
- data/ext/geos_c_impl/geometry.c +20 -2
- data/ext/geos_c_impl/geometry_collection.c +0 -17
- data/ext/geos_c_impl/main.c +5 -2
- data/ext/geos_c_impl/preface.h +3 -0
- data/lib/rgeo.rb +11 -13
- data/lib/rgeo/cartesian.rb +13 -23
- data/lib/rgeo/cartesian/analysis.rb +44 -20
- data/lib/rgeo/cartesian/bounding_box.rb +83 -79
- data/lib/rgeo/cartesian/calculations.rb +40 -38
- data/lib/rgeo/cartesian/factory.rb +134 -169
- data/lib/rgeo/cartesian/feature_classes.rb +2 -18
- data/lib/rgeo/cartesian/feature_methods.rb +37 -39
- data/lib/rgeo/cartesian/interface.rb +11 -9
- data/lib/rgeo/coord_sys.rb +9 -8
- data/lib/rgeo/coord_sys/cs/entities.rb +345 -303
- data/lib/rgeo/coord_sys/cs/factories.rb +30 -28
- data/lib/rgeo/coord_sys/cs/wkt_parser.rb +128 -126
- data/lib/rgeo/coord_sys/srs_database/{interface.rb → entry.rb} +26 -32
- data/lib/rgeo/coord_sys/srs_database/sr_org.rb +19 -17
- data/lib/rgeo/coord_sys/srs_database/url_reader.rb +21 -19
- data/lib/rgeo/error.rb +7 -1
- data/lib/rgeo/feature.rb +40 -51
- data/lib/rgeo/feature/curve.rb +2 -0
- data/lib/rgeo/feature/factory.rb +15 -13
- data/lib/rgeo/feature/factory_generator.rb +7 -5
- data/lib/rgeo/feature/geometry.rb +31 -29
- data/lib/rgeo/feature/geometry_collection.rb +6 -4
- data/lib/rgeo/feature/line.rb +2 -0
- data/lib/rgeo/feature/line_string.rb +3 -1
- data/lib/rgeo/feature/linear_ring.rb +12 -0
- data/lib/rgeo/feature/multi_curve.rb +2 -0
- data/lib/rgeo/feature/multi_line_string.rb +2 -0
- data/lib/rgeo/feature/multi_point.rb +2 -0
- data/lib/rgeo/feature/multi_polygon.rb +2 -0
- data/lib/rgeo/feature/multi_surface.rb +2 -0
- data/lib/rgeo/feature/point.rb +2 -0
- data/lib/rgeo/feature/polygon.rb +3 -1
- data/lib/rgeo/feature/surface.rb +2 -0
- data/lib/rgeo/feature/types.rb +107 -103
- data/lib/rgeo/geographic.rb +27 -37
- data/lib/rgeo/geographic/factory.rb +154 -199
- data/lib/rgeo/geographic/interface.rb +141 -137
- data/lib/rgeo/geographic/proj4_projector.rb +28 -23
- data/lib/rgeo/geographic/projected_feature_classes.rb +2 -18
- data/lib/rgeo/geographic/projected_feature_methods.rb +64 -54
- data/lib/rgeo/geographic/projected_window.rb +4 -2
- data/lib/rgeo/geographic/simple_mercator_projector.rb +41 -39
- data/lib/rgeo/geographic/spherical_feature_classes.rb +3 -18
- data/lib/rgeo/geographic/spherical_feature_methods.rb +90 -67
- data/lib/rgeo/geographic/spherical_math.rb +81 -87
- data/lib/rgeo/geos.rb +40 -53
- data/lib/rgeo/geos/capi_factory.rb +111 -136
- data/lib/rgeo/geos/capi_feature_classes.rb +22 -36
- data/lib/rgeo/geos/ffi_factory.rb +276 -297
- data/lib/rgeo/geos/ffi_feature_classes.rb +2 -20
- data/lib/rgeo/geos/ffi_feature_methods.rb +177 -169
- data/lib/rgeo/geos/interface.rb +25 -23
- data/lib/rgeo/geos/utils.rb +47 -39
- data/lib/rgeo/geos/zm_factory.rb +171 -185
- data/lib/rgeo/geos/zm_feature_classes.rb +2 -20
- data/lib/rgeo/geos/zm_feature_methods.rb +76 -72
- data/lib/rgeo/impl_helper.rb +8 -18
- data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +84 -75
- data/lib/rgeo/impl_helper/basic_geometry_methods.rb +21 -23
- data/lib/rgeo/impl_helper/basic_line_string_methods.rb +95 -48
- data/lib/rgeo/impl_helper/basic_point_methods.rb +29 -25
- data/lib/rgeo/impl_helper/basic_polygon_methods.rb +68 -27
- data/lib/rgeo/impl_helper/math.rb +2 -0
- data/lib/rgeo/impl_helper/utils.rb +9 -15
- data/lib/rgeo/version.rb +3 -1
- data/lib/rgeo/wkrep.rb +24 -34
- data/lib/rgeo/wkrep/wkb_generator.rb +87 -84
- data/lib/rgeo/wkrep/wkb_parser.rb +93 -93
- data/lib/rgeo/wkrep/wkt_generator.rb +67 -63
- data/lib/rgeo/wkrep/wkt_parser.rb +172 -168
- metadata +30 -36
- 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(
|
25
|
-
|
26
|
-
@x = (
|
27
|
-
@y = (
|
28
|
-
@z = (
|
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?(
|
41
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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 *
|
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(
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
if
|
91
|
-
|
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
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
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
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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(
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
new(
|
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(
|
123
|
-
new(
|
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(
|
134
|
-
@s =
|
135
|
-
@e =
|
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?(
|
147
|
-
|
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
|
-
|
153
|
-
|
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?(
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
!
|
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?(
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
if
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
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
|
data/lib/rgeo/geos.rb
CHANGED
@@ -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
|
-
#
|
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
|
-
|
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
|
-
|
34
|
-
|
35
|
-
require "rgeo/geos/interface"
|
24
|
+
require_relative "geos/utils"
|
25
|
+
require_relative "geos/interface"
|
36
26
|
begin
|
37
|
-
|
38
|
-
rescue
|
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
|
-
|
42
|
-
|
33
|
+
require_relative "geos/capi_feature_classes"
|
34
|
+
require_relative "geos/capi_factory"
|
43
35
|
end
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
51
|
+
rescue LoadError => ex
|
60
52
|
FFI_SUPPORTED = false
|
61
|
-
FFI_SUPPORT_EXCEPTION =
|
62
|
-
rescue =>
|
53
|
+
FFI_SUPPORT_EXCEPTION = ex
|
54
|
+
rescue StandardError => ex
|
63
55
|
FFI_SUPPORTED = false
|
64
|
-
FFI_SUPPORT_EXCEPTION =
|
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
|
-
|
75
|
-
|
76
|
-
|
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
|
-
|
85
|
-
|
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
|
25
|
+
return unless respond_to?(:_create)
|
23
26
|
|
24
27
|
# Get flags to pass to the C extension
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
if
|
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
|
-
|
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
|
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
|
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?(
|
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?(
|
70
|
-
coord_sys_ =
|
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
|
-
|
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
|
95
|
-
wkt_parser_ = WKRep::WKTParser.new(
|
93
|
+
when Hash
|
94
|
+
wkt_parser_ = WKRep::WKTParser.new(result, wkt_parser_)
|
96
95
|
else
|
97
|
-
wkt_parser_ = WKRep::WKTParser.new(
|
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
|
104
|
-
wkb_parser_ = WKRep::WKBParser.new(
|
102
|
+
when Hash
|
103
|
+
wkb_parser_ = WKRep::WKBParser.new(result, wkb_parser_)
|
105
104
|
else
|
106
|
-
wkb_parser_ = WKRep::WKBParser.new(
|
105
|
+
wkb_parser_ = WKRep::WKBParser.new(result)
|
107
106
|
end
|
108
|
-
|
107
|
+
result._set_wkrep_parsers(wkt_parser_, wkb_parser_)
|
109
108
|
|
110
109
|
# Return the result
|
111
|
-
|
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.
|
146
|
-
"wkbg" => _wkb_generator ? _wkb_generator.
|
147
|
-
"wktp" => _wkt_parser ? _wkt_parser.
|
148
|
-
"wkbp" => _wkb_parser ? _wkb_parser.
|
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(
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
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.
|
198
|
-
coder_["wkb_generator"] = _wkb_generator ? _wkb_generator.
|
199
|
-
coder_["wkt_parser"] = _wkt_parser ? _wkt_parser.
|
200
|
-
coder_["wkb_parser"] = _wkb_parser ? _wkb_parser.
|
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?(
|
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(
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
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
|
-
|
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
|
-
|
312
|
+
raise(RGeo::Error::InvalidGeometry, "Parse error")
|
306
313
|
else
|
307
|
-
|
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?(
|
319
|
-
|
320
|
-
|
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?(
|
338
|
-
|
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?(
|
349
|
-
|
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?(
|
360
|
-
|
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?(
|
371
|
-
|
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?(
|
382
|
-
|
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?(
|
393
|
-
|
394
|
-
|
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(
|
415
|
-
return
|
416
|
-
|
417
|
-
# force_new_ =
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
case
|
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
|
426
|
-
|
427
|
-
(!
|
428
|
-
|
429
|
-
|
430
|
-
return
|
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 (
|
434
|
-
|
435
|
-
(!
|
436
|
-
|
437
|
-
return IMPL_CLASSES[
|
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 ==
|
443
|
-
return Feature.cast(
|
444
|
-
elsif _flags & 0x6 == 0x4 && self ==
|
445
|
-
return Feature.cast(
|
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
|