Какой алгоритм может эффективно найти ряд точек на определенном расстоянии от пути?

Вы получаете ожидаемое поведение - сначала нарисуйте линии для значений y1, где цвет зависит от коэффициента (0,1) для каждой строки, а затем нарисуйте линии для значений y2, где цвет зависит от коэффициента (0,1) для каждого строки.

Сведение случая к первым двум записям, например: каково требование назначать цвета для y1 и y2, у которых значение f равно нулю? Хотите ли вы назначить цвет 0 для одного и цвет 1 для другого (в этом случае вам не нужна эта информация в каждом ряду) или вам нужна какая-то линия, которая будет чередовать цвет (поэтому здесь обе линии будут иметь цвет 0 для первых двух строк, тогда, если строка имеет коэффициент 1, обе строки будут иметь цвет 1)?

если вы хотите использовать один цвет на строку, используйте жесткий код в параметре цвета вместо использования фактора строки

dt1 <- data.frame(x = c("01/01/19","01/02/19","01/03/19"), f = as.factor(c(1,1,0)), y1 = c(6,8,7), y2 = c(10,12,14))
dt1$x <- as.Date(dt1$x, "%m/%d/%y")

ggplot(data = dt1) +
  geom_line(aes(x = x, y = y2, color = "red"))  + 
               geom_line(aes(x = x, y = y1, color = "blue"))

, если вы хотите чередовать цвета на y1 и y2, это то, на что это может быть похоже, используя точки (линии кажутся более хитрыми)

dt1 <- data.frame(x = c("01/01/19","01/02/19","01/03/19"), f = as.factor(c(1,1,0)), y1 = c(6,8,7), y2 = c(10,12,14))
dt1$x <- as.Date(dt1$x, "%m/%d/%y")

ggplot(data = dt1) +
  geom_point(aes(x = x, y = y2, color = factor(f)))  + 
  geom_point(aes(x = x, y = y1, color = factor(f))) 
11
задан Community 8 February 2017 в 14:09
поделиться

11 ответов

Я не действительно уверен, понимаю ли я вопрос правильно, но разве алгоритм Dijkstra не соответствовал бы? Это находит кратчайшие пути от исходного узла, и можно просто прерваться после достижения Вас максимальное расстояние, и проверьте, какие точки от s были уже найдены. Я не уверен, как хорошо это играет с SQL все же.

1
ответ дан 3 December 2019 в 09:42
поделиться
  1. Определите "левую дорожную" и "правильную дорогу": для каждого линейного сегмента первоначального тракта создайте линейный сегмент d единицы "левым" и d единицы к "праву" на сегмент.

  2. Соедините левую дорожную и правильную дорогу в концах для создания полигона.

  3. Примените стандартный алгоритм для определения, какие интересные места лежат в полигоне.

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

Жесткое присвоение домашней работы а?

Возможно, хорошее начало могло бы быть должно посмотреть на новаторские алгоритмы в ширину - возможно, что-то как подход заливки будет полезно для этого?

Править: Таким образом, если это просто похоже на присвоение домашней работы, возможно, я могу быть более услужливым...

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

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

К сожалению, я не знаю, что достаточно геометрии знает об умном способе решить, падает ли список точек внутри или снаружи круга кроме простого вычисления расстояния между ними и центром круга через аккуратный основной - я уверен, что существует тот. При помощи вышеупомянутого простого подразделения или некоторого варианта на нем необходимо найти, что можно заблаговременно сократить число возможных очков, которые должны быть перерыты.

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

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

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

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

  • продвиньтесь строка, ширина шага 2x расстояние, которое Вы хотите проверить (более или менее?) и создают искусственные точки, которые являются "рядом".
  • itereate: выберите новые точки вокруг точек, которые являются "рядом" (не вычисляйте евклидово расстояние, просто 1 норма и просто тестируйте координаты X и Y) - затем тестируют их расстояние (можно даже наследовать определенный линейный сегмент от искусственных точек до найденных "близких" точек и выбора, что одно первое для тестирования, но расширяют поиск, так как могли быть скручивания!)

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

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

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

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

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

Вы могли использовать дерево квадрантов для разделения пространства в сегменты, и затем только для точек в сегментах близко к пути?

0
ответ дан 3 December 2019 в 09:42
поделиться

Единственное решение этого вроде:

for each point
  for each line
    is distance to line within constraints

Внутренний цикл может быть завершен рано однажды точка, которая находится в рамках ограничения, найден. Обратите внимание, что внутренние и внешние циклы могут быть транспонированы.

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

|-------------
| *    /
|    --
|   /
|  /
| |
| |
|/
|         |--------| <- the line segment

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

Теперь, тест расстояния не мог бы быть 'по прямой' тест, но поиск графика, например, точки в x милях дороги с помощью только дороги для соединения их вместе:

--------------------------------------------------- < the road
   |
   |              * <- target
...|..............|................................ < check distance
   |              |
   |--------------| <- roads to target

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

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

Способы проверить ограничение, где ограничение 'по прямой' ограничение:

  1. Геометрически: Во-первых, определите расстояние от точки P к строке. Затем если точка в рамках ограничения, проектируют точку P на линейный сегмент, где строка определяется как:

    L = P1 + (P2-P1).n
    

    где P1 и P2 являются конечными точками, и n является параметрической переменной. Если значение n для спроектированного P находится в диапазоне 0 <= n <= 1 затем, точка между P1 и P2. Наконец, сделайте точку в круговом тесте для кругов, центрируемых на P1 и P2.

  2. Преобразования: Создайте матрицу преобразования для каждого линейного сегмента, таким образом, что P1 преобразовывается к источнику, и P2 преобразовывается к (|P1-P2 |, 0). Затем подайте заявку, каждый преобразовывает ко всем точкам и затем тестирует каждую точку в прямоугольнике (0, - ограничении) - (|P1-P2 |, ограничении). Этот метод может быть высоко оптимизирован с помощью SIMD или GPU

  3. Графически: Разграничьте сегменты к битовому массиву с помощью пера с округленными заглушками и шириной, пропорциональной ограничительному расстоянию. Затем для каждой контрольной точки проверьте пиксель в битовый массив, соответствующий точке. Это не точно (но большие битовые массивы создают более точные результаты, но нуждаются в большей памяти), но довольно быстро, после того как битовый массив создается.

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

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

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

Поскольку каждый линейный сегмент вычисляет, значения должны преобразовать точку от мировых координат до локальных координат относительно линейного сегмента (таким образом, любая точка пробегает вычисление, был бы относительно системы координат, где линейный сегмент является осью X),

Поскольку каждая точка осуществляет следующие проверки:

1-, Если точка на расстоянии любой конечной точки, мы знаем, что это должно быть включено. Это выполняется простым distance^2 <= (x2 - x1) ^2 + (y2 - y1) ^2 вычисление между каждой конечной точкой и целевой точкой.

2-Выполнений целевая точка посредством преобразования. После преобразования, если x> = 0 и x <= (продолжительность линейного сегмента) и |y | <= расстояние затем целевая точка должна быть включена иначе, это должно быть исключено.

Моя векторная математика немного ржава, таким образом, я не могу предоставить лучший код извините! Но возможно мое сообщение вдохновит кого-то еще выписывать надлежащий способ сделать это.

0
ответ дан 3 December 2019 в 09:42
поделиться

Я полагаю, что эти два класса ответят на Ваш вопрос. Я создал GetArea () функция с помощью Формулы Heron's. Удостоверьтесь, что Точки Сегмента всегда передаются сначала IsPointWithinDistanceToLineSegment, и TestPoint всегда передается 3-й.

Править: Я глупо использовал Точку, которая только позволяет целые числа для X и Y. Необходимо будет зафиксировать это с другим классом, который берет, удваивается или плавает как X и Y...

public class Geometry
{
    public static double GetDistanceBetweenTwoPoints(Point SegmentStart, Point SegmentEnd)
    {
        return Math.Sqrt(Math.Pow(SegmentEnd.X - SegmentStart.X, 2) + Math.Pow(SegmentEnd.Y - SegmentStart.Y, 2));
    }

    public static bool IsPointWithinDistanceToLineSegment(Point SegmentStart, Point SegmentEnd, Point TestPoint, double TestDistance)
    {
        if (GetDistanceBetweenTwoPoints(SegmentStart,SegmentEnd) <= TestDistance || GetDistanceBetweenTwoPoints(SegmentEnd,TestPoint) <= TestDistance)
        {
            return true;
        }
        var T = new Triangle(SegmentStart, SegmentEnd, TestPoint);
        var BaseLength = GetDistanceBetweenTwoPoints(SegmentStart, SegmentEnd);
        var Area = T.GetArea();
        var TriangleHeight = 2* Area / BaseLength;
        return T.AB >= T.BC && T.AB >= T.AC && TriangleHeight <= TestDistance;
    }
}

public class Triangle
{
    public Triangle(Point a, Point b, Point c)
    {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    public Point a
    {
        get;
        set;
    }

    public Point b
    {
        get;
        set;
    }

    public Point c
    {
        get;
        set;
    }

    //Lengths of Sides
    public double AB
    {
        get
        {
            return Geometry.GetDistanceBetweenTwoPoints(a, b);
        }
    }

    public double AC
    {
        get
        {
            return Geometry.GetDistanceBetweenTwoPoints(a, c);
        }
    }

    public double BC
    {
        get
        {
            return Geometry.GetDistanceBetweenTwoPoints(b, c);
        }
    }

    public double GetArea()
    {
        var Term1 = Math.Pow((Math.Pow(AB, 2) + Math.Pow(AC, 2) + Math.Pow(BC, 2)), 2);
        var Term2 = 2 * (Math.Pow(AB, 4) + Math.Pow(AC, 4) + Math.Pow(BC, 4));
        var result = .25 * Math.Sqrt(Term1 - Term2);
        return result;
    }
}
0
ответ дан 3 December 2019 в 09:42
поделиться

Учитывая общие вычислительные инструменты, Ваш лучший алгоритм будет некоторой вариацией на отфильтровывание очевидно неинтересных точек и нахождение расстояния от каждого линейного сегмента до каждой остающейся точки. (Предложенное решение для полигона неверно - сферой интересов является объединение того полигона с кругом радиуса d вокруг каждой точки на l - и на самом деле менее эффективный, чем простое нахождение расстояния от каждой точки до каждого линейного сегмента.)

То, какие фильтры являются лучшими, будет зависеть от природы Ваших данных - например, в демонстрационной схеме, фильтрующий на ограничительной рамке l (плюс d) будет очень полезно.

Интересный фильтр был бы: учитывая точку p определяющий l, возьмите круг радиуса r, где r является максимальной длиной этих двух сегментов, определенных частично p плюс d. Только точки в этом кругу могут быть достаточно близки к тем двум сегментам, чтобы быть в нашем наборе решения, таким образом, мы можем быстро определить, можем ли мы пропустить те два расчета расстояния линейного сегмента. (Это будет менее эффективно, если некоторые линейные сегменты будут очень длинны, но если они, те линейные сегменты могут быть легко разбиты в меньшие блоки.)

0
ответ дан 3 December 2019 в 09:42
поделиться

Я никого не удивляю упомянул для этого A * алогирифм. Кажется, идеально подходит. Что мне здесь не хватает? Если вы не знакомы с этим, погуглите и найдете =). (Да, это действительно из игрового мира ...)

0
ответ дан 3 December 2019 в 09:42
поделиться
Другие вопросы по тегам:

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