Кратчайшее расстояние между точкой и линейным сегментом

Разница между Люменом и Ларавелом в том, что в Ларавеле вы звоните Application->setLocale().

Это делает три вещи, как описано выше:

  1. Установить конфигурацию app.locale
  2. Установить локаль на переводчике
  3. Запустить локаль. измененное событие

В Lumen вы могли бы вызвать переводчик напрямую с помощью app('translator')->setLocale() или App::make('translator')->setLocale(),

, так что разница здесь в том, что конфигурация переменная не будет установлена ​​автоматически, и событие locale.changed не будет запущено.

Класс Application Laravel также обновляет конфигурацию и запускает событие:

public function setLocale($locale)
{
    $this['config']->set('app.locale', $locale);
    $this['translator']->setLocale($locale);
    $this['events']->fire('locale.changed', [$locale]);
}

, а в Laravel getLocale просто читает переменную конфигурации:

public function getLocale()
{
    return $this['config']->get('app.locale');
}

Для переводов, это переводчик, который имеет значение. Trans helper от Laravel выглядит следующим образом:

function trans($id = null, $parameters = [], $domain = 'messages', $locale = null)
{
    if (is_null($id)) {
        return app('translator');
    }
    return app('translator')->trans($id, $parameters, $domain, $locale);
}

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

335
задан 5 revs, 3 users 62% 13 May 2016 в 11:31
поделиться

7 ответов

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

Вот некоторый правильный код, в C ++. Он предполагает 2D-вектор класса class vec2 {float x, y;} , по сути, с операторами сложения, вычитания, масштабирования и т. Д., А также функцией расстояния и скалярного произведения (например, x1 x2 + y1 y2 ).

float minimum_distance(vec2 v, vec2 w, vec2 p) {
  // Return minimum distance between line segment vw and point p
  const float l2 = length_squared(v, w);  // i.e. |w-v|^2 -  avoid a sqrt
  if (l2 == 0.0) return distance(p, v);   // v == w case
  // Consider the line extending the segment, parameterized as v + t (w - v).
  // We find projection of point p onto the line. 
  // It falls where t = [(p-v) . (w-v)] / |w-v|^2
  // We clamp t from [0,1] to handle points outside the segment vw.
  const float t = max(0, min(1, dot(p - v, w - v) / l2));
  const vec2 projection = v + t * (w - v);  // Projection falls on the segment
  return distance(p, projection);
}

РЕДАКТИРОВАТЬ: Мне нужна была реализация Javascript, так что вот она, без зависимостей (или комментариев, но это прямой порт вышеупомянутого). Точки представлены как объекты с атрибутами x и y .

function sqr(x) { return x * x }
function dist2(v, w) { return sqr(v.x - w.x) + sqr(v.y - w.y) }
function distToSegmentSquared(p, v, w) {
  var l2 = dist2(v, w);
  if (l2 == 0) return dist2(p, v);
  var t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
  t = Math.max(0, Math.min(1, t));
  return dist2(p, { x: v.x + t * (w.x - v.x),
                    y: v.y + t * (w.y - v.y) });
}
function distToSegment(p, v, w) { return Math.sqrt(distToSegmentSquared(p, v, w)); }

РЕДАКТИРОВАТЬ 2: Мне нужна была версия Java, но, что более важно, она нужна мне в 3D вместо 2d.

float dist_to_segment_squared(float px, float py, float pz, float lx1, float ly1, float lz1, float lx2, float ly2, float lz2) {
  float line_dist = dist_sq(lx1, ly1, lz1, lx2, ly2, lz2);
  if (line_dist == 0) return dist_sq(px, py, pz, lx1, ly1, lz1);
  float t = ((px - lx1) * (lx2 - lx1) + (py - ly1) * (ly2 - ly1) + (pz - lz1) * (lz2 - lz1)) / line_dist;
  t = constrain(t, 0, 1);
  return dist_sq(px, py, pz, lx1 + t * (lx2 - lx1), ly1 + t * (ly2 - ly1), lz1 + t * (lz2 - lz1));
}
428
ответ дан 23 November 2019 в 00:41
поделиться

Я предполагаю, что вы хотите найти кратчайшее расстояние между точкой и отрезком линии; для этого вам нужно найти линию (lineA), которая перпендикулярна вашему линейному сегменту (lineB), который проходит через вашу точку, определить пересечение между этой линией (lineA) и вашей линией, которая проходит через ваш линейный сегмент (lineB) ; если эта точка находится между двумя точками вашего линейного сегмента, то расстояние - это расстояние между вашей точкой и точкой, которую вы только что нашли, которая является пересечением линий lineA и lineB; если точка не находится между двумя точками вашего линейного сегмента, вам нужно получить расстояние между вашей точкой и ближайшим из двух концов линейного сегмента; это легко сделать, взяв квадратное расстояние (чтобы избежать квадратного корня) между точкой и двумя точками линейного сегмента; в зависимости от того, что ближе, извлеките из него квадратный корень.

6
ответ дан 23 November 2019 в 00:41
поделиться

Here's the code I ended up writing. This code assumes that a point is defined in the form of {x:5, y:7}. Note that this is not the absolute most efficient way, but it's the simplest and easiest-to-understand code that I could come up with.

// a, b, and c in the code below are all points

function distance(a, b)
{
    var dx = a.x - b.x;
    var dy = a.y - b.y;
    return Math.sqrt(dx*dx + dy*dy);
}

function Segment(a, b)
{
    var ab = {
        x: b.x - a.x,
        y: b.y - a.y
    };
    var length = distance(a, b);

    function cross(c) {
        return ab.x * (c.y-a.y) - ab.y * (c.x-a.x);
    };

    this.distanceFrom = function(c) {
        return Math.min(distance(a,c),
                        distance(b,c),
                        Math.abs(cross(c) / length));
    };
}
1
ответ дан 23 November 2019 в 00:41
поделиться

Эй, я только вчера написал это. Это в ActionScript 3.0, который в основном является Javascript, хотя у вас может не быть того же класса Point.

//st = start of line segment
//b = the line segment (as in: st + b = end of line segment)
//pt = point to test
//Returns distance from point to line segment.  
//Note: nearest point on the segment to the test point is right there if we ever need it
public static function linePointDist( st:Point, b:Point, pt:Point ):Number
{
    var nearestPt:Point; //closest point on seqment to pt

    var keyDot:Number = dot( b, pt.subtract( st ) ); //key dot product
    var bLenSq:Number = dot( b, b ); //Segment length squared

    if( keyDot <= 0 )  //pt is "behind" st, use st
    {
        nearestPt = st  
    }
    else if( keyDot >= bLenSq ) //pt is "past" end of segment, use end (notice we are saving twin sqrts here cuz)
    {
        nearestPt = st.add(b);
    }
    else //pt is inside segment, reuse keyDot and bLenSq to get percent of seqment to move in to find closest point
    {
        var keyDotToPctOfB:Number = keyDot/bLenSq; //REM dot product comes squared
        var partOfB:Point = new Point( b.x * keyDotToPctOfB, b.y * keyDotToPctOfB );
        nearestPt = st.add(partOfB);
    }

    var dist:Number = (pt.subtract(nearestPt)).length;

    return dist;
}

Кроме того, здесь есть довольно полное и удобочитаемое обсуждение проблемы: notejot.com

11
ответ дан 23 November 2019 в 00:41
поделиться

Не удержался от написания кода на python :)

from math import sqrt, fabs
def pdis(a, b, c):
    t = b[0]-a[0], b[1]-a[1]           # Vector ab
    dd = sqrt(t[0]**2+t[1]**2)         # Length of ab
    t = t[0]/dd, t[1]/dd               # unit vector of ab
    n = -t[1], t[0]                    # normal unit vector to ab
    ac = c[0]-a[0], c[1]-a[1]          # vector ac
    return fabs(ac[0]*n[0]+ac[1]*n[1]) # Projection of ac to n (the minimum distance)

print pdis((1,1), (2,2), (2,0))        # Example (answer is 1.414)


То же для fortran :)

real function pdis(a, b, c)
    real, dimension(0:1), intent(in) :: a, b, c
    real, dimension(0:1) :: t, n, ac
    real :: dd
    t = b - a                          ! Vector ab
    dd = sqrt(t(0)**2+t(1)**2)         ! Length of ab
    t = t/dd                           ! unit vector of ab
    n = (/-t(1), t(0)/)                ! normal unit vector to ab
    ac = c - a                         ! vector ac
    pdis = abs(ac(0)*n(0)+ac(1)*n(1))  ! Projection of ac to n (the minimum distance)
end function pdis


program test
    print *, pdis((/1.0,1.0/), (/2.0,2.0/), (/2.0,0.0/))   ! Example (answer is 1.414)
end program test
10
ответ дан 23 November 2019 в 00:41
поделиться

Это реализация, сделанная для КОНЕЧНЫХ СТРОЧНЫХ СЕГМЕНТОВ, а не для бесконечных строк, как у большинства других функций (вот почему я сделал это).

Реализация теории Полом Бурком .

Python:

def dist(x1, y1, x2, y2, x3, y3): # x3,y3 is the point
    px = x2-x1
    py = y2-y1

    norm = px*px + py*py

    u =  ((x3 - x1) * px + (y3 - y1) * py) / float(norm)

    if u > 1:
        u = 1
    elif u < 0:
        u = 0

    x = x1 + u * px
    y = y1 + u * py

    dx = x - x3
    dy = y - y3

    # Note: If the actual distance does not matter,
    # if you only want to compare what this function
    # returns to other results of this function, you
    # can just return the squared distance instead
    # (i.e. remove the sqrt) to gain a little performance

    dist = (dx*dx + dy*dy)**.5

    return dist

AS3:

public static function segmentDistToPoint(segA:Point, segB:Point, p:Point):Number
{
    var p2:Point = new Point(segB.x - segA.x, segB.y - segA.y);
    var something:Number = p2.x*p2.x + p2.y*p2.y;
    var u:Number = ((p.x - segA.x) * p2.x + (p.y - segA.y) * p2.y) / something;

    if (u > 1)
        u = 1;
    else if (u < 0)
        u = 0;

    var x:Number = segA.x + u * p2.x;
    var y:Number = segA.y + u * p2.y;

    var dx:Number = x - p.x;
    var dy:Number = y - p.y;

    var dist:Number = Math.sqrt(dx*dx + dy*dy);

    return dist;
}

Java

private double shortestDistance(float x1,float y1,float x2,float y2,float x3,float y3)
    {
        float px=x2-x1;
        float py=y2-y1;
        float temp=(px*px)+(py*py);
        float u=((x3 - x1) * px + (y3 - y1) * py) / (temp);
        if(u>1){
            u=1;
        }
        else if(u<0){
            u=0;
        }
        float x = x1 + u * px;
        float y = y1 + u * py;

        float dx = x - x3;
        float dy = y - y3;
        double dist = Math.sqrt(dx*dx + dy*dy);
        return dist;

    }
67
ответ дан 23 November 2019 в 00:41
поделиться

Решение для стрелки и дрожания:

import 'dart:math' as math;
 class Utils {
   static double shortestDistance(Point p1, Point p2, Point p3){
      double px = p2.x - p1.x;
      double py = p2.y - p1.y;
      double temp = (px*px) + (py*py);
      double u = ((p3.x - p1.x)*px + (p3.y - p1.y)* py) /temp;
      if(u>1){
        u=1;
      }
      else if(u<0){
        u=0;
      }
      double x = p1.x + u*px;
      double y = p1.y + u*py;
      double dx = x - p3.x;
      double dy = y - p3.y;
      double dist = math.sqrt(dx*dx+dy*dy);
      return dist;
   }
}

class Point {
  double x;
  double y;
  Point(this.x, this.y);
}
0
ответ дан 23 November 2019 в 00:41
поделиться
Другие вопросы по тегам:

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