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.



187
188
189
190
191
192
193
194
# File 'lib/proj/pj_object.rb', line 187

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))
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:



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

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 (PJ_CATEGORY)

    A PJ_CATEGORY 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:



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

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<PJ_TYPE>) (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:



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

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::PJ_TYPE.native_type, types.size)
    types_ptr.write_array_of_int(types.map { |symbol| Api::PJ_TYPE[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:



144
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
# File 'lib/proj/pj_object.rb', line 144

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 [PJ_WKT_TYPE] 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 = {"STRICT": strict ? "YES" : "NO"}
  case unset_identifiers
  when TrueClass
    options["UNSET_IDENTIFIERS_IF_INCOMPATIBLE_DEF"] = "YES"
  when FalseClass
    options["UNSET_IDENTIFIERS_IF_INCOMPATIBLE_DEF"] = "NO"
  end
  options_ptr = create_options_pointer(options)

  ptr = Api.proj_create_from_wkt(context, wkt, options_ptr, 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



314
315
316
# File 'lib/proj/pj_object.rb', line 314

def accuracy
  self.info[:accuracy]
end

#angular_input?(direction) ⇒ Boolean

Returns if an operation expects input in radians

Parameters:

  • direction
    ]PJ_DIRECTION

    Direction of transformation

Returns:

  • (Boolean)

See Also:



541
542
543
544
# File 'lib/proj/pj_object.rb', line 541

def angular_input?(direction)
  result = Api.proj_angular_input(self, direction)
  result == 1 ? true : false
end

#angular_output?(direction) ⇒ Boolean

Check if an operation returns output in radians

Parameters:

  • direction
    ]PJ_DIRECTION

    Direction of transformation

Returns:

  • (Boolean)

See Also:



551
552
553
554
# File 'lib/proj/pj_object.rb', line 551

def angular_output?(direction)
  result = Api.proj_angular_output(self, direction)
  result == 1 ? true : false
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:



394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
# File 'lib/proj/pj_object.rb', line 394

def area_of_use
  p_name = FFI::MemoryPointer.new(:pointer)
  p_west_lon_degree = FFI::MemoryPointer.new(:double)
  p_south_lat_degree = FFI::MemoryPointer.new(:double)
  p_east_lon_degree = FFI::MemoryPointer.new(:double)
  p_north_lat_degree = FFI::MemoryPointer.new(:double)

  result = Api.proj_get_area_of_use(self.context, self,
                                    p_west_lon_degree, p_south_lat_degree, p_east_lon_degree, p_north_lat_degree,
                                    p_name)
  if result != 1
    Error.check_object(self)
  end

  name = p_name.read_pointer.read_string_to_null.force_encoding('utf-8')
  Area.new(west_lon_degree: p_west_lon_degree.read_double,
           south_lat_degree: p_south_lat_degree.read_double,
           east_lon_degree: p_east_lon_degree.read_double,
           north_lat_degree: p_north_lat_degree.read_double,
           name: name)
end

#auth(index = 0) ⇒ Object



376
377
378
379
380
381
382
383
384
385
386
387
# File 'lib/proj/pj_object.rb', line 376

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:



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

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

#contextObject



217
218
219
# File 'lib/proj/pj_object.rb', line 217

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



209
210
211
# File 'lib/proj/pj_object.rb', line 209

def context=(value)
  Api.proj_assign_context(self, value)
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”



296
297
298
# File 'lib/proj/pj_object.rb', line 296

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

#degree_input?(direction) ⇒ Boolean

Returns if an operation expects input in degrees

Parameters:

  • direction
    ]PJ_DIRECTION

    Direction of transformation

Returns:

  • (Boolean)

See Also:



561
562
563
564
# File 'lib/proj/pj_object.rb', line 561

def degree_input?(direction)
  result = Api.proj_degree_input(self, direction)
  result == 1 ? true : false
end

#degree_output?(direction) ⇒ Boolean

Check if an operation returns output in degrees

Parameters:

  • direction
    ]PJ_DIRECTION

    Direction of transformation

Returns:

  • (Boolean)

See Also:



571
572
573
574
# File 'lib/proj/pj_object.rb', line 571

def degree_output?(direction)
  result = Api.proj_degree_output(self, direction)
  result == 1 ? true : false
end

#deprecated?Boolean

Returns whether an object is deprecated

Returns:

  • (Boolean)

    True if the object is deprecated, otherwise false

See Also:



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

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=”



287
288
289
# File 'lib/proj/pj_object.rb', line 287

def description
  self.info[:description] ? self.info[:description].force_encoding('UTF-8') : nil
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 (PJ_COMPARISON_CRITERION)

    Comparison criterion

Returns:

  • (Boolean)

    True if the objects are equivalent, otherwise false

See Also:



245
246
247
248
249
250
251
252
# File 'lib/proj/pj_object.rb', line 245

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

#errnoObject



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

def errno
  Api.proj_errno(self)
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:



259
260
261
# File 'lib/proj/pj_object.rb', line 259

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:



447
448
449
# File 'lib/proj/pj_object.rb', line 447

def factors(coordinate)
  Api.proj_factors(self, coordinate)
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 first point. Must be lat/long in radians

Returns:

  • (Coordinate)

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

See Also:



531
532
533
534
# File 'lib/proj/pj_object.rb', line 531

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



305
306
307
# File 'lib/proj/pj_object.rb', line 305

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”.



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

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:



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

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

#infoPJ_PROJ_INFO

Get information about this object



268
269
270
# File 'lib/proj/pj_object.rb', line 268

def info
  Api.proj_pj_info(self)
end

#initialize_copy(original) ⇒ Object



196
197
198
199
200
201
202
203
204
# File 'lib/proj/pj_object.rb', line 196

def initialize_copy(original)
  ObjectSpace.undefine_finalizer(self)

  super

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

  ObjectSpace.define_finalizer(self, self.class.finalize(@pointer))
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:



472
473
474
# File 'lib/proj/pj_object.rb', line 472

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:



489
490
491
# File 'lib/proj/pj_object.rb', line 489

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

#nameString

Returns the name of an object



332
333
334
# File 'lib/proj/pj_object.rb', line 332

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



456
457
458
459
# File 'lib/proj/pj_object.rb', line 456

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

#proj_typePJ_TYPE

Return the type of an object



323
324
325
# File 'lib/proj/pj_object.rb', line 323

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:



363
364
365
# File 'lib/proj/pj_object.rb', line 363

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:



372
373
374
# File 'lib/proj/pj_object.rb', line 372

def scope
  Api.proj_get_scope(self)
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.



422
423
424
425
# File 'lib/proj/pj_object.rb', line 422

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



432
433
434
435
# File 'lib/proj/pj_object.rb', line 432

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:



607
608
609
610
611
612
613
# File 'lib/proj/pj_object.rb', line 607

def to_json(multiline: true, indentation_width: 2)
  options = {"MULTILINE": multiline ? "YES" : "NO",
             "INDENTATION_WIDTH": indentation_width}

  options_ptr = create_options_pointer(options)
  Api.proj_as_projjson(self.context, self, options_ptr).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 (PJ_PROJ_STRING_TYPE) (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:



587
588
589
590
591
592
593
594
595
596
597
# File 'lib/proj/pj_object.rb', line 587

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

  options = {"USE_APPROX_TMERC": use_approx_tmerc ? "YES" : "NO",
             "MULTILINE": multiline ? "YES" : "NO",
             "INDENTATION_WIDTH": indentation_width,
             "MAX_LINE_LENGTH": max_line_length}

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

#to_ptrObject



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

def to_ptr
  @pointer
end

#to_sString

Returns the string representation for this object

Returns:

  • (String)

    String



644
645
646
# File 'lib/proj/pj_object.rb', line 644

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 (PJ_WKT_TYPE) (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:



624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
# File 'lib/proj/pj_object.rb', line 624

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

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

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

  result.force_encoding('UTF-8')
end

#xy_distance(coord1, coord2) ⇒ Float

Calculate the 2-dimensional euclidean between two projected coordinates

Parameters:

  • coord1 (Coordinate)

    Coordinate of first point

  • coord2 (Coordinate)

    Coordinate of second point

Returns:

  • (Float)

    Distance between the coordinates in meters

See Also:



501
502
503
# File 'lib/proj/pj_object.rb', line 501

def xy_distance(coord1, coord2)
  Api.proj_xy_dist(coord1, coord2)
end

#xyz_distance(coord1, coord2) ⇒ Float

Calculate the 2-dimensional euclidean between two projected coordinates. Similar to PjObject#xy_distance but also takes height into account.

Parameters:

  • coord1 (Coordinate)

    Coordinate of first point

  • coord2 (Coordinate)

    Coordinate of second point

Returns:

  • (Float)

    Distance between the coordinates in meters

See Also:



514
515
516
# File 'lib/proj/pj_object.rb', line 514

def xyz_distance(coord1, coord2)
  Api.proj_xyz_dist(coord1, coord2)
end