Class: Proj::PjObject

Inherits:
Object
  • Object
show all
Defined in:
lib/proj/pj_object.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(pointer, context = nil) ⇒ PjObject

Returns a new instance of PjObject.



191
192
193
194
195
196
197
198
# File 'lib/proj/pj_object.rb', line 191

def initialize(pointer, context=nil)
  if pointer.null?
    raise(Error, "Cannot create a PjObject with a null pointer")
  end
  @pointer = pointer
  @context = context
  ObjectSpace.define_finalizer(self, self.class.finalize(@pointer, @context))
end

Class Method Details

.create(value, context = nil) ⇒ PjObject

Instantiates an object from a string

Examples:

conversion = Proj::Conversion.create("+proj=helmert")

Parameters:

  • value (String)

    Can be:

    • Proj string

    • WKT string

    • Object code (like “EPSG:4326”, “urn:ogc:def:crs:EPSG::4326”, “urn:ogc:def:coordinateOperation:EPSG::1671”),

    • Object name. e.g “WGS 84”, “WGS 84 / UTM zone 31N”. In that case as uniqueness is not guaranteed, heuristics are applied to determine the appropriate best match.

    • OGC URN combining references for compound coordinate reference systems (e.g “urn:ogc:def:crs,crs:EPSG::2393,crs:EPSG::5717” or custom abbreviated syntax “EPSG:2393+5717”),

    • OGC URN combining references for concatenated operations (e.g. “urn:ogc:def:coordinateOperation,coordinateOperation:EPSG::3895,coordinateOperation:EPSG::1618”)

    • PROJJSON string. The jsonschema is at proj.org/schemas/v0.4/projjson.schema.json (added in 6.2)

    • compound CRS made from two object names separated with “ + ”. e.g. “WGS 84 + EGM96 height” (added in 7.1)

Returns:

See Also:



67
68
69
70
71
72
73
74
75
# File 'lib/proj/pj_object.rb', line 67

def self.create(value, context=nil)
  ptr = Api.proj_create(context || Context.current, value)

  if ptr.null?
    Error.check_object(self)
  end

  create_object(ptr, context)
end

.create_from_database(auth_name, code, category, use_alternative_grid_names = false, context = nil) ⇒ PjObject

Instantiates an object from a database lookup

Examples:

crs = Proj::Crs.create_from_database("EPSG", "32631", :PJ_CATEGORY_CRS)

Parameters:

  • auth_name (String)

    Authority name (must not be nil)

  • code (String)

    Object code (must not be nil)

  • category (PjCategory)

    A PjCategory enum value

  • use_alternative_grid_names (Boolean) (defaults to: false)

    Whether PROJ alternative grid names should be substituted to the official grid names. Only used on transformations. Defaults to false

  • context (Context) (defaults to: nil)

    Context. If nil the current context is used

Returns:

See Also:



91
92
93
94
95
96
97
98
99
100
101
# File 'lib/proj/pj_object.rb', line 91

def self.create_from_database(auth_name, code, category, use_alternative_grid_names = false, context = nil)
  context ||= Context.current
  ptr = Api.proj_create_from_database(context, auth_name, code, category,
                                      use_alternative_grid_names ? 1 : 0, nil)

  if ptr.null?
    Error.check_context(context)
  end

  create_object(ptr, context)
end

.create_from_name(name, context, auth_name: nil, types: nil, approximate_match: false, limit: 0) ⇒ PjObjects

Return a list of objects by their name

Examples:

objects = Proj::PjObject.create_from_name("WGS 84", Context.current)

Parameters:

  • name (String)

    Search value, must be at least two characters

  • context (Context)

    Context. If nil the current context is used

  • auth_name (String) (defaults to: nil)

    Authority name or nil for all authorities. Default is nil

  • types (Array<PjType>) (defaults to: nil)

    Types of objects to search for or nil for all types. Default is nil

  • approximate_match (Boolean) (defaults to: false)

    Whether approximate name identification is allowed. Default is false

  • limit (Integer) (defaults to: 0)

    The maximum number of results to return, use 0 for all results. Default is 0

Returns:

See Also:



118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/proj/pj_object.rb', line 118

def self.create_from_name(name, context, auth_name: nil, types: nil, approximate_match: false, limit: 0)
  if types
    types_ptr = FFI::MemoryPointer.new(Api::PjType.native_type, types.size)
    types_ptr.write_array_of_int(types.map { |symbol| Api::PjType[symbol]})
    types_count = types.size
  else
    types_ptr = nil
    types_count = 0
  end

  ptr = Api.proj_create_from_name(context, auth_name, name, types_ptr, types_count, approximate_match ? 1 : 0, limit, nil)
  PjObjects.new(ptr, context)
end

.create_from_wkt(wkt, context = nil, strict: false, unset_identifiers: nil) ⇒ PjObject

Instantiates an object from a WKT string.

Parameters:

  • wkt (String)

    WKT string (must not be nil)

  • context (Context) (defaults to: nil)

    Context. If nil the current context is used

  • strict (Boolean) (defaults to: false)

    Enables strict validation will be enabled. Default is false

  • unset_identifiers (Boolean) (defaults to: nil)

    When enabled object identifiers are unset when there is a contradiction between the definition from WKT and the one from the database. Defaults to nil because this option is only available in Proj 9+

Returns:

See Also:



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/proj/pj_object.rb', line 145

def self.create_from_wkt(wkt, context = nil, strict: false, unset_identifiers: nil)
  out_warnings = FFI::MemoryPointer.new(:pointer)
  out_grammar_errors = FFI::MemoryPointer.new(:pointer)

  # @param wkt_type [PjWktType] WKT version to output. Defaults to PJ_WKT2_2018
  # @param multiline [Boolean] Specifies if output span multiple lines. Defaults to true.
  # @param indentation_width [Integer] Specifies the indentation level. Defaults to 4.
  #
  # @return [String] wkt

  # Unset
  options_hash = {"STRICT": strict ? "YES" : "NO"}
  case unset_identifiers
  when TrueClass
    options_hash["UNSET_IDENTIFIERS_IF_INCOMPATIBLE_DEF"] = "YES"
  when FalseClass
    options_hash["UNSET_IDENTIFIERS_IF_INCOMPATIBLE_DEF"] = "NO"
  end
  options = Options.new(options_hash)

  ptr = Api.proj_create_from_wkt(context, wkt, options, out_warnings, out_grammar_errors)

  warnings = Strings.new(out_warnings.read_pointer)
  errors = Strings.new(out_grammar_errors.read_pointer)

  unless errors.empty?
    raise(RuntimeError, errors.join(". "))
  end

  unless warnings.empty?
    warn(warnings.join(". "))
  end

  create_object(ptr, context)
end

Instance Method Details

#accuracyFloat

Expected accuracy of the transformation. -1 if unknown



325
326
327
# File 'lib/proj/pj_object.rb', line 325

def accuracy
  self.info[:accuracy]
end

#area_of_useArea

Return the area of use of an object.

Returns:

  • (Area)

    In case of multiple usages, this will be the one of first usage.

See Also:



415
416
417
# File 'lib/proj/pj_object.rb', line 415

def area_of_use
  domains.first&.area_of_use
end

#auth(index = 0) ⇒ Object



387
388
389
390
391
392
393
394
395
396
397
398
# File 'lib/proj/pj_object.rb', line 387

def auth(index=0)
  auth_name = self.auth_name(index)
  code = self.id_code(index)

  if auth_name and code
    "#{self.auth_name(index)}:#{self.id_code(index)}"
  elsif auth_name
    auth_name
  elsif code
    code
  end
end

#auth_name(index = 0) ⇒ String

Returns the authority name / codespace of an identifier of an object.

Parameters:

  • index (Integer) (defaults to: 0)

    Index of the identifier. 0 is for the first identifier. Default is 0.

Returns:

  • (String)

See Also:



354
355
356
# File 'lib/proj/pj_object.rb', line 354

def auth_name(index=0)
  Api.proj_get_id_auth_name(self, index)&.force_encoding('UTF-8')
end

#contextObject



232
233
234
# File 'lib/proj/pj_object.rb', line 232

def context
  @context || Context.current
end

#context=(value) ⇒ Object

Assign a new context to this object

Parameters:

  • value (Context)

    The context to assign to this object



221
222
223
224
225
226
# File 'lib/proj/pj_object.rb', line 221

def context=(value)
  Api.proj_assign_context(self, value)
  @context = value
  ObjectSpace.undefine_finalizer(self)
  ObjectSpace.define_finalizer(self, self.class.finalize(@pointer, @context))
end

#definitionString

The proj-string that was used to create the PJ object with, e.g. “+proj=merc lat_0=24 lon_0=53 +ellps=WGS84”



307
308
309
# File 'lib/proj/pj_object.rb', line 307

def definition
  self.info[:definition] ? self.info[:definition].force_encoding('UTF-8') : nil
end

#deprecated?Boolean

Returns whether an object is deprecated

Returns:

  • (Boolean)

    True if the object is deprecated, otherwise false

See Also:



241
242
243
244
# File 'lib/proj/pj_object.rb', line 241

def deprecated?
  result = Api.proj_is_deprecated(self)
  result == 1 ? true : false
end

#descriptionString

Long description of the operation the PJ object is based on, e.g. “Mercator Cyl, Sph&Ell lat_ts=”



298
299
300
# File 'lib/proj/pj_object.rb', line 298

def description
  self.info[:description] ? self.info[:description].force_encoding('UTF-8') : nil
end

#destroyObject

Explicitly free the underlying PROJ object.



211
212
213
214
215
216
# File 'lib/proj/pj_object.rb', line 211

def destroy
  Api.proj_destroy(@pointer)
  @pointer = FFI::Pointer::NULL
  ObjectSpace.undefine_finalizer(self)
  nil
end

#domainsArray<Domain>

Returns all usage domains for this object. Each domain has a scope and geographic area of use.

Returns:

See Also:



406
407
408
# File 'lib/proj/pj_object.rb', line 406

def domains
  Domain.domains(self)
end

#equivalent_to?(other, comparison) ⇒ Boolean

Return whether two objects are equivalent. For versions 6.3.0 and higher the check may use using the proj database to check for name aliases

Parameters:

  • other (PjObject)

    Object to compare to

  • comparison (PjComparisonCriterion)

    Comparison criterion

Returns:

  • (Boolean)

    True if the objects are equivalent, otherwise false

See Also:



256
257
258
259
260
261
262
263
# File 'lib/proj/pj_object.rb', line 256

def equivalent_to?(other, comparison)
  result = if defined?(Api.proj_is_equivalent_to_with_ctx)
             Api.proj_is_equivalent_to_with_ctx(self.context, self, other, comparison)
           else
             Api.proj_is_equivalent_to(self, other, comparison)
           end
  result == 1 ? true : false
end

#errornoInteger

Returns the current error-state of this object

Returns:

  • (Integer)

    An non-zero error codes indicates an error either with the transformation setup or during a transformation

See Also:



270
271
272
# File 'lib/proj/pj_object.rb', line 270

def errorno
  Api.proj_errno(self)
end

#factors(coordinate) ⇒ PJ_FACTORS

Calculate various cartographic properties, such as scale factors, angular distortion and meridian convergence. Depending on the underlying projection values will be calculated either numerically (default) or analytically. The function also calculates the partial derivatives of the given coordinate.

Parameters:

  • coordinate (Coordinate)

    Input geodetic coordinate in radians

Returns:

  • (PJ_FACTORS)

See Also:



450
451
452
# File 'lib/proj/pj_object.rb', line 450

def factors(coordinate)
  Api.proj_factors(self, coordinate)
end

#geod_direct(coord, azi1, s12) ⇒ Coordinate

Compute the endpoint from a start point, initial azimuth, and distance.

Parameters:

  • coord (Coordinate)

    Start coordinate (lon/lat in radians)

  • azi1 (Float)

    Forward azimuth at the start point (radians)

  • s12 (Float)

    Distance from the start point (meters)

Returns:

  • (Coordinate)

    Endpoint coordinate and reverse azimuth

See Also:



523
524
525
526
# File 'lib/proj/pj_object.rb', line 523

def geod_direct(coord, azi1, s12)
  ptr = Api.proj_geod_direct(self, coord, azi1, s12)
  Coordinate.from_coord(ptr)
end

#geod_distance(coord1, coord2) ⇒ Coordinate

Calculate the geodesic distance as well as forward and reverse azimuth between two points on the ellipsoid.

Note that the axis order of the transformation object is not taken into account, so even though a CRS object comes with axis ordering latitude/longitude coordinates used in this function should be reordered as longitude/latitude.

the second is the forward azimuth, the third value the reverse azimuth and the fourth value is unused.

Parameters:

  • coord1 (Coordinate)

    Coordinate of first point. Must be lat/long in radians

  • coord2 (Coordinate)

    Coordinate of second point. Must be lat/long in radians

Returns:

  • (Coordinate)

    The first value is the distance between coord1 and coord2 in meters,

See Also:



509
510
511
512
# File 'lib/proj/pj_object.rb', line 509

def geod_distance(coord1, coord2)
  ptr = Api.proj_geod(self, coord1, coord2)
  Coordinate.from_coord(ptr)
end

#has_inverse?Boolean

Returns true if an an inverse mapping of the defined operation exists, otherwise false



316
317
318
# File 'lib/proj/pj_object.rb', line 316

def has_inverse?
  self.info[:has_inverse] == 1 ? true : false
end

#idString

Short ID of the operation the PJ object is based on, that is, what comes after the +proj= in a proj-string, e.g. “merc”.



289
290
291
# File 'lib/proj/pj_object.rb', line 289

def id
  self.info[:id]
end

#id_code(index = 0) ⇒ String

Get the code of an identifier of an object

Parameters:

  • index (Integer) (defaults to: 0)

    Index of the identifier. 0 is the first identifier. Default is 0

Returns:

  • (String)

    The code or nil in case of error or missing name

See Also:



365
366
367
# File 'lib/proj/pj_object.rb', line 365

def id_code(index=0)
  Api.proj_get_id_code(self, index)
end

#infoPjProjInfo

Get information about this object



279
280
281
# File 'lib/proj/pj_object.rb', line 279

def info
  Api.proj_pj_info(self)
end

#initialize_copy(original) ⇒ Object



200
201
202
203
204
205
206
207
208
# File 'lib/proj/pj_object.rb', line 200

def initialize_copy(original)
  ObjectSpace.undefine_finalizer(self)

  super

  @pointer = Api.proj_clone(original.context, original)

  ObjectSpace.define_finalizer(self, self.class.finalize(@pointer, @context))
end

#lp_distance(coord1, coord2) ⇒ Float

Calculate geodesic distance between two points in geodetic coordinates. The calculated distance is between the two points located on the ellipsoid. Note that the axis order of the transformation object is not taken into account, so even though a CRS object comes with axis ordering latitude/longitude coordinates used in this function should be reordered as longitude/latitude.

Parameters:

  • coord1 (Coordinate)

    Coordinate of first point. Must be lat/long in radians

  • coord2 (Coordinate)

    Coordinate of second point. Must be lat/long in radians

Returns:

  • (Float)

    Distance between the coordinates in meters

See Also:



475
476
477
# File 'lib/proj/pj_object.rb', line 475

def lp_distance(coord1, coord2)
  Api.proj_lp_dist(self, coord1, coord2)
end

#lpz_distance(coord1, coord2) ⇒ Float

Calculate geodesic distance between two points in geodetic coordinates. Similar to PjObject#lp_distance but also takes the height above the ellipsoid into account.

Note that the axis order of the transformation object is not taken into account, so even though a CRS object comes with axis ordering latitude/longitude coordinates used in this function should be reordered as longitude/latitude.

Parameters:

  • coord1 (Coordinate)

    Coordinate of first point. Must be lat/long in radians

  • coord2 (Coordinate)

    Coordinate of second point. Must be lat/long in radians

Returns:

  • (Float)

    Distance between the coordinates in meters

See Also:



492
493
494
# File 'lib/proj/pj_object.rb', line 492

def lpz_distance(coord1, coord2)
  Api.proj_lpz_dist(self, coord1, coord2)
end

#nameString

Returns the name of an object



343
344
345
# File 'lib/proj/pj_object.rb', line 343

def name
  Api.proj_get_name(self)&.force_encoding('UTF-8')
end

#non_deprecatedArray

Return a list of non-deprecated objects related to the passed one



459
460
461
462
# File 'lib/proj/pj_object.rb', line 459

def non_deprecated
  ptr = Api.proj_get_non_deprecated(self.context, self)
  PjObjects.new(ptr, self.context)
end

#proj_typePjType

Return the type of an object



334
335
336
# File 'lib/proj/pj_object.rb', line 334

def proj_type
  Api.proj_get_type(self)
end

#remarksString

Get the remarks of an object

Returns:

  • (String)

    Remarks or nil in case of error

See Also:



374
375
376
# File 'lib/proj/pj_object.rb', line 374

def remarks
  Api.proj_get_remarks(self)
end

#scopeString

Get the scope of an object.

Returns:

  • (String)

    Scope or nil in case of error or a missing scope

See Also:



383
384
385
# File 'lib/proj/pj_object.rb', line 383

def scope
  domains.first&.scope
end

#source_crsCrs

Return the base CRS of a BoundCRS or a DerivedCRS/ProjectedCRS, or the source CRS of a CoordinateOperation, or the CRS of a CoordinateMetadata.



425
426
427
428
# File 'lib/proj/pj_object.rb', line 425

def source_crs
  ptr = Api.proj_get_source_crs(self.context, self)
  self.class.create_object(ptr, self.context)
end

#target_crsCrs

Return the hub CRS of a BoundCRS or the target CRS of a CoordinateOperation



435
436
437
438
# File 'lib/proj/pj_object.rb', line 435

def target_crs
  ptr = Api.proj_get_target_crs(self.context, self)
  self.class.create_object(ptr, self.context)
end

#to_json(multiline: true, indentation_width: 2) ⇒ String

Returns the json representation for this object

Parameters:

  • multiline (Boolean) (defaults to: true)

    Specifies if output span multiple lines. Defaults to true.

  • indentation_width (Integer) (defaults to: 2)

    Specifies the indentation level. Defaults to 2.

Returns:

  • (String)

See Also:



558
559
560
561
562
563
# File 'lib/proj/pj_object.rb', line 558

def to_json(multiline: true, indentation_width: 2)
  options = Options.new("MULTILINE": multiline ? "YES" : "NO",
                        "INDENTATION_WIDTH": indentation_width)

  Api.proj_as_projjson(self.context, self, options).force_encoding('UTF-8')
end

#to_proj_string(proj_version = :PJ_PROJ_5, use_approx_tmerc: false, multiline: false, indentation_width: 2, max_line_length: 80) ⇒ String

Returns the proj representation string for this object

Parameters:

  • proj_version (PjProjStringType) (defaults to: :PJ_PROJ_5)

    The proj version. Defaults to :PJ_PROJ_5

  • use_approx_tmerc (Boolean) (defaults to: false)

    True adds the approx flag to proj=tmerc or +proj=utm. Defaults to false

  • multiline (Boolean) (defaults to: false)

    Specifies if output span multiple lines. Defaults to false.

  • indentation_width (Integer) (defaults to: 2)

    Specifies the indentation level. Defaults to 2.

  • max_line_length (Integer) (defaults to: 80)

    Specifies the max line length level. Defaults to 80.

Returns:

  • (String)

See Also:



539
540
541
542
543
544
545
546
547
548
# File 'lib/proj/pj_object.rb', line 539

def to_proj_string(proj_version=:PJ_PROJ_5, use_approx_tmerc: false, multiline: false,
                                            indentation_width: 2, max_line_length: 80)

  options = Options.new("USE_APPROX_TMERC": use_approx_tmerc ? "YES" : "NO",
                        "MULTILINE": multiline ? "YES" : "NO",
                        "INDENTATION_WIDTH": indentation_width,
                        "MAX_LINE_LENGTH": max_line_length)

  Api.proj_as_proj_string(self.context, self, proj_version, options).force_encoding('UTF-8')
end

#to_ptrObject



228
229
230
# File 'lib/proj/pj_object.rb', line 228

def to_ptr
  @pointer
end

#to_sString

Returns the string representation for this object

Returns:

  • (String)

    String



593
594
595
# File 'lib/proj/pj_object.rb', line 593

def to_s
  "#<#{self.class.name} - #{name}, #{proj_type}>"
end

#to_wkt(wkt_type = :PJ_WKT2_2019, multiline: true, indentation_width: 4) ⇒ String

Returns the wkt representation for this object

Parameters:

  • wkt_type (PjWktType) (defaults to: :PJ_WKT2_2019)

    WKT version to output. Defaults to PJ_WKT2_2018

  • multiline (Boolean) (defaults to: true)

    Specifies if output span multiple lines. Defaults to true.

  • indentation_width (Integer) (defaults to: 4)

    Specifies the indentation level. Defaults to 4.

Returns:

  • (String)

    wkt

See Also:



574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
# File 'lib/proj/pj_object.rb', line 574

def to_wkt(wkt_type=:PJ_WKT2_2019, multiline: true, indentation_width: 4)
  options = Options.new("MULTILINE": multiline ? "YES" : "NO",
                        "INDENTATION_WIDTH": indentation_width,
                        "OUTPUT_AXIS": "AUTO",
                        "STRICT": "YES",
                        "ALLOW_ELLIPSOIDAL_HEIGHT_AS_VERTICAL_CRS": "NO")

  result = Api.proj_as_wkt(self.context, self, wkt_type, options)

  if result.nil?
    Error.check_object(self)
  end

  result.force_encoding('UTF-8')
end