SQL-запрос для вычисления координатной близости

Преобразование CGImage в массив значений интенсивности

Моя функция принимает CGImage и возвращает массив беззнаковых 8-битных целых чисел, а также ширину и высоту изображения. Я написал этот код для использования с изображениями в оттенках серого. Расширение этого цвета должно заключаться в изменении серого на RGB и изменении байтов на пиксель на 3, не предполагая альфа-канала.

func pixelValues(fromCGImage imageRef: CGImage?) -> (pixelValues: [UInt8]?, width: Int, height: Int)
{
    var width = 0
    var height = 0
    var pixelValues: [UInt8]?
    if let imageRef = imageRef {
        width = imageRef.width
        height = imageRef.height
        let bitsPerComponent = imageRef.bitsPerComponent
        let bytesPerRow = imageRef.bytesPerRow
        let totalBytes = height * bytesPerRow

        let colorSpace = CGColorSpaceCreateDeviceGray()
        var intensities = [UInt8](repeating: 0, count: totalBytes)

        let contextRef = CGContext(data: &intensities, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: 0)
        contextRef?.draw(imageRef, in: CGRect(x: 0.0, y: 0.0, width: CGFloat(width), height: CGFloat(height)))

        pixelValues = intensities
    }

    return (pixelValues, width, height)
}

func image(fromPixelValues pixelValues: [UInt8]?, width: Int, height: Int) -> CGImage?
{
    var imageRef: CGImage?
    if var pixelValues = pixelValues {
        let bitsPerComponent = 8
        let bytesPerPixel = 1
        let bitsPerPixel = bytesPerPixel * bitsPerComponent
        let bytesPerRow = bytesPerPixel * width
        let totalBytes = height * bytesPerRow

        imageRef = withUnsafePointer(to: &pixelValues, {
            ptr -> CGImage? in
            var imageRef: CGImage?
            let colorSpaceRef = CGColorSpaceCreateDeviceGray()
            let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue).union(CGBitmapInfo())
            let data = UnsafeRawPointer(ptr.pointee).assumingMemoryBound(to: UInt8.self)
            let releaseData: CGDataProviderReleaseDataCallback = {
                (info: UnsafeMutableRawPointer?, data: UnsafeRawPointer, size: Int) -> () in
            }

            if let providerRef = CGDataProvider(dataInfo: nil, data: data, size: totalBytes, releaseData: releaseData) {
                imageRef = CGImage(width: width,
                                   height: height,
                                   bitsPerComponent: bitsPerComponent,
                                   bitsPerPixel: bitsPerPixel,
                                   bytesPerRow: bytesPerRow,
                                   space: colorSpaceRef,
                                   bitmapInfo: bitmapInfo,
                                   provider: providerRef,
                                   decode: nil,
                                   shouldInterpolate: false,
                                   intent: CGColorRenderingIntent.defaultIntent)
            }

            return imageRef
        })
    }

    return imageRef
}
7
задан deceze 18 September 2008 в 23:27
поделиться

3 ответа

Для баз данных, которые не поддерживают аккуратный (такие как SQLite) можно использовать pythagorus. Даже если Ваша база данных действительно поддерживает аккуратный, pythagorus намного быстрее. Протесты:

  • необходимо сохранить провода в x, y сетка вместо (или а также) lat, СПГ;
  • вычисление принимает 'плоскую землю', но это хорошо для относительно локального поиска.

Вот пример из проекта направляющих, я продолжаю работать (важный бит является SQL в середине):

class User < ActiveRecord::Base
  ...
  # has integer x & y coordinates
  ...

  # Returns array of {:user => <User>, :distance => <distance>}, sorted by distance (in metres).
  # Distance is rounded to nearest integer.
  # point is a Geo::LatLng.
  # radius is in metres.
  # limit specifies the maximum number of records to return (default 100).
  def self.find_within_radius(point, radius, limit = 100)

    sql = <<-SQL
      select id, lat, lng, (#{point.x} - x) * (#{point.x} - x) + (#{point.y} - y) * (#{point.y} - y) d 
      from users where #{(radius ** 2)} >= d 
      order by d limit #{limit}
    SQL

    users = User.find_by_sql(sql)
    users.each {|user| user.d = Math.sqrt(user.d.to_f).round}
    return users
  end
7
ответ дан 6 December 2019 в 23:16
поделиться

Действительно ли я прав в размышлении, что это - формула Haversine?

2
ответ дан 6 December 2019 в 23:16
поделиться

Я использую тот же самый метод на приложении отслеживания транспортных средств и делал в течение многих лет. Это работает отлично. Быстрая проверка некоторого старого кода показывает, что я умножаю результат на 6378137, который, если не изменяет память, преобразовывает в метры, но я не коснулся его в течение очень долгого времени.

я верю SQL, 2008 имеет новый пространственный тип данных, который я воображаю, позволяет эти виды сравнений, не зная эту формулу, и также позволяет пространственные индексы, которые могли бы быть интересными, но я не изучил его.

1
ответ дан 6 December 2019 в 23:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: