[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Геометрия, задача с отрезками
иваува
суть таково нужно определить пересекаются ли два отрезка.

Я пробовал по этому http://otvety.google.ru/otvety/thread?tid=53e3d700aff620a5 все делать, не получилось. Подскажите формулу или правильное решения. В гугл не надо отравлять. Мне все это нужно для php.



Спустя 17 минут, 29 секунд (3.05.2012 - 11:26) Nikitian написал(а):
Отрезки заданы точками или уравнениями?

Спустя 12 минут, 30 секунд (3.05.2012 - 11:39) иваува написал(а):
Координаты точек, например так,

$segment1 = new Geo_Segment(array(0, 0), array(-1, -1));
$segment1->isIntersect(new Geo_Segment(array(-1, -1), array(0, -1)));

Точку я уже смог правильно найти, нашел правильную формулу,
T.x=-((a.x*b.y-b.x*a.y)*(d.x-c.x)-(c.x*d.y-d.x*c.y)*(b.x-a.x))/((a.y-b.y)*(d.x-c.x)-(c.y-d.y)*(b.x-a .x));
T.y=((c.y-d.y)*(-T.x)-(c.x*d.y-d.x*c.y))/(d.x-c.x);

Но есть проблема, сейчас, он не правильно определяет пересекается ли эти два отрезка.
Условие я взял с той страницы.
if ((($x1<=$x)and($x2>=$x)and($x3<=$x)and($x4>=$x)) OR (($y1<=$y)and($y2>=$y)and($y3<=$y)and($y4>=$y))){
return true;
}

Спустя 18 минут, 16 секунд (3.05.2012 - 11:57) redreem написал(а):
стрер smile.gif поторопился написать smile.gif

Спустя 16 минут, 55 секунд (3.05.2012 - 12:14) redreem написал(а):
//если отрезки заданы координатами:
//(x1,y1) - (x2,y2)
//(x3,y3) - (x4,y4)
//а (x,y) - точка пересечения прямых, построенных по координатам отрезков, то проверка принадлежности этой точки обеим отрезакам такая:


function inRange(a, a1, a2) {

$max_a = max(a1,a2);
$min_a = min(a1,a2);

if (($a > $max_a) OR ($a < $min_a)) return false; else return true;

}

if (

(!
inRange(x, x1, x2)) OR
(!inRange(x, x3, x4)) OR
(!inRange(y, y1, y2)) OR
(!inRange(y, y3, y4))

)
{

return false;

}

Спустя 22 минуты, 15 секунд (3.05.2012 - 12:36) иваува написал(а):
redreem я уже методом проб и ошибок сам допер до этого, только по другому

$minP1x = min(array($x1, $x2));
$maxP1x = max(array($x1, $x2));
$minP2x = min(array($x3, $x4));
$maxP2x = max(array($x3, $x4));
$minP1y = min(array($y1, $y2));
$maxP1y = max(array($y1, $y2));
$minP2y = min(array($y3, $y4));
$maxP2y = max(array($y3, $y4));
if (
((
$minP1x<=$x)and($maxP1x>=$x)and($minP2x<=$x)and($maxP2x>=$x))
AND
(($minP1y<=$y)and($maxP1y>=$y)and($minP2y<=$y)and($maxP2y>=$y))
)
{
return true;
}

Спустя 4 минуты, 28 секунд (3.05.2012 - 12:41) иваува написал(а):

class Geo_Segment {

public $point1 = array();
public $point2 = array();

/**
*
@param array $point1
*
@param array $point2
*/

public function __construct(array $point1, array $point2){
$this->point1 = $point1;
$this->point2 = $point2;
}

/**
* Определить пересекаются ли два отрезка
*
@param Geo_Segment $segment объект отрезка
*
@return boolean
*/

public function isIntersect(Geo_Segment $segment){
$x1 = $this->point1[0];
$y1 = $this->point1[1];
$x2 = $this->point2[0];
$y2 = $this->point2[1];
$x3 = $segment->point1[0];
$y3 = $segment->point1[1];
$x4 = $segment->point2[0];
$y4 = $segment->point2[1];
@$x =-(($x1*$y2-$x2*$y1)*($x4-$x3)-($x3*$y4-$x4*$y3)*($x2-$x1))/(($y1-$y2)*($x4-$x3)-($y3-$y4)*($x2-$x1));
@$y =(($y3-$y4)*(-$x)-($x3*$y4-$x4*$y3))/($x4-$x3);
$minP1x = min(array($x1, $x2));
$maxP1x = max(array($x1, $x2));
$minP2x = min(array($x3, $x4));
$maxP2x = max(array($x3, $x4));
$minP1y = min(array($y1, $y2));
$maxP1y = max(array($y1, $y2));
$minP2y = min(array($y3, $y4));
$maxP2y = max(array($y3, $y4));
if (
((
$minP1x<=$x)and($maxP1x>=$x)and($minP2x<=$x)and($maxP2x>=$x))
AND
(($minP1y<=$y)and($maxP1y>=$y)and($minP2y<=$y)and($maxP2y>=$y))
)
{
return true;
}
return false;
}

}


Готовое решение, вдруг кому-нибудь понадобится

Спустя 8 минут, 45 секунд (3.05.2012 - 12:49) иваува написал(а):
пример использования

$segment1 = new Geo_Segment(array(0, 0), array(5, 5));
$segment2 = new Geo_Segment(array(2, 2), array(5, 2));
var_dump($segment2->isIntersect($segment1));
var_dump($segment1->isIntersect($segment2));

$segment1 = new Geo_Segment(array(0, 0), array(1, 1));
$segment2 = new Geo_Segment(array(3, 3), array(2, 2));
var_dump($segment2->isIntersect($segment1));
var_dump($segment1->isIntersect($segment2));

результат
Цитата

boolean true
boolean true
boolean false
boolean false


Сейчас осталось только определить находится ли точка внутри полигона :D

Спустя 8 минут, 7 секунд (3.05.2012 - 12:57) redreem написал(а):
подсказка:

1. сортировать вершины полигона для возможности его "обхода" например по часовой стрелке по граням.
2. на базе каждой грани строить прямую.
3. проверять - находится ли точка "по правую или левую руку" относительно каждой грани.
4. в случае принадлежности, при обходе по часовой стрелке точка для всех прямых должна находиться по правую руку.
5. проверка "с какой стороны точка" - это построить "нормаль" к прямой, проходящюю через эту точку и вычислить синус угла между нормальню и прямой. по знаку синуса можно судить о "правой" или "левой" ориентации.
6. для оптимизации вычислений можно предварительно отсеивать точки, не попадающие в габарит полигона.

smile.gif

но это будет работать только для выпуклых полигонов


Спустя 5 минут, 22 секунды (3.05.2012 - 13:03) иваува написал(а):
redreem вообще то я делаю через трассировку луча http://ru.wikipedia.org/wiki/%D0%97%D0%B0%...%B8%D0%BA%D1%83, но у меня возникла проблемка, которая известна и описана, если попадает на вершину многоугольника, то происходит прибавление пересечения, сейчас надл подумать как мне отловить это хрень.

Спустя 1 минута, 54 секунды (3.05.2012 - 13:05) redreem написал(а):
для полигонов произвольной формы:

1. проводим горизонтальную прямую через искомую точку.
2. находим пересечение всех граней с этой прямой.
3. если с какой-либо стороны от точки ненашлось пересечения значит точка не входит в полигон
4. если получили четное количество граней с каждой стороны - точка не входит в полигон.
5. иначе входит.

smile.gif

Спустя 54 секунды (3.05.2012 - 13:06) redreem написал(а):
трассировать для определения принадлежности - не самый эффективный метод.

Спустя 4 минуты, 50 секунд (3.05.2012 - 13:10) иваува написал(а):
redreemтрассировка луча работает и этого уже достаточно. Что на счет эффективности, то я не игру пишу, а просто работаю с геоданными.
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.