class OGR::CoordinateTransformation

Attributes

c_pointer[R]

@return [FFI::Pointer] C pointer that represents the CoordinateTransformation.

destination_coordinate_system[R]

@return [OGR::SpatialReference]

source_coordinate_system[R]

@return [OGR::SpatialReference]

Public Class Methods

new(source_srs, destination_srs) click to toggle source

@param source_srs [OGR::SpatialReference] @param destination_srs [OGR::SpatialReference]

# File lib/ogr/coordinate_transformation.rb, line 38
def initialize(source_srs, destination_srs)
  source_ptr = GDAL._pointer(OGR::SpatialReference, source_srs)
  destination_ptr = GDAL._pointer(OGR::SpatialReference, destination_srs)

  # Input spatial reference system objects are assigned by copy (calling clone() method)
  # and no ownership transfer occurs.
  # NOTE: In GDAL 3, this will cause the GDAL error handler to raise a
  # GDAL::Error; in < 3, this just returns a null pointer, then gets handled
  # by the null-pointer check below.
  pointer = FFI::OGR::SRSAPI.OCTNewCoordinateTransformation(source_ptr, destination_ptr)

  raise GDAL::Error, "Unable to create coordinate transformation" if pointer.null?

  @c_pointer = pointer
end
proj4_normalize(proj4_source) click to toggle source

@param proj4_source [String] @return [String]

# File lib/ogr/coordinate_transformation.rb, line 11
def self.proj4_normalize(proj4_source)
  if GDAL._supported?(:OCTProj4Normalize)
    FFI::GDAL::GDAL.OCTProj4Normalize(proj4_source)
  else
    raise OGR::UnsupportedOperation,
          "Your version of GDAL/OGR does not support OCTProj4Normalize"
  end
end
release(pointer) click to toggle source

@param pointer [FFI::Pointer]

# File lib/ogr/coordinate_transformation.rb, line 21
def self.release(pointer)
  return unless pointer && !pointer.null?

  FFI::OGR::SRSAPI.OCTDestroyCoordinateTransformation(pointer)
end

Public Instance Methods

destroy!() click to toggle source

Deletes the object and deallocates all related C resources.

# File lib/ogr/coordinate_transformation.rb, line 55
def destroy!
  CoordinateTransformation.release(@c_pointer)

  @c_pointer = nil
end
transform(x_vertices, y_vertices, z_vertices = []) click to toggle source

Transforms points in the #source_coordinate_system space to points in the #destination_coordinate_system (given in {#initialize}).

@param x_vertices [Array<Float>] @param y_vertices [Array<Float>] @param z_vertices [Array<Float>] @return [Array<Array<Float>,Array<Float>,Array<Float>>] [[x1, x2, etc], [y1, y2, etc]]

Will include a 3rd array of Z values if z vertices are given.
# File lib/ogr/coordinate_transformation.rb, line 69
def transform(x_vertices, y_vertices, z_vertices = [])
  _transform(x_vertices, y_vertices, z_vertices) do |point_count, x_ptr, y_ptr, z_ptr|
    FFI::OGR::SRSAPI.OCTTransform(@c_pointer, point_count, x_ptr, y_ptr, z_ptr)
  end
end
transform_ex(x_vertices, y_vertices, z_vertices = []) click to toggle source

@param x_vertices [Array<Float>] @param y_vertices [Array<Float>] @param z_vertices [Array<Float>] @return [Hash{points => Array<Array<Float>,Array<Float>,Array<Float>>, success_at => Array}]

[[x1, y1], [x2, y2], etc]
# File lib/ogr/coordinate_transformation.rb, line 80
def transform_ex(x_vertices, y_vertices, z_vertices = [])
  success_ptr = nil

  point_array = _transform(x_vertices, y_vertices, z_vertices) do |point_count, x_ptr, y_ptr, z_ptr|
    success_ptr = FFI::MemoryPointer.new(:bool, point_count)
    FFI::OGR::SRSAPI.OCTTransformEx(@c_pointer, point_count, x_ptr, y_ptr, z_ptr, success_ptr)
  end

  successes = success_ptr.read_array_of_type(FFI::Type::BOOL, :read_char, point_array.first.length).map do |value|
    !value.zero?
  end

  { points: point_array, successes: successes }
end

Private Instance Methods

_transform(x_vertices, y_vertices, z_vertices = []) { |point_count, x_ptr, y_ptr, z_ptr| ... } click to toggle source

@param x_vertices [Array<Float>] @param y_vertices [Array<Float>] @param z_vertices [Array<Float>] @yieldparam point_count [Integer] @yieldparam x_ptr [FFI::MemoryPointer] @yieldparam y_ptr [FFI::MemoryPointer] @yieldparam z_ptr [FFI::MemoryPointer] @yieldreturn [Boolean] @return [Array<Array<Float>,Array<Float>,Array<Float>>] [[x1, x2, etc], [y1, y2, etc]]

Will include a 3rd array of Z values if z vertices are given.
# File lib/ogr/coordinate_transformation.rb, line 107
def _transform(x_vertices, y_vertices, z_vertices = [])
  x_ptr, y_ptr, z_ptr = init_transform_pointers(x_vertices, y_vertices, z_vertices)
  point_count = [x_vertices.length, y_vertices.length, z_vertices.length].max

  result = yield point_count, x_ptr, y_ptr, z_ptr

  # TODO: maybe this should raise?
  return false unless result

  x_vals = x_ptr.read_array_of_double(x_vertices.size)
  y_vals = y_ptr.read_array_of_double(y_vertices.size)
  z_vals = z_vertices.empty? ? nil : z_ptr.read_array_of_double(z_vertices.size)

  points = [x_vals, y_vals]
  points << z_vals unless z_vertices.empty?

  points
end
init_transform_pointers(x_vertices, y_vertices, z_vertices) click to toggle source

@param x_vertices [Array<Float>] @param y_vertices [Array<Float>] @param z_vertices [Array<Float>] @return [Array<FFI::Pointer>]

# File lib/ogr/coordinate_transformation.rb, line 130
def init_transform_pointers(x_vertices, y_vertices, z_vertices)
  x_ptr = FFI::MemoryPointer.new(:pointer, x_vertices.size)
  x_ptr.write_array_of_double(x_vertices)
  y_ptr = FFI::MemoryPointer.new(:pointer, y_vertices.size)
  y_ptr.write_array_of_double(y_vertices)

  if z_vertices.empty?
    z_ptr = nil
  else
    z_ptr = FFI::MemoryPointer.new(:pointer, z_vertices.size)
    z_ptr.write_array_of_double(z_vertices)
  end

  [x_ptr, y_ptr, z_ptr]
end