Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проверка координат, нужен запрос к бд 
:(
    Опции темы
Gtaman
Дата 9.9.2006, 09:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 10.4.2006

Репутация: нет
Всего: нет



Итак, проблема следующая:

условно есть некое пространство и записи в 2х таблицах, с использованием его координат. тоесть, к примеру пространтво X = 200; Y = 200;, а в тех двух таблицах структура которых имеет вид x1; x2; y1; y2; так вот например в каждой таблице есть записи:

The first table
_____________
x1 | x2 | y1 | y2
---------------------
 3  |  6  |  3 |  6 
_____________
The second table
_____________
x1 | x2 | y1 | y2
---------------------
 5  |  7  |  9  | 11
_____________

и нужна проверка чтобы при добавлении записи в the first table координаты высчитались так, чтобы "вокруг" этих координат было как минимум 2 свободные координаты.....

я делаю так, но у меня не получаеться..... в лучшем случае, происходит "наползание" координат, т.е. свободных координат не 2, а (-1)

Код

$stor = rand(2,5);
for($x = 3; $x <= 197; $x++)
{
$x2 = ($x + $stor) - 1;

$no_free_obs = mysql_query("SELECT * FROM second WHERE (sx1 <= '".intval($x2 - 2)."' AND sx2 >= '".intval($x + 2)."')");
$ssx1 = mysql_num_rows($no_free_obs);
if($ssx1 > 0) { continue; }
$no_free_buis = mysql_query("SELECT * FROM first WHERE (sx1 <= '".intval($x2 - 2)."' AND sx2 >= '".intval($x + 2)."')");
$ssx2 = mysql_num_rows($no_free_buis);
if($ssx2 > 0) { continue; }

if($ssx1 == 0 AND $ssx2 == 0)
{
for($y = 3; $y <= 197; $y++)
{
$y2 = ($y + $stor) - 1;

$no_free_obs = mysql_query("SELECT * FROM second WHERE (sy1 <= '".intval($y2 - 2)."' AND sy2 >= '".intval($y + 2)."') AND (sx1 <= '".intval($x2 - 2)."' AND sx2 >= '".intval($x + 2)."')");
$ssy1 = mysql_num_rows($no_free_obs);
if($ssy1 > 0) { continue; }
$no_free_buis = mysql_query("SELECT * FROM first WHERE (sy1 <= '".intval($y2 - 2)."' AND sy2 >= '".intval($y + 2)."') AND (sx1 <= '".intval($x2 - 2)."' AND sx2 >= '".intval($x + 2)."')");
$ssy2 = mysql_num_rows($no_free_buis);
if($ssy2 > 0) { continue; }
if($y >= 197) { header("Location: ?err=nopl"); }
if(($ssy1 == 0 AND $ssy2 == 0) AND empty($_SESSION['flag_sxy']))
{
$_SESSION['sec_sx1'] = $x;
$_SESSION['sec_sx2'] = $x2;
$_SESSION['sec_sy1'] = $y;
$_SESSION['sec_sy2'] = $y2;
$_SESSION['flag_sxy'] = 1;
break;
}

if($_SESSION['flag_sxy'] == 1) { break; }

}

}

}

$create = mysql_query("INSERT INTO first
(sx1,sx2,sy1,sy2)
VALUES
('$_SESSION[sec_sx1]','$_SESSION[sec_sx2]','$_SESSION[sec_sy1]','$_SESSION[sec_sy2]')");

PM MAIL   Вверх
Gtaman
Дата 10.9.2006, 11:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 10.4.2006

Репутация: нет
Всего: нет



Кто нибудь может мне помочь?
PM MAIL   Вверх
skyboy
Дата 10.9.2006, 11:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 14
Всего: 260



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

PM MAIL   Вверх
Gtaman
Дата 10.9.2006, 12:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 10.4.2006

Репутация: нет
Всего: нет



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

Кстати, если такой вариант, с 4 координатами(x1(левый верхний угол);x2(правый верхний угол);y1(левый верхний угол);y2(правый нижний угол);) нецелесообразен, то с удовольствием рассмотрю вариант с двумя координатами, x;y; при обозначении их центром объекта.....
PM MAIL   Вверх
vasac
Дата 10.9.2006, 12:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1060
Регистрация: 4.5.2006

Репутация: 3
Всего: 36



Gtaman, зачем ты делишь их на 2 таблицы?

Один из вариантов:
Прямоугольник области для добавляемого объекта будет (x1-2,y1-2,x2+2,y2+2)
Перебираешь все существующие объекты и проверяешь не пересекаются ли они с данной областью.


Цитата(Gtaman @  10.9.2006,  12:05 Найти цитируемый пост)
с удовольствием рассмотрю вариант с двумя координатами, x;y; при обозначении их центром объекта.

Если объекты имеют одинаковые размеры, то две координаты центра будут куда более разумным решением.
Если разные, то они не помогут.

Это сообщение отредактировал(а) vasac - 10.9.2006, 12:27
PM WWW   Вверх
Vaulter
Дата 10.9.2006, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1724
Регистрация: 30.12.2002
Где: бункер

Репутация: 3
Всего: 22



Gtaman, хех! а тебе 2 клетки зачем от краев карты??? smile
правила такие? smile


--------------------
PM MAIL WWW ICQ   Вверх
Gtaman
Дата 11.9.2006, 10:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 10.4.2006

Репутация: нет
Всего: нет



Цитата(vasac @  10.9.2006,  12:26 Найти цитируемый пост)
Gtaman, зачем ты делишь их на 2 таблицы?


Затем что в этих двух таблицах находяться совершенно разные объекты. Тоесть, в first храняться здания, а в second - деревья, камни.... вобщем, препятствия.


Цитата(vasac @  10.9.2006,  12:26 Найти цитируемый пост)
Один из вариантов:
Прямоугольник области для добавляемого объекта будет (x1-2,y1-2,x2+2,y2+2)
Перебираешь все существующие объекты и проверяешь не пересекаются ли они с данной областью.


Не мог бы ты записать это в коде? Или следующий вариант.

Цитата(vasac @  10.9.2006,  12:26 Найти цитируемый пост)
Цитата(Gtaman @  10.9.2006,  12:05 )
с удовольствием рассмотрю вариант с двумя координатами, x;y; при обозначении их центром объекта.


Если объекты имеют одинаковые размеры, то две координаты центра будут куда более разумным решением.
Если разные, то они не помогут.


Объекты все квадратные. Т.е. длина и ширина у них одинаковы.


Цитата(Vaulter @  10.9.2006,  13:55 Найти цитируемый пост)
Gtaman, хех! а тебе 2 клетки зачем от краев карты??? 
правила такие?  


Да, такие правила. Между любыми объектами должно быть 2 клетки промежутка.исключение - объекты second, так как как я уже сказал выше - это деревья, камни, итп..... и для упрощения их размещения думаю лучше сделать "большой" квадрат и по краям уже квадратиков понаставить,, чтоб все было более красиво.

Забыл добавить, second как исключение действует только в отношении second, минимальное расстояние first от second должно быть 2 клетки.

Это сообщение отредактировал(а) Gtaman - 11.9.2006, 10:40
PM MAIL   Вверх
Gtaman
Дата 12.9.2006, 15:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 10.4.2006

Репутация: нет
Всего: нет



У меня все еще не получаеться......
PM MAIL   Вверх
ewolf
Дата 12.9.2006, 20:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 389
Регистрация: 15.8.2006
Где: г. Москва

Репутация: 2
Всего: 18



Не лучше ли хранить координаты объектов в одной базе, просто ввести еще дополнительное поле для хранения типа объекта в данной области?

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

Не вдавая в детали размещения объектов на карте, я думаю, что проверку возможности размещения объекта в области (x,y)(x2,y2)
можно записать так (алгоритм пересечения двух прямоугольников):

Код

function checkFreeZone($x, $y, $x2, $y2, $free_zone, $object_type)
{
   $left = $x - $free_zone;
   $right = $x2 + $free_zone;

   $top = $y - $free_zone;
   $bottom = $y2 + $free_zone;

   $no_free_obs = mysql_query("SELECT * FROM second WHERE (GREATEST(sx1, {$left}) < GREATEST(sx2, {$right})) AND (GREATEST(sy1, {$top}) < GREATEST(sy2, {$bottom})) AND object_type = '{$object_type}'");
   $found = mysql_num_rows($no_free_obs);
   if( $found > 0 )
      return false;
   return true;
}

// Соответственно (1 - номер  типа объекта, скажем, это дома)

if( checkFreeZone(3, 4, 5, 6, 2, 1) )
   echo 'It's FREE!!';
else
   echo 'Sorry, it's not free :(';

PM MAIL ICQ   Вверх
Gtaman
Дата 13.9.2006, 10:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 10.4.2006

Репутация: нет
Всего: нет



Цитата(ewolf @  12.9.2006,  20:25 Найти цитируемый пост)
Не лучше ли хранить координаты объектов в одной базе, просто ввести еще дополнительное поле для хранения типа объекта в данной области?


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

Цитата(ewolf @  12.9.2006,  20:25 Найти цитируемый пост)
Дальше, если в дальнейшем все-таки планируется размещение объектов с разной длиной и шириной, то базу лучше оставить как есть, если же всегда объекты будут одинаковы, то лучше ввести сетку, где для каждой ячейки хранить объект.


Пока разные величины не планируються, чтобы ширина была 4, а длина 8. Т.е. когда добавляешь строения, указываеться площадь, например, 4. и будет ширина - 4, длина - 4. можно указать 4, 8, 15, 16, 23, 42 итд.....

Насчет кода: Не мог бы ты, или кто нибудь еще поподробнее и с проверкой из двух таблиц написать?
PM MAIL   Вверх
vasac
Дата 13.9.2006, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1060
Регистрация: 4.5.2006

Репутация: 3
Всего: 36



Код

/* Ïðîâåðêà ïåðåñå÷åíèÿ äâóõ ïðÿìîóãîëüíûõ îáëàñòåé
 @param array - êîîðäèíàòû ïåðâîé îáëàñòè (ïîðÿäêîâûé ìàññèâ x1,y1,x2,y2)
 @param array - âòîðàÿ îáëàñòü (àíàëîãè÷íûé ôîðìàò)
 @return bool - true - ïåðåñåêàþòñÿ, false - íåò
*/
 function crossObj( $o1, $o2 ) {
 
     if ( $o2[ 2 ] < $o1[ 0 ] ) return false; // Âòîðîé ëåâåå ïåðâîãî
     if ( $o2[ 0 ] > $o1[ 2 ] ) return false; // Âòîðîé ïðàâåå ïåðâîãî
     if ( $o2[ 3 ] < $o1[ 1 ] ) return false; // Âòîðîé âûøå ïåðâîãî
     if ( $o2[ 1 ] > $o1[ 3 ] ) return false; // Âòîðîé íèæå ïåðâîãî
     
     return true;
 
 } // crossObj().
 
 
 $o1 = Array( 10, 10, 20, 20 );
 $o2 = Array( 15, 15, 25, 25 );
 
 print crossObj( $o1, $o2 ) ? 'Ïåðåñåêàþòñÿ' : 'Íåò';

PM WWW   Вверх
Gtaman
Дата 13.9.2006, 11:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 10.4.2006

Репутация: нет
Всего: нет



vasac, что то я ничего не понял smile Коментарии расшифровал:

Код

/* Проверка пересечения двух прямоугольных областей
@param array - координаты первой области (порядковый массив x1,y1,x2,y2)
@param array - вторая область (аналогичный формат)
@return bool - true - пересекаются, false - нет
*/
function crossObj( $o1, $o2 ) {

if ( $o2[ 2 ] < $o1[ 0 ] ) return false; // Второй левее первого
if ( $o2[ 0 ] > $o1[ 2 ] ) return false; // Второй правее первого
if ( $o2[ 3 ] < $o1[ 1 ] ) return false; // Второй выше первого
if ( $o2[ 1 ] > $o1[ 3 ] ) return false; // Второй ниже первого

return true;

} // crossObj().


$o1 = Array( 10, 10, 20, 20 );
$o2 = Array( 15, 15, 25, 25 );

print crossObj( $o1, $o2 ) ? 'Пересекаются' : 'Нет';


но что за первая и вторая области? откуда они? и что за цифры в 1 и 2 массивах? тоже, откуда эти цифры?
PM MAIL   Вверх
Gtaman
Дата 14.9.2006, 12:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 10.4.2006

Репутация: нет
Всего: нет



Мне срочно нужно! Help me, please!
PM MAIL   Вверх
ewolf
Дата 15.9.2006, 01:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 389
Регистрация: 15.8.2006
Где: г. Москва

Репутация: 2
Всего: 18



Цитата(Gtaman @  13.9.2006,  10:23 Найти цитируемый пост)
Насчет кода: Не мог бы ты, или кто нибудь еще поподробнее и с проверкой из двух таблиц написать?


Ну и с двумя таблицами несложно, вот например:

Код

function checkFreeZone($x, $y, $x2, $y2, $free_zone, $table)
{
   $left = $x - $free_zone;
   $right = $x2 + $free_zone;

   $top = $y - $free_zone;
   $bottom = $y2 + $free_zone;

   $no_free_obs = mysql_query("SELECT * FROM {$table} WHERE (GREATEST(sx1, {$left}) < GREATEST(sx2, {$right})) AND (GREATEST(sy1, {$top}) < GREATEST(sy2, {$bottom}))");
   $found = mysql_num_rows($no_free_obs);
   if( $found > 0 )
      return false;
   return true;
}

checkFreeZone(5,6,7,8,2,'first'); // Первая таблица
checkFreeZone(5,6,7,8,1,'second'); // Вторая таблица

PM MAIL ICQ   Вверх
Gtaman
Дата 15.9.2006, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 10.4.2006

Репутация: нет
Всего: нет



ewolf, фигурные скобки даже phpmyadmin ругает smile так что они лишние, ну я их убрал. и, кстати, что это за greatest? вставлял в phpmyadmin с значениями - выбирает все объекты. может из за того что у некоторых координаты не указаны(хотя с координатами тоже помечаються)? и не могли бы вы писать код полностью? А то я не понял, что с моими for делать.....
PM MAIL   Вверх
ewolf
Дата 15.9.2006, 18:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 389
Регистрация: 15.8.2006
Где: г. Москва

Репутация: 2
Всего: 18



Зачем вставлять фигурные скобки в phpmyadmin? они служат только для вставки переменных в строки php, это называется сложный синтаксис, хотя, можно конечно и без них. Greatest выбирает наибольшее значение из 2х..

Вообще, извини, изначально в коде была ошибка smile

Правильно вот так (хотя не имея реальной базы - не проверял)

Код

function checkFreeZone($x, $y, $x2, $y2, $free_zone, $table)
{
   $left = $x - $free_zone;
   $right = $x2 + $free_zone;

   $top = $y - $free_zone;
   $bottom = $y2 + $free_zone;

   $no_free_obs = mysql_query("SELECT * FROM {$table} WHERE (sx1 < {$right} AND sx2 > {$left} AND sy1 < {$bottom} AND sy2 > {$top})");
   $found = mysql_num_rows($no_free_obs);
   if( $found > 0 )
      return false;
   return true;
}

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

PM MAIL ICQ   Вверх
Gtaman
Дата 20.9.2006, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 10.4.2006

Репутация: нет
Всего: нет



ewolf, с кодом вроде все понятно, но не мог бы ты написать полный вариант, т.е. начиная с for? А то я вставлять пробовал полюбому, не получаеться smile
PM MAIL   Вверх
ewolf
Дата 21.9.2006, 19:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 389
Регистрация: 15.8.2006
Где: г. Москва

Репутация: 2
Всего: 18



Ну, я вообще если речь идет о поиске свободной позиции для вставки объекта размерами WxH, то есть конечно более оптимальные алгоритмы, но попробуем обойтись вышеприведенной функцией

Код


$ZONE_WIDTH = 200;
$ZONE_HEIGHT = 200; // Карта квадратная, размером 200x200 единиц

function insertObject($obj_width, $obj_height, $obj_freezone)
{
   global $ZONE_WIDTH, $ZONE_HEIGHT;
   for( $x = $obj_freezone; $x <= $ZONE_WIDTH - $obj_freezone - $obj_width; $x++ )
   {
      for( $y = $obj_freezone; $y <= $ZONE_HEIGHT - $obj_freezone - $obj_height; $y++ )
      {
         // Проверяем свободную зону на свободу от камней и т.п.
         if( checkFreeZone($x, $y, $x + $obj_width, $y + $obj_height, $obj_freezone, 'second') )
         {
            // Проверяем зону на свободу от домов
            if( checkFreeZone($x, $y, $x + $obj_width, $y + $obj_height, $obj_freezone, 'first') )
            {
               // Вставка информации об объекте с координатами $x, $y
               return true;
            }
         }
      }
   }
   return false;
}

// Ну и вставка нужного числа объектов

$TOTAL_OBJECTS = 10;

for( $i = 0; $i < $TOTAL_OBJECTS; $i++ )
   insertObject(rand(3,10), rand(3,10), 2);



Я не уверен, что правильно понял твою идею для формирования карты. Может быть тебе нужна какая-то случайно создаваемая карта? Тогда поищи в интернете алгоритмы формирования случайных графов, карт и т.п. Они не имеют отношения к php или какому-то другому языку программирования, но ты сможешь почерпнуть от туда немало полезных знаний smile
PM MAIL ICQ   Вверх
Gtaman
Дата 21.9.2006, 19:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 10.4.2006

Репутация: нет
Всего: нет



ewolf, ну идея формирования простая - есть карта, 200*200 клеток. На этих клетках расположены разные объекты, как я уже говорил - здания и камни. при добавлении объекта - минимальное расстояние его от любого объекта должно быть 2 клетки. Ширина и высота зданий - одинакова(всмысле, у каждого экзэмпляра можетбыть разная длина, но если ширина 5, то и высота 5). Камни - тут по другому, тут уже ставиться радиус. т.е. сам объект имеет площадь 1 клетка, но если к примеру поставить у него x1 = 3; x2 = 6; y1 = 3; y2 = 5; то это как бы один объект, но в графическом варианте должно отображаться 6 объектов. я подумал, так будет лучше, чтобы не загружать базу. Экономнее так.

Что кавсается твоего кода - сейчас попробую, может быть получиться.  smile
PM MAIL   Вверх
Gtaman
Дата 24.9.2006, 09:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 10.4.2006

Репутация: нет
Всего: нет



Вроде все работает как надо...... Если что то не так будет - напишу...... Кстати, в WHERE надо ставить еще и =, т.е.

Код

$no_free_obs = mysql_query("SELECT * FROM {$table} WHERE (sx1 <= {$right} AND sx2 >= {$left} AND sy1 <= {$bottom} AND sy2 >= {$top})");


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

Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  out_scheme_1.JPG 31,77 Kb
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Базы Данных | Следующая тема »


 




[ Время генерации скрипта: 0.0674 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.