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.



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

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:



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

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:



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

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:



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

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:



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

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



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

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:



543
544
545
546
# File 'lib/proj/pj_object.rb', line 543

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:



553
554
555
556
# File 'lib/proj/pj_object.rb', line 553

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:



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

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



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

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:



345
346
347
# File 'lib/proj/pj_object.rb', line 345

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

#contextObject



219
220
221
# File 'lib/proj/pj_object.rb', line 219

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



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

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”



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

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:



563
564
565
566
# File 'lib/proj/pj_object.rb', line 563

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:



573
574
575
576
# File 'lib/proj/pj_object.rb', line 573

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:



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

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



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

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:



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

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



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

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:



261
262
263
# File 'lib/proj/pj_object.rb', line 261

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:



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

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:



533
534
535
536
# File 'lib/proj/pj_object.rb', line 533

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



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

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



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

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:



356
357
358
# File 'lib/proj/pj_object.rb', line 356

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

#infoPJ_PROJ_INFO

Get information about this object



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

def info
  Api.proj_pj_info(self)
end

#initialize_copy(original) ⇒ Object



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

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:



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

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:



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

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

#nameString

Returns the name of an object



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

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



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

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



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

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:



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

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:



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

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.



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

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



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

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:



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

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:



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

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



215
216
217
# File 'lib/proj/pj_object.rb', line 215

def to_ptr
  @pointer
end

#to_sString

Returns the string representation for this object

Returns:

  • (String)

    String



646
647
648
# File 'lib/proj/pj_object.rb', line 646

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:



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

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:



503
504
505
# File 'lib/proj/pj_object.rb', line 503

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:



516
517
518
# File 'lib/proj/pj_object.rb', line 516

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