Как определить, где пересекаются два отрезка? [закрыто]

Если вы пытаетесь запустить SERVICE, а не активность, это сработало для меня:

Intent intent = new Intent();
intent.setClassName("com.example.otherapplication", "com.example.otherapplication.ServiceName");
context.startService(intent);

Если вы используете метод intent.setComponent (...), как упоминается в других ответах, вы можете получить предупреждение «Неявные намерения с startService не безопасны».

520
задан Yvette Colomb 17 March 2019 в 17:05
поделиться

8 ответов

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

0
ответ дан Harper Shelby 18 March 2019 в 03:05
поделиться

There’s хороший подход к этой проблеме, которая использует векторные векторные произведения. Определите 2-мерное векторное векторное произведение В Г v — В w, чтобы быть vxВ w yВ в€ ’В v yВ wx.

предположим эти два линейных сегмента, выполненные от [1 183] p к [1 184] pВ +В r и от [1 186] q к [1 187] qВ +В s. Затем любая точка на первой строке является представимой как [1 189] pВ +В tВ r (для скаляра parameterВ t) и любая точка на второй строке как [1 191] qВ +В uВ s (для скалярного parameterВ u).

Two line segments intersecting

Эти две строки пересекаются, если мы можем найти t и u таким образом что:

p + tВ r = q + uВ Крест s

Formulae for the point of intersection

обе стороны с [1 197] s, добираясь

( p + tВ r) Г — s = ( q + uВ s) Г — s

И с тех пор В Г s — В s = 0, это означает

tВ ( r Г — s) = ( q в€’ p) Г — s

И поэтому, решая для [1 118] t:

t = ( q в€’ p) Г — s / ( r Г — s)

Таким же образом, мы можем решить для [1 120] u:

( p + tВ r) Г — r = ( q + uВ s) Г — r

uВ ( s Г — r) = ( p в€’ q) Г — r

u = ( p в€’ q) Г — r / ( s Г — r)

Для сокращения количества шагов вычисления удобно переписать это следующим образом (помнящий что В Г s — В r = в€ ’В В Г r — В s):

u = ( q в€’ p) Г — r / ( r Г — s)

Теперь существует четыре случая:

  1. , Если В Г r — В sВ =В 0 и ( qВ в€ ’В p) В Г — В rВ =В 0, то эти две строки коллинеарны.

    В этом случае, выразите конечные точки второго сегмента ( q и qВ +В s) с точки зрения уравнения первого линейного сегмента ( p + t r):

    t0 = ( q в€’ p) В В · В r / ( В В r · В r)

    t1 = ( q + s в€’ p) В В · В r / ( В В r · В r) = t0 + В В s · В r / ( В В r · В r)

    , Если интервал между [1 130] t0 и t1 пересекает интервал [0, 1] затем линейные сегменты, являются коллинеарными и перекрывающимися; иначе они являются коллинеарными и непересекающимися.

    Примечание, что, если s и точка r в противоположных направлениях, то В В s · В r < 0 и таким образом, интервал, который будет проверен, является [ t1, t0], а не [ t0, t1].

  2. , Если В Г r — В sВ =В 0 и ( qВ в€ ’В p) В Г — В % r В в В 0, то эти две строки параллельны и не пересекаются.

  3. , Если В Г r — В % s В в В 0 и 0В в‰ ¤В В в‰ t 1¤В и 0В в‰ ¤В В в‰ u 1¤В, эти два линейных сегмента встречаются в точке p + tВ r = q + uВ s.

  4. Иначе, эти два линейных сегмента не параллельны, но не пересекаются.

Кредит: этот метод является 2-мерной специализацией 3D перекрестного алгоритма строки из статьи "Intersection of two lines in three-space" Ronald Goldman, опубликованного в [1 140] Графические Драгоценные камни , страница 304. В трех измерениях обычный случай - то, что строки являются скосом (ни параллель, ни пересекающийся), в этом случае, метод дает точки самого близкого подхода этих двух строк.

661
ответ дан Gareth Rees 18 March 2019 в 03:05
поделиться

Это работает хорошо на меня. Взятый от здесь .

 // calculates intersection and checks for parallel lines.  
 // also checks that the intersection point is actually on  
 // the line segment p1-p2  
 Point findIntersection(Point p1,Point p2,  
   Point p3,Point p4) {  
   float xD1,yD1,xD2,yD2,xD3,yD3;  
   float dot,deg,len1,len2;  
   float segmentLen1,segmentLen2;  
   float ua,ub,div;  

   // calculate differences  
   xD1=p2.x-p1.x;  
   xD2=p4.x-p3.x;  
   yD1=p2.y-p1.y;  
   yD2=p4.y-p3.y;  
   xD3=p1.x-p3.x;  
   yD3=p1.y-p3.y;    

   // calculate the lengths of the two lines  
   len1=sqrt(xD1*xD1+yD1*yD1);  
   len2=sqrt(xD2*xD2+yD2*yD2);  

   // calculate angle between the two lines.  
   dot=(xD1*xD2+yD1*yD2); // dot product  
   deg=dot/(len1*len2);  

   // if abs(angle)==1 then the lines are parallell,  
   // so no intersection is possible  
   if(abs(deg)==1) return null;  

   // find intersection Pt between two lines  
   Point pt=new Point(0,0);  
   div=yD2*xD1-xD2*yD1;  
   ua=(xD2*yD3-yD2*xD3)/div;  
   ub=(xD1*yD3-yD1*xD3)/div;  
   pt.x=p1.x+ua*xD1;  
   pt.y=p1.y+ua*yD1;  

   // calculate the combined length of the two segments  
   // between Pt-p1 and Pt-p2  
   xD1=pt.x-p1.x;  
   xD2=pt.x-p2.x;  
   yD1=pt.y-p1.y;  
   yD2=pt.y-p2.y;  
   segmentLen1=sqrt(xD1*xD1+yD1*yD1)+sqrt(xD2*xD2+yD2*yD2);  

   // calculate the combined length of the two segments  
   // between Pt-p3 and Pt-p4  
   xD1=pt.x-p3.x;  
   xD2=pt.x-p4.x;  
   yD1=pt.y-p3.y;  
   yD2=pt.y-p4.y;  
   segmentLen2=sqrt(xD1*xD1+yD1*yD1)+sqrt(xD2*xD2+yD2*yD2);  

   // if the lengths of both sets of segments are the same as  
   // the lenghts of the two lines the point is actually  
   // on the line segment.  

   // if the point isn’t on the line, return null  
   if(abs(len1-segmentLen1)>0.01 || abs(len2-segmentLen2)>0.01)  
     return null;  

   // return the valid intersection  
   return pt;  
 }  

 class Point{  
   float x,y;  
   Point(float x, float y){  
     this.x = x;  
     this.y = y;  
   }  

   void set(float x, float y){  
     this.x = x;  
     this.y = y;  
   }  
 }  
6
ответ дан KingNestor 18 March 2019 в 03:05
поделиться

Проблема уменьшает до этого вопроса: две строки от до B и от C до D пересекаются? Затем можно спросить это четыре раза (между строкой и каждой из четырех сторон прямоугольника).

Вот векторная математика для того, чтобы сделать его. Я предполагаю, что строка от до B является рассматриваемой строкой, и строка от C до D является одной из прямоугольных строк. Моя нотация - то, что Ax "x-координата", и Cy "y-координата C.". И" *" означает скалярное произведение, так например, A*B = Ax*Bx + Ay*By.

E = B-A = ( Bx-Ax, By-Ay )
F = D-C = ( Dx-Cx, Dy-Cy ) 
P = ( -Ey, Ex )
h = ( (A-C) * P ) / ( F * P )

Этот h число является ключом. Если h между 0 и 1, строки пересекаются, иначе они не делают. Если F*P нуль, конечно, Вы не можете сделать вычисление, но в этом случае строки параллельны, и поэтому только пересекитесь в очевидных случаях.

точная точка пересечения C + F*h.

[еще 1141] Забава:

, Если h точно 0 или 1, строки заходят в конечную точку. Можно считать это "пересечением" или не, как Вы считаете целесообразным.

А именно, h то, насколько необходимо умножить длину строки для точного касания другой строки.

Поэтому, Если h<0, это означает, прямоугольная строка находится "позади" данной строки (при этом "направление" "от до B"), и если h>1 прямоугольная строка имеет "впереди" данную строку.

Деривация:

А и C являются векторами, которые указывают на запуск строки; E и F являются векторами от концов A и C, которые формируют строку.

Для любых двух непараллельных строк в плоскости, должна быть точно одна пара скаляра g и h таким образом, что это уравнение содержит:

A + E*g = C + F*h

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

( Сначала это похоже на единственное уравнение с двумя неизвестными! , Но это не, когда Вы полагаете, что это - 2D векторное уравнение, что означает, что это - действительно пара уравнений в [1 121] и y.)

Мы должны устранить одну из этих переменных. Простой способ состоит в том, чтобы сделать E нуль термина. Чтобы сделать это, возьмите скалярное произведение обеих сторон уравнения с помощью вектора, который отметит точкой для обнуления с E. Тот вектор, который я назвал P выше, и я сделал очевидное преобразование E.

Вы теперь имеете:

A*P = C*P + F*P*h
(A-C)*P = (F*P)*h
( (A-C)*P ) / (F*P) = h
64
ответ дан Lance Roberts 18 March 2019 в 03:05
поделиться
  • 1
    @Josh You' право ре, но можно всегда использовать window.location.href. – nyuszika7h 14 December 2010 в 15:41

Ответ, однажды принятый здесь, является неправильным (он был с тех пор не принят, так ура!). Это правильно не устраняет все непересечения. Тривиально это, может казаться, работает, но это может перестать работать, особенно в случае, которые 0 и 1 считают допустимыми для h.

Рассмотрите следующий случай:

Строки в (4,1) - (5,1) и (0,0) - (0,2)

Это перпендикулярные строки, которые ясно не накладываются.

A = (4,1)
B = (5,1)
C = (0,0)
D = (0,2)
E = (5,1) - (4,1) = (-1,0)
F = (0,2) - (0,0) = (0,-2)
P = (0,1)
h = (4,1) - (0,0)) точка (0,1) / ((0,-2) точка (0,1)) = 0

Согласно вышеупомянутому ответу, эти два линейных сегмента встречаются в конечной точке (значения 0 и 1). Та конечная точка была бы:

(0,0) + (0,-2) *0 = (0,0)

Так, по-видимому, эти два линейных сегмента встречаются в (0,0), который находится на строке CD, но не на строке AB. Таким образом, что идет не так, как надо? Ответ - то, что значения 0 и 1 не допустимы и только иногда, ОКАЗЫВАЕТСЯ, правильно предсказывают пересечение конечной точки. Когда расширение одной строки (но не другой) встретило бы линейный сегмент, алгоритм предсказывает пересечение линейных сегментов, но это не корректно. Я предполагаю, что путем тестирования запускающийся с AB по сравнению с CD и затем также тестирующий с CD по сравнению с AB, эта проблема была бы устранена. Только если и падение между 0 и 1 включительно может они, как говорить, пересечься.

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

- Dan

21
ответ дан 22 November 2019 в 22:29
поделиться

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

Например, рассмотрим точки A (10,10) B (20,20) C (10,1) D (1 , 10) дает h = 0,5, и все же при рассмотрении становится ясно, что эти отрезки нигде не находятся рядом друг с другом.

Из графика видно, что 0

46
ответ дан 22 November 2019 в 22:29
поделиться

FWIW, следующая функция (в букве С) как обнаруживает пересечения прямых, так и определяет точку пересечения. Она основана на алгоритме, описанном в работе Андре ЛеМота "Tricks of the Windows Game Programming Gurus". Он не отличается от некоторых алгоритмов в других ответах (например, Гарета). Затем ЛеМот использует правило Крамера (не спрашивайте меня) для решения уравнений самостоятельно.

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

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

// Returns 1 if the lines intersect, otherwise 0. In addition, if the lines 
// intersect the intersection point may be stored in the floats i_x and i_y.
char get_line_intersection(float p0_x, float p0_y, float p1_x, float p1_y, 
    float p2_x, float p2_y, float p3_x, float p3_y, float *i_x, float *i_y)
{
    float s1_x, s1_y, s2_x, s2_y;
    s1_x = p1_x - p0_x;     s1_y = p1_y - p0_y;
    s2_x = p3_x - p2_x;     s2_y = p3_y - p2_y;

    float s, t;
    s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
    t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);

    if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
    {
        // Collision detected
        if (i_x != NULL)
            *i_x = p0_x + (t * s1_x);
        if (i_y != NULL)
            *i_y = p0_y + (t * s1_y);
        return 1;
    }

    return 0; // No collision
}

BTW, должен сказать, что в книге ЛеМота, хотя он, видимо, правильно понимает алгоритм, конкретный пример, который он показывает, вставляет неправильные числа и делает неправильные вычисления. Например:

(4 * (4 - 1) + 12 * (7 - 1)) /(17 * 4 + 12 * 10)

= 844/0.88

= 0.44

Это сбило меня с толку на часы . :(

230
ответ дан 22 November 2019 в 22:29
поделиться

Я попробовал некоторые из этих ответов, но они не помогли мне (извините, ребята); после еще нескольких поисков в сети я нашел это .

С небольшой модификацией его кода у меня теперь есть эта функция, которая возвращает точку пересечения или, если пересечение не найдено, возвращает -1, -1.

    Public Function intercetion(ByVal ax As Integer, ByVal ay As Integer, ByVal bx As Integer, ByVal by As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal dx As Integer, ByVal dy As Integer) As Point
    '//  Determines the intersection point of the line segment defined by points A and B
    '//  with the line segment defined by points C and D.
    '//
    '//  Returns YES if the intersection point was found, and stores that point in X,Y.
    '//  Returns NO if there is no determinable intersection point, in which case X,Y will
    '//  be unmodified.

    Dim distAB, theCos, theSin, newX, ABpos As Double

    '//  Fail if either line segment is zero-length.
    If ax = bx And ay = by Or cx = dx And cy = dy Then Return New Point(-1, -1)

    '//  Fail if the segments share an end-point.
    If ax = cx And ay = cy Or bx = cx And by = cy Or ax = dx And ay = dy Or bx = dx And by = dy Then Return New Point(-1, -1)

    '//  (1) Translate the system so that point A is on the origin.
    bx -= ax
    by -= ay
    cx -= ax
    cy -= ay
    dx -= ax
    dy -= ay

    '//  Discover the length of segment A-B.
    distAB = Math.Sqrt(bx * bx + by * by)

    '//  (2) Rotate the system so that point B is on the positive X axis.
    theCos = bx / distAB
    theSin = by / distAB
    newX = cx * theCos + cy * theSin
    cy = cy * theCos - cx * theSin
    cx = newX
    newX = dx * theCos + dy * theSin
    dy = dy * theCos - dx * theSin
    dx = newX

    '//  Fail if segment C-D doesn't cross line A-B.
    If cy < 0 And dy < 0 Or cy >= 0 And dy >= 0 Then Return New Point(-1, -1)

    '//  (3) Discover the position of the intersection point along line A-B.
    ABpos = dx + (cx - dx) * dy / (dy - cy)

    '//  Fail if segment C-D crosses line A-B outside of segment A-B.
    If ABpos < 0 Or ABpos > distAB Then Return New Point(-1, -1)

    '//  (4) Apply the discovered position to line A-B in the original coordinate system.
    '*X=Ax+ABpos*theCos
    '*Y=Ay+ABpos*theSin

    '//  Success.
    Return New Point(ax + ABpos * theCos, ay + ABpos * theSin)
End Function
6
ответ дан 22 November 2019 в 22:29
поделиться
Другие вопросы по тегам:

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