Очень нужна помощь с MapBasic

MapInfo, MapBasic
Aphina
Интересующийся
Сообщения: 18
Зарегистрирован: 24 июн 2012, 17:43
Репутация: 0

Очень нужна помощь с MapBasic

Сообщение Aphina » 01 май 2013, 18:49

Изначально есть база данных, в которой описаны встречи с птицами по кварталу, стороне квартала и выделу из этого квартала, и таблица выделов с векторными изображениями этих самых выделов. Программа должна работать по следующему алгоритму:
1.открываем базу данных;

2. читаем таблицу построчно, в строке находим номер квартала и выдела,

3. строим оконтуривающий прямоугольник для выбранного выдела;

4.для объекта MBR (прямоугольник) узнаются координаты узлов, потом находится центр прямоугольника и середины сторон ( это будут точки с направлением на
север-юг-запад-восток).

5. строится отрезок: одна точка - середина прямоугольника, вторая точка зависит от содержимого колонки, в которой указано направление на стороны света;

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

7. все точки - для каждой строки из xls строим с помощью INSERT в
новую таблицу.

8. результат работы утилиты: таблица с точками, для каждой точки в
колонках описаны все атрибутивные данные.

Код: Выделить всё

Include "mapbasic.def"

Dim rect_mbr, st_sv As Object, x1, x2, y1, y2, x3, y3, cx, cy, centr As Float, r As Integer
Dim sv as alias
Dim tail as string
Dim al as alias
Dim videl as string
Dim kvartal as string
Dim storona as string
Dim tab as string

Open Table "БД_птиц" Interactive
Fetch First From БД_птиц
Select J, кварталы From БД_птиц 'Where кварталы = 1
r = TableInfo ("БД_птиц", TABLE_INF0_NROWS)



While r <= 10725 'пока не закончатся отведённые строки

tab = "выборка"
	al = tab+".кварталы"
	kvartal = al
Select * from Выделы Where Поле2 = videl and Номер_квартала = kvartal 'выборка выдела по стороне квартала
rect_mbr = Str$(Selection.obj)
Add Map Layer Результат
rect_mbr = MBR(Выделы.obj) 'окунтуривающий прямоугольник для выдела
y1 = ObjectGeography(rect_mbr.obj, OBJ_GEO_MINY) 'минимальные и максимальные координаты этого выдела
y2 = ObjectGeography(rect_mbr.obj, OBJ_GEO_MAXY)
x1 = ObjectGeography(rect_mbr.obj, OBJ_GEO_MINX)
x2 = ObjectGeography(rect_mbr.obj, OBJ_GEO_MAXX)
x3 = x2 - x1
y3 = y2 - y1
cx = x1+((x2 - x1)/2) 'координаты центра
cy = y1 + ((y2 - y1)/2)

tail = "выбор"
	sv = tail+".Бд_птиц"

Do Case Select * from ".БД_птиц" Where I = tail 'выборка на сторону света
Case tail = 1
"st_sv = CreateLine (cx, cy, x3, y2)"
Case tail = 2
"st_sv = CreateLine (cx ,cy, x2, y3)"
Case tail = 3
"st_sv = CreateLine (cx, cy, x3, y1)"
Case tail = 4
"st_sv = CreateLine (cx, cy, x1, y3)"
Case tail = 5
"st_sv = CreateLine (cx, cy, x1, y2)"
Case tail = 6
"st_sv = CreateLine (cx, cy, x2, y2)"
Case tail = 7
"st_sv = CreateLine (cx, cy, x2, y1)"
Case tail = 8 
"st_sv = CreateLine (cx, cy, x1, y1)"
Case tail = 9
"st_sv = CreateLine (cx, cy, cx, cy)"
nodes = IntersectNodes(Выделы.obj , st_sv, INCL_CROSSINGS) 'получение точки на пересечении границы выдела и стороны света
x = ObjectNodeX(nodex, 1, 1)
y = ObjectNodeY(nodex, 1, 1)
p = CreatePoint(x, y) 
INSERT INTO Результат(obj) values(p)
r = r + 1
Wend


Не компилируется с тремя ошибками, скриншот и таблицы прилагаю в архиве. Ума уже не приложу, что делать. Очень нужна помощь.

Исправление: добавила БД_птиц в отдельный архив.
Вложения
БД_птиц.zip
(206.18 КБ) 472 скачивания
ГИС.zip
(328.97 КБ) 479 скачиваний
Последний раз редактировалось Aphina 05 май 2013, 21:17, всего редактировалось 3 раза.

sysrepos
Активный участник
Сообщения: 128
Зарегистрирован: 07 окт 2012, 16:25
Репутация: 20
Откуда: Москва

Re: Прошу помощи с MapBasic

Сообщение sysrepos » 02 май 2013, 08:31

во первых в строчках

Код: Выделить всё

y1 = ObjectGeography(rect_mbr.obj, OBJ_GEO_MINY)  'минимальные и максимальные координаты этого выдела
уберите .obj, то есть должно получиться

Код: Выделить всё

y1 = ObjectGeography(rect_mbr, OBJ_GEO_MINY)
во вторых в выражении Do Case нельзя использовать просто выборку
если вам нужно использовать какое то одно значение из полученной выборки,

Код: Выделить всё

Select * from "БД_птиц" Where I = tail 'выборка на сторону света
присвойте данное значение переменной, и уже его используйте в Case

еще вы end Case забыли

в третьих у вас ошибка в строке

Код: Выделить всё

"st_sv = CreateLine (cx, cy, x3, y2)", нужно заменить так
st_sv = "CreateLine (cx, cy, x3, y2)"  (ковычки)
в четвертых у вас не объявлены многие переменные

Код: Выделить всё

dim nodes as object
dim x as float
dim y as float
dim p as object
в пятых
таблица БД птиц Висимского заповедника у меня не открылась (не хватает еще одно файла) - поэтому полностью разобраться в вашей задаче не смог

Aphina
Интересующийся
Сообщения: 18
Зарегистрирован: 24 июн 2012, 17:43
Репутация: 0

Re: Прошу помощи с MapBasic

Сообщение Aphina » 04 май 2013, 09:40

Большое спасибо за помощь)

Код: Выделить всё

Include "mapbasic.def"

Dim rect_mbr, st_sv As Object, x1, x2, y1, y2, x3, y3, cx, cy, centr As Float, r As Integer
Dim sv as alias
Dim tail as string
Dim rect as string
Dim al as alias
Dim videl as string
Dim kvartal as string
Dim storona as string
Dim tab as string
Dim nodes as object
Dim x as float
Dim y as float
Dim p as object

Open Table "БД_птиц" Interactive
Fetch First From БД_птиц
Select J, H From БД_птиц 'Where H = 1
r = TableInfo("БД_птиц",TAB_INFO_NROWS)
Open Table "Выделы" Interactive
While r <= 10725 'пока не закончатся отведённые строки

tab = "выборка"
	al = tab+".H"
	kvartal = al
Select * from Выделы Where Поле2 = videl and Номер_квартала = kvartal 'выборка выдела по стороне квартала
rect_mbr = Str$(Selection.obj)
Add Map Layer Результат
rect_mbr = MBR(Выделы.obj) 'окунтуривающий прямоугольник для выдела
y1 = ObjectGeography(rect_mbr, OBJ_GEO_MINY) 'минимальные и максимальные координаты этого выдела
y2 = ObjectGeography(rect_mbr, OBJ_GEO_MAXY)
x1 = ObjectGeography(rect_mbr, OBJ_GEO_MINX)
x2 = ObjectGeography(rect_mbr, OBJ_GEO_MAXX)
x3 = x2 - x1
y3 = y2 - y1
cx = x1+((x2 - x1)/2) 'координаты центра
cy = y1 + ((y2 - y1)/2)

tail = "выбор"
	sv = tail+".I"

Select * from ".БД_птиц" Where I = tail 'выборка на сторону света

Do Case tail
Case tail = 1
st_sv = "CreateLine (cx, cy, x3, y2)"
Case tail = 2
st_sv = "CreateLine (cx ,cy, x2, y3)"
Case tail = 3
st_sv = "CreateLine (cx, cy, x3, y1)"
Case tail = 4
st_sv = "CreateLine (cx, cy, x1, y3)"
Case tail = 5
st_sv = "CreateLine (cx, cy, x1, y2)"
Case tail = 6
st_sv = "CreateLine (cx, cy, x2, y2)"
Case tail = 7
st_sv = "CreateLine (cx, cy, x2, y1)"
Case tail = 8 
st_sv = "CreateLine (cx, cy, x1, y1)"
Case tail = 9
st_sv = "CreateLine (cx, cy, cx, cy)"
End Case
nodes = IntersectNodes(Выделы.obj , st_sv, INCL_CROSSINGS) 'получение точки на пересечении границы выдела и стороны света
x = ObjectNodeX(nodex, 1, 1)
y = ObjectNodeY(nodex, 1, 1)
p = CreatePoint(x, y) 
INSERT INTO Результат(obj) values(p)
r = r + 1
Wend
Переделала согласно полученным замечаниям. Теперь программа компилируется без ошибок и запускается. Но результатом служит открытие таблицы базы данных и выделение всех строк. Больше ничего. Очень нужен совет.
Добавила в первый пост отдельным архивом базу данных.

sysrepos
Активный участник
Сообщения: 128
Зарегистрирован: 07 окт 2012, 16:25
Репутация: 20
Откуда: Москва

Re: Очень нужна помощь с MapBasic

Сообщение sysrepos » 05 май 2013, 18:04

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

Aphina
Интересующийся
Сообщения: 18
Зарегистрирован: 24 июн 2012, 17:43
Репутация: 0

Re: Очень нужна помощь с MapBasic

Сообщение Aphina » 05 май 2013, 18:43

Я хочу, чтобы она строила точки с атрибутивной информацией. Ну согласно описанному в первом посте алгоритму.

sysrepos
Активный участник
Сообщения: 128
Зарегистрирован: 07 окт 2012, 16:25
Репутация: 20
Откуда: Москва

Re: Очень нужна помощь с MapBasic

Сообщение sysrepos » 05 май 2013, 22:43

объясните смысла запроса

Код: Выделить всё

Select * from Выделы Where Поле2 = videl and Номер_квартала = kvartal 
в таблице Выделы в Поле2 вообще нету значения videl , там только цифры

Поле2 у вас в таблице целое, а videl во всей программе равен ничему.

По каким именно колонкам должна быть связь между таблицами БД_птиц и Выделы?

7. все точки - для каждой строки из xls
xls - это что? какой то файл Excel?

а вообще у вас цикл даже и не начинается, поэтому ничего и не происходит
у вас написано

Код: Выделить всё

While r <= 10725
а перед этим r=11220

(в цикле вместо r введите другую переменную)

gamm
Гуру
Сообщения: 4168
Зарегистрирован: 15 окт 2010, 08:33
Репутация: 1107
Ваше звание: программист
Откуда: Казань

Re: Очень нужна помощь с MapBasic

Сообщение gamm » 06 май 2013, 07:41

Aphina писал(а):Изначально есть база данных, в которой описаны встречи с птицами по кварталу, стороне квартала и выделу из этого квартала, и таблица выделов с векторными изображениями этих самых выделов. Программа должна работать по следующему алгоритму:
напишите лучше постановку задачи, что вы хотите сделать (какой результат получить), а не как вы это придумали делать. Пока народ пытается это угадать из вашей программы.

Aphina
Интересующийся
Сообщения: 18
Зарегистрирован: 24 июн 2012, 17:43
Репутация: 0

Re: Очень нужна помощь с MapBasic

Сообщение Aphina » 06 май 2013, 08:23

videl и kvartal обозначения для кварталов и выделов. Там и должны быть цифры - это же номера.

Код: Выделить всё

tab = "выборка"
   al = tab+".H"
   kvartal = al
Select * from Выделы Where Поле2 = videl and Номер_квартала = kvartal 'выборка выдела по стороне квартала
Этот код предназначался для выбора столбцов с кварталами и выделами. Колонка Номер_квартала в Выделах это квартал в БД_птиц. Честно говорю, что такая выборка не моя идея, но мне сказали, что это единственный вариант.

Да, xls формат Excel, но у меня уже появилась таблица в формате MapInfo.

Я думала сделать цикл на окончание прочитываемых строк. С первой по указанное число. Значит ошиблась. А какое тогда условие можно поставить?

По идее, программа должна считывать данные по трём колонкам БД_птиц - кварталам, стороне и выделу. В каждой строке определяется квартал, его выдел и отрезок направления стороны света. На пересечении выдела и отрезка строится точка. Это точка встречи с птицами. Точка заносится в новую таблицу и цикл повторяется, пока не закончатся данные.
К моему великому сожалению, мой руководитель не разбирается в MapBasic, поэтому я пытаюсь разобраться по справочнику MapBasic и найденной информации на форумах.

sysrepos
Активный участник
Сообщения: 128
Зарегистрирован: 07 окт 2012, 16:25
Репутация: 20
Откуда: Москва

Re: Очень нужна помощь с MapBasic

Сообщение sysrepos » 06 май 2013, 10:39

чтобы работал цикл, попробуйте так:

Код: Выделить всё

rkol as integer
rkol = TableInfo("БД_птиц",TAB_INFO_NROWS)

While r <= rkol 
....
r=r+1
wend

trir
Гуру
Сообщения: 5354
Зарегистрирован: 09 апр 2010, 19:30
Репутация: 1021
Ваше звание: просто мимо прохожу
Откуда: Ё-бург

Re: Очень нужна помощь с MapBasic

Сообщение trir » 06 май 2013, 10:59

offtop:
Это точка встречи с птицами
А GPS'кой эту точку нельзя было определить?

Sibit
Активный участник
Сообщения: 216
Зарегистрирован: 21 окт 2009, 13:29
Репутация: 28
Откуда: Новосибирск

Re: Очень нужна помощь с MapBasic

Сообщение Sibit » 06 май 2013, 11:39

А зачем столько сложностей с определением прямоугольника, стороны выдела и т.д.? Не проще точку ставить в центроид выдела? Или , если нужна граница, в точку с максимальной координатой?

PS А, если не секрет, кто ГИС слой создавал?

Aphina
Интересующийся
Сообщения: 18
Зарегистрирован: 24 июн 2012, 17:43
Репутация: 0

Re: Очень нужна помощь с MapBasic

Сообщение Aphina » 06 май 2013, 15:11

trir писал(а):offtop:
Это точка встречи с птицами
А GPS'кой эту точку нельзя было определить?
Нет, тогда GPS'ок ещё не было. Данные наблюдения за 1989 год.
Sibit писал(а):А зачем столько сложностей с определением прямоугольника, стороны выдела и т.д.? Не проще точку ставить в центроид выдела? Или , если нужна граница, в точку с максимальной координатой?
Точка должна быть на пересечении направления стороны света и границы выдела. Центроид и максимальная координаты просто по описанию не подойдут, к сожалению.
Sibit писал(а): А, если не секрет, кто ГИС слой создавал?
В смысле Выделы?

sysrepos
Активный участник
Сообщения: 128
Зарегистрирован: 07 окт 2012, 16:25
Репутация: 20
Откуда: Москва

Re: Очень нужна помощь с MapBasic

Сообщение sysrepos » 06 май 2013, 22:32

было бы неплохо, если бы вы в своих таблицах дали имена колонкам, где там выдел, где сторона света и т.п., а не A,B,C,D, и поле1, поле2, поле3. , может быть тогда бы стало понятнее. ( и не используемые поля удалили бы)

juffin_h
Завсегдатай
Сообщения: 265
Зарегистрирован: 22 окт 2012, 08:35
Репутация: 49
Откуда: Нижний Новгород

Re: Очень нужна помощь с MapBasic

Сообщение juffin_h » 07 май 2013, 08:12

Aphina писал(а):мой руководитель не разбирается в MapBasic
Знание языка программирования задачу не решает, а лишь позволяет ее реализовать на данном языке.

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

Код: Выделить всё

''****************************
'' Для работы программы д. б. открыты таблицы - БД_птиц, Выделы, Результат (пустая)
'' Если в одной строке задано несколько номеров (выделов и/или кварталов) - обрабатывается только первый
'' Если нет стороны света - строка не обрабатывается
'' Атрибутивные данные не копируются - сделайте сами
''****************************
Include "MAPBASIC.DEF"

Declare Sub Main

Sub Main

	Dim iKvtl, iVdl, iDir As Integer
	Dim xmin, ymin, xmax, ymax, x0, y0, x1, y1 As Float
	Dim oDirLine As Object

	Fetch First From БД_птиц
	Do While Not EOT(БД_птиц) '' Перебираем все строки в БД_птиц

		iKvtl = Val(БД_птиц.H)		'' Квартал из текущей строки
		iVdl = Val(БД_птиц.J)		'' Выдел из текущей строки
		iDir = Val(БД_птиц.I)		'' Сторона света из текущей строки

		Select * From Выделы Where Поле2 = iVdl And Номер_квартала = iKvtl Into tmptab Noselect

		If TableInfo(tmptab, TAB_INFO_NROWS) < 1 Or iDir < 1 Then
			'' Нет такого выдела или не определена сторона света
		Else
			xmin = ObjectGeography(tmptab.obj, OBJ_GEO_MINX)
			ymin = ObjectGeography(tmptab.obj, OBJ_GEO_MINY)
			xmax = ObjectGeography(tmptab.obj, OBJ_GEO_MAXX)
			ymax = ObjectGeography(tmptab.obj, OBJ_GEO_MAXY)
			x0 = (xmin + xmax)/2
			y0 = (ymin + ymax)/2
			x1 = x0
			y1 = x0

			Do Case iDir
				Case 1, 3
					x1 = x0
				Case 6, 2, 7
					x1 = xmax
				Case 5, 4, 8
					x1 = xmin
			End Case

			Do Case iDir
				Case 4, 2
					y1 = y0
				Case 5, 1, 6
					y1 = ymax
				Case 3, 7, 8
					y1 = ymin
			End Case

			oDirLine = Overlap(CreateLine(x0, y0, x1, y1), tmptab.obj) '' Вектор от условной серидины выдела к точке пересечения с границей
			If ObjectInfo(oDirLine, OBJ_INFO_NPNTS) > 1 Then
				''Insert Into Результат (obj) Values (oDirLine) 
				Insert Into Результат (obj) Values (CreatePoint(ObjectNodeX(oDirLine,1,2), ObjectNodeY(oDirLine,1,2) ))
			End If
		End If

		Fetch Next From БД_птиц
	Loop 

	Drop Table tmptab


End Sub
В общем случае, такой способ поиска точки встречи, может не дать результата, поскольку пересечение вектора с границей гарантировано, только если граница имеет выпуклую форму.
Последний раз редактировалось juffin_h 07 май 2013, 11:17, всего редактировалось 1 раз.

Sibit
Активный участник
Сообщения: 216
Зарегистрирован: 21 окт 2009, 13:29
Репутация: 28
Откуда: Новосибирск

Re: Очень нужна помощь с MapBasic

Сообщение Sibit » 07 май 2013, 08:25

Aphina писал(а): Точка должна быть на пересечении направления стороны света и границы выдела. Центроид и максимальная координаты просто по описанию не подойдут, к сожалению.
Почему же? Я имел ввиду что если нужно направление на север, ищем точку с максимальной по Y координате и ставите ее в базу(она лежит на границе выдела). По сути вы ищите центр объекта(но он не обязательно попадает внутрь полигона), центроиды(в терминах MapInfo) же всегда лежат внутри полигона, если их никто не менял.
Aphina писал(а): В смысле Выделы?
[/quote]
Ага, слой выделов. И в каком году? если тоже не секрет :)

Про программу, даже и не знаю с чего начать :(
1) Неплохо бы было перед обработкой данные подготовить. Например, в таблице Бд_птиц переименовать поля, убрать заголовки из строк. Преобразовать поля.

2) Переменная цикла у вас как-то странно используется( выше об этом написали )

Код: Выделить всё

r = TableInfo("БД_птиц",TAB_INFO_NROWS)
Open Table "Выделы" Interactive
While r <= 10725 'пока не закончатся отведённые строки
3) Значения полей сравниваете с неопределенными переменными (это тоже писали), сравниваете Строки и Числа (MapInfo конечно подставит преобразование, но лучше так не делать )

Код: Выделить всё

Select * from Выделы Where Поле2 = videl and Номер_квартала = kvartal 'выборка выдела по стороне квартала
' videl  - не определено!
'Поле2 - число, videl   - строка,kvartal  - строка, Номер_квартала - число
4) Нигде нет в коде перехода к следующей строке в таблице

Код: Выделить всё

tab = "выборка"
al = tab+".H"
kvartal = al  ' kvartal  всегда будет равняться первой строке таблицы
5) Таблица с результатом нигде не создается.

В общем, проще переделать, чем исправить. Если эта задача для вас сложная, то необходимо разбить ее на подзадачи и решать их последовательно. Должна программа выглядеть так:

1) Создаем таблицу для сохранения результата, открываем таблицы с данными
2) выбор из таблицы встреч все записи с заполненными полями выдел, квартал, направление
3) перебор по всем строкам таблицы встреч (можно сделать сначала запрос по 2-м таблицам, но так будет проще)
3.1) выбираем строку
3.2) Выбираем из таблицы выделов, выдел с тем же номером выдела и квартала
3.3) строим точку
3.4) вставляем результат в таблицу

Вот собственно и все :)

Ответить

Вернуться в «MapInfo»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя