PDA

Просмотр полной версии : [Function] IsPointInPolygon



Seregamil
18.10.2015, 11:47
Да,знаю, есть функция от пользователя RyDeR`, но проблема в том, что она, лично у меня, корректно не работает.
Ссылка на тему: http://forum.sa-mp.com/showthread.php?p=1154971&highlight=IsPointInPolygon#post1154971

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

Значение MAX_POLYGON_POINTS меняйте в том случае, если количество точек полигона больше, чем 32.


stock IsPointInPolygon( Float: pointX, Float: pointY, Float: polygon[], totalPoints = sizeof( polygon ) ){
#define MAX_POLYGON_POINTS (32) // empty statement with 'polygonSize' =_=
new
polygonSize = ( totalPoints / 2 ), // get polygon size
Float: points[ MAX_POLYGON_POINTS ][ 2 ], // x and y
i = 0,
j = 0,
result = false
;
#undef MAX_POLYGON_POINTS

for( ; j != polygonSize ; j ++, i++ ) { // add points in array
points[ j ][ 0 ] = polygon[ i ] ; // x
points[ j ][ 1 ] = polygon[ ++i ] ; // y
}

for( i = 0, j -= 1; i < polygonSize; j = i++ ) { // first 'i' and last 'j'
if( ( ( points[ i ][ 1 ] >= pointY ) != ( points[ j ][ 1 ] >= pointY ) ) && ( pointX <= ( points[ j ][ 0 ] - points[ i ][ 0 ] ) * ( pointY - points[ i ][ 1 ] ) / ( points[ j ][ 1 ] - points[ i ][ 1 ] ) + points[ i ][ 0 ] ) )
result = !result; // MEGA OPTIMIZATOR 3500
}
return result ;
}

Пример использования:



new Float:country_points_0[] = { // "Los Santos"
3000.0,-3000.0,2996.0,-1040.0,1376.0,-684.0,84.0,-1000.0,100.0,-2996.0,3000.0,-3000.0
};

...

new Float: x, Float: y, Float: z ;
GetPlayerPos( playerid, x, y, z );
if( IsPointInPolygon( x, y, country_points_0 ) ) { // los santos
SendClientMessage( playerid, -1, "Вы в Лос Сантосе." );
}




bool IsPointInPolygon(List<Loc> poly, Loc point)
{
int i, j;
bool c = false;
for (i = 0, j = poly.Count - 1; i < poly.Count; j = i++)
{
if ((((poly[i].Lt <= point.Lt) && (point.Lt < poly[j].Lt))
|| ((poly[j].Lt <= point.Lt) && (point.Lt < poly[i].Lt)))
&& (point.Lg < (poly[j].Lg - poly[i].Lg) * (point.Lt - poly[i].Lt)
/ (poly[j].Lt - poly[i].Lt) + poly[i].Lg))

c = !c;
}
}

return c;
}

//Loc class

public class Loc
{
private double lt;
private double lg;

public double Lg
{
get { return lg; }
set { lg = value; }
}

public double Lt
{
get { return lt; }
set { lt = value; }
}

public Loc(double lt, double lg)
{
this.lt = lt;
this.lg = lg;
}
}

Daniel_Cortez
18.10.2015, 17:36
Во-первых, можно было обойтись без MAX_POLYGON_POINTS и без копирования координат в массив points, совершая все операции напрямую с массивом polygon.

Во-вторых, похожий функционал уже есть в стримере (функции IsPointInDynamicArea и IsPlayerInDynamicArea).

В-третьих, в Pawn не предусмотрено отдельных инструкций для операций с вещественными числами, поэтому все эти операции делаются с помощью нативных функций.
Эти вызовы сами по себе уже затратны: тратится время на переход из виртуальной машины на нативный код и обратно - такая проблема характера для многих языков интерпретируемого типа.
В данном же случае происходит куча вызовов floatcmp, floatadd, floatmul и floatdiv - каждая из этих функция вызывается от 1 до 3 раз для каждой точки.
Как следствие, та же функция IsPointInDynamicArea из стримера будет работать в разы быстрее.

Вывод: IsPointInPolygon (возможно) подойдёт только в том случае, если кому-то лень подключать стример из-за одной функции, но результатом такого удобства будет потеря производительности.

Seregamil
18.10.2015, 18:00
Во-вторых, похожий функционал уже есть в стримере (функции IsPointInDynamicArea и IsPlayerInDynamicArea).
Соль в том, что мне не нужен был стример для работы. Функцию я применил при переводе текстовых данных в БД для получения информации о геолокации объектов.

Ну а в остальном согласен. Будет время - переделаю.

Daniel_Cortez
18.10.2015, 18:22
Будет время - переделаю.
Нет смысла. Из-за операций с вещ. числами через нативки функции стримера в любом случае будут быстрее, чем реализация на Pawn.
#ITS_NO_USE

Seregamil
18.10.2015, 19:46
Нет смысла. Из-за операций с вещ. числами через нативки функции стримера в любом случае будут быстрее, чем реализация на Pawn.
#ITS_NO_USE

Про стример я не говорил не слова и функция с ним никаким боком не связана.

Daniel_Cortez
18.10.2015, 19:58
Про стример я не говорил не слова и функция с ним никаким боком не связана.
Это не повод запрещать другим говорить про альтернативы.