Как я могу сделать эффективный поиск диапазона + рассчитывающий с данными широты/долготы?

Линия Cell *m_firstCellPtr; относится к типу Cell, который явно не известен в этой точке.

Это очень вероятно, потому что книга просто показывает Stack -части на этой странице, не упоминая, что вам придется объявить Cell, например, включив что-то вроде #include "Cell.h"

Три способа выйти из этого:

  1. #include "Cell.h", если ресурсы книги предоставят его
  2. Форвард объявить [ 116] как class Cell; до определения Stack;
  3. изменить строку на class Cell *m_firstCellPtr;
10
задан mpobrien 5 February 2009 в 16:09
поделиться

5 ответов

Я не думаю, что необходимо использовать это решение. Случайным образом думая об этом несколько дней назад, я думаю, что, измеряя расстояние от отдельного момента местоположения квадратов сетки будут основаны на кругах, а не сетке одетой в форму. Еще дальше от 0,0 Вы - менее точное, которым это будет!

То, что я сделал, должно было иметь 2 дополнительных значения на моем классе PostalCode. Каждый раз, когда я обновляю Long/Lat на PostalCode, я вычисляю X, Y расстояние от Long 0, Lat 0.

public static class MathExtender
{
    public static double GetDistanceBetweenPoints(double sourceLatitude, double sourceLongitude, double destLatitude, double destLongitude)
    {
        double theta = sourceLongitude - destLongitude;
        double distance =
            Math.Sin(DegToRad(sourceLatitude))
            * Math.Sin(DegToRad(destLatitude))
            + Math.Cos(DegToRad(sourceLatitude))
            * Math.Cos(DegToRad(destLatitude))
            * Math.Cos(DegToRad(theta));
        distance = Math.Acos(distance);
        distance = RadToDeg(distance);
        distance = distance * 60 * 1.1515;
        return (distance);
    }


    public static double DegToRad(double degrees)
    {
        return (degrees * Math.PI / 180.0);
    }

    public static double RadToDeg(double radians)
    {
        return (radians / Math.PI * 180.0);
    }
}

Затем я обновляю свой класс как так:

private void CalculateGridReference()
{
    GridReferenceX = MathExtender.GetDistanceBetweenPoints(0, 0, 0, Longitude);
    GridReferenceY = MathExtender.GetDistanceBetweenPoints(0, 0, Latitude, 0);
}

Таким образом, теперь у меня есть x, y расстояние сетки (в милях) из ссылки сетки 0,0 для каждой строки в моем DB. Если бы я хочу найти все места с 5 милями long/lat, я сначала получил бы эти X, Y ссылка сетки (скажите 25,75), затем, я искал бы 20.. 30, 70.. 80 в DB и дальнейшем фильтре результаты в использовании памяти

MathExtensder.GetDistanceBetweenPoints(candidate.Lat, candidate.Long, search.Lat, search.Long) < TheRadiusOfInterest

В части DB крайний быстрый, и работы части в оперативной памяти над меньшим набором для создания этого крайним точный.

9
ответ дан 3 December 2019 в 19:35
поделиться

Использовать R-Trees.

В Oracle, с помощью Пространственной Oracle, можно создать индекс:

CREATE INDEX ix_spatial ON spatial_table (locations) INDEXTYPE IS MDSYS.SPATIAL_INDEX;

это создаст R-Tree для Вас и поиска по нему.

Можно использовать любого Earth Model Вам нравится: WGS84, PZ-90 и т.д.

4
ответ дан 3 December 2019 в 19:35
поделиться

Используйте некоторое дерево поиска для пространственных данных, например, дерево квадрантов. На большее количество таких структур данных ссылаются под, "См. также".

3
ответ дан 3 December 2019 в 19:35
поделиться

Вы могли, возможно, предоставить образец своего существующего дорогого запроса?

Если Вы делаете надлежащее большое круговое вычисление на основе взятия синуса () и косинус () контрольной точки и других точек данных, то очень существенная оптимизация могла быть сделана путем фактического хранения тех значений sin/cos в базе данных в дополнение к значениям lat/long.

С другой стороны, просто используйте свою базу данных для извлечения прямоугольника диапазонов lat/long, которые соответствуют и только впоследствии отфильтровывают тех, которые являются вне истинного кругового радиуса.

Но действительно примите во внимание, что один градус долготы является несколько более коротким расстоянием в высоких широтах, чем на экватор. Должно быть легко выяснить правильное соотношение сторон для того прямоугольника, все же. У Вас также были бы ошибки, если бы необходимо рассмотреть области очень близко к полюсам, поскольку rectanglar выбор не справился бы с кругом, который перекрыл полюс.

1
ответ дан 3 December 2019 в 19:35
поделиться

Этот UDF (SQL Server) получит Вас расстояние между двумя точками lat/lon:

CREATE FUNCTION [dbo].[zipDistance] (
    @Lat1 decimal(11, 6),
    @Lon1 decimal(11, 6),
    @Lat2 decimal(11, 6),
    @Lon2 decimal(11, 6)
)
RETURNS
    decimal(11, 6) AS
BEGIN

    IF @Lat1 = @Lat2 AND @Lon1 = @Lon2
        RETURN 0 /* same lat/long points, 0 distance = */

    DECLARE @x decimal(18,13)
    SET @x = 0.0

    /* degrees -> radians */
    SET @Lat1 = @Lat1 * PI() / 180
    SET @Lon1 = @Lon1 * PI() / 180
    SET @Lat2 = @Lat2 * PI() / 180
    SET @Lon2 = @Lon2 * PI() / 180

    /* accurate to +/- 30 feet */
    SET @x = Sin(@Lat1) * Sin(@Lat2) + Cos(@Lat1) * Cos(@Lat2) * Cos(@Lon2 - @Lon1)
    IF 1 = @x
        RETURN 0

    DECLARE @EarthRad decimal(5,1)
    SET @EarthRad = 3963.1

    RETURN @EarthRadius * (-1 * ATAN(@x / SQRT(1 - @x * @x)) + PI() / 2)

END

И, очевидно, можно использовать это в отдельном запросе, таком как:

SELECT * FROM table WHERE [dbo].[zipDistance] < 25.0
1
ответ дан 3 December 2019 в 19:35
поделиться
Другие вопросы по тегам:

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