Class: RGeo::Geographic::Factory

Inherits:
Object
  • Object
show all
Includes:
Feature::Factory::Instance, ImplHelper::Utils
Defined in:
lib/rgeo/geographic/factory.rb

Overview

This class implements the various factories for geography features. See methods of the RGeo::Geographic module for the API for creating geography factories.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ImplHelper::Utils

setup_coord_sys

Constructor Details

#initialize(impl_prefix, opts = {}) ⇒ Factory

:nodoc:


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/rgeo/geographic/factory.rb', line 28

def initialize(impl_prefix, opts = {}) # :nodoc:
  @impl_prefix = impl_prefix
  @point_class = Geographic.const_get("#{impl_prefix}PointImpl")
  @line_string_class = Geographic.const_get("#{impl_prefix}LineStringImpl")
  @linear_ring_class = Geographic.const_get("#{impl_prefix}LinearRingImpl")
  @line_class = Geographic.const_get("#{impl_prefix}LineImpl")
  @polygon_class = Geographic.const_get("#{impl_prefix}PolygonImpl")
  @geometry_collection_class = Geographic.const_get("#{impl_prefix}GeometryCollectionImpl")
  @multi_point_class = Geographic.const_get("#{impl_prefix}MultiPointImpl")
  @multi_line_string_class = Geographic.const_get("#{impl_prefix}MultiLineStringImpl")
  @multi_polygon_class = Geographic.const_get("#{impl_prefix}MultiPolygonImpl")
  @support_z = opts[:has_z_coordinate] ? true : false
  @support_m = opts[:has_m_coordinate] ? true : false
  @coordinate_dimension = 2
  @coordinate_dimension += 1 if @support_z
  @coordinate_dimension += 1 if @support_m
  @spatial_dimension = @support_z ? 3 : 2

  srid = opts.fetch(:srid, 4326).to_i
  coord_sys_info = ImplHelper::Utils.setup_coord_sys(srid, opts[:coord_sys], opts[:coord_sys_class])
  @coord_sys = coord_sys_info[:coord_sys]
  @srid = coord_sys_info[:srid]

  @buffer_resolution = opts[:buffer_resolution].to_i
  @buffer_resolution = 1 if @buffer_resolution < 1

  wkt_generator = opts[:wkt_generator]
  @wkt_generator =
    case wkt_generator
    when Hash
      WKRep::WKTGenerator.new(wkt_generator)
    else
      WKRep::WKTGenerator.new(convert_case: :upper)
    end
  wkb_generator = opts[:wkb_generator]
  @wkb_generator =
    case wkb_generator
    when Hash
      WKRep::WKBGenerator.new(wkb_generator)
    else
      WKRep::WKBGenerator.new
    end
  wkt_parser = opts[:wkt_parser]
  @wkt_parser =
    case wkt_parser
    when Hash
      WKRep::WKTParser.new(self, wkt_parser)
    else
      WKRep::WKTParser.new(self)
    end
  wkb_parser = opts[:wkb_parser]
  @wkb_parser =
    case wkb_parser
    when Hash
      WKRep::WKBParser.new(self, wkb_parser)
    else
      WKRep::WKBParser.new(self)
    end
  @projector = nil
end

Instance Attribute Details

#coord_sysObject (readonly)

See RGeo::Feature::Factory#coord_sys


26
27
28
# File 'lib/rgeo/geographic/factory.rb', line 26

def coord_sys
  @coord_sys
end

#coordinate_dimensionObject (readonly)

Returns the value of attribute coordinate_dimension.


20
21
22
# File 'lib/rgeo/geographic/factory.rb', line 20

def coordinate_dimension
  @coordinate_dimension
end

#projector=(value) ⇒ Object (writeonly)

Sets the attribute projector

Parameters:

  • value

    the value to set the attribute projector to.


18
19
20
# File 'lib/rgeo/geographic/factory.rb', line 18

def projector=(value)
  @projector = value
end

#spatial_dimensionObject (readonly)

Returns the value of attribute spatial_dimension.


20
21
22
# File 'lib/rgeo/geographic/factory.rb', line 20

def spatial_dimension
  @spatial_dimension
end

#sridObject (readonly)

Returns the srid reported by this factory.


23
24
25
# File 'lib/rgeo/geographic/factory.rb', line 23

def srid
  @srid
end

Instance Method Details

#collection(elems) ⇒ Object

See RGeo::Feature::Factory#collection


330
331
332
# File 'lib/rgeo/geographic/factory.rb', line 330

def collection(elems)
  @geometry_collection_class.new(self, elems)
end

#encode_with(coder) ⇒ Object

Psych support


160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/rgeo/geographic/factory.rb', line 160

def encode_with(coder) # :nodoc:
  coder["impl_prefix"] = @impl_prefix
  coder["has_z_coordinate"] = @support_z
  coder["has_m_coordinate"] = @support_m
  coder["srid"] = @srid
  coder["wkt_generator"] = @wkt_generator.properties
  coder["wkb_generator"] = @wkb_generator.properties
  coder["wkt_parser"] = @wkt_parser.properties
  coder["wkb_parser"] = @wkb_parser.properties
  coder["buffer_resolution"] = @buffer_resolution
  coder["coord_sys"] = @coord_sys.to_wkt if @coord_sys

  return unless @projector

  coder["projectorclass"] = @projector.class.name.sub(/.*::/, "")
  coder["projection_factory"] = @projector.projection_factory
end

#eql?(other) ⇒ Boolean Also known as: ==

Equivalence test.

Returns:

  • (Boolean)

91
92
93
94
95
96
97
# File 'lib/rgeo/geographic/factory.rb', line 91

def eql?(other)
  other.is_a?(Geographic::Factory) &&
    @impl_prefix == other.instance_variable_get(:@impl_prefix) &&
    @support_z == other.instance_variable_get(:@support_z) &&
    @support_m == other.instance_variable_get(:@support_m) &&
    @coord_sys == other.instance_variable_get(:@coord_sys)
end

#generate_wkb(obj) ⇒ Object

:nodoc:


356
357
358
# File 'lib/rgeo/geographic/factory.rb', line 356

def generate_wkb(obj) # :nodoc:
  @wkb_generator.generate(obj)
end

#generate_wkt(obj) ⇒ Object


352
353
354
# File 'lib/rgeo/geographic/factory.rb', line 352

def generate_wkt(obj)
  @wkt_generator.generate(obj)
end

#has_projection?Boolean

Returns true if this factory supports a projection.

Returns:

  • (Boolean)

210
211
212
# File 'lib/rgeo/geographic/factory.rb', line 210

def has_projection?
  !@projector.nil?
end

#hashObject

Standard hash code


102
103
104
# File 'lib/rgeo/geographic/factory.rb', line 102

def hash
  @hash ||= [@impl_prefix, @support_z, @support_m, @coord_sys].hash
end

#init_with(coder) ⇒ Object

:nodoc:


178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/rgeo/geographic/factory.rb', line 178

def init_with(coder) # :nodoc:
  cs_class = CoordSys::CONFIG.default_coord_sys_class
  coord_sys = coder["cs"]&.then { |cs| cs_class.create_from_wkt(cs) }

  initialize(
    coder["impl_prefix"],
    has_z_coordinate: coder["has_z_coordinate"],
    has_m_coordinate: coder["has_m_coordinate"],
    srid: coder["srid"],
    wkt_generator: symbolize_hash(coder["wkt_generator"]),
    wkb_generator: symbolize_hash(coder["wkb_generator"]),
    wkt_parser: symbolize_hash(coder["wkt_parser"]),
    wkb_parser: symbolize_hash(coder["wkb_parser"]),
    buffer_resolution: coder["buffer_resolution"],
    coord_sys: coord_sys
  )
  proj_klass = coder["projectorclass"]
  proj_factory = coder["projection_factory"]

  return unless proj_klass && proj_factory

  klass_ = RGeo::Geographic.const_get(proj_klass)

  return unless klass_

  projector = klass_.allocate
  projector.set_factories(self, proj_factory)
  @projector = projector
end

#line(start, stop) ⇒ Object

See RGeo::Feature::Factory#line


312
313
314
# File 'lib/rgeo/geographic/factory.rb', line 312

def line(start, stop)
  @line_class.new(self, start, stop)
end

#line_string(points) ⇒ Object

See RGeo::Feature::Factory#line_string


306
307
308
# File 'lib/rgeo/geographic/factory.rb', line 306

def line_string(points)
  @line_string_class.new(self, points)
end

#linear_ring(points) ⇒ Object

See RGeo::Feature::Factory#linear_ring


318
319
320
# File 'lib/rgeo/geographic/factory.rb', line 318

def linear_ring(points)
  @linear_ring_class.new(self, points)
end

#marshal_dumpObject

Marshal support


108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/rgeo/geographic/factory.rb', line 108

def marshal_dump # :nodoc:
  hash_ = {
    "pref" => @impl_prefix,
    "hasz" => @support_z,
    "hasm" => @support_m,
    "srid" => @srid,
    "wktg" => @wkt_generator.properties,
    "wkbg" => @wkb_generator.properties,
    "wktp" => @wkt_parser.properties,
    "wkbp" => @wkb_parser.properties,
    "bufr" => @buffer_resolution
  }
  hash_["cs"] = @coord_sys.to_wkt if @coord_sys
  if @projector
    hash_["prjc"] = @projector.class.name.sub(/.*::/, "")
    hash_["prjf"] = @projector.projection_factory
  end
  hash_
end

#marshal_load(data_) ⇒ Object

:nodoc:


128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/rgeo/geographic/factory.rb', line 128

def marshal_load(data_) # :nodoc:
  cs_class = CoordSys::CONFIG.default_coord_sys_class
  coord_sys = data_["cs"]&.then { |cs| cs_class.create_from_wkt(cs) }

  initialize(
    data_["pref"],
    has_z_coordinate: data_["hasz"],
    has_m_coordinate: data_["hasm"],
    srid: data_["srid"],
    wkt_generator: symbolize_hash(data_["wktg"]),
    wkb_generator: symbolize_hash(data_["wkbg"]),
    wkt_parser: symbolize_hash(data_["wktp"]),
    wkb_parser: symbolize_hash(data_["wkbp"]),
    buffer_resolution: data_["bufr"],
    coord_sys: coord_sys
  )
  proj_klass = data_["prjc"]
  proj_factory = data_["prjf"]

  return unless proj_klass && proj_factory

  klass_ = RGeo::Geographic.const_get(proj_klass)

  return unless klass_

  projector = klass_.allocate
  projector.set_factories(self, proj_factory)
  @projector = projector
end

#marshal_wkb_generatorObject


360
361
362
# File 'lib/rgeo/geographic/factory.rb', line 360

def marshal_wkb_generator
  @marshal_wkb_generator ||= RGeo::WKRep::WKBGenerator.new(type_format: :wkb12)
end

#marshal_wkb_parserObject


364
365
366
# File 'lib/rgeo/geographic/factory.rb', line 364

def marshal_wkb_parser
  @marshal_wkb_parser ||= RGeo::WKRep::WKBParser.new(self, support_wkb12: true)
end

#multi_line_string(elems) ⇒ Object

See RGeo::Feature::Factory#multi_line_string


342
343
344
# File 'lib/rgeo/geographic/factory.rb', line 342

def multi_line_string(elems)
  @multi_line_string_class.new(self, elems)
end

#multi_point(elems) ⇒ Object

See RGeo::Feature::Factory#multi_point


336
337
338
# File 'lib/rgeo/geographic/factory.rb', line 336

def multi_point(elems)
  @multi_point_class.new(self, elems)
end

#multi_polygon(elems) ⇒ Object

See RGeo::Feature::Factory#multi_polygon


348
349
350
# File 'lib/rgeo/geographic/factory.rb', line 348

def multi_polygon(elems)
  @multi_polygon_class.new(self, elems)
end

#parse_wkb(str) ⇒ Object

See RGeo::Feature::Factory#parse_wkb


294
295
296
# File 'lib/rgeo/geographic/factory.rb', line 294

def parse_wkb(str)
  @wkb_parser.parse(str)
end

#parse_wkt(str) ⇒ Object

See RGeo::Feature::Factory#parse_wkt


288
289
290
# File 'lib/rgeo/geographic/factory.rb', line 288

def parse_wkt(str)
  @wkt_parser.parse(str)
end

#point(x, y, *extra) ⇒ Object

See RGeo::Feature::Factory#point


300
301
302
# File 'lib/rgeo/geographic/factory.rb', line 300

def point(x, y, *extra)
  @point_class.new(self, x, y, *extra)
end

#polygon(outer_ring, inner_rings = nil) ⇒ Object

See RGeo::Feature::Factory#polygon


324
325
326
# File 'lib/rgeo/geographic/factory.rb', line 324

def polygon(outer_ring, inner_rings = nil)
  @polygon_class.new(self, outer_ring, inner_rings)
end

#project(geometry) ⇒ Object

Projects the given geometry into the projected coordinate space, and returns the projected geometry. Returns nil if this factory does not support a projection. Raises Error::InvalidGeometry if the given geometry is not of this factory.


227
228
229
230
231
# File 'lib/rgeo/geographic/factory.rb', line 227

def project(geometry)
  return unless @projector && geometry
  raise Error::InvalidGeometry, "Wrong geometry type" unless geometry.factory == self
  @projector.project(geometry)
end

#projection_factoryObject

Returns the factory for the projected coordinate space, or nil if this factory does not support a projection.


217
218
219
# File 'lib/rgeo/geographic/factory.rb', line 217

def projection_factory
  @projector&.projection_factory
end

#projection_limits_windowObject

Returns a ProjectedWindow specifying the limits of the domain of the projection space. Returns nil if this factory does not support a projection, or the projection limits are not known.


264
265
266
267
268
269
# File 'lib/rgeo/geographic/factory.rb', line 264

def projection_limits_window
  return @projection_limits_window if defined?(@projection_limits_window)
  return unless @projector

  @projection_limits_window = @projector.limits_window
end

#projection_wraps?Boolean

Returns true if this factory supports a projection and the projection wraps its x (easting) direction. For example, a Mercator projection wraps, but a local projection that is valid only for a small area does not wrap. Returns nil if this factory does not support or a projection, or if it is not known whether or not it wraps.

Returns:

  • (Boolean)

255
256
257
# File 'lib/rgeo/geographic/factory.rb', line 255

def projection_wraps?
  @projector ? @projector.wraps? : nil
end

#property(name) ⇒ Object

See RGeo::Feature::Factory#property


273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/rgeo/geographic/factory.rb', line 273

def property(name)
  case name
  when :has_z_coordinate
    @support_z
  when :has_m_coordinate
    @support_m
  when :buffer_resolution
    @buffer_resolution
  when :is_geographic
    true
  end
end

#psych_wkt_generatorObject


368
369
370
# File 'lib/rgeo/geographic/factory.rb', line 368

def psych_wkt_generator
  @psych_wkt_generator ||= RGeo::WKRep::WKTGenerator.new(tag_format: :wkt12)
end

#psych_wkt_parserObject


372
373
374
# File 'lib/rgeo/geographic/factory.rb', line 372

def psych_wkt_parser
  @psych_wkt_parser ||= RGeo::WKRep::WKTParser.new(self, support_wkt12: true, support_ewkt: true)
end

#unproject(geometry) ⇒ Object

Reverse-projects the given geometry from the projected coordinate space into lat-long space. Raises Error::InvalidGeometry if the given geometry is not of the projection defined by this factory.


238
239
240
241
242
243
244
245
246
# File 'lib/rgeo/geographic/factory.rb', line 238

def unproject(geometry)
  return unless geometry

  unless @projector && @projector.projection_factory == geometry.factory
    raise Error::InvalidGeometry, "You can unproject only features that are in the projected coordinate space."
  end

  @projector.unproject(geometry)
end