rgeo 0.3.5 → 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/History.rdoc +11 -0
  2. data/Version +1 -1
  3. data/ext/geos_c_impl/factory.c +134 -3
  4. data/ext/geos_c_impl/factory.h +5 -0
  5. data/ext/geos_c_impl/geometry_collection.c +18 -12
  6. data/lib/rgeo/cartesian/factory.rb +40 -33
  7. data/lib/rgeo/cartesian/interface.rb +6 -0
  8. data/lib/rgeo/coord_sys/cs/entities.rb +4 -4
  9. data/lib/rgeo/coord_sys/proj4.rb +5 -5
  10. data/lib/rgeo/coord_sys/srs_database/active_record_table.rb +5 -3
  11. data/lib/rgeo/feature/geometry.rb +8 -1
  12. data/lib/rgeo/geographic/factory.rb +124 -1
  13. data/lib/rgeo/geographic/interface.rb +6 -0
  14. data/lib/rgeo/geographic/proj4_projector.rb +6 -0
  15. data/lib/rgeo/geographic/simple_mercator_projector.rb +6 -0
  16. data/lib/rgeo/geos/factory.rb +119 -18
  17. data/lib/rgeo/geos/ffi_classes.rb +10 -5
  18. data/lib/rgeo/geos/ffi_factory.rb +106 -5
  19. data/lib/rgeo/geos/interface.rb +0 -2
  20. data/lib/rgeo/geos/zm_factory.rb +106 -2
  21. data/lib/rgeo/geos/zm_impl.rb +3 -2
  22. data/lib/rgeo/impl_helper.rb +1 -0
  23. data/lib/rgeo/impl_helper/basic_line_string_methods.rb +1 -1
  24. data/lib/rgeo/impl_helper/utils.rb +67 -0
  25. data/lib/rgeo/wkrep/wkb_generator.rb +4 -4
  26. data/lib/rgeo/wkrep/wkb_parser.rb +4 -4
  27. data/lib/rgeo/wkrep/wkt_generator.rb +4 -4
  28. data/lib/rgeo/wkrep/wkt_parser.rb +5 -5
  29. data/test/common/factory_tests.rb +117 -0
  30. data/test/common/geometry_collection_tests.rb +25 -0
  31. data/test/coord_sys/tc_active_record_table.rb +4 -5
  32. data/test/coord_sys/tc_ogc_cs.rb +0 -6
  33. data/test/coord_sys/tc_proj4.rb +4 -6
  34. data/test/geos_capi/tc_factory.rb +5 -33
  35. data/test/geos_capi/tc_zmfactory.rb +6 -0
  36. data/test/geos_ffi/tc_factory.rb +5 -33
  37. data/test/geos_ffi/tc_zmfactory.rb +6 -0
  38. data/test/projected_geographic/tc_factory.rb +63 -0
  39. data/test/simple_cartesian/tc_factory.rb +66 -0
  40. data/test/simple_mercator/tc_factory.rb +63 -0
  41. data/test/spherical_geographic/tc_factory.rb +66 -0
  42. data/test/tc_types.rb +4 -0
  43. metadata +12 -2
@@ -127,8 +127,10 @@ module RGeo
127
127
  @ar_class = ::Class.new(ar_base_class_)
128
128
  self.class.const_set("Klass#{@@class_counter}", @ar_class)
129
129
  @@class_counter += 1
130
- @ar_class.class_eval do
131
- establish_connection(opts_[:database_config]) if opts_[:database_config]
130
+ if opts_[:database_config]
131
+ @ar_class.class_eval do
132
+ establish_connection(opts_[:database_config])
133
+ end
132
134
  end
133
135
  end
134
136
  connection_ = @ar_class.connection
@@ -137,7 +139,7 @@ module RGeo
137
139
  end
138
140
  unless opts_[:ar_class]
139
141
  @ar_class.class_eval do
140
- set_table_name(opts_[:table_name] || 'spatial_ref_sys')
142
+ self.table_name = opts_[:table_name] || 'spatial_ref_sys'
141
143
  end
142
144
  end
143
145
  @srid_column = opts_[:srid_column] || 'srid'
@@ -452,11 +452,18 @@ module RGeo
452
452
  # this geometry, strictly speaking, the result of comparing objects
453
453
  # from different factories is undefined.
454
454
 
455
- def relate(another_geometry_, intersection_pattern_matrix_)
455
+ def relate?(another_geometry_, intersection_pattern_matrix_)
456
456
  raise Error::UnsupportedOperation, "Method Geometry#relate not defined."
457
457
  end
458
458
 
459
459
 
460
+ # Deprecated alias of Geometry#relate?
461
+
462
+ def relate(another_geometry_, intersection_pattern_matrix_)
463
+ relate?(another_geometry_, intersection_pattern_matrix_)
464
+ end
465
+
466
+
460
467
  # === SFS 1.1 Description
461
468
  #
462
469
  # Returns the shortest distance between any two Points in the two
@@ -61,7 +61,7 @@ module RGeo
61
61
  @multi_polygon_class = Geographic.const_get("#{impl_prefix_}MultiPolygonImpl")
62
62
  @support_z = opts_[:has_z_coordinate] ? true : false
63
63
  @support_m = opts_[:has_m_coordinate] ? true : false
64
- @srid = opts_[:srid] || 4326
64
+ @srid = (opts_[:srid] || 4326).to_i
65
65
  @proj4 = opts_[:proj4]
66
66
  if CoordSys::Proj4.supported?
67
67
  if @proj4.kind_of?(::String) || @proj4.kind_of?(::Hash)
@@ -74,6 +74,7 @@ module RGeo
74
74
  if @coord_sys.kind_of?(::String)
75
75
  @coord_sys = CoordSys::CS.create_from_wkt(@coord_sys) rescue nil
76
76
  end
77
+ @lenient_assertions = opts_[:uses_lenient_assertions] ? true : false
77
78
 
78
79
  wkt_generator_ = opts_[:wkt_generator]
79
80
  case wkt_generator_
@@ -103,6 +104,7 @@ module RGeo
103
104
  else
104
105
  @wkb_parser = WKRep::WKBParser.new(self)
105
106
  end
107
+ @projector = nil
106
108
  end
107
109
 
108
110
 
@@ -123,6 +125,125 @@ module RGeo
123
125
  alias_method :==, :eql?
124
126
 
125
127
 
128
+ # Marshal support
129
+
130
+ def marshal_dump # :nodoc:
131
+ hash_ = {
132
+ 'pref' => @impl_prefix,
133
+ 'hasz' => @support_z,
134
+ 'hasm' => @support_m,
135
+ 'srid' => @srid,
136
+ 'wktg' => @wkt_generator._properties,
137
+ 'wkbg' => @wkb_generator._properties,
138
+ 'wktp' => @wkt_parser._properties,
139
+ 'wkbp' => @wkb_parser._properties,
140
+ 'lena' => @lenient_assertions,
141
+ }
142
+ hash_['proj4'] = @proj4.marshal_dump if @proj4
143
+ hash_['cs'] = @coord_sys.to_wkt if @coord_sys
144
+ if @projector
145
+ hash_['prjc'] = @projector.class.name.sub(/.*::/, '')
146
+ hash_['prjf'] = @projector.projection_factory
147
+ end
148
+ hash_
149
+ end
150
+
151
+ def marshal_load(data_) # :nodoc:
152
+ if CoordSys::Proj4.supported? && (proj4_data_ = data_['proj4'])
153
+ proj4_ = CoordSys::Proj4.allocate
154
+ proj4_.marshal_load(proj4_data_)
155
+ else
156
+ proj4_ = nil
157
+ end
158
+ if (coord_sys_data_ = data_['cs'])
159
+ coord_sys_ = CoordSys::CS.create_from_wkt(coord_sys_data_)
160
+ else
161
+ coord_sys_ = nil
162
+ end
163
+ initialize(data_['pref'],
164
+ :has_z_coordinate => data_['hasz'],
165
+ :has_m_coordinate => data_['hasm'],
166
+ :srid => data_['srid'],
167
+ :wkt_generator => ImplHelper::Utils.symbolize_hash(data_['wktg']),
168
+ :wkb_generator => ImplHelper::Utils.symbolize_hash(data_['wkbg']),
169
+ :wkt_parser => ImplHelper::Utils.symbolize_hash(data_['wktp']),
170
+ :wkb_parser => ImplHelper::Utils.symbolize_hash(data_['wkbp']),
171
+ :uses_lenient_assertions => data_['lena'],
172
+ :proj4 => proj4_,
173
+ :coord_sys => coord_sys_
174
+ )
175
+ if (projklass_ = data_['prjc']) && (projfactory_ = data_['prjf'])
176
+ klass_ = ::RGeo::Geographic.const_get(projklass_) rescue nil
177
+ if klass_
178
+ projector_ = klass_.allocate
179
+ projector_._set_factories(self, projfactory_)
180
+ _set_projector(projector_)
181
+ end
182
+ end
183
+ end
184
+
185
+
186
+ # Psych support
187
+
188
+ def encode_with(coder_) # :nodoc:
189
+ coder_['impl_prefix'] = @impl_prefix
190
+ coder_['has_z_coordinate'] = @support_z
191
+ coder_['has_m_coordinate'] = @support_m
192
+ coder_['srid'] = @srid
193
+ coder_['wkt_generator'] = @wkt_generator._properties
194
+ coder_['wkb_generator'] = @wkb_generator._properties
195
+ coder_['wkt_parser'] = @wkt_parser._properties
196
+ coder_['wkb_parser'] = @wkb_parser._properties
197
+ coder_['lenient_assertions'] = @lenient_assertions
198
+ if @proj4
199
+ str_ = @proj4.original_str || @proj4.canonical_str
200
+ coder_['proj4'] = @proj4.radians? ? {'proj4' => str_, 'radians' => true} : str_
201
+ end
202
+ coder_['coord_sys'] = @coord_sys.to_wkt if @coord_sys
203
+ if @projector
204
+ coder_['projector_class'] = @projector.class.name.sub(/.*::/, '')
205
+ coder_['projection_factory'] = @projector.projection_factory
206
+ end
207
+ end
208
+
209
+ def init_with(coder_) # :nodoc:
210
+ if (proj4_data_ = coder_['proj4'])
211
+ if proj4_data_.is_a?(::Hash)
212
+ proj4_ = CoordSys::Proj4.create(proj4_data_['proj4'], :radians => proj4_data_['radians'])
213
+ else
214
+ proj4_ = CoordSys::Proj4.create(proj4_data_.to_s)
215
+ end
216
+ else
217
+ proj4_ = nil
218
+ end
219
+ if (coord_sys_data_ = coder_['cs'])
220
+ coord_sys_ = CoordSys::CS.create_from_wkt(coord_sys_data_.to_s)
221
+ else
222
+ coord_sys_ = nil
223
+ end
224
+ initialize(coder_['impl_prefix'],
225
+ :has_z_coordinate => coder_['has_z_coordinate'],
226
+ :has_m_coordinate => coder_['has_m_coordinate'],
227
+ :srid => coder_['srid'],
228
+ :wkt_generator => ImplHelper::Utils.symbolize_hash(coder_['wkt_generator']),
229
+ :wkb_generator => ImplHelper::Utils.symbolize_hash(coder_['wkb_generator']),
230
+ :wkt_parser => ImplHelper::Utils.symbolize_hash(coder_['wkt_parser']),
231
+ :wkb_parser => ImplHelper::Utils.symbolize_hash(coder_['wkb_parser']),
232
+ :uses_lenient_assertions => coder_['lenient_assertions'],
233
+ :proj4 => proj4_,
234
+ :coord_sys => coord_sys_
235
+ )
236
+ if (projklass_ = coder_['projector_class']) && (projfactory_ = coder_['projection_factory'])
237
+ klass_ = ::RGeo::Geographic.const_get(projklass_) rescue nil
238
+ if klass_
239
+ projector_ = klass_.allocate
240
+ projector_._set_factories(self, projfactory_)
241
+ _set_projector(projector_)
242
+ end
243
+ end
244
+ end
245
+
246
+
126
247
  # Returns the srid reported by this factory.
127
248
 
128
249
  def srid
@@ -210,6 +331,8 @@ module RGeo
210
331
  @support_z
211
332
  when :has_m_coordinate
212
333
  @support_m
334
+ when :uses_lenient_assertions
335
+ @lenient_assertions
213
336
  when :is_geographic
214
337
  true
215
338
  else
@@ -86,6 +86,12 @@ module RGeo
86
86
  # Support a Z coordinate. Default is false.
87
87
  # [<tt>:has_m_coordinate</tt>]
88
88
  # Support an M coordinate. Default is false.
89
+ # [<tt>:uses_lenient_assertions</tt>]
90
+ # If set to true, assertion checking is disabled. This includes
91
+ # simplicity checking on LinearRing, and validity checks on
92
+ # Polygon and MultiPolygon. This may speed up creation of certain
93
+ # objects, at the expense of not doing the proper checking for
94
+ # OGC compliance. Default is false.
89
95
  # [<tt>:proj4</tt>]
90
96
  # Provide the coordinate system in Proj4 format. You may pass
91
97
  # either an RGeo::CoordSys::Proj4 object, or a string or hash
@@ -48,6 +48,12 @@ module RGeo
48
48
  end
49
49
 
50
50
 
51
+ def _set_factories(geography_factory_, projection_factory_) # :nodoc:
52
+ @geography_factory = geography_factory_
53
+ @projection_factory = projection_factory_
54
+ end
55
+
56
+
51
57
  def project(geometry_)
52
58
  Feature.cast(geometry_, @projection_factory, :project)
53
59
  end
@@ -56,6 +56,12 @@ module RGeo
56
56
  end
57
57
 
58
58
 
59
+ def _set_factories(geography_factory_, projection_factory_) # :nodoc:
60
+ @geography_factory = geography_factory_
61
+ @projection_factory = projection_factory_
62
+ end
63
+
64
+
59
65
  def projection_factory
60
66
  @projection_factory
61
67
  end
@@ -117,7 +117,8 @@ module RGeo
117
117
  srid_ ||= coord_sys_.authority_code if coord_sys_
118
118
 
119
119
  # Create the factory and set instance variables
120
- result_ = _create(flags_, srid_.to_i, buffer_resolution_, wkt_generator_, wkb_generator_)
120
+ result_ = _create(flags_, srid_.to_i, buffer_resolution_,
121
+ wkt_generator_, wkb_generator_, proj4_, coord_sys_)
121
122
 
122
123
  # Interpret parser options
123
124
  wkt_parser_ = opts_[:wkt_parser]
@@ -138,14 +139,7 @@ module RGeo
138
139
  else
139
140
  wkb_parser_ = WKRep::WKBParser.new(result_)
140
141
  end
141
-
142
- # Set instance variables
143
- result_.instance_variable_set(:@proj4, proj4_)
144
- result_.instance_variable_set(:@coord_sys, coord_sys_)
145
- result_.instance_variable_set(:@wkt_parser, wkt_parser_)
146
- result_.instance_variable_set(:@wkb_parser, wkb_parser_)
147
- result_.instance_variable_set(:@wkt_generator, wkt_generator_)
148
- result_.instance_variable_set(:@wkb_generator, wkb_generator_)
142
+ result_._set_wkrep_parsers(wkt_parser_, wkb_parser_)
149
143
 
150
144
  # Return the result
151
145
  result_
@@ -166,11 +160,118 @@ module RGeo
166
160
  def eql?(rhs_)
167
161
  rhs_.is_a?(Factory) && rhs_.srid == _srid &&
168
162
  rhs_._buffer_resolution == _buffer_resolution && rhs_._flags == _flags &&
169
- rhs_.proj4 == @proj4
163
+ rhs_.proj4 == _proj4
170
164
  end
171
165
  alias_method :==, :eql?
172
166
 
173
167
 
168
+ # Marshal support
169
+
170
+ def marshal_dump # :nodoc:
171
+ hash_ = {
172
+ 'hasz' => (_flags & 0x2 != 0),
173
+ 'hasm' => (_flags & 0x4 != 0),
174
+ 'srid' => _srid,
175
+ 'bufr' => _buffer_resolution,
176
+ 'wktg' => _wkt_generator._properties,
177
+ 'wkbg' => _wkb_generator._properties,
178
+ 'wktp' => _wkt_parser._properties,
179
+ 'wkbp' => _wkb_parser._properties,
180
+ 'lmpa' => (_flags & 0x1 != 0),
181
+ 'apre' => ((_flags & 0x8) >> 3),
182
+ }
183
+ if (proj4_ = self._proj4)
184
+ hash_['proj4'] = proj4_.marshal_dump
185
+ end
186
+ if (coord_sys_ = self._coord_sys)
187
+ hash_['cs'] = coord_sys_.to_wkt
188
+ end
189
+ hash_
190
+ end
191
+
192
+ def marshal_load(data_) # :nodoc:
193
+ if CoordSys::Proj4.supported? && (proj4_data_ = data_['proj4'])
194
+ proj4_ = CoordSys::Proj4.allocate
195
+ proj4_.marshal_load(proj4_data_)
196
+ else
197
+ proj4_ = nil
198
+ end
199
+ if (coord_sys_data_ = data_['cs'])
200
+ coord_sys_ = CoordSys::CS.create_from_wkt(coord_sys_data_)
201
+ else
202
+ coord_sys_ = nil
203
+ end
204
+ initialize_copy(Factory.create(
205
+ :has_z_coordinate => data_['hasz'],
206
+ :has_m_coordinate => data_['hasm'],
207
+ :srid => data_['srid'],
208
+ :buffer_resolution => data_['bufr'],
209
+ :wkt_generator => ImplHelper::Utils.symbolize_hash(data_['wktg']),
210
+ :wkb_generator => ImplHelper::Utils.symbolize_hash(data_['wkbg']),
211
+ :wkt_parser => ImplHelper::Utils.symbolize_hash(data_['wktp']),
212
+ :wkb_parser => ImplHelper::Utils.symbolize_hash(data_['wkbp']),
213
+ :uses_lenient_multi_polygon_assertions => data_['lmpa'],
214
+ :auto_prepare => (data_['apre'] == 0 ? :disabled : :simple),
215
+ :proj4 => proj4_,
216
+ :coord_sys => coord_sys_
217
+ ))
218
+ end
219
+
220
+
221
+ # Psych support
222
+
223
+ def encode_with(coder_) # :nodoc:
224
+ coder_['has_z_coordinate'] = (_flags & 0x2 != 0)
225
+ coder_['has_m_coordinate'] = (_flags & 0x4 != 0)
226
+ coder_['srid'] = _srid
227
+ coder_['buffer_resolution'] = _buffer_resolution
228
+ coder_['lenient_multi_polygon_assertions'] = (_flags & 0x1 != 0)
229
+ coder_['wkt_generator'] = _wkt_generator._properties
230
+ coder_['wkb_generator'] = _wkb_generator._properties
231
+ coder_['wkt_parser'] = _wkt_parser._properties
232
+ coder_['wkb_parser'] = _wkb_parser._properties
233
+ coder_['auto_prepare'] = ((_flags & 0x8) == 0 ? 'disabled' : 'simple')
234
+ if (proj4_ = self._proj4)
235
+ str_ = proj4_.original_str || proj4_.canonical_str
236
+ coder_['proj4'] = proj4_.radians? ? {'proj4' => str_, 'radians' => true} : str_
237
+ end
238
+ if (coord_sys_ = self._coord_sys)
239
+ coder_['coord_sys'] = coord_sys_.to_wkt
240
+ end
241
+ end
242
+
243
+ def init_with(coder_) # :nodoc:
244
+ if (proj4_data_ = coder_['proj4'])
245
+ if proj4_data_.is_a?(::Hash)
246
+ proj4_ = CoordSys::Proj4.create(proj4_data_['proj4'], :radians => proj4_data_['radians'])
247
+ else
248
+ proj4_ = CoordSys::Proj4.create(proj4_data_.to_s)
249
+ end
250
+ else
251
+ proj4_ = nil
252
+ end
253
+ if (coord_sys_data_ = coder_['cs'])
254
+ coord_sys_ = CoordSys::CS.create_from_wkt(coord_sys_data_.to_s)
255
+ else
256
+ coord_sys_ = nil
257
+ end
258
+ initialize_copy(Factory.create(
259
+ :has_z_coordinate => coder_['has_z_coordinate'],
260
+ :has_m_coordinate => coder_['has_m_coordinate'],
261
+ :srid => coder_['srid'],
262
+ :buffer_resolution => coder_['buffer_resolution'],
263
+ :wkt_generator => ImplHelper::Utils.symbolize_hash(coder_['wkt_generator']),
264
+ :wkb_generator => ImplHelper::Utils.symbolize_hash(coder_['wkb_generator']),
265
+ :wkt_parser => ImplHelper::Utils.symbolize_hash(coder_['wkt_parser']),
266
+ :wkb_parser => ImplHelper::Utils.symbolize_hash(coder_['wkb_parser']),
267
+ :auto_prepare => coder_['auto_prepare'] == 'disabled' ? :disabled : :simple,
268
+ :uses_lenient_multi_polygon_assertions => coder_['lenient_multi_polygon_assertions'],
269
+ :proj4 => proj4_,
270
+ :coord_sys => coord_sys_
271
+ ))
272
+ end
273
+
274
+
174
275
  # Returns the SRID of geometries created by this factory.
175
276
 
176
277
  def srid
@@ -218,8 +319,8 @@ module RGeo
218
319
  # See ::RGeo::Feature::Factory#parse_wkt
219
320
 
220
321
  def parse_wkt(str_)
221
- if @wkt_parser
222
- @wkt_parser.parse(str_)
322
+ if (wkt_parser_ = self._wkt_parser)
323
+ wkt_parser_.parse(str_)
223
324
  else
224
325
  _parse_wkt_impl(str_)
225
326
  end
@@ -229,8 +330,8 @@ module RGeo
229
330
  # See ::RGeo::Feature::Factory#parse_wkb
230
331
 
231
332
  def parse_wkb(str_)
232
- if @wkb_parser
233
- @wkb_parser.parse(str_)
333
+ if (wkb_parser_ = self._wkb_parser)
334
+ wkb_parser_.parse(str_)
234
335
  else
235
336
  _parse_wkb_impl(str_)
236
337
  end
@@ -314,14 +415,14 @@ module RGeo
314
415
  # See ::RGeo::Feature::Factory#proj4
315
416
 
316
417
  def proj4
317
- @proj4
418
+ _proj4
318
419
  end
319
420
 
320
421
 
321
422
  # See ::RGeo::Feature::Factory#coord_sys
322
423
 
323
424
  def coord_sys
324
- @coord_sys
425
+ _coord_sys
325
426
  end
326
427
 
327
428
 
@@ -340,7 +441,7 @@ module RGeo
340
441
  # factories are zm-compatible and proj4-compatible.
341
442
  if original_.factory != self && ntype_ == type_ &&
342
443
  original_.factory._flags & 0x6 == _flags & 0x6 &&
343
- (!project_ || original_.factory.proj4 == @proj4)
444
+ (!project_ || original_.factory.proj4 == _proj4)
344
445
  then
345
446
  result_ = original_.dup
346
447
  result_._set_factory(self)
@@ -349,7 +450,7 @@ module RGeo
349
450
  # LineString conversion optimization.
350
451
  if (original_.factory != self || ntype_ != type_) &&
351
452
  original_.factory._flags & 0x6 == _flags & 0x6 &&
352
- (!project_ || original_.factory.proj4 == @proj4) &&
453
+ (!project_ || original_.factory.proj4 == _proj4) &&
353
454
  type_.subtype_of?(Feature::LineString) && ntype_.subtype_of?(Feature::LineString)
354
455
  then
355
456
  return IMPL_CLASSES[ntype_]._copy_from(self, original_)
@@ -96,7 +96,6 @@ module RGeo
96
96
 
97
97
  end
98
98
 
99
-
100
99
  end
101
100
 
102
101
 
@@ -298,10 +297,11 @@ module RGeo
298
297
  end
299
298
 
300
299
 
301
- def relate(rhs_, pattern_)
300
+ def relate?(rhs_, pattern_)
302
301
  fg_ = factory._convert_to_fg_geometry(rhs_)
303
302
  fg_ ? @fg_geom.relate_pattern(fg_, pattern_) : nil
304
303
  end
304
+ alias_method :relate, :relate? # DEPRECATED
305
305
 
306
306
 
307
307
  def distance(rhs_)
@@ -651,9 +651,14 @@ module RGeo
651
651
 
652
652
 
653
653
  def each
654
- @fg_geom.num_geometries.times do |n_|
655
- yield @factory.wrap_fg_geom(@fg_geom.get_geometry_n(n_),
656
- @_klasses ? @_klasses[n_] : nil)
654
+ if block_given?
655
+ @fg_geom.num_geometries.times do |n_|
656
+ yield @factory.wrap_fg_geom(@fg_geom.get_geometry_n(n_),
657
+ @_klasses ? @_klasses[n_] : nil)
658
+ end
659
+ self
660
+ else
661
+ enum_for
657
662
  end
658
663
  end
659
664